summaryrefslogtreecommitdiff
path: root/www/wiki/resources
diff options
context:
space:
mode:
authorYaco <franco@reevo.org>2019-01-06 00:20:37 -0300
committerYaco <franco@reevo.org>2019-01-06 00:20:37 -0300
commitdab3fd4a501df5c3fc30b4c9fe79bfada4415958 (patch)
tree3d1971414457ff62418a69b6a95bc4b4e93ab5e9 /www/wiki/resources
parent71ddfdcf197d529e0964059ad7b796913908f2b3 (diff)
grandes avances previos al primer deployment en reevo.wiki
Diffstat (limited to 'www/wiki/resources')
-rw-r--r--www/wiki/resources/Resources.php2870
-rw-r--r--www/wiki/resources/ResourcesOOUI.php182
-rw-r--r--www/wiki/resources/assets/file-type-icons/COPYING43
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-c.pngbin0 -> 1753 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-cpp.pngbin0 -> 1382 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-deb.pngbin0 -> 4435 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-djvu.pngbin0 -> 10351 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-djvu.xcfbin0 -> 83394 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-dvi.pngbin0 -> 12449 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-exe.pngbin0 -> 5371 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-h.pngbin0 -> 803 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-html.pngbin0 -> 7042 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-iso.pngbin0 -> 6105 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-java.pngbin0 -> 5628 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-mid.pngbin0 -> 6204 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-mov.pngbin0 -> 7357 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-o.pngbin0 -> 1742 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-ogg.pngbin0 -> 3151 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-ogg.xcfbin0 -> 40236 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-pdf.pngbin0 -> 4662 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-ps.pngbin0 -> 2780 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-psd.pngbin0 -> 7633 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-rm.pngbin0 -> 2498 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-rpm.pngbin0 -> 3748 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-svg.pngbin0 -> 4680 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-tar.pngbin0 -> 6025 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-tex.pngbin0 -> 3651 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-ttf.pngbin0 -> 3167 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-txt.pngbin0 -> 3374 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon-xcf.pngbin0 -> 9045 bytes
-rw-r--r--www/wiki/resources/assets/file-type-icons/fileicon.pngbin0 -> 789 bytes
-rw-r--r--www/wiki/resources/assets/licenses/README4
-rw-r--r--www/wiki/resources/assets/licenses/cc-0.pngbin0 -> 969 bytes
-rw-r--r--www/wiki/resources/assets/licenses/cc-by-nc-sa.pngbin0 -> 1530 bytes
-rw-r--r--www/wiki/resources/assets/licenses/cc-by-sa.pngbin0 -> 1377 bytes
-rw-r--r--www/wiki/resources/assets/licenses/cc-by.pngbin0 -> 1165 bytes
-rw-r--r--www/wiki/resources/assets/licenses/gnu-fdl.pngbin0 -> 1573 bytes
-rw-r--r--www/wiki/resources/assets/licenses/public-domain.pngbin0 -> 1976 bytes
-rw-r--r--www/wiki/resources/assets/mediawiki.pngbin0 -> 22508 bytes
-rw-r--r--www/wiki/resources/assets/poweredby_mediawiki_132x47.pngbin0 -> 5840 bytes
-rw-r--r--www/wiki/resources/assets/poweredby_mediawiki_176x62.pngbin0 -> 8519 bytes
-rw-r--r--www/wiki/resources/assets/poweredby_mediawiki_88x31.pngbin0 -> 3489 bytes
-rw-r--r--www/wiki/resources/assets/wiki.pngbin0 -> 24216 bytes
-rw-r--r--www/wiki/resources/lib/es5-shim/es5-shim.js1461
-rw-r--r--www/wiki/resources/lib/html5shiv/html5shiv.js326
-rw-r--r--www/wiki/resources/lib/html5shiv/html5shiv.min.js4
-rw-r--r--www/wiki/resources/lib/jquery.chosen/LICENSE24
-rw-r--r--www/wiki/resources/lib/jquery.chosen/chosen-sprite.pngbin0 -> 646 bytes
-rw-r--r--www/wiki/resources/lib/jquery.chosen/chosen-sprite@2x.pngbin0 -> 871 bytes
-rw-r--r--www/wiki/resources/lib/jquery.chosen/chosen.css440
-rw-r--r--www/wiki/resources/lib/jquery.chosen/chosen.jquery.js1103
-rw-r--r--www/wiki/resources/lib/jquery.client/AUTHORS.txt9
-rw-r--r--www/wiki/resources/lib/jquery.client/LICENSE-MIT.txt20
-rw-r--r--www/wiki/resources/lib/jquery.client/README.md6
-rw-r--r--www/wiki/resources/lib/jquery.client/jquery.client.js320
-rw-r--r--www/wiki/resources/lib/jquery.i18n/CREDITS9
-rw-r--r--www/wiki/resources/lib/jquery.i18n/GPL-LICENSE339
-rw-r--r--www/wiki/resources/lib/jquery.i18n/MIT-LICENSE21
-rw-r--r--www/wiki/resources/lib/jquery.i18n/README.md432
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.emitter.bidi.js88
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.emitter.js168
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.fallbacks.js186
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.js287
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.language.js472
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.messagestore.js125
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.parser.js309
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/bs.js22
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/dsb.js22
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/fi.js49
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/ga.js38
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/he.js31
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/hsb.js21
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/hu.js26
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/hy.js25
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/la.js54
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/ml.js98
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/os.js76
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/ru.js29
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/sl.js26
-rw-r--r--www/wiki/resources/lib/jquery.i18n/src/languages/uk.js39
-rw-r--r--www/wiki/resources/lib/jquery.ui/PATCHES34
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-af.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar-DZ.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-az.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bg.js24
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bs.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ca.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cs.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cy-GB.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-da.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-AT.js22
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-CH.js22
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-el.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-AU.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-NZ.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eo.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-es.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-et.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eu.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fa.js59
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fi.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fo.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr-CH.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr.js25
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-gl.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-he.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hi.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hr.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hu.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hy.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-id.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-is.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-it.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ja.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ka.js21
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-kk.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-km.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ko.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lb.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lt.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lv.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-mk.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ml.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ms.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl-BE.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-no.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pl.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt.js22
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-rm.js21
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ro.js26
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ru.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sk.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sl.js24
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sq.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sv.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ta.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-th.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tj.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tr.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-uk.js24
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-vi.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js23
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.accordion.js731
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.autocomplete.js602
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.button.js418
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.core.js356
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.datepicker.js1846
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.dialog.js858
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.draggable.js840
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.droppable.js294
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-blind.js82
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-bounce.js113
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-clip.js67
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-drop.js65
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-explode.js97
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-fade.js30
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-fold.js76
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-highlight.js50
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-pulsate.js63
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-scale.js318
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-shake.js74
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-slide.js64
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect-transfer.js47
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.effect.js1276
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.menu.js610
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.mouse.js169
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.position.js517
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.progressbar.js105
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.resizable.js801
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.selectable.js261
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.slider.js644
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.sortable.js1096
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.spinner.js478
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.tabs.js1366
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.tooltip.js398
-rw-r--r--www/wiki/resources/lib/jquery.ui/jquery.ui.widget.js528
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/PATCHES3
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.pngbin0 -> 212 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_flat_75_ffffff_40x100.pngbin0 -> 208 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.pngbin0 -> 335 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.pngbin0 -> 262 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.pngbin0 -> 262 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.pngbin0 -> 332 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.pngbin0 -> 280 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_222222_256x240.pngbin0 -> 6922 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_2e83ff_256x240.pngbin0 -> 4549 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_454545_256x240.pngbin0 -> 6992 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_888888_256x240.pngbin0 -> 6999 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.pngbin0 -> 4549 bytes
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.accordion.css16
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.autocomplete.css19
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.button.css40
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.core.css39
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.datepicker.css67
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.dialog.css22
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.menu.css30
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.progressbar.css12
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.resizable.css21
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.selectable.css11
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.slider.css25
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.spinner.css23
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.tabs.css18
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.theme.css246
-rw-r--r--www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.tooltip.css21
-rw-r--r--www/wiki/resources/lib/jquery/jquery.appear.js138
-rw-r--r--www/wiki/resources/lib/jquery/jquery.async.js69
-rw-r--r--www/wiki/resources/lib/jquery/jquery.ba-throttle-debounce.js252
-rw-r--r--www/wiki/resources/lib/jquery/jquery.cookie.js90
-rw-r--r--www/wiki/resources/lib/jquery/jquery.form.js1089
-rw-r--r--www/wiki/resources/lib/jquery/jquery.fullscreen.js175
-rw-r--r--www/wiki/resources/lib/jquery/jquery.hoverIntent.js111
-rw-r--r--www/wiki/resources/lib/jquery/jquery.jStorage.js996
-rw-r--r--www/wiki/resources/lib/jquery/jquery.js10351
-rw-r--r--www/wiki/resources/lib/jquery/jquery.migrate.js621
-rw-r--r--www/wiki/resources/lib/jquery/jquery.mockjax.js382
-rw-r--r--www/wiki/resources/lib/jquery/jquery.xmldom.js46
-rw-r--r--www/wiki/resources/lib/jquery/jquery3.js10253
-rw-r--r--www/wiki/resources/lib/json2/json2.js519
-rw-r--r--www/wiki/resources/lib/moment/LICENSE22
-rw-r--r--www/wiki/resources/lib/moment/README.md61
-rw-r--r--www/wiki/resources/lib/moment/locale/af.js73
-rw-r--r--www/wiki/resources/lib/moment/locale/ar-ma.js60
-rw-r--r--www/wiki/resources/lib/moment/locale/ar-sa.js105
-rw-r--r--www/wiki/resources/lib/moment/locale/ar-tn.js59
-rw-r--r--www/wiki/resources/lib/moment/locale/ar.js142
-rw-r--r--www/wiki/resources/lib/moment/locale/az.js105
-rw-r--r--www/wiki/resources/lib/moment/locale/be.js134
-rw-r--r--www/wiki/resources/lib/moment/locale/bg.js90
-rw-r--r--www/wiki/resources/lib/moment/locale/bm.js59
-rw-r--r--www/wiki/resources/lib/moment/locale/bn.js119
-rw-r--r--www/wiki/resources/lib/moment/locale/bo.js119
-rw-r--r--www/wiki/resources/lib/moment/locale/br.js108
-rw-r--r--www/wiki/resources/lib/moment/locale/bs.js143
-rw-r--r--www/wiki/resources/lib/moment/locale/ca.js88
-rw-r--r--www/wiki/resources/lib/moment/locale/cs.js172
-rw-r--r--www/wiki/resources/lib/moment/locale/cv.js63
-rw-r--r--www/wiki/resources/lib/moment/locale/cy.js81
-rw-r--r--www/wiki/resources/lib/moment/locale/da.js60
-rw-r--r--www/wiki/resources/lib/moment/locale/de-at.js79
-rw-r--r--www/wiki/resources/lib/moment/locale/de-ch.js78
-rw-r--r--www/wiki/resources/lib/moment/locale/de.js78
-rw-r--r--www/wiki/resources/lib/moment/locale/dv.js100
-rw-r--r--www/wiki/resources/lib/moment/locale/el.js100
-rw-r--r--www/wiki/resources/lib/moment/locale/en-au.js67
-rw-r--r--www/wiki/resources/lib/moment/locale/en-ca.js63
-rw-r--r--www/wiki/resources/lib/moment/locale/en-gb.js67
-rw-r--r--www/wiki/resources/lib/moment/locale/eo.js73
-rw-r--r--www/wiki/resources/lib/moment/locale/es.js92
-rw-r--r--www/wiki/resources/lib/moment/locale/et.js80
-rw-r--r--www/wiki/resources/lib/moment/locale/eu.js66
-rw-r--r--www/wiki/resources/lib/moment/locale/fa.js107
-rw-r--r--www/wiki/resources/lib/moment/locale/fi.js107
-rw-r--r--www/wiki/resources/lib/moment/locale/fo.js60
-rw-r--r--www/wiki/resources/lib/moment/locale/fr-ca.js74
-rw-r--r--www/wiki/resources/lib/moment/locale/fr.js83
-rw-r--r--www/wiki/resources/lib/moment/locale/fy.js75
-rw-r--r--www/wiki/resources/lib/moment/locale/gd.js76
-rw-r--r--www/wiki/resources/lib/moment/locale/gl.js77
-rw-r--r--www/wiki/resources/lib/moment/locale/gom-latn.js122
-rw-r--r--www/wiki/resources/lib/moment/locale/gu.js124
-rw-r--r--www/wiki/resources/lib/moment/locale/he.js99
-rw-r--r--www/wiki/resources/lib/moment/locale/hi.js124
-rw-r--r--www/wiki/resources/lib/moment/locale/hr.js145
-rw-r--r--www/wiki/resources/lib/moment/locale/hu.js108
-rw-r--r--www/wiki/resources/lib/moment/locale/hy-am.js95
-rw-r--r--www/wiki/resources/lib/moment/locale/id.js83
-rw-r--r--www/wiki/resources/lib/moment/locale/is.js127
-rw-r--r--www/wiki/resources/lib/moment/locale/it.js70
-rw-r--r--www/wiki/resources/lib/moment/locale/ja.js80
-rw-r--r--www/wiki/resources/lib/moment/locale/jv.js83
-rw-r--r--www/wiki/resources/lib/moment/locale/ka.js89
-rw-r--r--www/wiki/resources/lib/moment/locale/kk.js87
-rw-r--r--www/wiki/resources/lib/moment/locale/km.js58
-rw-r--r--www/wiki/resources/lib/moment/locale/kn.js126
-rw-r--r--www/wiki/resources/lib/moment/locale/ko.js83
-rw-r--r--www/wiki/resources/lib/moment/locale/ky.js88
-rw-r--r--www/wiki/resources/lib/moment/locale/lb.js137
-rw-r--r--www/wiki/resources/lib/moment/locale/lo.js70
-rw-r--r--www/wiki/resources/lib/moment/locale/lt.js117
-rw-r--r--www/wiki/resources/lib/moment/locale/lv.js97
-rw-r--r--www/wiki/resources/lib/moment/locale/mi.js64
-rw-r--r--www/wiki/resources/lib/moment/locale/mk.js90
-rw-r--r--www/wiki/resources/lib/moment/locale/ml.js81
-rw-r--r--www/wiki/resources/lib/moment/locale/mr.js159
-rw-r--r--www/wiki/resources/lib/moment/locale/ms-my.js83
-rw-r--r--www/wiki/resources/lib/moment/locale/ms.js82
-rw-r--r--www/wiki/resources/lib/moment/locale/my.js96
-rw-r--r--www/wiki/resources/lib/moment/locale/nb.js63
-rw-r--r--www/wiki/resources/lib/moment/locale/ne.js123
-rw-r--r--www/wiki/resources/lib/moment/locale/nl.js88
-rw-r--r--www/wiki/resources/lib/moment/locale/nn.js60
-rw-r--r--www/wiki/resources/lib/moment/locale/pa-in.js124
-rw-r--r--www/wiki/resources/lib/moment/locale/pl.js124
-rw-r--r--www/wiki/resources/lib/moment/locale/pt-br.js62
-rw-r--r--www/wiki/resources/lib/moment/locale/pt.js65
-rw-r--r--www/wiki/resources/lib/moment/locale/ro.js75
-rw-r--r--www/wiki/resources/lib/moment/locale/ru.js183
-rw-r--r--www/wiki/resources/lib/moment/locale/sd.js98
-rw-r--r--www/wiki/resources/lib/moment/locale/se.js61
-rw-r--r--www/wiki/resources/lib/moment/locale/si.js71
-rw-r--r--www/wiki/resources/lib/moment/locale/sk.js150
-rw-r--r--www/wiki/resources/lib/moment/locale/sl.js162
-rw-r--r--www/wiki/resources/lib/moment/locale/sq.js70
-rw-r--r--www/wiki/resources/lib/moment/locale/sr-cyrl.js110
-rw-r--r--www/wiki/resources/lib/moment/locale/sr.js110
-rw-r--r--www/wiki/resources/lib/moment/locale/ss.js89
-rw-r--r--www/wiki/resources/lib/moment/locale/sv.js69
-rw-r--r--www/wiki/resources/lib/moment/locale/sw.js59
-rw-r--r--www/wiki/resources/lib/moment/locale/ta.js130
-rw-r--r--www/wiki/resources/lib/moment/locale/te.js89
-rw-r--r--www/wiki/resources/lib/moment/locale/tet.js68
-rw-r--r--www/wiki/resources/lib/moment/locale/th.js67
-rw-r--r--www/wiki/resources/lib/moment/locale/tl-ph.js62
-rw-r--r--www/wiki/resources/lib/moment/locale/tr.js90
-rw-r--r--www/wiki/resources/lib/moment/locale/tzm-latn.js58
-rw-r--r--www/wiki/resources/lib/moment/locale/tzm.js58
-rw-r--r--www/wiki/resources/lib/moment/locale/uk.js151
-rw-r--r--www/wiki/resources/lib/moment/locale/ur.js99
-rw-r--r--www/wiki/resources/lib/moment/locale/uz-latn.js58
-rw-r--r--www/wiki/resources/lib/moment/locale/uz.js58
-rw-r--r--www/wiki/resources/lib/moment/locale/vi.js79
-rw-r--r--www/wiki/resources/lib/moment/locale/yo.js60
-rw-r--r--www/wiki/resources/lib/moment/locale/zh-cn.js111
-rw-r--r--www/wiki/resources/lib/moment/locale/zh-hk.js105
-rw-r--r--www/wiki/resources/lib/moment/locale/zh-tw.js104
-rw-r--r--www/wiki/resources/lib/moment/moment.js4515
-rw-r--r--www/wiki/resources/lib/mustache/LICENSE10
-rw-r--r--www/wiki/resources/lib/mustache/mustache.js578
-rw-r--r--www/wiki/resources/lib/oojs-router/AUTHORS.txt1
-rw-r--r--www/wiki/resources/lib/oojs-router/LICENSE-MIT20
-rw-r--r--www/wiki/resources/lib/oojs-router/oojs-router.js205
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ace.json10
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/af.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ais.json15
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/am.json7
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ar.json36
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/arc.json7
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/arq.json21
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/as.json25
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ast.json26
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/awa.json8
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/az.json13
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/azb.json11
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ba.json29
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/bcc.json9
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/bcl.json11
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/be-tarask.json29
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/be.json25
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/bg.json28
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/bho.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/bn.json32
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/bqi.json22
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/br.json28
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/bs.json25
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ca.json35
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/cdo.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ce.json19
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ckb.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/co.json9
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/crh-cyrl.json8
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/crh-latn.json8
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/cs.json36
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/cu.json10
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/cy.json27
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/da.json28
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/de.json33
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/diq.json29
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/dsb.json11
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/dty.json18
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/egl.json14
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/el.json31
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/eml.json14
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/en-ca.json22
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/en.json36
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/eo.json28
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/es.json38
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/et.json25
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/eu.json29
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/fa.json37
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/fi.json36
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/fo.json19
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/fr.json53
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/frr.json12
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/fur.json11
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/fy.json11
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/gd.json13
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/gl.json28
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/glk.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/gom-latn.json14
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/gor.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/gu.json27
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/he.json35
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/hi.json30
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/hif-latn.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/hr.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/hrx.json12
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/hsb.json20
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/hu-formal.json21
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/hu.json29
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/hy.json26
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ia.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/id.json32
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ie.json10
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ilo.json21
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/inh.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/io.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/is.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/it.json39
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ja.json30
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/jv.json27
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ka.json30
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/kab.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/khw.json12
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/kk-cyrl.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/km.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/kn.json26
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ko.json34
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/krc.json22
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/krl.json10
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ksh.json22
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ku-latn.json17
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/kw.json9
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ky.json11
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/la.json15
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/lb.json30
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/li.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/lki.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/lmo.json10
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/lt.json26
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/luz.json21
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/lv.json27
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/lzh.json8
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/mg.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/min.json14
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/mk.json26
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ml.json27
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/mn.json20
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/mr.json30
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ms.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/nan.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/nap.json27
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/nb.json29
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/nds-nl.json19
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/nds.json16
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ne.json22
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/nl.json41
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/nn.json20
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/oc.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/olo.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/om.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/or.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/pa.json27
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/pfl.json13
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/pl.json40
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/pms.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/pnb.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ps.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/pt-br.json34
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/pt.json34
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/qqq.json41
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/qu.json12
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ro.json27
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/roa-tara.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ru.json41
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sa.json14
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sah.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/scn.json13
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sco.json22
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sd.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sh.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/shn.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/si.json11
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sk.json22
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/skr-arab.json18
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sl.json26
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sq.json29
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sr-ec.json29
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sr-el.json21
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/su.json25
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sv.json34
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/sw.json16
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ta.json26
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/te.json30
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/tg-cyrl.json11
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/th.json10
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/tl.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/tr.json34
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/tt-cyrl.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ug-arab.json25
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/uk.json39
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/ur.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/uz.json13
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/vec.json22
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/vep.json8
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/vi.json28
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/vo.json8
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/war.json19
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/wuu.json10
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/xmf.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/yi.json24
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/yo.json10
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/yue.json27
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/zh-hans.json41
-rw-r--r--www/wiki/resources/lib/oojs-ui/i18n/zh-hant.json37
-rw-r--r--www/wiki/resources/lib/oojs-ui/images/grab.curbin0 -> 326 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/images/grabbing.curbin0 -> 326 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-apex.js45
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-apex.js.map1
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-core-apex.css1481
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-core-mediawiki.css1350
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-core-wikimediaui.css1987
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-core.js11511
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-core.js.map1
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-mediawiki.js79
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-apex.css559
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-mediawiki.css459
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-wikimediaui.css540
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars.js2366
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars.js.map1
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-apex.css1154
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-mediawiki.css1017
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-wikimediaui.css1324
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-widgets.js6932
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-widgets.js.map1
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-wikimediaui.js91
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-wikimediaui.js.map1
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-windows-apex.css414
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-windows-mediawiki.css385
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-windows-wikimediaui.css422
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-windows.js3571
-rw-r--r--www/wiki/resources/lib/oojs-ui/oojs-ui-windows.js.map1
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-accessibility.json28
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-alerts.json44
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-content.json30
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-advanced.json86
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-core.json32
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-list.json22
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-styling.json79
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-interactions.json71
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-layout.json28
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-media.json16
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-moderation.json44
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-movement.json40
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons-user.json7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/icons.json50
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/add.pngbin0 -> 129 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/add.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/advanced.pngbin0 -> 392 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/advanced.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/alert.pngbin0 -> 388 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/alert.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-center.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-center.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-left.pngbin0 -> 155 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-left.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-right.pngbin0 -> 162 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-right.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-ltr.pngbin0 -> 254 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-rtl.pngbin0 -> 254 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-ltr.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-rtl.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-ltr.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-rtl.pngbin0 -> 174 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-ltr.pngbin0 -> 330 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-rtl.pngbin0 -> 331 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-ltr.pngbin0 -> 367 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-rtl.pngbin0 -> 366 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bell.pngbin0 -> 235 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bell.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.pngbin0 -> 345 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.pngbin0 -> 367 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta-invert.pngbin0 -> 321 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta.pngbin0 -> 297 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch-invert.pngbin0 -> 288 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-ltr.pngbin0 -> 349 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-rtl.pngbin0 -> 348 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/block.pngbin0 -> 258 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/block.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-ltr.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-rtl.pngbin0 -> 289 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-a.pngbin0 -> 257 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-a.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-ain.pngbin0 -> 260 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-ain.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-dad.pngbin0 -> 297 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-dad.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-armn-to.pngbin0 -> 325 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-armn-to.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-b.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-b.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-be.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-be.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-te.pngbin0 -> 129 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-te.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-zhe.pngbin0 -> 320 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-zhe.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-f.pngbin0 -> 134 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-f.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-g.pngbin0 -> 304 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-g.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-geor-man.pngbin0 -> 279 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-geor-man.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-l.pngbin0 -> 127 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-l.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-n.pngbin0 -> 160 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-n.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-v.pngbin0 -> 240 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-v.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr-invert.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr.pngbin0 -> 203 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl-invert.pngbin0 -> 205 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright-invert.pngbin0 -> 372 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright.pngbin0 -> 368 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr-invert.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr.pngbin0 -> 186 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl-invert.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.pngbin0 -> 187 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/cancel.pngbin0 -> 325 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/cancel.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-ltr.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-rtl.pngbin0 -> 231 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretDown.pngbin0 -> 238 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretDown.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretUp.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretUp.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/case-sensitive.pngbin0 -> 353 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/case-sensitive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/check.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/check.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/circle.pngbin0 -> 200 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/circle.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear-invert.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clip.pngbin0 -> 279 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clip.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock-invert.pngbin0 -> 362 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock.pngbin0 -> 337 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/close.pngbin0 -> 205 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/close.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/code.pngbin0 -> 272 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/code.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/collapse.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/collapse.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/comment.pngbin0 -> 183 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/comment.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/diacritic.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/diacritic.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/downTriangle.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/downTriangle.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/draggable.pngbin0 -> 115 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/draggable.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-ltr.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-rtl.pngbin0 -> 267 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-ltr.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-rtl.pngbin0 -> 302 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-ltr.pngbin0 -> 361 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-rtl.pngbin0 -> 371 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ellipsis.pngbin0 -> 144 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ellipsis.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/expand.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/expand.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-ltr.pngbin0 -> 206 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-rtl.pngbin0 -> 203 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye-invert.pngbin0 -> 333 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye.pngbin0 -> 311 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed-invert.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.pngbin0 -> 296 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-ltr.pngbin0 -> 294 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-rtl.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-ltr.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-rtl.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-ltr.pngbin0 -> 214 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-rtl.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-ltr.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-rtl.pngbin0 -> 272 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/fullScreen.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/fullScreen.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr-invert.pngbin0 -> 221 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr.pngbin0 -> 216 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl-invert.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl.pngbin0 -> 217 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright-invert.pngbin0 -> 310 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright.pngbin0 -> 319 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-ltr.pngbin0 -> 429 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-rtl.pngbin0 -> 419 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart-invert.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart.pngbin0 -> 250 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-ltr.pngbin0 -> 483 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-ltr.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-rtl.pngbin0 -> 494 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-rtl.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-ltr.pngbin0 -> 328 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-rtl.pngbin0 -> 333 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/history.pngbin0 -> 524 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/history.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/image.pngbin0 -> 294 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/image.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-ltr.pngbin0 -> 291 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-rtl.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-ltr.pngbin0 -> 223 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-ltr.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-rtl.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-rtl.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/info.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/info.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-a.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-a.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-keheh-jeem.pngbin0 -> 317 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-keheh-jeem.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-meem.pngbin0 -> 240 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-meem.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-armn-sha.pngbin0 -> 324 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-armn-sha.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-c.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-c.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-d.pngbin0 -> 314 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-d.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-e.pngbin0 -> 240 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-e.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-geor-kan.pngbin0 -> 275 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-geor-kan.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-i.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-i.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-k.pngbin0 -> 268 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-k.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-s.pngbin0 -> 305 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-s.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-ltr.pngbin0 -> 168 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-rtl.pngbin0 -> 169 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr-invert.pngbin0 -> 270 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr.pngbin0 -> 255 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl-invert.pngbin0 -> 273 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr-invert.pngbin0 -> 170 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr.pngbin0 -> 164 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl-invert.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-ltr.pngbin0 -> 455 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-ltr.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-rtl.pngbin0 -> 448 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-rtl.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr-invert.pngbin0 -> 345 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr.pngbin0 -> 336 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl-invert.pngbin0 -> 354 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl.pngbin0 -> 340 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-ltr.pngbin0 -> 150 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-rtl.pngbin0 -> 147 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/link.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/link.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-ltr.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-ltr.svg11
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-rtl.pngbin0 -> 175 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-rtl.svg11
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-ltr.pngbin0 -> 240 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-ltr.svg11
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-rtl.pngbin0 -> 245 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-rtl.svg11
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/lock.pngbin0 -> 175 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/lock.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr-invert.pngbin0 -> 214 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr.pngbin0 -> 201 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl-invert.pngbin0 -> 236 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/markup.pngbin0 -> 251 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/markup.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/menu.pngbin0 -> 158 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/menu.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.pngbin0 -> 268 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.pngbin0 -> 272 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon-invert.pngbin0 -> 318 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon.pngbin0 -> 326 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-ltr.pngbin0 -> 204 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-rtl.pngbin0 -> 221 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-ltr.pngbin0 -> 179 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-rtl.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr-invert.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr.pngbin0 -> 194 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl-invert.pngbin0 -> 208 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl.pngbin0 -> 204 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-ltr.pngbin0 -> 248 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-rtl.pngbin0 -> 263 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-ltr.pngbin0 -> 212 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-rtl.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright-invert.pngbin0 -> 263 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright.pngbin0 -> 249 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notice.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notice.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-ltr.pngbin0 -> 257 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-rtl.pngbin0 -> 266 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-ltr.pngbin0 -> 224 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-ltr.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-rtl.pngbin0 -> 228 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-rtl.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-ltr.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-rtl.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-ltr.pngbin0 -> 261 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-rtl.pngbin0 -> 258 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr-invert.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl-invert.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/pushPin.pngbin0 -> 254 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/pushPin.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-ltr.pngbin0 -> 308 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-rtl.pngbin0 -> 321 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle.pngbin0 -> 310 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-ltr.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-rtl.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-ltr.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-ltr.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-rtl.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-rtl.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/regular-expression.pngbin0 -> 325 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/regular-expression.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize-invert.pngbin0 -> 381 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize.pngbin0 -> 373 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-ltr.pngbin0 -> 358 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-rtl.pngbin0 -> 331 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search.pngbin0 -> 350 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/secure-link.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/secure-link.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/settings.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/settings.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.pngbin0 -> 409 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.pngbin0 -> 425 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-ltr.pngbin0 -> 352 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-rtl.pngbin0 -> 350 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr-invert.pngbin0 -> 276 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl-invert.pngbin0 -> 261 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl.pngbin0 -> 261 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/specialCharacter.pngbin0 -> 323 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/specialCharacter.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.pngbin0 -> 142 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.pngbin0 -> 164 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.pngbin0 -> 177 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.pngbin0 -> 163 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.pngbin0 -> 168 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/star.pngbin0 -> 415 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/star.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-a.pngbin0 -> 280 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-a.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-s.pngbin0 -> 302 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-s.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-y.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-y.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-ltr.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-rtl.pngbin0 -> 140 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-ltr.pngbin0 -> 123 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-rtl.pngbin0 -> 124 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-ltr.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-rtl.pngbin0 -> 135 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-ltr.pngbin0 -> 224 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-rtl.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subtract.pngbin0 -> 115 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subtract.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr-invert.pngbin0 -> 374 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr.pngbin0 -> 361 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl-invert.pngbin0 -> 359 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl.pngbin0 -> 336 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-ltr.pngbin0 -> 220 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-rtl.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-caption.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-caption.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-ltr.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-rtl.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-after.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-after.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-before.pngbin0 -> 135 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-before.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-merge-cells.pngbin0 -> 204 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-merge-cells.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table.pngbin0 -> 135 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tag.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tag.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-ltr.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-rtl.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-lefttoright.pngbin0 -> 210 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-lefttoright.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-righttoleft.pngbin0 -> 215 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-righttoleft.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-style.pngbin0 -> 293 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-style.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trash.pngbin0 -> 149 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trash.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-ltr.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-rtl.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tray.pngbin0 -> 342 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tray.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-ltr.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-rtl.pngbin0 -> 289 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unClip.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unClip.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-ltr.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-rtl.pngbin0 -> 313 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-ltr.pngbin0 -> 175 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-rtl.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unStar.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unStar.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-ltr.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-rtl.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-a.pngbin0 -> 278 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-a.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-u.pngbin0 -> 192 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-u.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upTriangle.pngbin0 -> 187 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upTriangle.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-ltr.pngbin0 -> 234 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-rtl.pngbin0 -> 237 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/userAvatar.pngbin0 -> 318 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/userAvatar.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewCompact.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewCompact.svg14
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-ltr.pngbin0 -> 165 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-ltr.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-rtl.pngbin0 -> 165 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-rtl.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator-invert.pngbin0 -> 205 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr-invert.pngbin0 -> 294 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr.pngbin0 -> 280 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl-invert.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl.pngbin0 -> 266 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/wikiText.pngbin0 -> 140 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/wikiText.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/window.pngbin0 -> 226 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/window.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/alert.pngbin0 -> 190 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/alert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-down.pngbin0 -> 153 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-down.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-ltr.pngbin0 -> 150 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-rtl.pngbin0 -> 155 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-up.pngbin0 -> 155 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-up.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/clear.pngbin0 -> 197 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/clear.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/required.pngbin0 -> 201 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/required.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-ltr.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-rtl.pngbin0 -> 217 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/pending.gifbin0 -> 2032 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/transparency.pngbin0 -> 113 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/transparency.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/images/toolbar-shadow.pngbin0 -> 83 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/indicators.json23
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/apex/textures.json8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-accessibility.json26
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-alerts.json40
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-content.json65
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-advanced.json91
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-core.json54
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-list.json29
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-styling.json82
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-interactions.json59
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-layout.json43
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-location.json26
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-media.json39
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-moderation.json60
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-movement.json34
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-user.json26
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-wikimedia.json16
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons.json78
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-constructive.pngbin0 -> 133 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-constructive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-invert.pngbin0 -> 132 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-progressive.pngbin0 -> 133 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add.pngbin0 -> 129 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced-invert.pngbin0 -> 368 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced.pngbin0 -> 372 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-invert.pngbin0 -> 396 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-invert.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-warning.pngbin0 -> 532 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-warning.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert.pngbin0 -> 388 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center-invert.pngbin0 -> 145 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left-invert.pngbin0 -> 159 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left.pngbin0 -> 155 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right-invert.pngbin0 -> 173 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right.pngbin0 -> 162 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr-invert.pngbin0 -> 287 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl-invert.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl.pngbin0 -> 267 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr-invert.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl-invert.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr-invert.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl-invert.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl.pngbin0 -> 174 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr-invert.pngbin0 -> 297 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr.pngbin0 -> 287 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl-invert.pngbin0 -> 292 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl.pngbin0 -> 279 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr-invert.pngbin0 -> 360 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr.pngbin0 -> 330 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl-invert.pngbin0 -> 356 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl.pngbin0 -> 331 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr-invert.pngbin0 -> 349 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr.pngbin0 -> 331 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl-invert.pngbin0 -> 368 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl.pngbin0 -> 347 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr-invert.pngbin0 -> 380 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr.pngbin0 -> 367 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl-invert.pngbin0 -> 387 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl.pngbin0 -> 366 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.pngbin0 -> 238 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.pngbin0 -> 237 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.pngbin0 -> 370 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.pngbin0 -> 346 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.pngbin0 -> 379 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.pngbin0 -> 366 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta-invert.pngbin0 -> 321 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta.pngbin0 -> 297 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch-invert.pngbin0 -> 288 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr-invert.pngbin0 -> 331 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr.pngbin0 -> 322 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl-invert.pngbin0 -> 333 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl.pngbin0 -> 326 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.pngbin0 -> 277 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-invert.pngbin0 -> 267 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block.pngbin0 -> 258 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr-invert.pngbin0 -> 292 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl-invert.pngbin0 -> 287 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl.pngbin0 -> 289 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a-invert.pngbin0 -> 265 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a.pngbin0 -> 257 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain-invert.pngbin0 -> 272 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain.pngbin0 -> 260 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad-invert.pngbin0 -> 308 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad.pngbin0 -> 297 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to-invert.pngbin0 -> 335 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to.pngbin0 -> 325 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b-invert.pngbin0 -> 223 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be-invert.pngbin0 -> 208 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te-invert.pngbin0 -> 134 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te.pngbin0 -> 129 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe-invert.pngbin0 -> 319 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe.pngbin0 -> 320 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f-invert.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f.pngbin0 -> 134 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g-invert.pngbin0 -> 318 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g.pngbin0 -> 304 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man-invert.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man.pngbin0 -> 279 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l-invert.pngbin0 -> 130 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l.pngbin0 -> 127 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n-invert.pngbin0 -> 160 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n.pngbin0 -> 160 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v-invert.pngbin0 -> 245 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v.pngbin0 -> 240 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr-invert.pngbin0 -> 226 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr.pngbin0 -> 200 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl-invert.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl.pngbin0 -> 210 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr-invert.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr.pngbin0 -> 203 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl-invert.pngbin0 -> 205 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright-invert.pngbin0 -> 372 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright.pngbin0 -> 368 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr-invert.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr.pngbin0 -> 186 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl-invert.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.pngbin0 -> 187 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.pngbin0 -> 434 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-invert.pngbin0 -> 329 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel.pngbin0 -> 325 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr-invert.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl-invert.pngbin0 -> 243 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl.pngbin0 -> 231 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown-invert.pngbin0 -> 236 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown.pngbin0 -> 238 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp-invert.pngbin0 -> 234 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive-invert.pngbin0 -> 384 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive.pngbin0 -> 353 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive-deprecated.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive-deprecated.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-invert.pngbin0 -> 170 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-progressive.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check.pngbin0 -> 167 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive-deprecated.pngbin0 -> 227 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive-deprecated.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive.pngbin0 -> 227 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-invert.pngbin0 -> 211 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-progressive.pngbin0 -> 227 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle.pngbin0 -> 200 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr-invert.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl-invert.pngbin0 -> 197 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl.pngbin0 -> 197 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear-invert.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock-invert.pngbin0 -> 295 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock.pngbin0 -> 293 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.pngbin0 -> 275 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.pngbin0 -> 268 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.pngbin0 -> 268 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code-invert.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code.pngbin0 -> 272 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse-invert.pngbin0 -> 176 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment.pngbin0 -> 183 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr-invert.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl-invert.pngbin0 -> 217 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl.pngbin0 -> 194 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle-invert.pngbin0 -> 189 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr-invert.pngbin0 -> 235 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr.pngbin0 -> 232 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl-invert.pngbin0 -> 238 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-invert.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-progressive.pngbin0 -> 435 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-invert.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-progressive.pngbin0 -> 422 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl.pngbin0 -> 267 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr-invert.pngbin0 -> 314 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl-invert.pngbin0 -> 319 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl.pngbin0 -> 302 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr-invert.pngbin0 -> 374 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr.pngbin0 -> 361 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl-invert.pngbin0 -> 380 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl.pngbin0 -> 371 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis-invert.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis.pngbin0 -> 144 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand-invert.pngbin0 -> 182 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr-invert.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr.pngbin0 -> 206 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl-invert.pngbin0 -> 210 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl.pngbin0 -> 203 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye-invert.pngbin0 -> 332 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye.pngbin0 -> 311 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed-invert.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed.pngbin0 -> 296 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr-invert.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl-invert.pngbin0 -> 302 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr-invert.pngbin0 -> 231 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr.pngbin0 -> 214 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl-invert.pngbin0 -> 239 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr-invert.pngbin0 -> 232 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl-invert.pngbin0 -> 257 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl.pngbin0 -> 272 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr-invert.pngbin0 -> 159 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr.pngbin0 -> 147 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl-invert.pngbin0 -> 163 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl.pngbin0 -> 151 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen-invert.pngbin0 -> 227 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr-invert.pngbin0 -> 221 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr.pngbin0 -> 216 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl-invert.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl.pngbin0 -> 217 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright-invert.pngbin0 -> 310 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright.pngbin0 -> 319 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart-invert.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart.pngbin0 -> 250 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr-invert.pngbin0 -> 503 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr-invert.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr.pngbin0 -> 483 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl-invert.pngbin0 -> 515 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl-invert.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl.pngbin0 -> 494 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history-invert.pngbin0 -> 557 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history.pngbin0 -> 524 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr-invert.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr.pngbin0 -> 183 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl-invert.pngbin0 -> 187 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr-invert.pngbin0 -> 232 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr.pngbin0 -> 226 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl-invert.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl.pngbin0 -> 215 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr-invert.pngbin0 -> 213 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl-invert.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl.pngbin0 -> 201 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr-invert.pngbin0 -> 266 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr.pngbin0 -> 256 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl-invert.pngbin0 -> 268 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl.pngbin0 -> 256 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl-invert.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info-invert.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a-invert.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem-invert.pngbin0 -> 339 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem.pngbin0 -> 317 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem-invert.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem.pngbin0 -> 240 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha-invert.pngbin0 -> 322 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha.pngbin0 -> 324 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c-invert.pngbin0 -> 289 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d-invert.pngbin0 -> 335 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d.pngbin0 -> 314 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e-invert.pngbin0 -> 247 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e.pngbin0 -> 240 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan-invert.pngbin0 -> 288 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan.pngbin0 -> 275 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i-invert.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k-invert.pngbin0 -> 284 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k.pngbin0 -> 268 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s-invert.pngbin0 -> 323 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s.pngbin0 -> 305 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr-invert.pngbin0 -> 174 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr.pngbin0 -> 168 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl-invert.pngbin0 -> 179 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl.pngbin0 -> 176 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr-invert.pngbin0 -> 270 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr.pngbin0 -> 255 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl-invert.pngbin0 -> 273 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr-invert.pngbin0 -> 170 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr.pngbin0 -> 164 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl-invert.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr-invert.pngbin0 -> 480 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr-invert.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr.pngbin0 -> 455 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl-invert.pngbin0 -> 469 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl-invert.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl.pngbin0 -> 448 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr-invert.pngbin0 -> 345 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr.pngbin0 -> 336 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl-invert.pngbin0 -> 345 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl.pngbin0 -> 336 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr-invert.pngbin0 -> 157 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr.pngbin0 -> 150 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl-invert.pngbin0 -> 154 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl.pngbin0 -> 147 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr-invert.pngbin0 -> 444 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr.pngbin0 -> 412 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl-invert.pngbin0 -> 434 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl.pngbin0 -> 429 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr-invert.pngbin0 -> 155 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr.pngbin0 -> 145 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl-invert.pngbin0 -> 144 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl.pngbin0 -> 141 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr-invert.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl-invert.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-invert.pngbin0 -> 228 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr.pngbin0 -> 224 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-invert.pngbin0 -> 228 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl.pngbin0 -> 227 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr-invert.pngbin0 -> 214 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr.pngbin0 -> 201 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl-invert.pngbin0 -> 236 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc-invert.pngbin0 -> 338 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc.pngbin0 -> 319 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons-invert.pngbin0 -> 525 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons.pngbin0 -> 484 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia-invert.pngbin0 -> 445 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia.pngbin0 -> 428 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr-invert.pngbin0 -> 292 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr.pngbin0 -> 251 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl-invert.pngbin0 -> 309 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.pngbin0 -> 318 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.pngbin0 -> 323 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.pngbin0 -> 336 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.pngbin0 -> 343 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.pngbin0 -> 342 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.pngbin0 -> 351 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup-invert.pngbin0 -> 256 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup.pngbin0 -> 251 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu-invert.pngbin0 -> 160 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu.pngbin0 -> 158 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr-invert.pngbin0 -> 288 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr.pngbin0 -> 268 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl-invert.pngbin0 -> 288 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl.pngbin0 -> 272 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon-invert.pngbin0 -> 318 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon.pngbin0 -> 326 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-invert.pngbin0 -> 228 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr-invert.pngbin0 -> 179 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr.pngbin0 -> 179 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr-invert.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr.pngbin0 -> 194 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl-invert.pngbin0 -> 208 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl.pngbin0 -> 204 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr-invert.pngbin0 -> 255 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr.pngbin0 -> 248 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl-invert.pngbin0 -> 258 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl.pngbin0 -> 263 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr-invert.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr.pngbin0 -> 172 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl-invert.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl.pngbin0 -> 173 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr-invert.pngbin0 -> 212 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr.pngbin0 -> 212 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl-invert.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright-invert.pngbin0 -> 263 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright.pngbin0 -> 249 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice-invert.pngbin0 -> 210 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-invert.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-progressive.pngbin0 -> 339 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr.pngbin0 -> 257 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-invert.pngbin0 -> 285 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-progressive.pngbin0 -> 342 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl.pngbin0 -> 266 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr-invert.pngbin0 -> 186 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr.pngbin0 -> 174 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl.pngbin0 -> 177 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr-invert.pngbin0 -> 147 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl-invert.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr-invert.pngbin0 -> 272 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr.pngbin0 -> 260 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl-invert.pngbin0 -> 273 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl.pngbin0 -> 256 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr-invert.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl-invert.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr-invert.pngbin0 -> 294 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr.pngbin0 -> 308 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl-invert.pngbin0 -> 323 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl.pngbin0 -> 321 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr-invert.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl-invert.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr-invert.pngbin0 -> 279 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr-invert.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl-invert.pngbin0 -> 281 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl-invert.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression-invert.pngbin0 -> 344 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression-invert.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression.pngbin0 -> 325 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize-invert.pngbin0 -> 381 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize.pngbin0 -> 373 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr-invert.pngbin0 -> 334 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr.pngbin0 -> 358 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl-invert.pngbin0 -> 332 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl.pngbin0 -> 331 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link-invert.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings-invert.pngbin0 -> 175 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr-invert.pngbin0 -> 452 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr.pngbin0 -> 409 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl-invert.pngbin0 -> 460 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl.pngbin0 -> 425 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr-invert.pngbin0 -> 332 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr.pngbin0 -> 325 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl-invert.pngbin0 -> 331 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl.pngbin0 -> 326 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr-invert.pngbin0 -> 276 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl-invert.pngbin0 -> 261 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl.pngbin0 -> 261 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter-invert.pngbin0 -> 350 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter.pngbin0 -> 323 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr-invert.pngbin0 -> 152 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr.pngbin0 -> 142 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl-invert.pngbin0 -> 153 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl.pngbin0 -> 164 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr-invert.pngbin0 -> 183 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr.pngbin0 -> 177 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl-invert.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr-invert.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr.pngbin0 -> 163 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl-invert.pngbin0 -> 172 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl.pngbin0 -> 168 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-constructive.pngbin0 -> 610 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-constructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-invert.pngbin0 -> 416 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-progressive.pngbin0 -> 610 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star.pngbin0 -> 415 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop-invert.pngbin0 -> 317 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop.pngbin0 -> 317 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a-invert.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a.pngbin0 -> 280 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s-invert.pngbin0 -> 298 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s.pngbin0 -> 302 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y-invert.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr-invert.pngbin0 -> 139 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl-invert.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl.pngbin0 -> 140 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu-invert.pngbin0 -> 115 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu.pngbin0 -> 115 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr-invert.pngbin0 -> 123 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr.pngbin0 -> 123 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl-invert.pngbin0 -> 124 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl.pngbin0 -> 124 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-invert.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-progressive.pngbin0 -> 144 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-invert.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-progressive.pngbin0 -> 144 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl.pngbin0 -> 135 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr-invert.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr.pngbin0 -> 224 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl-invert.pngbin0 -> 221 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr-invert.pngbin0 -> 374 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr.pngbin0 -> 361 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl-invert.pngbin0 -> 359 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl.pngbin0 -> 336 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr-invert.pngbin0 -> 228 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr.pngbin0 -> 220 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl-invert.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption-invert.pngbin0 -> 148 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr-invert.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl-invert.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after-invert.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before-invert.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before.pngbin0 -> 135 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.pngbin0 -> 142 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells-invert.pngbin0 -> 208 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells-invert.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells.pngbin0 -> 204 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table.pngbin0 -> 135 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-constructive.pngbin0 -> 327 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-constructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.pngbin0 -> 327 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-invert.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-progressive.pngbin0 -> 327 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-warning.pngbin0 -> 327 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-warning.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl-invert.pngbin0 -> 194 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright-invert.pngbin0 -> 213 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright.pngbin0 -> 210 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft-invert.pngbin0 -> 218 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft.pngbin0 -> 215 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style-invert.pngbin0 -> 296 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style.pngbin0 -> 293 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-invert.pngbin0 -> 179 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr-invert.pngbin0 -> 252 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr.pngbin0 -> 236 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl-invert.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl.pngbin0 -> 263 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-invert.pngbin0 -> 234 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-invert.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-constructive.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-constructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-invert.pngbin0 -> 253 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-progressive.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a-invert.pngbin0 -> 291 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a.pngbin0 -> 278 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u-invert.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u.pngbin0 -> 192 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle.pngbin0 -> 187 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr-invert.pngbin0 -> 235 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr.pngbin0 -> 234 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl-invert.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl.pngbin0 -> 237 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr-invert.pngbin0 -> 326 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr.pngbin0 -> 305 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl-invert.pngbin0 -> 315 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl.pngbin0 -> 293 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar-invert.pngbin0 -> 332 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar.pngbin0 -> 318 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr-invert.pngbin0 -> 277 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr.pngbin0 -> 258 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl-invert.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl.pngbin0 -> 256 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr-invert.pngbin0 -> 307 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr.pngbin0 -> 292 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl-invert.pngbin0 -> 307 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl.pngbin0 -> 310 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact-invert.pngbin0 -> 145 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact-invert.svg14
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact.svg14
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr-invert.pngbin0 -> 166 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr-invert.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr.pngbin0 -> 165 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl-invert.pngbin0 -> 165 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl-invert.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl.pngbin0 -> 165 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator-invert.pngbin0 -> 205 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr-invert.pngbin0 -> 294 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr.pngbin0 -> 280 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl-invert.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl.pngbin0 -> 266 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText-invert.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText-invert.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText.pngbin0 -> 140 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr-invert.pngbin0 -> 384 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr.pngbin0 -> 370 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl-invert.pngbin0 -> 395 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl.pngbin0 -> 380 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window-invert.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window.pngbin0 -> 226 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert-invert.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert.pngbin0 -> 190 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.pngbin0 -> 117 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.pngbin0 -> 118 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.pngbin0 -> 134 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.pngbin0 -> 127 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.pngbin0 -> 132 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.pngbin0 -> 126 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.pngbin0 -> 121 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.pngbin0 -> 116 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear-invert.pngbin0 -> 197 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear.pngbin0 -> 197 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required-invert.pngbin0 -> 208 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required.pngbin0 -> 201 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr-invert.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl-invert.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl.pngbin0 -> 217 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/pending.gifbin0 -> 2032 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/transparency.pngbin0 -> 113 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/transparency.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/indicators.json30
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/mediawiki/textures.json8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-accessibility.json28
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-alerts.json64
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-content.json82
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-advanced.json106
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-core.json55
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-list.json42
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-styling.json99
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-interactions.json94
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-layout.json48
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-location.json39
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-media.json48
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-moderation.json68
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-movement.json60
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-user.json39
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-wikimedia.json21
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-constructive.pngbin0 -> 133 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-constructive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-invert.pngbin0 -> 132 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-progressive.pngbin0 -> 133 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add.pngbin0 -> 129 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-invert.pngbin0 -> 368 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-progressive.pngbin0 -> 501 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced.pngbin0 -> 372 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-invert.pngbin0 -> 396 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-invert.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-progressive.pngbin0 -> 569 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-progressive.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-warning.pngbin0 -> 532 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-warning.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert.pngbin0 -> 388 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-invert.pngbin0 -> 145 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-progressive.pngbin0 -> 145 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-invert.pngbin0 -> 159 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-progressive.pngbin0 -> 159 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left.pngbin0 -> 155 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-invert.pngbin0 -> 173 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-progressive.pngbin0 -> 173 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right.pngbin0 -> 162 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-invert.pngbin0 -> 287 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-progressive.pngbin0 -> 373 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-invert.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-progressive.pngbin0 -> 371 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl.pngbin0 -> 267 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-invert.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-progressive.pngbin0 -> 215 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-invert.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-progressive.pngbin0 -> 212 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-invert.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-progressive.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-invert.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-progressive.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl.pngbin0 -> 174 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-invert.pngbin0 -> 297 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-progressive.pngbin0 -> 355 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr.pngbin0 -> 287 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-invert.pngbin0 -> 292 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-progressive.pngbin0 -> 354 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl.pngbin0 -> 279 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-invert.pngbin0 -> 360 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-progressive.pngbin0 -> 439 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr.pngbin0 -> 330 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-invert.pngbin0 -> 356 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-progressive.pngbin0 -> 443 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl.pngbin0 -> 331 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-invert.pngbin0 -> 349 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-progressive.pngbin0 -> 405 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr.pngbin0 -> 331 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-invert.pngbin0 -> 368 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-progressive.pngbin0 -> 483 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl.pngbin0 -> 347 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-invert.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-progressive.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-invert.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-progressive.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-invert.pngbin0 -> 380 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-progressive.pngbin0 -> 590 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr.pngbin0 -> 367 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-invert.pngbin0 -> 387 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-progressive.pngbin0 -> 545 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl.pngbin0 -> 366 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-invert.pngbin0 -> 237 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-progressive.pngbin0 -> 306 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell.pngbin0 -> 235 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-invert.pngbin0 -> 372 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-progressive.pngbin0 -> 512 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr.pngbin0 -> 345 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-invert.pngbin0 -> 381 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-progressive.pngbin0 -> 509 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl.pngbin0 -> 367 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-invert.pngbin0 -> 371 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-progressive.pngbin0 -> 536 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr.pngbin0 -> 349 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-invert.pngbin0 -> 357 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-progressive.pngbin0 -> 549 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl.pngbin0 -> 348 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-destructive.pngbin0 -> 276 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-invert.pngbin0 -> 267 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-progressive.pngbin0 -> 276 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block.pngbin0 -> 258 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-invert.pngbin0 -> 265 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-progressive.pngbin0 -> 312 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a.pngbin0 -> 257 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-invert.pngbin0 -> 272 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-progressive.pngbin0 -> 369 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain.pngbin0 -> 260 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-invert.pngbin0 -> 308 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-progressive.pngbin0 -> 427 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad.pngbin0 -> 297 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-invert.pngbin0 -> 335 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-progressive.pngbin0 -> 462 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to.pngbin0 -> 325 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-invert.pngbin0 -> 223 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-progressive.pngbin0 -> 263 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-invert.pngbin0 -> 208 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-progressive.pngbin0 -> 255 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-invert.pngbin0 -> 134 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-progressive.pngbin0 -> 134 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te.pngbin0 -> 129 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-invert.pngbin0 -> 319 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-progressive.pngbin0 -> 419 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe.pngbin0 -> 320 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-invert.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-progressive.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f.pngbin0 -> 134 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-invert.pngbin0 -> 318 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-progressive.pngbin0 -> 435 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g.pngbin0 -> 304 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-invert.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-progressive.pngbin0 -> 380 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man.pngbin0 -> 279 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-invert.pngbin0 -> 130 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-progressive.pngbin0 -> 130 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l.pngbin0 -> 127 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-invert.pngbin0 -> 160 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-progressive.pngbin0 -> 173 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n.pngbin0 -> 160 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-invert.pngbin0 -> 245 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-progressive.pngbin0 -> 245 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v.pngbin0 -> 240 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-invert.pngbin0 -> 226 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-progressive.pngbin0 -> 242 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr.pngbin0 -> 200 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-invert.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-progressive.pngbin0 -> 243 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl.pngbin0 -> 210 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright-invert.pngbin0 -> 372 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright.pngbin0 -> 368 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-invert.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-progressive.pngbin0 -> 213 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr.pngbin0 -> 186 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-invert.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-progressive.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-invert.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-progressive.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr.pngbin0 -> 187 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-invert.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-progressive.pngbin0 -> 216 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-destructive.pngbin0 -> 434 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-destructive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-invert.pngbin0 -> 329 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-progressive.pngbin0 -> 434 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel.pngbin0 -> 325 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-invert.pngbin0 -> 384 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-progressive.pngbin0 -> 536 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive.pngbin0 -> 353 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-constructive.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-constructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-destructive.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-invert.pngbin0 -> 170 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-progressive.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check.pngbin0 -> 167 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-invert.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-progressive.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-invert.pngbin0 -> 197 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-progressive.pngbin0 -> 197 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl.pngbin0 -> 197 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-invert.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-progressive.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-invert.pngbin0 -> 298 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-progressive.pngbin0 -> 344 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip.pngbin0 -> 279 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-invert.pngbin0 -> 295 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-progressive.pngbin0 -> 330 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock.pngbin0 -> 293 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-invert.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-progressive.pngbin0 -> 268 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close.pngbin0 -> 226 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-invert.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-progressive.pngbin0 -> 330 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code.pngbin0 -> 272 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-invert.pngbin0 -> 176 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-progressive.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-progressive.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment.pngbin0 -> 183 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-invert.pngbin0 -> 313 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-progressive.pngbin0 -> 413 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-invert.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-progressive.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-invert.pngbin0 -> 217 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-progressive.pngbin0 -> 217 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl.pngbin0 -> 194 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-invert.pngbin0 -> 189 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-progressive.pngbin0 -> 226 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-invert.pngbin0 -> 235 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-progressive.pngbin0 -> 278 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr.pngbin0 -> 232 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-invert.pngbin0 -> 238 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-progressive.pngbin0 -> 278 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-invert.pngbin0 -> 115 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-progressive.pngbin0 -> 115 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable.pngbin0 -> 115 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-invert.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-progressive.pngbin0 -> 456 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-invert.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-progressive.pngbin0 -> 422 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl.pngbin0 -> 267 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-invert.pngbin0 -> 314 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-progressive.pngbin0 -> 416 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-invert.pngbin0 -> 319 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-progressive.pngbin0 -> 400 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl.pngbin0 -> 302 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-invert.pngbin0 -> 374 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-progressive.pngbin0 -> 540 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr.pngbin0 -> 361 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-invert.pngbin0 -> 380 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-progressive.pngbin0 -> 543 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl.pngbin0 -> 371 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-invert.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-progressive.pngbin0 -> 156 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis.pngbin0 -> 144 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-invert.pngbin0 -> 182 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-progressive.pngbin0 -> 204 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-invert.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-progressive.pngbin0 -> 214 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr.pngbin0 -> 206 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-invert.pngbin0 -> 210 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-progressive.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl.pngbin0 -> 203 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-invert.pngbin0 -> 333 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-progressive.pngbin0 -> 391 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye.pngbin0 -> 311 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-invert.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-progressive.pngbin0 -> 449 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed.pngbin0 -> 296 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-invert.pngbin0 -> 284 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-progressive.pngbin0 -> 373 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr.pngbin0 -> 294 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-invert.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-progressive.pngbin0 -> 376 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-invert.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-progressive.pngbin0 -> 387 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-invert.pngbin0 -> 302 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-progressive.pngbin0 -> 390 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-invert.pngbin0 -> 231 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-progressive.pngbin0 -> 252 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr.pngbin0 -> 214 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-invert.pngbin0 -> 258 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-progressive.pngbin0 -> 296 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-invert.pngbin0 -> 159 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-progressive.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr.pngbin0 -> 147 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-invert.pngbin0 -> 163 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-progressive.pngbin0 -> 175 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl.pngbin0 -> 151 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-invert.pngbin0 -> 227 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-progressive.pngbin0 -> 237 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-invert.pngbin0 -> 221 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-progressive.pngbin0 -> 275 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr.pngbin0 -> 216 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-invert.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-progressive.pngbin0 -> 275 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl.pngbin0 -> 217 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright-invert.pngbin0 -> 310 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright.pngbin0 -> 319 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-constructive.pngbin0 -> 638 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-constructive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-invert.pngbin0 -> 424 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-progressive.pngbin0 -> 638 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr.pngbin0 -> 429 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-constructive.pngbin0 -> 663 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-constructive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-invert.pngbin0 -> 430 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-progressive.pngbin0 -> 663 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl.pngbin0 -> 419 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-invert.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-progressive.pngbin0 -> 322 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart.pngbin0 -> 250 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-invert.pngbin0 -> 503 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-invert.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-progressive.pngbin0 -> 578 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-progressive.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr.pngbin0 -> 483 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-invert.pngbin0 -> 515 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-invert.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-progressive.pngbin0 -> 611 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-progressive.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl.pngbin0 -> 494 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-invert.pngbin0 -> 333 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-progressive.pngbin0 -> 445 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr.pngbin0 -> 328 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-invert.pngbin0 -> 345 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-progressive.pngbin0 -> 488 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl.pngbin0 -> 333 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-invert.pngbin0 -> 557 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-progressive.pngbin0 -> 737 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history.pngbin0 -> 524 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-invert.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-progressive.pngbin0 -> 212 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr.pngbin0 -> 183 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-invert.pngbin0 -> 187 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-progressive.pngbin0 -> 212 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-invert.pngbin0 -> 232 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-progressive.pngbin0 -> 238 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr.pngbin0 -> 226 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-invert.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-progressive.pngbin0 -> 239 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl.pngbin0 -> 215 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-invert.pngbin0 -> 213 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-progressive.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-invert.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-progressive.pngbin0 -> 234 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl.pngbin0 -> 201 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-invert.pngbin0 -> 266 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-progressive.pngbin0 -> 292 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr.pngbin0 -> 256 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-invert.pngbin0 -> 268 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-progressive.pngbin0 -> 292 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl.pngbin0 -> 256 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-progressive.pngbin0 -> 220 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-invert.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-progressive.pngbin0 -> 223 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-invert.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-progressive.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-invert.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-progressive.pngbin0 -> 361 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-invert.pngbin0 -> 339 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-progressive.pngbin0 -> 437 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem.pngbin0 -> 317 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-invert.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-progressive.pngbin0 -> 326 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem.pngbin0 -> 240 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-invert.pngbin0 -> 322 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-progressive.pngbin0 -> 484 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha.pngbin0 -> 324 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-invert.pngbin0 -> 289 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-progressive.pngbin0 -> 436 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c.pngbin0 -> 282 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-invert.pngbin0 -> 335 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-progressive.pngbin0 -> 419 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d.pngbin0 -> 314 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-invert.pngbin0 -> 247 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-progressive.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e.pngbin0 -> 240 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-invert.pngbin0 -> 288 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-progressive.pngbin0 -> 388 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan.pngbin0 -> 275 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-invert.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-progressive.pngbin0 -> 231 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-invert.pngbin0 -> 284 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-progressive.pngbin0 -> 360 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k.pngbin0 -> 268 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-invert.pngbin0 -> 323 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-progressive.pngbin0 -> 407 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s.pngbin0 -> 305 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-invert.pngbin0 -> 168 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-progressive.pngbin0 -> 168 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr.pngbin0 -> 168 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-invert.pngbin0 -> 169 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-progressive.pngbin0 -> 169 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl.pngbin0 -> 169 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-invert.pngbin0 -> 270 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-progressive.pngbin0 -> 303 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr.pngbin0 -> 255 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-invert.pngbin0 -> 273 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-progressive.pngbin0 -> 294 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-invert.pngbin0 -> 170 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-progressive.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr.pngbin0 -> 164 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-invert.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-progressive.pngbin0 -> 187 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-invert.pngbin0 -> 480 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-invert.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-progressive.pngbin0 -> 688 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-progressive.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr.pngbin0 -> 455 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-invert.pngbin0 -> 469 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-invert.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-progressive.pngbin0 -> 682 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-progressive.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl.pngbin0 -> 448 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr-invert.pngbin0 -> 345 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr.pngbin0 -> 336 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl-invert.pngbin0 -> 354 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl.pngbin0 -> 340 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-invert.pngbin0 -> 157 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-progressive.pngbin0 -> 157 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr.pngbin0 -> 150 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-invert.pngbin0 -> 154 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-progressive.pngbin0 -> 156 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl.pngbin0 -> 147 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-invert.pngbin0 -> 444 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-progressive.pngbin0 -> 625 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr.pngbin0 -> 412 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-invert.pngbin0 -> 434 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-progressive.pngbin0 -> 663 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl.pngbin0 -> 429 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-invert.pngbin0 -> 155 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-progressive.pngbin0 -> 155 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr.pngbin0 -> 145 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-invert.pngbin0 -> 144 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-progressive.pngbin0 -> 155 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl.pngbin0 -> 141 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-invert.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-progressive.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-invert.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-progressive.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-destructive.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-invert.pngbin0 -> 228 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-progressive.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr.pngbin0 -> 224 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-destructive.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-invert.pngbin0 -> 228 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-progressive.pngbin0 -> 289 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl.pngbin0 -> 227 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-invert.pngbin0 -> 214 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-progressive.pngbin0 -> 232 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr.pngbin0 -> 201 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-invert.pngbin0 -> 236 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-progressive.pngbin0 -> 239 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-invert.pngbin0 -> 338 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-progressive.pngbin0 -> 374 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc.pngbin0 -> 319 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-invert.pngbin0 -> 525 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-progressive.pngbin0 -> 621 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons.pngbin0 -> 484 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-invert.pngbin0 -> 288 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-progressive.pngbin0 -> 377 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-invert.pngbin0 -> 445 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-progressive.pngbin0 -> 638 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia.pngbin0 -> 428 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-invert.pngbin0 -> 292 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-progressive.pngbin0 -> 320 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr.pngbin0 -> 251 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-invert.pngbin0 -> 309 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-progressive.pngbin0 -> 331 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-invert.pngbin0 -> 330 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-progressive.pngbin0 -> 378 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin.pngbin0 -> 325 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-invert.pngbin0 -> 357 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-progressive.pngbin0 -> 383 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr.pngbin0 -> 337 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-invert.pngbin0 -> 360 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-progressive.pngbin0 -> 397 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl.pngbin0 -> 346 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-invert.pngbin0 -> 384 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-progressive.pngbin0 -> 481 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr.pngbin0 -> 370 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-invert.pngbin0 -> 395 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-progressive.pngbin0 -> 582 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl.pngbin0 -> 380 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-invert.pngbin0 -> 256 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-progressive.pngbin0 -> 321 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup.pngbin0 -> 251 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-invert.pngbin0 -> 160 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-progressive.pngbin0 -> 182 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu.pngbin0 -> 158 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-invert.pngbin0 -> 288 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-progressive.pngbin0 -> 320 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr.pngbin0 -> 268 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-invert.pngbin0 -> 288 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-progressive.pngbin0 -> 310 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl.pngbin0 -> 272 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon-invert.pngbin0 -> 318 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon.pngbin0 -> 326 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-invert.pngbin0 -> 216 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-progressive.pngbin0 -> 278 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr.pngbin0 -> 204 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-invert.pngbin0 -> 220 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-invert.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-progressive.pngbin0 -> 277 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-progressive.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl.pngbin0 -> 221 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-invert.pngbin0 -> 228 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-invert.pngbin0 -> 179 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-progressive.pngbin0 -> 258 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr.pngbin0 -> 179 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-progressive.pngbin0 -> 254 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-progressive.pngbin0 -> 261 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-invert.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-progressive.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr.pngbin0 -> 194 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-invert.pngbin0 -> 208 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-progressive.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl.pngbin0 -> 204 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-invert.pngbin0 -> 255 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-progressive.pngbin0 -> 302 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr.pngbin0 -> 248 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-invert.pngbin0 -> 258 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-progressive.pngbin0 -> 309 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl.pngbin0 -> 263 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-invert.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-progressive.pngbin0 -> 184 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr.pngbin0 -> 172 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-invert.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-progressive.pngbin0 -> 184 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl.pngbin0 -> 173 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-invert.pngbin0 -> 212 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-progressive.pngbin0 -> 212 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr.pngbin0 -> 212 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-invert.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-progressive.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright-invert.pngbin0 -> 263 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright.pngbin0 -> 249 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-invert.pngbin0 -> 210 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-progressive.pngbin0 -> 231 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-invert.pngbin0 -> 223 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-progressive.pngbin0 -> 280 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-invert.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-progressive.pngbin0 -> 270 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl.pngbin0 -> 210 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-invert.pngbin0 -> 186 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-progressive.pngbin0 -> 218 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr.pngbin0 -> 174 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-progressive.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl.pngbin0 -> 177 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-invert.pngbin0 -> 147 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-progressive.pngbin0 -> 147 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-invert.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-progressive.pngbin0 -> 147 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-invert.pngbin0 -> 275 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-progressive.pngbin0 -> 304 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr.pngbin0 -> 261 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-invert.pngbin0 -> 275 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-progressive.pngbin0 -> 304 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl.pngbin0 -> 258 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-invert.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-progressive.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-invert.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-progressive.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-invert.pngbin0 -> 266 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-progressive.pngbin0 -> 312 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin.pngbin0 -> 254 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-invert.pngbin0 -> 322 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-progressive.pngbin0 -> 421 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle.pngbin0 -> 310 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-invert.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-progressive.pngbin0 -> 303 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-invert.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-progressive.pngbin0 -> 302 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-invert.pngbin0 -> 279 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-invert.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-progressive.pngbin0 -> 365 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-progressive.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-invert.pngbin0 -> 281 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-invert.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-progressive.pngbin0 -> 356 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-progressive.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl.svg8
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-invert.pngbin0 -> 344 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-invert.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-progressive.pngbin0 -> 498 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-progressive.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression.pngbin0 -> 325 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-invert.pngbin0 -> 334 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-progressive.pngbin0 -> 452 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr.pngbin0 -> 358 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-invert.pngbin0 -> 332 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-progressive.pngbin0 -> 456 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl.pngbin0 -> 331 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-invert.pngbin0 -> 180 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-progressive.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-invert.pngbin0 -> 175 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-progressive.pngbin0 -> 186 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-invert.pngbin0 -> 452 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-progressive.pngbin0 -> 572 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr.pngbin0 -> 409 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-invert.pngbin0 -> 460 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-progressive.pngbin0 -> 591 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl.pngbin0 -> 425 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-invert.pngbin0 -> 359 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-progressive.pngbin0 -> 539 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr.pngbin0 -> 352 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-invert.pngbin0 -> 371 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-progressive.pngbin0 -> 537 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl.pngbin0 -> 350 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr-invert.pngbin0 -> 276 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl-invert.pngbin0 -> 261 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl.pngbin0 -> 261 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-invert.pngbin0 -> 350 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-progressive.pngbin0 -> 452 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter.pngbin0 -> 323 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-invert.pngbin0 -> 152 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-progressive.pngbin0 -> 170 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr.pngbin0 -> 142 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-invert.pngbin0 -> 153 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-progressive.pngbin0 -> 166 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl.pngbin0 -> 164 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-invert.pngbin0 -> 183 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-progressive.pngbin0 -> 183 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr.pngbin0 -> 177 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-invert.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-progressive.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl.pngbin0 -> 191 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-invert.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-progressive.pngbin0 -> 176 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr.pngbin0 -> 163 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-invert.pngbin0 -> 172 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-progressive.pngbin0 -> 172 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl.pngbin0 -> 168 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-constructive.pngbin0 -> 617 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-constructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-invert.pngbin0 -> 416 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-progressive.pngbin0 -> 617 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star.pngbin0 -> 415 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-invert.pngbin0 -> 281 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-progressive.pngbin0 -> 301 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-invert.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-progressive.pngbin0 -> 383 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a.pngbin0 -> 280 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-invert.pngbin0 -> 298 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-progressive.pngbin0 -> 409 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s.pngbin0 -> 302 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-invert.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-progressive.pngbin0 -> 247 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y.pngbin0 -> 207 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-invert.pngbin0 -> 139 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-progressive.pngbin0 -> 139 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-invert.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-progressive.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl.pngbin0 -> 140 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-invert.pngbin0 -> 123 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-progressive.pngbin0 -> 123 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr.pngbin0 -> 123 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-invert.pngbin0 -> 124 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-progressive.pngbin0 -> 124 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl.pngbin0 -> 124 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-invert.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-progressive.pngbin0 -> 144 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-invert.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-progressive.pngbin0 -> 144 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl.pngbin0 -> 135 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-invert.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-progressive.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr.pngbin0 -> 224 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-invert.pngbin0 -> 221 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-progressive.pngbin0 -> 287 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-invert.pngbin0 -> 116 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-progressive.pngbin0 -> 116 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract.pngbin0 -> 115 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-invert.pngbin0 -> 374 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-progressive.pngbin0 -> 392 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr.pngbin0 -> 361 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-invert.pngbin0 -> 359 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-progressive.pngbin0 -> 381 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl.pngbin0 -> 336 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-invert.pngbin0 -> 228 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-progressive.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr.pngbin0 -> 220 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-invert.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-invert.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-progressive.pngbin0 -> 287 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-progressive.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl.svg5
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-invert.pngbin0 -> 148 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-progressive.pngbin0 -> 148 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-invert.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-progressive.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr.pngbin0 -> 137 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-invert.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-progressive.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl.pngbin0 -> 138 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-invert.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-progressive.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-invert.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-progressive.pngbin0 -> 136 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before.pngbin0 -> 135 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-invert.pngbin0 -> 142 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-invert.pngbin0 -> 208 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-invert.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-progressive.pngbin0 -> 209 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-progressive.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells.pngbin0 -> 204 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells.svg10
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-progressive.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-progressive.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table.pngbin0 -> 135 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-constructive.pngbin0 -> 327 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-constructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-destructive.pngbin0 -> 327 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-invert.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-progressive.pngbin0 -> 327 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-warning.pngbin0 -> 327 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-warning.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-progressive.pngbin0 -> 196 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr.pngbin0 -> 178 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-invert.pngbin0 -> 194 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-progressive.pngbin0 -> 194 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl.pngbin0 -> 188 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-invert.pngbin0 -> 213 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-progressive.pngbin0 -> 250 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright.pngbin0 -> 210 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-invert.pngbin0 -> 218 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-progressive.pngbin0 -> 255 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft.pngbin0 -> 215 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-invert.pngbin0 -> 296 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-progressive.pngbin0 -> 393 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style.pngbin0 -> 293 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-destructive.pngbin0 -> 262 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-invert.pngbin0 -> 179 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-progressive.pngbin0 -> 277 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash.pngbin0 -> 171 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-invert.pngbin0 -> 359 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-progressive.pngbin0 -> 365 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray.pngbin0 -> 342 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-invert.pngbin0 -> 292 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-progressive.pngbin0 -> 326 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-invert.pngbin0 -> 287 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-progressive.pngbin0 -> 330 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl.pngbin0 -> 289 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-invert.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-progressive.pngbin0 -> 251 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-invert.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-progressive.pngbin0 -> 380 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr.pngbin0 -> 271 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-invert.pngbin0 -> 335 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-progressive.pngbin0 -> 414 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl.pngbin0 -> 313 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-destructive.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-invert.pngbin0 -> 234 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-progressive.pngbin0 -> 300 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-destructive.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-destructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-invert.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-progressive.pngbin0 -> 283 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-constructive.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-constructive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-invert.pngbin0 -> 253 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-progressive.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar.pngbin0 -> 246 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-invert.pngbin0 -> 252 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-progressive.pngbin0 -> 298 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr.pngbin0 -> 236 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-invert.pngbin0 -> 269 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-progressive.pngbin0 -> 327 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl.pngbin0 -> 263 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-invert.pngbin0 -> 291 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-progressive.pngbin0 -> 355 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a.pngbin0 -> 278 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-invert.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-progressive.pngbin0 -> 228 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u.pngbin0 -> 192 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-invert.pngbin0 -> 185 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-progressive.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle.pngbin0 -> 187 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-invert.pngbin0 -> 235 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-progressive.pngbin0 -> 290 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr.pngbin0 -> 234 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-invert.pngbin0 -> 233 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-progressive.pngbin0 -> 285 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl.pngbin0 -> 237 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-invert.pngbin0 -> 326 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-progressive.pngbin0 -> 379 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr.pngbin0 -> 305 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-invert.pngbin0 -> 315 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-progressive.pngbin0 -> 366 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl.pngbin0 -> 293 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-invert.pngbin0 -> 332 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-progressive.pngbin0 -> 425 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar.pngbin0 -> 318 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-invert.pngbin0 -> 277 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-progressive.pngbin0 -> 312 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr.pngbin0 -> 258 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-invert.pngbin0 -> 274 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-progressive.pngbin0 -> 312 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl.pngbin0 -> 256 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-invert.pngbin0 -> 307 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-progressive.pngbin0 -> 400 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr.pngbin0 -> 292 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-invert.pngbin0 -> 307 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-progressive.pngbin0 -> 401 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl.pngbin0 -> 310 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-invert.pngbin0 -> 145 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-invert.svg14
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-progressive.pngbin0 -> 172 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-progressive.svg14
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact.pngbin0 -> 146 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact.svg14
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-invert.pngbin0 -> 166 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-invert.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-progressive.pngbin0 -> 166 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-progressive.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr.pngbin0 -> 165 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-invert.pngbin0 -> 165 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-invert.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-progressive.pngbin0 -> 165 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-progressive.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl.pngbin0 -> 165 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator-invert.pngbin0 -> 205 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator.pngbin0 -> 202 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-invert.pngbin0 -> 294 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-progressive.pngbin0 -> 333 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr.pngbin0 -> 280 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-invert.pngbin0 -> 286 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-progressive.pngbin0 -> 363 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-progressive.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl.pngbin0 -> 266 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-invert.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-invert.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-progressive.pngbin0 -> 143 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-progressive.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText.pngbin0 -> 140 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText.svg9
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-invert.pngbin0 -> 229 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-invert.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-progressive.pngbin0 -> 236 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-progressive.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window.pngbin0 -> 226 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert-invert.pngbin0 -> 198 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert.pngbin0 -> 190 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down-invert.pngbin0 -> 174 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr-invert.pngbin0 -> 163 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr.pngbin0 -> 158 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl-invert.pngbin0 -> 160 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl.pngbin0 -> 163 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up-invert.pngbin0 -> 195 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up.pngbin0 -> 181 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear-invert.pngbin0 -> 197 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear.pngbin0 -> 197 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required-invert.pngbin0 -> 208 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required-invert.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required.pngbin0 -> 201 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required.svg4
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr-invert.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl-invert.pngbin0 -> 225 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl-invert.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl.pngbin0 -> 217 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl.svg6
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/pending.gifbin0 -> 2032 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/transparency.pngbin0 -> 113 bytes
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/transparency.svg7
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/indicators.json30
-rw-r--r--www/wiki/resources/lib/oojs-ui/themes/wikimediaui/textures.json8
-rw-r--r--www/wiki/resources/lib/oojs-ui/wikimedia-ui-base.less153
-rw-r--r--www/wiki/resources/lib/oojs/AUTHORS.txt10
-rw-r--r--www/wiki/resources/lib/oojs/LICENSE-MIT20
-rw-r--r--www/wiki/resources/lib/oojs/README.md98
-rw-r--r--www/wiki/resources/lib/oojs/oojs.jquery.js1610
-rw-r--r--www/wiki/resources/lib/phpjs-sha1/LICENSE.txt20
-rw-r--r--www/wiki/resources/lib/phpjs-sha1/sha1.js147
-rw-r--r--www/wiki/resources/lib/qunitjs/qunit.css436
-rw-r--r--www/wiki/resources/lib/qunitjs/qunit.js5048
-rw-r--r--www/wiki/resources/lib/sinonjs/sinon-1.17.3.js6437
-rw-r--r--www/wiki/resources/src/dom-level2-skip.js6
-rw-r--r--www/wiki/resources/src/es5-skip.js18
-rw-r--r--www/wiki/resources/src/jquery.tipsy/images/tipsy.pngbin0 -> 133 bytes
-rw-r--r--www/wiki/resources/src/jquery.tipsy/jquery.tipsy.css73
-rw-r--r--www/wiki/resources/src/jquery.tipsy/jquery.tipsy.js281
-rw-r--r--www/wiki/resources/src/jquery/images/jquery.arrowSteps.divider-ltr.pngbin0 -> 126 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/jquery.arrowSteps.divider-rtl.pngbin0 -> 126 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/jquery.arrowSteps.head-ltr.pngbin0 -> 301 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/jquery.arrowSteps.head-rtl.pngbin0 -> 297 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/jquery.arrowSteps.tail-ltr.pngbin0 -> 222 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/jquery.arrowSteps.tail-rtl.pngbin0 -> 219 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/marker.pngbin0 -> 471 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/mask.pngbin0 -> 1779 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/sort_both.pngbin0 -> 116 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/sort_both.svg4
-rw-r--r--www/wiki/resources/src/jquery/images/sort_down.pngbin0 -> 100 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/sort_down.svg4
-rw-r--r--www/wiki/resources/src/jquery/images/sort_up.pngbin0 -> 98 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/sort_up.svg4
-rw-r--r--www/wiki/resources/src/jquery/images/spinner-large.gifbin0 -> 1788 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/spinner.gifbin0 -> 1819 bytes
-rw-r--r--www/wiki/resources/src/jquery/images/wheel.pngbin0 -> 10733 bytes
-rw-r--r--www/wiki/resources/src/jquery/jquery.accessKeyLabel.js238
-rw-r--r--www/wiki/resources/src/jquery/jquery.arrowSteps.css45
-rw-r--r--www/wiki/resources/src/jquery/jquery.arrowSteps.js98
-rw-r--r--www/wiki/resources/src/jquery/jquery.autoEllipsis.js171
-rw-r--r--www/wiki/resources/src/jquery/jquery.badge.css36
-rw-r--r--www/wiki/resources/src/jquery/jquery.badge.js88
-rw-r--r--www/wiki/resources/src/jquery/jquery.byteLength.js40
-rw-r--r--www/wiki/resources/src/jquery/jquery.byteLimit.js238
-rw-r--r--www/wiki/resources/src/jquery/jquery.checkboxShiftClick.js43
-rw-r--r--www/wiki/resources/src/jquery/jquery.color.js55
-rw-r--r--www/wiki/resources/src/jquery/jquery.colorUtil.js265
-rw-r--r--www/wiki/resources/src/jquery/jquery.confirmable.css28
-rw-r--r--www/wiki/resources/src/jquery/jquery.confirmable.js183
-rw-r--r--www/wiki/resources/src/jquery/jquery.confirmable.mediawiki.js16
-rw-r--r--www/wiki/resources/src/jquery/jquery.expandableField.js147
-rw-r--r--www/wiki/resources/src/jquery/jquery.farbtastic.css55
-rw-r--r--www/wiki/resources/src/jquery/jquery.farbtastic.js286
-rw-r--r--www/wiki/resources/src/jquery/jquery.footHovzer.css6
-rw-r--r--www/wiki/resources/src/jquery/jquery.footHovzer.js66
-rw-r--r--www/wiki/resources/src/jquery/jquery.getAttrs.js37
-rw-r--r--www/wiki/resources/src/jquery/jquery.hidpi.js177
-rw-r--r--www/wiki/resources/src/jquery/jquery.highlightText.js97
-rw-r--r--www/wiki/resources/src/jquery/jquery.localize.js170
-rw-r--r--www/wiki/resources/src/jquery/jquery.makeCollapsible.css47
-rw-r--r--www/wiki/resources/src/jquery/jquery.makeCollapsible.js424
-rw-r--r--www/wiki/resources/src/jquery/jquery.mw-jump.js15
-rw-r--r--www/wiki/resources/src/jquery/jquery.mwExtension.js127
-rw-r--r--www/wiki/resources/src/jquery/jquery.placeholder.js18
-rw-r--r--www/wiki/resources/src/jquery/jquery.qunit.completenessTest.js309
-rw-r--r--www/wiki/resources/src/jquery/jquery.spinner.css40
-rw-r--r--www/wiki/resources/src/jquery/jquery.spinner.js114
-rw-r--r--www/wiki/resources/src/jquery/jquery.suggestions.css75
-rw-r--r--www/wiki/resources/src/jquery/jquery.suggestions.js787
-rw-r--r--www/wiki/resources/src/jquery/jquery.tabIndex.js57
-rw-r--r--www/wiki/resources/src/jquery/jquery.tablesorter.js1278
-rw-r--r--www/wiki/resources/src/jquery/jquery.tablesorter.less19
-rw-r--r--www/wiki/resources/src/jquery/jquery.textSelection.js610
-rw-r--r--www/wiki/resources/src/json-skip.js4
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/checker.pngbin0 -> 81 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/close.pngbin0 -> 168 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/close.svg5
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/green-checkmark.pngbin0 -> 557 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/nextredirect-ltr.pngbin0 -> 118 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/nextredirect-ltr.svg9
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/nextredirect-rtl.pngbin0 -> 115 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/nextredirect-rtl.svg9
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/redirect-ltr.pngbin0 -> 164 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/redirect-ltr.svg9
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/redirect-rtl.pngbin0 -> 139 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.action/images/redirect-rtl.svg9
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css17
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js66
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.css15
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js42
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.js45
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.preview.js334
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.stash.js164
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.styles.css36
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.styles.less56
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.history.css6
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.history.diff.css95
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.history.diff.print.css16
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.history.js111
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.history.styles.css23
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.categoryPage.less15
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.dblClickEdit.js20
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.filepage.css113
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.filepage.print.css8
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.metadata.css22
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.metadata.js52
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.css76
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.js78
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.less59
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.monobook.css3
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.redirect.js65
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.redirectPage.css59
-rw-r--r--www/wiki/resources/src/mediawiki.action/mediawiki.action.view.rightClickEdit.js26
-rw-r--r--www/wiki/resources/src/mediawiki.action/templates/postEdit.html6
-rw-r--r--www/wiki/resources/src/mediawiki.hidpi-skip.js4
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/bs.js19
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/dsb.js19
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/fi.js47
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/ga.js37
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/he.js29
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/hsb.js19
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/hu.js23
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/hy.js28
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/la.js50
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/os.js67
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/ru.js83
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/sl.js19
-rw-r--r--www/wiki/resources/src/mediawiki.language/languages/uk.js32
-rw-r--r--www/wiki/resources/src/mediawiki.language/mediawiki.cldr.js32
-rw-r--r--www/wiki/resources/src/mediawiki.language/mediawiki.language.fallback.js35
-rw-r--r--www/wiki/resources/src/mediawiki.language/mediawiki.language.init.js83
-rw-r--r--www/wiki/resources/src/mediawiki.language/mediawiki.language.js233
-rw-r--r--www/wiki/resources/src/mediawiki.language/mediawiki.language.months.js56
-rw-r--r--www/wiki/resources/src/mediawiki.language/mediawiki.language.numbers.js301
-rw-r--r--www/wiki/resources/src/mediawiki.language/specialcharacters.json510
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/commonPrint.css373
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/images/ajax-loader.gifbin0 -> 1788 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/images/help-question-hover.gifbin0 -> 1246 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/images/help-question.gifbin0 -> 126 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-ltr.pngbin0 -> 211 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-ltr.svg7
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-rtl.pngbin0 -> 215 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-rtl.svg7
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/images/spinner.gifbin0 -> 1819 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/oldshared.css462
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/protect.js245
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/shared.css806
-rw-r--r--www/wiki/resources/src/mediawiki.legacy/wikibits.js105
-rw-r--r--www/wiki/resources/src/mediawiki.less/mediawiki.mixins.animation.less11
-rw-r--r--www/wiki/resources/src/mediawiki.less/mediawiki.mixins.less192
-rw-r--r--www/wiki/resources/src/mediawiki.less/mediawiki.mixins.rotation.less29
-rw-r--r--www/wiki/resources/src/mediawiki.less/mediawiki.ui/mixins.less149
-rw-r--r--www/wiki/resources/src/mediawiki.less/mediawiki.ui/variables.less85
-rw-r--r--www/wiki/resources/src/mediawiki.libs/CLDRPluralRuleParser.js596
-rw-r--r--www/wiki/resources/src/mediawiki.libs/mediawiki.libs.jpegmeta.js737
-rw-r--r--www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.MessagePoster.js40
-rw-r--r--www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.WikitextMessagePoster.js53
-rw-r--r--www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.factory.js107
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js160
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js892
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js372
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js1118
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ItemModel.js298
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueriesModel.js282
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueryItemModel.js116
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/images/clip.svg4
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/images/pending.gifbin0 -> 2032 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/images/pushPin.svg4
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/images/unClip.svg4
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js1300
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.HighlightColors.js10
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.UriProcessor.js313
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js103
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.js53
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less134
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less87
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.CapsuleItemWidget.monobook.less9
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesLimitPopupWidget.less9
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.highlightCircles.seenunseen.less66
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less189
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.DatePopupWidget.less5
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemHighlightButton.less30
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuHeaderWidget.less36
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuOptionWidget.less26
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuOptionWidget.monobook.less5
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuSectionOptionWidget.less54
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterTagMultiselectWidget.less103
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less22
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.HighlightColorPickerWidget.less96
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ItemMenuOptionWidget.less71
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.LiveUpdateButtonWidget.less40
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less38
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.Overlay.less8
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.Overlay.monobook.less3
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.RcTopSectionWidget.less44
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SaveFiltersPopupButtonWidget.less39
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SavedLinksListItemWidget.less58
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SavedLinksListWidget.less28
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.TagItemWidget.less79
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ValuePickerWidget.less7
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ViewSwitchWidget.less14
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.WatchlistTopSectionWidget.less27
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.less19
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.variables.less21
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesLimitButtonWidget.js129
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesLimitPopupWidget.js83
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js478
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CheckboxInputWidget.js63
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DateButtonWidget.js120
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DatePopupWidget.js61
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemHighlightButton.js84
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuHeaderWidget.js165
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuOptionWidget.js84
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuSectionOptionWidget.js123
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagItemWidget.js41
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js685
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js100
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js169
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.HighlightColorPickerWidget.js112
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ItemMenuOptionWidget.js144
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.LiveUpdateButtonWidget.js69
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MarkSeenButtonWidget.js55
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js359
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.RcTopSectionWidget.js109
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SaveFiltersPopupButtonWidget.js189
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SavedLinksListItemWidget.js329
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SavedLinksListWidget.js156
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.TagItemWidget.js200
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ValuePickerWidget.js110
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ViewSwitchWidget.js76
-rw-r--r--www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.WatchlistTopSectionWidget.js82
-rw-r--r--www/wiki/resources/src/mediawiki.router/index.js4
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/content.css265
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/content.externallinks.css103
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/content.parsoid.less228
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/elements.css285
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/audio-ltr.pngbin0 -> 261 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/audio-ltr.svg8
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/audio-rtl.pngbin0 -> 261 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/audio-rtl.svg8
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/chat-ltr.pngbin0 -> 164 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/chat-ltr.svg6
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/chat-rtl.pngbin0 -> 163 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/chat-rtl.svg6
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/document-ltr.pngbin0 -> 153 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/document-ltr.svg5
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/document-rtl.pngbin0 -> 153 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/document-rtl.svg5
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/external link icons.svg697
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/external-link-icons.svg697
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/external-ltr.pngbin0 -> 236 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/external-ltr.svg8
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/external-rtl.pngbin0 -> 239 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/external-rtl.svg8
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/ftp-ltr.pngbin0 -> 203 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/ftp-ltr.svg9
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/ftp-rtl.pngbin0 -> 199 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/ftp-rtl.svg9
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-ltr.pngbin0 -> 160 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-ltr.svg7
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-rtl.pngbin0 -> 161 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-rtl.svg7
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/mail.pngbin0 -> 173 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/mail.svg7
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/video.pngbin0 -> 193 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/images/video.svg14
-rw-r--r--www/wiki/resources/src/mediawiki.skinning/interface.css81
-rw-r--r--www/wiki/resources/src/mediawiki.special/images/glyph-people-large.pngbin0 -> 1652 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.special/images/icon-contributors.pngbin0 -> 1129 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.special/images/icon-edits.pngbin0 -> 742 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.special/images/icon-lock.pngbin0 -> 172 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.special/images/icon-pages.pngbin0 -> 514 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.css109
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.js1953
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.top.css3
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.block.css11
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.block.js58
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.blocklist.css4
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.changecredentials.js55
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.css41
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css65
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css33
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.js24
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.visitedstatus.js12
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less19
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.contributions.js12
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.css130
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.edittags.css15
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.edittags.js25
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.import.js37
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.js9
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.movePage.css7
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.movePage.js15
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.pageLanguage.js11
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css4
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js63
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js9
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.js321
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.styles.css47
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js165
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js92
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.recentchanges.js38
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.search.commonsInterwikiWidget.js78
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.search.css9
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.search.interwikiwidget.styles.less121
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.search.js60
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.search.styles.css166
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.undelete.js10
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.unwatchedPages.css9
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.unwatchedPages.js52
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.css10
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.js615
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.styles.css15
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.common.css75
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.login.css29
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css66
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js122
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.userrights.css12
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.userrights.js18
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.version.css26
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.watchlist.css15
-rw-r--r--www/wiki/resources/src/mediawiki.special/mediawiki.special.watchlist.js155
-rw-r--r--www/wiki/resources/src/mediawiki.special/templates/thumbnail.html8
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/ar/button_bold.pngbin0 -> 522 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/ar/button_headline.pngbin0 -> 424 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/ar/button_italic.pngbin0 -> 474 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/ar/button_link.pngbin0 -> 523 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/ar/button_nowiki.pngbin0 -> 842 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_bold.pngbin0 -> 499 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_italic.pngbin0 -> 509 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_link.pngbin0 -> 396 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/de/button_bold.pngbin0 -> 230 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/de/button_italic.pngbin0 -> 257 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/en/button_bold.pngbin0 -> 226 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/en/button_extlink.pngbin0 -> 435 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/en/button_headline.pngbin0 -> 430 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/en/button_hr.pngbin0 -> 200 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/en/button_image.pngbin0 -> 483 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/en/button_italic.pngbin0 -> 234 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/en/button_link.pngbin0 -> 275 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/en/button_media.pngbin0 -> 707 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/en/button_nowiki.pngbin0 -> 321 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/en/button_sig.pngbin0 -> 904 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/fa/button_bold.pngbin0 -> 436 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/fa/button_headline.pngbin0 -> 374 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/fa/button_italic.pngbin0 -> 485 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/fa/button_link.pngbin0 -> 444 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/fa/button_nowiki.pngbin0 -> 842 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/ksh/LICENSE7
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/ksh/button_italic.pngbin0 -> 357 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/ru/LICENSE17
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/ru/button_bold.pngbin0 -> 242 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/ru/button_italic.pngbin0 -> 396 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/images/ru/button_link.pngbin0 -> 270 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/toolbar.js208
-rw-r--r--www/wiki/resources/src/mediawiki.toolbar/toolbar.less42
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/anchors.less75
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/buttons.less269
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/checkbox.less156
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/forms.less173
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/icons.less107
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/images/checkbox-checked.pngbin0 -> 170 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/images/checkbox-checked.svg4
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/images/checked.pngbin0 -> 320 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/images/checked.svg1
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/images/checked_disabled.pngbin0 -> 260 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/images/checked_disabled.svg1
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/images/radio_checked.pngbin0 -> 210 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/images/radio_checked.svg1
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/images/radio_disabled.pngbin0 -> 176 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/images/radio_disabled.svg1
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/inputs.less147
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/radio.less150
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/text.less36
-rw-r--r--www/wiki/resources/src/mediawiki.ui/components/utilities.less47
-rw-r--r--www/wiki/resources/src/mediawiki.ui/default.less5
-rw-r--r--www/wiki/resources/src/mediawiki.ui/styleguide.md11
-rw-r--r--www/wiki/resources/src/mediawiki.widgets.datetime/CalendarWidget.js596
-rw-r--r--www/wiki/resources/src/mediawiki.widgets.datetime/CalendarWidget.less75
-rw-r--r--www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeFormatter.js627
-rw-r--r--www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js837
-rw-r--r--www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.less155
-rw-r--r--www/wiki/resources/src/mediawiki.widgets.datetime/DiscordianDateTimeFormatter.js569
-rw-r--r--www/wiki/resources/src/mediawiki.widgets.datetime/ProlepticGregorianDateTimeFormatter.js675
-rw-r--r--www/wiki/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.definitions.less37
-rw-r--r--www/wiki/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.js2
-rw-r--r--www/wiki/resources/src/mediawiki.widgets.visibleByteLimit/mediawiki.widgets.visibleByteLimit.js21
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/AUTHORS.txt10
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/LICENSE.txt25
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/MediaSearch/broken-image.pngbin0 -> 1083 bytes
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsProvider.js229
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsQueue.js224
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceProvider.js322
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceQueue.js68
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.css92
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.js274
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchProvider.js69
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchQueue.js82
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.css10
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.js473
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.js591
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less254
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js205
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategoryMultiselectWidget.js416
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategorySelector.js399
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexNamespaceInputWidget.base.css26
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexNamespaceInputWidget.js136
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.base.css20
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.js121
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js697
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.less95
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.styles.less53
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.NamespaceInputWidget.js71
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.css3
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js258
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.SelectWithInputWidget.base.css20
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.SelectWithInputWidget.js145
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.js158
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.less162
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleInputWidget.js139
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleOptionWidget.js100
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleSearchWidget.js105
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js343
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.less79
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.UserInputWidget.js120
-rw-r--r--www/wiki/resources/src/mediawiki.widgets/mw.widgets.UsersMultiselectWidget.js171
-rw-r--r--www/wiki/resources/src/mediawiki/ForeignApi.js119
-rw-r--r--www/wiki/resources/src/mediawiki/api.js506
-rw-r--r--www/wiki/resources/src/mediawiki/api/category.js108
-rw-r--r--www/wiki/resources/src/mediawiki/api/edit.js193
-rw-r--r--www/wiki/resources/src/mediawiki/api/login.js60
-rw-r--r--www/wiki/resources/src/mediawiki/api/messages.js78
-rw-r--r--www/wiki/resources/src/mediawiki/api/options.js102
-rw-r--r--www/wiki/resources/src/mediawiki/api/parse.js49
-rw-r--r--www/wiki/resources/src/mediawiki/api/rollback.js33
-rw-r--r--www/wiki/resources/src/mediawiki/api/upload.js668
-rw-r--r--www/wiki/resources/src/mediawiki/api/user.js37
-rw-r--r--www/wiki/resources/src/mediawiki/api/watch.js70
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/autocomplete.js25
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/autoinfuse.js32
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/checkmatrix.js16
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/cloner.js36
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/hide-if.js295
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/htmlform.Checker.js180
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/htmlform.Element.js46
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/htmlform.js14
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/images/question.pngbin0 -> 259 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/images/question.svg1
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/multiselect.js114
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/ooui.styles.css47
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/selectandother.js41
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/selectorother.js62
-rw-r--r--www/wiki/resources/src/mediawiki/htmlform/styles.css54
-rw-r--r--www/wiki/resources/src/mediawiki/images/arrow-collapsed-ltr.pngbin0 -> 132 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/arrow-collapsed-ltr.svg1
-rw-r--r--www/wiki/resources/src/mediawiki/images/arrow-collapsed-rtl.pngbin0 -> 134 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/arrow-collapsed-rtl.svg1
-rw-r--r--www/wiki/resources/src/mediawiki/images/arrow-expanded.pngbin0 -> 133 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/arrow-expanded.svg1
-rw-r--r--www/wiki/resources/src/mediawiki/images/arrow-sort-ascending.pngbin0 -> 167 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/arrow-sort-ascending.svg1
-rw-r--r--www/wiki/resources/src/mediawiki/images/arrow-sort-descending.pngbin0 -> 166 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/arrow-sort-descending.svg1
-rw-r--r--www/wiki/resources/src/mediawiki/images/feed-icon.pngbin0 -> 505 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/feed-icon.svg1
-rw-r--r--www/wiki/resources/src/mediawiki/images/help.pngbin0 -> 405 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/help.svg1
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.pngbin0 -> 323 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.svg44
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.pngbin0 -> 318 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.svg44
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.pngbin0 -> 307 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.svg36
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.pngbin0 -> 301 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.svg36
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-ltr.pngbin0 -> 341 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-ltr.svg43
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-rtl.pngbin0 -> 350 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-rtl.svg69
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-forward-ltr.pngbin0 -> 327 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-forward-ltr.svg36
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-forward-rtl.pngbin0 -> 322 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/pager-arrow-forward-rtl.svg36
-rw-r--r--www/wiki/resources/src/mediawiki/images/question.pngbin0 -> 259 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/images/question.svg1
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js461
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.less19
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js264
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.ForeignUpload.js143
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.RegExp.js22
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.Title.js976
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js255
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.Upload.BookletLayout.css34
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js711
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.Upload.Dialog.js230
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.Upload.js393
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.Uri.js433
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.Uri.loose.regexp22
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.Uri.strict.regexp13
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.apihelp.css105
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.apipretty.css11
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.checkboxtoggle.css3
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.checkboxtoggle.js38
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.confirmCloseWindow.js111
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.content.json.css59
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.content.json.less59
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.cookie.js131
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.debug.init.js3
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.debug.js389
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.debug.less187
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.diff.styles.css121
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.diff.styles.print.css16
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.errorLogger.js58
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.experiments.js109
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.feedback.css31
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.feedback.js502
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.feedback.spinner.gifbin0 -> 1108 bytes
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.feedlink.css14
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.filewarning.js67
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.filewarning.less36
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.helplink.less11
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.hidpi.js5
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.hlist-allskins.less21
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.hlist.css90
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.htmlform.css49
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.htmlform.js440
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.htmlform.ooui.css34
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.icon.less19
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.inspect.js337
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.jqueryMsg.js1390
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.jqueryMsg.peg85
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.js2799
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.log.js74
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.notification.common.css7
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.notification.convertmessagebox.js64
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.notification.convertmessagebox.styles.less7
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.notification.css53
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.notification.hideForPrint.css3
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.notification.js441
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.notification.print.css3
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.notify.js28
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.pager.tablePager.less28
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.raggett.css3
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.requestIdleCallback.js52
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.searchSuggest.css24
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.searchSuggest.js316
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.sectionAnchor.css3
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.storage.js94
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.template.js124
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.template.mustache.js34
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.template.regexp.js15
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.toc.css11
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.toc.js60
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.toc.print.css5
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.user.js175
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.userSuggest.js42
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.util.js648
-rw-r--r--www/wiki/resources/src/mediawiki/mediawiki.viewport.js101
-rw-r--r--www/wiki/resources/src/mediawiki/page/gallery-print.css35
-rw-r--r--www/wiki/resources/src/mediawiki/page/gallery-slideshow.js460
-rw-r--r--www/wiki/resources/src/mediawiki/page/gallery.css188
-rw-r--r--www/wiki/resources/src/mediawiki/page/gallery.js268
-rw-r--r--www/wiki/resources/src/mediawiki/page/gallery.print.css35
-rw-r--r--www/wiki/resources/src/mediawiki/page/image-pagination.js143
-rw-r--r--www/wiki/resources/src/mediawiki/page/patrol.ajax.js64
-rw-r--r--www/wiki/resources/src/mediawiki/page/ready.js58
-rw-r--r--www/wiki/resources/src/mediawiki/page/rollback.js67
-rw-r--r--www/wiki/resources/src/mediawiki/page/startup.js49
-rw-r--r--www/wiki/resources/src/mediawiki/page/watch.js192
-rw-r--r--www/wiki/resources/src/moment-dmy.js16
-rw-r--r--www/wiki/resources/src/moment-global.js2
-rw-r--r--www/wiki/resources/src/moment-locale-overrides.js44
-rw-r--r--www/wiki/resources/src/oojs-global.js2
-rw-r--r--www/wiki/resources/src/oojs-ui-local.css6
-rw-r--r--www/wiki/resources/src/oojs-ui-local.js17
-rw-r--r--www/wiki/resources/src/oojs-ui-styles-skip.js9
-rw-r--r--www/wiki/resources/src/polyfill-nodeTypes.js19
-rw-r--r--www/wiki/resources/src/polyfill-object-create.js62
-rw-r--r--www/wiki/resources/src/startup.js168
4629 files changed, 195849 insertions, 0 deletions
diff --git a/www/wiki/resources/Resources.php b/www/wiki/resources/Resources.php
new file mode 100644
index 00000000..8bb26ec5
--- /dev/null
+++ b/www/wiki/resources/Resources.php
@@ -0,0 +1,2870 @@
+<?php
+/**
+ * Definition of core ResourceLoader modules.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ die( 'Not an entry point.' );
+}
+
+return [
+
+ /**
+ * Special modules who have their own classes
+ */
+ 'startup' => [ 'class' => 'ResourceLoaderStartUpModule' ],
+
+ // Scripts managed by the local wiki (stored in the MediaWiki namespace)
+ 'site' => [ 'class' => 'ResourceLoaderSiteModule' ],
+ 'site.styles' => [ 'class' => 'ResourceLoaderSiteStylesModule' ],
+ 'noscript' => [
+ 'class' => 'ResourceLoaderWikiModule',
+ 'styles' => [ 'MediaWiki:Noscript.css' ],
+ 'group' => 'noscript',
+ ],
+ 'filepage' => [
+ 'class' => 'ResourceLoaderWikiModule',
+ 'styles' => [ 'MediaWiki:Filepage.css' ],
+ ],
+ 'user.groups' => [
+ // Merged into 'user' since MediaWiki 1.28 - kept for back-compat
+ 'dependencies' => 'user',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ // Scripts managed by the current user (stored in their user space)
+ 'user' => [ 'class' => 'ResourceLoaderUserModule' ],
+ 'user.styles' => [ 'class' => 'ResourceLoaderUserStylesModule' ],
+
+ // Populate mediawiki.user placeholders with information about the current user
+ 'user.defaults' => [ 'class' => 'ResourceLoaderUserDefaultsModule' ],
+ 'user.options' => [ 'class' => 'ResourceLoaderUserOptionsModule' ],
+ 'user.tokens' => [ 'class' => 'ResourceLoaderUserTokensModule' ],
+
+ // Scripts for the dynamic language specific data, like grammar forms.
+ 'mediawiki.language.data' => [ 'class' => 'ResourceLoaderLanguageDataModule' ],
+
+ /* MediaWiki base skinning modules */
+
+ /**
+ * Common skin styles, grouped into three graded levels.
+ *
+ * Level 1 "elements":
+ * The base level that only contains the most basic of common skin styles.
+ * Only styles for single elements are included, no styling for complex structures like the
+ * TOC is present. This level is for skins that want to implement the entire style of even
+ * content area structures like the TOC themselves.
+ *
+ * Level 2 "content":
+ * The most commonly used level for skins implemented from scratch. This level includes all
+ * the single element styles from "elements" as well as styles for complex structures such
+ * as the TOC that are output in the content area by MediaWiki rather than the skin.
+ * Essentially this is the common level that lets skins leave the style of the content area
+ * as it is normally styled, while leaving the rest of the skin up to the skin
+ * implementation.
+ *
+ * Level 3 "interface":
+ * The highest level, this stylesheet contains extra common styles for classes like
+ * .firstHeading, #contentSub, et cetera which are not outputted by MediaWiki but are common
+ * to skins like MonoBook, Vector, etc... Essentially this level is for styles that are
+ * common to MonoBook clones. And since practically every skin that currently exists within
+ * core is a MonoBook clone, all our core skins currently use this level.
+ *
+ * These modules are typically loaded by addModuleStyles(), which has absolutely no concept of
+ * dependency management. As a result they contain duplicate stylesheet references instead of
+ * setting 'dependencies' to the lower level the module is based on. For this reason avoid
+ * including more than one of them into your skin as this will result in duplicate CSS.
+ */
+ 'mediawiki.skinning.elements' => [
+ 'styles' => [
+ 'resources/src/mediawiki.skinning/elements.css' => [ 'media' => 'screen' ],
+ ],
+ ],
+ 'mediawiki.skinning.content' => [
+ 'styles' => [
+ 'resources/src/mediawiki.skinning/elements.css' => [ 'media' => 'screen' ],
+ 'resources/src/mediawiki.skinning/content.css' => [ 'media' => 'screen' ],
+ ],
+ ],
+ // Used in the web installer. Test it after modifying this definition!
+ 'mediawiki.skinning.interface' => [
+ 'class' => 'ResourceLoaderSkinModule',
+ 'styles' => [
+ 'resources/src/mediawiki.skinning/elements.css' => [ 'media' => 'screen' ],
+ 'resources/src/mediawiki.skinning/content.css' => [ 'media' => 'screen' ],
+ 'resources/src/mediawiki.skinning/interface.css' => [ 'media' => 'screen' ],
+ ],
+ ],
+
+ 'mediawiki.skinning.content.parsoid' => [
+ // Style Parsoid HTML+RDFa output consistent with wikitext from PHP parser
+ // with the interface.css styles; skinStyles should be used if your
+ // skin over-rides common content styling.
+ 'skinStyles' => [
+ 'default' => 'resources/src/mediawiki.skinning/content.parsoid.less',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ 'mediawiki.skinning.content.externallinks' => [
+ 'styles' => [
+ 'resources/src/mediawiki.skinning/content.externallinks.css' => [ 'media' => 'screen' ],
+ ],
+ ],
+
+ /* jQuery */
+
+ 'jquery' => [
+ 'scripts' => ( $GLOBALS['wgUsejQueryThree'] ?
+ [
+ 'resources/lib/jquery/jquery3.js',
+ 'resources/lib/jquery/jquery.migrate.js',
+ ] : [
+ 'resources/lib/jquery/jquery.js',
+ ]
+ ),
+ 'raw' => true,
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ /* jQuery Plugins */
+
+ 'jquery.accessKeyLabel' => [
+ 'scripts' => 'resources/src/jquery/jquery.accessKeyLabel.js',
+ 'dependencies' => [
+ 'jquery.client',
+ 'mediawiki.RegExp',
+ ],
+ 'messages' => [ 'brackets', 'word-separator' ],
+ 'targets' => [ 'mobile', 'desktop' ],
+ ],
+ 'jquery.appear' => [
+ 'deprecated' => 'Please use "mediawiki.viewport" instead.',
+ 'scripts' => 'resources/lib/jquery/jquery.appear.js',
+ ],
+ 'jquery.async' => [
+ 'scripts' => 'resources/lib/jquery/jquery.async.js',
+ ],
+ 'jquery.autoEllipsis' => [
+ 'deprecated' => 'Use CSS text-overflow instead.',
+ 'scripts' => 'resources/src/jquery/jquery.autoEllipsis.js',
+ 'dependencies' => 'jquery.highlightText',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.badge' => [
+ 'deprecated' => 'Please use Notifications instead.',
+ 'scripts' => 'resources/src/jquery/jquery.badge.js',
+ 'styles' => 'resources/src/jquery/jquery.badge.css',
+ 'dependencies' => 'mediawiki.language',
+ ],
+ 'jquery.byteLength' => [
+ 'scripts' => 'resources/src/jquery/jquery.byteLength.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.byteLimit' => [
+ 'scripts' => 'resources/src/jquery/jquery.byteLimit.js',
+ 'dependencies' => 'jquery.byteLength',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.checkboxShiftClick' => [
+ 'scripts' => 'resources/src/jquery/jquery.checkboxShiftClick.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.chosen' => [
+ 'scripts' => 'resources/lib/jquery.chosen/chosen.jquery.js',
+ 'styles' => 'resources/lib/jquery.chosen/chosen.css',
+ ],
+ 'jquery.client' => [
+ 'scripts' => 'resources/lib/jquery.client/jquery.client.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.color' => [
+ 'scripts' => 'resources/src/jquery/jquery.color.js',
+ 'dependencies' => 'jquery.colorUtil',
+ ],
+ 'jquery.colorUtil' => [
+ 'scripts' => 'resources/src/jquery/jquery.colorUtil.js',
+ ],
+ 'jquery.confirmable' => [
+ 'scripts' => [
+ 'resources/src/jquery/jquery.confirmable.js',
+ 'resources/src/jquery/jquery.confirmable.mediawiki.js',
+ ],
+ 'messages' => [
+ 'confirmable-confirm',
+ 'confirmable-yes',
+ 'confirmable-no',
+ 'word-separator',
+ ],
+ 'styles' => 'resources/src/jquery/jquery.confirmable.css',
+ 'dependencies' => 'mediawiki.jqueryMsg',
+ ],
+ 'jquery.cookie' => [
+ 'scripts' => 'resources/lib/jquery/jquery.cookie.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.expandableField' => [
+ 'scripts' => 'resources/src/jquery/jquery.expandableField.js',
+ ],
+ 'jquery.farbtastic' => [
+ 'scripts' => 'resources/src/jquery/jquery.farbtastic.js',
+ 'styles' => 'resources/src/jquery/jquery.farbtastic.css',
+ 'dependencies' => 'jquery.colorUtil',
+ ],
+ 'jquery.footHovzer' => [
+ 'scripts' => 'resources/src/jquery/jquery.footHovzer.js',
+ 'styles' => 'resources/src/jquery/jquery.footHovzer.css',
+ ],
+ 'jquery.form' => [
+ 'scripts' => 'resources/lib/jquery/jquery.form.js',
+ ],
+ 'jquery.fullscreen' => [
+ 'scripts' => 'resources/lib/jquery/jquery.fullscreen.js',
+ ],
+ 'jquery.getAttrs' => [
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'scripts' => 'resources/src/jquery/jquery.getAttrs.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.hidpi' => [
+ 'scripts' => 'resources/src/jquery/jquery.hidpi.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.highlightText' => [
+ 'scripts' => 'resources/src/jquery/jquery.highlightText.js',
+ 'dependencies' => [
+ 'mediawiki.RegExp',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.hoverIntent' => [
+ 'scripts' => 'resources/lib/jquery/jquery.hoverIntent.js',
+ ],
+ 'jquery.i18n' => [
+ 'scripts' => [
+ 'resources/lib/jquery.i18n/src/jquery.i18n.js',
+ 'resources/lib/jquery.i18n/src/jquery.i18n.messagestore.js',
+ 'resources/lib/jquery.i18n/src/jquery.i18n.parser.js',
+ 'resources/lib/jquery.i18n/src/jquery.i18n.emitter.js',
+ 'resources/lib/jquery.i18n/src/jquery.i18n.emitter.bidi.js',
+ 'resources/lib/jquery.i18n/src/jquery.i18n.language.js',
+ 'resources/lib/jquery.i18n/src/jquery.i18n.fallbacks.js',
+ ],
+ 'dependencies' => 'mediawiki.libs.pluralruleparser',
+ 'languageScripts' => [
+ 'bs' => 'resources/lib/jquery.i18n/src/languages/bs.js',
+ 'dsb' => 'resources/lib/jquery.i18n/src/languages/dsb.js',
+ 'fi' => 'resources/lib/jquery.i18n/src/languages/fi.js',
+ 'ga' => 'resources/lib/jquery.i18n/src/languages/ga.js',
+ 'he' => 'resources/lib/jquery.i18n/src/languages/he.js',
+ 'hsb' => 'resources/lib/jquery.i18n/src/languages/hsb.js',
+ 'hu' => 'resources/lib/jquery.i18n/src/languages/hu.js',
+ 'hy' => 'resources/lib/jquery.i18n/src/languages/hy.js',
+ 'la' => 'resources/lib/jquery.i18n/src/languages/la.js',
+ 'ml' => 'resources/lib/jquery.i18n/src/languages/ml.js',
+ 'os' => 'resources/lib/jquery.i18n/src/languages/os.js',
+ 'ru' => 'resources/lib/jquery.i18n/src/languages/ru.js',
+ 'sl' => 'resources/lib/jquery.i18n/src/languages/sl.js',
+ 'uk' => 'resources/lib/jquery.i18n/src/languages/uk.js',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.localize' => [
+ 'scripts' => 'resources/src/jquery/jquery.localize.js',
+ ],
+ 'jquery.makeCollapsible' => [
+ 'scripts' => 'resources/src/jquery/jquery.makeCollapsible.js',
+ 'styles' => 'resources/src/jquery/jquery.makeCollapsible.css',
+ 'messages' => [ 'collapsible-expand', 'collapsible-collapse' ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.mockjax' => [
+ 'scripts' => 'resources/lib/jquery/jquery.mockjax.js',
+ ],
+ 'jquery.mw-jump' => [
+ 'scripts' => 'resources/src/jquery/jquery.mw-jump.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.placeholder' => [
+ 'deprecated' => 'Use of "jquery.placeholder" is deprecated since MediaWiki 1.29.0',
+
+ 'scripts' => 'resources/src/jquery/jquery.placeholder.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.qunit' => [
+ 'scripts' => 'resources/lib/qunitjs/qunit.js',
+ 'styles' => 'resources/lib/qunitjs/qunit.css',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.spinner' => [
+ 'scripts' => 'resources/src/jquery/jquery.spinner.js',
+ 'styles' => 'resources/src/jquery/jquery.spinner.css',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.jStorage' => [
+ 'deprecated' => 'Please use "mediawiki.storage" instead.',
+ 'scripts' => 'resources/lib/jquery/jquery.jStorage.js',
+ ],
+ 'jquery.suggestions' => [
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'scripts' => 'resources/src/jquery/jquery.suggestions.js',
+ 'styles' => 'resources/src/jquery/jquery.suggestions.css',
+ 'dependencies' => 'jquery.highlightText',
+ ],
+ 'jquery.tabIndex' => [
+ 'scripts' => 'resources/src/jquery/jquery.tabIndex.js',
+ ],
+ 'jquery.tablesorter' => [
+ 'scripts' => 'resources/src/jquery/jquery.tablesorter.js',
+ 'styles' => 'resources/src/jquery/jquery.tablesorter.less',
+ 'messages' => [ 'sort-descending', 'sort-ascending' ],
+ 'dependencies' => [
+ 'mediawiki.RegExp',
+ 'mediawiki.language.months',
+ ],
+ ],
+ 'jquery.textSelection' => [
+ 'scripts' => 'resources/src/jquery/jquery.textSelection.js',
+ 'dependencies' => 'jquery.client',
+ 'targets' => [ 'mobile', 'desktop' ],
+ ],
+ 'jquery.throttle-debounce' => [
+ 'scripts' => 'resources/lib/jquery/jquery.ba-throttle-debounce.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'jquery.xmldom' => [
+ 'scripts' => 'resources/lib/jquery/jquery.xmldom.js',
+ ],
+
+ /* jQuery Tipsy */
+
+ 'jquery.tipsy' => [
+ 'deprecated' => true,
+ 'scripts' => 'resources/src/jquery.tipsy/jquery.tipsy.js',
+ 'styles' => 'resources/src/jquery.tipsy/jquery.tipsy.css',
+ ],
+
+ /* jQuery UI */
+
+ 'jquery.ui.core' => [
+ 'deprecated' => 'Please use "mediawiki.ui.button" or "oojs-ui" instead.',
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.core.js',
+ 'dependencies' => [
+ 'jquery.ui.core.styles',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.core.styles' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.core.css',
+ 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.theme.css',
+ ],
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.accordion' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.accordion.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.accordion.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.autocomplete' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.autocomplete.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ 'jquery.ui.position',
+ 'jquery.ui.menu',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.autocomplete.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.button' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.button.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.button.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.datepicker' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.datepicker.js',
+ 'dependencies' => 'jquery.ui.core',
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.datepicker.css',
+ ],
+ 'languageScripts' => [
+ 'af' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-af.js',
+ 'ar' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar.js',
+ 'ar-dz' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar-DZ.js',
+ 'az' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-az.js',
+ 'bg' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bg.js',
+ 'bs' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bs.js',
+ 'ca' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ca.js',
+ 'cs' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cs.js',
+ 'da' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-da.js',
+ 'de-at' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-AT.js',
+ 'de-ch' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-CH.js',
+ 'de' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de.js',
+ 'el' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-el.js',
+ 'en-au' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-AU.js',
+ 'en-gb' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js',
+ 'en-nz' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-NZ.js',
+ 'eo' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eo.js',
+ 'es' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-es.js',
+ 'et' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-et.js',
+ 'eu' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eu.js',
+ 'fa' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fa.js',
+ 'fi' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fi.js',
+ 'fo' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fo.js',
+ 'fr' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr.js',
+ 'fr-ch' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr-CH.js',
+ 'gl' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-gl.js',
+ 'he' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-he.js',
+ 'hi' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hi.js',
+ 'hr' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hr.js',
+ 'hu' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hu.js',
+ 'hy' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hy.js',
+ 'id' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-id.js',
+ 'is' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-is.js',
+ 'it' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-it.js',
+ 'ja' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ja.js',
+ 'ka' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ka.js',
+ 'kk' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-kk.js',
+ 'km' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-km.js',
+ 'ko' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ko.js',
+ 'lb' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lb.js',
+ 'lt' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lt.js',
+ 'lv' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lv.js',
+ 'mk' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-mk.js',
+ 'ml' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ml.js',
+ 'ms' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ms.js',
+ 'nl' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl.js',
+ 'nl-be' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl-BE.js',
+ 'no' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-no.js',
+ 'pl' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pl.js',
+ 'pt' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt.js',
+ 'pt-br' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js',
+ 'rm' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-rm.js',
+ 'ro' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ro.js',
+ 'ru' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ru.js',
+ 'sk' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sk.js',
+ 'sl' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sl.js',
+ 'sq' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sq.js',
+ 'sr-ec' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr.js',
+ 'sr-el' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js',
+ 'sv' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sv.js',
+ 'ta' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ta.js',
+ 'th' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-th.js',
+ 'tj' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tj.js',
+ 'tr' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tr.js',
+ 'uk' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-uk.js',
+ 'vi' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-vi.js',
+ 'zh-cn' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js',
+ 'zh-hk' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js',
+ 'zh-tw' => 'resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.dialog' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.dialog.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ 'jquery.ui.button',
+ 'jquery.ui.draggable',
+ 'jquery.ui.mouse',
+ 'jquery.ui.position',
+ 'jquery.ui.resizable',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.dialog.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.draggable' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.draggable.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.mouse',
+ 'jquery.ui.widget',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.droppable' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.droppable.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.mouse',
+ 'jquery.ui.widget',
+ 'jquery.ui.draggable',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.menu' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.menu.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ 'jquery.ui.position',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.menu.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.mouse' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.mouse.js',
+ 'dependencies' => 'jquery.ui.widget',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.position' => [
+ 'deprecated' => true,
+ 'targets' => [ 'mobile', 'desktop' ],
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.position.js',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.progressbar' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.progressbar.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.progressbar.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.resizable' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.resizable.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ 'jquery.ui.mouse',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.resizable.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.selectable' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.selectable.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ 'jquery.ui.mouse',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.selectable.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.slider' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.slider.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ 'jquery.ui.mouse',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.slider.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.sortable' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.sortable.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.mouse',
+ 'jquery.ui.widget',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.spinner' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.spinner.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ 'jquery.ui.button',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.spinner.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.tabs' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.tabs.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.tabs.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.tooltip' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.tooltip.js',
+ 'dependencies' => [
+ 'jquery.ui.core',
+ 'jquery.ui.widget',
+ 'jquery.ui.position',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/lib/jquery.ui/themes/smoothness/jquery.ui.tooltip.css',
+ ],
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.ui.widget' => [
+ 'deprecated' => true,
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.widget.js',
+ 'group' => 'jquery.ui',
+ ],
+ // Effects
+ 'jquery.effects.core' => [
+ 'deprecated' => true,
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect.js',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.blind' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-blind.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.bounce' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-bounce.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.clip' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-clip.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.drop' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-drop.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.explode' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-explode.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.fade' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-fade.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.fold' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-fold.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.highlight' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-highlight.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.pulsate' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-pulsate.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.scale' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-scale.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.shake' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-shake.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.slide' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-slide.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+ 'jquery.effects.transfer' => [
+ 'scripts' => 'resources/lib/jquery.ui/jquery.ui.effect-transfer.js',
+ 'dependencies' => 'jquery.effects.core',
+ 'group' => 'jquery.ui',
+ ],
+
+ /* json2 */
+ 'json' => [
+ 'deprecated' => 'Use of the "json" module is deprecated since MediaWiki 1.29.0',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ /* Moment.js */
+
+ 'moment' => [
+ 'scripts' => [
+ // HACK: For some reason if you don't define window.moment first, loading moment fatals
+ 'resources/src/moment-global.js',
+ 'resources/lib/moment/moment.js',
+ ],
+ 'languageScripts' => [
+ 'aeb-arab' => 'resources/lib/moment/locale/ar-tn.js',
+ 'af' => 'resources/lib/moment/locale/af.js',
+ 'ar' => 'resources/lib/moment/locale/ar.js',
+ 'ar-ma' => 'resources/lib/moment/locale/ar-ma.js',
+ 'ar-sa' => 'resources/lib/moment/locale/ar-sa.js',
+ 'az' => 'resources/lib/moment/locale/az.js',
+ 'be' => 'resources/lib/moment/locale/be.js',
+ 'bg' => 'resources/lib/moment/locale/bg.js',
+ 'bm' => 'resources/lib/moment/locale/bm.js',
+ 'bn' => 'resources/lib/moment/locale/bn.js',
+ 'bo' => 'resources/lib/moment/locale/bo.js',
+ 'br' => 'resources/lib/moment/locale/br.js',
+ 'bs' => 'resources/lib/moment/locale/bs.js',
+ 'ca' => 'resources/lib/moment/locale/ca.js',
+ 'cs' => 'resources/lib/moment/locale/cs.js',
+ 'cv' => 'resources/lib/moment/locale/cv.js',
+ 'cy' => 'resources/lib/moment/locale/cy.js',
+ 'da' => 'resources/lib/moment/locale/da.js',
+ 'de' => 'resources/lib/moment/locale/de.js',
+ 'de-at' => 'resources/lib/moment/locale/de-at.js',
+ 'de-ch' => 'resources/lib/moment/locale/de-ch.js',
+ 'dv' => 'resources/lib/moment/locale/dv.js',
+ 'el' => 'resources/lib/moment/locale/el.js',
+ 'en' => 'resources/src/moment-dmy.js',
+ 'en-au' => 'resources/lib/moment/locale/en-au.js',
+ 'en-ca' => 'resources/lib/moment/locale/en-ca.js',
+ 'en-gb' => 'resources/lib/moment/locale/en-gb.js',
+ 'eo' => 'resources/lib/moment/locale/eo.js',
+ 'es' => 'resources/lib/moment/locale/es.js',
+ 'et' => 'resources/lib/moment/locale/et.js',
+ 'eu' => 'resources/lib/moment/locale/eu.js',
+ 'fa' => 'resources/lib/moment/locale/fa.js',
+ 'fi' => 'resources/lib/moment/locale/fi.js',
+ 'fo' => 'resources/lib/moment/locale/fo.js',
+ 'fr' => 'resources/lib/moment/locale/fr.js',
+ 'fr-ca' => 'resources/lib/moment/locale/fr-ca.js',
+ 'fy' => 'resources/lib/moment/locale/fy.js',
+ 'gd' => 'resources/lib/moment/locale/gd.js',
+ 'gl' => 'resources/lib/moment/locale/gl.js',
+ 'gom-latn' => 'resources/lib/moment/locale/gom-latn.js',
+ 'gu' => 'resources/lib/moment/locale/gu.js',
+ 'he' => 'resources/lib/moment/locale/he.js',
+ 'hi' => 'resources/lib/moment/locale/hi.js',
+ 'hr' => 'resources/lib/moment/locale/hr.js',
+ 'hu' => 'resources/lib/moment/locale/hu.js',
+ 'hy-am' => 'resources/lib/moment/locale/hy-am.js',
+ 'id' => 'resources/lib/moment/locale/id.js',
+ 'is' => 'resources/lib/moment/locale/is.js',
+ 'it' => 'resources/lib/moment/locale/it.js',
+ 'ja' => 'resources/lib/moment/locale/ja.js',
+ 'jv' => 'resources/lib/moment/locale/jv.js',
+ 'ka' => 'resources/lib/moment/locale/ka.js',
+ 'kk-cyrl' => 'resources/lib/moment/locale/kk.js',
+ 'kn' => 'resources/lib/moment/locale/kn.js',
+ 'ko' => 'resources/lib/moment/locale/ko.js',
+ 'ky' => 'resources/lib/moment/locale/ky.js',
+ 'lo' => 'resources/lib/moment/locale/lo.js',
+ 'lt' => 'resources/lib/moment/locale/lt.js',
+ 'lv' => 'resources/lib/moment/locale/lv.js',
+ 'mi' => 'resources/lib/moment/locale/mi.js',
+ 'mk' => 'resources/lib/moment/locale/mk.js',
+ 'ml' => 'resources/lib/moment/locale/ml.js',
+ 'mr' => 'resources/lib/moment/locale/mr.js',
+ 'ms-my' => 'resources/lib/moment/locale/ms-my.js',
+ 'ms' => 'resources/lib/moment/locale/ms.js',
+ 'my' => 'resources/lib/moment/locale/my.js',
+ 'nb' => 'resources/lib/moment/locale/nb.js',
+ 'ne' => 'resources/lib/moment/locale/ne.js',
+ 'nl' => 'resources/lib/moment/locale/nl.js',
+ 'nn' => 'resources/lib/moment/locale/nn.js',
+ 'pa' => 'resources/lib/moment/locale/pa-in.js',
+ 'pl' => 'resources/lib/moment/locale/pl.js',
+ 'pt' => 'resources/lib/moment/locale/pt.js',
+ 'pt-br' => 'resources/lib/moment/locale/pt-br.js',
+ 'ro' => 'resources/lib/moment/locale/ro.js',
+ 'ru' => 'resources/lib/moment/locale/ru.js',
+ 'sd' => 'resources/lib/moment/locale/sd.js',
+ 'se' => 'resources/lib/moment/locale/se.js',
+ 'si' => 'resources/lib/moment/locale/si.js',
+ 'sk' => 'resources/lib/moment/locale/sk.js',
+ 'sl' => 'resources/lib/moment/locale/sl.js',
+ 'sq' => 'resources/lib/moment/locale/sq.js',
+ 'sr-ec' => 'resources/lib/moment/locale/sr-cyrl.js',
+ 'sr-el' => 'resources/lib/moment/locale/sr.js',
+ 'ss' => 'resources/lib/moment/locale/ss.js',
+ 'sv' => 'resources/lib/moment/locale/sv.js',
+ 'sw' => 'resources/lib/moment/locale/sw.js',
+ 'ta' => 'resources/lib/moment/locale/ta.js',
+ 'te' => 'resources/lib/moment/locale/te.js',
+ 'tet' => 'resources/lib/moment/locale/tet.js',
+ 'th' => 'resources/lib/moment/locale/th.js',
+ 'tl-ph' => 'resources/lib/moment/locale/tl-ph.js',
+ 'tr' => 'resources/lib/moment/locale/tr.js',
+ 'tzm' => 'resources/lib/moment/locale/tzm.js',
+ 'tzm-latn' => 'resources/lib/moment/locale/tzm-latn.js',
+ 'uk' => 'resources/lib/moment/locale/uk.js',
+ 'ur' => 'resources/lib/moment/locale/ur.js',
+ 'uz' => 'resources/lib/moment/locale/uz.js',
+ 'uz-latn' => 'resources/lib/moment/locale/uz-latn.js',
+ 'vi' => 'resources/lib/moment/locale/vi.js',
+ 'yo' => 'resources/lib/moment/locale/yo.js',
+ 'zh-hans' => 'resources/lib/moment/locale/zh-cn.js',
+ 'zh-hant' => 'resources/lib/moment/locale/zh-tw.js',
+ 'zh-cn' => 'resources/lib/moment/locale/zh-cn.js',
+ 'zh-hk' => 'resources/lib/moment/locale/zh-hk.js',
+ 'zh-tw' => 'resources/lib/moment/locale/zh-tw.js',
+ ],
+ // HACK: skinScripts come after languageScripts, and we need locale overrides to come
+ // after locale definitions
+ 'skinScripts' => [
+ 'default' => [
+ 'resources/src/moment-locale-overrides.js',
+ ],
+ ],
+ 'dependencies' => [
+ 'mediawiki.language',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ /* MediaWiki */
+
+ 'mediawiki' => [
+ 'class' => 'ResourceLoaderRawFileModule',
+ // Keep in sync with maintenance/jsduck/eg-iframe.html
+ 'scripts' => [
+ 'resources/src/mediawiki/mediawiki.js',
+ 'resources/src/mediawiki/mediawiki.requestIdleCallback.js',
+ 'resources/src/mediawiki/mediawiki.errorLogger.js',
+ ],
+ 'debugScripts' => 'resources/src/mediawiki/mediawiki.log.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.apihelp' => [
+ 'styles' => 'resources/src/mediawiki/mediawiki.apihelp.css',
+ 'targets' => [ 'desktop' ],
+ ],
+ 'mediawiki.template' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.template.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.template.mustache' => [
+ 'scripts' => [
+ 'resources/lib/mustache/mustache.js',
+ 'resources/src/mediawiki/mediawiki.template.mustache.js',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'dependencies' => 'mediawiki.template',
+ ],
+ 'mediawiki.template.regexp' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.template.regexp.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'dependencies' => 'mediawiki.template',
+ ],
+ 'mediawiki.apipretty' => [
+ 'styles' => 'resources/src/mediawiki/mediawiki.apipretty.css',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.api' => [
+ 'scripts' => 'resources/src/mediawiki/api.js',
+ 'dependencies' => [
+ 'mediawiki.util',
+ 'user.tokens',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.api.category' => [
+ 'scripts' => 'resources/src/mediawiki/api/category.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'mediawiki.Title',
+ ],
+ ],
+ 'mediawiki.api.edit' => [
+ 'scripts' => 'resources/src/mediawiki/api/edit.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'mediawiki.Title',
+ 'mediawiki.user',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.api.login' => [
+ 'scripts' => 'resources/src/mediawiki/api/login.js',
+ 'dependencies' => 'mediawiki.api',
+ ],
+ 'mediawiki.api.options' => [
+ 'scripts' => 'resources/src/mediawiki/api/options.js',
+ 'dependencies' => 'mediawiki.api',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.api.parse' => [
+ 'scripts' => 'resources/src/mediawiki/api/parse.js',
+ 'dependencies' => 'mediawiki.api',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.api.upload' => [
+ 'scripts' => 'resources/src/mediawiki/api/upload.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'mediawiki.api.edit',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.api.user' => [
+ 'scripts' => 'resources/src/mediawiki/api/user.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.api.watch' => [
+ 'scripts' => 'resources/src/mediawiki/api/watch.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ ],
+ ],
+ 'mediawiki.api.messages' => [
+ 'scripts' => 'resources/src/mediawiki/api/messages.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.api.rollback' => [
+ 'scripts' => 'resources/src/mediawiki/api/rollback.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ ],
+ ],
+ 'mediawiki.content.json' => [
+ 'styles' => 'resources/src/mediawiki/mediawiki.content.json.less',
+ ],
+ 'mediawiki.confirmCloseWindow' => [
+ 'scripts' => [
+ 'resources/src/mediawiki/mediawiki.confirmCloseWindow.js',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.debug' => [
+ 'scripts' => [
+ 'resources/src/mediawiki/mediawiki.debug.js',
+ ],
+ 'styles' => [
+ 'resources/src/mediawiki/mediawiki.debug.less',
+ ],
+ 'dependencies' => [
+ 'jquery.footHovzer',
+ ],
+ ],
+ 'mediawiki.diff.styles' => [
+ 'styles' => [
+ 'resources/src/mediawiki/mediawiki.diff.styles.css',
+ 'resources/src/mediawiki/mediawiki.diff.styles.print.css' => [
+ 'media' => 'print'
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.feedback' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.feedback.js',
+ 'styles' => 'resources/src/mediawiki/mediawiki.feedback.css',
+ 'dependencies' => [
+ 'mediawiki.messagePoster',
+ 'mediawiki.Title',
+ 'oojs-ui-core',
+ 'oojs-ui-windows',
+ ],
+ 'messages' => [
+ 'feedback-adding',
+ 'feedback-back',
+ 'feedback-bugcheck',
+ 'feedback-dialog-intro',
+ 'feedback-external-bug-report-button',
+ 'feedback-bugnew',
+ 'feedback-bugornote',
+ 'feedback-cancel',
+ 'feedback-close',
+ 'feedback-dialog-title',
+ 'feedback-error1',
+ 'feedback-error2',
+ 'feedback-error3',
+ 'feedback-error4',
+ 'feedback-message',
+ 'feedback-subject',
+ 'feedback-submit',
+ 'feedback-terms',
+ 'feedback-termsofuse',
+ 'feedback-thanks',
+ 'feedback-thanks-title',
+ 'feedback-useragent'
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.feedlink' => [
+ 'styles' => 'resources/src/mediawiki/mediawiki.feedlink.css',
+ ],
+ 'mediawiki.filewarning' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.filewarning.js',
+ 'styles' => 'resources/src/mediawiki/mediawiki.filewarning.less',
+ 'dependencies' => [
+ 'oojs-ui-core',
+ 'oojs-ui.styles.icons-alerts',
+ ],
+ ],
+ 'mediawiki.ForeignApi' => [
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'class' => 'ResourceLoaderForeignApiModule',
+ // Additional dependencies generated dynamically
+ 'dependencies' => 'mediawiki.ForeignApi.core',
+ ],
+ 'mediawiki.ForeignApi.core' => [
+ 'scripts' => 'resources/src/mediawiki/ForeignApi.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'oojs',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.helplink' => [
+ 'styles' => [
+ 'resources/src/mediawiki/mediawiki.helplink.less',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.hidpi' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.hidpi.js',
+ 'dependencies' => 'jquery.hidpi',
+ 'skipFunction' => 'resources/src/mediawiki.hidpi-skip.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.hlist' => [
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'styles' => [
+ 'resources/src/mediawiki/mediawiki.hlist-allskins.less',
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/src/mediawiki/mediawiki.hlist.css',
+ ],
+ ],
+ 'mediawiki.htmlform' => [
+ 'scripts' => [
+ 'resources/src/mediawiki/htmlform/htmlform.js',
+ 'resources/src/mediawiki/htmlform/autocomplete.js',
+ 'resources/src/mediawiki/htmlform/autoinfuse.js',
+ 'resources/src/mediawiki/htmlform/checkmatrix.js',
+ 'resources/src/mediawiki/htmlform/cloner.js',
+ 'resources/src/mediawiki/htmlform/hide-if.js',
+ 'resources/src/mediawiki/htmlform/multiselect.js',
+ 'resources/src/mediawiki/htmlform/selectandother.js',
+ 'resources/src/mediawiki/htmlform/selectorother.js',
+ ],
+ 'dependencies' => [
+ 'mediawiki.RegExp',
+ 'jquery.byteLimit',
+ ],
+ 'messages' => [
+ 'htmlform-chosen-placeholder',
+ // @todo Load this message in content language
+ 'colon-separator',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.htmlform.checker' => [
+ 'scripts' => [
+ 'resources/src/mediawiki/htmlform/htmlform.Checker.js',
+ ],
+ 'dependencies' => [
+ 'jquery.throttle-debounce',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.htmlform.ooui' => [
+ 'scripts' => [
+ 'resources/src/mediawiki/htmlform/htmlform.Element.js',
+ ],
+ 'dependencies' => [
+ 'oojs-ui-core',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.htmlform.styles' => [
+ 'styles' => 'resources/src/mediawiki/htmlform/styles.css',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.htmlform.ooui.styles' => [
+ 'styles' => 'resources/src/mediawiki/htmlform/ooui.styles.css',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.icon' => [
+ 'styles' => 'resources/src/mediawiki/mediawiki.icon.less',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.inspect' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.inspect.js',
+ 'dependencies' => [
+ 'jquery.byteLength',
+ 'mediawiki.RegExp',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.messagePoster' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.messagePoster/mediawiki.messagePoster.factory.js',
+ 'resources/src/mediawiki.messagePoster/mediawiki.messagePoster.MessagePoster.js',
+ ],
+ 'dependencies' => [
+ 'oojs',
+ 'mediawiki.api',
+ 'mediawiki.ForeignApi',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.messagePoster.wikitext' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.messagePoster/mediawiki.messagePoster.WikitextMessagePoster.js',
+ ],
+ 'dependencies' => [
+ 'mediawiki.api.edit',
+ 'mediawiki.messagePoster',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.notification' => [
+ 'styles' => [
+ 'resources/src/mediawiki/mediawiki.notification.common.css',
+ 'resources/src/mediawiki/mediawiki.notification.print.css'
+ => [ 'media' => 'print' ],
+ ],
+ 'skinStyles' => [
+ 'default' => 'resources/src/mediawiki/mediawiki.notification.css',
+ ],
+ 'scripts' => 'resources/src/mediawiki/mediawiki.notification.js',
+ 'dependencies' => [
+ 'mediawiki.util',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.notify' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.notify.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.notification.convertmessagebox' => [
+ 'dependencies' => [
+ 'mediawiki.notification',
+ ],
+ 'scripts' => 'resources/src/mediawiki/mediawiki.notification.convertmessagebox.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.notification.convertmessagebox.styles' => [
+ 'styles' => [
+ 'resources/src/mediawiki/mediawiki.notification.convertmessagebox.styles.less',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.RegExp' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.RegExp.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.pager.tablePager' => [
+ 'styles' => 'resources/src/mediawiki/mediawiki.pager.tablePager.less',
+ ],
+ 'mediawiki.searchSuggest' => [
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'scripts' => 'resources/src/mediawiki/mediawiki.searchSuggest.js',
+ 'styles' => 'resources/src/mediawiki/mediawiki.searchSuggest.css',
+ 'messages' => [
+ 'searchsuggest-search',
+ 'searchsuggest-containing',
+ ],
+ 'dependencies' => [
+ 'jquery.suggestions',
+ 'jquery.getAttrs',
+ 'mediawiki.api',
+ ],
+ ],
+ 'mediawiki.sectionAnchor' => [
+ // Back-compat to hide it on cached pages (T18691; Ie9e334e973; 2015-03-17)
+ 'styles' => 'resources/src/mediawiki/mediawiki.sectionAnchor.css',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.storage' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.storage.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.Title' => [
+ 'scripts' => [
+ 'resources/src/mediawiki/mediawiki.Title.js',
+ 'resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js',
+ ],
+ 'dependencies' => [
+ 'jquery.byteLength',
+ 'mediawiki.util',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.Upload' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.Upload.js',
+ 'dependencies' => [
+ 'mediawiki.api.upload',
+ ],
+ ],
+ 'mediawiki.ForeignUpload' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.ForeignUpload.js',
+ 'dependencies' => [
+ 'mediawiki.ForeignApi',
+ 'mediawiki.Upload',
+ 'oojs',
+ ],
+ 'messages' => [
+ 'uploaddisabledtext',
+ 'upload-dialog-disabled',
+ 'upload-foreign-cant-upload',
+ ]
+ ],
+ 'mediawiki.ForeignStructuredUpload.config' => [
+ 'class' => 'ResourceLoaderUploadDialogModule',
+ ],
+ 'mediawiki.ForeignStructuredUpload' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js',
+ 'dependencies' => [
+ 'mediawiki.ForeignUpload',
+ 'mediawiki.ForeignStructuredUpload.config',
+ ],
+ 'messages' => [
+ 'upload-foreign-cant-load-config',
+ ],
+ ],
+ 'mediawiki.Upload.Dialog' => [
+ 'scripts' => [
+ 'resources/src/mediawiki/mediawiki.Upload.Dialog.js',
+ ],
+ 'dependencies' => [
+ 'mediawiki.Upload.BookletLayout',
+ ],
+ 'messages' => [
+ 'upload-dialog-title',
+ 'upload-dialog-button-cancel',
+ 'upload-dialog-button-back',
+ 'upload-dialog-button-done',
+ 'upload-dialog-button-save',
+ 'upload-dialog-button-upload',
+ ],
+ ],
+ 'mediawiki.Upload.BookletLayout' => [
+ 'scripts' => [
+ 'resources/src/mediawiki/mediawiki.Upload.BookletLayout.js',
+ ],
+ 'styles' => [
+ 'resources/src/mediawiki/mediawiki.Upload.BookletLayout.css',
+ ],
+ 'dependencies' => [
+ 'oojs-ui-core',
+ 'oojs-ui-widgets',
+ 'oojs-ui-windows',
+ 'oojs-ui.styles.icons-content',
+ 'oojs-ui.styles.icons-editing-advanced',
+ 'moment',
+ 'mediawiki.Title',
+ 'mediawiki.user',
+ 'mediawiki.Upload',
+ 'mediawiki.jqueryMsg',
+ 'mediawiki.widgets.StashedFileWidget'
+ ],
+ 'messages' => [
+ 'upload-form-label-infoform-title',
+ 'upload-form-label-infoform-name',
+ 'upload-form-label-infoform-name-tooltip',
+ 'upload-form-label-infoform-description',
+ 'upload-form-label-infoform-description-tooltip',
+ 'upload-form-label-usage-title',
+ 'upload-form-label-usage-filename',
+ 'action-upload',
+ 'apierror-mustbeloggedin',
+ 'badaccess-groups',
+ 'apierror-timeout',
+ 'apierror-offline',
+ 'apierror-unknownerror',
+ 'api-error-unknown-warning',
+ 'fileexists',
+ 'filepageexists',
+ 'file-exists-duplicate',
+ 'file-deleted-duplicate',
+ 'filename-bad-prefix',
+ 'filename-thumb-name',
+ 'filewasdeleted',
+ 'badfilename',
+ 'protectedpagetext',
+ ],
+ ],
+ 'mediawiki.ForeignStructuredUpload.BookletLayout' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js',
+ 'styles' => 'resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.less',
+ 'dependencies' => [
+ 'mediawiki.ForeignStructuredUpload',
+ 'mediawiki.Upload.BookletLayout',
+ 'mediawiki.widgets.CategoryMultiselectWidget',
+ 'mediawiki.widgets.DateInputWidget',
+ 'mediawiki.jqueryMsg',
+ 'mediawiki.api.messages',
+ 'moment',
+ 'mediawiki.libs.jpegmeta',
+ ],
+ 'messages' => [
+ 'upload-form-label-own-work',
+ 'upload-form-label-infoform-categories',
+ 'upload-form-label-infoform-date',
+ 'upload-form-label-own-work-message-generic-local',
+ 'upload-form-label-not-own-work-message-generic-local',
+ 'upload-form-label-not-own-work-local-generic-local',
+ 'upload-form-label-own-work-message-generic-foreign',
+ 'upload-form-label-not-own-work-message-generic-foreign',
+ 'upload-form-label-not-own-work-local-generic-foreign',
+ ],
+ ],
+ 'mediawiki.toc' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.toc.js',
+ 'styles' => [
+ 'resources/src/mediawiki/mediawiki.toc.css'
+ => [ 'media' => 'screen' ],
+ 'resources/src/mediawiki/mediawiki.toc.print.css'
+ => [ 'media' => 'print' ],
+ ],
+ 'dependencies' => 'mediawiki.cookie',
+ 'messages' => [ 'showtoc', 'hidetoc' ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.Uri' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.Uri.js',
+ 'templates' => [
+ 'strict.regexp' => 'resources/src/mediawiki/mediawiki.Uri.strict.regexp',
+ 'loose.regexp' => 'resources/src/mediawiki/mediawiki.Uri.loose.regexp',
+ ],
+ 'dependencies' => 'mediawiki.util',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.user' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.user.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'mediawiki.api.user',
+ 'mediawiki.storage',
+ 'user.options',
+ 'user.tokens',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.userSuggest' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.userSuggest.js',
+ 'dependencies' => [
+ 'jquery.suggestions',
+ 'mediawiki.api'
+ ]
+ ],
+ 'mediawiki.util' => [
+ 'class' => 'ResourceLoaderMediaWikiUtilModule',
+ 'scripts' => 'resources/src/mediawiki/mediawiki.util.js',
+ 'dependencies' => [
+ 'jquery.accessKeyLabel',
+ 'mediawiki.RegExp',
+ 'mediawiki.notify',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.viewport' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.viewport.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.checkboxtoggle' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.checkboxtoggle.js',
+ ],
+ 'mediawiki.checkboxtoggle.styles' => [
+ 'styles' => 'resources/src/mediawiki/mediawiki.checkboxtoggle.css',
+ ],
+ 'mediawiki.cookie' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.cookie.js',
+ 'dependencies' => 'jquery.cookie',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.toolbar' => [
+ 'class' => 'ResourceLoaderEditToolbarModule',
+ 'scripts' => 'resources/src/mediawiki.toolbar/toolbar.js',
+ 'styles' => 'resources/src/mediawiki.toolbar/toolbar.less',
+ 'dependencies' => 'jquery.textSelection',
+ ],
+ 'mediawiki.experiments' => [
+ 'scripts' => 'resources/src/mediawiki/mediawiki.experiments.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ /* MediaWiki Action */
+
+ 'mediawiki.action.edit' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.action/mediawiki.action.edit.js',
+ 'resources/src/mediawiki.action/mediawiki.action.edit.stash.js',
+ ],
+ 'styles' => 'resources/src/mediawiki.action/mediawiki.action.edit.css',
+ 'dependencies' => [
+ 'mediawiki.action.edit.styles',
+ 'jquery.textSelection',
+ 'oojs-ui-core',
+ 'mediawiki.widgets.visibleByteLimit',
+ 'mediawiki.api',
+ ],
+ ],
+ 'mediawiki.action.edit.styles' => [
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'styles' => 'resources/src/mediawiki.action/mediawiki.action.edit.styles.less',
+ ],
+ 'mediawiki.action.edit.collapsibleFooter' => [
+ 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js',
+ 'styles' => 'resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css',
+ 'dependencies' => [
+ 'jquery.makeCollapsible',
+ 'mediawiki.storage',
+ 'mediawiki.icon',
+ ],
+ ],
+ 'mediawiki.action.edit.preview' => [
+ 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.preview.js',
+ 'dependencies' => [
+ 'jquery.form',
+ 'jquery.spinner',
+ 'jquery.textSelection',
+ 'mediawiki.api',
+ 'mediawiki.diff.styles',
+ 'mediawiki.language',
+ 'mediawiki.util',
+ 'mediawiki.jqueryMsg',
+ 'oojs-ui-core',
+ ],
+ 'messages' => [
+ // Keep the uses message keys in sync with EditPage#setHeaders
+ 'creating',
+ 'editconflict',
+ 'editing',
+ 'editingcomment',
+ 'editingsection',
+ 'pagetitle',
+ 'otherlanguages',
+ 'summary-preview',
+ 'subject-preview',
+ 'parentheses',
+ 'previewerrortext',
+ ],
+ ],
+ 'mediawiki.action.history' => [
+ 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.history.js',
+ 'styles' => 'resources/src/mediawiki.action/mediawiki.action.history.css',
+ ],
+ 'mediawiki.action.history.styles' => [
+ 'styles' => 'resources/src/mediawiki.action/mediawiki.action.history.styles.css',
+ ],
+ // using this module is deprecated, for diff styles use mediawiki.diff.styles instead
+ 'mediawiki.action.history.diff' => [
+ 'styles' => [
+ 'resources/src/mediawiki/mediawiki.diff.styles.css',
+ 'resources/src/mediawiki/mediawiki.diff.styles.print.css' => [
+ 'media' => 'print'
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.action.view.dblClickEdit' => [
+ 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.dblClickEdit.js',
+ 'dependencies' => [
+ 'mediawiki.util',
+ 'user.options',
+ ],
+ ],
+ 'mediawiki.action.view.metadata' => [
+ 'styles' => 'resources/src/mediawiki.action/mediawiki.action.view.metadata.css',
+ 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.metadata.js',
+ 'messages' => [
+ 'metadata-expand',
+ 'metadata-collapse',
+ ],
+ ],
+ 'mediawiki.action.view.categoryPage.styles' => [
+ 'styles' => 'resources/src/mediawiki.action/mediawiki.action.view.categoryPage.less',
+ 'targets' => [ 'desktop', 'mobile' ]
+ ],
+ 'mediawiki.action.view.postEdit' => [
+ 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.postEdit.js',
+ 'styles' => 'resources/src/mediawiki.action/mediawiki.action.view.postEdit.less',
+ 'skinStyles' => [
+ 'monobook' => 'resources/src/mediawiki.action/mediawiki.action.view.postEdit.monobook.css',
+ ],
+ 'dependencies' => [
+ 'mediawiki.jqueryMsg',
+ 'mediawiki.notification'
+ ],
+ 'messages' => [
+ 'postedit-confirmation-created',
+ 'postedit-confirmation-restored',
+ 'postedit-confirmation-saved',
+ ],
+ ],
+ 'mediawiki.action.view.redirect' => [
+ 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.redirect.js',
+ 'dependencies' => 'jquery.client',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.action.view.redirectPage' => [
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'styles' => 'resources/src/mediawiki.action/mediawiki.action.view.redirectPage.css',
+ ],
+ 'mediawiki.action.view.rightClickEdit' => [
+ 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.view.rightClickEdit.js',
+ ],
+ 'mediawiki.action.edit.editWarning' => [
+ 'scripts' => 'resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js',
+ 'dependencies' => [
+ 'jquery.textSelection',
+ 'mediawiki.jqueryMsg',
+ 'mediawiki.confirmCloseWindow',
+ 'user.options',
+ ],
+ 'messages' => [
+ 'editwarning-warning',
+ // editwarning-warning uses {{int:prefs-editing}}
+ 'prefs-editing'
+ ],
+ ],
+ 'mediawiki.action.view.filepage' => [
+ 'styles' => [
+ 'resources/src/mediawiki.action/mediawiki.action.view.filepage.print.css' =>
+ [ 'media' => 'print' ],
+ 'resources/src/mediawiki.action/mediawiki.action.view.filepage.css',
+ ],
+ ],
+
+ /* MediaWiki Language */
+
+ 'mediawiki.language' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.language/mediawiki.language.js',
+ 'resources/src/mediawiki.language/mediawiki.language.numbers.js',
+ 'resources/src/mediawiki.language/mediawiki.language.fallback.js',
+ ],
+ 'languageScripts' => [
+ 'bs' => 'resources/src/mediawiki.language/languages/bs.js',
+ 'dsb' => 'resources/src/mediawiki.language/languages/dsb.js',
+ 'fi' => 'resources/src/mediawiki.language/languages/fi.js',
+ 'ga' => 'resources/src/mediawiki.language/languages/ga.js',
+ 'hsb' => 'resources/src/mediawiki.language/languages/hsb.js',
+ 'hu' => 'resources/src/mediawiki.language/languages/hu.js',
+ 'hy' => 'resources/src/mediawiki.language/languages/hy.js',
+ 'la' => 'resources/src/mediawiki.language/languages/la.js',
+ 'os' => 'resources/src/mediawiki.language/languages/os.js',
+ 'sl' => 'resources/src/mediawiki.language/languages/sl.js',
+ ],
+ 'dependencies' => [
+ 'mediawiki.language.data',
+ 'mediawiki.cldr',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'messages' => [
+ 'and',
+ 'comma-separator',
+ 'word-separator'
+ ],
+ ],
+
+ 'mediawiki.cldr' => [
+ 'scripts' => 'resources/src/mediawiki.language/mediawiki.cldr.js',
+ 'dependencies' => [
+ 'mediawiki.libs.pluralruleparser',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ 'mediawiki.libs.pluralruleparser' => [
+ 'scripts' => 'resources/src/mediawiki.libs/CLDRPluralRuleParser.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ 'mediawiki.language.init' => [
+ 'scripts' => 'resources/src/mediawiki.language/mediawiki.language.init.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ 'mediawiki.jqueryMsg' => [
+ // Add data for mediawiki.jqueryMsg, such as allowed tags
+ 'class' => 'ResourceLoaderJqueryMsgModule',
+ 'scripts' => 'resources/src/mediawiki/mediawiki.jqueryMsg.js',
+ 'dependencies' => [
+ 'mediawiki.util',
+ 'mediawiki.language',
+ 'user.options',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ 'mediawiki.language.months' => [
+ 'scripts' => 'resources/src/mediawiki.language/mediawiki.language.months.js',
+ 'dependencies' => 'mediawiki.language',
+ 'messages' => array_merge(
+ Language::$mMonthMsgs,
+ Language::$mMonthGenMsgs,
+ Language::$mMonthAbbrevMsgs
+ )
+ ],
+
+ 'mediawiki.language.names' => [ 'class' => 'ResourceLoaderLanguageNamesModule' ],
+
+ 'mediawiki.language.specialCharacters' => [
+ 'class' => 'ResourceLoaderSpecialCharacterDataModule'
+ ],
+
+ /* MediaWiki Libs */
+
+ 'mediawiki.libs.jpegmeta' => [
+ 'scripts' => 'resources/src/mediawiki.libs/mediawiki.libs.jpegmeta.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ /* MediaWiki Page */
+
+ 'mediawiki.page.gallery' => [
+ 'scripts' => 'resources/src/mediawiki/page/gallery.js',
+ 'dependencies' => [
+ 'mediawiki.page.gallery.styles',
+ 'jquery.throttle-debounce',
+ ]
+ ],
+ 'mediawiki.page.gallery.styles' => [
+ 'styles' => [
+ 'resources/src/mediawiki/page/gallery.print.css' => [ 'media' => 'print' ],
+ 'resources/src/mediawiki/page/gallery.css',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.page.gallery.slideshow' => [
+ 'scripts' => 'resources/src/mediawiki/page/gallery-slideshow.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'mediawiki.Title',
+ 'oojs',
+ 'oojs-ui-core',
+ 'oojs-ui-widgets',
+ 'oojs-ui.styles.icons-media',
+ 'oojs-ui.styles.icons-movement'
+ ],
+ 'messages' => [
+ 'gallery-slideshow-toggle'
+ ]
+ ],
+ 'mediawiki.page.ready' => [
+ 'scripts' => 'resources/src/mediawiki/page/ready.js',
+ 'dependencies' => [
+ 'jquery.accessKeyLabel',
+ 'jquery.checkboxShiftClick',
+ 'jquery.mw-jump',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.page.startup' => [
+ 'scripts' => 'resources/src/mediawiki/page/startup.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.page.patrol.ajax' => [
+ 'scripts' => 'resources/src/mediawiki/page/patrol.ajax.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'mediawiki.util',
+ 'mediawiki.Title',
+ 'mediawiki.notify',
+ 'jquery.spinner',
+ 'user.tokens'
+ ],
+ 'messages' => [
+ 'markedaspatrollednotify',
+ 'markedaspatrollederrornotify',
+ 'markedaspatrollederror-noautopatrol'
+ ],
+ ],
+ 'mediawiki.page.watch.ajax' => [
+ 'scripts' => 'resources/src/mediawiki/page/watch.js',
+ 'dependencies' => [
+ 'mediawiki.page.startup',
+ 'mediawiki.api.watch',
+ 'mediawiki.notify',
+ 'mediawiki.util',
+ 'mediawiki.Title',
+ 'mediawiki.jqueryMsg',
+ 'jquery.accessKeyLabel',
+ 'mediawiki.RegExp',
+ ],
+ 'messages' => [
+ 'watch',
+ 'unwatch',
+ 'watching',
+ 'unwatching',
+ 'tooltip-ca-watch',
+ 'tooltip-ca-unwatch',
+ 'watcherrortext',
+ 'addedwatchtext',
+ 'addedwatchtext-talk',
+ 'removedwatchtext',
+ 'removedwatchtext-talk',
+ ],
+ ],
+ 'mediawiki.page.rollback' => [
+ 'scripts' => 'resources/src/mediawiki/page/rollback.js',
+ 'dependencies' => [
+ 'mediawiki.api.rollback',
+ 'mediawiki.notify',
+ 'mediawiki.util',
+ 'jquery.spinner',
+ ],
+ 'messages' => [
+ 'rollbackfailed',
+ 'actioncomplete',
+ ],
+ ],
+ 'mediawiki.page.image.pagination' => [
+ 'scripts' => 'resources/src/mediawiki/page/image-pagination.js',
+ 'dependencies' => [
+ 'mediawiki.util',
+ 'jquery.spinner',
+ ],
+ ],
+
+ /* MediaWiki Special pages */
+
+ 'mediawiki.rcfilters.filters.base.styles' => [
+ 'styles' => [
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less',
+ ],
+ ],
+ 'mediawiki.rcfilters.highlightCircles.seenunseen.styles' => [
+ 'styles' => [
+ 'resources/src/mediawiki.rcfilters/' .
+ 'styles/mw.rcfilters.ui.ChangesListWrapperWidget.highlightCircles.seenunseen.less',
+ ],
+ ],
+ 'mediawiki.rcfilters.filters.dm' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.rcfilters/mw.rcfilters.js',
+ 'resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ItemModel.js',
+ 'resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js',
+ 'resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js',
+ 'resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js',
+ 'resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueryItemModel.js',
+ 'resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueriesModel.js',
+ 'resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js',
+ 'resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js',
+ 'resources/src/mediawiki.rcfilters/mw.rcfilters.UriProcessor.js',
+ ],
+ 'dependencies' => [
+ 'jquery.byteLength',
+ 'oojs',
+ 'mediawiki.api',
+ 'mediawiki.api.options',
+ 'mediawiki.Uri',
+ 'mediawiki.user',
+ ],
+ ],
+ 'mediawiki.rcfilters.filters.ui' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CheckboxInputWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ItemMenuOptionWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuOptionWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuSectionOptionWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.TagItemWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagItemWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuHeaderWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ViewSwitchWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ValuePickerWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesLimitPopupWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesLimitButtonWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DateButtonWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DatePopupWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SavedLinksListWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SavedLinksListItemWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SaveFiltersPopupButtonWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemHighlightButton.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.HighlightColorPickerWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.LiveUpdateButtonWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MarkSeenButtonWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.RcTopSectionWidget.js',
+ 'resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.WatchlistTopSectionWidget.js',
+ 'resources/src/mediawiki.rcfilters/mw.rcfilters.HighlightColors.js',
+ 'resources/src/mediawiki.rcfilters/mw.rcfilters.init.js',
+ ],
+ 'styles' => [
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.variables.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.Overlay.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterTagMultiselectWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ItemMenuOptionWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuOptionWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuSectionOptionWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.TagItemWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuHeaderWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ViewSwitchWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ValuePickerWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesLimitPopupWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.DatePopupWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.HighlightColorPickerWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemHighlightButton.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SavedLinksListWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SavedLinksListItemWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SaveFiltersPopupButtonWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.LiveUpdateButtonWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.RcTopSectionWidget.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.WatchlistTopSectionWidget.less',
+ ],
+ 'skinStyles' => [
+ 'monobook' => [
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.Overlay.monobook.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.CapsuleItemWidget.monobook.less',
+ 'resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuOptionWidget.monobook.less',
+ ],
+ ],
+ 'messages' => [
+ 'rcfilters-tag-remove',
+ 'rcfilters-activefilters',
+ 'rcfilters-advancedfilters',
+ 'rcfilters-group-results-by-page',
+ 'rcfilters-grouping-title',
+ 'rcfilters-limit-title',
+ 'rcfilters-limit-shownum',
+ 'rcfilters-days-title',
+ 'rcfilters-hours-title',
+ 'rcfilters-days-show-days',
+ 'rcfilters-days-show-hours',
+ 'rcfilters-highlighted-filters-list',
+ 'rcfilters-quickfilters',
+ 'rcfilters-quickfilters-placeholder-title',
+ 'rcfilters-quickfilters-placeholder-description',
+ 'rcfilters-savedqueries-defaultlabel',
+ 'rcfilters-savedqueries-rename',
+ 'rcfilters-savedqueries-setdefault',
+ 'rcfilters-savedqueries-unsetdefault',
+ 'rcfilters-savedqueries-remove',
+ 'rcfilters-savedqueries-new-name-label',
+ 'rcfilters-savedqueries-new-name-placeholder',
+ 'rcfilters-savedqueries-add-new-title',
+ 'rcfilters-savedqueries-apply-label',
+ 'rcfilters-savedqueries-apply-and-setdefault-label',
+ 'rcfilters-savedqueries-cancel-label',
+ 'rcfilters-restore-default-filters',
+ 'rcfilters-clear-all-filters',
+ 'rcfilters-show-new-changes',
+ 'rcfilters-search-placeholder',
+ 'rcfilters-invalid-filter',
+ 'rcfilters-empty-filter',
+ 'rcfilters-filterlist-title',
+ 'rcfilters-filterlist-feedbacklink',
+ 'rcfilters-filterlist-noresults',
+ 'rcfilters-filterlist-whatsthis',
+ 'rcfilters-highlightbutton-title',
+ 'rcfilters-highlightmenu-title',
+ 'rcfilters-highlightmenu-help',
+ 'rcfilters-noresults-conflict',
+ 'rcfilters-state-message-subset',
+ 'rcfilters-state-message-fullcoverage',
+ 'rcfilters-filter-excluded',
+ 'rcfilters-tag-prefix-namespace',
+ 'rcfilters-tag-prefix-namespace-inverted',
+ 'rcfilters-tag-prefix-tags',
+ 'rcfilters-exclude-button-off',
+ 'rcfilters-exclude-button-on',
+ 'rcfilters-view-advanced-filters-label',
+ 'rcfilters-view-tags',
+ 'rcfilters-view-namespaces-tooltip',
+ 'rcfilters-view-tags-tooltip',
+ 'rcfilters-view-return-to-default-tooltip',
+ 'rcfilters-liveupdates-button',
+ 'rcfilters-liveupdates-button-title-on',
+ 'rcfilters-liveupdates-button-title-off',
+ 'rcfilters-watchlist-markseen-button',
+ 'rcfilters-watchlist-edit-watchlist-button',
+ 'rcfilters-other-review-tools',
+ 'blanknamespace',
+ 'namespaces',
+ 'invert',
+ 'recentchanges-noresult',
+ 'quotation-marks',
+ ],
+ 'dependencies' => [
+ 'oojs-ui',
+ 'jquery.makeCollapsible',
+ 'mediawiki.language',
+ 'mediawiki.user',
+ 'mediawiki.rcfilters.filters.dm',
+ 'oojs-ui.styles.icons-content',
+ 'oojs-ui.styles.icons-moderation',
+ 'oojs-ui.styles.icons-editing-core',
+ 'oojs-ui.styles.icons-editing-styling',
+ 'oojs-ui.styles.icons-interactions',
+ 'oojs-ui.styles.icons-content',
+ 'oojs-ui.styles.icons-layout',
+ 'oojs-ui.styles.icons-media',
+ ],
+ ],
+ 'mediawiki.special' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.css',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.special.apisandbox.styles' => [
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.apisandbox.top.css',
+ ],
+ 'mediawiki.special.apisandbox' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.apisandbox.css',
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.apisandbox.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'mediawiki.jqueryMsg',
+ 'mediawiki.util',
+ 'oojs-ui',
+ 'oojs-ui.styles.icons-content',
+ 'oojs-ui.styles.icons-editing-advanced',
+ 'oojs-ui.styles.icons-interactions',
+ 'oojs-ui.styles.icons-moderation',
+ 'mediawiki.widgets.datetime',
+ 'jquery.makeCollapsible',
+ ],
+ 'messages' => [
+ 'apisandbox-intro',
+ 'apisandbox-submit',
+ 'apisandbox-reset',
+ 'apisandbox-fullscreen',
+ 'apisandbox-fullscreen-tooltip',
+ 'apisandbox-unfullscreen',
+ 'apisandbox-unfullscreen-tooltip',
+ 'apisandbox-retry',
+ 'apisandbox-loading',
+ 'apisandbox-load-error',
+ 'apisandbox-fetch-token',
+ 'apisandbox-helpurls',
+ 'apisandbox-examples',
+ 'apisandbox-dynamic-parameters',
+ 'apisandbox-dynamic-parameters-add-label',
+ 'apisandbox-dynamic-parameters-add-placeholder',
+ 'apisandbox-dynamic-error-exists',
+ 'apisandbox-deprecated-parameters',
+ 'apisandbox-no-parameters',
+ 'api-help-param-limit',
+ 'api-help-param-limit2',
+ 'api-help-param-integer-min',
+ 'api-help-param-integer-max',
+ 'api-help-param-integer-minmax',
+ 'api-help-param-multi-separate',
+ 'api-help-param-multi-max',
+ 'apisandbox-submit-invalid-fields-title',
+ 'apisandbox-submit-invalid-fields-message',
+ 'apisandbox-results',
+ 'apisandbox-sending-request',
+ 'apisandbox-loading-results',
+ 'apisandbox-results-error',
+ 'apisandbox-results-login-suppressed',
+ 'apisandbox-request-selectformat-label',
+ 'apisandbox-request-format-url-label',
+ 'apisandbox-request-url-label',
+ 'apisandbox-request-format-json-label',
+ 'apisandbox-request-json-label',
+ 'apisandbox-request-time',
+ 'apisandbox-results-fixtoken',
+ 'apisandbox-results-fixtoken-fail',
+ 'apisandbox-alert-page',
+ 'apisandbox-alert-field',
+ 'apisandbox-continue',
+ 'apisandbox-continue-clear',
+ 'apisandbox-continue-help',
+ 'apisandbox-param-limit',
+ 'apisandbox-multivalue-all-namespaces',
+ 'apisandbox-multivalue-all-values',
+ 'api-format-prettyprint-status',
+ 'blanknamespace',
+ ],
+ ],
+ 'mediawiki.special.block' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.block.js',
+ 'dependencies' => [
+ 'mediawiki.util',
+ 'mediawiki.htmlform',
+ ],
+ ],
+ 'mediawiki.special.changecredentials.js' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changecredentials.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'mediawiki.htmlform.ooui'
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.special.changeslist' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.css',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.special.changeslist.enhanced' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css',
+ ],
+ 'mediawiki.special.changeslist.legend' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.special.changeslist.legend.js' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.legend.js',
+ 'dependencies' => [
+ 'jquery.makeCollapsible',
+ 'mediawiki.cookie',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.special.changeslist.visitedstatus' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.changeslist.visitedstatus.js',
+ ],
+ 'mediawiki.special.comparepages.styles' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less',
+ ],
+ 'mediawiki.special.contributions' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.contributions.js',
+ 'dependencies' => [
+ 'mediawiki.widgets.DateInputWidget',
+ 'mediawiki.jqueryMsg',
+ ]
+ ],
+ 'mediawiki.special.edittags' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.edittags.js',
+ 'dependencies' => [
+ 'jquery.chosen',
+ ],
+ 'messages' => [
+ 'tags-edit-chosen-placeholder',
+ 'tags-edit-chosen-no-results',
+ ],
+ ],
+ 'mediawiki.special.edittags.styles' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.edittags.css',
+ ],
+ 'mediawiki.special.import' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.import.js',
+ ],
+ 'mediawiki.special.movePage' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.movePage.js',
+ 'dependencies' => [
+ 'mediawiki.widgets.visibleByteLimit',
+ 'mediawiki.widgets',
+ ],
+ ],
+ 'mediawiki.special.movePage.styles' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.movePage.css',
+ ],
+ 'mediawiki.special.pageLanguage' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.pageLanguage.js',
+ 'dependencies' => [
+ 'oojs-ui-core',
+ ],
+ ],
+ 'mediawiki.special.pagesWithProp' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css',
+ ],
+ 'mediawiki.special.preferences' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js',
+ 'resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js',
+ 'resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js',
+ 'resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js',
+ ],
+ 'messages' => [
+ 'prefs-tabs-navigation-hint',
+ 'prefswarning-warning',
+ 'saveprefs',
+ 'savedprefs',
+ ],
+ 'dependencies' => [
+ 'mediawiki.language',
+ 'mediawiki.confirmCloseWindow',
+ 'mediawiki.notification.convertmessagebox',
+ ],
+ ],
+ 'mediawiki.special.preferences.styles' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.preferences.styles.css',
+ ],
+ 'mediawiki.special.recentchanges' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.recentchanges.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.special.search' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.search.js',
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.search.css',
+ 'dependencies' => 'mediawiki.widgets.SearchInputWidget',
+ 'messages' => [
+ 'powersearch-togglelabel',
+ 'powersearch-toggleall',
+ 'powersearch-togglenone',
+ ],
+ ],
+ 'mediawiki.special.search.commonsInterwikiWidget' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.search.commonsInterwikiWidget.js',
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'mediawiki.Uri',
+ 'mediawiki.jqueryMsg'
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'messages' => [
+ 'search-interwiki-more-results',
+ 'searchprofile-images'
+ ],
+ ],
+ 'mediawiki.special.search.interwikiwidget.styles' => [
+ 'styles' => 'resources/src/mediawiki.special/'
+ . 'mediawiki.special.search.interwikiwidget.styles.less',
+ 'targets' => [ 'desktop', 'mobile' ]
+ ],
+ 'mediawiki.special.search.styles' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.search.styles.css',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.special.undelete' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.undelete.js',
+ ],
+ 'mediawiki.special.unwatchedPages' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.unwatchedPages.js',
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.unwatchedPages.css',
+ 'messages' => [
+ 'addedwatchtext-short',
+ 'removedwatchtext-short',
+ 'unwatch',
+ 'unwatching',
+ 'watch',
+ 'watcherrortext',
+ 'watching',
+ ],
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'mediawiki.api.watch',
+ 'mediawiki.notify',
+ 'mediawiki.Title',
+ 'mediawiki.util',
+ ],
+ ],
+ 'mediawiki.special.upload' => [
+ 'templates' => [
+ 'thumbnail.html' => 'resources/src/mediawiki.special/templates/thumbnail.html',
+ ],
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.upload.js',
+ 'messages' => [
+ 'widthheight',
+ 'size-bytes',
+ 'size-kilobytes',
+ 'size-megabytes',
+ 'size-gigabytes',
+ 'largefileserver',
+ 'editwarning-warning',
+ // editwarning-warning uses {{int:prefs-editing}}
+ 'prefs-editing',
+ ],
+ 'dependencies' => [
+ 'mediawiki.special.upload.styles',
+ 'jquery.spinner',
+ 'mediawiki.jqueryMsg',
+ 'mediawiki.api',
+ 'mediawiki.libs.jpegmeta',
+ 'mediawiki.Title',
+ 'mediawiki.util',
+ 'mediawiki.confirmCloseWindow',
+ 'user.options',
+ ],
+ ],
+ 'mediawiki.special.upload.styles' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.upload.styles.css',
+ ],
+ 'mediawiki.special.userlogin.common.styles' => [
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'skinStyles' => [
+ 'default' => 'resources/src/mediawiki.special/mediawiki.special.userlogin.common.css',
+ ],
+ ],
+ 'mediawiki.special.userlogin.login.styles' => [
+ 'styles' => [
+ 'resources/src/mediawiki.special/mediawiki.special.userlogin.login.css',
+ ],
+ ],
+ 'mediawiki.special.userlogin.signup.js' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js',
+ 'messages' => [
+ 'createacct-emailrequired',
+ 'noname',
+ 'userexists',
+ ],
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'mediawiki.jqueryMsg',
+ 'jquery.throttle-debounce',
+ 'mediawiki.htmlform.checker',
+ ],
+ ],
+ 'mediawiki.special.userlogin.signup.styles' => [
+ 'styles' => [
+ 'resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css',
+ ],
+ ],
+ 'mediawiki.special.userrights' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.userrights.css',
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.userrights.js',
+ 'dependencies' => [
+ 'mediawiki.notification.convertmessagebox',
+ ],
+ ],
+ 'mediawiki.special.watchlist' => [
+ 'scripts' => 'resources/src/mediawiki.special/mediawiki.special.watchlist.js',
+ 'messages' => [
+ 'addedwatchtext',
+ 'addedwatchtext-talk',
+ 'removedwatchtext',
+ 'removedwatchtext-talk',
+ 'tooltip-ca-watch',
+ 'tooltip-ca-unwatch',
+ 'watchlist-unwatch',
+ 'watchlist-unwatch-undo',
+ ],
+ 'dependencies' => [
+ 'mediawiki.api.watch',
+ 'mediawiki.jqueryMsg',
+ 'mediawiki.Title',
+ 'mediawiki.util',
+ 'oojs-ui-core',
+ 'user.options',
+ ],
+ ],
+ 'mediawiki.special.watchlist.styles' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.watchlist.css',
+ ],
+ 'mediawiki.special.version' => [
+ 'styles' => 'resources/src/mediawiki.special/mediawiki.special.version.css',
+ ],
+
+ /* MediaWiki Installer */
+
+ // Used in the web installer. Test it after modifying this definition!
+ 'mediawiki.legacy.config' => [
+ // These files are not actually loaded via ResourceLoader, so dependencies etc. won't work.
+ 'scripts' => 'mw-config/config.js',
+ 'styles' => 'mw-config/config.css',
+ ],
+
+ /* MediaWiki Legacy */
+
+ 'mediawiki.legacy.commonPrint' => [
+ 'styles' => [
+ 'resources/src/mediawiki.legacy/commonPrint.css' => [ 'media' => 'print' ]
+ ],
+ ],
+ 'mediawiki.legacy.protect' => [
+ 'scripts' => 'resources/src/mediawiki.legacy/protect.js',
+ 'dependencies' => 'jquery.byteLimit',
+ 'messages' => [ 'protect-unchain-permissions' ]
+ ],
+ // Used in the web installer. Test it after modifying this definition!
+ 'mediawiki.legacy.shared' => [
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'styles' => [
+ 'resources/src/mediawiki.legacy/shared.css' => [ 'media' => 'screen' ]
+ ],
+ ],
+ 'mediawiki.legacy.oldshared' => [
+ 'styles' => [
+ 'resources/src/mediawiki.legacy/oldshared.css' => [ 'media' => 'screen' ]
+ ],
+ ],
+ 'mediawiki.legacy.wikibits' => [
+ 'scripts' => 'resources/src/mediawiki.legacy/wikibits.js',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ /* MediaWiki UI */
+
+ 'mediawiki.ui' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.ui/default.less',
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.ui.checkbox' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.ui/components/checkbox.less',
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.ui.radio' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.ui/components/radio.less',
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ // Lightweight module for anchor styles
+ 'mediawiki.ui.anchor' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.ui/components/anchors.less',
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ // Lightweight module for button styles
+ 'mediawiki.ui.button' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.ui/components/buttons.less',
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.ui.input' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.ui/components/inputs.less',
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.ui.icon' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.ui/components/icons.less',
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ // Lightweight module for text styles
+ 'mediawiki.ui.text' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.ui/components/text.less',
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ 'mediawiki.widgets' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.NamespaceInputWidget.js',
+ 'resources/src/mediawiki.widgets/mw.widgets.ComplexNamespaceInputWidget.js',
+ 'resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js',
+ 'resources/src/mediawiki.widgets/mw.widgets.TitleInputWidget.js',
+ 'resources/src/mediawiki.widgets/mw.widgets.TitleSearchWidget.js',
+ 'resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.js',
+ 'resources/src/mediawiki.widgets/mw.widgets.TitleOptionWidget.js',
+ ],
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.TitleWidget.less',
+ ],
+ ],
+ 'dependencies' => [
+ 'oojs-ui-widgets',
+ 'mediawiki.widgets.styles',
+ // TitleInputWidget
+ 'mediawiki.Title',
+ 'mediawiki.api',
+ 'jquery.byteLimit',
+ // TitleOptionWidget
+ 'jquery.highlightText',
+ ],
+ 'messages' => [
+ // NamespaceInputWidget
+ 'blanknamespace',
+ 'namespacesall',
+ // TitleInputWidget
+ 'mw-widgets-titleinput-description-new-page',
+ 'mw-widgets-titleinput-description-redirect',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.styles' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.ComplexNamespaceInputWidget.base.css',
+ 'resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.base.css',
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.DateInputWidget' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.js',
+ 'resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js',
+ ],
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less',
+ 'resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.less',
+ ],
+ ],
+ 'messages' => [
+ 'mw-widgets-dateinput-no-date',
+ 'mw-widgets-dateinput-placeholder-day',
+ 'mw-widgets-dateinput-placeholder-month',
+ ],
+ 'dependencies' => [
+ 'oojs-ui-widgets',
+ 'oojs-ui.styles.icons-movement',
+ 'moment',
+ 'mediawiki.widgets.DateInputWidget.styles',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.DateInputWidget.styles' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.styles.less',
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.visibleByteLimit' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.widgets.visibleByteLimit/mediawiki.widgets.visibleByteLimit.js'
+ ],
+ 'dependencies' => [
+ 'oojs-ui-core',
+ 'jquery.byteLimit'
+ ],
+ 'targets' => [ 'desktop', 'mobile' ]
+ ],
+ 'mediawiki.widgets.datetime' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.js',
+ 'resources/src/mediawiki.widgets.datetime/CalendarWidget.js',
+ 'resources/src/mediawiki.widgets.datetime/DateTimeFormatter.js',
+ 'resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js',
+ 'resources/src/mediawiki.widgets.datetime/ProlepticGregorianDateTimeFormatter.js',
+ ],
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.widgets.datetime/CalendarWidget.less',
+ 'resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.less',
+ ],
+ ],
+ 'messages' => [
+ 'timezone-utc',
+ 'timezone-local',
+ 'january',
+ 'february',
+ 'march',
+ 'april',
+ 'may_long',
+ 'june',
+ 'july',
+ 'august',
+ 'september',
+ 'october',
+ 'november',
+ 'december',
+ 'jan',
+ 'feb',
+ 'mar',
+ 'apr',
+ 'may',
+ 'jun',
+ 'jul',
+ 'aug',
+ 'sep',
+ 'oct',
+ 'nov',
+ 'dec',
+ 'sunday',
+ 'monday',
+ 'tuesday',
+ 'wednesday',
+ 'thursday',
+ 'friday',
+ 'saturday',
+ 'sun',
+ 'mon',
+ 'tue',
+ 'wed',
+ 'thu',
+ 'fri',
+ 'sat',
+ 'period-am',
+ 'period-pm',
+ ],
+ 'dependencies' => [
+ 'oojs-ui-core',
+ 'oojs-ui.styles.icons-moderation',
+ 'oojs-ui.styles.icons-movement',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.CategorySelector' => [
+ 'deprecated' => 'Use "mw.widgets.CategoryMultiselectWidget" instead. See T161285.',
+ 'dependencies' => [
+ 'mediawiki.widgets.CategoryMultiselectWidget',
+ ],
+ ],
+ 'mediawiki.widgets.CategoryMultiselectWidget' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js',
+ 'resources/src/mediawiki.widgets/mw.widgets.CategoryMultiselectWidget.js',
+ ],
+ 'dependencies' => [
+ 'oojs-ui-widgets',
+ 'mediawiki.api',
+ 'mediawiki.ForeignApi',
+ 'mediawiki.Title',
+ ],
+ 'messages' => [
+ 'red-link-title',
+ 'mw-widgets-categoryselector-add-category-placeholder',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.SelectWithInputWidget' => [
+ 'scripts' => 'resources/src/mediawiki.widgets/mw.widgets.SelectWithInputWidget.js',
+ 'dependencies' => [
+ 'mediawiki.widgets.SelectWithInputWidget.styles',
+ 'oojs-ui-widgets',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.SelectWithInputWidget.styles' => [
+ 'styles' => 'resources/src/mediawiki.widgets/mw.widgets.SelectWithInputWidget.base.css',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.MediaSearch' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsProvider.js',
+ 'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsQueue.js',
+ 'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceProvider.js',
+ 'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchProvider.js',
+ 'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceQueue.js',
+ 'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchQueue.js',
+ 'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.js',
+ 'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.js',
+ ],
+ 'styles' => [
+ 'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.css',
+ 'resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.css',
+ ],
+ 'dependencies' => [
+ 'oojs-ui-widgets',
+ 'mediawiki.ForeignApi',
+ 'mediawiki.Title',
+ 'mediawiki.util',
+ ],
+ 'messages' => [
+ 'mw-widgets-mediasearch-noresults',
+ 'mw-widgets-mediasearch-input-placeholder',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.UserInputWidget' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.UserInputWidget.js',
+ ],
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'oojs-ui-widgets',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.UsersMultiselectWidget' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.UsersMultiselectWidget.js',
+ ],
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'oojs-ui-widgets',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.SearchInputWidget' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js',
+ ],
+ 'dependencies' => [
+ 'mediawiki.searchSuggest',
+ 'oojs-ui.styles.icons-interactions',
+ // FIXME: Needs TitleInputWidget only
+ 'mediawiki.widgets',
+ ],
+ ],
+ 'mediawiki.widgets.SearchInputWidget.styles' => [
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.css',
+ ],
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ 'mediawiki.widgets.StashedFileWidget' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.js',
+ ],
+ 'skinStyles' => [
+ 'default' => [
+ 'resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.less',
+ ],
+ ],
+ 'dependencies' => [
+ 'mediawiki.api',
+ 'oojs-ui-core',
+ ],
+ ],
+
+ /* es5-shim */
+ 'es5-shim' => [
+ 'deprecated' => 'Use of the "es5-shim" module is deprecated since MediaWiki 1.29.0',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ /* dom-level2-shim */
+ 'dom-level2-shim' => [
+ 'deprecated' => 'Use of the "dom-level2-shim" module is deprecated since MediaWiki 1.29.0',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ /* OOjs */
+ 'oojs' => [
+ 'scripts' => [
+ 'resources/lib/oojs/oojs.jquery.js',
+ 'resources/src/oojs-global.js',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ 'mediawiki.router' => [
+ 'scripts' => [
+ 'resources/src/mediawiki.router/index.js',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'dependencies' => [
+ 'oojs-router',
+ ],
+ ],
+
+ 'oojs-router' => [
+ 'scripts' => [
+ 'resources/lib/oojs-router/oojs-router.js',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ 'dependencies' => [
+ 'oojs',
+ ],
+ ],
+
+ /* OOjs UI */
+
+ // Omnibus module.
+ 'oojs-ui' => [
+ 'dependencies' => [
+ 'oojs-ui-core',
+ 'oojs-ui-widgets',
+ 'oojs-ui-toolbars',
+ 'oojs-ui-windows',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ // The core JavaScript library.
+ 'oojs-ui-core' => [
+ 'class' => 'ResourceLoaderOOUIFileModule',
+ 'scripts' => [
+ 'resources/lib/oojs-ui/oojs-ui-core.js',
+ 'resources/src/oojs-ui-local.js',
+ ],
+ 'themeScripts' => 'core',
+ 'dependencies' => [
+ 'oojs',
+ 'oojs-ui-core.styles',
+ 'oojs-ui.styles.indicators',
+ 'oojs-ui.styles.textures',
+ 'mediawiki.language',
+ 'oojs-ui.styles.icons-content',
+ 'oojs-ui.styles.icons-alerts',
+ 'oojs-ui.styles.icons-interactions',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ // This contains only the styles required by core widgets.
+ 'oojs-ui-core.styles' => [
+ 'class' => 'ResourceLoaderOOUIFileModule',
+ 'styles' => [
+ 'resources/lib/oojs-ui/wikimedia-ui-base.less', // Providing Wikimedia UI LESS variables to all
+ 'resources/src/oojs-ui-local.css', // HACK, see inside the file
+ ],
+ 'themeStyles' => 'core',
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ // Additional widgets and layouts module.
+ 'oojs-ui-widgets' => [
+ 'class' => 'ResourceLoaderOOUIFileModule',
+ 'scripts' => 'resources/lib/oojs-ui/oojs-ui-widgets.js',
+ 'themeStyles' => 'widgets',
+ 'dependencies' => [
+ 'oojs-ui-core',
+ 'oojs-ui.styles.icons-interactions',
+ 'oojs-ui.styles.icons-content',
+ 'oojs-ui.styles.icons-editing-advanced',
+ 'oojs-ui.styles.icons-movement',
+ 'oojs-ui.styles.icons-moderation',
+ ],
+ 'messages' => [
+ 'ooui-outline-control-move-down',
+ 'ooui-outline-control-move-up',
+ 'ooui-outline-control-remove',
+ 'ooui-selectfile-button-select',
+ 'ooui-selectfile-dragdrop-placeholder',
+ 'ooui-selectfile-not-supported',
+ 'ooui-selectfile-placeholder',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ // Toolbar and tools module.
+ 'oojs-ui-toolbars' => [
+ 'class' => 'ResourceLoaderOOUIFileModule',
+ 'scripts' => 'resources/lib/oojs-ui/oojs-ui-toolbars.js',
+ 'themeStyles' => 'toolbars',
+ 'dependencies' => [
+ 'oojs-ui-core',
+ 'oojs-ui.styles.icons-movement',
+ ],
+ 'messages' => [
+ 'ooui-toolbar-more',
+ 'ooui-toolgroup-collapse',
+ 'ooui-toolgroup-expand',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+ // Windows and dialogs module.
+ 'oojs-ui-windows' => [
+ 'class' => 'ResourceLoaderOOUIFileModule',
+ 'scripts' => 'resources/lib/oojs-ui/oojs-ui-windows.js',
+ 'themeStyles' => 'windows',
+ 'dependencies' => [
+ 'oojs-ui-core',
+ 'oojs-ui.styles.icons-movement',
+ ],
+ 'messages' => [
+ 'ooui-dialog-message-accept',
+ 'ooui-dialog-message-reject',
+ 'ooui-dialog-process-continue',
+ 'ooui-dialog-process-dismiss',
+ 'ooui-dialog-process-error',
+ 'ooui-dialog-process-retry',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ],
+
+ 'oojs-ui.styles.indicators' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'indicators',
+ ],
+ 'oojs-ui.styles.textures' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'textures',
+ ],
+ 'oojs-ui.styles.icons-accessibility' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-accessibility',
+ ],
+ 'oojs-ui.styles.icons-alerts' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-alerts',
+ ],
+ 'oojs-ui.styles.icons-content' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-content',
+ ],
+ 'oojs-ui.styles.icons-editing-advanced' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-editing-advanced',
+ ],
+ 'oojs-ui.styles.icons-editing-core' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-editing-core',
+ ],
+ 'oojs-ui.styles.icons-editing-list' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-editing-list',
+ ],
+ 'oojs-ui.styles.icons-editing-styling' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-editing-styling',
+ ],
+ 'oojs-ui.styles.icons-interactions' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-interactions',
+ ],
+ 'oojs-ui.styles.icons-layout' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-layout',
+ ],
+ 'oojs-ui.styles.icons-location' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-location',
+ ],
+ 'oojs-ui.styles.icons-media' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-media',
+ ],
+ 'oojs-ui.styles.icons-moderation' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-moderation',
+ ],
+ 'oojs-ui.styles.icons-movement' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-movement',
+ ],
+ 'oojs-ui.styles.icons-user' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-user',
+ ],
+ 'oojs-ui.styles.icons-wikimedia' => [
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'themeImages' => 'icons-wikimedia',
+ ],
+];
diff --git a/www/wiki/resources/ResourcesOOUI.php b/www/wiki/resources/ResourcesOOUI.php
new file mode 100644
index 00000000..b2e2bd4d
--- /dev/null
+++ b/www/wiki/resources/ResourcesOOUI.php
@@ -0,0 +1,182 @@
+<?php
+/**
+ * Definition of OOjs UI ResourceLoader modules.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ * @file
+ */
+
+if ( !defined( 'MEDIAWIKI' ) ) {
+ die( 'Not an entry point.' );
+}
+
+// WARNING: OOjs-UI is NOT TESTED with older browsers and is likely to break
+// if loaded in browsers that don't support ES5
+return call_user_func( function () {
+ $themes = ExtensionRegistry::getInstance()->getAttribute( 'SkinOOUIThemes' );
+ // We only use the theme names for file names, and they are lowercase
+ $themes = array_map( 'strtolower', $themes );
+ $themes['default'] = 'mediawiki';
+
+ // Helper function to generate paths to files used in 'skinStyles' and 'skinScripts'.
+ $getSkinSpecific = function ( $module, $ext = 'css' ) use ( $themes ) {
+ return array_combine(
+ array_keys( $themes ),
+ array_map( function ( $theme ) use ( $module, $ext ) {
+ $module = $module ? "$module-" : '';
+ // TODO Allow extensions to specify this path somehow
+ return "resources/lib/oojs-ui/oojs-ui-$module$theme.$ext";
+ }, array_values( $themes ) )
+ );
+ };
+
+ $modules = [];
+
+ // Omnibus module.
+ $modules['oojs-ui'] = [
+ 'dependencies' => [
+ 'oojs-ui-core',
+ 'oojs-ui-widgets',
+ 'oojs-ui-toolbars',
+ 'oojs-ui-windows',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ];
+
+ // The core JavaScript library.
+ $modules['oojs-ui-core'] = [
+ 'scripts' => [
+ 'resources/lib/oojs-ui/oojs-ui-core.js',
+ 'resources/src/oojs-ui-local.js',
+ ],
+ 'skinScripts' => $getSkinSpecific( null, 'js' ),
+ 'dependencies' => [
+ 'es5-shim',
+ 'oojs',
+ 'oojs-ui-core.styles',
+ 'mediawiki.language',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ];
+ // This contains only the styles required by core widgets.
+ $modules['oojs-ui-core.styles'] = [
+ 'position' => 'top',
+ 'styles' => 'resources/src/oojs-ui-local.css', // HACK, see inside the file
+ 'skinStyles' => $getSkinSpecific( 'core' ),
+ 'targets' => [ 'desktop', 'mobile' ],
+ // ResourceLoaderImageModule doesn't support 'skipFunction', so instead we set this up so that
+ // this module is skipped together with its dependencies. Nothing else depends on these modules.
+ 'dependencies' => [
+ 'oojs-ui.styles.icons',
+ 'oojs-ui.styles.indicators',
+ 'oojs-ui.styles.textures',
+ ],
+ 'skipFunction' => 'resources/src/oojs-ui-styles-skip.js',
+ ];
+
+ // Deprecated old name for the module 'oojs-ui-core.styles'.
+ $modules['oojs-ui.styles'] = $modules['oojs-ui-core.styles'];
+
+ // Additional widgets and layouts module.
+ $modules['oojs-ui-widgets'] = [
+ 'scripts' => 'resources/lib/oojs-ui/oojs-ui-widgets.js',
+ 'skinStyles' => $getSkinSpecific( 'widgets' ),
+ 'dependencies' => 'oojs-ui-core',
+ 'messages' => [
+ 'ooui-outline-control-move-down',
+ 'ooui-outline-control-move-up',
+ 'ooui-outline-control-remove',
+ 'ooui-selectfile-button-select',
+ 'ooui-selectfile-dragdrop-placeholder',
+ 'ooui-selectfile-not-supported',
+ 'ooui-selectfile-placeholder',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ];
+ // Toolbar and tools module.
+ $modules['oojs-ui-toolbars'] = [
+ 'scripts' => 'resources/lib/oojs-ui/oojs-ui-toolbars.js',
+ 'skinStyles' => $getSkinSpecific( 'toolbars' ),
+ 'dependencies' => 'oojs-ui-core',
+ 'messages' => [
+ 'ooui-toolbar-more',
+ 'ooui-toolgroup-collapse',
+ 'ooui-toolgroup-expand',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ];
+ // Windows and dialogs module.
+ $modules['oojs-ui-windows'] = [
+ 'scripts' => 'resources/lib/oojs-ui/oojs-ui-windows.js',
+ 'skinStyles' => $getSkinSpecific( 'windows' ),
+ 'dependencies' => 'oojs-ui-core',
+ 'messages' => [
+ 'ooui-dialog-message-accept',
+ 'ooui-dialog-message-reject',
+ 'ooui-dialog-process-continue',
+ 'ooui-dialog-process-dismiss',
+ 'ooui-dialog-process-error',
+ 'ooui-dialog-process-retry',
+ ],
+ 'targets' => [ 'desktop', 'mobile' ],
+ ];
+
+ $imageSets = [
+ // Comments for greppability
+ 'icons', // oojs-ui.styles.icons
+ 'indicators', // oojs-ui.styles.indicators
+ 'textures', // oojs-ui.styles.textures
+ 'icons-accessibility', // oojs-ui.styles.icons-accessibility
+ 'icons-alerts', // oojs-ui.styles.icons-alerts
+ 'icons-content', // oojs-ui.styles.icons-content
+ 'icons-editing-advanced', // oojs-ui.styles.icons-editing-advanced
+ 'icons-editing-core', // oojs-ui.styles.icons-editing-core
+ 'icons-editing-list', // oojs-ui.styles.icons-editing-list
+ 'icons-editing-styling', // oojs-ui.styles.icons-editing-styling
+ 'icons-interactions', // oojs-ui.styles.icons-interactions
+ 'icons-layout', // oojs-ui.styles.icons-layout
+ 'icons-location', // oojs-ui.styles.icons-location
+ 'icons-media', // oojs-ui.styles.icons-media
+ 'icons-moderation', // oojs-ui.styles.icons-moderation
+ 'icons-movement', // oojs-ui.styles.icons-movement
+ 'icons-user', // oojs-ui.styles.icons-user
+ 'icons-wikimedia', // oojs-ui.styles.icons-wikimedia
+ ];
+ $rootPath = 'resources/lib/oojs-ui/themes';
+
+ foreach ( $imageSets as $name ) {
+ $module = [
+ 'position' => 'top',
+ 'class' => 'ResourceLoaderOOUIImageModule',
+ 'name' => $name,
+ 'rootPath' => $rootPath,
+ ];
+
+ if ( substr( $name, 0, 5 ) === 'icons' ) {
+ $module['selectorWithoutVariant'] = '.oo-ui-icon-{name}, .mw-ui-icon-{name}:before';
+ $module['selectorWithVariant'] = '
+ .oo-ui-image-{variant}.oo-ui-icon-{name}, .mw-ui-icon-{name}-{variant}:before,
+ /* Hack for Flow, see T110051 */
+ .mw-ui-hovericon:hover .mw-ui-icon-{name}-{variant}-hover:before,
+ .mw-ui-hovericon.mw-ui-icon-{name}-{variant}-hover:hover:before';
+ }
+
+ $modules["oojs-ui.styles.$name"] = $module;
+ }
+
+ return $modules;
+} );
diff --git a/www/wiki/resources/assets/file-type-icons/COPYING b/www/wiki/resources/assets/file-type-icons/COPYING
new file mode 100644
index 00000000..19a775a8
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/COPYING
@@ -0,0 +1,43 @@
+The icons used here are derived from the crystalsvg icons in the
+pics/crystalsvg/ directory of kdelibs-3.4.0 they were modified on 2005-05-15
+by Ævar Arnfjörð Bjarmason for use in MediaWiki.
+
+What follows is the contents of the LICENSE.crystalsvg file found in the pics/
+subdirectory of kdelibs-3.4.0:
+
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+This copyright and license notice covers all CrystalSVG images.
+Note the license notice contains an add-on.
+********************************************************************************
+KDE Crystal theme icons.
+Copyright (C) 2002 and following years KDE Artists
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation,
+version 2.1 of the License.
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+ **** NOTE THIS ADD-ON ****
+The GNU Lesser General Public License or LGPL is written for software libraries
+in the first place. We expressly want the LGPL to be valid for this artwork
+library too.
+KDE Crystal theme icons is a special kind of software library, it is an
+artwork library, it's elements can be used in a Graphical User Interface, or
+GUI.
+Source code, for this library means:
+ - for vectors svg;
+ - for pixels, if applicable, the multi-layered formats xcf or psd, or
+otherwise png.
+The LGPL in some sections obliges you to make the files carry
+notices. With images this is in some cases impossible or hardly useful.
+With this library a notice is placed at a prominent place in the directory
+containing the elements. You may follow this practice.
+The exception in section 6 of the GNU Lesser General Public License covers
+the use of elements of this art library in a GUI.
+kde-artists [at] kde.org
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-c.png b/www/wiki/resources/assets/file-type-icons/fileicon-c.png
new file mode 100644
index 00000000..0d603b70
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-c.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-cpp.png b/www/wiki/resources/assets/file-type-icons/fileicon-cpp.png
new file mode 100644
index 00000000..123688f0
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-cpp.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-deb.png b/www/wiki/resources/assets/file-type-icons/fileicon-deb.png
new file mode 100644
index 00000000..8e07a236
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-deb.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-djvu.png b/www/wiki/resources/assets/file-type-icons/fileicon-djvu.png
new file mode 100644
index 00000000..66199129
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-djvu.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-djvu.xcf b/www/wiki/resources/assets/file-type-icons/fileicon-djvu.xcf
new file mode 100644
index 00000000..8043dcdb
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-djvu.xcf
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-dvi.png b/www/wiki/resources/assets/file-type-icons/fileicon-dvi.png
new file mode 100644
index 00000000..e7b828ae
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-dvi.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-exe.png b/www/wiki/resources/assets/file-type-icons/fileicon-exe.png
new file mode 100644
index 00000000..6cfec03b
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-exe.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-h.png b/www/wiki/resources/assets/file-type-icons/fileicon-h.png
new file mode 100644
index 00000000..339bf025
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-h.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-html.png b/www/wiki/resources/assets/file-type-icons/fileicon-html.png
new file mode 100644
index 00000000..d3986321
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-html.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-iso.png b/www/wiki/resources/assets/file-type-icons/fileicon-iso.png
new file mode 100644
index 00000000..c73d2294
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-iso.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-java.png b/www/wiki/resources/assets/file-type-icons/fileicon-java.png
new file mode 100644
index 00000000..b1fe8806
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-java.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-mid.png b/www/wiki/resources/assets/file-type-icons/fileicon-mid.png
new file mode 100644
index 00000000..864ce6d7
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-mid.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-mov.png b/www/wiki/resources/assets/file-type-icons/fileicon-mov.png
new file mode 100644
index 00000000..2b3a0d94
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-mov.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-o.png b/www/wiki/resources/assets/file-type-icons/fileicon-o.png
new file mode 100644
index 00000000..f3523d96
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-o.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-ogg.png b/www/wiki/resources/assets/file-type-icons/fileicon-ogg.png
new file mode 100644
index 00000000..ef4d8016
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-ogg.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-ogg.xcf b/www/wiki/resources/assets/file-type-icons/fileicon-ogg.xcf
new file mode 100644
index 00000000..a91024bf
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-ogg.xcf
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-pdf.png b/www/wiki/resources/assets/file-type-icons/fileicon-pdf.png
new file mode 100644
index 00000000..ab5149cc
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-pdf.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-ps.png b/www/wiki/resources/assets/file-type-icons/fileicon-ps.png
new file mode 100644
index 00000000..45c00fd1
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-ps.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-psd.png b/www/wiki/resources/assets/file-type-icons/fileicon-psd.png
new file mode 100644
index 00000000..183d1e96
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-psd.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-rm.png b/www/wiki/resources/assets/file-type-icons/fileicon-rm.png
new file mode 100644
index 00000000..77e9f528
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-rm.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-rpm.png b/www/wiki/resources/assets/file-type-icons/fileicon-rpm.png
new file mode 100644
index 00000000..a28ad27f
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-rpm.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-svg.png b/www/wiki/resources/assets/file-type-icons/fileicon-svg.png
new file mode 100644
index 00000000..759faf35
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-svg.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-tar.png b/www/wiki/resources/assets/file-type-icons/fileicon-tar.png
new file mode 100644
index 00000000..e5fd1b74
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-tar.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-tex.png b/www/wiki/resources/assets/file-type-icons/fileicon-tex.png
new file mode 100644
index 00000000..1e82e7ad
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-tex.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-ttf.png b/www/wiki/resources/assets/file-type-icons/fileicon-ttf.png
new file mode 100644
index 00000000..838a4b28
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-ttf.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-txt.png b/www/wiki/resources/assets/file-type-icons/fileicon-txt.png
new file mode 100644
index 00000000..94439340
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-txt.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon-xcf.png b/www/wiki/resources/assets/file-type-icons/fileicon-xcf.png
new file mode 100644
index 00000000..2a07b83f
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon-xcf.png
Binary files differ
diff --git a/www/wiki/resources/assets/file-type-icons/fileicon.png b/www/wiki/resources/assets/file-type-icons/fileicon.png
new file mode 100644
index 00000000..59696a38
--- /dev/null
+++ b/www/wiki/resources/assets/file-type-icons/fileicon.png
Binary files differ
diff --git a/www/wiki/resources/assets/licenses/README b/www/wiki/resources/assets/licenses/README
new file mode 100644
index 00000000..dae2549b
--- /dev/null
+++ b/www/wiki/resources/assets/licenses/README
@@ -0,0 +1,4 @@
+These license icons are used in LocalSettings.php files that are generated by
+the installer. Although "Public domain" has been removed from the installer as
+an option, the public-domain.png image needs to remain here to support older
+installations that refer to it in LocalSettings.php.
diff --git a/www/wiki/resources/assets/licenses/cc-0.png b/www/wiki/resources/assets/licenses/cc-0.png
new file mode 100644
index 00000000..9d3fe5f8
--- /dev/null
+++ b/www/wiki/resources/assets/licenses/cc-0.png
Binary files differ
diff --git a/www/wiki/resources/assets/licenses/cc-by-nc-sa.png b/www/wiki/resources/assets/licenses/cc-by-nc-sa.png
new file mode 100644
index 00000000..0d24a713
--- /dev/null
+++ b/www/wiki/resources/assets/licenses/cc-by-nc-sa.png
Binary files differ
diff --git a/www/wiki/resources/assets/licenses/cc-by-sa.png b/www/wiki/resources/assets/licenses/cc-by-sa.png
new file mode 100644
index 00000000..518fb647
--- /dev/null
+++ b/www/wiki/resources/assets/licenses/cc-by-sa.png
Binary files differ
diff --git a/www/wiki/resources/assets/licenses/cc-by.png b/www/wiki/resources/assets/licenses/cc-by.png
new file mode 100644
index 00000000..9cca2f92
--- /dev/null
+++ b/www/wiki/resources/assets/licenses/cc-by.png
Binary files differ
diff --git a/www/wiki/resources/assets/licenses/gnu-fdl.png b/www/wiki/resources/assets/licenses/gnu-fdl.png
new file mode 100644
index 00000000..3feaf57f
--- /dev/null
+++ b/www/wiki/resources/assets/licenses/gnu-fdl.png
Binary files differ
diff --git a/www/wiki/resources/assets/licenses/public-domain.png b/www/wiki/resources/assets/licenses/public-domain.png
new file mode 100644
index 00000000..9458f0a7
--- /dev/null
+++ b/www/wiki/resources/assets/licenses/public-domain.png
Binary files differ
diff --git a/www/wiki/resources/assets/mediawiki.png b/www/wiki/resources/assets/mediawiki.png
new file mode 100644
index 00000000..53bb23fc
--- /dev/null
+++ b/www/wiki/resources/assets/mediawiki.png
Binary files differ
diff --git a/www/wiki/resources/assets/poweredby_mediawiki_132x47.png b/www/wiki/resources/assets/poweredby_mediawiki_132x47.png
new file mode 100644
index 00000000..dadf8095
--- /dev/null
+++ b/www/wiki/resources/assets/poweredby_mediawiki_132x47.png
Binary files differ
diff --git a/www/wiki/resources/assets/poweredby_mediawiki_176x62.png b/www/wiki/resources/assets/poweredby_mediawiki_176x62.png
new file mode 100644
index 00000000..cdcb69d9
--- /dev/null
+++ b/www/wiki/resources/assets/poweredby_mediawiki_176x62.png
Binary files differ
diff --git a/www/wiki/resources/assets/poweredby_mediawiki_88x31.png b/www/wiki/resources/assets/poweredby_mediawiki_88x31.png
new file mode 100644
index 00000000..6883e1c1
--- /dev/null
+++ b/www/wiki/resources/assets/poweredby_mediawiki_88x31.png
Binary files differ
diff --git a/www/wiki/resources/assets/wiki.png b/www/wiki/resources/assets/wiki.png
new file mode 100644
index 00000000..9793c704
--- /dev/null
+++ b/www/wiki/resources/assets/wiki.png
Binary files differ
diff --git a/www/wiki/resources/lib/es5-shim/es5-shim.js b/www/wiki/resources/lib/es5-shim/es5-shim.js
new file mode 100644
index 00000000..85f51e2d
--- /dev/null
+++ b/www/wiki/resources/lib/es5-shim/es5-shim.js
@@ -0,0 +1,1461 @@
+/*!
+ * https://github.com/es-shims/es5-shim
+ * @license es5-shim Copyright 2009-2015 by contributors, MIT License
+ * see https://github.com/es-shims/es5-shim/blob/master/LICENSE
+ */
+
+// vim: ts=4 sts=4 sw=4 expandtab
+
+// Add semicolon to prevent IIFE from being passed as argument to concatenated code.
+;
+
+// UMD (Universal Module Definition)
+// see https://github.com/umdjs/umd/blob/master/returnExports.js
+(function (root, factory) {
+ 'use strict';
+
+ /*global define, exports, module */
+ if (typeof define === 'function' && define.amd) {
+ // AMD. Register as an anonymous module.
+ define(factory);
+ } else if (typeof exports === 'object') {
+ // Node. Does not work with strict CommonJS, but
+ // only CommonJS-like enviroments that support module.exports,
+ // like Node.
+ module.exports = factory();
+ } else {
+ // Browser globals (root is window)
+ root.returnExports = factory();
+ }
+}(this, function () {
+
+/**
+ * Brings an environment as close to ECMAScript 5 compliance
+ * as is possible with the facilities of erstwhile engines.
+ *
+ * Annotated ES5: http://es5.github.com/ (specific links below)
+ * ES5 Spec: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
+ * Required reading: http://javascriptweblog.wordpress.com/2011/12/05/extending-javascript-natives/
+ */
+
+// Shortcut to an often accessed properties, in order to avoid multiple
+// dereference that costs universally.
+var ArrayPrototype = Array.prototype;
+var ObjectPrototype = Object.prototype;
+var FunctionPrototype = Function.prototype;
+var StringPrototype = String.prototype;
+var NumberPrototype = Number.prototype;
+var array_slice = ArrayPrototype.slice;
+var array_splice = ArrayPrototype.splice;
+var array_push = ArrayPrototype.push;
+var array_unshift = ArrayPrototype.unshift;
+var array_concat = ArrayPrototype.concat;
+var call = FunctionPrototype.call;
+
+// Having a toString local variable name breaks in Opera so use to_string.
+var to_string = ObjectPrototype.toString;
+
+var isArray = Array.isArray || function isArray(obj) {
+ return to_string.call(obj) === '[object Array]';
+};
+
+var hasToStringTag = typeof Symbol === 'function' && typeof Symbol.toStringTag === 'symbol';
+var isCallable; /* inlined from https://npmjs.com/is-callable */ var fnToStr = Function.prototype.toString, tryFunctionObject = function tryFunctionObject(value) { try { fnToStr.call(value); return true; } catch (e) { return false; } }, fnClass = '[object Function]', genClass = '[object GeneratorFunction]'; isCallable = function isCallable(value) { if (typeof value !== 'function') { return false; } if (hasToStringTag) { return tryFunctionObject(value); } var strClass = to_string.call(value); return strClass === fnClass || strClass === genClass; };
+var isRegex; /* inlined from https://npmjs.com/is-regex */ var regexExec = RegExp.prototype.exec, tryRegexExec = function tryRegexExec(value) { try { regexExec.call(value); return true; } catch (e) { return false; } }, regexClass = '[object RegExp]'; isRegex = function isRegex(value) { if (typeof value !== 'object') { return false; } return hasToStringTag ? tryRegexExec(value) : to_string.call(value) === regexClass; };
+var isString; /* inlined from https://npmjs.com/is-string */ var strValue = String.prototype.valueOf, tryStringObject = function tryStringObject(value) { try { strValue.call(value); return true; } catch (e) { return false; } }, stringClass = '[object String]'; isString = function isString(value) { if (typeof value === 'string') { return true; } if (typeof value !== 'object') { return false; } return hasToStringTag ? tryStringObject(value) : to_string.call(value) === stringClass; };
+
+var isArguments = function isArguments(value) {
+ var str = to_string.call(value);
+ var isArgs = str === '[object Arguments]';
+ if (!isArgs) {
+ isArgs = !isArray(value) &&
+ value !== null &&
+ typeof value === 'object' &&
+ typeof value.length === 'number' &&
+ value.length >= 0 &&
+ isCallable(value.callee);
+ }
+ return isArgs;
+};
+
+/* inlined from http://npmjs.com/define-properties */
+var defineProperties = (function (has) {
+ var supportsDescriptors = Object.defineProperty && (function () {
+ try {
+ var obj = {};
+ Object.defineProperty(obj, 'x', { enumerable: false, value: obj });
+ for (var _ in obj) { return false; }
+ return obj.x === obj;
+ } catch (e) { /* this is ES3 */
+ return false;
+ }
+ }());
+
+ // Define configurable, writable and non-enumerable props
+ // if they don't exist.
+ var defineProperty;
+ if (supportsDescriptors) {
+ defineProperty = function (object, name, method, forceAssign) {
+ if (!forceAssign && (name in object)) { return; }
+ Object.defineProperty(object, name, {
+ configurable: true,
+ enumerable: false,
+ writable: true,
+ value: method
+ });
+ };
+ } else {
+ defineProperty = function (object, name, method, forceAssign) {
+ if (!forceAssign && (name in object)) { return; }
+ object[name] = method;
+ };
+ }
+ return function defineProperties(object, map, forceAssign) {
+ for (var name in map) {
+ if (has.call(map, name)) {
+ defineProperty(object, name, map[name], forceAssign);
+ }
+ }
+ };
+}(ObjectPrototype.hasOwnProperty));
+
+//
+// Util
+// ======
+//
+
+/* replaceable with https://npmjs.com/package/es-abstract /helpers/isPrimitive */
+var isPrimitive = function isPrimitive(input) {
+ var type = typeof input;
+ return input === null || (type !== 'object' && type !== 'function');
+};
+
+var ES = {
+ // ES5 9.4
+ // http://es5.github.com/#x9.4
+ // http://jsperf.com/to-integer
+ /* replaceable with https://npmjs.com/package/es-abstract ES5.ToInteger */
+ ToInteger: function ToInteger(num) {
+ var n = +num;
+ if (n !== n) { // isNaN
+ n = 0;
+ } else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0)) {
+ n = (n > 0 || -1) * Math.floor(Math.abs(n));
+ }
+ return n;
+ },
+
+ /* replaceable with https://npmjs.com/package/es-abstract ES5.ToPrimitive */
+ ToPrimitive: function ToPrimitive(input) {
+ var val, valueOf, toStr;
+ if (isPrimitive(input)) {
+ return input;
+ }
+ valueOf = input.valueOf;
+ if (isCallable(valueOf)) {
+ val = valueOf.call(input);
+ if (isPrimitive(val)) {
+ return val;
+ }
+ }
+ toStr = input.toString;
+ if (isCallable(toStr)) {
+ val = toStr.call(input);
+ if (isPrimitive(val)) {
+ return val;
+ }
+ }
+ throw new TypeError();
+ },
+
+ // ES5 9.9
+ // http://es5.github.com/#x9.9
+ /* replaceable with https://npmjs.com/package/es-abstract ES5.ToObject */
+ ToObject: function (o) {
+ /*jshint eqnull: true */
+ if (o == null) { // this matches both null and undefined
+ throw new TypeError("can't convert " + o + ' to object');
+ }
+ return Object(o);
+ },
+
+ /* replaceable with https://npmjs.com/package/es-abstract ES5.ToUint32 */
+ ToUint32: function ToUint32(x) {
+ return x >>> 0;
+ }
+};
+
+//
+// Function
+// ========
+//
+
+// ES-5 15.3.4.5
+// http://es5.github.com/#x15.3.4.5
+
+var Empty = function Empty() {};
+
+defineProperties(FunctionPrototype, {
+ bind: function bind(that) { // .length is 1
+ // 1. Let Target be the this value.
+ var target = this;
+ // 2. If IsCallable(Target) is false, throw a TypeError exception.
+ if (!isCallable(target)) {
+ throw new TypeError('Function.prototype.bind called on incompatible ' + target);
+ }
+ // 3. Let A be a new (possibly empty) internal list of all of the
+ // argument values provided after thisArg (arg1, arg2 etc), in order.
+ // XXX slicedArgs will stand in for "A" if used
+ var args = array_slice.call(arguments, 1); // for normal call
+ // 4. Let F be a new native ECMAScript object.
+ // 11. Set the [[Prototype]] internal property of F to the standard
+ // built-in Function prototype object as specified in 15.3.3.1.
+ // 12. Set the [[Call]] internal property of F as described in
+ // 15.3.4.5.1.
+ // 13. Set the [[Construct]] internal property of F as described in
+ // 15.3.4.5.2.
+ // 14. Set the [[HasInstance]] internal property of F as described in
+ // 15.3.4.5.3.
+ var bound;
+ var binder = function () {
+
+ if (this instanceof bound) {
+ // 15.3.4.5.2 [[Construct]]
+ // When the [[Construct]] internal method of a function object,
+ // F that was created using the bind function is called with a
+ // list of arguments ExtraArgs, the following steps are taken:
+ // 1. Let target be the value of F's [[TargetFunction]]
+ // internal property.
+ // 2. If target has no [[Construct]] internal method, a
+ // TypeError exception is thrown.
+ // 3. Let boundArgs be the value of F's [[BoundArgs]] internal
+ // property.
+ // 4. Let args be a new list containing the same values as the
+ // list boundArgs in the same order followed by the same
+ // values as the list ExtraArgs in the same order.
+ // 5. Return the result of calling the [[Construct]] internal
+ // method of target providing args as the arguments.
+
+ var result = target.apply(
+ this,
+ array_concat.call(args, array_slice.call(arguments))
+ );
+ if (Object(result) === result) {
+ return result;
+ }
+ return this;
+
+ } else {
+ // 15.3.4.5.1 [[Call]]
+ // When the [[Call]] internal method of a function object, F,
+ // which was created using the bind function is called with a
+ // this value and a list of arguments ExtraArgs, the following
+ // steps are taken:
+ // 1. Let boundArgs be the value of F's [[BoundArgs]] internal
+ // property.
+ // 2. Let boundThis be the value of F's [[BoundThis]] internal
+ // property.
+ // 3. Let target be the value of F's [[TargetFunction]] internal
+ // property.
+ // 4. Let args be a new list containing the same values as the
+ // list boundArgs in the same order followed by the same
+ // values as the list ExtraArgs in the same order.
+ // 5. Return the result of calling the [[Call]] internal method
+ // of target providing boundThis as the this value and
+ // providing args as the arguments.
+
+ // equiv: target.call(this, ...boundArgs, ...args)
+ return target.apply(
+ that,
+ array_concat.call(args, array_slice.call(arguments))
+ );
+
+ }
+
+ };
+
+ // 15. If the [[Class]] internal property of Target is "Function", then
+ // a. Let L be the length property of Target minus the length of A.
+ // b. Set the length own property of F to either 0 or L, whichever is
+ // larger.
+ // 16. Else set the length own property of F to 0.
+
+ var boundLength = Math.max(0, target.length - args.length);
+
+ // 17. Set the attributes of the length own property of F to the values
+ // specified in 15.3.5.1.
+ var boundArgs = [];
+ for (var i = 0; i < boundLength; i++) {
+ boundArgs.push('$' + i);
+ }
+
+ // XXX Build a dynamic function with desired amount of arguments is the only
+ // way to set the length property of a function.
+ // In environments where Content Security Policies enabled (Chrome extensions,
+ // for ex.) all use of eval or Function costructor throws an exception.
+ // However in all of these environments Function.prototype.bind exists
+ // and so this code will never be executed.
+ bound = Function('binder', 'return function (' + boundArgs.join(',') + '){ return binder.apply(this, arguments); }')(binder);
+
+ if (target.prototype) {
+ Empty.prototype = target.prototype;
+ bound.prototype = new Empty();
+ // Clean up dangling references.
+ Empty.prototype = null;
+ }
+
+ // TODO
+ // 18. Set the [[Extensible]] internal property of F to true.
+
+ // TODO
+ // 19. Let thrower be the [[ThrowTypeError]] function Object (13.2.3).
+ // 20. Call the [[DefineOwnProperty]] internal method of F with
+ // arguments "caller", PropertyDescriptor {[[Get]]: thrower, [[Set]]:
+ // thrower, [[Enumerable]]: false, [[Configurable]]: false}, and
+ // false.
+ // 21. Call the [[DefineOwnProperty]] internal method of F with
+ // arguments "arguments", PropertyDescriptor {[[Get]]: thrower,
+ // [[Set]]: thrower, [[Enumerable]]: false, [[Configurable]]: false},
+ // and false.
+
+ // TODO
+ // NOTE Function objects created using Function.prototype.bind do not
+ // have a prototype property or the [[Code]], [[FormalParameters]], and
+ // [[Scope]] internal properties.
+ // XXX can't delete prototype in pure-js.
+
+ // 22. Return F.
+ return bound;
+ }
+});
+
+// _Please note: Shortcuts are defined after `Function.prototype.bind` as we
+// us it in defining shortcuts.
+var owns = call.bind(ObjectPrototype.hasOwnProperty);
+
+//
+// Array
+// =====
+//
+
+// ES5 15.4.4.12
+// http://es5.github.com/#x15.4.4.12
+var spliceNoopReturnsEmptyArray = (function () {
+ var a = [1, 2];
+ var result = a.splice();
+ return a.length === 2 && isArray(result) && result.length === 0;
+}());
+defineProperties(ArrayPrototype, {
+ // Safari 5.0 bug where .splice() returns undefined
+ splice: function splice(start, deleteCount) {
+ if (arguments.length === 0) {
+ return [];
+ } else {
+ return array_splice.apply(this, arguments);
+ }
+ }
+}, !spliceNoopReturnsEmptyArray);
+
+var spliceWorksWithEmptyObject = (function () {
+ var obj = {};
+ ArrayPrototype.splice.call(obj, 0, 0, 1);
+ return obj.length === 1;
+}());
+defineProperties(ArrayPrototype, {
+ splice: function splice(start, deleteCount) {
+ if (arguments.length === 0) { return []; }
+ var args = arguments;
+ this.length = Math.max(ES.ToInteger(this.length), 0);
+ if (arguments.length > 0 && typeof deleteCount !== 'number') {
+ args = array_slice.call(arguments);
+ if (args.length < 2) {
+ args.push(this.length - start);
+ } else {
+ args[1] = ES.ToInteger(deleteCount);
+ }
+ }
+ return array_splice.apply(this, args);
+ }
+}, !spliceWorksWithEmptyObject);
+
+// ES5 15.4.4.12
+// http://es5.github.com/#x15.4.4.13
+// Return len+argCount.
+// [bugfix, ielt8]
+// IE < 8 bug: [].unshift(0) === undefined but should be "1"
+var hasUnshiftReturnValueBug = [].unshift(0) !== 1;
+defineProperties(ArrayPrototype, {
+ unshift: function () {
+ array_unshift.apply(this, arguments);
+ return this.length;
+ }
+}, hasUnshiftReturnValueBug);
+
+// ES5 15.4.3.2
+// http://es5.github.com/#x15.4.3.2
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/isArray
+defineProperties(Array, { isArray: isArray });
+
+// The IsCallable() check in the Array functions
+// has been replaced with a strict check on the
+// internal class of the object to trap cases where
+// the provided function was actually a regular
+// expression literal, which in V8 and
+// JavaScriptCore is a typeof "function". Only in
+// V8 are regular expression literals permitted as
+// reduce parameters, so it is desirable in the
+// general case for the shim to match the more
+// strict and common behavior of rejecting regular
+// expressions.
+
+// ES5 15.4.4.18
+// http://es5.github.com/#x15.4.4.18
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/array/forEach
+
+// Check failure of by-index access of string characters (IE < 9)
+// and failure of `0 in boxedString` (Rhino)
+var boxedString = Object('a');
+var splitString = boxedString[0] !== 'a' || !(0 in boxedString);
+
+var properlyBoxesContext = function properlyBoxed(method) {
+ // Check node 0.6.21 bug where third parameter is not boxed
+ var properlyBoxesNonStrict = true;
+ var properlyBoxesStrict = true;
+ if (method) {
+ method.call('foo', function (_, __, context) {
+ if (typeof context !== 'object') { properlyBoxesNonStrict = false; }
+ });
+
+ method.call([1], function () {
+ 'use strict';
+
+ properlyBoxesStrict = typeof this === 'string';
+ }, 'x');
+ }
+ return !!method && properlyBoxesNonStrict && properlyBoxesStrict;
+};
+
+defineProperties(ArrayPrototype, {
+ forEach: function forEach(callbackfn /*, thisArg*/) {
+ var object = ES.ToObject(this);
+ var self = splitString && isString(this) ? this.split('') : object;
+ var i = -1;
+ var length = self.length >>> 0;
+ var T;
+ if (arguments.length > 1) {
+ T = arguments[1];
+ }
+
+ // If no callback function or if callback is not a callable function
+ if (!isCallable(callbackfn)) {
+ throw new TypeError('Array.prototype.forEach callback must be a function');
+ }
+
+ while (++i < length) {
+ if (i in self) {
+ // Invoke the callback function with call, passing arguments:
+ // context, property value, property key, thisArg object
+ if (typeof T !== 'undefined') {
+ callbackfn.call(T, self[i], i, object);
+ } else {
+ callbackfn(self[i], i, object);
+ }
+ }
+ }
+ }
+}, !properlyBoxesContext(ArrayPrototype.forEach));
+
+// ES5 15.4.4.19
+// http://es5.github.com/#x15.4.4.19
+// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/map
+defineProperties(ArrayPrototype, {
+ map: function map(callbackfn/*, thisArg*/) {
+ var object = ES.ToObject(this);
+ var self = splitString && isString(this) ? this.split('') : object;
+ var length = self.length >>> 0;
+ var result = Array(length);
+ var T;
+ if (arguments.length > 1) {
+ T = arguments[1];
+ }
+
+ // If no callback function or if callback is not a callable function
+ if (!isCallable(callbackfn)) {
+ throw new TypeError('Array.prototype.map callback must be a function');
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self) {
+ if (typeof T !== 'undefined') {
+ result[i] = callbackfn.call(T, self[i], i, object);
+ } else {
+ result[i] = callbackfn(self[i], i, object);
+ }
+ }
+ }
+ return result;
+ }
+}, !properlyBoxesContext(ArrayPrototype.map));
+
+// ES5 15.4.4.20
+// http://es5.github.com/#x15.4.4.20
+// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/filter
+defineProperties(ArrayPrototype, {
+ filter: function filter(callbackfn /*, thisArg*/) {
+ var object = ES.ToObject(this);
+ var self = splitString && isString(this) ? this.split('') : object;
+ var length = self.length >>> 0;
+ var result = [];
+ var value;
+ var T;
+ if (arguments.length > 1) {
+ T = arguments[1];
+ }
+
+ // If no callback function or if callback is not a callable function
+ if (!isCallable(callbackfn)) {
+ throw new TypeError('Array.prototype.filter callback must be a function');
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self) {
+ value = self[i];
+ if (typeof T === 'undefined' ? callbackfn(value, i, object) : callbackfn.call(T, value, i, object)) {
+ result.push(value);
+ }
+ }
+ }
+ return result;
+ }
+}, !properlyBoxesContext(ArrayPrototype.filter));
+
+// ES5 15.4.4.16
+// http://es5.github.com/#x15.4.4.16
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/every
+defineProperties(ArrayPrototype, {
+ every: function every(callbackfn /*, thisArg*/) {
+ var object = ES.ToObject(this);
+ var self = splitString && isString(this) ? this.split('') : object;
+ var length = self.length >>> 0;
+ var T;
+ if (arguments.length > 1) {
+ T = arguments[1];
+ }
+
+ // If no callback function or if callback is not a callable function
+ if (!isCallable(callbackfn)) {
+ throw new TypeError('Array.prototype.every callback must be a function');
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self && !(typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
+ return false;
+ }
+ }
+ return true;
+ }
+}, !properlyBoxesContext(ArrayPrototype.every));
+
+// ES5 15.4.4.17
+// http://es5.github.com/#x15.4.4.17
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/some
+defineProperties(ArrayPrototype, {
+ some: function some(callbackfn/*, thisArg */) {
+ var object = ES.ToObject(this);
+ var self = splitString && isString(this) ? this.split('') : object;
+ var length = self.length >>> 0;
+ var T;
+ if (arguments.length > 1) {
+ T = arguments[1];
+ }
+
+ // If no callback function or if callback is not a callable function
+ if (!isCallable(callbackfn)) {
+ throw new TypeError('Array.prototype.some callback must be a function');
+ }
+
+ for (var i = 0; i < length; i++) {
+ if (i in self && (typeof T === 'undefined' ? callbackfn(self[i], i, object) : callbackfn.call(T, self[i], i, object))) {
+ return true;
+ }
+ }
+ return false;
+ }
+}, !properlyBoxesContext(ArrayPrototype.some));
+
+// ES5 15.4.4.21
+// http://es5.github.com/#x15.4.4.21
+// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduce
+var reduceCoercesToObject = false;
+if (ArrayPrototype.reduce) {
+ reduceCoercesToObject = typeof ArrayPrototype.reduce.call('es5', function (_, __, ___, list) { return list; }) === 'object';
+}
+defineProperties(ArrayPrototype, {
+ reduce: function reduce(callbackfn /*, initialValue*/) {
+ var object = ES.ToObject(this);
+ var self = splitString && isString(this) ? this.split('') : object;
+ var length = self.length >>> 0;
+
+ // If no callback function or if callback is not a callable function
+ if (!isCallable(callbackfn)) {
+ throw new TypeError('Array.prototype.reduce callback must be a function');
+ }
+
+ // no value to return if no initial value and an empty array
+ if (length === 0 && arguments.length === 1) {
+ throw new TypeError('reduce of empty array with no initial value');
+ }
+
+ var i = 0;
+ var result;
+ if (arguments.length >= 2) {
+ result = arguments[1];
+ } else {
+ do {
+ if (i in self) {
+ result = self[i++];
+ break;
+ }
+
+ // if array contains no values, no initial value to return
+ if (++i >= length) {
+ throw new TypeError('reduce of empty array with no initial value');
+ }
+ } while (true);
+ }
+
+ for (; i < length; i++) {
+ if (i in self) {
+ result = callbackfn(result, self[i], i, object);
+ }
+ }
+
+ return result;
+ }
+}, !reduceCoercesToObject);
+
+// ES5 15.4.4.22
+// http://es5.github.com/#x15.4.4.22
+// https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Objects/Array/reduceRight
+var reduceRightCoercesToObject = false;
+if (ArrayPrototype.reduceRight) {
+ reduceRightCoercesToObject = typeof ArrayPrototype.reduceRight.call('es5', function (_, __, ___, list) { return list; }) === 'object';
+}
+defineProperties(ArrayPrototype, {
+ reduceRight: function reduceRight(callbackfn/*, initial*/) {
+ var object = ES.ToObject(this);
+ var self = splitString && isString(this) ? this.split('') : object;
+ var length = self.length >>> 0;
+
+ // If no callback function or if callback is not a callable function
+ if (!isCallable(callbackfn)) {
+ throw new TypeError('Array.prototype.reduceRight callback must be a function');
+ }
+
+ // no value to return if no initial value, empty array
+ if (length === 0 && arguments.length === 1) {
+ throw new TypeError('reduceRight of empty array with no initial value');
+ }
+
+ var result;
+ var i = length - 1;
+ if (arguments.length >= 2) {
+ result = arguments[1];
+ } else {
+ do {
+ if (i in self) {
+ result = self[i--];
+ break;
+ }
+
+ // if array contains no values, no initial value to return
+ if (--i < 0) {
+ throw new TypeError('reduceRight of empty array with no initial value');
+ }
+ } while (true);
+ }
+
+ if (i < 0) {
+ return result;
+ }
+
+ do {
+ if (i in self) {
+ result = callbackfn(result, self[i], i, object);
+ }
+ } while (i--);
+
+ return result;
+ }
+}, !reduceRightCoercesToObject);
+
+// ES5 15.4.4.14
+// http://es5.github.com/#x15.4.4.14
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/indexOf
+var hasFirefox2IndexOfBug = Array.prototype.indexOf && [0, 1].indexOf(1, 2) !== -1;
+defineProperties(ArrayPrototype, {
+ indexOf: function indexOf(searchElement /*, fromIndex */) {
+ var self = splitString && isString(this) ? this.split('') : ES.ToObject(this);
+ var length = self.length >>> 0;
+
+ if (length === 0) {
+ return -1;
+ }
+
+ var i = 0;
+ if (arguments.length > 1) {
+ i = ES.ToInteger(arguments[1]);
+ }
+
+ // handle negative indices
+ i = i >= 0 ? i : Math.max(0, length + i);
+ for (; i < length; i++) {
+ if (i in self && self[i] === searchElement) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}, hasFirefox2IndexOfBug);
+
+// ES5 15.4.4.15
+// http://es5.github.com/#x15.4.4.15
+// https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/lastIndexOf
+var hasFirefox2LastIndexOfBug = Array.prototype.lastIndexOf && [0, 1].lastIndexOf(0, -3) !== -1;
+defineProperties(ArrayPrototype, {
+ lastIndexOf: function lastIndexOf(searchElement /*, fromIndex */) {
+ var self = splitString && isString(this) ? this.split('') : ES.ToObject(this);
+ var length = self.length >>> 0;
+
+ if (length === 0) {
+ return -1;
+ }
+ var i = length - 1;
+ if (arguments.length > 1) {
+ i = Math.min(i, ES.ToInteger(arguments[1]));
+ }
+ // handle negative indices
+ i = i >= 0 ? i : length - Math.abs(i);
+ for (; i >= 0; i--) {
+ if (i in self && searchElement === self[i]) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}, hasFirefox2LastIndexOfBug);
+
+//
+// Object
+// ======
+//
+
+// ES5 15.2.3.14
+// http://es5.github.com/#x15.2.3.14
+
+// http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
+var hasDontEnumBug = !({ 'toString': null }).propertyIsEnumerable('toString'),
+ hasProtoEnumBug = function () {}.propertyIsEnumerable('prototype'),
+ hasStringEnumBug = !owns('x', '0'),
+ dontEnums = [
+ 'toString',
+ 'toLocaleString',
+ 'valueOf',
+ 'hasOwnProperty',
+ 'isPrototypeOf',
+ 'propertyIsEnumerable',
+ 'constructor'
+ ],
+ dontEnumsLength = dontEnums.length;
+
+defineProperties(Object, {
+ keys: function keys(object) {
+ var isFn = isCallable(object),
+ isArgs = isArguments(object),
+ isObject = object !== null && typeof object === 'object',
+ isStr = isObject && isString(object);
+
+ if (!isObject && !isFn && !isArgs) {
+ throw new TypeError('Object.keys called on a non-object');
+ }
+
+ var theKeys = [];
+ var skipProto = hasProtoEnumBug && isFn;
+ if ((isStr && hasStringEnumBug) || isArgs) {
+ for (var i = 0; i < object.length; ++i) {
+ theKeys.push(String(i));
+ }
+ }
+
+ if (!isArgs) {
+ for (var name in object) {
+ if (!(skipProto && name === 'prototype') && owns(object, name)) {
+ theKeys.push(String(name));
+ }
+ }
+ }
+
+ if (hasDontEnumBug) {
+ var ctor = object.constructor,
+ skipConstructor = ctor && ctor.prototype === object;
+ for (var j = 0; j < dontEnumsLength; j++) {
+ var dontEnum = dontEnums[j];
+ if (!(skipConstructor && dontEnum === 'constructor') && owns(object, dontEnum)) {
+ theKeys.push(dontEnum);
+ }
+ }
+ }
+ return theKeys;
+ }
+});
+
+var keysWorksWithArguments = Object.keys && (function () {
+ // Safari 5.0 bug
+ return Object.keys(arguments).length === 2;
+}(1, 2));
+var originalKeys = Object.keys;
+defineProperties(Object, {
+ keys: function keys(object) {
+ if (isArguments(object)) {
+ return originalKeys(ArrayPrototype.slice.call(object));
+ } else {
+ return originalKeys(object);
+ }
+ }
+}, !keysWorksWithArguments);
+
+//
+// Date
+// ====
+//
+
+// ES5 15.9.5.43
+// http://es5.github.com/#x15.9.5.43
+// This function returns a String value represent the instance in time
+// represented by this Date object. The format of the String is the Date Time
+// string format defined in 15.9.1.15. All fields are present in the String.
+// The time zone is always UTC, denoted by the suffix Z. If the time value of
+// this object is not a finite Number a RangeError exception is thrown.
+var negativeDate = -62198755200000;
+var negativeYearString = '-000001';
+var hasNegativeDateBug = Date.prototype.toISOString && new Date(negativeDate).toISOString().indexOf(negativeYearString) === -1;
+
+defineProperties(Date.prototype, {
+ toISOString: function toISOString() {
+ var result, length, value, year, month;
+ if (!isFinite(this)) {
+ throw new RangeError('Date.prototype.toISOString called on non-finite value.');
+ }
+
+ year = this.getUTCFullYear();
+
+ month = this.getUTCMonth();
+ // see https://github.com/es-shims/es5-shim/issues/111
+ year += Math.floor(month / 12);
+ month = (month % 12 + 12) % 12;
+
+ // the date time string format is specified in 15.9.1.15.
+ result = [month + 1, this.getUTCDate(), this.getUTCHours(), this.getUTCMinutes(), this.getUTCSeconds()];
+ year = (
+ (year < 0 ? '-' : (year > 9999 ? '+' : '')) +
+ ('00000' + Math.abs(year)).slice((0 <= year && year <= 9999) ? -4 : -6)
+ );
+
+ length = result.length;
+ while (length--) {
+ value = result[length];
+ // pad months, days, hours, minutes, and seconds to have two
+ // digits.
+ if (value < 10) {
+ result[length] = '0' + value;
+ }
+ }
+ // pad milliseconds to have three digits.
+ return (
+ year + '-' + result.slice(0, 2).join('-') +
+ 'T' + result.slice(2).join(':') + '.' +
+ ('000' + this.getUTCMilliseconds()).slice(-3) + 'Z'
+ );
+ }
+}, hasNegativeDateBug);
+
+// ES5 15.9.5.44
+// http://es5.github.com/#x15.9.5.44
+// This function provides a String representation of a Date object for use by
+// JSON.stringify (15.12.3).
+var dateToJSONIsSupported = (function () {
+ try {
+ return Date.prototype.toJSON &&
+ new Date(NaN).toJSON() === null &&
+ new Date(negativeDate).toJSON().indexOf(negativeYearString) !== -1 &&
+ Date.prototype.toJSON.call({ // generic
+ toISOString: function () { return true; }
+ });
+ } catch (e) {
+ return false;
+ }
+}());
+if (!dateToJSONIsSupported) {
+ Date.prototype.toJSON = function toJSON(key) {
+ // When the toJSON method is called with argument key, the following
+ // steps are taken:
+
+ // 1. Let O be the result of calling ToObject, giving it the this
+ // value as its argument.
+ // 2. Let tv be ES.ToPrimitive(O, hint Number).
+ var O = Object(this);
+ var tv = ES.ToPrimitive(O);
+ // 3. If tv is a Number and is not finite, return null.
+ if (typeof tv === 'number' && !isFinite(tv)) {
+ return null;
+ }
+ // 4. Let toISO be the result of calling the [[Get]] internal method of
+ // O with argument "toISOString".
+ var toISO = O.toISOString;
+ // 5. If IsCallable(toISO) is false, throw a TypeError exception.
+ if (!isCallable(toISO)) {
+ throw new TypeError('toISOString property is not callable');
+ }
+ // 6. Return the result of calling the [[Call]] internal method of
+ // toISO with O as the this value and an empty argument list.
+ return toISO.call(O);
+
+ // NOTE 1 The argument is ignored.
+
+ // NOTE 2 The toJSON function is intentionally generic; it does not
+ // require that its this value be a Date object. Therefore, it can be
+ // transferred to other kinds of objects for use as a method. However,
+ // it does require that any such object have a toISOString method. An
+ // object is free to use the argument key to filter its
+ // stringification.
+ };
+}
+
+// ES5 15.9.4.2
+// http://es5.github.com/#x15.9.4.2
+// based on work shared by Daniel Friesen (dantman)
+// http://gist.github.com/303249
+var supportsExtendedYears = Date.parse('+033658-09-27T01:46:40.000Z') === 1e15;
+var acceptsInvalidDates = !isNaN(Date.parse('2012-04-04T24:00:00.500Z')) || !isNaN(Date.parse('2012-11-31T23:59:59.000Z')) || !isNaN(Date.parse('2012-12-31T23:59:60.000Z'));
+var doesNotParseY2KNewYear = isNaN(Date.parse('2000-01-01T00:00:00.000Z'));
+if (!Date.parse || doesNotParseY2KNewYear || acceptsInvalidDates || !supportsExtendedYears) {
+ // XXX global assignment won't work in embeddings that use
+ // an alternate object for the context.
+ /*global Date: true */
+ /*eslint-disable no-undef*/
+ Date = (function (NativeDate) {
+ /*eslint-enable no-undef*/
+ // Date.length === 7
+ var DateShim = function Date(Y, M, D, h, m, s, ms) {
+ var length = arguments.length;
+ var date;
+ if (this instanceof NativeDate) {
+ date = length === 1 && String(Y) === Y ? // isString(Y)
+ // We explicitly pass it through parse:
+ new NativeDate(DateShim.parse(Y)) :
+ // We have to manually make calls depending on argument
+ // length here
+ length >= 7 ? new NativeDate(Y, M, D, h, m, s, ms) :
+ length >= 6 ? new NativeDate(Y, M, D, h, m, s) :
+ length >= 5 ? new NativeDate(Y, M, D, h, m) :
+ length >= 4 ? new NativeDate(Y, M, D, h) :
+ length >= 3 ? new NativeDate(Y, M, D) :
+ length >= 2 ? new NativeDate(Y, M) :
+ length >= 1 ? new NativeDate(Y) :
+ new NativeDate();
+ } else {
+ date = NativeDate.apply(this, arguments);
+ }
+ // Prevent mixups with unfixed Date object
+ defineProperties(date, { constructor: DateShim }, true);
+ return date;
+ };
+
+ // 15.9.1.15 Date Time String Format.
+ var isoDateExpression = new RegExp('^' +
+ '(\\d{4}|[+-]\\d{6})' + // four-digit year capture or sign +
+ // 6-digit extended year
+ '(?:-(\\d{2})' + // optional month capture
+ '(?:-(\\d{2})' + // optional day capture
+ '(?:' + // capture hours:minutes:seconds.milliseconds
+ 'T(\\d{2})' + // hours capture
+ ':(\\d{2})' + // minutes capture
+ '(?:' + // optional :seconds.milliseconds
+ ':(\\d{2})' + // seconds capture
+ '(?:(\\.\\d{1,}))?' + // milliseconds capture
+ ')?' +
+ '(' + // capture UTC offset component
+ 'Z|' + // UTC capture
+ '(?:' + // offset specifier +/-hours:minutes
+ '([-+])' + // sign capture
+ '(\\d{2})' + // hours offset capture
+ ':(\\d{2})' + // minutes offset capture
+ ')' +
+ ')?)?)?)?' +
+ '$');
+
+ var months = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365];
+
+ var dayFromMonth = function dayFromMonth(year, month) {
+ var t = month > 1 ? 1 : 0;
+ return (
+ months[month] +
+ Math.floor((year - 1969 + t) / 4) -
+ Math.floor((year - 1901 + t) / 100) +
+ Math.floor((year - 1601 + t) / 400) +
+ 365 * (year - 1970)
+ );
+ };
+
+ var toUTC = function toUTC(t) {
+ return Number(new NativeDate(1970, 0, 1, 0, 0, 0, t));
+ };
+
+ // Copy any custom methods a 3rd party library may have added
+ for (var key in NativeDate) {
+ if (owns(NativeDate, key)) {
+ DateShim[key] = NativeDate[key];
+ }
+ }
+
+ // Copy "native" methods explicitly; they may be non-enumerable
+ defineProperties(DateShim, {
+ now: NativeDate.now,
+ UTC: NativeDate.UTC
+ }, true);
+ DateShim.prototype = NativeDate.prototype;
+ defineProperties(DateShim.prototype, {
+ constructor: DateShim
+ }, true);
+
+ // Upgrade Date.parse to handle simplified ISO 8601 strings
+ DateShim.parse = function parse(string) {
+ var match = isoDateExpression.exec(string);
+ if (match) {
+ // parse months, days, hours, minutes, seconds, and milliseconds
+ // provide default values if necessary
+ // parse the UTC offset component
+ var year = Number(match[1]),
+ month = Number(match[2] || 1) - 1,
+ day = Number(match[3] || 1) - 1,
+ hour = Number(match[4] || 0),
+ minute = Number(match[5] || 0),
+ second = Number(match[6] || 0),
+ millisecond = Math.floor(Number(match[7] || 0) * 1000),
+ // When time zone is missed, local offset should be used
+ // (ES 5.1 bug)
+ // see https://bugs.ecmascript.org/show_bug.cgi?id=112
+ isLocalTime = Boolean(match[4] && !match[8]),
+ signOffset = match[9] === '-' ? 1 : -1,
+ hourOffset = Number(match[10] || 0),
+ minuteOffset = Number(match[11] || 0),
+ result;
+ if (
+ hour < (
+ minute > 0 || second > 0 || millisecond > 0 ?
+ 24 : 25
+ ) &&
+ minute < 60 && second < 60 && millisecond < 1000 &&
+ month > -1 && month < 12 && hourOffset < 24 &&
+ minuteOffset < 60 && // detect invalid offsets
+ day > -1 &&
+ day < (
+ dayFromMonth(year, month + 1) -
+ dayFromMonth(year, month)
+ )
+ ) {
+ result = (
+ (dayFromMonth(year, month) + day) * 24 +
+ hour +
+ hourOffset * signOffset
+ ) * 60;
+ result = (
+ (result + minute + minuteOffset * signOffset) * 60 +
+ second
+ ) * 1000 + millisecond;
+ if (isLocalTime) {
+ result = toUTC(result);
+ }
+ if (-8.64e15 <= result && result <= 8.64e15) {
+ return result;
+ }
+ }
+ return NaN;
+ }
+ return NativeDate.parse.apply(this, arguments);
+ };
+
+ return DateShim;
+ }(Date));
+ /*global Date: false */
+}
+
+// ES5 15.9.4.4
+// http://es5.github.com/#x15.9.4.4
+if (!Date.now) {
+ Date.now = function now() {
+ return new Date().getTime();
+ };
+}
+
+//
+// Number
+// ======
+//
+
+// ES5.1 15.7.4.5
+// http://es5.github.com/#x15.7.4.5
+var hasToFixedBugs = NumberPrototype.toFixed && (
+ (0.00008).toFixed(3) !== '0.000' ||
+ (0.9).toFixed(0) !== '1' ||
+ (1.255).toFixed(2) !== '1.25' ||
+ (1000000000000000128).toFixed(0) !== '1000000000000000128'
+);
+
+var toFixedHelpers = {
+ base: 1e7,
+ size: 6,
+ data: [0, 0, 0, 0, 0, 0],
+ multiply: function multiply(n, c) {
+ var i = -1;
+ var c2 = c;
+ while (++i < toFixedHelpers.size) {
+ c2 += n * toFixedHelpers.data[i];
+ toFixedHelpers.data[i] = c2 % toFixedHelpers.base;
+ c2 = Math.floor(c2 / toFixedHelpers.base);
+ }
+ },
+ divide: function divide(n) {
+ var i = toFixedHelpers.size, c = 0;
+ while (--i >= 0) {
+ c += toFixedHelpers.data[i];
+ toFixedHelpers.data[i] = Math.floor(c / n);
+ c = (c % n) * toFixedHelpers.base;
+ }
+ },
+ numToString: function numToString() {
+ var i = toFixedHelpers.size;
+ var s = '';
+ while (--i >= 0) {
+ if (s !== '' || i === 0 || toFixedHelpers.data[i] !== 0) {
+ var t = String(toFixedHelpers.data[i]);
+ if (s === '') {
+ s = t;
+ } else {
+ s += '0000000'.slice(0, 7 - t.length) + t;
+ }
+ }
+ }
+ return s;
+ },
+ pow: function pow(x, n, acc) {
+ return (n === 0 ? acc : (n % 2 === 1 ? pow(x, n - 1, acc * x) : pow(x * x, n / 2, acc)));
+ },
+ log: function log(x) {
+ var n = 0;
+ var x2 = x;
+ while (x2 >= 4096) {
+ n += 12;
+ x2 /= 4096;
+ }
+ while (x2 >= 2) {
+ n += 1;
+ x2 /= 2;
+ }
+ return n;
+ }
+};
+
+defineProperties(NumberPrototype, {
+ toFixed: function toFixed(fractionDigits) {
+ var f, x, s, m, e, z, j, k;
+
+ // Test for NaN and round fractionDigits down
+ f = Number(fractionDigits);
+ f = f !== f ? 0 : Math.floor(f);
+
+ if (f < 0 || f > 20) {
+ throw new RangeError('Number.toFixed called with invalid number of decimals');
+ }
+
+ x = Number(this);
+
+ // Test for NaN
+ if (x !== x) {
+ return 'NaN';
+ }
+
+ // If it is too big or small, return the string value of the number
+ if (x <= -1e21 || x >= 1e21) {
+ return String(x);
+ }
+
+ s = '';
+
+ if (x < 0) {
+ s = '-';
+ x = -x;
+ }
+
+ m = '0';
+
+ if (x > 1e-21) {
+ // 1e-21 < x < 1e21
+ // -70 < log2(x) < 70
+ e = toFixedHelpers.log(x * toFixedHelpers.pow(2, 69, 1)) - 69;
+ z = (e < 0 ? x * toFixedHelpers.pow(2, -e, 1) : x / toFixedHelpers.pow(2, e, 1));
+ z *= 0x10000000000000; // Math.pow(2, 52);
+ e = 52 - e;
+
+ // -18 < e < 122
+ // x = z / 2 ^ e
+ if (e > 0) {
+ toFixedHelpers.multiply(0, z);
+ j = f;
+
+ while (j >= 7) {
+ toFixedHelpers.multiply(1e7, 0);
+ j -= 7;
+ }
+
+ toFixedHelpers.multiply(toFixedHelpers.pow(10, j, 1), 0);
+ j = e - 1;
+
+ while (j >= 23) {
+ toFixedHelpers.divide(1 << 23);
+ j -= 23;
+ }
+
+ toFixedHelpers.divide(1 << j);
+ toFixedHelpers.multiply(1, 1);
+ toFixedHelpers.divide(2);
+ m = toFixedHelpers.numToString();
+ } else {
+ toFixedHelpers.multiply(0, z);
+ toFixedHelpers.multiply(1 << (-e), 0);
+ m = toFixedHelpers.numToString() + '0.00000000000000000000'.slice(2, 2 + f);
+ }
+ }
+
+ if (f > 0) {
+ k = m.length;
+
+ if (k <= f) {
+ m = s + '0.0000000000000000000'.slice(0, f - k + 2) + m;
+ } else {
+ m = s + m.slice(0, k - f) + '.' + m.slice(k - f);
+ }
+ } else {
+ m = s + m;
+ }
+
+ return m;
+ }
+}, hasToFixedBugs);
+
+//
+// String
+// ======
+//
+
+// ES5 15.5.4.14
+// http://es5.github.com/#x15.5.4.14
+
+// [bugfix, IE lt 9, firefox 4, Konqueror, Opera, obscure browsers]
+// Many browsers do not split properly with regular expressions or they
+// do not perform the split correctly under obscure conditions.
+// See http://blog.stevenlevithan.com/archives/cross-browser-split
+// I've tested in many browsers and this seems to cover the deviant ones:
+// 'ab'.split(/(?:ab)*/) should be ["", ""], not [""]
+// '.'.split(/(.?)(.?)/) should be ["", ".", "", ""], not ["", ""]
+// 'tesst'.split(/(s)*/) should be ["t", undefined, "e", "s", "t"], not
+// [undefined, "t", undefined, "e", ...]
+// ''.split(/.?/) should be [], not [""]
+// '.'.split(/()()/) should be ["."], not ["", "", "."]
+
+var string_split = StringPrototype.split;
+if (
+ 'ab'.split(/(?:ab)*/).length !== 2 ||
+ '.'.split(/(.?)(.?)/).length !== 4 ||
+ 'tesst'.split(/(s)*/)[1] === 't' ||
+ 'test'.split(/(?:)/, -1).length !== 4 ||
+ ''.split(/.?/).length ||
+ '.'.split(/()()/).length > 1
+) {
+ (function () {
+ var compliantExecNpcg = typeof (/()??/).exec('')[1] === 'undefined'; // NPCG: nonparticipating capturing group
+
+ StringPrototype.split = function (separator, limit) {
+ var string = this;
+ if (typeof separator === 'undefined' && limit === 0) {
+ return [];
+ }
+
+ // If `separator` is not a regex, use native split
+ if (!isRegex(separator)) {
+ return string_split.call(this, separator, limit);
+ }
+
+ var output = [];
+ var flags = (separator.ignoreCase ? 'i' : '') +
+ (separator.multiline ? 'm' : '') +
+ (separator.extended ? 'x' : '') + // Proposed for ES6
+ (separator.sticky ? 'y' : ''), // Firefox 3+
+ lastLastIndex = 0,
+ // Make `global` and avoid `lastIndex` issues by working with a copy
+ separator2, match, lastIndex, lastLength;
+ var separatorCopy = new RegExp(separator.source, flags + 'g');
+ string += ''; // Type-convert
+ if (!compliantExecNpcg) {
+ // Doesn't need flags gy, but they don't hurt
+ separator2 = new RegExp('^' + separatorCopy.source + '$(?!\\s)', flags);
+ }
+ /* Values for `limit`, per the spec:
+ * If undefined: 4294967295 // Math.pow(2, 32) - 1
+ * If 0, Infinity, or NaN: 0
+ * If positive number: limit = Math.floor(limit); if (limit > 4294967295) limit -= 4294967296;
+ * If negative number: 4294967296 - Math.floor(Math.abs(limit))
+ * If other: Type-convert, then use the above rules
+ */
+ var splitLimit = typeof limit === 'undefined' ?
+ -1 >>> 0 : // Math.pow(2, 32) - 1
+ ES.ToUint32(limit);
+ match = separatorCopy.exec(string);
+ while (match) {
+ // `separatorCopy.lastIndex` is not reliable cross-browser
+ lastIndex = match.index + match[0].length;
+ if (lastIndex > lastLastIndex) {
+ output.push(string.slice(lastLastIndex, match.index));
+ // Fix browsers whose `exec` methods don't consistently return `undefined` for
+ // nonparticipating capturing groups
+ if (!compliantExecNpcg && match.length > 1) {
+ /*eslint-disable no-loop-func */
+ match[0].replace(separator2, function () {
+ for (var i = 1; i < arguments.length - 2; i++) {
+ if (typeof arguments[i] === 'undefined') {
+ match[i] = void 0;
+ }
+ }
+ });
+ /*eslint-enable no-loop-func */
+ }
+ if (match.length > 1 && match.index < string.length) {
+ array_push.apply(output, match.slice(1));
+ }
+ lastLength = match[0].length;
+ lastLastIndex = lastIndex;
+ if (output.length >= splitLimit) {
+ break;
+ }
+ }
+ if (separatorCopy.lastIndex === match.index) {
+ separatorCopy.lastIndex++; // Avoid an infinite loop
+ }
+ match = separatorCopy.exec(string);
+ }
+ if (lastLastIndex === string.length) {
+ if (lastLength || !separatorCopy.test('')) {
+ output.push('');
+ }
+ } else {
+ output.push(string.slice(lastLastIndex));
+ }
+ return output.length > splitLimit ? output.slice(0, splitLimit) : output;
+ };
+ }());
+
+// [bugfix, chrome]
+// If separator is undefined, then the result array contains just one String,
+// which is the this value (converted to a String). If limit is not undefined,
+// then the output array is truncated so that it contains no more than limit
+// elements.
+// "0".split(undefined, 0) -> []
+} else if ('0'.split(void 0, 0).length) {
+ StringPrototype.split = function split(separator, limit) {
+ if (typeof separator === 'undefined' && limit === 0) { return []; }
+ return string_split.call(this, separator, limit);
+ };
+}
+
+var str_replace = StringPrototype.replace;
+var replaceReportsGroupsCorrectly = (function () {
+ var groups = [];
+ 'x'.replace(/x(.)?/g, function (match, group) {
+ groups.push(group);
+ });
+ return groups.length === 1 && typeof groups[0] === 'undefined';
+}());
+
+if (!replaceReportsGroupsCorrectly) {
+ StringPrototype.replace = function replace(searchValue, replaceValue) {
+ var isFn = isCallable(replaceValue);
+ var hasCapturingGroups = isRegex(searchValue) && (/\)[*?]/).test(searchValue.source);
+ if (!isFn || !hasCapturingGroups) {
+ return str_replace.call(this, searchValue, replaceValue);
+ } else {
+ var wrappedReplaceValue = function (match) {
+ var length = arguments.length;
+ var originalLastIndex = searchValue.lastIndex;
+ searchValue.lastIndex = 0;
+ var args = searchValue.exec(match) || [];
+ searchValue.lastIndex = originalLastIndex;
+ args.push(arguments[length - 2], arguments[length - 1]);
+ return replaceValue.apply(this, args);
+ };
+ return str_replace.call(this, searchValue, wrappedReplaceValue);
+ }
+ };
+}
+
+// ECMA-262, 3rd B.2.3
+// Not an ECMAScript standard, although ECMAScript 3rd Edition has a
+// non-normative section suggesting uniform semantics and it should be
+// normalized across all browsers
+// [bugfix, IE lt 9] IE < 9 substr() with negative value not working in IE
+var string_substr = StringPrototype.substr;
+var hasNegativeSubstrBug = ''.substr && '0b'.substr(-1) !== 'b';
+defineProperties(StringPrototype, {
+ substr: function substr(start, length) {
+ var normalizedStart = start;
+ if (start < 0) {
+ normalizedStart = Math.max(this.length + start, 0);
+ }
+ return string_substr.call(this, normalizedStart, length);
+ }
+}, hasNegativeSubstrBug);
+
+// ES5 15.5.4.20
+// whitespace from: http://es5.github.io/#x15.5.4.20
+var ws = '\x09\x0A\x0B\x0C\x0D\x20\xA0\u1680\u180E\u2000\u2001\u2002\u2003' +
+ '\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u3000\u2028' +
+ '\u2029\uFEFF';
+var zeroWidth = '\u200b';
+var wsRegexChars = '[' + ws + ']';
+var trimBeginRegexp = new RegExp('^' + wsRegexChars + wsRegexChars + '*');
+var trimEndRegexp = new RegExp(wsRegexChars + wsRegexChars + '*$');
+var hasTrimWhitespaceBug = StringPrototype.trim && (ws.trim() || !zeroWidth.trim());
+defineProperties(StringPrototype, {
+ // http://blog.stevenlevithan.com/archives/faster-trim-javascript
+ // http://perfectionkills.com/whitespace-deviations/
+ trim: function trim() {
+ if (typeof this === 'undefined' || this === null) {
+ throw new TypeError("can't convert " + this + ' to object');
+ }
+ return String(this).replace(trimBeginRegexp, '').replace(trimEndRegexp, '');
+ }
+}, hasTrimWhitespaceBug);
+
+// ES-5 15.1.2.2
+if (parseInt(ws + '08') !== 8 || parseInt(ws + '0x16') !== 22) {
+ /*global parseInt: true */
+ parseInt = (function (origParseInt) {
+ var hexRegex = /^0[xX]/;
+ return function parseInt(str, radix) {
+ var string = String(str).trim();
+ var defaultedRadix = Number(radix) || (hexRegex.test(string) ? 16 : 10);
+ return origParseInt(string, defaultedRadix);
+ };
+ }(parseInt));
+}
+
+}));
diff --git a/www/wiki/resources/lib/html5shiv/html5shiv.js b/www/wiki/resources/lib/html5shiv/html5shiv.js
new file mode 100644
index 00000000..45ea723d
--- /dev/null
+++ b/www/wiki/resources/lib/html5shiv/html5shiv.js
@@ -0,0 +1,326 @@
+/**
+* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
+*/
+;(function(window, document) {
+/*jshint evil:true */
+ /** version */
+ var version = '3.7.3';
+
+ /** Preset options */
+ var options = window.html5 || {};
+
+ /** Used to skip problem elements */
+ var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
+
+ /** Not all elements can be cloned in IE **/
+ var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
+
+ /** Detect whether the browser supports default html5 styles */
+ var supportsHtml5Styles;
+
+ /** Name of the expando, to work with multiple documents or to re-shiv one document */
+ var expando = '_html5shiv';
+
+ /** The id for the the documents expando */
+ var expanID = 0;
+
+ /** Cached data for each document */
+ var expandoData = {};
+
+ /** Detect whether the browser supports unknown elements */
+ var supportsUnknownElements;
+
+ (function() {
+ try {
+ var a = document.createElement('a');
+ a.innerHTML = '<xyz></xyz>';
+ //if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
+ supportsHtml5Styles = ('hidden' in a);
+
+ supportsUnknownElements = a.childNodes.length == 1 || (function() {
+ // assign a false positive if unable to shiv
+ (document.createElement)('a');
+ var frag = document.createDocumentFragment();
+ return (
+ typeof frag.cloneNode == 'undefined' ||
+ typeof frag.createDocumentFragment == 'undefined' ||
+ typeof frag.createElement == 'undefined'
+ );
+ }());
+ } catch(e) {
+ // assign a false positive if detection fails => unable to shiv
+ supportsHtml5Styles = true;
+ supportsUnknownElements = true;
+ }
+
+ }());
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Creates a style sheet with the given CSS text and adds it to the document.
+ * @private
+ * @param {Document} ownerDocument The document.
+ * @param {String} cssText The CSS text.
+ * @returns {StyleSheet} The style element.
+ */
+ function addStyleSheet(ownerDocument, cssText) {
+ var p = ownerDocument.createElement('p'),
+ parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
+
+ p.innerHTML = 'x<style>' + cssText + '</style>';
+ return parent.insertBefore(p.lastChild, parent.firstChild);
+ }
+
+ /**
+ * Returns the value of `html5.elements` as an array.
+ * @private
+ * @returns {Array} An array of shived element node names.
+ */
+ function getElements() {
+ var elements = html5.elements;
+ return typeof elements == 'string' ? elements.split(' ') : elements;
+ }
+
+ /**
+ * Extends the built-in list of html5 elements
+ * @memberOf html5
+ * @param {String|Array} newElements whitespace separated list or array of new element names to shiv
+ * @param {Document} ownerDocument The context document.
+ */
+ function addElements(newElements, ownerDocument) {
+ var elements = html5.elements;
+ if(typeof elements != 'string'){
+ elements = elements.join(' ');
+ }
+ if(typeof newElements != 'string'){
+ newElements = newElements.join(' ');
+ }
+ html5.elements = elements +' '+ newElements;
+ shivDocument(ownerDocument);
+ }
+
+ /**
+ * Returns the data associated to the given document
+ * @private
+ * @param {Document} ownerDocument The document.
+ * @returns {Object} An object of data.
+ */
+ function getExpandoData(ownerDocument) {
+ var data = expandoData[ownerDocument[expando]];
+ if (!data) {
+ data = {};
+ expanID++;
+ ownerDocument[expando] = expanID;
+ expandoData[expanID] = data;
+ }
+ return data;
+ }
+
+ /**
+ * returns a shived element for the given nodeName and document
+ * @memberOf html5
+ * @param {String} nodeName name of the element
+ * @param {Document|DocumentFragment} ownerDocument The context document.
+ * @returns {Object} The shived element.
+ */
+ function createElement(nodeName, ownerDocument, data){
+ if (!ownerDocument) {
+ ownerDocument = document;
+ }
+ if(supportsUnknownElements){
+ return ownerDocument.createElement(nodeName);
+ }
+ if (!data) {
+ data = getExpandoData(ownerDocument);
+ }
+ var node;
+
+ if (data.cache[nodeName]) {
+ node = data.cache[nodeName].cloneNode();
+ } else if (saveClones.test(nodeName)) {
+ node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
+ } else {
+ node = data.createElem(nodeName);
+ }
+
+ // Avoid adding some elements to fragments in IE < 9 because
+ // * Attributes like `name` or `type` cannot be set/changed once an element
+ // is inserted into a document/fragment
+ // * Link elements with `src` attributes that are inaccessible, as with
+ // a 403 response, will cause the tab/window to crash
+ // * Script elements appended to fragments will execute when their `src`
+ // or `text` property is set
+ return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
+ }
+
+ /**
+ * returns a shived DocumentFragment for the given document
+ * @memberOf html5
+ * @param {Document} ownerDocument The context document.
+ * @returns {Object} The shived DocumentFragment.
+ */
+ function createDocumentFragment(ownerDocument, data){
+ if (!ownerDocument) {
+ ownerDocument = document;
+ }
+ if(supportsUnknownElements){
+ return ownerDocument.createDocumentFragment();
+ }
+ data = data || getExpandoData(ownerDocument);
+ var clone = data.frag.cloneNode(),
+ i = 0,
+ elems = getElements(),
+ l = elems.length;
+ for(;i<l;i++){
+ clone.createElement(elems[i]);
+ }
+ return clone;
+ }
+
+ /**
+ * Shivs the `createElement` and `createDocumentFragment` methods of the document.
+ * @private
+ * @param {Document|DocumentFragment} ownerDocument The document.
+ * @param {Object} data of the document.
+ */
+ function shivMethods(ownerDocument, data) {
+ if (!data.cache) {
+ data.cache = {};
+ data.createElem = ownerDocument.createElement;
+ data.createFrag = ownerDocument.createDocumentFragment;
+ data.frag = data.createFrag();
+ }
+
+
+ ownerDocument.createElement = function(nodeName) {
+ //abort shiv
+ if (!html5.shivMethods) {
+ return data.createElem(nodeName);
+ }
+ return createElement(nodeName, ownerDocument, data);
+ };
+
+ ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
+ 'var n=f.cloneNode(),c=n.createElement;' +
+ 'h.shivMethods&&(' +
+ // unroll the `createElement` calls
+ getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
+ data.createElem(nodeName);
+ data.frag.createElement(nodeName);
+ return 'c("' + nodeName + '")';
+ }) +
+ ');return n}'
+ )(html5, data.frag);
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * Shivs the given document.
+ * @memberOf html5
+ * @param {Document} ownerDocument The document to shiv.
+ * @returns {Document} The shived document.
+ */
+ function shivDocument(ownerDocument) {
+ if (!ownerDocument) {
+ ownerDocument = document;
+ }
+ var data = getExpandoData(ownerDocument);
+
+ if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
+ data.hasCSS = !!addStyleSheet(ownerDocument,
+ // corrects block display not defined in IE6/7/8/9
+ 'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
+ // adds styling not present in IE6/7/8/9
+ 'mark{background:#FF0;color:#000}' +
+ // hides non-rendered elements
+ 'template{display:none}'
+ );
+ }
+ if (!supportsUnknownElements) {
+ shivMethods(ownerDocument, data);
+ }
+ return ownerDocument;
+ }
+
+ /*--------------------------------------------------------------------------*/
+
+ /**
+ * The `html5` object is exposed so that more elements can be shived and
+ * existing shiving can be detected on iframes.
+ * @type Object
+ * @example
+ *
+ * // options can be changed before the script is included
+ * html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
+ */
+ var html5 = {
+
+ /**
+ * An array or space separated string of node names of the elements to shiv.
+ * @memberOf html5
+ * @type Array|String
+ */
+ 'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
+
+ /**
+ * current version of html5shiv
+ */
+ 'version': version,
+
+ /**
+ * A flag to indicate that the HTML5 style sheet should be inserted.
+ * @memberOf html5
+ * @type Boolean
+ */
+ 'shivCSS': (options.shivCSS !== false),
+
+ /**
+ * Is equal to true if a browser supports creating unknown/HTML5 elements
+ * @memberOf html5
+ * @type boolean
+ */
+ 'supportsUnknownElements': supportsUnknownElements,
+
+ /**
+ * A flag to indicate that the document's `createElement` and `createDocumentFragment`
+ * methods should be overwritten.
+ * @memberOf html5
+ * @type Boolean
+ */
+ 'shivMethods': (options.shivMethods !== false),
+
+ /**
+ * A string to describe the type of `html5` object ("default" or "default print").
+ * @memberOf html5
+ * @type String
+ */
+ 'type': 'default',
+
+ // shivs the document according to the specified `html5` object options
+ 'shivDocument': shivDocument,
+
+ //creates a shived element
+ createElement: createElement,
+
+ //creates a shived documentFragment
+ createDocumentFragment: createDocumentFragment,
+
+ //extends list of elements
+ addElements: addElements
+ };
+
+ /*--------------------------------------------------------------------------*/
+
+ // expose html5
+ window.html5 = html5;
+
+ // shiv the document
+ shivDocument(document);
+
+ if(typeof module == 'object' && module.exports){
+ module.exports = html5;
+ }
+
+}(typeof window !== "undefined" ? window : this, document));
diff --git a/www/wiki/resources/lib/html5shiv/html5shiv.min.js b/www/wiki/resources/lib/html5shiv/html5shiv.min.js
new file mode 100644
index 00000000..355afd10
--- /dev/null
+++ b/www/wiki/resources/lib/html5shiv/html5shiv.min.js
@@ -0,0 +1,4 @@
+/**
+* @preserve HTML5 Shiv 3.7.3 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
+*/
+!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document); \ No newline at end of file
diff --git a/www/wiki/resources/lib/jquery.chosen/LICENSE b/www/wiki/resources/lib/jquery.chosen/LICENSE
new file mode 100644
index 00000000..0675dc52
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.chosen/LICENSE
@@ -0,0 +1,24 @@
+# Chosen, a Select Box Enhancer for jQuery and Protoype
+## by Patrick Filler for [Harvest](http://getharvest.com)
+
+Available for use under the [MIT License](http://en.wikipedia.org/wiki/MIT_License)
+
+Copyright (c) 2011-2013 by Harvest
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/www/wiki/resources/lib/jquery.chosen/chosen-sprite.png b/www/wiki/resources/lib/jquery.chosen/chosen-sprite.png
new file mode 100644
index 00000000..3611ae4a
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.chosen/chosen-sprite.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.chosen/chosen-sprite@2x.png b/www/wiki/resources/lib/jquery.chosen/chosen-sprite@2x.png
new file mode 100644
index 00000000..bd61d963
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.chosen/chosen-sprite@2x.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.chosen/chosen.css b/www/wiki/resources/lib/jquery.chosen/chosen.css
new file mode 100644
index 00000000..17793ed7
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.chosen/chosen.css
@@ -0,0 +1,440 @@
+/* @group Base */
+.chzn-container {
+ font-size: 13px;
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+ zoom: 1;
+ *display: inline;
+}
+.chzn-container .chzn-drop {
+ background: #fff;
+ border: 1px solid #aaa;
+ border-top: 0;
+ position: absolute;
+ top: 100%;
+ left: -9999px;
+ -webkit-box-shadow: 0 4px 5px rgba(0,0,0,.15);
+ -moz-box-shadow : 0 4px 5px rgba(0,0,0,.15);
+ box-shadow : 0 4px 5px rgba(0,0,0,.15);
+ z-index: 1010;
+ width: 100%;
+ -moz-box-sizing : border-box;
+ -ms-box-sizing : border-box;
+ -webkit-box-sizing: border-box;
+ -khtml-box-sizing : border-box;
+ box-sizing : border-box;
+}
+
+.chzn-container.chzn-with-drop .chzn-drop {
+ left: 0;
+}
+
+/* @end */
+
+/* @group Single Chosen */
+.chzn-container-single .chzn-single {
+ background-color: #ffffff;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffff', endColorstr='#eeeeee', GradientType=0 );
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #ffffff), color-stop(50%, #f6f6f6), color-stop(52%, #eeeeee), color-stop(100%, #f4f4f4));
+ background-image: -webkit-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
+ background-image: -moz-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
+ background-image: -o-linear-gradient(top, #ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
+ background-image: linear-gradient(#ffffff 20%, #f6f6f6 50%, #eeeeee 52%, #f4f4f4 100%);
+ -webkit-border-radius: 5px;
+ -moz-border-radius : 5px;
+ border-radius : 5px;
+ -moz-background-clip : padding;
+ -webkit-background-clip: padding-box;
+ background-clip : padding-box;
+ border: 1px solid #aaaaaa;
+ -webkit-box-shadow: 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
+ -moz-box-shadow : 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
+ box-shadow : 0 0 3px #ffffff inset, 0 1px 1px rgba(0,0,0,0.1);
+ display: block;
+ overflow: hidden;
+ white-space: nowrap;
+ position: relative;
+ height: 23px;
+ line-height: 24px;
+ padding: 0 0 0 8px;
+ color: #444444;
+ text-decoration: none;
+}
+.chzn-container-single .chzn-default {
+ color: #999;
+}
+.chzn-container-single .chzn-single span {
+ margin-right: 26px;
+ display: block;
+ overflow: hidden;
+ white-space: nowrap;
+ -o-text-overflow: ellipsis;
+ -ms-text-overflow: ellipsis;
+ text-overflow: ellipsis;
+}
+.chzn-container-single .chzn-single abbr {
+ display: block;
+ position: absolute;
+ right: 26px;
+ top: 6px;
+ width: 12px;
+ height: 12px;
+ font-size: 1px;
+ background: url('chosen-sprite.png') -42px 1px no-repeat;
+}
+.chzn-container-single .chzn-single abbr:hover {
+ background-position: -42px -10px;
+}
+.chzn-container-single.chzn-disabled .chzn-single abbr:hover {
+ background-position: -42px -10px;
+}
+.chzn-container-single .chzn-single div {
+ position: absolute;
+ right: 0;
+ top: 0;
+ display: block;
+ height: 100%;
+ width: 18px;
+}
+.chzn-container-single .chzn-single div b {
+ background: url('chosen-sprite.png') no-repeat 0px 2px;
+ display: block;
+ width: 100%;
+ height: 100%;
+}
+.chzn-container-single .chzn-search {
+ padding: 3px 4px;
+ position: relative;
+ margin: 0;
+ white-space: nowrap;
+ z-index: 1010;
+}
+.chzn-container-single .chzn-search input {
+ background: #fff url('chosen-sprite.png') no-repeat 100% -20px;
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat 100% -20px, -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat 100% -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
+ margin: 1px 0;
+ padding: 4px 20px 4px 5px;
+ outline: 0;
+ border: 1px solid #aaa;
+ font-family: sans-serif;
+ font-size: 1em;
+ width: 100%;
+ -moz-box-sizing : border-box;
+ -ms-box-sizing : border-box;
+ -webkit-box-sizing: border-box;
+ -khtml-box-sizing : border-box;
+ box-sizing : border-box;
+}
+.chzn-container-single .chzn-drop {
+ margin-top: -1px;
+ -webkit-border-radius: 0 0 4px 4px;
+ -moz-border-radius : 0 0 4px 4px;
+ border-radius : 0 0 4px 4px;
+ -moz-background-clip : padding;
+ -webkit-background-clip: padding-box;
+ background-clip : padding-box;
+}
+.chzn-container-single-nosearch .chzn-search {
+ position: absolute;
+ left: -9999px;
+}
+/* @end */
+
+/* @group Multi Chosen */
+.chzn-container-multi .chzn-choices {
+ background-color: #fff;
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
+ background-image: -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background-image: -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background-image: -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background-image: linear-gradient(#eeeeee 1%, #ffffff 15%);
+ border: 1px solid #aaa;
+ margin: 0;
+ padding: 0;
+ cursor: text;
+ overflow: hidden;
+ height: auto !important;
+ height: 1%;
+ position: relative;
+ width: 100%;
+ -moz-box-sizing : border-box;
+ -ms-box-sizing : border-box;
+ -webkit-box-sizing: border-box;
+ -khtml-box-sizing : border-box;
+ box-sizing : border-box;
+}
+.chzn-container-multi .chzn-choices li {
+ float: left;
+ list-style: none;
+}
+.chzn-container-multi .chzn-choices .search-field {
+ white-space: nowrap;
+ margin: 0;
+ padding: 0;
+}
+.chzn-container-multi .chzn-choices .search-field input {
+ color: #666;
+ background: transparent !important;
+ border: 0 !important;
+ font-family: sans-serif;
+ font-size: 100%;
+ height: 15px;
+ padding: 5px;
+ margin: 1px 0;
+ outline: 0;
+ -webkit-box-shadow: none;
+ -moz-box-shadow : none;
+ box-shadow : none;
+}
+.chzn-container-multi .chzn-choices .search-field .default {
+ color: #999;
+}
+.chzn-container-multi .chzn-choices .search-choice {
+ -webkit-border-radius: 3px;
+ -moz-border-radius : 3px;
+ border-radius : 3px;
+ -moz-background-clip : padding;
+ -webkit-background-clip: padding-box;
+ background-clip : padding-box;
+ background-color: #e4e4e4;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 );
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
+ background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: linear-gradient(#f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ -webkit-box-shadow: 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
+ -moz-box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
+ box-shadow : 0 0 2px #ffffff inset, 0 1px 0 rgba(0,0,0,0.05);
+ color: #333;
+ border: 1px solid #aaaaaa;
+ line-height: 13px;
+ padding: 3px 20px 3px 5px;
+ margin: 3px 0 3px 5px;
+ position: relative;
+ cursor: default;
+}
+.chzn-container-multi .chzn-choices .search-choice.search-choice-disabled {
+ background-color: #e4e4e4;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f4f4f4', endColorstr='#eeeeee', GradientType=0 );
+ background-image: -webkit-gradient(linear, 0% 0%, 0% 100%, color-stop(20%, #f4f4f4), color-stop(50%, #f0f0f0), color-stop(52%, #e8e8e8), color-stop(100%, #eeeeee));
+ background-image: -webkit-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -moz-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -o-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: -ms-linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ background-image: linear-gradient(top, #f4f4f4 20%, #f0f0f0 50%, #e8e8e8 52%, #eeeeee 100%);
+ color: #666;
+ border: 1px solid #cccccc;
+ padding-right: 5px;
+}
+.chzn-container-multi .chzn-choices .search-choice-focus {
+ background: #d4d4d4;
+}
+.chzn-container-multi .chzn-choices .search-choice .search-choice-close {
+ display: block;
+ position: absolute;
+ right: 3px;
+ top: 4px;
+ width: 12px;
+ height: 12px;
+ font-size: 1px;
+ background: url('chosen-sprite.png') -42px 1px no-repeat;
+}
+.chzn-container-multi .chzn-choices .search-choice .search-choice-close:hover {
+ background-position: -42px -10px;
+}
+.chzn-container-multi .chzn-choices .search-choice-focus .search-choice-close {
+ background-position: -42px -10px;
+}
+/* @end */
+
+/* @group Results */
+.chzn-container .chzn-results {
+ margin: 0 4px 4px 0;
+ max-height: 240px;
+ padding: 0 0 0 4px;
+ position: relative;
+ overflow-x: hidden;
+ overflow-y: auto;
+ -webkit-overflow-scrolling: touch;
+}
+.chzn-container-multi .chzn-results {
+ margin: 0;
+ padding: 0;
+}
+.chzn-container .chzn-results li {
+ display: none;
+ line-height: 15px;
+ padding: 5px 6px;
+ margin: 0;
+ list-style: none;
+}
+.chzn-container .chzn-results .active-result {
+ cursor: pointer;
+ display: list-item;
+}
+.chzn-container .chzn-results .highlighted {
+ background-color: #3875d7;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#3875d7', endColorstr='#2a62bc', GradientType=0 );
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #3875d7), color-stop(90%, #2a62bc));
+ background-image: -webkit-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
+ background-image: -moz-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
+ background-image: -o-linear-gradient(top, #3875d7 20%, #2a62bc 90%);
+ background-image: linear-gradient(#3875d7 20%, #2a62bc 90%);
+ color: #fff;
+}
+.chzn-container .chzn-results li em {
+ background: #feffde;
+ font-style: normal;
+}
+.chzn-container .chzn-results .highlighted em {
+ background: transparent;
+}
+.chzn-container .chzn-results .no-results {
+ background: #f4f4f4;
+ display: list-item;
+}
+.chzn-container .chzn-results .group-result {
+ cursor: default;
+ color: #999;
+ font-weight: bold;
+}
+.chzn-container .chzn-results .group-option {
+ padding-left: 15px;
+}
+.chzn-container-multi .chzn-drop .result-selected {
+ display: none;
+}
+.chzn-container .chzn-results-scroll {
+ background: white;
+ margin: 0 4px;
+ position: absolute;
+ text-align: center;
+ width: 321px; /* This should by dynamic with js */
+ z-index: 1;
+}
+.chzn-container .chzn-results-scroll span {
+ display: inline-block;
+ height: 17px;
+ text-indent: -5000px;
+ width: 9px;
+}
+.chzn-container .chzn-results-scroll-down {
+ bottom: 0;
+}
+.chzn-container .chzn-results-scroll-down span {
+ background: url('chosen-sprite.png') no-repeat -4px -3px;
+}
+.chzn-container .chzn-results-scroll-up span {
+ background: url('chosen-sprite.png') no-repeat -22px -3px;
+}
+/* @end */
+
+/* @group Active */
+.chzn-container-active .chzn-single {
+ -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
+ -moz-box-shadow : 0 0 5px rgba(0,0,0,.3);
+ box-shadow : 0 0 5px rgba(0,0,0,.3);
+ border: 1px solid #5897fb;
+}
+.chzn-container-active.chzn-with-drop .chzn-single {
+ border: 1px solid #aaa;
+ -webkit-box-shadow: 0 1px 0 #fff inset;
+ -moz-box-shadow : 0 1px 0 #fff inset;
+ box-shadow : 0 1px 0 #fff inset;
+ background-color: #eee;
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#eeeeee', endColorstr='#ffffff', GradientType=0 );
+ background-image: -webkit-gradient(linear, 0 0, 0 100%, color-stop(20%, #eeeeee), color-stop(80%, #ffffff));
+ background-image: -webkit-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
+ background-image: -moz-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
+ background-image: -o-linear-gradient(top, #eeeeee 20%, #ffffff 80%);
+ background-image: linear-gradient(#eeeeee 20%, #ffffff 80%);
+ -webkit-border-bottom-left-radius : 0;
+ -webkit-border-bottom-right-radius: 0;
+ -moz-border-radius-bottomleft : 0;
+ -moz-border-radius-bottomright: 0;
+ border-bottom-left-radius : 0;
+ border-bottom-right-radius: 0;
+}
+.chzn-container-active.chzn-with-drop .chzn-single div {
+ background: transparent;
+ border-left: none;
+}
+.chzn-container-active.chzn-with-drop .chzn-single div b {
+ background-position: -18px 2px;
+}
+.chzn-container-active .chzn-choices {
+ -webkit-box-shadow: 0 0 5px rgba(0,0,0,.3);
+ -moz-box-shadow : 0 0 5px rgba(0,0,0,.3);
+ box-shadow : 0 0 5px rgba(0,0,0,.3);
+ border: 1px solid #5897fb;
+}
+.chzn-container-active .chzn-choices .search-field input {
+ color: #111 !important;
+}
+/* @end */
+
+/* @group Disabled Support */
+.chzn-disabled {
+ cursor: default;
+ opacity:0.5 !important;
+}
+.chzn-disabled .chzn-single {
+ cursor: default;
+}
+.chzn-disabled .chzn-choices .search-choice .search-choice-close {
+ cursor: default;
+}
+
+/* @group Right to Left */
+.chzn-rtl { text-align: right; }
+.chzn-rtl .chzn-single { padding: 0 8px 0 0; overflow: visible; }
+.chzn-rtl .chzn-single span { margin-left: 26px; margin-right: 0; direction: rtl; }
+
+.chzn-rtl .chzn-single div { left: 3px; right: auto; }
+.chzn-rtl .chzn-single abbr {
+ left: 26px;
+ right: auto;
+}
+.chzn-rtl .chzn-choices .search-field input { direction: rtl; }
+.chzn-rtl .chzn-choices li { float: right; }
+.chzn-rtl .chzn-choices .search-choice { padding: 3px 5px 3px 19px; margin: 3px 5px 3px 0; }
+.chzn-rtl .chzn-choices .search-choice .search-choice-close { left: 4px; right: auto; }
+.chzn-rtl .chzn-search { left: 9999px; }
+.chzn-rtl.chzn-with-drop .chzn-search { left: 0px; }
+.chzn-rtl .chzn-drop { left: 9999px; }
+.chzn-rtl.chzn-container-single .chzn-results { margin: 0 0 4px 4px; padding: 0 4px 0 0; }
+.chzn-rtl .chzn-results .group-option { padding-left: 0; padding-right: 15px; }
+.chzn-rtl.chzn-container-active.chzn-with-drop .chzn-single div { border-right: none; }
+.chzn-rtl .chzn-search input {
+ background: #fff url('chosen-sprite.png') no-repeat -30px -20px;
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-gradient(linear, 0 0, 0 100%, color-stop(1%, #eeeeee), color-stop(15%, #ffffff));
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -webkit-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -moz-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat -30px -20px, -o-linear-gradient(top, #eeeeee 1%, #ffffff 15%);
+ background: url('chosen-sprite.png') no-repeat -30px -20px, linear-gradient(#eeeeee 1%, #ffffff 15%);
+ padding: 4px 5px 4px 20px;
+ direction: rtl;
+}
+.chzn-container-single.chzn-rtl .chzn-single div b {
+ background-position: 6px 2px;
+}
+.chzn-container-single.chzn-rtl.chzn-with-drop .chzn-single div b {
+ background-position: -12px 2px;
+}
+/* @end */
+
+/* @group Retina compatibility */
+@media only screen and (-webkit-min-device-pixel-ratio: 2), only screen and (min-resolution: 144dpi) {
+ .chzn-rtl .chzn-search input, .chzn-container-single .chzn-single abbr, .chzn-container-single .chzn-single div b, .chzn-container-single .chzn-search input, .chzn-container-multi .chzn-choices .search-choice .search-choice-close, .chzn-container .chzn-results-scroll-down span, .chzn-container .chzn-results-scroll-up span {
+ background-image: url('chosen-sprite@2x.png') !important;
+ background-repeat: no-repeat !important;
+ background-size: 52px 37px !important;
+ }
+}
+/* @end */
diff --git a/www/wiki/resources/lib/jquery.chosen/chosen.jquery.js b/www/wiki/resources/lib/jquery.chosen/chosen.jquery.js
new file mode 100644
index 00000000..745174f7
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.chosen/chosen.jquery.js
@@ -0,0 +1,1103 @@
+// Chosen, a Select Box Enhancer for jQuery and Protoype
+// by Patrick Filler for Harvest, http://getharvest.com
+//
+// Version 0.9.14
+// Full source at https://github.com/harvesthq/chosen
+// Copyright (c) 2011 Harvest http://getharvest.com
+
+// MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
+// This file is generated by `cake build`, do not edit it by hand.
+(function() {
+ var SelectParser;
+
+ SelectParser = (function() {
+
+ function SelectParser() {
+ this.options_index = 0;
+ this.parsed = [];
+ }
+
+ SelectParser.prototype.add_node = function(child) {
+ if (child.nodeName.toUpperCase() === "OPTGROUP") {
+ return this.add_group(child);
+ } else {
+ return this.add_option(child);
+ }
+ };
+
+ SelectParser.prototype.add_group = function(group) {
+ var group_position, option, _i, _len, _ref, _results;
+ group_position = this.parsed.length;
+ this.parsed.push({
+ array_index: group_position,
+ group: true,
+ label: group.label,
+ children: 0,
+ disabled: group.disabled
+ });
+ _ref = group.childNodes;
+ _results = [];
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ option = _ref[_i];
+ _results.push(this.add_option(option, group_position, group.disabled));
+ }
+ return _results;
+ };
+
+ SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
+ if (option.nodeName.toUpperCase() === "OPTION") {
+ if (option.text !== "") {
+ if (group_position != null) {
+ this.parsed[group_position].children += 1;
+ }
+ this.parsed.push({
+ array_index: this.parsed.length,
+ options_index: this.options_index,
+ value: option.value,
+ text: option.text,
+ html: option.innerHTML,
+ selected: option.selected,
+ disabled: group_disabled === true ? group_disabled : option.disabled,
+ group_array_index: group_position,
+ classes: option.className,
+ style: option.style.cssText
+ });
+ } else {
+ this.parsed.push({
+ array_index: this.parsed.length,
+ options_index: this.options_index,
+ empty: true
+ });
+ }
+ return this.options_index += 1;
+ }
+ };
+
+ return SelectParser;
+
+ })();
+
+ SelectParser.select_to_array = function(select) {
+ var child, parser, _i, _len, _ref;
+ parser = new SelectParser();
+ _ref = select.childNodes;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ child = _ref[_i];
+ parser.add_node(child);
+ }
+ return parser.parsed;
+ };
+
+ this.SelectParser = SelectParser;
+
+}).call(this);
+
+/*
+Chosen source: generate output using 'cake build'
+Copyright (c) 2011 by Harvest
+*/
+
+
+(function() {
+ var AbstractChosen, root;
+
+ root = this;
+
+ AbstractChosen = (function() {
+
+ function AbstractChosen(form_field, options) {
+ this.form_field = form_field;
+ this.options = options != null ? options : {};
+ if (!AbstractChosen.browser_is_supported()) {
+ return;
+ }
+ this.is_multiple = this.form_field.multiple;
+ this.set_default_text();
+ this.set_default_values();
+ this.setup();
+ this.set_up_html();
+ this.register_observers();
+ this.finish_setup();
+ }
+
+ AbstractChosen.prototype.set_default_values = function() {
+ var _this = this;
+ this.click_test_action = function(evt) {
+ return _this.test_active_click(evt);
+ };
+ this.activate_action = function(evt) {
+ return _this.activate_field(evt);
+ };
+ this.active_field = false;
+ this.mouse_on_container = false;
+ this.results_showing = false;
+ this.result_highlighted = null;
+ this.result_single_selected = null;
+ this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
+ this.disable_search_threshold = this.options.disable_search_threshold || 0;
+ this.disable_search = this.options.disable_search || false;
+ this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
+ this.search_contains = this.options.search_contains || false;
+ this.choices = 0;
+ this.single_backstroke_delete = this.options.single_backstroke_delete || false;
+ this.max_selected_options = this.options.max_selected_options || Infinity;
+ return this.inherit_select_classes = this.options.inherit_select_classes || false;
+ };
+
+ AbstractChosen.prototype.set_default_text = function() {
+ if (this.form_field.getAttribute("data-placeholder")) {
+ this.default_text = this.form_field.getAttribute("data-placeholder");
+ } else if (this.is_multiple) {
+ this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
+ } else {
+ this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
+ }
+ return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
+ };
+
+ AbstractChosen.prototype.mouse_enter = function() {
+ return this.mouse_on_container = true;
+ };
+
+ AbstractChosen.prototype.mouse_leave = function() {
+ return this.mouse_on_container = false;
+ };
+
+ AbstractChosen.prototype.input_focus = function(evt) {
+ var _this = this;
+ if (this.is_multiple) {
+ if (!this.active_field) {
+ return setTimeout((function() {
+ return _this.container_mousedown();
+ }), 50);
+ }
+ } else {
+ if (!this.active_field) {
+ return this.activate_field();
+ }
+ }
+ };
+
+ AbstractChosen.prototype.input_blur = function(evt) {
+ var _this = this;
+ if (!this.mouse_on_container) {
+ this.active_field = false;
+ return setTimeout((function() {
+ return _this.blur_test();
+ }), 100);
+ }
+ };
+
+ AbstractChosen.prototype.result_add_option = function(option) {
+ var classes, style;
+ if (!option.disabled) {
+ option.dom_id = this.container_id + "_o_" + option.array_index;
+ classes = option.selected && this.is_multiple ? [] : ["active-result"];
+ if (option.selected) {
+ classes.push("result-selected");
+ }
+ if (option.group_array_index != null) {
+ classes.push("group-option");
+ }
+ if (option.classes !== "") {
+ classes.push(option.classes);
+ }
+ style = option.style.cssText !== "" ? " style=\"" + option.style + "\"" : "";
+ return '<li id="' + option.dom_id + '" class="' + classes.join(' ') + '"' + style + '>' + option.html + '</li>';
+ } else {
+ return "";
+ }
+ };
+
+ AbstractChosen.prototype.results_update_field = function() {
+ this.set_default_text();
+ if (!this.is_multiple) {
+ this.results_reset_cleanup();
+ }
+ this.result_clear_highlight();
+ this.result_single_selected = null;
+ return this.results_build();
+ };
+
+ AbstractChosen.prototype.results_toggle = function() {
+ if (this.results_showing) {
+ return this.results_hide();
+ } else {
+ return this.results_show();
+ }
+ };
+
+ AbstractChosen.prototype.results_search = function(evt) {
+ if (this.results_showing) {
+ return this.winnow_results();
+ } else {
+ return this.results_show();
+ }
+ };
+
+ AbstractChosen.prototype.choices_click = function(evt) {
+ evt.preventDefault();
+ if (!this.results_showing) {
+ return this.results_show();
+ }
+ };
+
+ AbstractChosen.prototype.keyup_checker = function(evt) {
+ var stroke, _ref;
+ stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
+ this.search_field_scale();
+ switch (stroke) {
+ case 8:
+ if (this.is_multiple && this.backstroke_length < 1 && this.choices > 0) {
+ return this.keydown_backstroke();
+ } else if (!this.pending_backstroke) {
+ this.result_clear_highlight();
+ return this.results_search();
+ }
+ break;
+ case 13:
+ evt.preventDefault();
+ if (this.results_showing) {
+ return this.result_select(evt);
+ }
+ break;
+ case 27:
+ if (this.results_showing) {
+ this.results_hide();
+ }
+ return true;
+ case 9:
+ case 38:
+ case 40:
+ case 16:
+ case 91:
+ case 17:
+ break;
+ default:
+ return this.results_search();
+ }
+ };
+
+ AbstractChosen.prototype.generate_field_id = function() {
+ var new_id;
+ new_id = this.generate_random_id();
+ this.form_field.id = new_id;
+ return new_id;
+ };
+
+ AbstractChosen.prototype.generate_random_char = function() {
+ var chars, newchar, rand;
+ chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ rand = Math.floor(Math.random() * chars.length);
+ return newchar = chars.substring(rand, rand + 1);
+ };
+
+ AbstractChosen.prototype.container_width = function() {
+ var width;
+ if (this.options.width != null) {
+ return this.options.width;
+ }
+ width = window.getComputedStyle != null ? parseFloat(window.getComputedStyle(this.form_field).getPropertyValue('width')) : (typeof jQuery !== "undefined" && jQuery !== null) && (this.form_field_jq != null) ? this.form_field_jq.outerWidth() : this.form_field.getWidth();
+ return width + "px";
+ };
+
+ AbstractChosen.browser_is_supported = function() {
+ var _ref;
+ if (window.navigator.appName === "Microsoft Internet Explorer") {
+ return (null !== (_ref = document.documentMode) && _ref >= 8);
+ }
+ return true;
+ };
+
+ AbstractChosen.default_multiple_text = "Select Some Options";
+
+ AbstractChosen.default_single_text = "Select an Option";
+
+ AbstractChosen.default_no_result_text = "No results match";
+
+ return AbstractChosen;
+
+ })();
+
+ root.AbstractChosen = AbstractChosen;
+
+}).call(this);
+
+/*
+Chosen source: generate output using 'cake build'
+Copyright (c) 2011 by Harvest
+*/
+
+
+(function() {
+ var $, Chosen, root,
+ __hasProp = {}.hasOwnProperty,
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
+
+ root = this;
+
+ $ = jQuery;
+
+ $.fn.extend({
+ chosen: function(options) {
+ if (!AbstractChosen.browser_is_supported()) {
+ return this;
+ }
+ return this.each(function(input_field) {
+ var $this;
+ $this = $(this);
+ if (!$this.hasClass("chzn-done")) {
+ return $this.data('chosen', new Chosen(this, options));
+ }
+ });
+ }
+ });
+
+ Chosen = (function(_super) {
+
+ __extends(Chosen, _super);
+
+ function Chosen() {
+ return Chosen.__super__.constructor.apply(this, arguments);
+ }
+
+ Chosen.prototype.setup = function() {
+ this.form_field_jq = $(this.form_field);
+ this.current_selectedIndex = this.form_field.selectedIndex;
+ return this.is_rtl = this.form_field_jq.hasClass("chzn-rtl");
+ };
+
+ Chosen.prototype.finish_setup = function() {
+ return this.form_field_jq.addClass("chzn-done");
+ };
+
+ Chosen.prototype.set_up_html = function() {
+ var container_classes, container_props;
+ this.container_id = this.form_field.id.length ? this.form_field.id.replace(/[^\w]/g, '_') : this.generate_field_id();
+ this.container_id += "_chzn";
+ container_classes = ["chzn-container"];
+ container_classes.push("chzn-container-" + (this.is_multiple ? "multi" : "single"));
+ if (this.inherit_select_classes && this.form_field.className) {
+ container_classes.push(this.form_field.className);
+ }
+ if (this.is_rtl) {
+ container_classes.push("chzn-rtl");
+ }
+ container_props = {
+ 'id': this.container_id,
+ 'class': container_classes.join(' '),
+ 'style': "width: " + (this.container_width()) + ";",
+ 'title': this.form_field.title
+ };
+ this.container = $("<div />", container_props);
+ if (this.is_multiple) {
+ this.container.html('<ul class="chzn-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:auto;" /></li></ul><div class="chzn-drop"><ul class="chzn-results"></ul></div>');
+ } else {
+ this.container.html('<a href="javascript:void(0)" class="chzn-single chzn-default" tabindex="-1"><span>' + this.default_text + '</span><div><b></b></div></a><div class="chzn-drop"><div class="chzn-search"><input type="text" autocomplete="off" /></div><ul class="chzn-results"></ul></div>');
+ }
+ this.form_field_jq.hide().after(this.container);
+ this.dropdown = this.container.find('div.chzn-drop').first();
+ this.search_field = this.container.find('input').first();
+ this.search_results = this.container.find('ul.chzn-results').first();
+ this.search_field_scale();
+ this.search_no_results = this.container.find('li.no-results').first();
+ if (this.is_multiple) {
+ this.search_choices = this.container.find('ul.chzn-choices').first();
+ this.search_container = this.container.find('li.search-field').first();
+ } else {
+ this.search_container = this.container.find('div.chzn-search').first();
+ this.selected_item = this.container.find('.chzn-single').first();
+ }
+ this.results_build();
+ this.set_tab_index();
+ this.set_label_behavior();
+ return this.form_field_jq.trigger("liszt:ready", {
+ chosen: this
+ });
+ };
+
+ Chosen.prototype.register_observers = function() {
+ var _this = this;
+ this.container.mousedown(function(evt) {
+ _this.container_mousedown(evt);
+ });
+ this.container.mouseup(function(evt) {
+ _this.container_mouseup(evt);
+ });
+ this.container.mouseenter(function(evt) {
+ _this.mouse_enter(evt);
+ });
+ this.container.mouseleave(function(evt) {
+ _this.mouse_leave(evt);
+ });
+ this.search_results.mouseup(function(evt) {
+ _this.search_results_mouseup(evt);
+ });
+ this.search_results.mouseover(function(evt) {
+ _this.search_results_mouseover(evt);
+ });
+ this.search_results.mouseout(function(evt) {
+ _this.search_results_mouseout(evt);
+ });
+ this.search_results.bind('mousewheel DOMMouseScroll', function(evt) {
+ _this.search_results_mousewheel(evt);
+ });
+ this.form_field_jq.bind("liszt:updated", function(evt) {
+ _this.results_update_field(evt);
+ });
+ this.form_field_jq.bind("liszt:activate", function(evt) {
+ _this.activate_field(evt);
+ });
+ this.form_field_jq.bind("liszt:open", function(evt) {
+ _this.container_mousedown(evt);
+ });
+ this.search_field.blur(function(evt) {
+ _this.input_blur(evt);
+ });
+ this.search_field.keyup(function(evt) {
+ _this.keyup_checker(evt);
+ });
+ this.search_field.keydown(function(evt) {
+ _this.keydown_checker(evt);
+ });
+ this.search_field.focus(function(evt) {
+ _this.input_focus(evt);
+ });
+ if (this.is_multiple) {
+ return this.search_choices.click(function(evt) {
+ _this.choices_click(evt);
+ });
+ } else {
+ return this.container.click(function(evt) {
+ evt.preventDefault();
+ });
+ }
+ };
+
+ Chosen.prototype.search_field_disabled = function() {
+ this.is_disabled = this.form_field_jq[0].disabled;
+ if (this.is_disabled) {
+ this.container.addClass('chzn-disabled');
+ this.search_field[0].disabled = true;
+ if (!this.is_multiple) {
+ this.selected_item.unbind("focus", this.activate_action);
+ }
+ return this.close_field();
+ } else {
+ this.container.removeClass('chzn-disabled');
+ this.search_field[0].disabled = false;
+ if (!this.is_multiple) {
+ return this.selected_item.bind("focus", this.activate_action);
+ }
+ }
+ };
+
+ Chosen.prototype.container_mousedown = function(evt) {
+ if (!this.is_disabled) {
+ if (evt && evt.type === "mousedown" && !this.results_showing) {
+ evt.preventDefault();
+ }
+ if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
+ if (!this.active_field) {
+ if (this.is_multiple) {
+ this.search_field.val("");
+ }
+ $(document).click(this.click_test_action);
+ this.results_show();
+ } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chzn-single").length)) {
+ evt.preventDefault();
+ this.results_toggle();
+ }
+ return this.activate_field();
+ }
+ }
+ };
+
+ Chosen.prototype.container_mouseup = function(evt) {
+ if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
+ return this.results_reset(evt);
+ }
+ };
+
+ Chosen.prototype.search_results_mousewheel = function(evt) {
+ var delta, _ref, _ref1;
+ delta = -((_ref = evt.originalEvent) != null ? _ref.wheelDelta : void 0) || ((_ref1 = evt.originialEvent) != null ? _ref1.detail : void 0);
+ if (delta != null) {
+ evt.preventDefault();
+ if (evt.type === 'DOMMouseScroll') {
+ delta = delta * 40;
+ }
+ return this.search_results.scrollTop(delta + this.search_results.scrollTop());
+ }
+ };
+
+ Chosen.prototype.blur_test = function(evt) {
+ if (!this.active_field && this.container.hasClass("chzn-container-active")) {
+ return this.close_field();
+ }
+ };
+
+ Chosen.prototype.close_field = function() {
+ $(document).unbind("click", this.click_test_action);
+ this.active_field = false;
+ this.results_hide();
+ this.container.removeClass("chzn-container-active");
+ this.winnow_results_clear();
+ this.clear_backstroke();
+ this.show_search_field_default();
+ return this.search_field_scale();
+ };
+
+ Chosen.prototype.activate_field = function() {
+ this.container.addClass("chzn-container-active");
+ this.active_field = true;
+ this.search_field.val(this.search_field.val());
+ return this.search_field.focus();
+ };
+
+ Chosen.prototype.test_active_click = function(evt) {
+ if ($(evt.target).parents('#' + this.container_id).length) {
+ return this.active_field = true;
+ } else {
+ return this.close_field();
+ }
+ };
+
+ Chosen.prototype.results_build = function() {
+ var content, data, _i, _len, _ref;
+ this.parsing = true;
+ this.results_data = root.SelectParser.select_to_array(this.form_field);
+ if (this.is_multiple && this.choices > 0) {
+ this.search_choices.find("li.search-choice").remove();
+ this.choices = 0;
+ } else if (!this.is_multiple) {
+ this.selected_item.addClass("chzn-default").find("span").text(this.default_text);
+ if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
+ this.container.addClass("chzn-container-single-nosearch");
+ } else {
+ this.container.removeClass("chzn-container-single-nosearch");
+ }
+ }
+ content = '';
+ _ref = this.results_data;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ data = _ref[_i];
+ if (data.group) {
+ content += this.result_add_group(data);
+ } else if (!data.empty) {
+ content += this.result_add_option(data);
+ if (data.selected && this.is_multiple) {
+ this.choice_build(data);
+ } else if (data.selected && !this.is_multiple) {
+ this.selected_item.removeClass("chzn-default").find("span").text(data.text);
+ if (this.allow_single_deselect) {
+ this.single_deselect_control_build();
+ }
+ }
+ }
+ }
+ this.search_field_disabled();
+ this.show_search_field_default();
+ this.search_field_scale();
+ this.search_results.html(content);
+ return this.parsing = false;
+ };
+
+ Chosen.prototype.result_add_group = function(group) {
+ if (!group.disabled) {
+ group.dom_id = this.container_id + "_g_" + group.array_index;
+ return '<li id="' + group.dom_id + '" class="group-result">' + $("<div />").text(group.label).html() + '</li>';
+ } else {
+ return "";
+ }
+ };
+
+ Chosen.prototype.result_do_highlight = function(el) {
+ var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
+ if (el.length) {
+ this.result_clear_highlight();
+ this.result_highlight = el;
+ this.result_highlight.addClass("highlighted");
+ maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
+ visible_top = this.search_results.scrollTop();
+ visible_bottom = maxHeight + visible_top;
+ high_top = this.result_highlight.position().top + this.search_results.scrollTop();
+ high_bottom = high_top + this.result_highlight.outerHeight();
+ if (high_bottom >= visible_bottom) {
+ return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
+ } else if (high_top < visible_top) {
+ return this.search_results.scrollTop(high_top);
+ }
+ }
+ };
+
+ Chosen.prototype.result_clear_highlight = function() {
+ if (this.result_highlight) {
+ this.result_highlight.removeClass("highlighted");
+ }
+ return this.result_highlight = null;
+ };
+
+ Chosen.prototype.results_show = function() {
+ if (this.result_single_selected != null) {
+ this.result_do_highlight(this.result_single_selected);
+ } else if (this.is_multiple && this.max_selected_options <= this.choices) {
+ this.form_field_jq.trigger("liszt:maxselected", {
+ chosen: this
+ });
+ return false;
+ }
+ this.container.addClass("chzn-with-drop");
+ this.form_field_jq.trigger("liszt:showing_dropdown", {
+ chosen: this
+ });
+ this.results_showing = true;
+ this.search_field.focus();
+ this.search_field.val(this.search_field.val());
+ return this.winnow_results();
+ };
+
+ Chosen.prototype.results_hide = function() {
+ this.result_clear_highlight();
+ this.container.removeClass("chzn-with-drop");
+ this.form_field_jq.trigger("liszt:hiding_dropdown", {
+ chosen: this
+ });
+ return this.results_showing = false;
+ };
+
+ Chosen.prototype.set_tab_index = function(el) {
+ var ti;
+ if (this.form_field_jq.attr("tabindex")) {
+ ti = this.form_field_jq.attr("tabindex");
+ this.form_field_jq.attr("tabindex", -1);
+ return this.search_field.attr("tabindex", ti);
+ }
+ };
+
+ Chosen.prototype.set_label_behavior = function() {
+ var _this = this;
+ this.form_field_label = this.form_field_jq.parents("label");
+ if (!this.form_field_label.length && this.form_field.id.length) {
+ this.form_field_label = $("label[for=" + this.form_field.id + "]");
+ }
+ if (this.form_field_label.length > 0) {
+ return this.form_field_label.click(function(evt) {
+ if (_this.is_multiple) {
+ return _this.container_mousedown(evt);
+ } else {
+ return _this.activate_field();
+ }
+ });
+ }
+ };
+
+ Chosen.prototype.show_search_field_default = function() {
+ if (this.is_multiple && this.choices < 1 && !this.active_field) {
+ this.search_field.val(this.default_text);
+ return this.search_field.addClass("default");
+ } else {
+ this.search_field.val("");
+ return this.search_field.removeClass("default");
+ }
+ };
+
+ Chosen.prototype.search_results_mouseup = function(evt) {
+ var target;
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
+ if (target.length) {
+ this.result_highlight = target;
+ this.result_select(evt);
+ return this.search_field.focus();
+ }
+ };
+
+ Chosen.prototype.search_results_mouseover = function(evt) {
+ var target;
+ target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
+ if (target) {
+ return this.result_do_highlight(target);
+ }
+ };
+
+ Chosen.prototype.search_results_mouseout = function(evt) {
+ if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
+ return this.result_clear_highlight();
+ }
+ };
+
+ Chosen.prototype.choice_build = function(item) {
+ var choice_id, html, link,
+ _this = this;
+ if (this.is_multiple && this.max_selected_options <= this.choices) {
+ this.form_field_jq.trigger("liszt:maxselected", {
+ chosen: this
+ });
+ return false;
+ }
+ choice_id = this.container_id + "_c_" + item.array_index;
+ this.choices += 1;
+ if (item.disabled) {
+ html = '<li class="search-choice search-choice-disabled" id="' + choice_id + '"><span>' + item.html + '</span></li>';
+ } else {
+ html = '<li class="search-choice" id="' + choice_id + '"><span>' + item.html + '</span><a href="javascript:void(0)" class="search-choice-close" rel="' + item.array_index + '"></a></li>';
+ }
+ this.search_container.before(html);
+ link = $('#' + choice_id).find("a").first();
+ return link.click(function(evt) {
+ return _this.choice_destroy_link_click(evt);
+ });
+ };
+
+ Chosen.prototype.choice_destroy_link_click = function(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ if (!this.is_disabled) {
+ return this.choice_destroy($(evt.target));
+ }
+ };
+
+ Chosen.prototype.choice_destroy = function(link) {
+ if (this.result_deselect(link.attr("rel"))) {
+ this.choices -= 1;
+ this.show_search_field_default();
+ if (this.is_multiple && this.choices > 0 && this.search_field.val().length < 1) {
+ this.results_hide();
+ }
+ link.parents('li').first().remove();
+ return this.search_field_scale();
+ }
+ };
+
+ Chosen.prototype.results_reset = function() {
+ this.form_field.options[0].selected = true;
+ this.selected_item.find("span").text(this.default_text);
+ if (!this.is_multiple) {
+ this.selected_item.addClass("chzn-default");
+ }
+ this.show_search_field_default();
+ this.results_reset_cleanup();
+ this.form_field_jq.trigger("change");
+ if (this.active_field) {
+ return this.results_hide();
+ }
+ };
+
+ Chosen.prototype.results_reset_cleanup = function() {
+ this.current_selectedIndex = this.form_field.selectedIndex;
+ return this.selected_item.find("abbr").remove();
+ };
+
+ Chosen.prototype.result_select = function(evt) {
+ var high, high_id, item, position;
+ if (this.result_highlight) {
+ high = this.result_highlight;
+ high_id = high.attr("id");
+ this.result_clear_highlight();
+ if (this.is_multiple) {
+ this.result_deactivate(high);
+ } else {
+ this.search_results.find(".result-selected").removeClass("result-selected");
+ this.result_single_selected = high;
+ this.selected_item.removeClass("chzn-default");
+ }
+ high.addClass("result-selected");
+ position = high_id.substr(high_id.lastIndexOf("_") + 1);
+ item = this.results_data[position];
+ item.selected = true;
+ this.form_field.options[item.options_index].selected = true;
+ if (this.is_multiple) {
+ this.choice_build(item);
+ } else {
+ this.selected_item.find("span").first().text(item.text);
+ if (this.allow_single_deselect) {
+ this.single_deselect_control_build();
+ }
+ }
+ if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
+ this.results_hide();
+ }
+ this.search_field.val("");
+ if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
+ this.form_field_jq.trigger("change", {
+ 'selected': this.form_field.options[item.options_index].value
+ });
+ }
+ this.current_selectedIndex = this.form_field.selectedIndex;
+ return this.search_field_scale();
+ }
+ };
+
+ Chosen.prototype.result_activate = function(el) {
+ return el.addClass("active-result");
+ };
+
+ Chosen.prototype.result_deactivate = function(el) {
+ return el.removeClass("active-result");
+ };
+
+ Chosen.prototype.result_deselect = function(pos) {
+ var result, result_data;
+ result_data = this.results_data[pos];
+ if (!this.form_field.options[result_data.options_index].disabled) {
+ result_data.selected = false;
+ this.form_field.options[result_data.options_index].selected = false;
+ result = $("#" + this.container_id + "_o_" + pos);
+ result.removeClass("result-selected").addClass("active-result").show();
+ this.result_clear_highlight();
+ this.winnow_results();
+ this.form_field_jq.trigger("change", {
+ deselected: this.form_field.options[result_data.options_index].value
+ });
+ this.search_field_scale();
+ return true;
+ } else {
+ return false;
+ }
+ };
+
+ Chosen.prototype.single_deselect_control_build = function() {
+ if (this.allow_single_deselect && this.selected_item.find("abbr").length < 1) {
+ return this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
+ }
+ };
+
+ Chosen.prototype.winnow_results = function() {
+ var found, option, part, parts, regex, regexAnchor, result, result_id, results, searchText, startpos, text, zregex, _i, _j, _len, _len1, _ref;
+ this.no_results_clear();
+ results = 0;
+ searchText = this.search_field.val() === this.default_text ? "" : $('<div/>').text($.trim(this.search_field.val())).html();
+ regexAnchor = this.search_contains ? "" : "^";
+ regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
+ zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
+ _ref = this.results_data;
+ for (_i = 0, _len = _ref.length; _i < _len; _i++) {
+ option = _ref[_i];
+ if (!option.disabled && !option.empty) {
+ if (option.group) {
+ $('#' + option.dom_id).css('display', 'none');
+ } else if (!(this.is_multiple && option.selected)) {
+ found = false;
+ result_id = option.dom_id;
+ result = $("#" + result_id);
+ if (regex.test(option.html)) {
+ found = true;
+ results += 1;
+ } else if (this.enable_split_word_search && (option.html.indexOf(" ") >= 0 || option.html.indexOf("[") === 0)) {
+ parts = option.html.replace(/\[|\]/g, "").split(" ");
+ if (parts.length) {
+ for (_j = 0, _len1 = parts.length; _j < _len1; _j++) {
+ part = parts[_j];
+ if (regex.test(part)) {
+ found = true;
+ results += 1;
+ }
+ }
+ }
+ }
+ if (found) {
+ if (searchText.length) {
+ startpos = option.html.search(zregex);
+ text = option.html.substr(0, startpos + searchText.length) + '</em>' + option.html.substr(startpos + searchText.length);
+ text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
+ } else {
+ text = option.html;
+ }
+ result.html(text);
+ this.result_activate(result);
+ if (option.group_array_index != null) {
+ $("#" + this.results_data[option.group_array_index].dom_id).css('display', 'list-item');
+ }
+ } else {
+ if (this.result_highlight && result_id === this.result_highlight.attr('id')) {
+ this.result_clear_highlight();
+ }
+ this.result_deactivate(result);
+ }
+ }
+ }
+ }
+ if (results < 1 && searchText.length) {
+ return this.no_results(searchText);
+ } else {
+ return this.winnow_results_set_highlight();
+ }
+ };
+
+ Chosen.prototype.winnow_results_clear = function() {
+ var li, lis, _i, _len, _results;
+ this.search_field.val("");
+ lis = this.search_results.find("li");
+ _results = [];
+ for (_i = 0, _len = lis.length; _i < _len; _i++) {
+ li = lis[_i];
+ li = $(li);
+ if (li.hasClass("group-result")) {
+ _results.push(li.css('display', 'auto'));
+ } else if (!this.is_multiple || !li.hasClass("result-selected")) {
+ _results.push(this.result_activate(li));
+ } else {
+ _results.push(void 0);
+ }
+ }
+ return _results;
+ };
+
+ Chosen.prototype.winnow_results_set_highlight = function() {
+ var do_high, selected_results;
+ if (!this.result_highlight) {
+ selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
+ do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
+ if (do_high != null) {
+ return this.result_do_highlight(do_high);
+ }
+ }
+ };
+
+ Chosen.prototype.no_results = function(terms) {
+ var no_results_html;
+ no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
+ no_results_html.find("span").first().html(terms);
+ return this.search_results.append(no_results_html);
+ };
+
+ Chosen.prototype.no_results_clear = function() {
+ return this.search_results.find(".no-results").remove();
+ };
+
+ Chosen.prototype.keydown_arrow = function() {
+ var first_active, next_sib;
+ if (!this.result_highlight) {
+ first_active = this.search_results.find("li.active-result").first();
+ if (first_active) {
+ this.result_do_highlight($(first_active));
+ }
+ } else if (this.results_showing) {
+ next_sib = this.result_highlight.nextAll("li.active-result").first();
+ if (next_sib) {
+ this.result_do_highlight(next_sib);
+ }
+ }
+ if (!this.results_showing) {
+ return this.results_show();
+ }
+ };
+
+ Chosen.prototype.keyup_arrow = function() {
+ var prev_sibs;
+ if (!this.results_showing && !this.is_multiple) {
+ return this.results_show();
+ } else if (this.result_highlight) {
+ prev_sibs = this.result_highlight.prevAll("li.active-result");
+ if (prev_sibs.length) {
+ return this.result_do_highlight(prev_sibs.first());
+ } else {
+ if (this.choices > 0) {
+ this.results_hide();
+ }
+ return this.result_clear_highlight();
+ }
+ }
+ };
+
+ Chosen.prototype.keydown_backstroke = function() {
+ var next_available_destroy;
+ if (this.pending_backstroke) {
+ this.choice_destroy(this.pending_backstroke.find("a").first());
+ return this.clear_backstroke();
+ } else {
+ next_available_destroy = this.search_container.siblings("li.search-choice").last();
+ if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
+ this.pending_backstroke = next_available_destroy;
+ if (this.single_backstroke_delete) {
+ return this.keydown_backstroke();
+ } else {
+ return this.pending_backstroke.addClass("search-choice-focus");
+ }
+ }
+ }
+ };
+
+ Chosen.prototype.clear_backstroke = function() {
+ if (this.pending_backstroke) {
+ this.pending_backstroke.removeClass("search-choice-focus");
+ }
+ return this.pending_backstroke = null;
+ };
+
+ Chosen.prototype.keydown_checker = function(evt) {
+ var stroke, _ref;
+ stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
+ this.search_field_scale();
+ if (stroke !== 8 && this.pending_backstroke) {
+ this.clear_backstroke();
+ }
+ switch (stroke) {
+ case 8:
+ this.backstroke_length = this.search_field.val().length;
+ break;
+ case 9:
+ if (this.results_showing && !this.is_multiple) {
+ this.result_select(evt);
+ }
+ this.mouse_on_container = false;
+ break;
+ case 13:
+ evt.preventDefault();
+ break;
+ case 38:
+ evt.preventDefault();
+ this.keyup_arrow();
+ break;
+ case 40:
+ this.keydown_arrow();
+ break;
+ }
+ };
+
+ Chosen.prototype.search_field_scale = function() {
+ var div, h, style, style_block, styles, w, _i, _len;
+ if (this.is_multiple) {
+ h = 0;
+ w = 0;
+ style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
+ styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
+ for (_i = 0, _len = styles.length; _i < _len; _i++) {
+ style = styles[_i];
+ style_block += style + ":" + this.search_field.css(style) + ";";
+ }
+ div = $('<div />', {
+ 'style': style_block
+ });
+ div.text(this.search_field.val());
+ $('body').append(div);
+ w = div.width() + 25;
+ div.remove();
+ if (!this.f_width) {
+ this.f_width = this.container.outerWidth();
+ }
+ if (w > this.f_width - 10) {
+ w = this.f_width - 10;
+ }
+ return this.search_field.css({
+ 'width': w + 'px'
+ });
+ }
+ };
+
+ Chosen.prototype.generate_random_id = function() {
+ var string;
+ string = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char();
+ while ($("#" + string).length > 0) {
+ string += this.generate_random_char();
+ }
+ return string;
+ };
+
+ return Chosen;
+
+ })(AbstractChosen);
+
+ root.Chosen = Chosen;
+
+}).call(this);
diff --git a/www/wiki/resources/lib/jquery.client/AUTHORS.txt b/www/wiki/resources/lib/jquery.client/AUTHORS.txt
new file mode 100644
index 00000000..9f186cac
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.client/AUTHORS.txt
@@ -0,0 +1,9 @@
+Trevor Parscal <trevorparscal@gmail.com>
+Timo Tijhof <krinklemail@gmail.com>
+Roan Kattouw <roan.kattouw@gmail.com>
+Derk-Jan Hartman <hartman.wiki@gmail.com>
+Bartosz Dziewoński <matma.rex@gmail.com>
+Rob Moen <rmoen@wikimedia.org>
+Ed Sanders <esanders@wikimedia.org>
+Alex Monk <krenair@gmail.com>
+James D. Forrester <jforrester@wikimedia.org>
diff --git a/www/wiki/resources/lib/jquery.client/LICENSE-MIT.txt b/www/wiki/resources/lib/jquery.client/LICENSE-MIT.txt
new file mode 100644
index 00000000..f149289d
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.client/LICENSE-MIT.txt
@@ -0,0 +1,20 @@
+Copyright 2010-2015 jquery-client maintainers and other contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/www/wiki/resources/lib/jquery.client/README.md b/www/wiki/resources/lib/jquery.client/README.md
new file mode 100644
index 00000000..02b5dd41
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.client/README.md
@@ -0,0 +1,6 @@
+[![Build Status](https://travis-ci.org/wikimedia/jquery-client.svg?branch=master)](https://travis-ci.org/wikimedia/jquery-client) [![npm](https://img.shields.io/npm/v/jquery-client.svg?style=flat)](https://www.npmjs.com/package/jquery-client)
+
+jQuery Client
+=================
+
+jQuery Client is a jQuery plugin for user-agent detection.
diff --git a/www/wiki/resources/lib/jquery.client/jquery.client.js b/www/wiki/resources/lib/jquery.client/jquery.client.js
new file mode 100644
index 00000000..8257d85b
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.client/jquery.client.js
@@ -0,0 +1,320 @@
+/*!
+ * jQuery Client v2.0.0
+ * https://www.mediawiki.org/wiki/JQuery_Client
+ *
+ * Copyright 2010-2015 jquery-client maintainers and other contributors.
+ * Released under the MIT license
+ * http://jquery-client.mit-license.org
+ */
+
+/**
+ * User-agent detection
+ *
+ * @class jQuery.client
+ * @singleton
+ */
+( function ( $ ) {
+
+ /**
+ * @private
+ * @property {Object} profileCache Keyed by userAgent string,
+ * value is the parsed $.client.profile object for that user agent.
+ */
+ var profileCache = {};
+
+ $.client = {
+
+ /**
+ * Get an object containing information about the client.
+ *
+ * @param {Object} [nav] An object with a 'userAgent' and 'platform' property.
+ * Defaults to the global `navigator` object.
+ * @return {Object} The resulting client object will be in the following format:
+ *
+ * {
+ * 'name': 'firefox',
+ * 'layout': 'gecko',
+ * 'layoutVersion': 20101026,
+ * 'platform': 'linux'
+ * 'version': '3.5.1',
+ * 'versionBase': '3',
+ * 'versionNumber': 3.5,
+ * }
+ */
+ profile: function ( nav ) {
+ /*jshint boss:true */
+
+ if ( nav === undefined ) {
+ nav = window.navigator;
+ }
+
+ // Use the cached version if possible
+ if ( profileCache[ nav.userAgent + '|' + nav.platform ] !== undefined ) {
+ return profileCache[ nav.userAgent + '|' + nav.platform ];
+ }
+
+ var
+ versionNumber,
+ key = nav.userAgent + '|' + nav.platform,
+
+ // Configuration
+
+ // Name of browsers or layout engines we don't recognize
+ uk = 'unknown',
+ // Generic version digit
+ x = 'x',
+ // Strings found in user agent strings that need to be conformed
+ wildUserAgents = ['Opera', 'Navigator', 'Minefield', 'KHTML', 'Chrome', 'PLAYSTATION 3', 'Iceweasel'],
+ // Translations for conforming user agent strings
+ userAgentTranslations = [
+ // Tons of browsers lie about being something they are not
+ [/(Firefox|MSIE|KHTML,?\slike\sGecko|Konqueror)/, ''],
+ // Chrome lives in the shadow of Safari still
+ ['Chrome Safari', 'Chrome'],
+ // KHTML is the layout engine not the browser - LIES!
+ ['KHTML', 'Konqueror'],
+ // Firefox nightly builds
+ ['Minefield', 'Firefox'],
+ // This helps keep different versions consistent
+ ['Navigator', 'Netscape'],
+ // This prevents version extraction issues, otherwise translation would happen later
+ ['PLAYSTATION 3', 'PS3']
+ ],
+ // Strings which precede a version number in a user agent string - combined and used as
+ // match 1 in version detection
+ versionPrefixes = [
+ 'camino', 'chrome', 'firefox', 'iceweasel', 'netscape', 'netscape6', 'opera', 'version', 'konqueror',
+ 'lynx', 'msie', 'safari', 'ps3', 'android'
+ ],
+ // Used as matches 2, 3 and 4 in version extraction - 3 is used as actual version number
+ versionSuffix = '(\\/|\\;?\\s|)([a-z0-9\\.\\+]*?)(\\;|dev|rel|\\)|\\s|$)',
+ // Names of known browsers
+ names = [
+ 'camino', 'chrome', 'firefox', 'iceweasel', 'netscape', 'konqueror', 'lynx', 'msie', 'opera',
+ 'safari', 'ipod', 'iphone', 'blackberry', 'ps3', 'rekonq', 'android'
+ ],
+ // Tanslations for conforming browser names
+ nameTranslations = [],
+ // Names of known layout engines
+ layouts = ['gecko', 'konqueror', 'msie', 'trident', 'edge', 'opera', 'webkit'],
+ // Translations for conforming layout names
+ layoutTranslations = [ ['konqueror', 'khtml'], ['msie', 'trident'], ['opera', 'presto'] ],
+ // Names of supported layout engines for version number
+ layoutVersions = ['applewebkit', 'gecko', 'trident', 'edge'],
+ // Names of known operating systems
+ platforms = ['win', 'wow64', 'mac', 'linux', 'sunos', 'solaris', 'iphone'],
+ // Translations for conforming operating system names
+ platformTranslations = [ ['sunos', 'solaris'], ['wow64', 'win'] ],
+
+ /**
+ * Performs multiple replacements on a string
+ * @ignore
+ */
+ translate = function ( source, translations ) {
+ var i;
+ for ( i = 0; i < translations.length; i++ ) {
+ source = source.replace( translations[i][0], translations[i][1] );
+ }
+ return source;
+ },
+
+ // Pre-processing
+
+ ua = nav.userAgent,
+ match,
+ name = uk,
+ layout = uk,
+ layoutversion = uk,
+ platform = uk,
+ version = x;
+
+ if ( match = new RegExp( '(' + wildUserAgents.join( '|' ) + ')' ).exec( ua ) ) {
+ // Takes a userAgent string and translates given text into something we can more easily work with
+ ua = translate( ua, userAgentTranslations );
+ }
+ // Everything will be in lowercase from now on
+ ua = ua.toLowerCase();
+
+ // Extraction
+
+ if ( match = new RegExp( '(' + names.join( '|' ) + ')' ).exec( ua ) ) {
+ name = translate( match[1], nameTranslations );
+ }
+ if ( match = new RegExp( '(' + layouts.join( '|' ) + ')' ).exec( ua ) ) {
+ layout = translate( match[1], layoutTranslations );
+ }
+ if ( match = new RegExp( '(' + layoutVersions.join( '|' ) + ')\\\/(\\d+)').exec( ua ) ) {
+ layoutversion = parseInt( match[2], 10 );
+ }
+ if ( match = new RegExp( '(' + platforms.join( '|' ) + ')' ).exec( nav.platform.toLowerCase() ) ) {
+ platform = translate( match[1], platformTranslations );
+ }
+ if ( match = new RegExp( '(' + versionPrefixes.join( '|' ) + ')' + versionSuffix ).exec( ua ) ) {
+ version = match[3];
+ }
+
+ // Edge Cases -- did I mention about how user agent string lie?
+
+ // Decode Safari's crazy 400+ version numbers
+ if ( name === 'safari' && version > 400 ) {
+ version = '2.0';
+ }
+ // Expose Opera 10's lies about being Opera 9.8
+ if ( name === 'opera' && version >= 9.8 ) {
+ match = ua.match( /\bversion\/([0-9\.]*)/ );
+ if ( match && match[1] ) {
+ version = match[1];
+ } else {
+ version = '10';
+ }
+ }
+ // And Opera 15's lies about being Chrome
+ if ( name === 'chrome' && ( match = ua.match( /\bopr\/([0-9\.]*)/ ) ) ) {
+ if ( match[1] ) {
+ name = 'opera';
+ version = match[1];
+ }
+ }
+ // And IE 11's lies about being not being IE
+ if ( layout === 'trident' && layoutversion >= 7 && ( match = ua.match( /\brv[ :\/]([0-9\.]*)/ ) ) ) {
+ if ( match[1] ) {
+ name = 'msie';
+ version = match[1];
+ }
+ }
+ // And MS Edge's lies about being Chrome
+ //
+ // It's different enough from classic IE Trident engine that they do this
+ // to avoid getting caught by MSIE-specific browser sniffing.
+ if ( name === 'chrome' && ( match = ua.match( /\bedge\/([0-9\.]*)/ ) ) ) {
+ name = 'edge';
+ version = match[1];
+ layout = 'edge';
+ layoutversion = parseInt( match[1], 10 );
+ }
+ // And Amazon Silk's lies about being Android on mobile or Safari on desktop
+ if ( match = ua.match( /\bsilk\/([0-9.\-_]*)/ ) ) {
+ if ( match[1] ) {
+ name = 'silk';
+ version = match[1];
+ }
+ }
+
+ versionNumber = parseFloat( version, 10 ) || 0.0;
+
+ // Caching
+
+ return profileCache[ key ] = {
+ name: name,
+ layout: layout,
+ layoutVersion: layoutversion,
+ platform: platform,
+ version: version,
+ versionBase: ( version !== x ? Math.floor( versionNumber ).toString() : x ),
+ versionNumber: versionNumber
+ };
+ },
+
+ /**
+ * Checks the current browser against a support map object.
+ *
+ * Version numbers passed as numeric values will be compared like numbers (1.2 > 1.11).
+ * Version numbers passed as string values will be compared using a simple component-wise
+ * algorithm, similar to PHP's version_compare ('1.2' < '1.11').
+ *
+ * A browser map is in the following format:
+ *
+ * {
+ * // Multiple rules with configurable operators
+ * 'msie': [['>=', 7], ['!=', 9]],
+ * // Match no versions
+ * 'iphone': false,
+ * // Match any version
+ * 'android': null
+ * }
+ *
+ * It can optionally be split into ltr/rtl sections:
+ *
+ * {
+ * 'ltr': {
+ * 'android': null,
+ * 'iphone': false
+ * },
+ * 'rtl': {
+ * 'android': false,
+ * // rules are not inherited from ltr
+ * 'iphone': false
+ * }
+ * }
+ *
+ * @param {Object} map Browser support map
+ * @param {Object} [profile] A client-profile object
+ * @param {boolean} [exactMatchOnly=false] Only return true if the browser is matched, otherwise
+ * returns true if the browser is not found.
+ *
+ * @return {boolean} The current browser is in the support map
+ */
+ test: function ( map, profile, exactMatchOnly ) {
+ /*jshint evil:true */
+
+ var conditions, dir, i, op, val, j, pieceVersion, pieceVal, compare;
+ profile = $.isPlainObject( profile ) ? profile : $.client.profile();
+ if ( map.ltr && map.rtl ) {
+ dir = $( 'body' ).is( '.rtl' ) ? 'rtl' : 'ltr';
+ map = map[dir];
+ }
+ // Check over each browser condition to determine if we are running in a compatible client
+ if ( typeof map !== 'object' || map[profile.name] === undefined ) {
+ // Not found, return true if exactMatchOnly not set, false otherwise
+ return !exactMatchOnly;
+ }
+ conditions = map[profile.name];
+ if ( conditions === false ) {
+ // Match no versions
+ return false;
+ }
+ if ( conditions === null ) {
+ // Match all versions
+ return true;
+ }
+ for ( i = 0; i < conditions.length; i++ ) {
+ op = conditions[i][0];
+ val = conditions[i][1];
+ if ( typeof val === 'string' ) {
+ // Perform a component-wise comparison of versions, similar to PHP's version_compare
+ // but simpler. '1.11' is larger than '1.2'.
+ pieceVersion = profile.version.toString().split( '.' );
+ pieceVal = val.split( '.' );
+ // Extend with zeroes to equal length
+ while ( pieceVersion.length < pieceVal.length ) {
+ pieceVersion.push( '0' );
+ }
+ while ( pieceVal.length < pieceVersion.length ) {
+ pieceVal.push( '0' );
+ }
+ // Compare components
+ compare = 0;
+ for ( j = 0; j < pieceVersion.length; j++ ) {
+ if ( Number( pieceVersion[j] ) < Number( pieceVal[j] ) ) {
+ compare = -1;
+ break;
+ } else if ( Number( pieceVersion[j] ) > Number( pieceVal[j] ) ) {
+ compare = 1;
+ break;
+ }
+ }
+ // compare will be -1, 0 or 1, depending on comparison result
+ if ( !( eval( String( compare + op + '0' ) ) ) ) {
+ return false;
+ }
+ } else if ( typeof val === 'number' ) {
+ if ( !( eval( 'profile.versionNumber' + op + val ) ) ) {
+ return false;
+ }
+ }
+ }
+
+ return true;
+ }
+ };
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/CREDITS b/www/wiki/resources/lib/jquery.i18n/CREDITS
new file mode 100644
index 00000000..3a4eb5e2
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/CREDITS
@@ -0,0 +1,9 @@
+Credits
+=======
+
+Santhosh Thottingal
+Amir E. Aharoni
+Siebrand Mazeland
+Niklas Laxström
+Neil Kandalgaonkar
+David Chan
diff --git a/www/wiki/resources/lib/jquery.i18n/GPL-LICENSE b/www/wiki/resources/lib/jquery.i18n/GPL-LICENSE
new file mode 100644
index 00000000..d159169d
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/GPL-LICENSE
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
diff --git a/www/wiki/resources/lib/jquery.i18n/MIT-LICENSE b/www/wiki/resources/lib/jquery.i18n/MIT-LICENSE
new file mode 100644
index 00000000..f3a03b7e
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/MIT-LICENSE
@@ -0,0 +1,21 @@
+Copyright (c) 2012-2013 Santhosh Thottingal and other
+contributors. See CREDITS for a list.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/www/wiki/resources/lib/jquery.i18n/README.md b/www/wiki/resources/lib/jquery.i18n/README.md
new file mode 100644
index 00000000..da82c2bc
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/README.md
@@ -0,0 +1,432 @@
+jQuery.i18n
+===========
+
+jQuery.i18n is a jQuery based Javascript internationalization library. It helps you to internationalize your web applications easily.
+
+This is a project by Wikimedia foundation's [Language Engineering team](http://wikimediafoundation.org/wiki/Language_Engineering_team) and used in some of the Wikimedia Foundation projects like Universal Language Selector.
+
+The jquery.i18n library uses a json based localization file format, "banana", which is used as the localization file format for MediaWiki and other projects.
+
+Features
+========
+* Simple file format - JSON. Easily readable for humans and machines.
+* Author and metadata information is not lost anywhere. There are other file formats using comments to store this.
+* Uses MediaWiki convention for placeholders. Easily readable and proven convention. Example: ```There are $1 cars```
+* Supports plural conversion without using extra messages for all plural forms. Plural rule handling is done using CLDR. Covers a wide range of languages
+* Supports gender. By passing the gender value, you get correct sentences according to gender.
+* Supports grammar forms. jquery.i18n has a basic but extensible grammar conversion support
+* Fallback chains for all languages.
+* Data api- the message key. Example: ```<li data-i18n="message-key"></li>```.
+* Dynamic change of interface language without refreshing a webpage.
+* Nestable grammar, plural, gender support. These constructs can be nested to any arbitrary level for supporting sophisticated message localization
+* Message documentation through special language code ```qqq```
+* Extensible message parser to add or customize magic words in the messages. Example: ```{sitename}``` or ```[[link]]``
+
+
+Quick start
+-----------
+
+```bash
+git clone https://github.com/wikimedia/jquery.i18n.git
+cd jquery.i18n
+git submodule update --init
+```
+
+Testing
+-------
+
+```shell
+npm install
+```
+
+To run tests locally, run `npm test`, and this will run the tests.
+
+Message File Format
+===================
+
+The message files are json formatted. As a convention you can have a folder named i18n inside your source code. For each language or locale, have a file named like languagecode.json.
+
+Example:
+```
+App
+ |--src
+ |--doc
+ |--i18n
+ |--ar.json
+ |--de.json
+ |--en.json
+ |--he.json
+ |--hi.json
+ |--fr.json
+ |--qqq.json
+```
+
+A simple en.json file example is given below
+
+```json
+{
+ "@metadata": {
+ "authors": [
+ "Alice",
+ "David",
+ "Santhosh"
+ ],
+ "last-updated": "2012-09-21",
+ "locale": "en",
+ "message-documentation": "qqq",
+ "AnotherMetadata": "AnotherMedatadataValue"
+ },
+ "appname-title": "Example Application",
+ "appname-sub-title": "An example application with jquery.i18n",
+ "appname-header-introduction": "Introduction",
+ "appname-about": "About this application",
+ "appname-footer": "Footer text"
+}
+```
+
+The json file should be a valid json. The ```@metadata``` holds all kind of data that are not messages. You can store author information, copyright, updated date or anything there.
+
+Messages are key value pairs. It is a good convention to prefix your appname to message keys to make the messages unique. It acts as the namespace for the message keys. It is also a good convention to have the message keys with ```-``` separated words, all in lower case.
+
+If you are curious to see some real jquery.i18n message file from other projects:
+
+- message files of MediaWiki https://github.com/wikimedia/mediawiki-core/tree/master/languages/i18n
+- message files from jquery.uls project https://github.com/wikimedia/jquery.uls/blob/master/i18n
+
+Single message file for all languages
+-------------------------------------
+There are some alternate message file format supported for different use cases. If your application is not big, and want all the translation in a single file, you can have it as shown in the below example:
+
+```json
+{
+ "@metadata": {
+ "authors": [
+ "Alice",
+ "David",
+ "Santhosh"
+ ],
+ "last-updated": "2012-09-21",
+ "locale": "en",
+ "message-documentation": "qqq",
+ "AnotherMetadata": "AnotherMedatadataValue"
+ },
+ "en": {
+ "appname-title": "Example Application",
+ "appname-sub-title": "An example application with jquery.i18n",
+ "appname-header-introduction": "Introduction",
+ "appname-about": "About this application",
+ "appname-footer": "Footer text"
+ },
+ "ml": {
+ "appname-title": "അപ്ലിക്കേഷന്‍ ഉദാഹരണം",
+ "appname-sub-title": "jquery.i18n ഉപയോഗിച്ചുള്ള അപ്ലിക്കേഷന്‍ ഉദാഹരണം",
+ "appname-header-introduction": "ആമുഖം",
+ "appname-about": "ഈ അപ്ലിക്കേഷനെപ്പറ്റി",
+ "appname-footer": "അടിക്കുറിപ്പു്"
+ }
+}
+```
+
+Here the json file contains language code as key value and messagekey-message pairs as the value for all language pairs. You can choose this format or per-language file formats depending on your use case. Per-language files are more convenient for collaboration, version controlling, scalability, etc.
+
+In this approach, it is also possible to give a file name as the value of language code.
+
+```json
+{
+ "@metadata": {
+ "authors": [
+ "Alice",
+ "David",
+ "Santhosh"
+ ],
+ "last-updated": "2012-09-21",
+ "locale": "en",
+ "message-documentation": "qqq",
+ "AnotherMetadata": "AnotherMedatadataValue"
+ },
+ "en": {
+ "appname-title": "Example Application",
+ "appname-sub-title": "An example application with jquery.i18n",
+ "appname-header-introduction": "Introduction",
+ "appname-about": "About this application",
+ "appname-footer": "Footer text"
+ },
+ "ml": "path/to/ml.json"
+}
+```
+
+Translation
+===========
+To translate the jquery.i18n application, depending on the expertise of the translator, there are multiple ways.
+
+* Editing the json files directly - Suitable for translators with technical background. Also suitable if your application is small and you want to work with only a small number of languages
+* Providing a translation interface along with your application: Suitable for proprietary or private applications with significant amount of translators
+* Using open source translation platforms like translatewiki.net. The MediaWiki and jquery.uls from previous examples use translatewiki.net for crowdsourced message translation. Translatewiki.net can update your code repo in regular intervals with updated translations. Highly recommended if your application is opensource and want localized to as many as languages possible with maximum number of translators.
+
+Usage
+=====
+
+## Switching locale
+
+While initializing the `jquery.i18n`, the locale for the page can be given using the `locale` option. For example
+
+```javascript
+$.i18n( {
+ locale: 'he' // Locale is Hebrew
+} );
+```
+
+In case locale option is not given, `jquery.i18n` plugin will use the language attribute given for the html tag. For example
+
+```html
+<html lang="he" dir="rtl">
+```
+
+In this case the locale will be he(Hebrew). If that `lang` attribute is also missing, it will try to use the locale specified by the browser.
+
+It is possible to switch to another locale after plugin is initialized. See below example:
+
+```javascript
+$.i18n({
+ locale: 'he' // Locale is Hebrew
+});
+$.i18n( 'message_hello' ); // This will give the Hebrew translation of message key `message_hello`.
+$.i18n().locale = 'ml'; // Now onwards locale is 'Malayalam'
+$.i18n( 'message_hello' ); // This will give the Malayalam translation of message key `message_hello`.
+```
+
+## Message Loading
+
+JSON formatted messages can be loaded to the plugin using multiple ways.
+
+### Dynamic loading using `load` method.
+
+Following example shows loading messages for two locales- localex, and localey. Here localex and localey are just examples. They should be valid IS0 639 language codes(eg: en, ml, hi, fr, ta etc)
+
+```javascript
+$.i18n().load( {
+ 'localex' : {
+ 'message-key1' : 'message1' // Message for localex.
+ },
+ 'localey' : {
+ 'message-key1' : 'message1'
+ }
+} );
+```
+
+If we want to load the messages for a specific locale, it can be done like this:
+
+```javascript
+$.i18n().load({
+ 'message-hello': 'Hello World',
+ 'message-welcome': 'Welcome'
+}, 'en');
+```
+
+Note the second argument for the `load` method. It should be a valid language code.
+
+It is also possible to refer messages from an external URL. See below example
+
+```javascript
+$.i18n().load( {
+ en: {
+ message_hello: 'Hello World',
+ message_welcome: 'Welcome'
+ },
+ hi: 'i18n/messages-hi.json', // Messages for Hindi
+ de: 'i18n/messages-de.json'
+} );
+```
+
+Messages for a locale can be also loaded in parts. Example
+
+```javascript
+$.i18n().load( {
+ en: {
+ message_hello: 'Hello World',
+ message_welcome: 'Welcome'
+ }
+} );
+
+$.i18n().load( {
+ // This does not remove the previous messages.
+ en: {
+ 'message_header' : 'Header',
+ 'message_footer' : 'Footer',
+ // This will overwrite message_welcome message
+ 'message_welcome' : 'Welcome back'
+ }
+} );
+```
+
+Since it is desirable to render interface messages instantly and not after a delay of loading the message files from a server, make sure that the messages are present at client side before using jQuery.i18n.
+
+The library should expose an API to load an object containing key-value pair of messages. Example: ```$.i18n.load(data)```. This will return a ```jQuery.Promise```.
+
+jquery.i18n plugin
+=========================
+
+The jQuery plugin defines ```$.i18n()``` and ```$.fn.i18n()```
+
+```javascript
+$.i18n( 'message-key-sample1' );
+$.i18n( 'message-key-sample1' );
+$.i18n( 'Found $1 {{plural:$1|result|results}}', 10 ); // Message key itself is message text
+$.i18n( 'Showing $1 out of $2 {{plural:$2|result|results}}', 5,100 );
+$.i18n(' User X updated {{gender|his|her}} profile', 'male' );
+
+$( '#foo' ).i18n(); // to translate the element matching jquery selector based on data-i18n key
+```
+
+Data API
+--------
+
+It is possible to display localized messages without any custom JavaScript. For the HTML tags, add an attribute data-i18n with value as the message key. Example:
+```html
+<li data-i18n="message-key"></li>.
+```
+
+It is also possible to have the above li node with fallback text already in place.
+```html
+<li data-i18n="message-key">Fallback text</li>
+```
+
+The framework will place the localized message corresponding to message-key as the text value of the node. Similar to $('selector').i18n( ... ).
+This will not work for dynamically created elements.
+
+Note that if data-i18n contains html markup, that html will not be used as the element content, instead, the text version will be used. $.fn.i18n is always about replacing text of the element. If you want to change the html of the element, you may want to use: ```$(selector).html($.i18n(messagekey))```
+
+Examples
+========
+
+See http://thottingal.in/projects/js/jquery.i18n/demo/
+
+Message format
+==============
+
+## Placeholders
+
+Messages take parameters. They are represented by $1, $2, $3, … in the message texts, and replaced at run time. Typical parameter values are numbers (Example: "Delete 3 versions?"), or user names (Example: "Page last edited by $1"), page names, links, and so on, or sometimes other messages.
+
+```javascript
+var message = "Welcome, $1";
+$.i18n(message, 'Alice'); // This gives "Welcome, Alice"
+```
+
+
+## Plurals
+
+To make the syntax of sentence correct, plural forms are required. jquery.i18n support plural forms in the message using the syntax `{{PLURAL:$1|pluralform1|pluralform2|...}}`
+
+For example:
+
+```javascript
+var message = "Found $1 {{PLURAL:$1|result|results}}";
+$.i18n(message, 1); // This gives "Found 1 result"
+$.i18n(message, 4); // This gives "Found 4 results"
+```
+Note that {{PLURAL:...}} is not case sensitive. It can be {{plural:...}} too.
+
+In case of English, there are only 2 plural forms, but many languages use more than 2 plural forms. All the plural forms can be given in the above syntax, separated by pipe(|)
+
+## Gender
+Similar to plural, depending on gender of placeholders, mostly user names, the syntax changes dynamically. An example in English is "Alice changed her profile picture" and "Bob changed his profile picture". To support this {{GENDER...}} syntax can be used as show in example
+
+```javascript
+var message = "$1 changed {{GENDER:$2|his|her}} profile picture";
+$.i18n(message, 'Alice', 'female' ); // This gives "Alice changed her profile picture"
+$.i18n(message, 'Bob', 'male' ); // This gives "Bob changed his profile picture"
+```
+
+Note that {{GENDER:...}} is not case sensitive. It can be {{gender:...}} too.
+
+## Grammar
+
+
+```javascript
+$.i18n( { locale: 'fi' } );
+
+var message = "{{grammar:genitive|$1}}";
+
+$.i18n(message, 'talo' ); // This gives "talon"
+
+$.i18n().locale = 'hy'; // Switch to locale Armenian
+$.i18n(message, 'Մաունա'); // This gives "Մաունայի"
+```
+
+## Directionality-safe isolation
+
+To avoid BIDI corruption that looks like "(Foo_(Bar", which happens when a string is inserted into a context with the reverse directionality, you can use `{{bidi:…}}`. Directionality-neutral characters at the edge of the string can get wrongly interpreted by the BIDI algorithm. This would let you embed your substituted string into a new BIDI context, //e.g.//:
+
+ "`Shalom, {{bidi:$1}}, hi!`"
+
+The embedded context's directionality is determined by looking at the argument for `$1`, and then explicitly inserted into the Unicode text, ensuring correct rendering (because then the bidi algorithm "knows" the argument text is a separate context).
+
+
+Fallback
+========
+
+The plugin takes an option 'fallback' with the default value 'en'. The library reuses the fallback data available in MediaWiki for calculating the language fallbacks. Fallbacks are used when a message key is not found in a locale. Example fallbacks: sa->hi->en or tt->tt-cyrl->ru.
+
+See jquery.i18n.fallbacks.js in the source.
+
+Magic word support
+===================
+* For plural, gender and grammar support, MediaWiki template-like syntax - {{...}} will be used.
+* There will be a default implementation for all these in $.i18n.language['default']
+* The plural, gender and grammar methods in ```$.i18n.language[ 'default' ]``` can be overridden or extended in ```$.i18n.language['languageCode']```.
+* Language-specific rules about Gender and Grammar can be written in languages/langXYZ.js files
+* Plural forms will be dynamically calculated using the CLDR plural parser.
+
+Extending the parser
+--------------------
+Following example illustrates extending the parser to support more magic words
+
+```javascript
+$.extend( $.i18n.parser.emitter, {
+ // Handle SITENAME keywords
+ sitename: function () {
+ return 'Wikipedia';
+ },
+ // Handle LINK keywords
+ link: function ( nodes ) {
+ return '<a href="' + nodes[1] + '">' + nodes[0] + '</a>';
+ }
+} );
+```
+
+This will parse the message
+```javascript
+$.i18n( '{{link:{{SITENAME}}|http://en.wikipedia.org}}' );
+```
+
+to
+
+```html
+<a href="http://en.wikipedia.org">Wikipedia</a>
+```
+
+Message documentation
+=====================
+
+The message keys and messages won't give a enough context about the message being translated to the translator. Whenever a developer adds a new message, it is a usual practice to document the message to a file named qqq.json
+with same message key.
+
+Example qqq.json:
+```json
+{
+ "@metadata": {
+ "authors": [
+ "Developer Name"
+ ]
+ },
+ "appname-title": "Application name. Transliteration is recommended",
+ "appname-sub-title": "Brief explanation of the application",
+ "appname-header-introduction": "Text for the introduction header",
+ "appname-about": "About this application text",
+ "appname-footer": "Footer text"
+}
+
+```
+
+In MediaWiki and its hundreds of extensions, message documentation is a strictly followed practice. There is a grunt task to check whether all messages are documented or not. See https://www.npmjs.org/package/grunt-banana-checker
diff --git a/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.emitter.bidi.js b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.emitter.bidi.js
new file mode 100644
index 00000000..3a5b6251
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.emitter.bidi.js
@@ -0,0 +1,88 @@
+/**
+ * BIDI embedding support for jQuery.i18n
+ *
+ * Copyright (C) 2015, David Chan
+ *
+ * This code is dual licensed GPLv2 or later and MIT. You don't have to do
+ * anything special to choose one license or the other and you don't have to
+ * notify anyone which license you are using. You are free to use this code
+ * in commercial projects as long as the copyright header is left intact.
+ * See files GPL-LICENSE and MIT-LICENSE for details.
+ *
+ * @licence GNU General Public Licence 2.0 or later
+ * @licence MIT License
+ */
+
+( function ( $ ) {
+ 'use strict';
+ var strongDirRegExp;
+
+ /**
+ * Matches the first strong directionality codepoint:
+ * - in group 1 if it is LTR
+ * - in group 2 if it is RTL
+ * Does not match if there is no strong directionality codepoint.
+ *
+ * Generated by UnicodeJS (see tools/strongDir) from the UCD; see
+ * https://git.wikimedia.org/summary/unicodejs.git .
+ */
+ strongDirRegExp = new RegExp(
+ '(?:' +
+ '(' +
+ '[\u0041-\u005a\u0061-\u007a\u00aa\u00b5\u00ba\u00c0-\u00d6\u00d8-\u00f6\u00f8-\u02b8\u02bb-\u02c1\u02d0\u02d1\u02e0-\u02e4\u02ee\u0370-\u0373\u0376\u0377\u037a-\u037d\u037f\u0386\u0388-\u038a\u038c\u038e-\u03a1\u03a3-\u03f5\u03f7-\u0482\u048a-\u052f\u0531-\u0556\u0559-\u055f\u0561-\u0587\u0589\u0903-\u0939\u093b\u093d-\u0940\u0949-\u094c\u094e-\u0950\u0958-\u0961\u0964-\u0980\u0982\u0983\u0985-\u098c\u098f\u0990\u0993-\u09a8\u09aa-\u09b0\u09b2\u09b6-\u09b9\u09bd-\u09c0\u09c7\u09c8\u09cb\u09cc\u09ce\u09d7\u09dc\u09dd\u09df-\u09e1\u09e6-\u09f1\u09f4-\u09fa\u0a03\u0a05-\u0a0a\u0a0f\u0a10\u0a13-\u0a28\u0a2a-\u0a30\u0a32\u0a33\u0a35\u0a36\u0a38\u0a39\u0a3e-\u0a40\u0a59-\u0a5c\u0a5e\u0a66-\u0a6f\u0a72-\u0a74\u0a83\u0a85-\u0a8d\u0a8f-\u0a91\u0a93-\u0aa8\u0aaa-\u0ab0\u0ab2\u0ab3\u0ab5-\u0ab9\u0abd-\u0ac0\u0ac9\u0acb\u0acc\u0ad0\u0ae0\u0ae1\u0ae6-\u0af0\u0af9\u0b02\u0b03\u0b05-\u0b0c\u0b0f\u0b10\u0b13-\u0b28\u0b2a-\u0b30\u0b32\u0b33\u0b35-\u0b39\u0b3d\u0b3e\u0b40\u0b47\u0b48\u0b4b\u0b4c\u0b57\u0b5c\u0b5d\u0b5f-\u0b61\u0b66-\u0b77\u0b83\u0b85-\u0b8a\u0b8e-\u0b90\u0b92-\u0b95\u0b99\u0b9a\u0b9c\u0b9e\u0b9f\u0ba3\u0ba4\u0ba8-\u0baa\u0bae-\u0bb9\u0bbe\u0bbf\u0bc1\u0bc2\u0bc6-\u0bc8\u0bca-\u0bcc\u0bd0\u0bd7\u0be6-\u0bf2\u0c01-\u0c03\u0c05-\u0c0c\u0c0e-\u0c10\u0c12-\u0c28\u0c2a-\u0c39\u0c3d\u0c41-\u0c44\u0c58-\u0c5a\u0c60\u0c61\u0c66-\u0c6f\u0c7f\u0c82\u0c83\u0c85-\u0c8c\u0c8e-\u0c90\u0c92-\u0ca8\u0caa-\u0cb3\u0cb5-\u0cb9\u0cbd-\u0cc4\u0cc6-\u0cc8\u0cca\u0ccb\u0cd5\u0cd6\u0cde\u0ce0\u0ce1\u0ce6-\u0cef\u0cf1\u0cf2\u0d02\u0d03\u0d05-\u0d0c\u0d0e-\u0d10\u0d12-\u0d3a\u0d3d-\u0d40\u0d46-\u0d48\u0d4a-\u0d4c\u0d4e\u0d57\u0d5f-\u0d61\u0d66-\u0d75\u0d79-\u0d7f\u0d82\u0d83\u0d85-\u0d96\u0d9a-\u0db1\u0db3-\u0dbb\u0dbd\u0dc0-\u0dc6\u0dcf-\u0dd1\u0dd8-\u0ddf\u0de6-\u0def\u0df2-\u0df4\u0e01-\u0e30\u0e32\u0e33\u0e40-\u0e46\u0e4f-\u0e5b\u0e81\u0e82\u0e84\u0e87\u0e88\u0e8a\u0e8d\u0e94-\u0e97\u0e99-\u0e9f\u0ea1-\u0ea3\u0ea5\u0ea7\u0eaa\u0eab\u0ead-\u0eb0\u0eb2\u0eb3\u0ebd\u0ec0-\u0ec4\u0ec6\u0ed0-\u0ed9\u0edc-\u0edf\u0f00-\u0f17\u0f1a-\u0f34\u0f36\u0f38\u0f3e-\u0f47\u0f49-\u0f6c\u0f7f\u0f85\u0f88-\u0f8c\u0fbe-\u0fc5\u0fc7-\u0fcc\u0fce-\u0fda\u1000-\u102c\u1031\u1038\u103b\u103c\u103f-\u1057\u105a-\u105d\u1061-\u1070\u1075-\u1081\u1083\u1084\u1087-\u108c\u108e-\u109c\u109e-\u10c5\u10c7\u10cd\u10d0-\u1248\u124a-\u124d\u1250-\u1256\u1258\u125a-\u125d\u1260-\u1288\u128a-\u128d\u1290-\u12b0\u12b2-\u12b5\u12b8-\u12be\u12c0\u12c2-\u12c5\u12c8-\u12d6\u12d8-\u1310\u1312-\u1315\u1318-\u135a\u1360-\u137c\u1380-\u138f\u13a0-\u13f5\u13f8-\u13fd\u1401-\u167f\u1681-\u169a\u16a0-\u16f8\u1700-\u170c\u170e-\u1711\u1720-\u1731\u1735\u1736\u1740-\u1751\u1760-\u176c\u176e-\u1770\u1780-\u17b3\u17b6\u17be-\u17c5\u17c7\u17c8\u17d4-\u17da\u17dc\u17e0-\u17e9\u1810-\u1819\u1820-\u1877\u1880-\u18a8\u18aa\u18b0-\u18f5\u1900-\u191e\u1923-\u1926\u1929-\u192b\u1930\u1931\u1933-\u1938\u1946-\u196d\u1970-\u1974\u1980-\u19ab\u19b0-\u19c9\u19d0-\u19da\u1a00-\u1a16\u1a19\u1a1a\u1a1e-\u1a55\u1a57\u1a61\u1a63\u1a64\u1a6d-\u1a72\u1a80-\u1a89\u1a90-\u1a99\u1aa0-\u1aad\u1b04-\u1b33\u1b35\u1b3b\u1b3d-\u1b41\u1b43-\u1b4b\u1b50-\u1b6a\u1b74-\u1b7c\u1b82-\u1ba1\u1ba6\u1ba7\u1baa\u1bae-\u1be5\u1be7\u1bea-\u1bec\u1bee\u1bf2\u1bf3\u1bfc-\u1c2b\u1c34\u1c35\u1c3b-\u1c49\u1c4d-\u1c7f\u1cc0-\u1cc7\u1cd3\u1ce1\u1ce9-\u1cec\u1cee-\u1cf3\u1cf5\u1cf6\u1d00-\u1dbf\u1e00-\u1f15\u1f18-\u1f1d\u1f20-\u1f45\u1f48-\u1f4d\u1f50-\u1f57\u1f59\u1f5b\u1f5d\u1f5f-\u1f7d\u1f80-\u1fb4\u1fb6-\u1fbc\u1fbe\u1fc2-\u1fc4\u1fc6-\u1fcc\u1fd0-\u1fd3\u1fd6-\u1fdb\u1fe0-\u1fec\u1ff2-\u1ff4\u1ff6-\u1ffc\u200e\u2071\u207f\u2090-\u209c\u2102\u2107\u210a-\u2113\u2115\u2119-\u211d\u2124\u2126\u2128\u212a-\u212d\u212f-\u2139\u213c-\u213f\u2145-\u2149\u214e\u214f\u2160-\u2188\u2336-\u237a\u2395\u249c-\u24e9\u26ac\u2800-\u28ff\u2c00-\u2c2e\u2c30-\u2c5e\u2c60-\u2ce4\u2ceb-\u2cee\u2cf2\u2cf3\u2d00-\u2d25\u2d27\u2d2d\u2d30-\u2d67\u2d6f\u2d70\u2d80-\u2d96\u2da0-\u2da6\u2da8-\u2dae\u2db0-\u2db6\u2db8-\u2dbe\u2dc0-\u2dc6\u2dc8-\u2dce\u2dd0-\u2dd6\u2dd8-\u2dde\u3005-\u3007\u3021-\u3029\u302e\u302f\u3031-\u3035\u3038-\u303c\u3041-\u3096\u309d-\u309f\u30a1-\u30fa\u30fc-\u30ff\u3105-\u312d\u3131-\u318e\u3190-\u31ba\u31f0-\u321c\u3220-\u324f\u3260-\u327b\u327f-\u32b0\u32c0-\u32cb\u32d0-\u32fe\u3300-\u3376\u337b-\u33dd\u33e0-\u33fe\u3400-\u4db5\u4e00-\u9fd5\ua000-\ua48c\ua4d0-\ua60c\ua610-\ua62b\ua640-\ua66e\ua680-\ua69d\ua6a0-\ua6ef\ua6f2-\ua6f7\ua722-\ua787\ua789-\ua7ad\ua7b0-\ua7b7\ua7f7-\ua801\ua803-\ua805\ua807-\ua80a\ua80c-\ua824\ua827\ua830-\ua837\ua840-\ua873\ua880-\ua8c3\ua8ce-\ua8d9\ua8f2-\ua8fd\ua900-\ua925\ua92e-\ua946\ua952\ua953\ua95f-\ua97c\ua983-\ua9b2\ua9b4\ua9b5\ua9ba\ua9bb\ua9bd-\ua9cd\ua9cf-\ua9d9\ua9de-\ua9e4\ua9e6-\ua9fe\uaa00-\uaa28\uaa2f\uaa30\uaa33\uaa34\uaa40-\uaa42\uaa44-\uaa4b\uaa4d\uaa50-\uaa59\uaa5c-\uaa7b\uaa7d-\uaaaf\uaab1\uaab5\uaab6\uaab9-\uaabd\uaac0\uaac2\uaadb-\uaaeb\uaaee-\uaaf5\uab01-\uab06\uab09-\uab0e\uab11-\uab16\uab20-\uab26\uab28-\uab2e\uab30-\uab65\uab70-\uabe4\uabe6\uabe7\uabe9-\uabec\uabf0-\uabf9\uac00-\ud7a3\ud7b0-\ud7c6\ud7cb-\ud7fb\ue000-\ufa6d\ufa70-\ufad9\ufb00-\ufb06\ufb13-\ufb17\uff21-\uff3a\uff41-\uff5a\uff66-\uffbe\uffc2-\uffc7\uffca-\uffcf\uffd2-\uffd7\uffda-\uffdc]|\ud800[\udc00-\udc0b]|\ud800[\udc0d-\udc26]|\ud800[\udc28-\udc3a]|\ud800\udc3c|\ud800\udc3d|\ud800[\udc3f-\udc4d]|\ud800[\udc50-\udc5d]|\ud800[\udc80-\udcfa]|\ud800\udd00|\ud800\udd02|\ud800[\udd07-\udd33]|\ud800[\udd37-\udd3f]|\ud800[\uddd0-\uddfc]|\ud800[\ude80-\ude9c]|\ud800[\udea0-\uded0]|\ud800[\udf00-\udf23]|\ud800[\udf30-\udf4a]|\ud800[\udf50-\udf75]|\ud800[\udf80-\udf9d]|\ud800[\udf9f-\udfc3]|\ud800[\udfc8-\udfd5]|\ud801[\udc00-\udc9d]|\ud801[\udca0-\udca9]|\ud801[\udd00-\udd27]|\ud801[\udd30-\udd63]|\ud801\udd6f|\ud801[\ude00-\udf36]|\ud801[\udf40-\udf55]|\ud801[\udf60-\udf67]|\ud804\udc00|\ud804[\udc02-\udc37]|\ud804[\udc47-\udc4d]|\ud804[\udc66-\udc6f]|\ud804[\udc82-\udcb2]|\ud804\udcb7|\ud804\udcb8|\ud804[\udcbb-\udcc1]|\ud804[\udcd0-\udce8]|\ud804[\udcf0-\udcf9]|\ud804[\udd03-\udd26]|\ud804\udd2c|\ud804[\udd36-\udd43]|\ud804[\udd50-\udd72]|\ud804[\udd74-\udd76]|\ud804[\udd82-\uddb5]|\ud804[\uddbf-\uddc9]|\ud804\uddcd|\ud804[\uddd0-\udddf]|\ud804[\udde1-\uddf4]|\ud804[\ude00-\ude11]|\ud804[\ude13-\ude2e]|\ud804\ude32|\ud804\ude33|\ud804\ude35|\ud804[\ude38-\ude3d]|\ud804[\ude80-\ude86]|\ud804\ude88|\ud804[\ude8a-\ude8d]|\ud804[\ude8f-\ude9d]|\ud804[\ude9f-\udea9]|\ud804[\udeb0-\udede]|\ud804[\udee0-\udee2]|\ud804[\udef0-\udef9]|\ud804\udf02|\ud804\udf03|\ud804[\udf05-\udf0c]|\ud804\udf0f|\ud804\udf10|\ud804[\udf13-\udf28]|\ud804[\udf2a-\udf30]|\ud804\udf32|\ud804\udf33|\ud804[\udf35-\udf39]|\ud804[\udf3d-\udf3f]|\ud804[\udf41-\udf44]|\ud804\udf47|\ud804\udf48|\ud804[\udf4b-\udf4d]|\ud804\udf50|\ud804\udf57|\ud804[\udf5d-\udf63]|\ud805[\udc80-\udcb2]|\ud805\udcb9|\ud805[\udcbb-\udcbe]|\ud805\udcc1|\ud805[\udcc4-\udcc7]|\ud805[\udcd0-\udcd9]|\ud805[\udd80-\uddb1]|\ud805[\uddb8-\uddbb]|\ud805\uddbe|\ud805[\uddc1-\udddb]|\ud805[\ude00-\ude32]|\ud805\ude3b|\ud805\ude3c|\ud805\ude3e|\ud805[\ude41-\ude44]|\ud805[\ude50-\ude59]|\ud805[\ude80-\udeaa]|\ud805\udeac|\ud805\udeae|\ud805\udeaf|\ud805\udeb6|\ud805[\udec0-\udec9]|\ud805[\udf00-\udf19]|\ud805\udf20|\ud805\udf21|\ud805\udf26|\ud805[\udf30-\udf3f]|\ud806[\udca0-\udcf2]|\ud806\udcff|\ud806[\udec0-\udef8]|\ud808[\udc00-\udf99]|\ud809[\udc00-\udc6e]|\ud809[\udc70-\udc74]|\ud809[\udc80-\udd43]|\ud80c[\udc00-\udfff]|\ud80d[\udc00-\udc2e]|\ud811[\udc00-\ude46]|\ud81a[\udc00-\ude38]|\ud81a[\ude40-\ude5e]|\ud81a[\ude60-\ude69]|\ud81a\ude6e|\ud81a\ude6f|\ud81a[\uded0-\udeed]|\ud81a\udef5|\ud81a[\udf00-\udf2f]|\ud81a[\udf37-\udf45]|\ud81a[\udf50-\udf59]|\ud81a[\udf5b-\udf61]|\ud81a[\udf63-\udf77]|\ud81a[\udf7d-\udf8f]|\ud81b[\udf00-\udf44]|\ud81b[\udf50-\udf7e]|\ud81b[\udf93-\udf9f]|\ud82c\udc00|\ud82c\udc01|\ud82f[\udc00-\udc6a]|\ud82f[\udc70-\udc7c]|\ud82f[\udc80-\udc88]|\ud82f[\udc90-\udc99]|\ud82f\udc9c|\ud82f\udc9f|\ud834[\udc00-\udcf5]|\ud834[\udd00-\udd26]|\ud834[\udd29-\udd66]|\ud834[\udd6a-\udd72]|\ud834\udd83|\ud834\udd84|\ud834[\udd8c-\udda9]|\ud834[\uddae-\udde8]|\ud834[\udf60-\udf71]|\ud835[\udc00-\udc54]|\ud835[\udc56-\udc9c]|\ud835\udc9e|\ud835\udc9f|\ud835\udca2|\ud835\udca5|\ud835\udca6|\ud835[\udca9-\udcac]|\ud835[\udcae-\udcb9]|\ud835\udcbb|\ud835[\udcbd-\udcc3]|\ud835[\udcc5-\udd05]|\ud835[\udd07-\udd0a]|\ud835[\udd0d-\udd14]|\ud835[\udd16-\udd1c]|\ud835[\udd1e-\udd39]|\ud835[\udd3b-\udd3e]|\ud835[\udd40-\udd44]|\ud835\udd46|\ud835[\udd4a-\udd50]|\ud835[\udd52-\udea5]|\ud835[\udea8-\udeda]|\ud835[\udedc-\udf14]|\ud835[\udf16-\udf4e]|\ud835[\udf50-\udf88]|\ud835[\udf8a-\udfc2]|\ud835[\udfc4-\udfcb]|\ud836[\udc00-\uddff]|\ud836[\ude37-\ude3a]|\ud836[\ude6d-\ude74]|\ud836[\ude76-\ude83]|\ud836[\ude85-\ude8b]|\ud83c[\udd10-\udd2e]|\ud83c[\udd30-\udd69]|\ud83c[\udd70-\udd9a]|\ud83c[\udde6-\ude02]|\ud83c[\ude10-\ude3a]|\ud83c[\ude40-\ude48]|\ud83c\ude50|\ud83c\ude51|[\ud840-\ud868][\udc00-\udfff]|\ud869[\udc00-\uded6]|\ud869[\udf00-\udfff]|[\ud86a-\ud86c][\udc00-\udfff]|\ud86d[\udc00-\udf34]|\ud86d[\udf40-\udfff]|\ud86e[\udc00-\udc1d]|\ud86e[\udc20-\udfff]|[\ud86f-\ud872][\udc00-\udfff]|\ud873[\udc00-\udea1]|\ud87e[\udc00-\ude1d]|[\udb80-\udbbe][\udc00-\udfff]|\udbbf[\udc00-\udffd]|[\udbc0-\udbfe][\udc00-\udfff]|\udbff[\udc00-\udffd]' +
+ ')|(' +
+ '[\u0590\u05be\u05c0\u05c3\u05c6\u05c8-\u05ff\u07c0-\u07ea\u07f4\u07f5\u07fa-\u0815\u081a\u0824\u0828\u082e-\u0858\u085c-\u089f\u200f\ufb1d\ufb1f-\ufb28\ufb2a-\ufb4f\u0608\u060b\u060d\u061b-\u064a\u066d-\u066f\u0671-\u06d5\u06e5\u06e6\u06ee\u06ef\u06fa-\u0710\u0712-\u072f\u074b-\u07a5\u07b1-\u07bf\u08a0-\u08e2\ufb50-\ufd3d\ufd40-\ufdcf\ufdf0-\ufdfc\ufdfe\ufdff\ufe70-\ufefe]|\ud802[\udc00-\udd1e]|\ud802[\udd20-\ude00]|\ud802\ude04|\ud802[\ude07-\ude0b]|\ud802[\ude10-\ude37]|\ud802[\ude3b-\ude3e]|\ud802[\ude40-\udee4]|\ud802[\udee7-\udf38]|\ud802[\udf40-\udfff]|\ud803[\udc00-\ude5f]|\ud803[\ude7f-\udfff]|\ud83a[\udc00-\udccf]|\ud83a[\udcd7-\udfff]|\ud83b[\udc00-\uddff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\udf00-\udfff]|\ud83b[\ude00-\udeef]|\ud83b[\udef2-\udeff]' +
+ ')' +
+ ')'
+ );
+
+ /**
+ * Gets directionality of the first strongly directional codepoint
+ *
+ * This is the rule the BIDI algorithm uses to determine the directionality of
+ * paragraphs ( http://unicode.org/reports/tr9/#The_Paragraph_Level ) and
+ * FSI isolates ( http://unicode.org/reports/tr9/#Explicit_Directional_Isolates ).
+ *
+ * TODO: Does not handle BIDI control characters inside the text.
+ * TODO: Does not handle unallocated characters.
+ */
+ function strongDirFromContent( text ) {
+ var m = text.match( strongDirRegExp );
+ if ( !m ) {
+ return null;
+ }
+ if ( m[2] === undefined ) {
+ return 'ltr';
+ }
+ return 'rtl';
+ }
+
+ $.extend( $.i18n.parser.emitter, {
+ /**
+ * Wraps argument with unicode control characters for directionality safety
+ *
+ * This solves the problem where directionality-neutral characters at the edge of
+ * the argument string get interpreted with the wrong directionality from the
+ * enclosing context, giving renderings that look corrupted like "(Ben_(WMF".
+ *
+ * The wrapping is LRE...PDF or RLE...PDF, depending on the detected
+ * directionality of the argument string, using the BIDI algorithm's own "First
+ * strong directional codepoint" rule. Essentially, this works round the fact that
+ * there is no embedding equivalent of U+2068 FSI (isolation with heuristic
+ * direction inference). The latter is cleaner but still not widely supported.
+ */
+ bidi: function ( nodes ) {
+ var dir = strongDirFromContent( nodes[0] );
+ if ( dir === 'ltr' ) {
+ // Wrap in LEFT-TO-RIGHT EMBEDDING ... POP DIRECTIONAL FORMATTING
+ return '\u202A' + nodes[0] + '\u202C';
+ }
+ if ( dir === 'rtl' ) {
+ // Wrap in RIGHT-TO-LEFT EMBEDDING ... POP DIRECTIONAL FORMATTING
+ return '\u202B' + nodes[0] + '\u202C';
+ }
+ // No strong directionality: do not wrap
+ return nodes[0];
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.emitter.js b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.emitter.js
new file mode 100644
index 00000000..b26f147d
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.emitter.js
@@ -0,0 +1,168 @@
+/**
+ * jQuery Internationalization library
+ *
+ * Copyright (C) 2011-2013 Santhosh Thottingal, Neil Kandalgaonkar
+ *
+ * jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do
+ * anything special to choose one license or the other and you don't have to
+ * notify anyone which license you are using. You are free to use
+ * UniversalLanguageSelector in commercial projects as long as the copyright
+ * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
+ *
+ * @licence GNU General Public Licence 2.0 or later
+ * @licence MIT License
+ */
+
+( function ( $ ) {
+ 'use strict';
+
+ var MessageParserEmitter = function () {
+ this.language = $.i18n.languages[String.locale] || $.i18n.languages['default'];
+ };
+
+ MessageParserEmitter.prototype = {
+ constructor: MessageParserEmitter,
+
+ /**
+ * (We put this method definition here, and not in prototype, to make
+ * sure it's not overwritten by any magic.) Walk entire node structure,
+ * applying replacements and template functions when appropriate
+ *
+ * @param {Mixed} node abstract syntax tree (top node or subnode)
+ * @param {Array} replacements for $1, $2, ... $n
+ * @return {Mixed} single-string node or array of nodes suitable for
+ * jQuery appending.
+ */
+ emit: function ( node, replacements ) {
+ var ret, subnodes, operation,
+ messageParserEmitter = this;
+
+ switch ( typeof node ) {
+ case 'string':
+ case 'number':
+ ret = node;
+ break;
+ case 'object':
+ // node is an array of nodes
+ subnodes = $.map( node.slice( 1 ), function ( n ) {
+ return messageParserEmitter.emit( n, replacements );
+ } );
+
+ operation = node[0].toLowerCase();
+
+ if ( typeof messageParserEmitter[operation] === 'function' ) {
+ ret = messageParserEmitter[operation]( subnodes, replacements );
+ } else {
+ throw new Error( 'unknown operation "' + operation + '"' );
+ }
+
+ break;
+ case 'undefined':
+ // Parsing the empty string (as an entire expression, or as a
+ // paramExpression in a template) results in undefined
+ // Perhaps a more clever parser can detect this, and return the
+ // empty string? Or is that useful information?
+ // The logical thing is probably to return the empty string here
+ // when we encounter undefined.
+ ret = '';
+ break;
+ default:
+ throw new Error( 'unexpected type in AST: ' + typeof node );
+ }
+
+ return ret;
+ },
+
+ /**
+ * Parsing has been applied depth-first we can assume that all nodes
+ * here are single nodes Must return a single node to parents -- a
+ * jQuery with synthetic span However, unwrap any other synthetic spans
+ * in our children and pass them upwards
+ *
+ * @param {Array} nodes Mixed, some single nodes, some arrays of nodes.
+ * @return String
+ */
+ concat: function ( nodes ) {
+ var result = '';
+
+ $.each( nodes, function ( i, node ) {
+ // strings, integers, anything else
+ result += node;
+ } );
+
+ return result;
+ },
+
+ /**
+ * Return escaped replacement of correct index, or string if
+ * unavailable. Note that we expect the parsed parameter to be
+ * zero-based. i.e. $1 should have become [ 0 ]. if the specified
+ * parameter is not found return the same string (e.g. "$99" ->
+ * parameter 98 -> not found -> return "$99" ) TODO throw error if
+ * nodes.length > 1 ?
+ *
+ * @param {Array} nodes One element, integer, n >= 0
+ * @param {Array} replacements for $1, $2, ... $n
+ * @return {string} replacement
+ */
+ replace: function ( nodes, replacements ) {
+ var index = parseInt( nodes[0], 10 );
+
+ if ( index < replacements.length ) {
+ // replacement is not a string, don't touch!
+ return replacements[index];
+ } else {
+ // index not found, fallback to displaying variable
+ return '$' + ( index + 1 );
+ }
+ },
+
+ /**
+ * Transform parsed structure into pluralization n.b. The first node may
+ * be a non-integer (for instance, a string representing an Arabic
+ * number). So convert it back with the current language's
+ * convertNumber.
+ *
+ * @param {Array} nodes List [ {String|Number}, {String}, {String} ... ]
+ * @return {String} selected pluralized form according to current
+ * language.
+ */
+ plural: function ( nodes ) {
+ var count = parseFloat( this.language.convertNumber( nodes[0], 10 ) ),
+ forms = nodes.slice( 1 );
+
+ return forms.length ? this.language.convertPlural( count, forms ) : '';
+ },
+
+ /**
+ * Transform parsed structure into gender Usage
+ * {{gender:gender|masculine|feminine|neutral}}.
+ *
+ * @param {Array} nodes List [ {String}, {String}, {String} , {String} ]
+ * @return {String} selected gender form according to current language
+ */
+ gender: function ( nodes ) {
+ var gender = nodes[0],
+ forms = nodes.slice( 1 );
+
+ return this.language.gender( gender, forms );
+ },
+
+ /**
+ * Transform parsed structure into grammar conversion. Invoked by
+ * putting {{grammar:form|word}} in a message
+ *
+ * @param {Array} nodes List [{Grammar case eg: genitive}, {String word}]
+ * @return {String} selected grammatical form according to current
+ * language.
+ */
+ grammar: function ( nodes ) {
+ var form = nodes[0],
+ word = nodes[1];
+
+ return word && form && this.language.convertGrammar( word, form );
+ }
+ };
+
+ $.extend( $.i18n.parser.emitter, new MessageParserEmitter() );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.fallbacks.js b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.fallbacks.js
new file mode 100644
index 00000000..4584c5f2
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.fallbacks.js
@@ -0,0 +1,186 @@
+/**
+ * jQuery Internationalization library
+ *
+ * Copyright (C) 2012 Santhosh Thottingal
+ *
+ * jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do anything special to
+ * choose one license or the other and you don't have to notify anyone which license you are using.
+ * You are free to use UniversalLanguageSelector in commercial projects as long as the copyright
+ * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
+ *
+ * @licence GNU General Public Licence 2.0 or later
+ * @licence MIT License
+ */
+( function ( $, undefined ) {
+ 'use strict';
+
+ $.i18n = $.i18n || {};
+ $.extend( $.i18n.fallbacks, {
+ ab: [ 'ru' ],
+ ace: [ 'id' ],
+ aln: [ 'sq' ],
+ // Not so standard - als is supposed to be Tosk Albanian,
+ // but in Wikipedia it's used for a Germanic language.
+ als: [ 'gsw', 'de' ],
+ an: [ 'es' ],
+ anp: [ 'hi' ],
+ arn: [ 'es' ],
+ arz: [ 'ar' ],
+ av: [ 'ru' ],
+ ay: [ 'es' ],
+ ba: [ 'ru' ],
+ bar: [ 'de' ],
+ 'bat-smg': [ 'sgs', 'lt' ],
+ bcc: [ 'fa' ],
+ 'be-x-old': [ 'be-tarask' ],
+ bh: [ 'bho' ],
+ bjn: [ 'id' ],
+ bm: [ 'fr' ],
+ bpy: [ 'bn' ],
+ bqi: [ 'fa' ],
+ bug: [ 'id' ],
+ 'cbk-zam': [ 'es' ],
+ ce: [ 'ru' ],
+ crh: [ 'crh-latn' ],
+ 'crh-cyrl': [ 'ru' ],
+ csb: [ 'pl' ],
+ cv: [ 'ru' ],
+ 'de-at': [ 'de' ],
+ 'de-ch': [ 'de' ],
+ 'de-formal': [ 'de' ],
+ dsb: [ 'de' ],
+ dtp: [ 'ms' ],
+ egl: [ 'it' ],
+ eml: [ 'it' ],
+ ff: [ 'fr' ],
+ fit: [ 'fi' ],
+ 'fiu-vro': [ 'vro', 'et' ],
+ frc: [ 'fr' ],
+ frp: [ 'fr' ],
+ frr: [ 'de' ],
+ fur: [ 'it' ],
+ gag: [ 'tr' ],
+ gan: [ 'gan-hant', 'zh-hant', 'zh-hans' ],
+ 'gan-hans': [ 'zh-hans' ],
+ 'gan-hant': [ 'zh-hant', 'zh-hans' ],
+ gl: [ 'pt' ],
+ glk: [ 'fa' ],
+ gn: [ 'es' ],
+ gsw: [ 'de' ],
+ hif: [ 'hif-latn' ],
+ hsb: [ 'de' ],
+ ht: [ 'fr' ],
+ ii: [ 'zh-cn', 'zh-hans' ],
+ inh: [ 'ru' ],
+ iu: [ 'ike-cans' ],
+ jut: [ 'da' ],
+ jv: [ 'id' ],
+ kaa: [ 'kk-latn', 'kk-cyrl' ],
+ kbd: [ 'kbd-cyrl' ],
+ khw: [ 'ur' ],
+ kiu: [ 'tr' ],
+ kk: [ 'kk-cyrl' ],
+ 'kk-arab': [ 'kk-cyrl' ],
+ 'kk-latn': [ 'kk-cyrl' ],
+ 'kk-cn': [ 'kk-arab', 'kk-cyrl' ],
+ 'kk-kz': [ 'kk-cyrl' ],
+ 'kk-tr': [ 'kk-latn', 'kk-cyrl' ],
+ kl: [ 'da' ],
+ 'ko-kp': [ 'ko' ],
+ koi: [ 'ru' ],
+ krc: [ 'ru' ],
+ ks: [ 'ks-arab' ],
+ ksh: [ 'de' ],
+ ku: [ 'ku-latn' ],
+ 'ku-arab': [ 'ckb' ],
+ kv: [ 'ru' ],
+ lad: [ 'es' ],
+ lb: [ 'de' ],
+ lbe: [ 'ru' ],
+ lez: [ 'ru' ],
+ li: [ 'nl' ],
+ lij: [ 'it' ],
+ liv: [ 'et' ],
+ lmo: [ 'it' ],
+ ln: [ 'fr' ],
+ ltg: [ 'lv' ],
+ lzz: [ 'tr' ],
+ mai: [ 'hi' ],
+ 'map-bms': [ 'jv', 'id' ],
+ mg: [ 'fr' ],
+ mhr: [ 'ru' ],
+ min: [ 'id' ],
+ mo: [ 'ro' ],
+ mrj: [ 'ru' ],
+ mwl: [ 'pt' ],
+ myv: [ 'ru' ],
+ mzn: [ 'fa' ],
+ nah: [ 'es' ],
+ nap: [ 'it' ],
+ nds: [ 'de' ],
+ 'nds-nl': [ 'nl' ],
+ 'nl-informal': [ 'nl' ],
+ no: [ 'nb' ],
+ os: [ 'ru' ],
+ pcd: [ 'fr' ],
+ pdc: [ 'de' ],
+ pdt: [ 'de' ],
+ pfl: [ 'de' ],
+ pms: [ 'it' ],
+ pt: [ 'pt-br' ],
+ 'pt-br': [ 'pt' ],
+ qu: [ 'es' ],
+ qug: [ 'qu', 'es' ],
+ rgn: [ 'it' ],
+ rmy: [ 'ro' ],
+ 'roa-rup': [ 'rup' ],
+ rue: [ 'uk', 'ru' ],
+ ruq: [ 'ruq-latn', 'ro' ],
+ 'ruq-cyrl': [ 'mk' ],
+ 'ruq-latn': [ 'ro' ],
+ sa: [ 'hi' ],
+ sah: [ 'ru' ],
+ scn: [ 'it' ],
+ sg: [ 'fr' ],
+ sgs: [ 'lt' ],
+ sli: [ 'de' ],
+ sr: [ 'sr-ec' ],
+ srn: [ 'nl' ],
+ stq: [ 'de' ],
+ su: [ 'id' ],
+ szl: [ 'pl' ],
+ tcy: [ 'kn' ],
+ tg: [ 'tg-cyrl' ],
+ tt: [ 'tt-cyrl', 'ru' ],
+ 'tt-cyrl': [ 'ru' ],
+ ty: [ 'fr' ],
+ udm: [ 'ru' ],
+ ug: [ 'ug-arab' ],
+ uk: [ 'ru' ],
+ vec: [ 'it' ],
+ vep: [ 'et' ],
+ vls: [ 'nl' ],
+ vmf: [ 'de' ],
+ vot: [ 'fi' ],
+ vro: [ 'et' ],
+ wa: [ 'fr' ],
+ wo: [ 'fr' ],
+ wuu: [ 'zh-hans' ],
+ xal: [ 'ru' ],
+ xmf: [ 'ka' ],
+ yi: [ 'he' ],
+ za: [ 'zh-hans' ],
+ zea: [ 'nl' ],
+ zh: [ 'zh-hans' ],
+ 'zh-classical': [ 'lzh' ],
+ 'zh-cn': [ 'zh-hans' ],
+ 'zh-hant': [ 'zh-hans' ],
+ 'zh-hk': [ 'zh-hant', 'zh-hans' ],
+ 'zh-min-nan': [ 'nan' ],
+ 'zh-mo': [ 'zh-hk', 'zh-hant', 'zh-hans' ],
+ 'zh-my': [ 'zh-sg', 'zh-hans' ],
+ 'zh-sg': [ 'zh-hans' ],
+ 'zh-tw': [ 'zh-hant', 'zh-hans' ],
+ 'zh-yue': [ 'yue' ]
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.js b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.js
new file mode 100644
index 00000000..9236e4e2
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.js
@@ -0,0 +1,287 @@
+/**
+ * jQuery Internationalization library
+ *
+ * Copyright (C) 2012 Santhosh Thottingal
+ *
+ * jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do
+ * anything special to choose one license or the other and you don't have to
+ * notify anyone which license you are using. You are free to use
+ * UniversalLanguageSelector in commercial projects as long as the copyright
+ * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
+ *
+ * @licence GNU General Public Licence 2.0 or later
+ * @licence MIT License
+ */
+
+( function ( $ ) {
+ 'use strict';
+
+ var nav, I18N,
+ slice = Array.prototype.slice;
+ /**
+ * @constructor
+ * @param {Object} options
+ */
+ I18N = function ( options ) {
+ // Load defaults
+ this.options = $.extend( {}, I18N.defaults, options );
+
+ this.parser = this.options.parser;
+ this.locale = this.options.locale;
+ this.messageStore = this.options.messageStore;
+ this.languages = {};
+
+ this.init();
+ };
+
+ I18N.prototype = {
+ /**
+ * Initialize by loading locales and setting up
+ * String.prototype.toLocaleString and String.locale.
+ */
+ init: function () {
+ var i18n = this;
+
+ // Set locale of String environment
+ String.locale = i18n.locale;
+
+ // Override String.localeString method
+ String.prototype.toLocaleString = function () {
+ var localeParts, localePartIndex, value, locale, fallbackIndex,
+ tryingLocale, message;
+
+ value = this.valueOf();
+ locale = i18n.locale;
+ fallbackIndex = 0;
+
+ while ( locale ) {
+ // Iterate through locales starting at most-specific until
+ // localization is found. As in fi-Latn-FI, fi-Latn and fi.
+ localeParts = locale.split( '-' );
+ localePartIndex = localeParts.length;
+
+ do {
+ tryingLocale = localeParts.slice( 0, localePartIndex ).join( '-' );
+ message = i18n.messageStore.get( tryingLocale, value );
+
+ if ( message ) {
+ return message;
+ }
+
+ localePartIndex--;
+ } while ( localePartIndex );
+
+ if ( locale === 'en' ) {
+ break;
+ }
+
+ locale = ( $.i18n.fallbacks[i18n.locale] && $.i18n.fallbacks[i18n.locale][fallbackIndex] ) ||
+ i18n.options.fallbackLocale;
+ $.i18n.log( 'Trying fallback locale for ' + i18n.locale + ': ' + locale );
+
+ fallbackIndex++;
+ }
+
+ // key not found
+ return '';
+ };
+ },
+
+ /*
+ * Destroy the i18n instance.
+ */
+ destroy: function () {
+ $.removeData( document, 'i18n' );
+ },
+
+ /**
+ * General message loading API This can take a URL string for
+ * the json formatted messages. Example:
+ * <code>load('path/to/all_localizations.json');</code>
+ *
+ * To load a localization file for a locale:
+ * <code>
+ * load('path/to/de-messages.json', 'de' );
+ * </code>
+ *
+ * To load a localization file from a directory:
+ * <code>
+ * load('path/to/i18n/directory', 'de' );
+ * </code>
+ * The above method has the advantage of fallback resolution.
+ * ie, it will automatically load the fallback locales for de.
+ * For most usecases, this is the recommended method.
+ * It is optional to have trailing slash at end.
+ *
+ * A data object containing message key- message translation mappings
+ * can also be passed. Example:
+ * <code>
+ * load( { 'hello' : 'Hello' }, optionalLocale );
+ * </code>
+ *
+ * A source map containing key-value pair of languagename and locations
+ * can also be passed. Example:
+ * <code>
+ * load( {
+ * bn: 'i18n/bn.json',
+ * he: 'i18n/he.json',
+ * en: 'i18n/en.json'
+ * } )
+ * </code>
+ *
+ * If the data argument is null/undefined/false,
+ * all cached messages for the i18n instance will get reset.
+ *
+ * @param {String|Object} source
+ * @param {String} locale Language tag
+ * @returns {jQuery.Promise}
+ */
+ load: function ( source, locale ) {
+ var fallbackLocales, locIndex, fallbackLocale, sourceMap = {};
+ if ( !source && !locale ) {
+ source = 'i18n/' + $.i18n().locale + '.json';
+ locale = $.i18n().locale;
+ }
+ if ( typeof source === 'string' &&
+ source.split( '.' ).pop() !== 'json'
+ ) {
+ // Load specified locale then check for fallbacks when directory is specified in load()
+ sourceMap[locale] = source + '/' + locale + '.json';
+ fallbackLocales = ( $.i18n.fallbacks[locale] || [] )
+ .concat( this.options.fallbackLocale );
+ for ( locIndex in fallbackLocales ) {
+ fallbackLocale = fallbackLocales[locIndex];
+ sourceMap[fallbackLocale] = source + '/' + fallbackLocale + '.json';
+ }
+ return this.load( sourceMap );
+ } else {
+ return this.messageStore.load( source, locale );
+ }
+
+ },
+
+ /**
+ * Does parameter and magic word substitution.
+ *
+ * @param {string} key Message key
+ * @param {Array} parameters Message parameters
+ * @return {string}
+ */
+ parse: function ( key, parameters ) {
+ var message = key.toLocaleString();
+ // FIXME: This changes the state of the I18N object,
+ // should probably not change the 'this.parser' but just
+ // pass it to the parser.
+ this.parser.language = $.i18n.languages[$.i18n().locale] || $.i18n.languages['default'];
+ if ( message === '' ) {
+ message = key;
+ }
+ return this.parser.parse( message, parameters );
+ }
+ };
+
+ /**
+ * Process a message from the $.I18N instance
+ * for the current document, stored in jQuery.data(document).
+ *
+ * @param {string} key Key of the message.
+ * @param {string} param1 [param...] Variadic list of parameters for {key}.
+ * @return {string|$.I18N} Parsed message, or if no key was given
+ * the instance of $.I18N is returned.
+ */
+ $.i18n = function ( key, param1 ) {
+ var parameters,
+ i18n = $.data( document, 'i18n' ),
+ options = typeof key === 'object' && key;
+
+ // If the locale option for this call is different then the setup so far,
+ // update it automatically. This doesn't just change the context for this
+ // call but for all future call as well.
+ // If there is no i18n setup yet, don't do this. It will be taken care of
+ // by the `new I18N` construction below.
+ // NOTE: It should only change language for this one call.
+ // Then cache instances of I18N somewhere.
+ if ( options && options.locale && i18n && i18n.locale !== options.locale ) {
+ String.locale = i18n.locale = options.locale;
+ }
+
+ if ( !i18n ) {
+ i18n = new I18N( options );
+ $.data( document, 'i18n', i18n );
+ }
+
+ if ( typeof key === 'string' ) {
+ if ( param1 !== undefined ) {
+ parameters = slice.call( arguments, 1 );
+ } else {
+ parameters = [];
+ }
+
+ return i18n.parse( key, parameters );
+ } else {
+ // FIXME: remove this feature/bug.
+ return i18n;
+ }
+ };
+
+ $.fn.i18n = function () {
+ var i18n = $.data( document, 'i18n' );
+
+ if ( !i18n ) {
+ i18n = new I18N();
+ $.data( document, 'i18n', i18n );
+ }
+ String.locale = i18n.locale;
+ return this.each( function () {
+ var $this = $( this ),
+ messageKey = $this.data( 'i18n' );
+
+ if ( messageKey ) {
+ $this.text( i18n.parse( messageKey ) );
+ } else {
+ $this.find( '[data-i18n]' ).i18n();
+ }
+ } );
+ };
+
+ String.locale = String.locale || $( 'html' ).attr( 'lang' );
+
+ if ( !String.locale ) {
+ if ( typeof window.navigator !== undefined ) {
+ nav = window.navigator;
+ String.locale = nav.language || nav.userLanguage || '';
+ } else {
+ String.locale = '';
+ }
+ }
+
+ $.i18n.languages = {};
+ $.i18n.messageStore = $.i18n.messageStore || {};
+ $.i18n.parser = {
+ // The default parser only handles variable substitution
+ parse: function ( message, parameters ) {
+ return message.replace( /\$(\d+)/g, function ( str, match ) {
+ var index = parseInt( match, 10 ) - 1;
+ return parameters[index] !== undefined ? parameters[index] : '$' + match;
+ } );
+ },
+ emitter: {}
+ };
+ $.i18n.fallbacks = {};
+ $.i18n.debug = false;
+ $.i18n.log = function ( /* arguments */ ) {
+ if ( window.console && $.i18n.debug ) {
+ window.console.log.apply( window.console, arguments );
+ }
+ };
+ /* Static members */
+ I18N.defaults = {
+ locale: String.locale,
+ fallbackLocale: 'en',
+ parser: $.i18n.parser,
+ messageStore: $.i18n.messageStore
+ };
+
+ // Expose constructor
+ $.i18n.constructor = I18N;
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.language.js b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.language.js
new file mode 100644
index 00000000..e596fbc8
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.language.js
@@ -0,0 +1,472 @@
+/*global pluralRuleParser */
+( function ( $ ) {
+ 'use strict';
+
+ var language = {
+ // CLDR plural rules generated using
+ // libs/CLDRPluralRuleParser/tools/PluralXML2JSON.html
+ pluralRules: {
+ ak: {
+ one: 'n = 0..1'
+ },
+ am: {
+ one: 'i = 0 or n = 1'
+ },
+ ar: {
+ zero: 'n = 0',
+ one: 'n = 1',
+ two: 'n = 2',
+ few: 'n % 100 = 3..10',
+ many: 'n % 100 = 11..99'
+ },
+ be: {
+ one: 'n % 10 = 1 and n % 100 != 11',
+ few: 'n % 10 = 2..4 and n % 100 != 12..14',
+ many: 'n % 10 = 0 or n % 10 = 5..9 or n % 100 = 11..14'
+ },
+ bh: {
+ one: 'n = 0..1'
+ },
+ bn: {
+ one: 'i = 0 or n = 1'
+ },
+ br: {
+ one: 'n % 10 = 1 and n % 100 != 11,71,91',
+ two: 'n % 10 = 2 and n % 100 != 12,72,92',
+ few: 'n % 10 = 3..4,9 and n % 100 != 10..19,70..79,90..99',
+ many: 'n != 0 and n % 1000000 = 0'
+ },
+ bs: {
+ one: 'v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11',
+ few: 'v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14'
+ },
+ cs: {
+ one: 'i = 1 and v = 0',
+ few: 'i = 2..4 and v = 0',
+ many: 'v != 0'
+ },
+ cy: {
+ zero: 'n = 0',
+ one: 'n = 1',
+ two: 'n = 2',
+ few: 'n = 3',
+ many: 'n = 6'
+ },
+ da: {
+ one: 'n = 1 or t != 0 and i = 0,1'
+ },
+ fa: {
+ one: 'i = 0 or n = 1'
+ },
+ ff: {
+ one: 'i = 0,1'
+ },
+ fil: {
+ one: 'i = 0..1 and v = 0'
+ },
+ fr: {
+ one: 'i = 0,1'
+ },
+ ga: {
+ one: 'n = 1',
+ two: 'n = 2',
+ few: 'n = 3..6',
+ many: 'n = 7..10'
+ },
+ gd: {
+ one: 'n = 1,11',
+ two: 'n = 2,12',
+ few: 'n = 3..10,13..19'
+ },
+ gu: {
+ one: 'i = 0 or n = 1'
+ },
+ guw: {
+ one: 'n = 0..1'
+ },
+ gv: {
+ one: 'n % 10 = 1',
+ two: 'n % 10 = 2',
+ few: 'n % 100 = 0,20,40,60'
+ },
+ he: {
+ one: 'i = 1 and v = 0',
+ two: 'i = 2 and v = 0',
+ many: 'v = 0 and n != 0..10 and n % 10 = 0'
+ },
+ hi: {
+ one: 'i = 0 or n = 1'
+ },
+ hr: {
+ one: 'v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11',
+ few: 'v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14'
+ },
+ hy: {
+ one: 'i = 0,1'
+ },
+ is: {
+ one: 't = 0 and i % 10 = 1 and i % 100 != 11 or t != 0'
+ },
+ iu: {
+ one: 'n = 1',
+ two: 'n = 2'
+ },
+ iw: {
+ one: 'i = 1 and v = 0',
+ two: 'i = 2 and v = 0',
+ many: 'v = 0 and n != 0..10 and n % 10 = 0'
+ },
+ kab: {
+ one: 'i = 0,1'
+ },
+ kn: {
+ one: 'i = 0 or n = 1'
+ },
+ kw: {
+ one: 'n = 1',
+ two: 'n = 2'
+ },
+ lag: {
+ zero: 'n = 0',
+ one: 'i = 0,1 and n != 0'
+ },
+ ln: {
+ one: 'n = 0..1'
+ },
+ lt: {
+ one: 'n % 10 = 1 and n % 100 != 11..19',
+ few: 'n % 10 = 2..9 and n % 100 != 11..19',
+ many: 'f != 0'
+ },
+ lv: {
+ zero: 'n % 10 = 0 or n % 100 = 11..19 or v = 2 and f % 100 = 11..19',
+ one: 'n % 10 = 1 and n % 100 != 11 or v = 2 and f % 10 = 1 and f % 100 != 11 or v != 2 and f % 10 = 1'
+ },
+ mg: {
+ one: 'n = 0..1'
+ },
+ mk: {
+ one: 'v = 0 and i % 10 = 1 or f % 10 = 1'
+ },
+ mo: {
+ one: 'i = 1 and v = 0',
+ few: 'v != 0 or n = 0 or n != 1 and n % 100 = 1..19'
+ },
+ mr: {
+ one: 'i = 0 or n = 1'
+ },
+ mt: {
+ one: 'n = 1',
+ few: 'n = 0 or n % 100 = 2..10',
+ many: 'n % 100 = 11..19'
+ },
+ naq: {
+ one: 'n = 1',
+ two: 'n = 2'
+ },
+ nso: {
+ one: 'n = 0..1'
+ },
+ pa: {
+ one: 'n = 0..1'
+ },
+ pl: {
+ one: 'i = 1 and v = 0',
+ few: 'v = 0 and i % 10 = 2..4 and i % 100 != 12..14',
+ many: 'v = 0 and i != 1 and i % 10 = 0..1 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 12..14'
+ },
+ pt: {
+ one: 'i = 1 and v = 0 or i = 0 and t = 1'
+ },
+ // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
+ pt_PT: {
+ one: 'n = 1 and v = 0'
+ },
+ // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
+ ro: {
+ one: 'i = 1 and v = 0',
+ few: 'v != 0 or n = 0 or n != 1 and n % 100 = 1..19'
+ },
+ ru: {
+ one: 'v = 0 and i % 10 = 1 and i % 100 != 11',
+ many: 'v = 0 and i % 10 = 0 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 11..14'
+ },
+ se: {
+ one: 'n = 1',
+ two: 'n = 2'
+ },
+ sh: {
+ one: 'v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11',
+ few: 'v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14'
+ },
+ shi: {
+ one: 'i = 0 or n = 1',
+ few: 'n = 2..10'
+ },
+ si: {
+ one: 'n = 0,1 or i = 0 and f = 1'
+ },
+ sk: {
+ one: 'i = 1 and v = 0',
+ few: 'i = 2..4 and v = 0',
+ many: 'v != 0'
+ },
+ sl: {
+ one: 'v = 0 and i % 100 = 1',
+ two: 'v = 0 and i % 100 = 2',
+ few: 'v = 0 and i % 100 = 3..4 or v != 0'
+ },
+ sma: {
+ one: 'n = 1',
+ two: 'n = 2'
+ },
+ smi: {
+ one: 'n = 1',
+ two: 'n = 2'
+ },
+ smj: {
+ one: 'n = 1',
+ two: 'n = 2'
+ },
+ smn: {
+ one: 'n = 1',
+ two: 'n = 2'
+ },
+ sms: {
+ one: 'n = 1',
+ two: 'n = 2'
+ },
+ sr: {
+ one: 'v = 0 and i % 10 = 1 and i % 100 != 11 or f % 10 = 1 and f % 100 != 11',
+ few: 'v = 0 and i % 10 = 2..4 and i % 100 != 12..14 or f % 10 = 2..4 and f % 100 != 12..14'
+ },
+ ti: {
+ one: 'n = 0..1'
+ },
+ tl: {
+ one: 'i = 0..1 and v = 0'
+ },
+ tzm: {
+ one: 'n = 0..1 or n = 11..99'
+ },
+ uk: {
+ one: 'v = 0 and i % 10 = 1 and i % 100 != 11',
+ few: 'v = 0 and i % 10 = 2..4 and i % 100 != 12..14',
+ many: 'v = 0 and i % 10 = 0 or v = 0 and i % 10 = 5..9 or v = 0 and i % 100 = 11..14'
+ },
+ wa: {
+ one: 'n = 0..1'
+ },
+ zu: {
+ one: 'i = 0 or n = 1'
+ }
+ },
+
+ /**
+ * Plural form transformations, needed for some languages.
+ *
+ * @param count
+ * integer Non-localized quantifier
+ * @param forms
+ * array List of plural forms
+ * @return string Correct form for quantifier in this language
+ */
+ convertPlural: function ( count, forms ) {
+ var pluralRules,
+ pluralFormIndex,
+ index,
+ explicitPluralPattern = new RegExp( '\\d+=', 'i' ),
+ formCount,
+ form;
+
+ if ( !forms || forms.length === 0 ) {
+ return '';
+ }
+
+ // Handle for Explicit 0= & 1= values
+ for ( index = 0; index < forms.length; index++ ) {
+ form = forms[index];
+ if ( explicitPluralPattern.test( form ) ) {
+ formCount = parseInt( form.substring( 0, form.indexOf( '=' ) ), 10 );
+ if ( formCount === count ) {
+ return ( form.substr( form.indexOf( '=' ) + 1 ) );
+ }
+ forms[index] = undefined;
+ }
+ }
+
+ forms = $.map( forms, function ( form ) {
+ if ( form !== undefined ) {
+ return form;
+ }
+ } );
+
+ pluralRules = this.pluralRules[$.i18n().locale];
+
+ if ( !pluralRules ) {
+ // default fallback.
+ return ( count === 1 ) ? forms[0] : forms[1];
+ }
+
+ pluralFormIndex = this.getPluralForm( count, pluralRules );
+ pluralFormIndex = Math.min( pluralFormIndex, forms.length - 1 );
+
+ return forms[pluralFormIndex];
+ },
+
+ /**
+ * For the number, get the plural for index
+ *
+ * @param number
+ * @param pluralRules
+ * @return plural form index
+ */
+ getPluralForm: function ( number, pluralRules ) {
+ var i,
+ pluralForms = [ 'zero', 'one', 'two', 'few', 'many', 'other' ],
+ pluralFormIndex = 0;
+
+ for ( i = 0; i < pluralForms.length; i++ ) {
+ if ( pluralRules[pluralForms[i]] ) {
+ if ( pluralRuleParser( pluralRules[pluralForms[i]], number ) ) {
+ return pluralFormIndex;
+ }
+
+ pluralFormIndex++;
+ }
+ }
+
+ return pluralFormIndex;
+ },
+
+ /**
+ * Converts a number using digitTransformTable.
+ *
+ * @param {number} num Value to be converted
+ * @param {boolean} integer Convert the return value to an integer
+ */
+ convertNumber: function ( num, integer ) {
+ var tmp, item, i,
+ transformTable, numberString, convertedNumber;
+
+ // Set the target Transform table:
+ transformTable = this.digitTransformTable( $.i18n().locale );
+ numberString = String( num );
+ convertedNumber = '';
+
+ if ( !transformTable ) {
+ return num;
+ }
+
+ // Check if the restore to Latin number flag is set:
+ if ( integer ) {
+ if ( parseFloat( num, 10 ) === num ) {
+ return num;
+ }
+
+ tmp = [];
+
+ for ( item in transformTable ) {
+ tmp[transformTable[item]] = item;
+ }
+
+ transformTable = tmp;
+ }
+
+ for ( i = 0; i < numberString.length; i++ ) {
+ if ( transformTable[numberString[i]] ) {
+ convertedNumber += transformTable[numberString[i]];
+ } else {
+ convertedNumber += numberString[i];
+ }
+ }
+
+ return integer ? parseFloat( convertedNumber, 10 ) : convertedNumber;
+ },
+
+ /**
+ * Grammatical transformations, needed for inflected languages.
+ * Invoked by putting {{grammar:form|word}} in a message.
+ * Override this method for languages that need special grammar rules
+ * applied dynamically.
+ *
+ * @param word {String}
+ * @param form {String}
+ * @return {String}
+ */
+ convertGrammar: function ( word, form ) { /*jshint unused: false */
+ return word;
+ },
+
+ /**
+ * Provides an alternative text depending on specified gender. Usage
+ * {{gender:[gender|user object]|masculine|feminine|neutral}}. If second
+ * or third parameter are not specified, masculine is used.
+ *
+ * These details may be overriden per language.
+ *
+ * @param gender
+ * string male, female, or anything else for neutral.
+ * @param forms
+ * array List of gender forms
+ *
+ * @return string
+ */
+ gender: function ( gender, forms ) {
+ if ( !forms || forms.length === 0 ) {
+ return '';
+ }
+
+ while ( forms.length < 2 ) {
+ forms.push( forms[forms.length - 1] );
+ }
+
+ if ( gender === 'male' ) {
+ return forms[0];
+ }
+
+ if ( gender === 'female' ) {
+ return forms[1];
+ }
+
+ return ( forms.length === 3 ) ? forms[2] : forms[0];
+ },
+
+ /**
+ * Get the digit transform table for the given language
+ * See http://cldr.unicode.org/translation/numbering-systems
+ * @param language
+ * @returns {Array|boolean} List of digits in the passed language or false
+ * representation, or boolean false if there is no information.
+ */
+ digitTransformTable: function ( language ) {
+ var tables = {
+ ar: '٠١٢٣٤٥٦٧٨٩',
+ fa: '۰۱۲۳۴۵۶۷۸۹',
+ ml: '൦൧൨൩൪൫൬൭൮൯',
+ kn: '೦೧೨೩೪೫೬೭೮೯',
+ lo: '໐໑໒໓໔໕໖໗໘໙',
+ or: '୦୧୨୩୪୫୬୭୮୯',
+ kh: '០១២៣៤៥៦៧៨៩',
+ pa: '੦੧੨੩੪੫੬੭੮੯',
+ gu: '૦૧૨૩૪૫૬૭૮૯',
+ hi: '०१२३४५६७८९',
+ my: '၀၁၂၃၄၅၆၇၈၉',
+ ta: '௦௧௨௩௪௫௬௭௮௯',
+ te: '౦౧౨౩౪౫౬౭౮౯',
+ th: '๐๑๒๓๔๕๖๗๘๙', // FIXME use iso 639 codes
+ bo: '༠༡༢༣༤༥༦༧༨༩' // FIXME use iso 639 codes
+ };
+
+ if ( !tables[language] ) {
+ return false;
+ }
+
+ return tables[language].split( '' );
+ }
+ };
+
+ $.extend( $.i18n.languages, {
+ 'default': language
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.messagestore.js b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.messagestore.js
new file mode 100644
index 00000000..759295ce
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.messagestore.js
@@ -0,0 +1,125 @@
+/**
+ * jQuery Internationalization library - Message Store
+ *
+ * Copyright (C) 2012 Santhosh Thottingal
+ *
+ * jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do anything special to
+ * choose one license or the other and you don't have to notify anyone which license you are using.
+ * You are free to use UniversalLanguageSelector in commercial projects as long as the copyright
+ * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
+ *
+ * @licence GNU General Public Licence 2.0 or later
+ * @licence MIT License
+ */
+
+( function ( $, window, undefined ) {
+ 'use strict';
+
+ var MessageStore = function () {
+ this.messages = {};
+ this.sources = {};
+ };
+
+ /**
+ * See https://github.com/wikimedia/jquery.i18n/wiki/Specification#wiki-Message_File_Loading
+ */
+ MessageStore.prototype = {
+
+ /**
+ * General message loading API This can take a URL string for
+ * the json formatted messages.
+ * <code>load('path/to/all_localizations.json');</code>
+ *
+ * This can also load a localization file for a locale <code>
+ * load( 'path/to/de-messages.json', 'de' );
+ * </code>
+ * A data object containing message key- message translation mappings
+ * can also be passed Eg:
+ * <code>
+ * load( { 'hello' : 'Hello' }, optionalLocale );
+ * </code> If the data argument is
+ * null/undefined/false,
+ * all cached messages for the i18n instance will get reset.
+ *
+ * @param {String|Object} source
+ * @param {String} locale Language tag
+ * @return {jQuery.Promise}
+ */
+ load: function ( source, locale ) {
+ var key = null,
+ deferred = null,
+ deferreds = [],
+ messageStore = this;
+
+ if ( typeof source === 'string' ) {
+ // This is a URL to the messages file.
+ $.i18n.log( 'Loading messages from: ' + source );
+ deferred = jsonMessageLoader( source )
+ .done( function ( localization ) {
+ messageStore.set( locale, localization );
+ } );
+
+ return deferred.promise();
+ }
+
+ if ( locale ) {
+ // source is an key-value pair of messages for given locale
+ messageStore.set( locale, source );
+
+ return $.Deferred().resolve();
+ } else {
+ // source is a key-value pair of locales and their source
+ for ( key in source ) {
+ if ( Object.prototype.hasOwnProperty.call( source, key ) ) {
+ locale = key;
+ // No {locale} given, assume data is a group of languages,
+ // call this function again for each language.
+ deferreds.push( messageStore.load( source[key], locale ) );
+ }
+ }
+ return $.when.apply( $, deferreds );
+ }
+
+ },
+
+ /**
+ * Set messages to the given locale.
+ * If locale exists, add messages to the locale.
+ * @param locale
+ * @param messages
+ */
+ set: function ( locale, messages ) {
+ if ( !this.messages[locale] ) {
+ this.messages[locale] = messages;
+ } else {
+ this.messages[locale] = $.extend( this.messages[locale], messages );
+ }
+ },
+
+ /**
+ *
+ * @param locale
+ * @param messageKey
+ * @returns {Boolean}
+ */
+ get: function ( locale, messageKey ) {
+ return this.messages[locale] && this.messages[locale][messageKey];
+ }
+ };
+
+ function jsonMessageLoader( url ) {
+ var deferred = $.Deferred();
+
+ $.getJSON( url )
+ .done( deferred.resolve )
+ .fail( function ( jqxhr, settings, exception ) {
+ $.i18n.log( 'Error in loading messages from ' + url + ' Exception: ' + exception );
+ // Ignore 404 exception, because we are handling fallabacks explicitly
+ deferred.resolve();
+ } );
+
+ return deferred.promise();
+ }
+
+ $.extend( $.i18n.messageStore, new MessageStore() );
+}( jQuery, window ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.parser.js b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.parser.js
new file mode 100644
index 00000000..3dea2842
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/jquery.i18n.parser.js
@@ -0,0 +1,309 @@
+/**
+ * jQuery Internationalization library
+ *
+ * Copyright (C) 2011-2013 Santhosh Thottingal, Neil Kandalgaonkar
+ *
+ * jquery.i18n is dual licensed GPLv2 or later and MIT. You don't have to do
+ * anything special to choose one license or the other and you don't have to
+ * notify anyone which license you are using. You are free to use
+ * UniversalLanguageSelector in commercial projects as long as the copyright
+ * header is left intact. See files GPL-LICENSE and MIT-LICENSE for details.
+ *
+ * @licence GNU General Public Licence 2.0 or later
+ * @licence MIT License
+ */
+
+( function ( $ ) {
+ 'use strict';
+
+ var MessageParser = function ( options ) {
+ this.options = $.extend( {}, $.i18n.parser.defaults, options );
+ this.language = $.i18n.languages[String.locale] || $.i18n.languages['default'];
+ this.emitter = $.i18n.parser.emitter;
+ };
+
+ MessageParser.prototype = {
+
+ constructor: MessageParser,
+
+ simpleParse: function ( message, parameters ) {
+ return message.replace( /\$(\d+)/g, function ( str, match ) {
+ var index = parseInt( match, 10 ) - 1;
+
+ return parameters[index] !== undefined ? parameters[index] : '$' + match;
+ } );
+ },
+
+ parse: function ( message, replacements ) {
+ if ( message.indexOf( '{{' ) < 0 ) {
+ return this.simpleParse( message, replacements );
+ }
+
+ this.emitter.language = $.i18n.languages[$.i18n().locale] ||
+ $.i18n.languages['default'];
+
+ return this.emitter.emit( this.ast( message ), replacements );
+ },
+
+ ast: function ( message ) {
+ var pipe, colon, backslash, anyCharacter, dollar, digits, regularLiteral,
+ regularLiteralWithoutBar, regularLiteralWithoutSpace, escapedOrLiteralWithoutBar,
+ escapedOrRegularLiteral, templateContents, templateName, openTemplate,
+ closeTemplate, expression, paramExpression, result,
+ pos = 0;
+
+ // Try parsers until one works, if none work return null
+ function choice( parserSyntax ) {
+ return function () {
+ var i, result;
+
+ for ( i = 0; i < parserSyntax.length; i++ ) {
+ result = parserSyntax[i]();
+
+ if ( result !== null ) {
+ return result;
+ }
+ }
+
+ return null;
+ };
+ }
+
+ // Try several parserSyntax-es in a row.
+ // All must succeed; otherwise, return null.
+ // This is the only eager one.
+ function sequence( parserSyntax ) {
+ var i, res,
+ originalPos = pos,
+ result = [];
+
+ for ( i = 0; i < parserSyntax.length; i++ ) {
+ res = parserSyntax[i]();
+
+ if ( res === null ) {
+ pos = originalPos;
+
+ return null;
+ }
+
+ result.push( res );
+ }
+
+ return result;
+ }
+
+ // Run the same parser over and over until it fails.
+ // Must succeed a minimum of n times; otherwise, return null.
+ function nOrMore( n, p ) {
+ return function () {
+ var originalPos = pos,
+ result = [],
+ parsed = p();
+
+ while ( parsed !== null ) {
+ result.push( parsed );
+ parsed = p();
+ }
+
+ if ( result.length < n ) {
+ pos = originalPos;
+
+ return null;
+ }
+
+ return result;
+ };
+ }
+
+ // Helpers -- just make parserSyntax out of simpler JS builtin types
+
+ function makeStringParser( s ) {
+ var len = s.length;
+
+ return function () {
+ var result = null;
+
+ if ( message.substr( pos, len ) === s ) {
+ result = s;
+ pos += len;
+ }
+
+ return result;
+ };
+ }
+
+ function makeRegexParser( regex ) {
+ return function () {
+ var matches = message.substr( pos ).match( regex );
+
+ if ( matches === null ) {
+ return null;
+ }
+
+ pos += matches[0].length;
+
+ return matches[0];
+ };
+ }
+
+ pipe = makeStringParser( '|' );
+ colon = makeStringParser( ':' );
+ backslash = makeStringParser( '\\' );
+ anyCharacter = makeRegexParser( /^./ );
+ dollar = makeStringParser( '$' );
+ digits = makeRegexParser( /^\d+/ );
+ regularLiteral = makeRegexParser( /^[^{}\[\]$\\]/ );
+ regularLiteralWithoutBar = makeRegexParser( /^[^{}\[\]$\\|]/ );
+ regularLiteralWithoutSpace = makeRegexParser( /^[^{}\[\]$\s]/ );
+
+ // There is a general pattern:
+ // parse a thing;
+ // if it worked, apply transform,
+ // otherwise return null.
+ // But using this as a combinator seems to cause problems
+ // when combined with nOrMore().
+ // May be some scoping issue.
+ function transform( p, fn ) {
+ return function () {
+ var result = p();
+
+ return result === null ? null : fn( result );
+ };
+ }
+
+ // Used to define "literals" within template parameters. The pipe
+ // character is the parameter delimeter, so by default
+ // it is not a literal in the parameter
+ function literalWithoutBar() {
+ var result = nOrMore( 1, escapedOrLiteralWithoutBar )();
+
+ return result === null ? null : result.join( '' );
+ }
+
+ function literal() {
+ var result = nOrMore( 1, escapedOrRegularLiteral )();
+
+ return result === null ? null : result.join( '' );
+ }
+
+ function escapedLiteral() {
+ var result = sequence( [ backslash, anyCharacter ] );
+
+ return result === null ? null : result[1];
+ }
+
+ choice( [ escapedLiteral, regularLiteralWithoutSpace ] );
+ escapedOrLiteralWithoutBar = choice( [ escapedLiteral, regularLiteralWithoutBar ] );
+ escapedOrRegularLiteral = choice( [ escapedLiteral, regularLiteral ] );
+
+ function replacement() {
+ var result = sequence( [ dollar, digits ] );
+
+ if ( result === null ) {
+ return null;
+ }
+
+ return [ 'REPLACE', parseInt( result[1], 10 ) - 1 ];
+ }
+
+ templateName = transform(
+ // see $wgLegalTitleChars
+ // not allowing : due to the need to catch "PLURAL:$1"
+ makeRegexParser( /^[ !"$&'()*,.\/0-9;=?@A-Z\^_`a-z~\x80-\xFF+\-]+/ ),
+
+ function ( result ) {
+ return result.toString();
+ }
+ );
+
+ function templateParam() {
+ var expr,
+ result = sequence( [ pipe, nOrMore( 0, paramExpression ) ] );
+
+ if ( result === null ) {
+ return null;
+ }
+
+ expr = result[1];
+
+ // use a "CONCAT" operator if there are multiple nodes,
+ // otherwise return the first node, raw.
+ return expr.length > 1 ? [ 'CONCAT' ].concat( expr ) : expr[0];
+ }
+
+ function templateWithReplacement() {
+ var result = sequence( [ templateName, colon, replacement ] );
+
+ return result === null ? null : [ result[0], result[2] ];
+ }
+
+ function templateWithOutReplacement() {
+ var result = sequence( [ templateName, colon, paramExpression ] );
+
+ return result === null ? null : [ result[0], result[2] ];
+ }
+
+ templateContents = choice( [
+ function () {
+ var res = sequence( [
+ // templates can have placeholders for dynamic
+ // replacement eg: {{PLURAL:$1|one car|$1 cars}}
+ // or no placeholders eg:
+ // {{GRAMMAR:genitive|{{SITENAME}}}
+ choice( [ templateWithReplacement, templateWithOutReplacement ] ),
+ nOrMore( 0, templateParam )
+ ] );
+
+ return res === null ? null : res[0].concat( res[1] );
+ },
+ function () {
+ var res = sequence( [ templateName, nOrMore( 0, templateParam ) ] );
+
+ if ( res === null ) {
+ return null;
+ }
+
+ return [ res[0] ].concat( res[1] );
+ }
+ ] );
+
+ openTemplate = makeStringParser( '{{' );
+ closeTemplate = makeStringParser( '}}' );
+
+ function template() {
+ var result = sequence( [ openTemplate, templateContents, closeTemplate ] );
+
+ return result === null ? null : result[1];
+ }
+
+ expression = choice( [ template, replacement, literal ] );
+ paramExpression = choice( [ template, replacement, literalWithoutBar ] );
+
+ function start() {
+ var result = nOrMore( 0, expression )();
+
+ if ( result === null ) {
+ return null;
+ }
+
+ return [ 'CONCAT' ].concat( result );
+ }
+
+ result = start();
+
+ /*
+ * For success, the pos must have gotten to the end of the input
+ * and returned a non-null.
+ * n.b. This is part of language infrastructure, so we do not throw an internationalizable message.
+ */
+ if ( result === null || pos !== message.length ) {
+ throw new Error( 'Parse error at position ' + pos.toString() + ' in input: ' + message );
+ }
+
+ return result;
+ }
+
+ };
+
+ $.extend( $.i18n.parser, new MessageParser() );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/bs.js b/www/wiki/resources/lib/jquery.i18n/src/languages/bs.js
new file mode 100644
index 00000000..5370069e
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/bs.js
@@ -0,0 +1,22 @@
+/**
+ * Bosnian (bosanski) language functions
+ */
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.bs = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ switch ( form ) {
+ case 'instrumental': // instrumental
+ word = 's ' + word;
+ break;
+ case 'lokativ': // locative
+ word = 'o ' + word;
+ break;
+ }
+
+ return word;
+ }
+ } );
+
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/dsb.js b/www/wiki/resources/lib/jquery.i18n/src/languages/dsb.js
new file mode 100644
index 00000000..cc069ebf
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/dsb.js
@@ -0,0 +1,22 @@
+/**
+ * Lower Sorbian (Dolnoserbski) language functions
+ */
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.dsb = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ switch ( form ) {
+ case 'instrumental': // instrumental
+ word = 'z ' + word;
+ break;
+ case 'lokatiw': // lokatiw
+ word = 'wo ' + word;
+ break;
+ }
+
+ return word;
+ }
+ } );
+
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/fi.js b/www/wiki/resources/lib/jquery.i18n/src/languages/fi.js
new file mode 100644
index 00000000..d8e9578a
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/fi.js
@@ -0,0 +1,49 @@
+/**
+ * Finnish (Suomi) language functions
+ *
+ * @author Santhosh Thottingal
+ */
+
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.fi = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ // vowel harmony flag
+ var aou = word.match( /[aou][^äöy]*$/i ),
+ origWord = word;
+ if ( word.match( /wiki$/i ) ) {
+ aou = false;
+ }
+
+ // append i after final consonant
+ if ( word.match( /[bcdfghjklmnpqrstvwxz]$/i ) ) {
+ word += 'i';
+ }
+
+ switch ( form ) {
+ case 'genitive':
+ word += 'n';
+ break;
+ case 'elative':
+ word += ( aou ? 'sta' : 'stä' );
+ break;
+ case 'partitive':
+ word += ( aou ? 'a' : 'ä' );
+ break;
+ case 'illative':
+ // Double the last letter and add 'n'
+ word += word.substr( word.length - 1 ) + 'n';
+ break;
+ case 'inessive':
+ word += ( aou ? 'ssa' : 'ssä' );
+ break;
+ default:
+ word = origWord;
+ break;
+ }
+
+ return word;
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/ga.js b/www/wiki/resources/lib/jquery.i18n/src/languages/ga.js
new file mode 100644
index 00000000..1aceab75
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/ga.js
@@ -0,0 +1,38 @@
+/**
+ * Irish (Gaeilge) language functions
+ */
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.ga = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ if ( form === 'ainmlae' ) {
+ switch ( word ) {
+ case 'an Domhnach':
+ word = 'Dé Domhnaigh';
+ break;
+ case 'an Luan':
+ word = 'Dé Luain';
+ break;
+ case 'an Mháirt':
+ word = 'Dé Mháirt';
+ break;
+ case 'an Chéadaoin':
+ word = 'Dé Chéadaoin';
+ break;
+ case 'an Déardaoin':
+ word = 'Déardaoin';
+ break;
+ case 'an Aoine':
+ word = 'Dé hAoine';
+ break;
+ case 'an Satharn':
+ word = 'Dé Sathairn';
+ break;
+ }
+ }
+
+ return word;
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/he.js b/www/wiki/resources/lib/jquery.i18n/src/languages/he.js
new file mode 100644
index 00000000..cbbe90b9
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/he.js
@@ -0,0 +1,31 @@
+/**
+ * Hebrew (עברית) language functions
+ */
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.he = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ switch ( form ) {
+ case 'prefixed':
+ case 'תחילית': // the same word in Hebrew
+ // Duplicate prefixed "Waw", but only if it's not already double
+ if ( word.substr( 0, 1 ) === 'ו' && word.substr( 0, 2 ) !== 'וו' ) {
+ word = 'ו' + word;
+ }
+
+ // Remove the "He" if prefixed
+ if ( word.substr( 0, 1 ) === 'ה' ) {
+ word = word.substr( 1, word.length );
+ }
+
+ // Add a hyphen (maqaf) before numbers and non-Hebrew letters
+ if ( word.substr( 0, 1 ) < 'א' || word.substr( 0, 1 ) > 'ת' ) {
+ word = '־' + word;
+ }
+ }
+
+ return word;
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/hsb.js b/www/wiki/resources/lib/jquery.i18n/src/languages/hsb.js
new file mode 100644
index 00000000..957616f6
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/hsb.js
@@ -0,0 +1,21 @@
+/**
+ * Upper Sorbian (Hornjoserbsce) language functions
+ */
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.hsb = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ switch ( form ) {
+ case 'instrumental': // instrumental
+ word = 'z ' + word;
+ break;
+ case 'lokatiw': // lokatiw
+ word = 'wo ' + word;
+ break;
+ }
+
+ return word;
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/hu.js b/www/wiki/resources/lib/jquery.i18n/src/languages/hu.js
new file mode 100644
index 00000000..1177b850
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/hu.js
@@ -0,0 +1,26 @@
+/**
+ * Hungarian language functions
+ *
+ * @author Santhosh Thottingal
+ */
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.hu = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ switch ( form ) {
+ case 'rol':
+ word += 'ról';
+ break;
+ case 'ba':
+ word += 'ba';
+ break;
+ case 'k':
+ word += 'k';
+ break;
+ }
+
+ return word;
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/hy.js b/www/wiki/resources/lib/jquery.i18n/src/languages/hy.js
new file mode 100644
index 00000000..9c568992
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/hy.js
@@ -0,0 +1,25 @@
+/**
+ * Armenian (Հայերեն) language functions
+ */
+
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.hy = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ if ( form === 'genitive' ) { // սեռական հոլով
+ if ( word.substr( -1 ) === 'ա' ) {
+ word = word.substr( 0, word.length - 1 ) + 'այի';
+ } else if ( word.substr( -1 ) === 'ո' ) {
+ word = word.substr( 0, word.length - 1 ) + 'ոյի';
+ } else if ( word.substr( -4 ) === 'գիրք' ) {
+ word = word.substr( 0, word.length - 4 ) + 'գրքի';
+ } else {
+ word = word + 'ի';
+ }
+ }
+
+ return word;
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/la.js b/www/wiki/resources/lib/jquery.i18n/src/languages/la.js
new file mode 100644
index 00000000..11c1122d
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/la.js
@@ -0,0 +1,54 @@
+/**
+ * Latin (lingua Latina) language functions
+ *
+ * @author Santhosh Thottingal
+ */
+
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.la = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ switch ( form ) {
+ case 'genitive':
+ // only a few declensions, and even for those mostly the singular only
+ word = word.replace( /u[ms]$/i, 'i' ); // 2nd declension singular
+ word = word.replace( /ommunia$/i, 'ommunium' ); // 3rd declension neuter plural (partly)
+ word = word.replace( /a$/i, 'ae' ); // 1st declension singular
+ word = word.replace( /libri$/i, 'librorum' ); // 2nd declension plural (partly)
+ word = word.replace( /nuntii$/i, 'nuntiorum' ); // 2nd declension plural (partly)
+ word = word.replace( /tio$/i, 'tionis' ); // 3rd declension singular (partly)
+ word = word.replace( /ns$/i, 'ntis' );
+ word = word.replace( /as$/i, 'atis' );
+ word = word.replace( /es$/i, 'ei' ); // 5th declension singular
+ break;
+ case 'accusative':
+ // only a few declensions, and even for those mostly the singular only
+ word = word.replace( /u[ms]$/i, 'um' ); // 2nd declension singular
+ word = word.replace( /ommunia$/i, 'am' ); // 3rd declension neuter plural (partly)
+ word = word.replace( /a$/i, 'ommunia' ); // 1st declension singular
+ word = word.replace( /libri$/i, 'libros' ); // 2nd declension plural (partly)
+ word = word.replace( /nuntii$/i, 'nuntios' );// 2nd declension plural (partly)
+ word = word.replace( /tio$/i, 'tionem' ); // 3rd declension singular (partly)
+ word = word.replace( /ns$/i, 'ntem' );
+ word = word.replace( /as$/i, 'atem' );
+ word = word.replace( /es$/i, 'em' ); // 5th declension singular
+ break;
+ case 'ablative':
+ // only a few declensions, and even for those mostly the singular only
+ word = word.replace( /u[ms]$/i, 'o' ); // 2nd declension singular
+ word = word.replace( /ommunia$/i, 'ommunibus' ); // 3rd declension neuter plural (partly)
+ word = word.replace( /a$/i, 'a' ); // 1st declension singular
+ word = word.replace( /libri$/i, 'libris' ); // 2nd declension plural (partly)
+ word = word.replace( /nuntii$/i, 'nuntiis' ); // 2nd declension plural (partly)
+ word = word.replace( /tio$/i, 'tione' ); // 3rd declension singular (partly)
+ word = word.replace( /ns$/i, 'nte' );
+ word = word.replace( /as$/i, 'ate' );
+ word = word.replace( /es$/i, 'e' ); // 5th declension singular
+ break;
+ }
+
+ return word;
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/ml.js b/www/wiki/resources/lib/jquery.i18n/src/languages/ml.js
new file mode 100644
index 00000000..f724b7b2
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/ml.js
@@ -0,0 +1,98 @@
+/**
+ * Malayalam language functions
+ *
+ * @author Santhosh Thottingal
+ */
+
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.ml = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ form = form.toLowerCase();
+ switch ( form ) {
+ case 'ഉദ്ദേശിക':
+ case 'dative':
+ if ( word.substr( -1 ) === 'ു' ||
+ word.substr( -1 ) === 'ൂ' ||
+ word.substr( -1 ) === 'ൗ' ||
+ word.substr( -1 ) === 'ൌ'
+ ) {
+ word += 'വിന്';
+ } else if ( word.substr( -1 ) === 'ം' ) {
+ word = word.substr( 0, word.length - 1 ) + 'ത്തിന്';
+ } else if ( word.substr( -1 ) === 'ൻ' ) {
+ // Atomic chillu n. അവൻ -> അവന്
+ word = word.substr( 0, word.length - 1 ) + 'ന്';
+ } else if ( word.substr( -3 ) === 'ന്\u200d' ) {
+ // chillu n. അവൻ -> അവന്
+ word = word.substr( 0, word.length - 1 );
+ } else if ( word.substr( -1 ) === 'ൾ' || word.substr( -3 ) === 'ള്\u200d' ) {
+ word += 'ക്ക്';
+ } else if ( word.substr( -1 ) === 'ർ' || word.substr( -3 ) === 'ര്\u200d' ) {
+ word += 'ക്ക്';
+ } else if ( word.substr( -1 ) === 'ൽ' ) {
+ // Atomic chillu ൽ , ഫയൽ -> ഫയലിന്
+ word = word.substr( 0, word.length - 1 ) + 'ലിന്';
+ } else if ( word.substr( -3 ) === 'ല്\u200d' ) {
+ // chillu ല്\u200d , ഫയല്\u200d -> ഫയലിന്
+ word = word.substr( 0, word.length - 2 ) + 'ിന്';
+ } else if ( word.substr( -2 ) === 'ു്' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ിന്';
+ } else if ( word.substr( -1 ) === '്' ) {
+ word = word.substr( 0, word.length - 1 ) + 'ിന്';
+ } else {
+ // കാവ്യ -> കാവ്യയ്ക്ക്, ഹരി -> ഹരിയ്ക്ക്, മല -> മലയ്ക്ക്
+ word += 'യ്ക്ക്';
+ }
+
+ break;
+ case 'സംബന്ധിക':
+ case 'genitive':
+ if ( word.substr( -1 ) === 'ം' ) {
+ word = word.substr( 0, word.length - 1 ) + 'ത്തിന്റെ';
+ } else if ( word.substr( -2 ) === 'ു്' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ിന്റെ';
+ } else if ( word.substr( -1 ) === '്' ) {
+ word = word.substr( 0, word.length - 1 ) + 'ിന്റെ';
+ } else if ( word.substr( -1 ) === 'ു' ||
+ word.substr( -1 ) === 'ൂ' ||
+ word.substr( -1 ) === 'ൗ' ||
+ word.substr( -1 ) === 'ൌ'
+ ) {
+ word += 'വിന്റെ';
+ } else if ( word.substr( -1 ) === 'ൻ' ) {
+ // Atomic chillu n. അവൻ -> അവന്റെ
+ word = word.substr( 0, word.length - 1 ) + 'ന്റെ';
+ } else if ( word.substr( -3 ) === 'ന്\u200d' ) {
+ // chillu n. അവൻ -> അവന്റെ
+ word = word.substr( 0, word.length - 1 ) + 'റെ';
+ } else if ( word.substr( -3 ) === 'ള്\u200d' ) {
+ // chillu n. അവൾ -> അവളുടെ
+ word = word.substr( 0, word.length - 2 ) + 'ുടെ';
+ } else if ( word.substr( -1 ) === 'ൾ' ) {
+ // Atomic chillu n. അവള്\u200d -> അവളുടെ
+ word = word.substr( 0, word.length - 1 ) + 'ളുടെ';
+ } else if ( word.substr( -1 ) === 'ൽ' ) {
+ // Atomic l. മുയല്\u200d -> മുയലിന്റെ
+ word = word.substr( 0, word.length - 1 ) + 'ലിന്റെ';
+ } else if ( word.substr( -3 ) === 'ല്\u200d' ) {
+ // chillu l. മുയല്\u200d -> അവളുടെ
+ word = word.substr( 0, word.length - 2 ) + 'ിന്റെ';
+ } else if ( word.substr( -3 ) === 'ര്\u200d' ) {
+ // chillu r. അവര്\u200d -> അവരുടെ
+ word = word.substr( 0, word.length - 2 ) + 'ുടെ';
+ } else if ( word.substr( -1 ) === 'ർ' ) {
+ // Atomic chillu r. അവർ -> അവരുടെ
+ word = word.substr( 0, word.length - 1 ) + 'രുടെ';
+ } else {
+ word += 'യുടെ';
+ }
+
+ break;
+ }
+
+ return word;
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/os.js b/www/wiki/resources/lib/jquery.i18n/src/languages/os.js
new file mode 100644
index 00000000..47443671
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/os.js
@@ -0,0 +1,76 @@
+/**
+ * Ossetian (Ирон) language functions
+ *
+ * @author Santhosh Thottingal
+ */
+
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.os = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ var endAllative, jot, hyphen, ending;
+
+ // Ending for allative case
+ endAllative = 'мæ';
+ // Variable for 'j' beetwen vowels
+ jot = '';
+ // Variable for "-" for not Ossetic words
+ hyphen = '';
+ // Variable for ending
+ ending = '';
+
+ if ( word.match( /тæ$/i ) ) {
+ // Checking if the $word is in plural form
+ word = word.substring( 0, word.length - 1 );
+ endAllative = 'æм';
+ } else if ( word.match( /[аæеёиоыэюя]$/i ) ) {
+ // Works if word is in singular form.
+ // Checking if word ends on one of the vowels: е, ё, и, о, ы, э, ю,
+ // я.
+ jot = 'й';
+ } else if ( word.match( /у$/i ) ) {
+ // Checking if word ends on 'у'. 'У' can be either consonant 'W' or
+ // vowel 'U' in cyrillic Ossetic.
+ // Examples: {{grammar:genitive|аунеу}} = аунеуы,
+ // {{grammar:genitive|лæппу}} = лæппуйы.
+ if ( !word.substring( word.length - 2, word.length - 1 )
+ .match( /[аæеёиоыэюя]$/i ) ) {
+ jot = 'й';
+ }
+ } else if ( !word.match( /[бвгджзйклмнопрстфхцчшщьъ]$/i ) ) {
+ hyphen = '-';
+ }
+
+ switch ( form ) {
+ case 'genitive':
+ ending = hyphen + jot + 'ы';
+ break;
+ case 'dative':
+ ending = hyphen + jot + 'æн';
+ break;
+ case 'allative':
+ ending = hyphen + endAllative;
+ break;
+ case 'ablative':
+ if ( jot === 'й' ) {
+ ending = hyphen + jot + 'æ';
+ } else {
+ ending = hyphen + jot + 'æй';
+ }
+ break;
+ case 'superessive':
+ ending = hyphen + jot + 'ыл';
+ break;
+ case 'equative':
+ ending = hyphen + jot + 'ау';
+ break;
+ case 'comitative':
+ ending = hyphen + 'имæ';
+ break;
+ }
+
+ return word + ending;
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/ru.js b/www/wiki/resources/lib/jquery.i18n/src/languages/ru.js
new file mode 100644
index 00000000..893b2386
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/ru.js
@@ -0,0 +1,29 @@
+/**
+ * Russian (Русский) language functions
+ */
+
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.ru = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ if ( form === 'genitive' ) { // родительный падеж
+ if ( word.substr( -1 ) === 'ь' ) {
+ word = word.substr( 0, word.length - 1 ) + 'я';
+ } else if ( word.substr( -2 ) === 'ия' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ии';
+ } else if ( word.substr( -2 ) === 'ка' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ки';
+ } else if ( word.substr( -2 ) === 'ти' ) {
+ word = word.substr( 0, word.length - 2 ) + 'тей';
+ } else if ( word.substr( -2 ) === 'ды' ) {
+ word = word.substr( 0, word.length - 2 ) + 'дов';
+ } else if ( word.substr( -3 ) === 'ник' ) {
+ word = word.substr( 0, word.length - 3 ) + 'ника';
+ }
+ }
+
+ return word;
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/sl.js b/www/wiki/resources/lib/jquery.i18n/src/languages/sl.js
new file mode 100644
index 00000000..a3aafc3b
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/sl.js
@@ -0,0 +1,26 @@
+/**
+ * Slovenian (Slovenščina) language functions
+ */
+
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.sl = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ switch ( form ) {
+ // locative
+ case 'mestnik':
+ word = 'o ' + word;
+
+ break;
+ // instrumental
+ case 'orodnik':
+ word = 'z ' + word;
+
+ break;
+ }
+
+ return word;
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.i18n/src/languages/uk.js b/www/wiki/resources/lib/jquery.i18n/src/languages/uk.js
new file mode 100644
index 00000000..8e69efcd
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.i18n/src/languages/uk.js
@@ -0,0 +1,39 @@
+/**
+ * Ukrainian (Українська) language functions
+ */
+
+( function ( $ ) {
+ 'use strict';
+
+ $.i18n.languages.uk = $.extend( {}, $.i18n.languages['default'], {
+ convertGrammar: function ( word, form ) {
+ switch ( form ) {
+ case 'genitive': // родовий відмінок
+ if ( word.substr( -1 ) === 'ь' ) {
+ word = word.substr( 0, word.length - 1 ) + 'я';
+ } else if ( word.substr( -2 ) === 'ія' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ії';
+ } else if ( word.substr( -2 ) === 'ка' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ки';
+ } else if ( word.substr( -2 ) === 'ти' ) {
+ word = word.substr( 0, word.length - 2 ) + 'тей';
+ } else if ( word.substr( -2 ) === 'ды' ) {
+ word = word.substr( 0, word.length - 2 ) + 'дов';
+ } else if ( word.substr( -3 ) === 'ник' ) {
+ word = word.substr( 0, word.length - 3 ) + 'ника';
+ }
+
+ break;
+ case 'accusative': // знахідний відмінок
+ if ( word.substr( -2 ) === 'ія' ) {
+ word = word.substr( 0, word.length - 2 ) + 'ію';
+ }
+
+ break;
+ }
+
+ return word;
+ }
+ } );
+
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.ui/PATCHES b/www/wiki/resources/lib/jquery.ui/PATCHES
new file mode 100644
index 00000000..bcff2ac3
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/PATCHES
@@ -0,0 +1,34 @@
+jquery.ui.core.js
+* I7ffbfd2e5 Avoid deprecated jQuery.expr[":"].
+
+
+jquery.ui.draggable.js
+* 71e11de2a3 Fix positioning error with draggable, revert and grid.
+ https://phabricator.wikimedia.org/T140965#2944610
+
+ https://bugs.jqueryui.com/ticket/4696
+
+
+jquery.ui.datepicker
+* 19531f3c23 Add translations in de-AT and de-CH
+
+
+jquery.ui.widget.js
+* I7ffbfd2e5 Avoid deprecated jQuery.expr[":"].
+
+
+themes/smoothness/jquery.ui.theme.css
+* 5e772e39dd Remove dark color from links inside dialogs
+ https://phabricator.wikimedia.org/T85857
+
+ Removed ".ui-widget-content a { color: #222222; }"
+ and ".ui-widget-header a { color: #222222; }"
+
+
+themes/smoothness/jquery.ui.core.css:
+* dc1c29f204 Collapse border in ui-helper-clearfix
+ https://phabricator.wikimedia.org/T73601
+
+ Backport of upstream change released in jQuery UI v1.10.1
+ - http://bugs.jqueryui.com/ticket/8442
+ - https://github.com/jquery/jquery-ui/commit/cb42ee7ccd
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-af.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-af.js
new file mode 100644
index 00000000..0922ef7a
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-af.js
@@ -0,0 +1,23 @@
+/* Afrikaans initialisation for the jQuery UI date picker plugin. */
+/* Written by Renier Pretorius. */
+jQuery(function($){
+ $.datepicker.regional['af'] = {
+ closeText: 'Selekteer',
+ prevText: 'Vorige',
+ nextText: 'Volgende',
+ currentText: 'Vandag',
+ monthNames: ['Januarie','Februarie','Maart','April','Mei','Junie',
+ 'Julie','Augustus','September','Oktober','November','Desember'],
+ monthNamesShort: ['Jan', 'Feb', 'Mrt', 'Apr', 'Mei', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Des'],
+ dayNames: ['Sondag', 'Maandag', 'Dinsdag', 'Woensdag', 'Donderdag', 'Vrydag', 'Saterdag'],
+ dayNamesShort: ['Son', 'Maa', 'Din', 'Woe', 'Don', 'Vry', 'Sat'],
+ dayNamesMin: ['So','Ma','Di','Wo','Do','Vr','Sa'],
+ weekHeader: 'Wk',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['af']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar-DZ.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar-DZ.js
new file mode 100644
index 00000000..7b175af4
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar-DZ.js
@@ -0,0 +1,23 @@
+/* Algerian Arabic Translation for jQuery UI date picker plugin. (can be used for Tunisia)*/
+/* Mohamed Cherif BOUCHELAGHEM -- cherifbouchelaghem@yahoo.fr */
+
+jQuery(function($){
+ $.datepicker.regional['ar-DZ'] = {
+ closeText: 'إغلاق',
+ prevText: '&#x3C;السابق',
+ nextText: 'التالي&#x3E;',
+ currentText: 'اليوم',
+ monthNames: ['جانفي', 'فيفري', 'مارس', 'أفريل', 'ماي', 'جوان',
+ 'جويلية', 'أوت', 'سبتمبر','أكتوبر', 'نوفمبر', 'ديسمبر'],
+ monthNamesShort: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
+ dayNames: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ dayNamesShort: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ dayNamesMin: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ weekHeader: 'أسبوع',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 6,
+ isRTL: true,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['ar-DZ']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar.js
new file mode 100644
index 00000000..cef0f08f
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ar.js
@@ -0,0 +1,23 @@
+/* Arabic Translation for jQuery UI date picker plugin. */
+/* Khaled Alhourani -- me@khaledalhourani.com */
+/* NOTE: monthNames are the original months names and they are the Arabic names, not the new months name فبراير - يناير and there isn't any Arabic roots for these months */
+jQuery(function($){
+ $.datepicker.regional['ar'] = {
+ closeText: 'إغلاق',
+ prevText: '&#x3C;السابق',
+ nextText: 'التالي&#x3E;',
+ currentText: 'اليوم',
+ monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'مايو', 'حزيران',
+ 'تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
+ monthNamesShort: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12'],
+ dayNames: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ dayNamesShort: ['الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة', 'السبت'],
+ dayNamesMin: ['ح', 'ن', 'ث', 'ر', 'خ', 'ج', 'س'],
+ weekHeader: 'أسبوع',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 6,
+ isRTL: true,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['ar']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-az.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-az.js
new file mode 100644
index 00000000..a133a9eb
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-az.js
@@ -0,0 +1,23 @@
+/* Azerbaijani (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Jamil Najafov (necefov33@gmail.com). */
+jQuery(function($) {
+ $.datepicker.regional['az'] = {
+ closeText: 'Bağla',
+ prevText: '&#x3C;Geri',
+ nextText: 'İrəli&#x3E;',
+ currentText: 'Bugün',
+ monthNames: ['Yanvar','Fevral','Mart','Aprel','May','İyun',
+ 'İyul','Avqust','Sentyabr','Oktyabr','Noyabr','Dekabr'],
+ monthNamesShort: ['Yan','Fev','Mar','Apr','May','İyun',
+ 'İyul','Avq','Sen','Okt','Noy','Dek'],
+ dayNames: ['Bazar','Bazar ertəsi','Çərşənbə axşamı','Çərşənbə','Cümə axşamı','Cümə','Şənbə'],
+ dayNamesShort: ['B','Be','Ça','Ç','Ca','C','Ş'],
+ dayNamesMin: ['B','B','Ç','С','Ç','C','Ş'],
+ weekHeader: 'Hf',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['az']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bg.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bg.js
new file mode 100644
index 00000000..86ab8858
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bg.js
@@ -0,0 +1,24 @@
+/* Bulgarian initialisation for the jQuery UI date picker plugin. */
+/* Written by Stoyan Kyosev (http://svest.org). */
+jQuery(function($){
+ $.datepicker.regional['bg'] = {
+ closeText: 'затвори',
+ prevText: '&#x3C;назад',
+ nextText: 'напред&#x3E;',
+ nextBigText: '&#x3E;&#x3E;',
+ currentText: 'днес',
+ monthNames: ['Януари','Февруари','Март','Април','Май','Юни',
+ 'Юли','Август','Септември','Октомври','Ноември','Декември'],
+ monthNamesShort: ['Яну','Фев','Мар','Апр','Май','Юни',
+ 'Юли','Авг','Сеп','Окт','Нов','Дек'],
+ dayNames: ['Неделя','Понеделник','Вторник','Сряда','Четвъртък','Петък','Събота'],
+ dayNamesShort: ['Нед','Пон','Вто','Сря','Чет','Пет','Съб'],
+ dayNamesMin: ['Не','По','Вт','Ср','Че','Пе','Съ'],
+ weekHeader: 'Wk',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['bg']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bs.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bs.js
new file mode 100644
index 00000000..f08870ff
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-bs.js
@@ -0,0 +1,23 @@
+/* Bosnian i18n for the jQuery UI date picker plugin. */
+/* Written by Kenan Konjo. */
+jQuery(function($){
+ $.datepicker.regional['bs'] = {
+ closeText: 'Zatvori',
+ prevText: '&#x3C;',
+ nextText: '&#x3E;',
+ currentText: 'Danas',
+ monthNames: ['Januar','Februar','Mart','April','Maj','Juni',
+ 'Juli','August','Septembar','Oktobar','Novembar','Decembar'],
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+ 'Jul','Aug','Sep','Okt','Nov','Dec'],
+ dayNames: ['Nedelja','Ponedeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],
+ dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],
+ dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
+ weekHeader: 'Wk',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['bs']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ca.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ca.js
new file mode 100644
index 00000000..a10b549c
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ca.js
@@ -0,0 +1,23 @@
+/* Inicialització en català per a l'extensió 'UI date picker' per jQuery. */
+/* Writers: (joan.leon@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['ca'] = {
+ closeText: 'Tanca',
+ prevText: 'Anterior',
+ nextText: 'Següent',
+ currentText: 'Avui',
+ monthNames: ['gener','febrer','març','abril','maig','juny',
+ 'juliol','agost','setembre','octubre','novembre','desembre'],
+ monthNamesShort: ['gen','feb','març','abr','maig','juny',
+ 'jul','ag','set','oct','nov','des'],
+ dayNames: ['diumenge','dilluns','dimarts','dimecres','dijous','divendres','dissabte'],
+ dayNamesShort: ['dg','dl','dt','dc','dj','dv','ds'],
+ dayNamesMin: ['dg','dl','dt','dc','dj','dv','ds'],
+ weekHeader: 'Set',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['ca']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cs.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cs.js
new file mode 100644
index 00000000..b96b1a51
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cs.js
@@ -0,0 +1,23 @@
+/* Czech initialisation for the jQuery UI date picker plugin. */
+/* Written by Tomas Muller (tomas@tomas-muller.net). */
+jQuery(function($){
+ $.datepicker.regional['cs'] = {
+ closeText: 'Zavřít',
+ prevText: '&#x3C;Dříve',
+ nextText: 'Později&#x3E;',
+ currentText: 'Nyní',
+ monthNames: ['leden','únor','březen','duben','květen','červen',
+ 'červenec','srpen','září','říjen','listopad','prosinec'],
+ monthNamesShort: ['led','úno','bře','dub','kvě','čer',
+ 'čvc','srp','zář','říj','lis','pro'],
+ dayNames: ['neděle', 'pondělí', 'úterý', 'středa', 'čtvrtek', 'pátek', 'sobota'],
+ dayNamesShort: ['ne', 'po', 'út', 'st', 'čt', 'pá', 'so'],
+ dayNamesMin: ['ne','po','út','st','čt','pá','so'],
+ weekHeader: 'Týd',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['cs']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cy-GB.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cy-GB.js
new file mode 100644
index 00000000..cf3a38e6
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-cy-GB.js
@@ -0,0 +1,23 @@
+/* Welsh/UK initialisation for the jQuery UI date picker plugin. */
+/* Written by William Griffiths. */
+jQuery(function($){
+ $.datepicker.regional['cy-GB'] = {
+ closeText: 'Done',
+ prevText: 'Prev',
+ nextText: 'Next',
+ currentText: 'Today',
+ monthNames: ['Ionawr','Chwefror','Mawrth','Ebrill','Mai','Mehefin',
+ 'Gorffennaf','Awst','Medi','Hydref','Tachwedd','Rhagfyr'],
+ monthNamesShort: ['Ion', 'Chw', 'Maw', 'Ebr', 'Mai', 'Meh',
+ 'Gor', 'Aws', 'Med', 'Hyd', 'Tac', 'Rha'],
+ dayNames: ['Dydd Sul', 'Dydd Llun', 'Dydd Mawrth', 'Dydd Mercher', 'Dydd Iau', 'Dydd Gwener', 'Dydd Sadwrn'],
+ dayNamesShort: ['Sul', 'Llu', 'Maw', 'Mer', 'Iau', 'Gwe', 'Sad'],
+ dayNamesMin: ['Su','Ll','Ma','Me','Ia','Gw','Sa'],
+ weekHeader: 'Wy',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['cy-GB']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-da.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-da.js
new file mode 100644
index 00000000..7e42948b
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-da.js
@@ -0,0 +1,23 @@
+/* Danish initialisation for the jQuery UI date picker plugin. */
+/* Written by Jan Christensen ( deletestuff@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['da'] = {
+ closeText: 'Luk',
+ prevText: '&#x3C;Forrige',
+ nextText: 'Næste&#x3E;',
+ currentText: 'Idag',
+ monthNames: ['Januar','Februar','Marts','April','Maj','Juni',
+ 'Juli','August','September','Oktober','November','December'],
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+ 'Jul','Aug','Sep','Okt','Nov','Dec'],
+ dayNames: ['Søndag','Mandag','Tirsdag','Onsdag','Torsdag','Fredag','Lørdag'],
+ dayNamesShort: ['Søn','Man','Tir','Ons','Tor','Fre','Lør'],
+ dayNamesMin: ['Sø','Ma','Ti','On','To','Fr','Lø'],
+ weekHeader: 'Uge',
+ dateFormat: 'dd-mm-yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['da']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-AT.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-AT.js
new file mode 100644
index 00000000..456c3a05
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-AT.js
@@ -0,0 +1,22 @@
+/* Austrian German initialisation for the jQuery UI date picker plugin. */
+jQuery(function($){
+ $.datepicker.regional['de-AT'] = {
+ closeText: 'schließen',
+ prevText: '&#x3C;zurück',
+ nextText: 'Vor&#x3E;',
+ currentText: 'heute',
+ monthNames: ['Jänner','Februar','März','April','Mai','Juni',
+ 'Juli','August','September','Oktober','November','Dezember'],
+ monthNamesShort: ['Jän','Feb','Mär','Apr','Mai','Jun',
+ 'Jul','Aug','Sep','Okt','Nov','Dez'],
+ dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
+ dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+ dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+ weekHeader: 'KW',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['de-AT']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-CH.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-CH.js
new file mode 100644
index 00000000..60cbc29f
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de-CH.js
@@ -0,0 +1,22 @@
+/* Swiss Standard German initialisation for the jQuery UI date picker plugin. */
+jQuery(function($){
+ $.datepicker.regional['de-CH'] = {
+ closeText: 'schliessen',
+ prevText: '&#x3C;zurück',
+ nextText: 'Vor&#x3E;',
+ currentText: 'heute',
+ monthNames: ['Januar','Februar','März','April','Mai','Juni',
+ 'Juli','August','September','Oktober','November','Dezember'],
+ monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun',
+ 'Jul','Aug','Sep','Okt','Nov','Dez'],
+ dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
+ dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+ dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+ weekHeader: 'KW',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['de-CH']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de.js
new file mode 100644
index 00000000..cfe91759
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-de.js
@@ -0,0 +1,23 @@
+/* German initialisation for the jQuery UI date picker plugin. */
+/* Written by Milian Wolff (mail@milianw.de). */
+jQuery(function($){
+ $.datepicker.regional['de'] = {
+ closeText: 'schließen',
+ prevText: '&#x3C;zurück',
+ nextText: 'Vor&#x3E;',
+ currentText: 'heute',
+ monthNames: ['Januar','Februar','März','April','Mai','Juni',
+ 'Juli','August','September','Oktober','November','Dezember'],
+ monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun',
+ 'Jul','Aug','Sep','Okt','Nov','Dez'],
+ dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
+ dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+ dayNamesMin: ['So','Mo','Di','Mi','Do','Fr','Sa'],
+ weekHeader: 'KW',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['de']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-el.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-el.js
new file mode 100644
index 00000000..1ac47561
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-el.js
@@ -0,0 +1,23 @@
+/* Greek (el) initialisation for the jQuery UI date picker plugin. */
+/* Written by Alex Cicovic (http://www.alexcicovic.com) */
+jQuery(function($){
+ $.datepicker.regional['el'] = {
+ closeText: 'Κλείσιμο',
+ prevText: 'Προηγούμενος',
+ nextText: 'Επόμενος',
+ currentText: 'Τρέχων Μήνας',
+ monthNames: ['Ιανουάριος','Φεβρουάριος','Μάρτιος','Απρίλιος','Μάιος','Ιούνιος',
+ 'Ιούλιος','Αύγουστος','Σεπτέμβριος','Οκτώβριος','Νοέμβριος','Δεκέμβριος'],
+ monthNamesShort: ['Ιαν','Φεβ','Μαρ','Απρ','Μαι','Ιουν',
+ 'Ιουλ','Αυγ','Σεπ','Οκτ','Νοε','Δεκ'],
+ dayNames: ['Κυριακή','Δευτέρα','Τρίτη','Τετάρτη','Πέμπτη','Παρασκευή','Σάββατο'],
+ dayNamesShort: ['Κυρ','Δευ','Τρι','Τετ','Πεμ','Παρ','Σαβ'],
+ dayNamesMin: ['Κυ','Δε','Τρ','Τε','Πε','Πα','Σα'],
+ weekHeader: 'Εβδ',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['el']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-AU.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-AU.js
new file mode 100644
index 00000000..c1a1020a
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-AU.js
@@ -0,0 +1,23 @@
+/* English/Australia initialisation for the jQuery UI date picker plugin. */
+/* Based on the en-GB initialisation. */
+jQuery(function($){
+ $.datepicker.regional['en-AU'] = {
+ closeText: 'Done',
+ prevText: 'Prev',
+ nextText: 'Next',
+ currentText: 'Today',
+ monthNames: ['January','February','March','April','May','June',
+ 'July','August','September','October','November','December'],
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'],
+ weekHeader: 'Wk',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['en-AU']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js
new file mode 100644
index 00000000..16a096e7
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-GB.js
@@ -0,0 +1,23 @@
+/* English/UK initialisation for the jQuery UI date picker plugin. */
+/* Written by Stuart. */
+jQuery(function($){
+ $.datepicker.regional['en-GB'] = {
+ closeText: 'Done',
+ prevText: 'Prev',
+ nextText: 'Next',
+ currentText: 'Today',
+ monthNames: ['January','February','March','April','May','June',
+ 'July','August','September','October','November','December'],
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'],
+ weekHeader: 'Wk',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['en-GB']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-NZ.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-NZ.js
new file mode 100644
index 00000000..7819df05
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-en-NZ.js
@@ -0,0 +1,23 @@
+/* English/New Zealand initialisation for the jQuery UI date picker plugin. */
+/* Based on the en-GB initialisation. */
+jQuery(function($){
+ $.datepicker.regional['en-NZ'] = {
+ closeText: 'Done',
+ prevText: 'Prev',
+ nextText: 'Next',
+ currentText: 'Today',
+ monthNames: ['January','February','March','April','May','June',
+ 'July','August','September','October','November','December'],
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'],
+ weekHeader: 'Wk',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['en-NZ']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eo.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eo.js
new file mode 100644
index 00000000..39e44fc5
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eo.js
@@ -0,0 +1,23 @@
+/* Esperanto initialisation for the jQuery UI date picker plugin. */
+/* Written by Olivier M. (olivierweb@ifrance.com). */
+jQuery(function($){
+ $.datepicker.regional['eo'] = {
+ closeText: 'Fermi',
+ prevText: '&#x3C;Anta',
+ nextText: 'Sekv&#x3E;',
+ currentText: 'Nuna',
+ monthNames: ['Januaro','Februaro','Marto','Aprilo','Majo','Junio',
+ 'Julio','Aŭgusto','Septembro','Oktobro','Novembro','Decembro'],
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+ 'Jul','Aŭg','Sep','Okt','Nov','Dec'],
+ dayNames: ['Dimanĉo','Lundo','Mardo','Merkredo','Ĵaŭdo','Vendredo','Sabato'],
+ dayNamesShort: ['Dim','Lun','Mar','Mer','Ĵaŭ','Ven','Sab'],
+ dayNamesMin: ['Di','Lu','Ma','Me','Ĵa','Ve','Sa'],
+ weekHeader: 'Sb',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 0,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['eo']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-es.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-es.js
new file mode 100644
index 00000000..97a2d6ea
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-es.js
@@ -0,0 +1,23 @@
+/* Inicialización en español para la extensión 'UI date picker' para jQuery. */
+/* Traducido por Vester (xvester@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['es'] = {
+ closeText: 'Cerrar',
+ prevText: '&#x3C;Ant',
+ nextText: 'Sig&#x3E;',
+ currentText: 'Hoy',
+ monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio',
+ 'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
+ monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun',
+ 'Jul','Ago','Sep','Oct','Nov','Dic'],
+ dayNames: ['Domingo','Lunes','Martes','Miércoles','Jueves','Viernes','Sábado'],
+ dayNamesShort: ['Dom','Lun','Mar','Mié','Juv','Vie','Sáb'],
+ dayNamesMin: ['Do','Lu','Ma','Mi','Ju','Vi','Sá'],
+ weekHeader: 'Sm',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['es']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-et.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-et.js
new file mode 100644
index 00000000..62cbea8f
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-et.js
@@ -0,0 +1,23 @@
+/* Estonian initialisation for the jQuery UI date picker plugin. */
+/* Written by Mart Sõmermaa (mrts.pydev at gmail com). */
+jQuery(function($){
+ $.datepicker.regional['et'] = {
+ closeText: 'Sulge',
+ prevText: 'Eelnev',
+ nextText: 'Järgnev',
+ currentText: 'Täna',
+ monthNames: ['Jaanuar','Veebruar','Märts','Aprill','Mai','Juuni',
+ 'Juuli','August','September','Oktoober','November','Detsember'],
+ monthNamesShort: ['Jaan', 'Veebr', 'Märts', 'Apr', 'Mai', 'Juuni',
+ 'Juuli', 'Aug', 'Sept', 'Okt', 'Nov', 'Dets'],
+ dayNames: ['Pühapäev', 'Esmaspäev', 'Teisipäev', 'Kolmapäev', 'Neljapäev', 'Reede', 'Laupäev'],
+ dayNamesShort: ['Pühap', 'Esmasp', 'Teisip', 'Kolmap', 'Neljap', 'Reede', 'Laup'],
+ dayNamesMin: ['P','E','T','K','N','R','L'],
+ weekHeader: 'näd',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['et']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eu.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eu.js
new file mode 100644
index 00000000..a71db2c7
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-eu.js
@@ -0,0 +1,23 @@
+/* Euskarako oinarria 'UI date picker' jquery-ko extentsioarentzat */
+/* Karrikas-ek itzulia (karrikas@karrikas.com) */
+jQuery(function($){
+ $.datepicker.regional['eu'] = {
+ closeText: 'Egina',
+ prevText: '&#x3C;Aur',
+ nextText: 'Hur&#x3E;',
+ currentText: 'Gaur',
+ monthNames: ['urtarrila','otsaila','martxoa','apirila','maiatza','ekaina',
+ 'uztaila','abuztua','iraila','urria','azaroa','abendua'],
+ monthNamesShort: ['urt.','ots.','mar.','api.','mai.','eka.',
+ 'uzt.','abu.','ira.','urr.','aza.','abe.'],
+ dayNames: ['igandea','astelehena','asteartea','asteazkena','osteguna','ostirala','larunbata'],
+ dayNamesShort: ['ig.','al.','ar.','az.','og.','ol.','lr.'],
+ dayNamesMin: ['ig','al','ar','az','og','ol','lr'],
+ weekHeader: 'As',
+ dateFormat: 'yy-mm-dd',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['eu']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fa.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fa.js
new file mode 100644
index 00000000..bb957f6d
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fa.js
@@ -0,0 +1,59 @@
+/* Persian (Farsi) Translation for the jQuery UI date picker plugin. */
+/* Javad Mowlanezhad -- jmowla@gmail.com */
+/* Jalali calendar should supported soon! (Its implemented but I have to test it) */
+jQuery(function($) {
+ $.datepicker.regional['fa'] = {
+ closeText: 'بستن',
+ prevText: '&#x3C;قبلی',
+ nextText: 'بعدی&#x3E;',
+ currentText: 'امروز',
+ monthNames: [
+ 'فروردين',
+ 'ارديبهشت',
+ 'خرداد',
+ 'تير',
+ 'مرداد',
+ 'شهريور',
+ 'مهر',
+ 'آبان',
+ 'آذر',
+ 'دی',
+ 'بهمن',
+ 'اسفند'
+ ],
+ monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],
+ dayNames: [
+ 'يکشنبه',
+ 'دوشنبه',
+ 'سه‌شنبه',
+ 'چهارشنبه',
+ 'پنجشنبه',
+ 'جمعه',
+ 'شنبه'
+ ],
+ dayNamesShort: [
+ 'ی',
+ 'د',
+ 'س',
+ 'چ',
+ 'پ',
+ 'ج',
+ 'ش'
+ ],
+ dayNamesMin: [
+ 'ی',
+ 'د',
+ 'س',
+ 'چ',
+ 'پ',
+ 'ج',
+ 'ش'
+ ],
+ weekHeader: 'هف',
+ dateFormat: 'yy/mm/dd',
+ firstDay: 6,
+ isRTL: true,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['fa']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fi.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fi.js
new file mode 100644
index 00000000..bd6d9949
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fi.js
@@ -0,0 +1,23 @@
+/* Finnish initialisation for the jQuery UI date picker plugin. */
+/* Written by Harri Kilpiö (harrikilpio@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['fi'] = {
+ closeText: 'Sulje',
+ prevText: '&#xAB;Edellinen',
+ nextText: 'Seuraava&#xBB;',
+ currentText: 'Tänään',
+ monthNames: ['Tammikuu','Helmikuu','Maaliskuu','Huhtikuu','Toukokuu','Kesäkuu',
+ 'Heinäkuu','Elokuu','Syyskuu','Lokakuu','Marraskuu','Joulukuu'],
+ monthNamesShort: ['Tammi','Helmi','Maalis','Huhti','Touko','Kesä',
+ 'Heinä','Elo','Syys','Loka','Marras','Joulu'],
+ dayNamesShort: ['Su','Ma','Ti','Ke','To','Pe','La'],
+ dayNames: ['Sunnuntai','Maanantai','Tiistai','Keskiviikko','Torstai','Perjantai','Lauantai'],
+ dayNamesMin: ['Su','Ma','Ti','Ke','To','Pe','La'],
+ weekHeader: 'Vk',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['fi']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fo.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fo.js
new file mode 100644
index 00000000..cb0e3def
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fo.js
@@ -0,0 +1,23 @@
+/* Faroese initialisation for the jQuery UI date picker plugin */
+/* Written by Sverri Mohr Olsen, sverrimo@gmail.com */
+jQuery(function($){
+ $.datepicker.regional['fo'] = {
+ closeText: 'Lat aftur',
+ prevText: '&#x3C;Fyrra',
+ nextText: 'Næsta&#x3E;',
+ currentText: 'Í dag',
+ monthNames: ['Januar','Februar','Mars','Apríl','Mei','Juni',
+ 'Juli','August','September','Oktober','November','Desember'],
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',
+ 'Jul','Aug','Sep','Okt','Nov','Des'],
+ dayNames: ['Sunnudagur','Mánadagur','Týsdagur','Mikudagur','Hósdagur','Fríggjadagur','Leyardagur'],
+ dayNamesShort: ['Sun','Mán','Týs','Mik','Hós','Frí','Ley'],
+ dayNamesMin: ['Su','Má','Tý','Mi','Hó','Fr','Le'],
+ weekHeader: 'Vk',
+ dateFormat: 'dd-mm-yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['fo']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr-CH.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr-CH.js
new file mode 100644
index 00000000..e574537b
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr-CH.js
@@ -0,0 +1,23 @@
+/* Swiss-French initialisation for the jQuery UI date picker plugin. */
+/* Written Martin Voelkle (martin.voelkle@e-tc.ch). */
+jQuery(function($){
+ $.datepicker.regional['fr-CH'] = {
+ closeText: 'Fermer',
+ prevText: '&#x3C;Préc',
+ nextText: 'Suiv&#x3E;',
+ currentText: 'Courant',
+ monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',
+ 'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
+ monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun',
+ 'Jul','Aoû','Sep','Oct','Nov','Déc'],
+ dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
+ dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
+ dayNamesMin: ['Di','Lu','Ma','Me','Je','Ve','Sa'],
+ weekHeader: 'Sm',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['fr-CH']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr.js
new file mode 100644
index 00000000..934afd1d
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-fr.js
@@ -0,0 +1,25 @@
+/* French initialisation for the jQuery UI date picker plugin. */
+/* Written by Keith Wood (kbwood{at}iinet.com.au),
+ Stéphane Nahmani (sholby@sholby.net),
+ Stéphane Raimbault <stephane.raimbault@gmail.com> */
+jQuery(function($){
+ $.datepicker.regional['fr'] = {
+ closeText: 'Fermer',
+ prevText: 'Précédent',
+ nextText: 'Suivant',
+ currentText: 'Aujourd\'hui',
+ monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin',
+ 'Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
+ monthNamesShort: ['Janv.','Févr.','Mars','Avril','Mai','Juin',
+ 'Juil.','Août','Sept.','Oct.','Nov.','Déc.'],
+ dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
+ dayNamesShort: ['Dim.','Lun.','Mar.','Mer.','Jeu.','Ven.','Sam.'],
+ dayNamesMin: ['D','L','M','M','J','V','S'],
+ weekHeader: 'Sem.',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['fr']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-gl.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-gl.js
new file mode 100644
index 00000000..59b989a6
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-gl.js
@@ -0,0 +1,23 @@
+/* Galician localization for 'UI date picker' jQuery extension. */
+/* Translated by Jorge Barreiro <yortx.barry@gmail.com>. */
+jQuery(function($){
+ $.datepicker.regional['gl'] = {
+ closeText: 'Pechar',
+ prevText: '&#x3C;Ant',
+ nextText: 'Seg&#x3E;',
+ currentText: 'Hoxe',
+ monthNames: ['Xaneiro','Febreiro','Marzo','Abril','Maio','Xuño',
+ 'Xullo','Agosto','Setembro','Outubro','Novembro','Decembro'],
+ monthNamesShort: ['Xan','Feb','Mar','Abr','Mai','Xuñ',
+ 'Xul','Ago','Set','Out','Nov','Dec'],
+ dayNames: ['Domingo','Luns','Martes','Mércores','Xoves','Venres','Sábado'],
+ dayNamesShort: ['Dom','Lun','Mar','Mér','Xov','Ven','Sáb'],
+ dayNamesMin: ['Do','Lu','Ma','Mé','Xo','Ve','Sá'],
+ weekHeader: 'Sm',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['gl']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-he.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-he.js
new file mode 100644
index 00000000..b9e8deec
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-he.js
@@ -0,0 +1,23 @@
+/* Hebrew initialisation for the UI Datepicker extension. */
+/* Written by Amir Hardon (ahardon at gmail dot com). */
+jQuery(function($){
+ $.datepicker.regional['he'] = {
+ closeText: 'סגור',
+ prevText: '&#x3C;הקודם',
+ nextText: 'הבא&#x3E;',
+ currentText: 'היום',
+ monthNames: ['ינואר','פברואר','מרץ','אפריל','מאי','יוני',
+ 'יולי','אוגוסט','ספטמבר','אוקטובר','נובמבר','דצמבר'],
+ monthNamesShort: ['ינו','פבר','מרץ','אפר','מאי','יוני',
+ 'יולי','אוג','ספט','אוק','נוב','דצמ'],
+ dayNames: ['ראשון','שני','שלישי','רביעי','חמישי','שישי','שבת'],
+ dayNamesShort: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
+ dayNamesMin: ['א\'','ב\'','ג\'','ד\'','ה\'','ו\'','שבת'],
+ weekHeader: 'Wk',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 0,
+ isRTL: true,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['he']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hi.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hi.js
new file mode 100644
index 00000000..6c563b99
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hi.js
@@ -0,0 +1,23 @@
+/* Hindi initialisation for the jQuery UI date picker plugin. */
+/* Written by Michael Dawart. */
+jQuery(function($){
+ $.datepicker.regional['hi'] = {
+ closeText: 'बंद',
+ prevText: 'पिछला',
+ nextText: 'अगला',
+ currentText: 'आज',
+ monthNames: ['जनवरी ','फरवरी','मार्च','अप्रेल','मई','जून',
+ 'जूलाई','अगस्त ','सितम्बर','अक्टूबर','नवम्बर','दिसम्बर'],
+ monthNamesShort: ['जन', 'फर', 'मार्च', 'अप्रेल', 'मई', 'जून',
+ 'जूलाई', 'अग', 'सित', 'अक्ट', 'नव', 'दि'],
+ dayNames: ['रविवार', 'सोमवार', 'मंगलवार', 'बुधवार', 'गुरुवार', 'शुक्रवार', 'शनिवार'],
+ dayNamesShort: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
+ dayNamesMin: ['रवि', 'सोम', 'मंगल', 'बुध', 'गुरु', 'शुक्र', 'शनि'],
+ weekHeader: 'हफ्ता',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['hi']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hr.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hr.js
new file mode 100644
index 00000000..2fe37b64
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hr.js
@@ -0,0 +1,23 @@
+/* Croatian i18n for the jQuery UI date picker plugin. */
+/* Written by Vjekoslav Nesek. */
+jQuery(function($){
+ $.datepicker.regional['hr'] = {
+ closeText: 'Zatvori',
+ prevText: '&#x3C;',
+ nextText: '&#x3E;',
+ currentText: 'Danas',
+ monthNames: ['Siječanj','Veljača','Ožujak','Travanj','Svibanj','Lipanj',
+ 'Srpanj','Kolovoz','Rujan','Listopad','Studeni','Prosinac'],
+ monthNamesShort: ['Sij','Velj','Ožu','Tra','Svi','Lip',
+ 'Srp','Kol','Ruj','Lis','Stu','Pro'],
+ dayNames: ['Nedjelja','Ponedjeljak','Utorak','Srijeda','Četvrtak','Petak','Subota'],
+ dayNamesShort: ['Ned','Pon','Uto','Sri','Čet','Pet','Sub'],
+ dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
+ weekHeader: 'Tje',
+ dateFormat: 'dd.mm.yy.',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['hr']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hu.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hu.js
new file mode 100644
index 00000000..b28c268c
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hu.js
@@ -0,0 +1,23 @@
+/* Hungarian initialisation for the jQuery UI date picker plugin. */
+/* Written by Istvan Karaszi (jquery@spam.raszi.hu). */
+jQuery(function($){
+ $.datepicker.regional['hu'] = {
+ closeText: 'bezár',
+ prevText: 'vissza',
+ nextText: 'előre',
+ currentText: 'ma',
+ monthNames: ['Január', 'Február', 'Március', 'Április', 'Május', 'Június',
+ 'Július', 'Augusztus', 'Szeptember', 'Október', 'November', 'December'],
+ monthNamesShort: ['Jan', 'Feb', 'Már', 'Ápr', 'Máj', 'Jún',
+ 'Júl', 'Aug', 'Szep', 'Okt', 'Nov', 'Dec'],
+ dayNames: ['Vasárnap', 'Hétfő', 'Kedd', 'Szerda', 'Csütörtök', 'Péntek', 'Szombat'],
+ dayNamesShort: ['Vas', 'Hét', 'Ked', 'Sze', 'Csü', 'Pén', 'Szo'],
+ dayNamesMin: ['V', 'H', 'K', 'Sze', 'Cs', 'P', 'Szo'],
+ weekHeader: 'Hét',
+ dateFormat: 'yy.mm.dd.',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: true,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['hu']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hy.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hy.js
new file mode 100644
index 00000000..6d4eca55
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-hy.js
@@ -0,0 +1,23 @@
+/* Armenian(UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Levon Zakaryan (levon.zakaryan@gmail.com)*/
+jQuery(function($){
+ $.datepicker.regional['hy'] = {
+ closeText: 'Փակել',
+ prevText: '&#x3C;Նախ.',
+ nextText: 'Հաջ.&#x3E;',
+ currentText: 'Այսօր',
+ monthNames: ['Հունվար','Փետրվար','Մարտ','Ապրիլ','Մայիս','Հունիս',
+ 'Հուլիս','Օգոստոս','Սեպտեմբեր','Հոկտեմբեր','Նոյեմբեր','Դեկտեմբեր'],
+ monthNamesShort: ['Հունվ','Փետր','Մարտ','Ապր','Մայիս','Հունիս',
+ 'Հուլ','Օգս','Սեպ','Հոկ','Նոյ','Դեկ'],
+ dayNames: ['կիրակի','եկուշաբթի','երեքշաբթի','չորեքշաբթի','հինգշաբթի','ուրբաթ','շաբաթ'],
+ dayNamesShort: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],
+ dayNamesMin: ['կիր','երկ','երք','չրք','հնգ','ուրբ','շբթ'],
+ weekHeader: 'ՇԲՏ',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['hy']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-id.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-id.js
new file mode 100644
index 00000000..6327fa60
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-id.js
@@ -0,0 +1,23 @@
+/* Indonesian initialisation for the jQuery UI date picker plugin. */
+/* Written by Deden Fathurahman (dedenf@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['id'] = {
+ closeText: 'Tutup',
+ prevText: '&#x3C;mundur',
+ nextText: 'maju&#x3E;',
+ currentText: 'hari ini',
+ monthNames: ['Januari','Februari','Maret','April','Mei','Juni',
+ 'Juli','Agustus','September','Oktober','Nopember','Desember'],
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun',
+ 'Jul','Agus','Sep','Okt','Nop','Des'],
+ dayNames: ['Minggu','Senin','Selasa','Rabu','Kamis','Jumat','Sabtu'],
+ dayNamesShort: ['Min','Sen','Sel','Rab','kam','Jum','Sab'],
+ dayNamesMin: ['Mg','Sn','Sl','Rb','Km','jm','Sb'],
+ weekHeader: 'Mg',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 0,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['id']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-is.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-is.js
new file mode 100644
index 00000000..925341a7
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-is.js
@@ -0,0 +1,23 @@
+/* Icelandic initialisation for the jQuery UI date picker plugin. */
+/* Written by Haukur H. Thorsson (haukur@eskill.is). */
+jQuery(function($){
+ $.datepicker.regional['is'] = {
+ closeText: 'Loka',
+ prevText: '&#x3C; Fyrri',
+ nextText: 'Næsti &#x3E;',
+ currentText: 'Í dag',
+ monthNames: ['Janúar','Febrúar','Mars','Apríl','Maí','Júní',
+ 'Júlí','Ágúst','September','Október','Nóvember','Desember'],
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maí','Jún',
+ 'Júl','Ágú','Sep','Okt','Nóv','Des'],
+ dayNames: ['Sunnudagur','Mánudagur','Þriðjudagur','Miðvikudagur','Fimmtudagur','Föstudagur','Laugardagur'],
+ dayNamesShort: ['Sun','Mán','Þri','Mið','Fim','Fös','Lau'],
+ dayNamesMin: ['Su','Má','Þr','Mi','Fi','Fö','La'],
+ weekHeader: 'Vika',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 0,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['is']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-it.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-it.js
new file mode 100644
index 00000000..a01f043f
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-it.js
@@ -0,0 +1,23 @@
+/* Italian initialisation for the jQuery UI date picker plugin. */
+/* Written by Antonello Pasella (antonello.pasella@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['it'] = {
+ closeText: 'Chiudi',
+ prevText: '&#x3C;Prec',
+ nextText: 'Succ&#x3E;',
+ currentText: 'Oggi',
+ monthNames: ['Gennaio','Febbraio','Marzo','Aprile','Maggio','Giugno',
+ 'Luglio','Agosto','Settembre','Ottobre','Novembre','Dicembre'],
+ monthNamesShort: ['Gen','Feb','Mar','Apr','Mag','Giu',
+ 'Lug','Ago','Set','Ott','Nov','Dic'],
+ dayNames: ['Domenica','Lunedì','Martedì','Mercoledì','Giovedì','Venerdì','Sabato'],
+ dayNamesShort: ['Dom','Lun','Mar','Mer','Gio','Ven','Sab'],
+ dayNamesMin: ['Do','Lu','Ma','Me','Gi','Ve','Sa'],
+ weekHeader: 'Sm',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['it']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ja.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ja.js
new file mode 100644
index 00000000..4d0b63c7
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ja.js
@@ -0,0 +1,23 @@
+/* Japanese initialisation for the jQuery UI date picker plugin. */
+/* Written by Kentaro SATO (kentaro@ranvis.com). */
+jQuery(function($){
+ $.datepicker.regional['ja'] = {
+ closeText: '閉じる',
+ prevText: '&#x3C;前',
+ nextText: '次&#x3E;',
+ currentText: '今日',
+ monthNames: ['1月','2月','3月','4月','5月','6月',
+ '7月','8月','9月','10月','11月','12月'],
+ monthNamesShort: ['1月','2月','3月','4月','5月','6月',
+ '7月','8月','9月','10月','11月','12月'],
+ dayNames: ['日曜日','月曜日','火曜日','水曜日','木曜日','金曜日','土曜日'],
+ dayNamesShort: ['日','月','火','水','木','金','土'],
+ dayNamesMin: ['日','月','火','水','木','金','土'],
+ weekHeader: '週',
+ dateFormat: 'yy/mm/dd',
+ firstDay: 0,
+ isRTL: false,
+ showMonthAfterYear: true,
+ yearSuffix: '年'};
+ $.datepicker.setDefaults($.datepicker.regional['ja']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ka.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ka.js
new file mode 100644
index 00000000..c10658d7
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ka.js
@@ -0,0 +1,21 @@
+/* Georgian (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Lado Lomidze (lado.lomidze@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['ka'] = {
+ closeText: 'დახურვა',
+ prevText: '&#x3c; წინა',
+ nextText: 'შემდეგი &#x3e;',
+ currentText: 'დღეს',
+ monthNames: ['იანვარი','თებერვალი','მარტი','აპრილი','მაისი','ივნისი', 'ივლისი','აგვისტო','სექტემბერი','ოქტომბერი','ნოემბერი','დეკემბერი'],
+ monthNamesShort: ['იან','თებ','მარ','აპრ','მაი','ივნ', 'ივლ','აგვ','სექ','ოქტ','ნოე','დეკ'],
+ dayNames: ['კვირა','ორშაბათი','სამშაბათი','ოთხშაბათი','ხუთშაბათი','პარასკევი','შაბათი'],
+ dayNamesShort: ['კვ','ორშ','სამ','ოთხ','ხუთ','პარ','შაბ'],
+ dayNamesMin: ['კვ','ორშ','სამ','ოთხ','ხუთ','პარ','შაბ'],
+ weekHeader: 'კვირა',
+ dateFormat: 'dd-mm-yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['ka']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-kk.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-kk.js
new file mode 100644
index 00000000..dcd6a65d
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-kk.js
@@ -0,0 +1,23 @@
+/* Kazakh (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Dmitriy Karasyov (dmitriy.karasyov@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['kk'] = {
+ closeText: 'Жабу',
+ prevText: '&#x3C;Алдыңғы',
+ nextText: 'Келесі&#x3E;',
+ currentText: 'Бүгін',
+ monthNames: ['Қаңтар','Ақпан','Наурыз','Сәуір','Мамыр','Маусым',
+ 'Шілде','Тамыз','Қыркүйек','Қазан','Қараша','Желтоқсан'],
+ monthNamesShort: ['Қаң','Ақп','Нау','Сәу','Мам','Мау',
+ 'Шіл','Там','Қыр','Қаз','Қар','Жел'],
+ dayNames: ['Жексенбі','Дүйсенбі','Сейсенбі','Сәрсенбі','Бейсенбі','Жұма','Сенбі'],
+ dayNamesShort: ['жкс','дсн','ссн','срс','бсн','жма','снб'],
+ dayNamesMin: ['Жк','Дс','Сс','Ср','Бс','Жм','Сн'],
+ weekHeader: 'Не',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['kk']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-km.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-km.js
new file mode 100644
index 00000000..f9c4e3a0
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-km.js
@@ -0,0 +1,23 @@
+/* Khmer initialisation for the jQuery calendar extension. */
+/* Written by Chandara Om (chandara.teacher@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['km'] = {
+ closeText: 'ធ្វើ​រួច',
+ prevText: 'មុន',
+ nextText: 'បន្ទាប់',
+ currentText: 'ថ្ងៃ​នេះ',
+ monthNames: ['មករា','កុម្ភៈ','មីនា','មេសា','ឧសភា','មិថុនា',
+ 'កក្កដា','សីហា','កញ្ញា','តុលា','វិច្ឆិកា','ធ្នូ'],
+ monthNamesShort: ['មករា','កុម្ភៈ','មីនា','មេសា','ឧសភា','មិថុនា',
+ 'កក្កដា','សីហា','កញ្ញា','តុលា','វិច្ឆិកា','ធ្នូ'],
+ dayNames: ['អាទិត្យ', 'ចន្ទ', 'អង្គារ', 'ពុធ', 'ព្រហស្បតិ៍', 'សុក្រ', 'សៅរ៍'],
+ dayNamesShort: ['អា', 'ច', 'អ', 'ពុ', 'ព្រហ', 'សុ', 'សៅ'],
+ dayNamesMin: ['អា', 'ច', 'អ', 'ពុ', 'ព្រហ', 'សុ', 'សៅ'],
+ weekHeader: 'សប្ដាហ៍',
+ dateFormat: 'dd-mm-yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['km']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ko.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ko.js
new file mode 100644
index 00000000..af36f3d6
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ko.js
@@ -0,0 +1,23 @@
+/* Korean initialisation for the jQuery calendar extension. */
+/* Written by DaeKwon Kang (ncrash.dk@gmail.com), Edited by Genie. */
+jQuery(function($){
+ $.datepicker.regional['ko'] = {
+ closeText: '닫기',
+ prevText: '이전달',
+ nextText: '다음달',
+ currentText: '오늘',
+ monthNames: ['1월','2월','3월','4월','5월','6월',
+ '7월','8월','9월','10월','11월','12월'],
+ monthNamesShort: ['1월','2월','3월','4월','5월','6월',
+ '7월','8월','9월','10월','11월','12월'],
+ dayNames: ['일요일','월요일','화요일','수요일','목요일','금요일','토요일'],
+ dayNamesShort: ['일','월','화','수','목','금','토'],
+ dayNamesMin: ['일','월','화','수','목','금','토'],
+ weekHeader: 'Wk',
+ dateFormat: 'yy-mm-dd',
+ firstDay: 0,
+ isRTL: false,
+ showMonthAfterYear: true,
+ yearSuffix: '년'};
+ $.datepicker.setDefaults($.datepicker.regional['ko']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lb.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lb.js
new file mode 100644
index 00000000..87c79d59
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lb.js
@@ -0,0 +1,23 @@
+/* Luxembourgish initialisation for the jQuery UI date picker plugin. */
+/* Written by Michel Weimerskirch <michel@weimerskirch.net> */
+jQuery(function($){
+ $.datepicker.regional['lb'] = {
+ closeText: 'Fäerdeg',
+ prevText: 'Zréck',
+ nextText: 'Weider',
+ currentText: 'Haut',
+ monthNames: ['Januar','Februar','Mäerz','Abrëll','Mee','Juni',
+ 'Juli','August','September','Oktober','November','Dezember'],
+ monthNamesShort: ['Jan', 'Feb', 'Mäe', 'Abr', 'Mee', 'Jun',
+ 'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
+ dayNames: ['Sonndeg', 'Méindeg', 'Dënschdeg', 'Mëttwoch', 'Donneschdeg', 'Freideg', 'Samschdeg'],
+ dayNamesShort: ['Son', 'Méi', 'Dën', 'Mët', 'Don', 'Fre', 'Sam'],
+ dayNamesMin: ['So','Mé','Dë','Më','Do','Fr','Sa'],
+ weekHeader: 'W',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['lb']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lt.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lt.js
new file mode 100644
index 00000000..1afaaac5
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lt.js
@@ -0,0 +1,23 @@
+/* Lithuanian (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* @author Arturas Paleicikas <arturas@avalon.lt> */
+jQuery(function($){
+ $.datepicker.regional['lt'] = {
+ closeText: 'Uždaryti',
+ prevText: '&#x3C;Atgal',
+ nextText: 'Pirmyn&#x3E;',
+ currentText: 'Šiandien',
+ monthNames: ['Sausis','Vasaris','Kovas','Balandis','Gegužė','Birželis',
+ 'Liepa','Rugpjūtis','Rugsėjis','Spalis','Lapkritis','Gruodis'],
+ monthNamesShort: ['Sau','Vas','Kov','Bal','Geg','Bir',
+ 'Lie','Rugp','Rugs','Spa','Lap','Gru'],
+ dayNames: ['sekmadienis','pirmadienis','antradienis','trečiadienis','ketvirtadienis','penktadienis','šeštadienis'],
+ dayNamesShort: ['sek','pir','ant','tre','ket','pen','šeš'],
+ dayNamesMin: ['Se','Pr','An','Tr','Ke','Pe','Še'],
+ weekHeader: 'Wk',
+ dateFormat: 'yy-mm-dd',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['lt']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lv.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lv.js
new file mode 100644
index 00000000..28cc102f
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-lv.js
@@ -0,0 +1,23 @@
+/* Latvian (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* @author Arturas Paleicikas <arturas.paleicikas@metasite.net> */
+jQuery(function($){
+ $.datepicker.regional['lv'] = {
+ closeText: 'Aizvērt',
+ prevText: 'Iepr',
+ nextText: 'Nāka',
+ currentText: 'Šodien',
+ monthNames: ['Janvāris','Februāris','Marts','Aprīlis','Maijs','Jūnijs',
+ 'Jūlijs','Augusts','Septembris','Oktobris','Novembris','Decembris'],
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Mai','Jūn',
+ 'Jūl','Aug','Sep','Okt','Nov','Dec'],
+ dayNames: ['svētdiena','pirmdiena','otrdiena','trešdiena','ceturtdiena','piektdiena','sestdiena'],
+ dayNamesShort: ['svt','prm','otr','tre','ctr','pkt','sst'],
+ dayNamesMin: ['Sv','Pr','Ot','Tr','Ct','Pk','Ss'],
+ weekHeader: 'Nav',
+ dateFormat: 'dd-mm-yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['lv']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-mk.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-mk.js
new file mode 100644
index 00000000..02853255
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-mk.js
@@ -0,0 +1,23 @@
+/* Macedonian i18n for the jQuery UI date picker plugin. */
+/* Written by Stojce Slavkovski. */
+jQuery(function($){
+ $.datepicker.regional['mk'] = {
+ closeText: 'Затвори',
+ prevText: '&#x3C;',
+ nextText: '&#x3E;',
+ currentText: 'Денес',
+ monthNames: ['Јануари','Февруари','Март','Април','Мај','Јуни',
+ 'Јули','Август','Септември','Октомври','Ноември','Декември'],
+ monthNamesShort: ['Јан','Фев','Мар','Апр','Мај','Јун',
+ 'Јул','Авг','Сеп','Окт','Ное','Дек'],
+ dayNames: ['Недела','Понеделник','Вторник','Среда','Четврток','Петок','Сабота'],
+ dayNamesShort: ['Нед','Пон','Вто','Сре','Чет','Пет','Саб'],
+ dayNamesMin: ['Не','По','Вт','Ср','Че','Пе','Са'],
+ weekHeader: 'Сед',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['mk']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ml.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ml.js
new file mode 100644
index 00000000..9b8f460d
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ml.js
@@ -0,0 +1,23 @@
+/* Malayalam (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Saji Nediyanchath (saji89@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['ml'] = {
+ closeText: 'ശരി',
+ prevText: 'മുന്നത്തെ',
+ nextText: 'അടുത്തത് ',
+ currentText: 'ഇന്ന്',
+ monthNames: ['ജനുവരി','ഫെബ്രുവരി','മാര്‍ച്ച്','ഏപ്രില്‍','മേയ്','ജൂണ്‍',
+ 'ജൂലൈ','ആഗസ്റ്റ്','സെപ്റ്റംബര്‍','ഒക്ടോബര്‍','നവംബര്‍','ഡിസംബര്‍'],
+ monthNamesShort: ['ജനു', 'ഫെബ്', 'മാര്‍', 'ഏപ്രി', 'മേയ്', 'ജൂണ്‍',
+ 'ജൂലാ', 'ആഗ', 'സെപ്', 'ഒക്ടോ', 'നവം', 'ഡിസ'],
+ dayNames: ['ഞായര്‍', 'തിങ്കള്‍', 'ചൊവ്വ', 'ബുധന്‍', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],
+ dayNamesShort: ['ഞായ', 'തിങ്ക', 'ചൊവ്വ', 'ബുധ', 'വ്യാഴം', 'വെള്ളി', 'ശനി'],
+ dayNamesMin: ['ഞാ','തി','ചൊ','ബു','വ്യാ','വെ','ശ'],
+ weekHeader: 'ആ',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['ml']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ms.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ms.js
new file mode 100644
index 00000000..e70de729
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ms.js
@@ -0,0 +1,23 @@
+/* Malaysian initialisation for the jQuery UI date picker plugin. */
+/* Written by Mohd Nawawi Mohamad Jamili (nawawi@ronggeng.net). */
+jQuery(function($){
+ $.datepicker.regional['ms'] = {
+ closeText: 'Tutup',
+ prevText: '&#x3C;Sebelum',
+ nextText: 'Selepas&#x3E;',
+ currentText: 'hari ini',
+ monthNames: ['Januari','Februari','Mac','April','Mei','Jun',
+ 'Julai','Ogos','September','Oktober','November','Disember'],
+ monthNamesShort: ['Jan','Feb','Mac','Apr','Mei','Jun',
+ 'Jul','Ogo','Sep','Okt','Nov','Dis'],
+ dayNames: ['Ahad','Isnin','Selasa','Rabu','Khamis','Jumaat','Sabtu'],
+ dayNamesShort: ['Aha','Isn','Sel','Rab','kha','Jum','Sab'],
+ dayNamesMin: ['Ah','Is','Se','Ra','Kh','Ju','Sa'],
+ weekHeader: 'Mg',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 0,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['ms']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl-BE.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl-BE.js
new file mode 100644
index 00000000..7b3cdf42
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl-BE.js
@@ -0,0 +1,23 @@
+/* Dutch (Belgium) initialisation for the jQuery UI date picker plugin. */
+/* David De Sloovere @DavidDeSloovere */
+jQuery(function($){
+ $.datepicker.regional['nl-BE'] = {
+ closeText: 'Sluiten',
+ prevText: '←',
+ nextText: '→',
+ currentText: 'Vandaag',
+ monthNames: ['januari', 'februari', 'maart', 'april', 'mei', 'juni',
+ 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
+ monthNamesShort: ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun',
+ 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
+ dayNames: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
+ dayNamesShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'],
+ dayNamesMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
+ weekHeader: 'Wk',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['nl-BE']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl.js
new file mode 100644
index 00000000..203f1606
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-nl.js
@@ -0,0 +1,23 @@
+/* Dutch (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Mathias Bynens <http://mathiasbynens.be/> */
+jQuery(function($){
+ $.datepicker.regional.nl = {
+ closeText: 'Sluiten',
+ prevText: '←',
+ nextText: '→',
+ currentText: 'Vandaag',
+ monthNames: ['januari', 'februari', 'maart', 'april', 'mei', 'juni',
+ 'juli', 'augustus', 'september', 'oktober', 'november', 'december'],
+ monthNamesShort: ['jan', 'feb', 'mrt', 'apr', 'mei', 'jun',
+ 'jul', 'aug', 'sep', 'okt', 'nov', 'dec'],
+ dayNames: ['zondag', 'maandag', 'dinsdag', 'woensdag', 'donderdag', 'vrijdag', 'zaterdag'],
+ dayNamesShort: ['zon', 'maa', 'din', 'woe', 'don', 'vri', 'zat'],
+ dayNamesMin: ['zo', 'ma', 'di', 'wo', 'do', 'vr', 'za'],
+ weekHeader: 'Wk',
+ dateFormat: 'dd-mm-yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional.nl);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-no.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-no.js
new file mode 100644
index 00000000..d36e430b
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-no.js
@@ -0,0 +1,23 @@
+/* Norwegian initialisation for the jQuery UI date picker plugin. */
+/* Written by Naimdjon Takhirov (naimdjon@gmail.com). */
+
+jQuery(function($){
+ $.datepicker.regional['no'] = {
+ closeText: 'Lukk',
+ prevText: '&#xAB;Forrige',
+ nextText: 'Neste&#xBB;',
+ currentText: 'I dag',
+ monthNames: ['januar','februar','mars','april','mai','juni','juli','august','september','oktober','november','desember'],
+ monthNamesShort: ['jan','feb','mar','apr','mai','jun','jul','aug','sep','okt','nov','des'],
+ dayNamesShort: ['søn','man','tir','ons','tor','fre','lør'],
+ dayNames: ['søndag','mandag','tirsdag','onsdag','torsdag','fredag','lørdag'],
+ dayNamesMin: ['sø','ma','ti','on','to','fr','lø'],
+ weekHeader: 'Uke',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''
+ };
+ $.datepicker.setDefaults($.datepicker.regional['no']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pl.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pl.js
new file mode 100644
index 00000000..0ffc515b
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pl.js
@@ -0,0 +1,23 @@
+/* Polish initialisation for the jQuery UI date picker plugin. */
+/* Written by Jacek Wysocki (jacek.wysocki@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['pl'] = {
+ closeText: 'Zamknij',
+ prevText: '&#x3C;Poprzedni',
+ nextText: 'Następny&#x3E;',
+ currentText: 'Dziś',
+ monthNames: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec',
+ 'Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],
+ monthNamesShort: ['Sty','Lu','Mar','Kw','Maj','Cze',
+ 'Lip','Sie','Wrz','Pa','Lis','Gru'],
+ dayNames: ['Niedziela','Poniedziałek','Wtorek','Środa','Czwartek','Piątek','Sobota'],
+ dayNamesShort: ['Nie','Pn','Wt','Śr','Czw','Pt','So'],
+ dayNamesMin: ['N','Pn','Wt','Śr','Cz','Pt','So'],
+ weekHeader: 'Tydz',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['pl']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js
new file mode 100644
index 00000000..521967ec
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt-BR.js
@@ -0,0 +1,23 @@
+/* Brazilian initialisation for the jQuery UI date picker plugin. */
+/* Written by Leonildo Costa Silva (leocsilva@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['pt-BR'] = {
+ closeText: 'Fechar',
+ prevText: '&#x3C;Anterior',
+ nextText: 'Próximo&#x3E;',
+ currentText: 'Hoje',
+ monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho',
+ 'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
+ monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',
+ 'Jul','Ago','Set','Out','Nov','Dez'],
+ dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'],
+ dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
+ dayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
+ weekHeader: 'Sm',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 0,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['pt-BR']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt.js
new file mode 100644
index 00000000..999f20e3
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-pt.js
@@ -0,0 +1,22 @@
+/* Portuguese initialisation for the jQuery UI date picker plugin. */
+jQuery(function($){
+ $.datepicker.regional['pt'] = {
+ closeText: 'Fechar',
+ prevText: '&#x3C;Anterior',
+ nextText: 'Seguinte',
+ currentText: 'Hoje',
+ monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho',
+ 'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
+ monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun',
+ 'Jul','Ago','Set','Out','Nov','Dez'],
+ dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'],
+ dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
+ dayNamesMin: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
+ weekHeader: 'Sem',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 0,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['pt']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-rm.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-rm.js
new file mode 100644
index 00000000..22ed2168
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-rm.js
@@ -0,0 +1,21 @@
+/* Romansh initialisation for the jQuery UI date picker plugin. */
+/* Written by Yvonne Gienal (yvonne.gienal@educa.ch). */
+jQuery(function($){
+ $.datepicker.regional['rm'] = {
+ closeText: 'Serrar',
+ prevText: '&#x3C;Suandant',
+ nextText: 'Precedent&#x3E;',
+ currentText: 'Actual',
+ monthNames: ['Schaner','Favrer','Mars','Avrigl','Matg','Zercladur', 'Fanadur','Avust','Settember','October','November','December'],
+ monthNamesShort: ['Scha','Fev','Mar','Avr','Matg','Zer', 'Fan','Avu','Sett','Oct','Nov','Dec'],
+ dayNames: ['Dumengia','Glindesdi','Mardi','Mesemna','Gievgia','Venderdi','Sonda'],
+ dayNamesShort: ['Dum','Gli','Mar','Mes','Gie','Ven','Som'],
+ dayNamesMin: ['Du','Gl','Ma','Me','Gi','Ve','So'],
+ weekHeader: 'emna',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['rm']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ro.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ro.js
new file mode 100644
index 00000000..a988270d
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ro.js
@@ -0,0 +1,26 @@
+/* Romanian initialisation for the jQuery UI date picker plugin.
+ *
+ * Written by Edmond L. (ll_edmond@walla.com)
+ * and Ionut G. Stan (ionut.g.stan@gmail.com)
+ */
+jQuery(function($){
+ $.datepicker.regional['ro'] = {
+ closeText: 'Închide',
+ prevText: '&#xAB; Luna precedentă',
+ nextText: 'Luna următoare &#xBB;',
+ currentText: 'Azi',
+ monthNames: ['Ianuarie','Februarie','Martie','Aprilie','Mai','Iunie',
+ 'Iulie','August','Septembrie','Octombrie','Noiembrie','Decembrie'],
+ monthNamesShort: ['Ian', 'Feb', 'Mar', 'Apr', 'Mai', 'Iun',
+ 'Iul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
+ dayNames: ['Duminică', 'Luni', 'Marţi', 'Miercuri', 'Joi', 'Vineri', 'Sâmbătă'],
+ dayNamesShort: ['Dum', 'Lun', 'Mar', 'Mie', 'Joi', 'Vin', 'Sâm'],
+ dayNamesMin: ['Du','Lu','Ma','Mi','Jo','Vi','Sâ'],
+ weekHeader: 'Săpt',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['ro']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ru.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ru.js
new file mode 100644
index 00000000..a5197140
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ru.js
@@ -0,0 +1,23 @@
+/* Russian (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Andrew Stromnov (stromnov@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['ru'] = {
+ closeText: 'Закрыть',
+ prevText: '&#x3C;Пред',
+ nextText: 'След&#x3E;',
+ currentText: 'Сегодня',
+ monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь',
+ 'Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],
+ monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн',
+ 'Июл','Авг','Сен','Окт','Ноя','Дек'],
+ dayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'],
+ dayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'],
+ dayNamesMin: ['Вс','Пн','Вт','Ср','Чт','Пт','Сб'],
+ weekHeader: 'Нед',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['ru']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sk.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sk.js
new file mode 100644
index 00000000..83ae8e81
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sk.js
@@ -0,0 +1,23 @@
+/* Slovak initialisation for the jQuery UI date picker plugin. */
+/* Written by Vojtech Rinik (vojto@hmm.sk). */
+jQuery(function($){
+ $.datepicker.regional['sk'] = {
+ closeText: 'Zavrieť',
+ prevText: '&#x3C;Predchádzajúci',
+ nextText: 'Nasledujúci&#x3E;',
+ currentText: 'Dnes',
+ monthNames: ['Január','Február','Marec','Apríl','Máj','Jún',
+ 'Júl','August','September','Október','November','December'],
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Máj','Jún',
+ 'Júl','Aug','Sep','Okt','Nov','Dec'],
+ dayNames: ['Nedeľa','Pondelok','Utorok','Streda','Štvrtok','Piatok','Sobota'],
+ dayNamesShort: ['Ned','Pon','Uto','Str','Štv','Pia','Sob'],
+ dayNamesMin: ['Ne','Po','Ut','St','Št','Pia','So'],
+ weekHeader: 'Ty',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['sk']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sl.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sl.js
new file mode 100644
index 00000000..048a47af
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sl.js
@@ -0,0 +1,24 @@
+/* Slovenian initialisation for the jQuery UI date picker plugin. */
+/* Written by Jaka Jancar (jaka@kubje.org). */
+/* c = č, s = š z = ž C = Č S = Š Z = Ž */
+jQuery(function($){
+ $.datepicker.regional['sl'] = {
+ closeText: 'Zapri',
+ prevText: '&#x3C;Prejšnji',
+ nextText: 'Naslednji&#x3E;',
+ currentText: 'Trenutni',
+ monthNames: ['Januar','Februar','Marec','April','Maj','Junij',
+ 'Julij','Avgust','September','Oktober','November','December'],
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+ 'Jul','Avg','Sep','Okt','Nov','Dec'],
+ dayNames: ['Nedelja','Ponedeljek','Torek','Sreda','Četrtek','Petek','Sobota'],
+ dayNamesShort: ['Ned','Pon','Tor','Sre','Čet','Pet','Sob'],
+ dayNamesMin: ['Ne','Po','To','Sr','Če','Pe','So'],
+ weekHeader: 'Teden',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['sl']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sq.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sq.js
new file mode 100644
index 00000000..d6086a78
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sq.js
@@ -0,0 +1,23 @@
+/* Albanian initialisation for the jQuery UI date picker plugin. */
+/* Written by Flakron Bytyqi (flakron@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['sq'] = {
+ closeText: 'mbylle',
+ prevText: '&#x3C;mbrapa',
+ nextText: 'Përpara&#x3E;',
+ currentText: 'sot',
+ monthNames: ['Janar','Shkurt','Mars','Prill','Maj','Qershor',
+ 'Korrik','Gusht','Shtator','Tetor','Nëntor','Dhjetor'],
+ monthNamesShort: ['Jan','Shk','Mar','Pri','Maj','Qer',
+ 'Kor','Gus','Sht','Tet','Nën','Dhj'],
+ dayNames: ['E Diel','E Hënë','E Martë','E Mërkurë','E Enjte','E Premte','E Shtune'],
+ dayNamesShort: ['Di','Hë','Ma','Më','En','Pr','Sh'],
+ dayNamesMin: ['Di','Hë','Ma','Më','En','Pr','Sh'],
+ weekHeader: 'Ja',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['sq']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js
new file mode 100644
index 00000000..6d5d0421
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr-SR.js
@@ -0,0 +1,23 @@
+/* Serbian i18n for the jQuery UI date picker plugin. */
+/* Written by Dejan Dimić. */
+jQuery(function($){
+ $.datepicker.regional['sr-SR'] = {
+ closeText: 'Zatvori',
+ prevText: '&#x3C;',
+ nextText: '&#x3E;',
+ currentText: 'Danas',
+ monthNames: ['Januar','Februar','Mart','April','Maj','Jun',
+ 'Jul','Avgust','Septembar','Oktobar','Novembar','Decembar'],
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+ 'Jul','Avg','Sep','Okt','Nov','Dec'],
+ dayNames: ['Nedelja','Ponedeljak','Utorak','Sreda','Četvrtak','Petak','Subota'],
+ dayNamesShort: ['Ned','Pon','Uto','Sre','Čet','Pet','Sub'],
+ dayNamesMin: ['Ne','Po','Ut','Sr','Če','Pe','Su'],
+ weekHeader: 'Sed',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['sr-SR']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr.js
new file mode 100644
index 00000000..d4e1d9af
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sr.js
@@ -0,0 +1,23 @@
+/* Serbian i18n for the jQuery UI date picker plugin. */
+/* Written by Dejan Dimić. */
+jQuery(function($){
+ $.datepicker.regional['sr'] = {
+ closeText: 'Затвори',
+ prevText: '&#x3C;',
+ nextText: '&#x3E;',
+ currentText: 'Данас',
+ monthNames: ['Јануар','Фебруар','Март','Април','Мај','Јун',
+ 'Јул','Август','Септембар','Октобар','Новембар','Децембар'],
+ monthNamesShort: ['Јан','Феб','Мар','Апр','Мај','Јун',
+ 'Јул','Авг','Сеп','Окт','Нов','Дец'],
+ dayNames: ['Недеља','Понедељак','Уторак','Среда','Четвртак','Петак','Субота'],
+ dayNamesShort: ['Нед','Пон','Уто','Сре','Чет','Пет','Суб'],
+ dayNamesMin: ['Не','По','Ут','Ср','Че','Пе','Су'],
+ weekHeader: 'Сед',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['sr']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sv.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sv.js
new file mode 100644
index 00000000..cbb5ad13
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-sv.js
@@ -0,0 +1,23 @@
+/* Swedish initialisation for the jQuery UI date picker plugin. */
+/* Written by Anders Ekdahl ( anders@nomadiz.se). */
+jQuery(function($){
+ $.datepicker.regional['sv'] = {
+ closeText: 'Stäng',
+ prevText: '&#xAB;Förra',
+ nextText: 'Nästa&#xBB;',
+ currentText: 'Idag',
+ monthNames: ['Januari','Februari','Mars','April','Maj','Juni',
+ 'Juli','Augusti','September','Oktober','November','December'],
+ monthNamesShort: ['Jan','Feb','Mar','Apr','Maj','Jun',
+ 'Jul','Aug','Sep','Okt','Nov','Dec'],
+ dayNamesShort: ['Sön','Mån','Tis','Ons','Tor','Fre','Lör'],
+ dayNames: ['Söndag','Måndag','Tisdag','Onsdag','Torsdag','Fredag','Lördag'],
+ dayNamesMin: ['Sö','Må','Ti','On','To','Fr','Lö'],
+ weekHeader: 'Ve',
+ dateFormat: 'yy-mm-dd',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['sv']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ta.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ta.js
new file mode 100644
index 00000000..40431ed8
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-ta.js
@@ -0,0 +1,23 @@
+/* Tamil (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by S A Sureshkumar (saskumar@live.com). */
+jQuery(function($){
+ $.datepicker.regional['ta'] = {
+ closeText: 'மூடு',
+ prevText: 'முன்னையது',
+ nextText: 'அடுத்தது',
+ currentText: 'இன்று',
+ monthNames: ['தை','மாசி','பங்குனி','சித்திரை','வைகாசி','ஆனி',
+ 'ஆடி','ஆவணி','புரட்டாசி','ஐப்பசி','கார்த்திகை','மார்கழி'],
+ monthNamesShort: ['தை','மாசி','பங்','சித்','வைகா','ஆனி',
+ 'ஆடி','ஆவ','புர','ஐப்','கார்','மார்'],
+ dayNames: ['ஞாயிற்றுக்கிழமை','திங்கட்கிழமை','செவ்வாய்க்கிழமை','புதன்கிழமை','வியாழக்கிழமை','வெள்ளிக்கிழமை','சனிக்கிழமை'],
+ dayNamesShort: ['ஞாயிறு','திங்கள்','செவ்வாய்','புதன்','வியாழன்','வெள்ளி','சனி'],
+ dayNamesMin: ['ஞா','தி','செ','பு','வி','வெ','ச'],
+ weekHeader: 'Не',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['ta']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-th.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-th.js
new file mode 100644
index 00000000..aecfd27c
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-th.js
@@ -0,0 +1,23 @@
+/* Thai initialisation for the jQuery UI date picker plugin. */
+/* Written by pipo (pipo@sixhead.com). */
+jQuery(function($){
+ $.datepicker.regional['th'] = {
+ closeText: 'ปิด',
+ prevText: '&#xAB;&#xA0;ย้อน',
+ nextText: 'ถัดไป&#xA0;&#xBB;',
+ currentText: 'วันนี้',
+ monthNames: ['มกราคม','กุมภาพันธ์','มีนาคม','เมษายน','พฤษภาคม','มิถุนายน',
+ 'กรกฎาคม','สิงหาคม','กันยายน','ตุลาคม','พฤศจิกายน','ธันวาคม'],
+ monthNamesShort: ['ม.ค.','ก.พ.','มี.ค.','เม.ย.','พ.ค.','มิ.ย.',
+ 'ก.ค.','ส.ค.','ก.ย.','ต.ค.','พ.ย.','ธ.ค.'],
+ dayNames: ['อาทิตย์','จันทร์','อังคาร','พุธ','พฤหัสบดี','ศุกร์','เสาร์'],
+ dayNamesShort: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],
+ dayNamesMin: ['อา.','จ.','อ.','พ.','พฤ.','ศ.','ส.'],
+ weekHeader: 'Wk',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 0,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['th']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tj.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tj.js
new file mode 100644
index 00000000..9a20e4d3
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tj.js
@@ -0,0 +1,23 @@
+/* Tajiki (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Abdurahmon Saidov (saidovab@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['tj'] = {
+ closeText: 'Идома',
+ prevText: '&#x3c;Қафо',
+ nextText: 'Пеш&#x3e;',
+ currentText: 'Имрӯз',
+ monthNames: ['Январ','Феврал','Март','Апрел','Май','Июн',
+ 'Июл','Август','Сентябр','Октябр','Ноябр','Декабр'],
+ monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн',
+ 'Июл','Авг','Сен','Окт','Ноя','Дек'],
+ dayNames: ['якшанбе','душанбе','сешанбе','чоршанбе','панҷшанбе','ҷумъа','шанбе'],
+ dayNamesShort: ['якш','душ','сеш','чор','пан','ҷум','шан'],
+ dayNamesMin: ['Як','Дш','Сш','Чш','Пш','Ҷм','Шн'],
+ weekHeader: 'Хф',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['tj']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tr.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tr.js
new file mode 100644
index 00000000..75b583a7
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-tr.js
@@ -0,0 +1,23 @@
+/* Turkish initialisation for the jQuery UI date picker plugin. */
+/* Written by Izzet Emre Erkan (kara@karalamalar.net). */
+jQuery(function($){
+ $.datepicker.regional['tr'] = {
+ closeText: 'kapat',
+ prevText: '&#x3C;geri',
+ nextText: 'ileri&#x3e',
+ currentText: 'bugün',
+ monthNames: ['Ocak','Şubat','Mart','Nisan','Mayıs','Haziran',
+ 'Temmuz','Ağustos','Eylül','Ekim','Kasım','Aralık'],
+ monthNamesShort: ['Oca','Şub','Mar','Nis','May','Haz',
+ 'Tem','Ağu','Eyl','Eki','Kas','Ara'],
+ dayNames: ['Pazar','Pazartesi','Salı','Çarşamba','Perşembe','Cuma','Cumartesi'],
+ dayNamesShort: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],
+ dayNamesMin: ['Pz','Pt','Sa','Ça','Pe','Cu','Ct'],
+ weekHeader: 'Hf',
+ dateFormat: 'dd.mm.yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['tr']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-uk.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-uk.js
new file mode 100644
index 00000000..2bdc82ff
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-uk.js
@@ -0,0 +1,24 @@
+/* Ukrainian (UTF-8) initialisation for the jQuery UI date picker plugin. */
+/* Written by Maxim Drogobitskiy (maxdao@gmail.com). */
+/* Corrected by Igor Milla (igor.fsp.milla@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['uk'] = {
+ closeText: 'Закрити',
+ prevText: '&#x3C;',
+ nextText: '&#x3E;',
+ currentText: 'Сьогодні',
+ monthNames: ['Січень','Лютий','Березень','Квітень','Травень','Червень',
+ 'Липень','Серпень','Вересень','Жовтень','Листопад','Грудень'],
+ monthNamesShort: ['Січ','Лют','Бер','Кві','Тра','Чер',
+ 'Лип','Сер','Вер','Жов','Лис','Гру'],
+ dayNames: ['неділя','понеділок','вівторок','середа','четвер','п’ятниця','субота'],
+ dayNamesShort: ['нед','пнд','вів','срд','чтв','птн','сбт'],
+ dayNamesMin: ['Нд','Пн','Вт','Ср','Чт','Пт','Сб'],
+ weekHeader: 'Тиж',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['uk']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-vi.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-vi.js
new file mode 100644
index 00000000..b49e7eb1
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-vi.js
@@ -0,0 +1,23 @@
+/* Vietnamese initialisation for the jQuery UI date picker plugin. */
+/* Translated by Le Thanh Huy (lthanhhuy@cit.ctu.edu.vn). */
+jQuery(function($){
+ $.datepicker.regional['vi'] = {
+ closeText: 'Đóng',
+ prevText: '&#x3C;Trước',
+ nextText: 'Tiếp&#x3E;',
+ currentText: 'Hôm nay',
+ monthNames: ['Tháng Một', 'Tháng Hai', 'Tháng Ba', 'Tháng Tư', 'Tháng Năm', 'Tháng Sáu',
+ 'Tháng Bảy', 'Tháng Tám', 'Tháng Chín', 'Tháng Mười', 'Tháng Mười Một', 'Tháng Mười Hai'],
+ monthNamesShort: ['Tháng 1', 'Tháng 2', 'Tháng 3', 'Tháng 4', 'Tháng 5', 'Tháng 6',
+ 'Tháng 7', 'Tháng 8', 'Tháng 9', 'Tháng 10', 'Tháng 11', 'Tháng 12'],
+ dayNames: ['Chủ Nhật', 'Thứ Hai', 'Thứ Ba', 'Thứ Tư', 'Thứ Năm', 'Thứ Sáu', 'Thứ Bảy'],
+ dayNamesShort: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
+ dayNamesMin: ['CN', 'T2', 'T3', 'T4', 'T5', 'T6', 'T7'],
+ weekHeader: 'Tu',
+ dateFormat: 'dd/mm/yy',
+ firstDay: 0,
+ isRTL: false,
+ showMonthAfterYear: false,
+ yearSuffix: ''};
+ $.datepicker.setDefaults($.datepicker.regional['vi']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js
new file mode 100644
index 00000000..d337e4a9
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-CN.js
@@ -0,0 +1,23 @@
+/* Chinese initialisation for the jQuery UI date picker plugin. */
+/* Written by Cloudream (cloudream@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['zh-CN'] = {
+ closeText: '关闭',
+ prevText: '&#x3C;上月',
+ nextText: '下月&#x3E;',
+ currentText: '今天',
+ monthNames: ['一月','二月','三月','四月','五月','六月',
+ '七月','八月','九月','十月','十一月','十二月'],
+ monthNamesShort: ['一月','二月','三月','四月','五月','六月',
+ '七月','八月','九月','十月','十一月','十二月'],
+ dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
+ dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
+ dayNamesMin: ['日','一','二','三','四','五','六'],
+ weekHeader: '周',
+ dateFormat: 'yy-mm-dd',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: true,
+ yearSuffix: '年'};
+ $.datepicker.setDefaults($.datepicker.regional['zh-CN']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js
new file mode 100644
index 00000000..ef6f4e71
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js
@@ -0,0 +1,23 @@
+/* Chinese initialisation for the jQuery UI date picker plugin. */
+/* Written by SCCY (samuelcychan@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['zh-HK'] = {
+ closeText: '關閉',
+ prevText: '&#x3C;上月',
+ nextText: '下月&#x3E;',
+ currentText: '今天',
+ monthNames: ['一月','二月','三月','四月','五月','六月',
+ '七月','八月','九月','十月','十一月','十二月'],
+ monthNamesShort: ['一月','二月','三月','四月','五月','六月',
+ '七月','八月','九月','十月','十一月','十二月'],
+ dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
+ dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
+ dayNamesMin: ['日','一','二','三','四','五','六'],
+ weekHeader: '周',
+ dateFormat: 'dd-mm-yy',
+ firstDay: 0,
+ isRTL: false,
+ showMonthAfterYear: true,
+ yearSuffix: '年'};
+ $.datepicker.setDefaults($.datepicker.regional['zh-HK']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js
new file mode 100644
index 00000000..b9105ea5
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js
@@ -0,0 +1,23 @@
+/* Chinese initialisation for the jQuery UI date picker plugin. */
+/* Written by Ressol (ressol@gmail.com). */
+jQuery(function($){
+ $.datepicker.regional['zh-TW'] = {
+ closeText: '關閉',
+ prevText: '&#x3C;上月',
+ nextText: '下月&#x3E;',
+ currentText: '今天',
+ monthNames: ['一月','二月','三月','四月','五月','六月',
+ '七月','八月','九月','十月','十一月','十二月'],
+ monthNamesShort: ['一月','二月','三月','四月','五月','六月',
+ '七月','八月','九月','十月','十一月','十二月'],
+ dayNames: ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'],
+ dayNamesShort: ['周日','周一','周二','周三','周四','周五','周六'],
+ dayNamesMin: ['日','一','二','三','四','五','六'],
+ weekHeader: '周',
+ dateFormat: 'yy/mm/dd',
+ firstDay: 1,
+ isRTL: false,
+ showMonthAfterYear: true,
+ yearSuffix: '年'};
+ $.datepicker.setDefaults($.datepicker.regional['zh-TW']);
+});
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.accordion.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.accordion.js
new file mode 100644
index 00000000..55bbecba
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.accordion.js
@@ -0,0 +1,731 @@
+/*!
+ * jQuery UI Accordion 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/accordion/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+var uid = 0,
+ hideProps = {},
+ showProps = {};
+
+hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
+ hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
+showProps.height = showProps.paddingTop = showProps.paddingBottom =
+ showProps.borderTopWidth = showProps.borderBottomWidth = "show";
+
+$.widget( "ui.accordion", {
+ version: "1.9.2",
+ options: {
+ active: 0,
+ animate: {},
+ collapsible: false,
+ event: "click",
+ header: "> li > :first-child,> :not(li):even",
+ heightStyle: "auto",
+ icons: {
+ activeHeader: "ui-icon-triangle-1-s",
+ header: "ui-icon-triangle-1-e"
+ },
+
+ // callbacks
+ activate: null,
+ beforeActivate: null
+ },
+
+ _create: function() {
+ var accordionId = this.accordionId = "ui-accordion-" +
+ (this.element.attr( "id" ) || ++uid),
+ options = this.options;
+
+ this.prevShow = this.prevHide = $();
+ this.element.addClass( "ui-accordion ui-widget ui-helper-reset" );
+
+ this.headers = this.element.find( options.header )
+ .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );
+ this._hoverable( this.headers );
+ this._focusable( this.headers );
+
+ this.headers.next()
+ .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
+ .hide();
+
+ // don't allow collapsible: false and active: false / null
+ if ( !options.collapsible && (options.active === false || options.active == null) ) {
+ options.active = 0;
+ }
+ // handle negative values
+ if ( options.active < 0 ) {
+ options.active += this.headers.length;
+ }
+ this.active = this._findActive( options.active )
+ .addClass( "ui-accordion-header-active ui-state-active" )
+ .toggleClass( "ui-corner-all ui-corner-top" );
+ this.active.next()
+ .addClass( "ui-accordion-content-active" )
+ .show();
+
+ this._createIcons();
+ this.refresh();
+
+ // ARIA
+ this.element.attr( "role", "tablist" );
+
+ this.headers
+ .attr( "role", "tab" )
+ .each(function( i ) {
+ var header = $( this ),
+ headerId = header.attr( "id" ),
+ panel = header.next(),
+ panelId = panel.attr( "id" );
+ if ( !headerId ) {
+ headerId = accordionId + "-header-" + i;
+ header.attr( "id", headerId );
+ }
+ if ( !panelId ) {
+ panelId = accordionId + "-panel-" + i;
+ panel.attr( "id", panelId );
+ }
+ header.attr( "aria-controls", panelId );
+ panel.attr( "aria-labelledby", headerId );
+ })
+ .next()
+ .attr( "role", "tabpanel" );
+
+ this.headers
+ .not( this.active )
+ .attr({
+ "aria-selected": "false",
+ tabIndex: -1
+ })
+ .next()
+ .attr({
+ "aria-expanded": "false",
+ "aria-hidden": "true"
+ })
+ .hide();
+
+ // make sure at least one header is in the tab order
+ if ( !this.active.length ) {
+ this.headers.eq( 0 ).attr( "tabIndex", 0 );
+ } else {
+ this.active.attr({
+ "aria-selected": "true",
+ tabIndex: 0
+ })
+ .next()
+ .attr({
+ "aria-expanded": "true",
+ "aria-hidden": "false"
+ });
+ }
+
+ this._on( this.headers, { keydown: "_keydown" });
+ this._on( this.headers.next(), { keydown: "_panelKeyDown" });
+ this._setupEvents( options.event );
+ },
+
+ _getCreateEventData: function() {
+ return {
+ header: this.active,
+ content: !this.active.length ? $() : this.active.next()
+ };
+ },
+
+ _createIcons: function() {
+ var icons = this.options.icons;
+ if ( icons ) {
+ $( "<span>" )
+ .addClass( "ui-accordion-header-icon ui-icon " + icons.header )
+ .prependTo( this.headers );
+ this.active.children( ".ui-accordion-header-icon" )
+ .removeClass( icons.header )
+ .addClass( icons.activeHeader );
+ this.headers.addClass( "ui-accordion-icons" );
+ }
+ },
+
+ _destroyIcons: function() {
+ this.headers
+ .removeClass( "ui-accordion-icons" )
+ .children( ".ui-accordion-header-icon" )
+ .remove();
+ },
+
+ _destroy: function() {
+ var contents;
+
+ // clean up main element
+ this.element
+ .removeClass( "ui-accordion ui-widget ui-helper-reset" )
+ .removeAttr( "role" );
+
+ // clean up headers
+ this.headers
+ .removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-selected" )
+ .removeAttr( "aria-controls" )
+ .removeAttr( "tabIndex" )
+ .each(function() {
+ if ( /^ui-accordion/.test( this.id ) ) {
+ this.removeAttribute( "id" );
+ }
+ });
+ this._destroyIcons();
+
+ // clean up content panels
+ contents = this.headers.next()
+ .css( "display", "" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-expanded" )
+ .removeAttr( "aria-hidden" )
+ .removeAttr( "aria-labelledby" )
+ .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )
+ .each(function() {
+ if ( /^ui-accordion/.test( this.id ) ) {
+ this.removeAttribute( "id" );
+ }
+ });
+ if ( this.options.heightStyle !== "content" ) {
+ contents.css( "height", "" );
+ }
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "active" ) {
+ // _activate() will handle invalid values and update this.options
+ this._activate( value );
+ return;
+ }
+
+ if ( key === "event" ) {
+ if ( this.options.event ) {
+ this._off( this.headers, this.options.event );
+ }
+ this._setupEvents( value );
+ }
+
+ this._super( key, value );
+
+ // setting collapsible: false while collapsed; open first panel
+ if ( key === "collapsible" && !value && this.options.active === false ) {
+ this._activate( 0 );
+ }
+
+ if ( key === "icons" ) {
+ this._destroyIcons();
+ if ( value ) {
+ this._createIcons();
+ }
+ }
+
+ // #5332 - opacity doesn't cascade to positioned elements in IE
+ // so we need to add the disabled class to the headers and panels
+ if ( key === "disabled" ) {
+ this.headers.add( this.headers.next() )
+ .toggleClass( "ui-state-disabled", !!value );
+ }
+ },
+
+ _keydown: function( event ) {
+ if ( event.altKey || event.ctrlKey ) {
+ return;
+ }
+
+ var keyCode = $.ui.keyCode,
+ length = this.headers.length,
+ currentIndex = this.headers.index( event.target ),
+ toFocus = false;
+
+ switch ( event.keyCode ) {
+ case keyCode.RIGHT:
+ case keyCode.DOWN:
+ toFocus = this.headers[ ( currentIndex + 1 ) % length ];
+ break;
+ case keyCode.LEFT:
+ case keyCode.UP:
+ toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
+ break;
+ case keyCode.SPACE:
+ case keyCode.ENTER:
+ this._eventHandler( event );
+ break;
+ case keyCode.HOME:
+ toFocus = this.headers[ 0 ];
+ break;
+ case keyCode.END:
+ toFocus = this.headers[ length - 1 ];
+ break;
+ }
+
+ if ( toFocus ) {
+ $( event.target ).attr( "tabIndex", -1 );
+ $( toFocus ).attr( "tabIndex", 0 );
+ toFocus.focus();
+ event.preventDefault();
+ }
+ },
+
+ _panelKeyDown : function( event ) {
+ if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
+ $( event.currentTarget ).prev().focus();
+ }
+ },
+
+ refresh: function() {
+ var maxHeight, overflow,
+ heightStyle = this.options.heightStyle,
+ parent = this.element.parent();
+
+
+ if ( heightStyle === "fill" ) {
+ // IE 6 treats height like minHeight, so we need to turn off overflow
+ // in order to get a reliable height
+ // we use the minHeight support test because we assume that only
+ // browsers that don't support minHeight will treat height as minHeight
+ if ( !$.support.minHeight ) {
+ overflow = parent.css( "overflow" );
+ parent.css( "overflow", "hidden");
+ }
+ maxHeight = parent.height();
+ this.element.siblings( ":visible" ).each(function() {
+ var elem = $( this ),
+ position = elem.css( "position" );
+
+ if ( position === "absolute" || position === "fixed" ) {
+ return;
+ }
+ maxHeight -= elem.outerHeight( true );
+ });
+ if ( overflow ) {
+ parent.css( "overflow", overflow );
+ }
+
+ this.headers.each(function() {
+ maxHeight -= $( this ).outerHeight( true );
+ });
+
+ this.headers.next()
+ .each(function() {
+ $( this ).height( Math.max( 0, maxHeight -
+ $( this ).innerHeight() + $( this ).height() ) );
+ })
+ .css( "overflow", "auto" );
+ } else if ( heightStyle === "auto" ) {
+ maxHeight = 0;
+ this.headers.next()
+ .each(function() {
+ maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
+ })
+ .height( maxHeight );
+ }
+ },
+
+ _activate: function( index ) {
+ var active = this._findActive( index )[ 0 ];
+
+ // trying to activate the already active panel
+ if ( active === this.active[ 0 ] ) {
+ return;
+ }
+
+ // trying to collapse, simulate a click on the currently active header
+ active = active || this.active[ 0 ];
+
+ this._eventHandler({
+ target: active,
+ currentTarget: active,
+ preventDefault: $.noop
+ });
+ },
+
+ _findActive: function( selector ) {
+ return typeof selector === "number" ? this.headers.eq( selector ) : $();
+ },
+
+ _setupEvents: function( event ) {
+ var events = {};
+ if ( !event ) {
+ return;
+ }
+ $.each( event.split(" "), function( index, eventName ) {
+ events[ eventName ] = "_eventHandler";
+ });
+ this._on( this.headers, events );
+ },
+
+ _eventHandler: function( event ) {
+ var options = this.options,
+ active = this.active,
+ clicked = $( event.currentTarget ),
+ clickedIsActive = clicked[ 0 ] === active[ 0 ],
+ collapsing = clickedIsActive && options.collapsible,
+ toShow = collapsing ? $() : clicked.next(),
+ toHide = active.next(),
+ eventData = {
+ oldHeader: active,
+ oldPanel: toHide,
+ newHeader: collapsing ? $() : clicked,
+ newPanel: toShow
+ };
+
+ event.preventDefault();
+
+ if (
+ // click on active header, but not collapsible
+ ( clickedIsActive && !options.collapsible ) ||
+ // allow canceling activation
+ ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
+ return;
+ }
+
+ options.active = collapsing ? false : this.headers.index( clicked );
+
+ // when the call to ._toggle() comes after the class changes
+ // it causes a very odd bug in IE 8 (see #6720)
+ this.active = clickedIsActive ? $() : clicked;
+ this._toggle( eventData );
+
+ // switch classes
+ // corner classes on the previously active header stay after the animation
+ active.removeClass( "ui-accordion-header-active ui-state-active" );
+ if ( options.icons ) {
+ active.children( ".ui-accordion-header-icon" )
+ .removeClass( options.icons.activeHeader )
+ .addClass( options.icons.header );
+ }
+
+ if ( !clickedIsActive ) {
+ clicked
+ .removeClass( "ui-corner-all" )
+ .addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
+ if ( options.icons ) {
+ clicked.children( ".ui-accordion-header-icon" )
+ .removeClass( options.icons.header )
+ .addClass( options.icons.activeHeader );
+ }
+
+ clicked
+ .next()
+ .addClass( "ui-accordion-content-active" );
+ }
+ },
+
+ _toggle: function( data ) {
+ var toShow = data.newPanel,
+ toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
+
+ // handle activating a panel during the animation for another activation
+ this.prevShow.add( this.prevHide ).stop( true, true );
+ this.prevShow = toShow;
+ this.prevHide = toHide;
+
+ if ( this.options.animate ) {
+ this._animate( toShow, toHide, data );
+ } else {
+ toHide.hide();
+ toShow.show();
+ this._toggleComplete( data );
+ }
+
+ toHide.attr({
+ "aria-expanded": "false",
+ "aria-hidden": "true"
+ });
+ toHide.prev().attr( "aria-selected", "false" );
+ // if we're switching panels, remove the old header from the tab order
+ // if we're opening from collapsed state, remove the previous header from the tab order
+ // if we're collapsing, then keep the collapsing header in the tab order
+ if ( toShow.length && toHide.length ) {
+ toHide.prev().attr( "tabIndex", -1 );
+ } else if ( toShow.length ) {
+ this.headers.filter(function() {
+ return $( this ).attr( "tabIndex" ) === 0;
+ })
+ .attr( "tabIndex", -1 );
+ }
+
+ toShow
+ .attr({
+ "aria-expanded": "true",
+ "aria-hidden": "false"
+ })
+ .prev()
+ .attr({
+ "aria-selected": "true",
+ tabIndex: 0
+ });
+ },
+
+ _animate: function( toShow, toHide, data ) {
+ var total, easing, duration,
+ that = this,
+ adjust = 0,
+ down = toShow.length &&
+ ( !toHide.length || ( toShow.index() < toHide.index() ) ),
+ animate = this.options.animate || {},
+ options = down && animate.down || animate,
+ complete = function() {
+ that._toggleComplete( data );
+ };
+
+ if ( typeof options === "number" ) {
+ duration = options;
+ }
+ if ( typeof options === "string" ) {
+ easing = options;
+ }
+ // fall back from options to animation in case of partial down settings
+ easing = easing || options.easing || animate.easing;
+ duration = duration || options.duration || animate.duration;
+
+ if ( !toHide.length ) {
+ return toShow.animate( showProps, duration, easing, complete );
+ }
+ if ( !toShow.length ) {
+ return toHide.animate( hideProps, duration, easing, complete );
+ }
+
+ total = toShow.show().outerHeight();
+ toHide.animate( hideProps, {
+ duration: duration,
+ easing: easing,
+ step: function( now, fx ) {
+ fx.now = Math.round( now );
+ }
+ });
+ toShow
+ .hide()
+ .animate( showProps, {
+ duration: duration,
+ easing: easing,
+ complete: complete,
+ step: function( now, fx ) {
+ fx.now = Math.round( now );
+ if ( fx.prop !== "height" ) {
+ adjust += fx.now;
+ } else if ( that.options.heightStyle !== "content" ) {
+ fx.now = Math.round( total - toHide.outerHeight() - adjust );
+ adjust = 0;
+ }
+ }
+ });
+ },
+
+ _toggleComplete: function( data ) {
+ var toHide = data.oldPanel;
+
+ toHide
+ .removeClass( "ui-accordion-content-active" )
+ .prev()
+ .removeClass( "ui-corner-top" )
+ .addClass( "ui-corner-all" );
+
+ // Work around for rendering bug in IE (#5421)
+ if ( toHide.length ) {
+ toHide.parent()[0].className = toHide.parent()[0].className;
+ }
+
+ this._trigger( "activate", null, data );
+ }
+});
+
+
+
+// DEPRECATED
+if ( $.uiBackCompat !== false ) {
+ // navigation options
+ (function( $, prototype ) {
+ $.extend( prototype.options, {
+ navigation: false,
+ navigationFilter: function() {
+ return this.href.toLowerCase() === location.href.toLowerCase();
+ }
+ });
+
+ var _create = prototype._create;
+ prototype._create = function() {
+ if ( this.options.navigation ) {
+ var that = this,
+ headers = this.element.find( this.options.header ),
+ content = headers.next(),
+ current = headers.add( content )
+ .find( "a" )
+ .filter( this.options.navigationFilter )
+ [ 0 ];
+ if ( current ) {
+ headers.add( content ).each( function( index ) {
+ if ( $.contains( this, current ) ) {
+ that.options.active = Math.floor( index / 2 );
+ return false;
+ }
+ });
+ }
+ }
+ _create.call( this );
+ };
+ }( jQuery, jQuery.ui.accordion.prototype ) );
+
+ // height options
+ (function( $, prototype ) {
+ $.extend( prototype.options, {
+ heightStyle: null, // remove default so we fall back to old values
+ autoHeight: true, // use heightStyle: "auto"
+ clearStyle: false, // use heightStyle: "content"
+ fillSpace: false // use heightStyle: "fill"
+ });
+
+ var _create = prototype._create,
+ _setOption = prototype._setOption;
+
+ $.extend( prototype, {
+ _create: function() {
+ this.options.heightStyle = this.options.heightStyle ||
+ this._mergeHeightStyle();
+
+ _create.call( this );
+ },
+
+ _setOption: function( key ) {
+ if ( key === "autoHeight" || key === "clearStyle" || key === "fillSpace" ) {
+ this.options.heightStyle = this._mergeHeightStyle();
+ }
+ _setOption.apply( this, arguments );
+ },
+
+ _mergeHeightStyle: function() {
+ var options = this.options;
+
+ if ( options.fillSpace ) {
+ return "fill";
+ }
+
+ if ( options.clearStyle ) {
+ return "content";
+ }
+
+ if ( options.autoHeight ) {
+ return "auto";
+ }
+ }
+ });
+ }( jQuery, jQuery.ui.accordion.prototype ) );
+
+ // icon options
+ (function( $, prototype ) {
+ $.extend( prototype.options.icons, {
+ activeHeader: null, // remove default so we fall back to old values
+ headerSelected: "ui-icon-triangle-1-s"
+ });
+
+ var _createIcons = prototype._createIcons;
+ prototype._createIcons = function() {
+ if ( this.options.icons ) {
+ this.options.icons.activeHeader = this.options.icons.activeHeader ||
+ this.options.icons.headerSelected;
+ }
+ _createIcons.call( this );
+ };
+ }( jQuery, jQuery.ui.accordion.prototype ) );
+
+ // expanded active option, activate method
+ (function( $, prototype ) {
+ prototype.activate = prototype._activate;
+
+ var _findActive = prototype._findActive;
+ prototype._findActive = function( index ) {
+ if ( index === -1 ) {
+ index = false;
+ }
+ if ( index && typeof index !== "number" ) {
+ index = this.headers.index( this.headers.filter( index ) );
+ if ( index === -1 ) {
+ index = false;
+ }
+ }
+ return _findActive.call( this, index );
+ };
+ }( jQuery, jQuery.ui.accordion.prototype ) );
+
+ // resize method
+ jQuery.ui.accordion.prototype.resize = jQuery.ui.accordion.prototype.refresh;
+
+ // change events
+ (function( $, prototype ) {
+ $.extend( prototype.options, {
+ change: null,
+ changestart: null
+ });
+
+ var _trigger = prototype._trigger;
+ prototype._trigger = function( type, event, data ) {
+ var ret = _trigger.apply( this, arguments );
+ if ( !ret ) {
+ return false;
+ }
+
+ if ( type === "beforeActivate" ) {
+ ret = _trigger.call( this, "changestart", event, {
+ oldHeader: data.oldHeader,
+ oldContent: data.oldPanel,
+ newHeader: data.newHeader,
+ newContent: data.newPanel
+ });
+ } else if ( type === "activate" ) {
+ ret = _trigger.call( this, "change", event, {
+ oldHeader: data.oldHeader,
+ oldContent: data.oldPanel,
+ newHeader: data.newHeader,
+ newContent: data.newPanel
+ });
+ }
+ return ret;
+ };
+ }( jQuery, jQuery.ui.accordion.prototype ) );
+
+ // animated option
+ // NOTE: this only provides support for "slide", "bounceslide", and easings
+ // not the full $.ui.accordion.animations API
+ (function( $, prototype ) {
+ $.extend( prototype.options, {
+ animate: null,
+ animated: "slide"
+ });
+
+ var _create = prototype._create;
+ prototype._create = function() {
+ var options = this.options;
+ if ( options.animate === null ) {
+ if ( !options.animated ) {
+ options.animate = false;
+ } else if ( options.animated === "slide" ) {
+ options.animate = 300;
+ } else if ( options.animated === "bounceslide" ) {
+ options.animate = {
+ duration: 200,
+ down: {
+ easing: "easeOutBounce",
+ duration: 1000
+ }
+ };
+ } else {
+ options.animate = options.animated;
+ }
+ }
+
+ _create.call( this );
+ };
+ }( jQuery, jQuery.ui.accordion.prototype ) );
+}
+
+})( jQuery );
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.autocomplete.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.autocomplete.js
new file mode 100644
index 00000000..3baed1da
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.autocomplete.js
@@ -0,0 +1,602 @@
+/*!
+ * jQuery UI Autocomplete 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/autocomplete/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.position.js
+ * jquery.ui.menu.js
+ */
+(function( $, undefined ) {
+
+// used to prevent race conditions with remote data sources
+var requestIndex = 0;
+
+$.widget( "ui.autocomplete", {
+ version: "1.9.2",
+ defaultElement: "<input>",
+ options: {
+ appendTo: "body",
+ autoFocus: false,
+ delay: 300,
+ minLength: 1,
+ position: {
+ my: "left top",
+ at: "left bottom",
+ collision: "none"
+ },
+ source: null,
+
+ // callbacks
+ change: null,
+ close: null,
+ focus: null,
+ open: null,
+ response: null,
+ search: null,
+ select: null
+ },
+
+ pending: 0,
+
+ _create: function() {
+ // Some browsers only repeat keydown events, not keypress events,
+ // so we use the suppressKeyPress flag to determine if we've already
+ // handled the keydown event. #7269
+ // Unfortunately the code for & in keypress is the same as the up arrow,
+ // so we use the suppressKeyPressRepeat flag to avoid handling keypress
+ // events when we know the keydown event was used to modify the
+ // search term. #7799
+ var suppressKeyPress, suppressKeyPressRepeat, suppressInput;
+
+ this.isMultiLine = this._isMultiLine();
+ this.valueMethod = this.element[ this.element.is( "input,textarea" ) ? "val" : "text" ];
+ this.isNewMenu = true;
+
+ this.element
+ .addClass( "ui-autocomplete-input" )
+ .attr( "autocomplete", "off" );
+
+ this._on( this.element, {
+ keydown: function( event ) {
+ if ( this.element.prop( "readOnly" ) ) {
+ suppressKeyPress = true;
+ suppressInput = true;
+ suppressKeyPressRepeat = true;
+ return;
+ }
+
+ suppressKeyPress = false;
+ suppressInput = false;
+ suppressKeyPressRepeat = false;
+ var keyCode = $.ui.keyCode;
+ switch( event.keyCode ) {
+ case keyCode.PAGE_UP:
+ suppressKeyPress = true;
+ this._move( "previousPage", event );
+ break;
+ case keyCode.PAGE_DOWN:
+ suppressKeyPress = true;
+ this._move( "nextPage", event );
+ break;
+ case keyCode.UP:
+ suppressKeyPress = true;
+ this._keyEvent( "previous", event );
+ break;
+ case keyCode.DOWN:
+ suppressKeyPress = true;
+ this._keyEvent( "next", event );
+ break;
+ case keyCode.ENTER:
+ case keyCode.NUMPAD_ENTER:
+ // when menu is open and has focus
+ if ( this.menu.active ) {
+ // #6055 - Opera still allows the keypress to occur
+ // which causes forms to submit
+ suppressKeyPress = true;
+ event.preventDefault();
+ this.menu.select( event );
+ }
+ break;
+ case keyCode.TAB:
+ if ( this.menu.active ) {
+ this.menu.select( event );
+ }
+ break;
+ case keyCode.ESCAPE:
+ if ( this.menu.element.is( ":visible" ) ) {
+ this._value( this.term );
+ this.close( event );
+ // Different browsers have different default behavior for escape
+ // Single press can mean undo or clear
+ // Double press in IE means clear the whole form
+ event.preventDefault();
+ }
+ break;
+ default:
+ suppressKeyPressRepeat = true;
+ // search timeout should be triggered before the input value is changed
+ this._searchTimeout( event );
+ break;
+ }
+ },
+ keypress: function( event ) {
+ if ( suppressKeyPress ) {
+ suppressKeyPress = false;
+ event.preventDefault();
+ return;
+ }
+ if ( suppressKeyPressRepeat ) {
+ return;
+ }
+
+ // replicate some key handlers to allow them to repeat in Firefox and Opera
+ var keyCode = $.ui.keyCode;
+ switch( event.keyCode ) {
+ case keyCode.PAGE_UP:
+ this._move( "previousPage", event );
+ break;
+ case keyCode.PAGE_DOWN:
+ this._move( "nextPage", event );
+ break;
+ case keyCode.UP:
+ this._keyEvent( "previous", event );
+ break;
+ case keyCode.DOWN:
+ this._keyEvent( "next", event );
+ break;
+ }
+ },
+ input: function( event ) {
+ if ( suppressInput ) {
+ suppressInput = false;
+ event.preventDefault();
+ return;
+ }
+ this._searchTimeout( event );
+ },
+ focus: function() {
+ this.selectedItem = null;
+ this.previous = this._value();
+ },
+ blur: function( event ) {
+ if ( this.cancelBlur ) {
+ delete this.cancelBlur;
+ return;
+ }
+
+ clearTimeout( this.searching );
+ this.close( event );
+ this._change( event );
+ }
+ });
+
+ this._initSource();
+ this.menu = $( "<ul>" )
+ .addClass( "ui-autocomplete" )
+ .appendTo( this.document.find( this.options.appendTo || "body" )[ 0 ] )
+ .menu({
+ // custom key handling for now
+ input: $(),
+ // disable ARIA support, the live region takes care of that
+ role: null
+ })
+ .zIndex( this.element.zIndex() + 1 )
+ .hide()
+ .data( "menu" );
+
+ this._on( this.menu.element, {
+ mousedown: function( event ) {
+ // prevent moving focus out of the text field
+ event.preventDefault();
+
+ // IE doesn't prevent moving focus even with event.preventDefault()
+ // so we set a flag to know when we should ignore the blur event
+ this.cancelBlur = true;
+ this._delay(function() {
+ delete this.cancelBlur;
+ });
+
+ // clicking on the scrollbar causes focus to shift to the body
+ // but we can't detect a mouseup or a click immediately afterward
+ // so we have to track the next mousedown and close the menu if
+ // the user clicks somewhere outside of the autocomplete
+ var menuElement = this.menu.element[ 0 ];
+ if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
+ this._delay(function() {
+ var that = this;
+ this.document.one( "mousedown", function( event ) {
+ if ( event.target !== that.element[ 0 ] &&
+ event.target !== menuElement &&
+ !$.contains( menuElement, event.target ) ) {
+ that.close();
+ }
+ });
+ });
+ }
+ },
+ menufocus: function( event, ui ) {
+ // #7024 - Prevent accidental activation of menu items in Firefox
+ if ( this.isNewMenu ) {
+ this.isNewMenu = false;
+ if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
+ this.menu.blur();
+
+ this.document.one( "mousemove", function() {
+ $( event.target ).trigger( event.originalEvent );
+ });
+
+ return;
+ }
+ }
+
+ // back compat for _renderItem using item.autocomplete, via #7810
+ // TODO remove the fallback, see #8156
+ var item = ui.item.data( "ui-autocomplete-item" ) || ui.item.data( "item.autocomplete" );
+ if ( false !== this._trigger( "focus", event, { item: item } ) ) {
+ // use value to match what will end up in the input, if it was a key event
+ if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
+ this._value( item.value );
+ }
+ } else {
+ // Normally the input is populated with the item's value as the
+ // menu is navigated, causing screen readers to notice a change and
+ // announce the item. Since the focus event was canceled, this doesn't
+ // happen, so we update the live region so that screen readers can
+ // still notice the change and announce it.
+ this.liveRegion.text( item.value );
+ }
+ },
+ menuselect: function( event, ui ) {
+ // back compat for _renderItem using item.autocomplete, via #7810
+ // TODO remove the fallback, see #8156
+ var item = ui.item.data( "ui-autocomplete-item" ) || ui.item.data( "item.autocomplete" ),
+ previous = this.previous;
+
+ // only trigger when focus was lost (click on menu)
+ if ( this.element[0] !== this.document[0].activeElement ) {
+ this.element.focus();
+ this.previous = previous;
+ // #6109 - IE triggers two focus events and the second
+ // is asynchronous, so we need to reset the previous
+ // term synchronously and asynchronously :-(
+ this._delay(function() {
+ this.previous = previous;
+ this.selectedItem = item;
+ });
+ }
+
+ if ( false !== this._trigger( "select", event, { item: item } ) ) {
+ this._value( item.value );
+ }
+ // reset the term after the select event
+ // this allows custom select handling to work properly
+ this.term = this._value();
+
+ this.close( event );
+ this.selectedItem = item;
+ }
+ });
+
+ this.liveRegion = $( "<span>", {
+ role: "status",
+ "aria-live": "polite"
+ })
+ .addClass( "ui-helper-hidden-accessible" )
+ .insertAfter( this.element );
+
+ if ( $.fn.bgiframe ) {
+ this.menu.element.bgiframe();
+ }
+
+ // turning off autocomplete prevents the browser from remembering the
+ // value when navigating through history, so we re-enable autocomplete
+ // if the page is unloaded before the widget is destroyed. #7790
+ this._on( this.window, {
+ beforeunload: function() {
+ this.element.removeAttr( "autocomplete" );
+ }
+ });
+ },
+
+ _destroy: function() {
+ clearTimeout( this.searching );
+ this.element
+ .removeClass( "ui-autocomplete-input" )
+ .removeAttr( "autocomplete" );
+ this.menu.element.remove();
+ this.liveRegion.remove();
+ },
+
+ _setOption: function( key, value ) {
+ this._super( key, value );
+ if ( key === "source" ) {
+ this._initSource();
+ }
+ if ( key === "appendTo" ) {
+ this.menu.element.appendTo( this.document.find( value || "body" )[0] );
+ }
+ if ( key === "disabled" && value && this.xhr ) {
+ this.xhr.abort();
+ }
+ },
+
+ _isMultiLine: function() {
+ // Textareas are always multi-line
+ if ( this.element.is( "textarea" ) ) {
+ return true;
+ }
+ // Inputs are always single-line, even if inside a contentEditable element
+ // IE also treats inputs as contentEditable
+ if ( this.element.is( "input" ) ) {
+ return false;
+ }
+ // All other element types are determined by whether or not they're contentEditable
+ return this.element.prop( "isContentEditable" );
+ },
+
+ _initSource: function() {
+ var array, url,
+ that = this;
+ if ( $.isArray(this.options.source) ) {
+ array = this.options.source;
+ this.source = function( request, response ) {
+ response( $.ui.autocomplete.filter( array, request.term ) );
+ };
+ } else if ( typeof this.options.source === "string" ) {
+ url = this.options.source;
+ this.source = function( request, response ) {
+ if ( that.xhr ) {
+ that.xhr.abort();
+ }
+ that.xhr = $.ajax({
+ url: url,
+ data: request,
+ dataType: "json",
+ success: function( data ) {
+ response( data );
+ },
+ error: function() {
+ response( [] );
+ }
+ });
+ };
+ } else {
+ this.source = this.options.source;
+ }
+ },
+
+ _searchTimeout: function( event ) {
+ clearTimeout( this.searching );
+ this.searching = this._delay(function() {
+ // only search if the value has changed
+ if ( this.term !== this._value() ) {
+ this.selectedItem = null;
+ this.search( null, event );
+ }
+ }, this.options.delay );
+ },
+
+ search: function( value, event ) {
+ value = value != null ? value : this._value();
+
+ // always save the actual value, not the one passed as an argument
+ this.term = this._value();
+
+ if ( value.length < this.options.minLength ) {
+ return this.close( event );
+ }
+
+ if ( this._trigger( "search", event ) === false ) {
+ return;
+ }
+
+ return this._search( value );
+ },
+
+ _search: function( value ) {
+ this.pending++;
+ this.element.addClass( "ui-autocomplete-loading" );
+ this.cancelSearch = false;
+
+ this.source( { term: value }, this._response() );
+ },
+
+ _response: function() {
+ var that = this,
+ index = ++requestIndex;
+
+ return function( content ) {
+ if ( index === requestIndex ) {
+ that.__response( content );
+ }
+
+ that.pending--;
+ if ( !that.pending ) {
+ that.element.removeClass( "ui-autocomplete-loading" );
+ }
+ };
+ },
+
+ __response: function( content ) {
+ if ( content ) {
+ content = this._normalize( content );
+ }
+ this._trigger( "response", null, { content: content } );
+ if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
+ this._suggest( content );
+ this._trigger( "open" );
+ } else {
+ // use ._close() instead of .close() so we don't cancel future searches
+ this._close();
+ }
+ },
+
+ close: function( event ) {
+ this.cancelSearch = true;
+ this._close( event );
+ },
+
+ _close: function( event ) {
+ if ( this.menu.element.is( ":visible" ) ) {
+ this.menu.element.hide();
+ this.menu.blur();
+ this.isNewMenu = true;
+ this._trigger( "close", event );
+ }
+ },
+
+ _change: function( event ) {
+ if ( this.previous !== this._value() ) {
+ this._trigger( "change", event, { item: this.selectedItem } );
+ }
+ },
+
+ _normalize: function( items ) {
+ // assume all items have the right format when the first item is complete
+ if ( items.length && items[0].label && items[0].value ) {
+ return items;
+ }
+ return $.map( items, function( item ) {
+ if ( typeof item === "string" ) {
+ return {
+ label: item,
+ value: item
+ };
+ }
+ return $.extend({
+ label: item.label || item.value,
+ value: item.value || item.label
+ }, item );
+ });
+ },
+
+ _suggest: function( items ) {
+ var ul = this.menu.element
+ .empty()
+ .zIndex( this.element.zIndex() + 1 );
+ this._renderMenu( ul, items );
+ this.menu.refresh();
+
+ // size and position menu
+ ul.show();
+ this._resizeMenu();
+ ul.position( $.extend({
+ of: this.element
+ }, this.options.position ));
+
+ if ( this.options.autoFocus ) {
+ this.menu.next();
+ }
+ },
+
+ _resizeMenu: function() {
+ var ul = this.menu.element;
+ ul.outerWidth( Math.max(
+ // Firefox wraps long text (possibly a rounding bug)
+ // so we add 1px to avoid the wrapping (#7513)
+ ul.width( "" ).outerWidth() + 1,
+ this.element.outerWidth()
+ ) );
+ },
+
+ _renderMenu: function( ul, items ) {
+ var that = this;
+ $.each( items, function( index, item ) {
+ that._renderItemData( ul, item );
+ });
+ },
+
+ _renderItemData: function( ul, item ) {
+ return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
+ },
+
+ _renderItem: function( ul, item ) {
+ return $( "<li>" )
+ .append( $( "<a>" ).text( item.label ) )
+ .appendTo( ul );
+ },
+
+ _move: function( direction, event ) {
+ if ( !this.menu.element.is( ":visible" ) ) {
+ this.search( null, event );
+ return;
+ }
+ if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
+ this.menu.isLastItem() && /^next/.test( direction ) ) {
+ this._value( this.term );
+ this.menu.blur();
+ return;
+ }
+ this.menu[ direction ]( event );
+ },
+
+ widget: function() {
+ return this.menu.element;
+ },
+
+ _value: function() {
+ return this.valueMethod.apply( this.element, arguments );
+ },
+
+ _keyEvent: function( keyEvent, event ) {
+ if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
+ this._move( keyEvent, event );
+
+ // prevents moving cursor to beginning/end of the text field in some browsers
+ event.preventDefault();
+ }
+ }
+});
+
+$.extend( $.ui.autocomplete, {
+ escapeRegex: function( value ) {
+ return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
+ },
+ filter: function(array, term) {
+ var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
+ return $.grep( array, function(value) {
+ return matcher.test( value.label || value.value || value );
+ });
+ }
+});
+
+
+// live region extension, adding a `messages` option
+// NOTE: This is an experimental API. We are still investigating
+// a full solution for string manipulation and internationalization.
+$.widget( "ui.autocomplete", $.ui.autocomplete, {
+ options: {
+ messages: {
+ noResults: "No search results.",
+ results: function( amount ) {
+ return amount + ( amount > 1 ? " results are" : " result is" ) +
+ " available, use up and down arrow keys to navigate.";
+ }
+ }
+ },
+
+ __response: function( content ) {
+ var message;
+ this._superApply( arguments );
+ if ( this.options.disabled || this.cancelSearch ) {
+ return;
+ }
+ if ( content && content.length ) {
+ message = this.options.messages.results( content.length );
+ } else {
+ message = this.options.messages.noResults;
+ }
+ this.liveRegion.text( message );
+ }
+});
+
+
+}( jQuery ));
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.button.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.button.js
new file mode 100644
index 00000000..53cf6992
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.button.js
@@ -0,0 +1,418 @@
+/*!
+ * jQuery UI Button 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/button/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+var lastActive, startXPos, startYPos, clickDragged,
+ baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
+ stateClasses = "ui-state-hover ui-state-active ",
+ typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
+ formResetHandler = function() {
+ var buttons = $( this ).find( ":ui-button" );
+ setTimeout(function() {
+ buttons.button( "refresh" );
+ }, 1 );
+ },
+ radioGroup = function( radio ) {
+ var name = radio.name,
+ form = radio.form,
+ radios = $( [] );
+ if ( name ) {
+ if ( form ) {
+ radios = $( form ).find( "[name='" + name + "']" );
+ } else {
+ radios = $( "[name='" + name + "']", radio.ownerDocument )
+ .filter(function() {
+ return !this.form;
+ });
+ }
+ }
+ return radios;
+ };
+
+$.widget( "ui.button", {
+ version: "1.9.2",
+ defaultElement: "<button>",
+ options: {
+ disabled: null,
+ text: true,
+ label: null,
+ icons: {
+ primary: null,
+ secondary: null
+ }
+ },
+ _create: function() {
+ this.element.closest( "form" )
+ .unbind( "reset" + this.eventNamespace )
+ .bind( "reset" + this.eventNamespace, formResetHandler );
+
+ if ( typeof this.options.disabled !== "boolean" ) {
+ this.options.disabled = !!this.element.prop( "disabled" );
+ } else {
+ this.element.prop( "disabled", this.options.disabled );
+ }
+
+ this._determineButtonType();
+ this.hasTitle = !!this.buttonElement.attr( "title" );
+
+ var that = this,
+ options = this.options,
+ toggleButton = this.type === "checkbox" || this.type === "radio",
+ activeClass = !toggleButton ? "ui-state-active" : "",
+ focusClass = "ui-state-focus";
+
+ if ( options.label === null ) {
+ options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
+ }
+
+ this._hoverable( this.buttonElement );
+
+ this.buttonElement
+ .addClass( baseClasses )
+ .attr( "role", "button" )
+ .bind( "mouseenter" + this.eventNamespace, function() {
+ if ( options.disabled ) {
+ return;
+ }
+ if ( this === lastActive ) {
+ $( this ).addClass( "ui-state-active" );
+ }
+ })
+ .bind( "mouseleave" + this.eventNamespace, function() {
+ if ( options.disabled ) {
+ return;
+ }
+ $( this ).removeClass( activeClass );
+ })
+ .bind( "click" + this.eventNamespace, function( event ) {
+ if ( options.disabled ) {
+ event.preventDefault();
+ event.stopImmediatePropagation();
+ }
+ });
+
+ this.element
+ .bind( "focus" + this.eventNamespace, function() {
+ // no need to check disabled, focus won't be triggered anyway
+ that.buttonElement.addClass( focusClass );
+ })
+ .bind( "blur" + this.eventNamespace, function() {
+ that.buttonElement.removeClass( focusClass );
+ });
+
+ if ( toggleButton ) {
+ this.element.bind( "change" + this.eventNamespace, function() {
+ if ( clickDragged ) {
+ return;
+ }
+ that.refresh();
+ });
+ // if mouse moves between mousedown and mouseup (drag) set clickDragged flag
+ // prevents issue where button state changes but checkbox/radio checked state
+ // does not in Firefox (see ticket #6970)
+ this.buttonElement
+ .bind( "mousedown" + this.eventNamespace, function( event ) {
+ if ( options.disabled ) {
+ return;
+ }
+ clickDragged = false;
+ startXPos = event.pageX;
+ startYPos = event.pageY;
+ })
+ .bind( "mouseup" + this.eventNamespace, function( event ) {
+ if ( options.disabled ) {
+ return;
+ }
+ if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
+ clickDragged = true;
+ }
+ });
+ }
+
+ if ( this.type === "checkbox" ) {
+ this.buttonElement.bind( "click" + this.eventNamespace, function() {
+ if ( options.disabled || clickDragged ) {
+ return false;
+ }
+ $( this ).toggleClass( "ui-state-active" );
+ that.buttonElement.attr( "aria-pressed", that.element[0].checked );
+ });
+ } else if ( this.type === "radio" ) {
+ this.buttonElement.bind( "click" + this.eventNamespace, function() {
+ if ( options.disabled || clickDragged ) {
+ return false;
+ }
+ $( this ).addClass( "ui-state-active" );
+ that.buttonElement.attr( "aria-pressed", "true" );
+
+ var radio = that.element[ 0 ];
+ radioGroup( radio )
+ .not( radio )
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", "false" );
+ });
+ } else {
+ this.buttonElement
+ .bind( "mousedown" + this.eventNamespace, function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).addClass( "ui-state-active" );
+ lastActive = this;
+ that.document.one( "mouseup", function() {
+ lastActive = null;
+ });
+ })
+ .bind( "mouseup" + this.eventNamespace, function() {
+ if ( options.disabled ) {
+ return false;
+ }
+ $( this ).removeClass( "ui-state-active" );
+ })
+ .bind( "keydown" + this.eventNamespace, function(event) {
+ if ( options.disabled ) {
+ return false;
+ }
+ if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
+ $( this ).addClass( "ui-state-active" );
+ }
+ })
+ .bind( "keyup" + this.eventNamespace, function() {
+ $( this ).removeClass( "ui-state-active" );
+ });
+
+ if ( this.buttonElement.is("a") ) {
+ this.buttonElement.keyup(function(event) {
+ if ( event.keyCode === $.ui.keyCode.SPACE ) {
+ // TODO pass through original event correctly (just as 2nd argument doesn't work)
+ $( this ).click();
+ }
+ });
+ }
+ }
+
+ // TODO: pull out $.Widget's handling for the disabled option into
+ // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
+ // be overridden by individual plugins
+ this._setOption( "disabled", options.disabled );
+ this._resetButton();
+ },
+
+ _determineButtonType: function() {
+ var ancestor, labelSelector, checked;
+
+ if ( this.element.is("[type=checkbox]") ) {
+ this.type = "checkbox";
+ } else if ( this.element.is("[type=radio]") ) {
+ this.type = "radio";
+ } else if ( this.element.is("input") ) {
+ this.type = "input";
+ } else {
+ this.type = "button";
+ }
+
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ // we don't search against the document in case the element
+ // is disconnected from the DOM
+ ancestor = this.element.parents().last();
+ labelSelector = "label[for='" + this.element.attr("id") + "']";
+ this.buttonElement = ancestor.find( labelSelector );
+ if ( !this.buttonElement.length ) {
+ ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
+ this.buttonElement = ancestor.filter( labelSelector );
+ if ( !this.buttonElement.length ) {
+ this.buttonElement = ancestor.find( labelSelector );
+ }
+ }
+ this.element.addClass( "ui-helper-hidden-accessible" );
+
+ checked = this.element.is( ":checked" );
+ if ( checked ) {
+ this.buttonElement.addClass( "ui-state-active" );
+ }
+ this.buttonElement.prop( "aria-pressed", checked );
+ } else {
+ this.buttonElement = this.element;
+ }
+ },
+
+ widget: function() {
+ return this.buttonElement;
+ },
+
+ _destroy: function() {
+ this.element
+ .removeClass( "ui-helper-hidden-accessible" );
+ this.buttonElement
+ .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
+ .removeAttr( "role" )
+ .removeAttr( "aria-pressed" )
+ .html( this.buttonElement.find(".ui-button-text").html() );
+
+ if ( !this.hasTitle ) {
+ this.buttonElement.removeAttr( "title" );
+ }
+ },
+
+ _setOption: function( key, value ) {
+ this._super( key, value );
+ if ( key === "disabled" ) {
+ if ( value ) {
+ this.element.prop( "disabled", true );
+ } else {
+ this.element.prop( "disabled", false );
+ }
+ return;
+ }
+ this._resetButton();
+ },
+
+ refresh: function() {
+ //See #8237 & #8828
+ var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );
+
+ if ( isDisabled !== this.options.disabled ) {
+ this._setOption( "disabled", isDisabled );
+ }
+ if ( this.type === "radio" ) {
+ radioGroup( this.element[0] ).each(function() {
+ if ( $( this ).is( ":checked" ) ) {
+ $( this ).button( "widget" )
+ .addClass( "ui-state-active" )
+ .attr( "aria-pressed", "true" );
+ } else {
+ $( this ).button( "widget" )
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", "false" );
+ }
+ });
+ } else if ( this.type === "checkbox" ) {
+ if ( this.element.is( ":checked" ) ) {
+ this.buttonElement
+ .addClass( "ui-state-active" )
+ .attr( "aria-pressed", "true" );
+ } else {
+ this.buttonElement
+ .removeClass( "ui-state-active" )
+ .attr( "aria-pressed", "false" );
+ }
+ }
+ },
+
+ _resetButton: function() {
+ if ( this.type === "input" ) {
+ if ( this.options.label ) {
+ this.element.val( this.options.label );
+ }
+ return;
+ }
+ var buttonElement = this.buttonElement.removeClass( typeClasses ),
+ buttonText = $( "<span></span>", this.document[0] )
+ .addClass( "ui-button-text" )
+ .html( this.options.label )
+ .appendTo( buttonElement.empty() )
+ .text(),
+ icons = this.options.icons,
+ multipleIcons = icons.primary && icons.secondary,
+ buttonClasses = [];
+
+ if ( icons.primary || icons.secondary ) {
+ if ( this.options.text ) {
+ buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
+ }
+
+ if ( icons.primary ) {
+ buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
+ }
+
+ if ( icons.secondary ) {
+ buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
+ }
+
+ if ( !this.options.text ) {
+ buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
+
+ if ( !this.hasTitle ) {
+ buttonElement.attr( "title", $.trim( buttonText ) );
+ }
+ }
+ } else {
+ buttonClasses.push( "ui-button-text-only" );
+ }
+ buttonElement.addClass( buttonClasses.join( " " ) );
+ }
+});
+
+$.widget( "ui.buttonset", {
+ version: "1.9.2",
+ options: {
+ items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(button)"
+ },
+
+ _create: function() {
+ this.element.addClass( "ui-buttonset" );
+ },
+
+ _init: function() {
+ this.refresh();
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "disabled" ) {
+ this.buttons.button( "option", key, value );
+ }
+
+ this._super( key, value );
+ },
+
+ refresh: function() {
+ var rtl = this.element.css( "direction" ) === "rtl";
+
+ this.buttons = this.element.find( this.options.items )
+ .filter( ":ui-button" )
+ .button( "refresh" )
+ .end()
+ .not( ":ui-button" )
+ .button()
+ .end()
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
+ .filter( ":first" )
+ .addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
+ .end()
+ .filter( ":last" )
+ .addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
+ .end()
+ .end();
+ },
+
+ _destroy: function() {
+ this.element.removeClass( "ui-buttonset" );
+ this.buttons
+ .map(function() {
+ return $( this ).button( "widget" )[ 0 ];
+ })
+ .removeClass( "ui-corner-left ui-corner-right" )
+ .end()
+ .button( "destroy" );
+ }
+});
+
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.core.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.core.js
new file mode 100644
index 00000000..19f0069e
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.core.js
@@ -0,0 +1,356 @@
+/*!
+ * jQuery UI Core 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/category/ui-core/
+ */
+(function( $, undefined ) {
+
+var uuid = 0,
+ runiqueId = /^ui-id-\d+$/;
+
+// prevent duplicate loading
+// this is only a problem because we proxy existing functions
+// and we don't want to double proxy them
+$.ui = $.ui || {};
+if ( $.ui.version ) {
+ return;
+}
+
+$.extend( $.ui, {
+ version: "1.9.2",
+
+ keyCode: {
+ BACKSPACE: 8,
+ COMMA: 188,
+ DELETE: 46,
+ DOWN: 40,
+ END: 35,
+ ENTER: 13,
+ ESCAPE: 27,
+ HOME: 36,
+ LEFT: 37,
+ NUMPAD_ADD: 107,
+ NUMPAD_DECIMAL: 110,
+ NUMPAD_DIVIDE: 111,
+ NUMPAD_ENTER: 108,
+ NUMPAD_MULTIPLY: 106,
+ NUMPAD_SUBTRACT: 109,
+ PAGE_DOWN: 34,
+ PAGE_UP: 33,
+ PERIOD: 190,
+ RIGHT: 39,
+ SPACE: 32,
+ TAB: 9,
+ UP: 38
+ }
+});
+
+// plugins
+$.fn.extend({
+ _focus: $.fn.focus,
+ focus: function( delay, fn ) {
+ return typeof delay === "number" ?
+ this.each(function() {
+ var elem = this;
+ setTimeout(function() {
+ $( elem ).focus();
+ if ( fn ) {
+ fn.call( elem );
+ }
+ }, delay );
+ }) :
+ this._focus.apply( this, arguments );
+ },
+
+ scrollParent: function() {
+ var scrollParent;
+ if (($.ui.ie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
+ scrollParent = this.parents().filter(function() {
+ return (/(relative|absolute|fixed)/).test($.css(this,'position')) && (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
+ }).eq(0);
+ } else {
+ scrollParent = this.parents().filter(function() {
+ return (/(auto|scroll)/).test($.css(this,'overflow')+$.css(this,'overflow-y')+$.css(this,'overflow-x'));
+ }).eq(0);
+ }
+
+ return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
+ },
+
+ zIndex: function( zIndex ) {
+ if ( zIndex !== undefined ) {
+ return this.css( "zIndex", zIndex );
+ }
+
+ if ( this.length ) {
+ var elem = $( this[ 0 ] ), position, value;
+ while ( elem.length && elem[ 0 ] !== document ) {
+ // Ignore z-index if position is set to a value where z-index is ignored by the browser
+ // This makes behavior of this function consistent across browsers
+ // WebKit always returns auto if the element is positioned
+ position = elem.css( "position" );
+ if ( position === "absolute" || position === "relative" || position === "fixed" ) {
+ // IE returns 0 when zIndex is not specified
+ // other browsers return a string
+ // we ignore the case of nested elements with an explicit value of 0
+ // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
+ value = parseInt( elem.css( "zIndex" ), 10 );
+ if ( !isNaN( value ) && value !== 0 ) {
+ return value;
+ }
+ }
+ elem = elem.parent();
+ }
+ }
+
+ return 0;
+ },
+
+ uniqueId: function() {
+ return this.each(function() {
+ if ( !this.id ) {
+ this.id = "ui-id-" + (++uuid);
+ }
+ });
+ },
+
+ removeUniqueId: function() {
+ return this.each(function() {
+ if ( runiqueId.test( this.id ) ) {
+ $( this ).removeAttr( "id" );
+ }
+ });
+ }
+});
+
+// selectors
+function focusable( element, isTabIndexNotNaN ) {
+ var map, mapName, img,
+ nodeName = element.nodeName.toLowerCase();
+ if ( "area" === nodeName ) {
+ map = element.parentNode;
+ mapName = map.name;
+ if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
+ return false;
+ }
+ img = $( "img[usemap=#" + mapName + "]" )[0];
+ return !!img && visible( img );
+ }
+ return ( /input|select|textarea|button|object/.test( nodeName ) ?
+ !element.disabled :
+ "a" === nodeName ?
+ element.href || isTabIndexNotNaN :
+ isTabIndexNotNaN) &&
+ // the element and all of its ancestors must be visible
+ visible( element );
+}
+
+function visible( element ) {
+ return $.expr.filters.visible( element ) &&
+ !$( element ).parents().andSelf().filter(function() {
+ return $.css( this, "visibility" ) === "hidden";
+ }).length;
+}
+
+$.extend( $.expr.pseudos, {
+ data: $.expr.createPseudo ?
+ $.expr.createPseudo(function( dataName ) {
+ return function( elem ) {
+ return !!$.data( elem, dataName );
+ };
+ }) :
+ // support: jQuery <1.8
+ function( elem, i, match ) {
+ return !!$.data( elem, match[ 3 ] );
+ },
+
+ focusable: function( element ) {
+ return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
+ },
+
+ tabbable: function( element ) {
+ var tabIndex = $.attr( element, "tabindex" ),
+ isTabIndexNaN = isNaN( tabIndex );
+ return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
+ }
+});
+
+// support
+$(function() {
+ var body = document.body,
+ div = body.appendChild( div = document.createElement( "div" ) );
+
+ // access offsetHeight before setting the style to prevent a layout bug
+ // in IE 9 which causes the element to continue to take up space even
+ // after it is removed from the DOM (#8026)
+ div.offsetHeight;
+
+ $.extend( div.style, {
+ minHeight: "100px",
+ height: "auto",
+ padding: 0,
+ borderWidth: 0
+ });
+
+ $.support.minHeight = div.offsetHeight === 100;
+ $.support.selectstart = "onselectstart" in div;
+
+ // set display to none to avoid a layout bug in IE
+ // http://dev.jquery.com/ticket/4014
+ body.removeChild( div ).style.display = "none";
+});
+
+// support: jQuery <1.8
+if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
+ $.each( [ "Width", "Height" ], function( i, name ) {
+ var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
+ type = name.toLowerCase(),
+ orig = {
+ innerWidth: $.fn.innerWidth,
+ innerHeight: $.fn.innerHeight,
+ outerWidth: $.fn.outerWidth,
+ outerHeight: $.fn.outerHeight
+ };
+
+ function reduce( elem, size, border, margin ) {
+ $.each( side, function() {
+ size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
+ if ( border ) {
+ size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
+ }
+ if ( margin ) {
+ size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
+ }
+ });
+ return size;
+ }
+
+ $.fn[ "inner" + name ] = function( size ) {
+ if ( size === undefined ) {
+ return orig[ "inner" + name ].call( this );
+ }
+
+ return this.each(function() {
+ $( this ).css( type, reduce( this, size ) + "px" );
+ });
+ };
+
+ $.fn[ "outer" + name] = function( size, margin ) {
+ if ( typeof size !== "number" ) {
+ return orig[ "outer" + name ].call( this, size );
+ }
+
+ return this.each(function() {
+ $( this).css( type, reduce( this, size, true, margin ) + "px" );
+ });
+ };
+ });
+}
+
+// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
+if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
+ $.fn.removeData = (function( removeData ) {
+ return function( key ) {
+ if ( arguments.length ) {
+ return removeData.call( this, $.camelCase( key ) );
+ } else {
+ return removeData.call( this );
+ }
+ };
+ })( $.fn.removeData );
+}
+
+
+
+
+
+// deprecated
+
+(function() {
+ var uaMatch = /msie ([\w.]+)/.exec( navigator.userAgent.toLowerCase() ) || [];
+ $.ui.ie = uaMatch.length ? true : false;
+ $.ui.ie6 = parseFloat( uaMatch[ 1 ], 10 ) === 6;
+})();
+
+$.fn.extend({
+ disableSelection: function() {
+ return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
+ ".ui-disableSelection", function( event ) {
+ event.preventDefault();
+ });
+ },
+
+ enableSelection: function() {
+ return this.unbind( ".ui-disableSelection" );
+ }
+});
+
+$.extend( $.ui, {
+ // $.ui.plugin is deprecated. Use the proxy pattern instead.
+ plugin: {
+ add: function( module, option, set ) {
+ var i,
+ proto = $.ui[ module ].prototype;
+ for ( i in set ) {
+ proto.plugins[ i ] = proto.plugins[ i ] || [];
+ proto.plugins[ i ].push( [ option, set[ i ] ] );
+ }
+ },
+ call: function( instance, name, args ) {
+ var i,
+ set = instance.plugins[ name ];
+ if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
+ return;
+ }
+
+ for ( i = 0; i < set.length; i++ ) {
+ if ( instance.options[ set[ i ][ 0 ] ] ) {
+ set[ i ][ 1 ].apply( instance.element, args );
+ }
+ }
+ }
+ },
+
+ contains: $.contains,
+
+ // only used by resizable
+ hasScroll: function( el, a ) {
+
+ //If overflow is hidden, the element might have extra content, but the user wants to hide it
+ if ( $( el ).css( "overflow" ) === "hidden") {
+ return false;
+ }
+
+ var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
+ has = false;
+
+ if ( el[ scroll ] > 0 ) {
+ return true;
+ }
+
+ // TODO: determine which cases actually cause this to happen
+ // if the element doesn't have the scroll set, see if it's possible to
+ // set the scroll
+ el[ scroll ] = 1;
+ has = ( el[ scroll ] > 0 );
+ el[ scroll ] = 0;
+ return has;
+ },
+
+ // these are odd functions, fix the API or move into individual plugins
+ isOverAxis: function( x, reference, size ) {
+ //Determines when x coordinate is over "b" element axis
+ return ( x > reference ) && ( x < ( reference + size ) );
+ },
+ isOver: function( y, x, top, left, height, width ) {
+ //Determines when x, y coordinates is over "b" element
+ return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
+ }
+});
+
+})( jQuery );
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.datepicker.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.datepicker.js
new file mode 100644
index 00000000..cd5d4901
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.datepicker.js
@@ -0,0 +1,1846 @@
+/*!
+ * jQuery UI Datepicker 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/datepicker/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ */
+(function( $, undefined ) {
+
+$.extend($.ui, { datepicker: { version: "1.9.2" } });
+
+var PROP_NAME = 'datepicker';
+var dpuuid = new Date().getTime();
+var instActive;
+
+/* Date picker manager.
+ Use the singleton instance of this class, $.datepicker, to interact with the date picker.
+ Settings for (groups of) date pickers are maintained in an instance object,
+ allowing multiple different settings on the same page. */
+
+function Datepicker() {
+ this.debug = false; // Change this to true to start debugging
+ this._curInst = null; // The current instance in use
+ this._keyEvent = false; // If the last event was a key event
+ this._disabledInputs = []; // List of date picker inputs that have been disabled
+ this._datepickerShowing = false; // True if the popup picker is showing , false if not
+ this._inDialog = false; // True if showing within a "dialog", false if not
+ this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
+ this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
+ this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
+ this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
+ this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
+ this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
+ this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
+ this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
+ this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
+ this.regional = []; // Available regional settings, indexed by language code
+ this.regional[''] = { // Default regional settings
+ closeText: 'Done', // Display text for close link
+ prevText: 'Prev', // Display text for previous month link
+ nextText: 'Next', // Display text for next month link
+ currentText: 'Today', // Display text for current month link
+ monthNames: ['January','February','March','April','May','June',
+ 'July','August','September','October','November','December'], // Names of months for drop-down and formatting
+ monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
+ dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
+ dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
+ weekHeader: 'Wk', // Column header for week of the year
+ dateFormat: 'mm/dd/yy', // See format options on parseDate
+ firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
+ isRTL: false, // True if right-to-left language, false if left-to-right
+ showMonthAfterYear: false, // True if the year select precedes month, false for month then year
+ yearSuffix: '' // Additional text to append to the year in the month headers
+ };
+ this._defaults = { // Global defaults for all the date picker instances
+ showOn: 'focus', // 'focus' for popup on focus,
+ // 'button' for trigger button, or 'both' for either
+ showAnim: 'fadeIn', // Name of jQuery animation for popup
+ showOptions: {}, // Options for enhanced animations
+ defaultDate: null, // Used when field is blank: actual date,
+ // +/-number for offset from today, null for today
+ appendText: '', // Display text following the input box, e.g. showing the format
+ buttonText: '...', // Text for trigger button
+ buttonImage: '', // URL for trigger button image
+ buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
+ hideIfNoPrevNext: false, // True to hide next/previous month links
+ // if not applicable, false to just disable them
+ navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
+ gotoCurrent: false, // True if today link goes back to current selection instead
+ changeMonth: false, // True if month can be selected directly, false if only prev/next
+ changeYear: false, // True if year can be selected directly, false if only prev/next
+ yearRange: 'c-10:c+10', // Range of years to display in drop-down,
+ // either relative to today's year (-nn:+nn), relative to currently displayed year
+ // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
+ showOtherMonths: false, // True to show dates in other months, false to leave blank
+ selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
+ showWeek: false, // True to show week of the year, false to not show it
+ calculateWeek: this.iso8601Week, // How to calculate the week of the year,
+ // takes a Date and returns the number of the week for it
+ shortYearCutoff: '+10', // Short year values < this are in the current century,
+ // > this are in the previous century,
+ // string value starting with '+' for current year + value
+ minDate: null, // The earliest selectable date, or null for no limit
+ maxDate: null, // The latest selectable date, or null for no limit
+ duration: 'fast', // Duration of display/closure
+ beforeShowDay: null, // Function that takes a date and returns an array with
+ // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
+ // [2] = cell title (optional), e.g. $.datepicker.noWeekends
+ beforeShow: null, // Function that takes an input field and
+ // returns a set of custom settings for the date picker
+ onSelect: null, // Define a callback function when a date is selected
+ onChangeMonthYear: null, // Define a callback function when the month or year is changed
+ onClose: null, // Define a callback function when the datepicker is closed
+ numberOfMonths: 1, // Number of months to show at a time
+ showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
+ stepMonths: 1, // Number of months to step back/forward
+ stepBigMonths: 12, // Number of months to step back/forward for the big links
+ altField: '', // Selector for an alternate field to store selected dates into
+ altFormat: '', // The date format to use for the alternate field
+ constrainInput: true, // The input is constrained by the current date format
+ showButtonPanel: false, // True to show button panel, false to not show it
+ autoSize: false, // True to size the input for the date format, false to leave as is
+ disabled: false // The initial disabled state
+ };
+ $.extend(this._defaults, this.regional['']);
+ this.dpDiv = bindHover($('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'));
+}
+
+$.extend(Datepicker.prototype, {
+ /* Class name added to elements to indicate already configured with a date picker. */
+ markerClassName: 'hasDatepicker',
+
+ //Keep track of the maximum number of rows displayed (see #7043)
+ maxRows: 4,
+
+ /* Debug logging (if enabled). */
+ log: function () {
+ if (this.debug)
+ console.log.apply('', arguments);
+ },
+
+ // TODO rename to "widget" when switching to widget factory
+ _widgetDatepicker: function() {
+ return this.dpDiv;
+ },
+
+ /* Override the default settings for all instances of the date picker.
+ @param settings object - the new settings to use as defaults (anonymous object)
+ @return the manager object */
+ setDefaults: function(settings) {
+ extendRemove(this._defaults, settings || {});
+ return this;
+ },
+
+ /* Attach the date picker to a jQuery selection.
+ @param target element - the target input field or division or span
+ @param settings object - the new settings to use for this date picker instance (anonymous) */
+ _attachDatepicker: function(target, settings) {
+ // check for settings on the control itself - in namespace 'date:'
+ var inlineSettings = null;
+ for (var attrName in this._defaults) {
+ var attrValue = target.getAttribute('date:' + attrName);
+ if (attrValue) {
+ inlineSettings = inlineSettings || {};
+ try {
+ inlineSettings[attrName] = eval(attrValue);
+ } catch (err) {
+ inlineSettings[attrName] = attrValue;
+ }
+ }
+ }
+ var nodeName = target.nodeName.toLowerCase();
+ var inline = (nodeName == 'div' || nodeName == 'span');
+ if (!target.id) {
+ this.uuid += 1;
+ target.id = 'dp' + this.uuid;
+ }
+ var inst = this._newInst($(target), inline);
+ inst.settings = $.extend({}, settings || {}, inlineSettings || {});
+ if (nodeName == 'input') {
+ this._connectDatepicker(target, inst);
+ } else if (inline) {
+ this._inlineDatepicker(target, inst);
+ }
+ },
+
+ /* Create a new instance object. */
+ _newInst: function(target, inline) {
+ var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
+ return {id: id, input: target, // associated target
+ selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
+ drawMonth: 0, drawYear: 0, // month being drawn
+ inline: inline, // is datepicker inline or not
+ dpDiv: (!inline ? this.dpDiv : // presentation div
+ bindHover($('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>')))};
+ },
+
+ /* Attach the date picker to an input field. */
+ _connectDatepicker: function(target, inst) {
+ var input = $(target);
+ inst.append = $([]);
+ inst.trigger = $([]);
+ if (input.hasClass(this.markerClassName))
+ return;
+ this._attachments(input, inst);
+ input.addClass(this.markerClassName).keydown(this._doKeyDown).
+ keypress(this._doKeyPress).keyup(this._doKeyUp).
+ bind("setData.datepicker", function(event, key, value) {
+ inst.settings[key] = value;
+ }).bind("getData.datepicker", function(event, key) {
+ return this._get(inst, key);
+ });
+ this._autoSize(inst);
+ $.data(target, PROP_NAME, inst);
+ //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
+ if( inst.settings.disabled ) {
+ this._disableDatepicker( target );
+ }
+ },
+
+ /* Make attachments based on settings. */
+ _attachments: function(input, inst) {
+ var appendText = this._get(inst, 'appendText');
+ var isRTL = this._get(inst, 'isRTL');
+ if (inst.append)
+ inst.append.remove();
+ if (appendText) {
+ inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
+ input[isRTL ? 'before' : 'after'](inst.append);
+ }
+ input.unbind('focus', this._showDatepicker);
+ if (inst.trigger)
+ inst.trigger.remove();
+ var showOn = this._get(inst, 'showOn');
+ if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
+ input.focus(this._showDatepicker);
+ if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
+ var buttonText = this._get(inst, 'buttonText');
+ var buttonImage = this._get(inst, 'buttonImage');
+ inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
+ $('<img/>').addClass(this._triggerClass).
+ attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
+ $('<button type="button"></button>').addClass(this._triggerClass).
+ html(buttonImage == '' ? buttonText : $('<img/>').attr(
+ { src:buttonImage, alt:buttonText, title:buttonText })));
+ input[isRTL ? 'before' : 'after'](inst.trigger);
+ inst.trigger.click(function() {
+ if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
+ $.datepicker._hideDatepicker();
+ else if ($.datepicker._datepickerShowing && $.datepicker._lastInput != input[0]) {
+ $.datepicker._hideDatepicker();
+ $.datepicker._showDatepicker(input[0]);
+ } else
+ $.datepicker._showDatepicker(input[0]);
+ return false;
+ });
+ }
+ },
+
+ /* Apply the maximum length for the date format. */
+ _autoSize: function(inst) {
+ if (this._get(inst, 'autoSize') && !inst.inline) {
+ var date = new Date(2009, 12 - 1, 20); // Ensure double digits
+ var dateFormat = this._get(inst, 'dateFormat');
+ if (dateFormat.match(/[DM]/)) {
+ var findMax = function(names) {
+ var max = 0;
+ var maxI = 0;
+ for (var i = 0; i < names.length; i++) {
+ if (names[i].length > max) {
+ max = names[i].length;
+ maxI = i;
+ }
+ }
+ return maxI;
+ };
+ date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
+ 'monthNames' : 'monthNamesShort'))));
+ date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
+ 'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
+ }
+ inst.input.attr('size', this._formatDate(inst, date).length);
+ }
+ },
+
+ /* Attach an inline date picker to a div. */
+ _inlineDatepicker: function(target, inst) {
+ var divSpan = $(target);
+ if (divSpan.hasClass(this.markerClassName))
+ return;
+ divSpan.addClass(this.markerClassName).append(inst.dpDiv).
+ bind("setData.datepicker", function(event, key, value){
+ inst.settings[key] = value;
+ }).bind("getData.datepicker", function(event, key){
+ return this._get(inst, key);
+ });
+ $.data(target, PROP_NAME, inst);
+ this._setDate(inst, this._getDefaultDate(inst), true);
+ this._updateDatepicker(inst);
+ this._updateAlternate(inst);
+ //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
+ if( inst.settings.disabled ) {
+ this._disableDatepicker( target );
+ }
+ // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
+ // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
+ inst.dpDiv.css( "display", "block" );
+ },
+
+ /* Pop-up the date picker in a "dialog" box.
+ @param input element - ignored
+ @param date string or Date - the initial date to display
+ @param onSelect function - the function to call when a date is selected
+ @param settings object - update the dialog date picker instance's settings (anonymous object)
+ @param pos int[2] - coordinates for the dialog's position within the screen or
+ event - with x/y coordinates or
+ leave empty for default (screen centre)
+ @return the manager object */
+ _dialogDatepicker: function(input, date, onSelect, settings, pos) {
+ var inst = this._dialogInst; // internal instance
+ if (!inst) {
+ this.uuid += 1;
+ var id = 'dp' + this.uuid;
+ this._dialogInput = $('<input type="text" id="' + id +
+ '" style="position: absolute; top: -100px; width: 0px;"/>');
+ this._dialogInput.keydown(this._doKeyDown);
+ $('body').append(this._dialogInput);
+ inst = this._dialogInst = this._newInst(this._dialogInput, false);
+ inst.settings = {};
+ $.data(this._dialogInput[0], PROP_NAME, inst);
+ }
+ extendRemove(inst.settings, settings || {});
+ date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
+ this._dialogInput.val(date);
+
+ this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
+ if (!this._pos) {
+ var browserWidth = document.documentElement.clientWidth;
+ var browserHeight = document.documentElement.clientHeight;
+ var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
+ var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
+ this._pos = // should use actual width/height below
+ [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
+ }
+
+ // move input on screen for focus, but hidden behind dialog
+ this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
+ inst.settings.onSelect = onSelect;
+ this._inDialog = true;
+ this.dpDiv.addClass(this._dialogClass);
+ this._showDatepicker(this._dialogInput[0]);
+ if ($.blockUI)
+ $.blockUI(this.dpDiv);
+ $.data(this._dialogInput[0], PROP_NAME, inst);
+ return this;
+ },
+
+ /* Detach a datepicker from its control.
+ @param target element - the target input field or division or span */
+ _destroyDatepicker: function(target) {
+ var $target = $(target);
+ var inst = $.data(target, PROP_NAME);
+ if (!$target.hasClass(this.markerClassName)) {
+ return;
+ }
+ var nodeName = target.nodeName.toLowerCase();
+ $.removeData(target, PROP_NAME);
+ if (nodeName == 'input') {
+ inst.append.remove();
+ inst.trigger.remove();
+ $target.removeClass(this.markerClassName).
+ unbind('focus', this._showDatepicker).
+ unbind('keydown', this._doKeyDown).
+ unbind('keypress', this._doKeyPress).
+ unbind('keyup', this._doKeyUp);
+ } else if (nodeName == 'div' || nodeName == 'span')
+ $target.removeClass(this.markerClassName).empty();
+ },
+
+ /* Enable the date picker to a jQuery selection.
+ @param target element - the target input field or division or span */
+ _enableDatepicker: function(target) {
+ var $target = $(target);
+ var inst = $.data(target, PROP_NAME);
+ if (!$target.hasClass(this.markerClassName)) {
+ return;
+ }
+ var nodeName = target.nodeName.toLowerCase();
+ if (nodeName == 'input') {
+ target.disabled = false;
+ inst.trigger.filter('button').
+ each(function() { this.disabled = false; }).end().
+ filter('img').css({opacity: '1.0', cursor: ''});
+ }
+ else if (nodeName == 'div' || nodeName == 'span') {
+ var inline = $target.children('.' + this._inlineClass);
+ inline.children().removeClass('ui-state-disabled');
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
+ prop("disabled", false);
+ }
+ this._disabledInputs = $.map(this._disabledInputs,
+ function(value) { return (value == target ? null : value); }); // delete entry
+ },
+
+ /* Disable the date picker to a jQuery selection.
+ @param target element - the target input field or division or span */
+ _disableDatepicker: function(target) {
+ var $target = $(target);
+ var inst = $.data(target, PROP_NAME);
+ if (!$target.hasClass(this.markerClassName)) {
+ return;
+ }
+ var nodeName = target.nodeName.toLowerCase();
+ if (nodeName == 'input') {
+ target.disabled = true;
+ inst.trigger.filter('button').
+ each(function() { this.disabled = true; }).end().
+ filter('img').css({opacity: '0.5', cursor: 'default'});
+ }
+ else if (nodeName == 'div' || nodeName == 'span') {
+ var inline = $target.children('.' + this._inlineClass);
+ inline.children().addClass('ui-state-disabled');
+ inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
+ prop("disabled", true);
+ }
+ this._disabledInputs = $.map(this._disabledInputs,
+ function(value) { return (value == target ? null : value); }); // delete entry
+ this._disabledInputs[this._disabledInputs.length] = target;
+ },
+
+ /* Is the first field in a jQuery collection disabled as a datepicker?
+ @param target element - the target input field or division or span
+ @return boolean - true if disabled, false if enabled */
+ _isDisabledDatepicker: function(target) {
+ if (!target) {
+ return false;
+ }
+ for (var i = 0; i < this._disabledInputs.length; i++) {
+ if (this._disabledInputs[i] == target)
+ return true;
+ }
+ return false;
+ },
+
+ /* Retrieve the instance data for the target control.
+ @param target element - the target input field or division or span
+ @return object - the associated instance data
+ @throws error if a jQuery problem getting data */
+ _getInst: function(target) {
+ try {
+ return $.data(target, PROP_NAME);
+ }
+ catch (err) {
+ throw 'Missing instance data for this datepicker';
+ }
+ },
+
+ /* Update or retrieve the settings for a date picker attached to an input field or division.
+ @param target element - the target input field or division or span
+ @param name object - the new settings to update or
+ string - the name of the setting to change or retrieve,
+ when retrieving also 'all' for all instance settings or
+ 'defaults' for all global defaults
+ @param value any - the new value for the setting
+ (omit if above is an object or to retrieve a value) */
+ _optionDatepicker: function(target, name, value) {
+ var inst = this._getInst(target);
+ if (arguments.length == 2 && typeof name == 'string') {
+ return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
+ (inst ? (name == 'all' ? $.extend({}, inst.settings) :
+ this._get(inst, name)) : null));
+ }
+ var settings = name || {};
+ if (typeof name == 'string') {
+ settings = {};
+ settings[name] = value;
+ }
+ if (inst) {
+ if (this._curInst == inst) {
+ this._hideDatepicker();
+ }
+ var date = this._getDateDatepicker(target, true);
+ var minDate = this._getMinMaxDate(inst, 'min');
+ var maxDate = this._getMinMaxDate(inst, 'max');
+ extendRemove(inst.settings, settings);
+ // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
+ if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
+ inst.settings.minDate = this._formatDate(inst, minDate);
+ if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
+ inst.settings.maxDate = this._formatDate(inst, maxDate);
+ this._attachments($(target), inst);
+ this._autoSize(inst);
+ this._setDate(inst, date);
+ this._updateAlternate(inst);
+ this._updateDatepicker(inst);
+ }
+ },
+
+ // change method deprecated
+ _changeDatepicker: function(target, name, value) {
+ this._optionDatepicker(target, name, value);
+ },
+
+ /* Redraw the date picker attached to an input field or division.
+ @param target element - the target input field or division or span */
+ _refreshDatepicker: function(target) {
+ var inst = this._getInst(target);
+ if (inst) {
+ this._updateDatepicker(inst);
+ }
+ },
+
+ /* Set the dates for a jQuery selection.
+ @param target element - the target input field or division or span
+ @param date Date - the new date */
+ _setDateDatepicker: function(target, date) {
+ var inst = this._getInst(target);
+ if (inst) {
+ this._setDate(inst, date);
+ this._updateDatepicker(inst);
+ this._updateAlternate(inst);
+ }
+ },
+
+ /* Get the date(s) for the first entry in a jQuery selection.
+ @param target element - the target input field or division or span
+ @param noDefault boolean - true if no default date is to be used
+ @return Date - the current date */
+ _getDateDatepicker: function(target, noDefault) {
+ var inst = this._getInst(target);
+ if (inst && !inst.inline)
+ this._setDateFromField(inst, noDefault);
+ return (inst ? this._getDate(inst) : null);
+ },
+
+ /* Handle keystrokes. */
+ _doKeyDown: function(event) {
+ var inst = $.datepicker._getInst(event.target);
+ var handled = true;
+ var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
+ inst._keyEvent = true;
+ if ($.datepicker._datepickerShowing)
+ switch (event.keyCode) {
+ case 9: $.datepicker._hideDatepicker();
+ handled = false;
+ break; // hide on tab out
+ case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' +
+ $.datepicker._currentClass + ')', inst.dpDiv);
+ if (sel[0])
+ $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
+ var onSelect = $.datepicker._get(inst, 'onSelect');
+ if (onSelect) {
+ var dateStr = $.datepicker._formatDate(inst);
+
+ // trigger custom callback
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
+ }
+ else
+ $.datepicker._hideDatepicker();
+ return false; // don't submit the form
+ break; // select the value on enter
+ case 27: $.datepicker._hideDatepicker();
+ break; // hide on escape
+ case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ -$.datepicker._get(inst, 'stepBigMonths') :
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
+ break; // previous month/year on page up/+ ctrl
+ case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ +$.datepicker._get(inst, 'stepBigMonths') :
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
+ break; // next month/year on page down/+ ctrl
+ case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
+ handled = event.ctrlKey || event.metaKey;
+ break; // clear on ctrl or command +end
+ case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
+ handled = event.ctrlKey || event.metaKey;
+ break; // current on ctrl or command +home
+ case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
+ handled = event.ctrlKey || event.metaKey;
+ // -1 day on ctrl or command +left
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ -$.datepicker._get(inst, 'stepBigMonths') :
+ -$.datepicker._get(inst, 'stepMonths')), 'M');
+ // next month/year on alt +left on Mac
+ break;
+ case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
+ handled = event.ctrlKey || event.metaKey;
+ break; // -1 week on ctrl or command +up
+ case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
+ handled = event.ctrlKey || event.metaKey;
+ // +1 day on ctrl or command +right
+ if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
+ +$.datepicker._get(inst, 'stepBigMonths') :
+ +$.datepicker._get(inst, 'stepMonths')), 'M');
+ // next month/year on alt +right
+ break;
+ case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
+ handled = event.ctrlKey || event.metaKey;
+ break; // +1 week on ctrl or command +down
+ default: handled = false;
+ }
+ else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
+ $.datepicker._showDatepicker(this);
+ else {
+ handled = false;
+ }
+ if (handled) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ },
+
+ /* Filter entered characters - based on date format. */
+ _doKeyPress: function(event) {
+ var inst = $.datepicker._getInst(event.target);
+ if ($.datepicker._get(inst, 'constrainInput')) {
+ var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
+ var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
+ return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
+ }
+ },
+
+ /* Synchronise manual entry and field/alternate field. */
+ _doKeyUp: function(event) {
+ var inst = $.datepicker._getInst(event.target);
+ if (inst.input.val() != inst.lastVal) {
+ try {
+ var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
+ (inst.input ? inst.input.val() : null),
+ $.datepicker._getFormatConfig(inst));
+ if (date) { // only if valid
+ $.datepicker._setDateFromField(inst);
+ $.datepicker._updateAlternate(inst);
+ $.datepicker._updateDatepicker(inst);
+ }
+ }
+ catch (err) {
+ $.datepicker.log(err);
+ }
+ }
+ return true;
+ },
+
+ /* Pop-up the date picker for a given input field.
+ If false returned from beforeShow event handler do not show.
+ @param input element - the input field attached to the date picker or
+ event - if triggered by focus */
+ _showDatepicker: function(input) {
+ input = input.target || input;
+ if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
+ input = $('input', input.parentNode)[0];
+ if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
+ return;
+ var inst = $.datepicker._getInst(input);
+ if ($.datepicker._curInst && $.datepicker._curInst != inst) {
+ $.datepicker._curInst.dpDiv.stop(true, true);
+ if ( inst && $.datepicker._datepickerShowing ) {
+ $.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
+ }
+ }
+ var beforeShow = $.datepicker._get(inst, 'beforeShow');
+ var beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
+ if(beforeShowSettings === false){
+ //false
+ return;
+ }
+ extendRemove(inst.settings, beforeShowSettings);
+ inst.lastVal = null;
+ $.datepicker._lastInput = input;
+ $.datepicker._setDateFromField(inst);
+ if ($.datepicker._inDialog) // hide cursor
+ input.value = '';
+ if (!$.datepicker._pos) { // position below input
+ $.datepicker._pos = $.datepicker._findPos(input);
+ $.datepicker._pos[1] += input.offsetHeight; // add the height
+ }
+ var isFixed = false;
+ $(input).parents().each(function() {
+ isFixed |= $(this).css('position') == 'fixed';
+ return !isFixed;
+ });
+ var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
+ $.datepicker._pos = null;
+ //to avoid flashes on Firefox
+ inst.dpDiv.empty();
+ // determine sizing offscreen
+ inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
+ $.datepicker._updateDatepicker(inst);
+ // fix width for dynamic number of date pickers
+ // and adjust position before showing
+ offset = $.datepicker._checkOffset(inst, offset, isFixed);
+ inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
+ 'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
+ left: offset.left + 'px', top: offset.top + 'px'});
+ if (!inst.inline) {
+ var showAnim = $.datepicker._get(inst, 'showAnim');
+ var duration = $.datepicker._get(inst, 'duration');
+ var postProcess = function() {
+ var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
+ if( !! cover.length ){
+ var borders = $.datepicker._getBorders(inst.dpDiv);
+ cover.css({left: -borders[0], top: -borders[1],
+ width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
+ }
+ };
+ inst.dpDiv.zIndex($(input).zIndex()+1);
+ $.datepicker._datepickerShowing = true;
+
+ // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
+ if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )
+ inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
+ else
+ inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
+ if (!showAnim || !duration)
+ postProcess();
+ if (inst.input.is(':visible') && !inst.input.is(':disabled'))
+ inst.input.focus();
+ $.datepicker._curInst = inst;
+ }
+ },
+
+ /* Generate the date picker content. */
+ _updateDatepicker: function(inst) {
+ this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
+ var borders = $.datepicker._getBorders(inst.dpDiv);
+ instActive = inst; // for delegate hover events
+ inst.dpDiv.empty().append(this._generateHTML(inst));
+ this._attachHandlers(inst);
+ var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
+ if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
+ cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
+ }
+ inst.dpDiv.find('.' + this._dayOverClass + ' a').mouseover();
+ var numMonths = this._getNumberOfMonths(inst);
+ var cols = numMonths[1];
+ var width = 17;
+ inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
+ if (cols > 1)
+ inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
+ inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
+ 'Class']('ui-datepicker-multi');
+ inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
+ 'Class']('ui-datepicker-rtl');
+ if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
+ // #6694 - don't focus the input if it's already focused
+ // this breaks the change event in IE
+ inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
+ inst.input.focus();
+ // deffered render of the years select (to avoid flashes on Firefox)
+ if( inst.yearshtml ){
+ var origyearshtml = inst.yearshtml;
+ setTimeout(function(){
+ //assure that inst.yearshtml didn't change.
+ if( origyearshtml === inst.yearshtml && inst.yearshtml ){
+ inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
+ }
+ origyearshtml = inst.yearshtml = null;
+ }, 0);
+ }
+ },
+
+ /* Retrieve the size of left and top borders for an element.
+ @param elem (jQuery object) the element of interest
+ @return (number[2]) the left and top borders */
+ _getBorders: function(elem) {
+ var convert = function(value) {
+ return {thin: 1, medium: 2, thick: 3}[value] || value;
+ };
+ return [parseFloat(convert(elem.css('border-left-width'))),
+ parseFloat(convert(elem.css('border-top-width')))];
+ },
+
+ /* Check positioning to remain on screen. */
+ _checkOffset: function(inst, offset, isFixed) {
+ var dpWidth = inst.dpDiv.outerWidth();
+ var dpHeight = inst.dpDiv.outerHeight();
+ var inputWidth = inst.input ? inst.input.outerWidth() : 0;
+ var inputHeight = inst.input ? inst.input.outerHeight() : 0;
+ var viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft());
+ var viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());
+
+ offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
+ offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
+ offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
+
+ // now check if datepicker is showing outside window viewport - move to a better place if so.
+ offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
+ Math.abs(offset.left + dpWidth - viewWidth) : 0);
+ offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
+ Math.abs(dpHeight + inputHeight) : 0);
+
+ return offset;
+ },
+
+ /* Find an object's position on the screen. */
+ _findPos: function(obj) {
+ var inst = this._getInst(obj);
+ var isRTL = this._get(inst, 'isRTL');
+ while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
+ obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
+ }
+ var position = $(obj).offset();
+ return [position.left, position.top];
+ },
+
+ /* Hide the date picker from view.
+ @param input element - the input field attached to the date picker */
+ _hideDatepicker: function(input) {
+ var inst = this._curInst;
+ if (!inst || (input && inst != $.data(input, PROP_NAME)))
+ return;
+ if (this._datepickerShowing) {
+ var showAnim = this._get(inst, 'showAnim');
+ var duration = this._get(inst, 'duration');
+ var postProcess = function() {
+ $.datepicker._tidyDialog(inst);
+ };
+
+ // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
+ if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) )
+ inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
+ else
+ inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
+ (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
+ if (!showAnim)
+ postProcess();
+ this._datepickerShowing = false;
+ var onClose = this._get(inst, 'onClose');
+ if (onClose)
+ onClose.apply((inst.input ? inst.input[0] : null),
+ [(inst.input ? inst.input.val() : ''), inst]);
+ this._lastInput = null;
+ if (this._inDialog) {
+ this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
+ if ($.blockUI) {
+ $.unblockUI();
+ $('body').append(this.dpDiv);
+ }
+ }
+ this._inDialog = false;
+ }
+ },
+
+ /* Tidy up after a dialog display. */
+ _tidyDialog: function(inst) {
+ inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
+ },
+
+ /* Close date picker if clicked elsewhere. */
+ _checkExternalClick: function(event) {
+ if (!$.datepicker._curInst)
+ return;
+
+ var $target = $(event.target),
+ inst = $.datepicker._getInst($target[0]);
+
+ if ( ( ( $target[0].id != $.datepicker._mainDivId &&
+ $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
+ !$target.hasClass($.datepicker.markerClassName) &&
+ !$target.closest("." + $.datepicker._triggerClass).length &&
+ $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
+ ( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst != inst ) )
+ $.datepicker._hideDatepicker();
+ },
+
+ /* Adjust one of the date sub-fields. */
+ _adjustDate: function(id, offset, period) {
+ var target = $(id);
+ var inst = this._getInst(target[0]);
+ if (this._isDisabledDatepicker(target[0])) {
+ return;
+ }
+ this._adjustInstDate(inst, offset +
+ (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
+ period);
+ this._updateDatepicker(inst);
+ },
+
+ /* Action for current link. */
+ _gotoToday: function(id) {
+ var target = $(id);
+ var inst = this._getInst(target[0]);
+ if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
+ inst.selectedDay = inst.currentDay;
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth;
+ inst.drawYear = inst.selectedYear = inst.currentYear;
+ }
+ else {
+ var date = new Date();
+ inst.selectedDay = date.getDate();
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
+ inst.drawYear = inst.selectedYear = date.getFullYear();
+ }
+ this._notifyChange(inst);
+ this._adjustDate(target);
+ },
+
+ /* Action for selecting a new month/year. */
+ _selectMonthYear: function(id, select, period) {
+ var target = $(id);
+ var inst = this._getInst(target[0]);
+ inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
+ inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
+ parseInt(select.options[select.selectedIndex].value,10);
+ this._notifyChange(inst);
+ this._adjustDate(target);
+ },
+
+ /* Action for selecting a day. */
+ _selectDay: function(id, month, year, td) {
+ var target = $(id);
+ if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
+ return;
+ }
+ var inst = this._getInst(target[0]);
+ inst.selectedDay = inst.currentDay = $('a', td).html();
+ inst.selectedMonth = inst.currentMonth = month;
+ inst.selectedYear = inst.currentYear = year;
+ this._selectDate(id, this._formatDate(inst,
+ inst.currentDay, inst.currentMonth, inst.currentYear));
+ },
+
+ /* Erase the input field and hide the date picker. */
+ _clearDate: function(id) {
+ var target = $(id);
+ var inst = this._getInst(target[0]);
+ this._selectDate(target, '');
+ },
+
+ /* Update the input field with the selected date. */
+ _selectDate: function(id, dateStr) {
+ var target = $(id);
+ var inst = this._getInst(target[0]);
+ dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
+ if (inst.input)
+ inst.input.val(dateStr);
+ this._updateAlternate(inst);
+ var onSelect = this._get(inst, 'onSelect');
+ if (onSelect)
+ onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]); // trigger custom callback
+ else if (inst.input)
+ inst.input.trigger('change'); // fire the change event
+ if (inst.inline)
+ this._updateDatepicker(inst);
+ else {
+ this._hideDatepicker();
+ this._lastInput = inst.input[0];
+ if (typeof(inst.input[0]) != 'object')
+ inst.input.focus(); // restore focus
+ this._lastInput = null;
+ }
+ },
+
+ /* Update any alternate field to synchronise with the main field. */
+ _updateAlternate: function(inst) {
+ var altField = this._get(inst, 'altField');
+ if (altField) { // update alternate field too
+ var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
+ var date = this._getDate(inst);
+ var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
+ $(altField).each(function() { $(this).val(dateStr); });
+ }
+ },
+
+ /* Set as beforeShowDay function to prevent selection of weekends.
+ @param date Date - the date to customise
+ @return [boolean, string] - is this date selectable?, what is its CSS class? */
+ noWeekends: function(date) {
+ var day = date.getDay();
+ return [(day > 0 && day < 6), ''];
+ },
+
+ /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
+ @param date Date - the date to get the week for
+ @return number - the number of the week within the year that contains this date */
+ iso8601Week: function(date) {
+ var checkDate = new Date(date.getTime());
+ // Find Thursday of this week starting on Monday
+ checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
+ var time = checkDate.getTime();
+ checkDate.setMonth(0); // Compare with Jan 1
+ checkDate.setDate(1);
+ return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
+ },
+
+ /* Parse a string value into a date object.
+ See formatDate below for the possible formats.
+
+ @param format string - the expected format of the date
+ @param value string - the date in the above format
+ @param settings Object - attributes include:
+ shortYearCutoff number - the cutoff year for determining the century (optional)
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
+ dayNames string[7] - names of the days from Sunday (optional)
+ monthNamesShort string[12] - abbreviated names of the months (optional)
+ monthNames string[12] - names of the months (optional)
+ @return Date - the extracted date value or null if value is blank */
+ parseDate: function (format, value, settings) {
+ if (format == null || value == null)
+ throw 'Invalid arguments';
+ value = (typeof value == 'object' ? value.toString() : value + '');
+ if (value == '')
+ return null;
+ var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
+ var year = -1;
+ var month = -1;
+ var day = -1;
+ var doy = -1;
+ var literal = false;
+ // Check whether a format character is doubled
+ var lookAhead = function(match) {
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+ if (matches)
+ iFormat++;
+ return matches;
+ };
+ // Extract a number from the string value
+ var getNumber = function(match) {
+ var isDoubled = lookAhead(match);
+ var size = (match == '@' ? 14 : (match == '!' ? 20 :
+ (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
+ var digits = new RegExp('^\\d{1,' + size + '}');
+ var num = value.substring(iValue).match(digits);
+ if (!num)
+ throw 'Missing number at position ' + iValue;
+ iValue += num[0].length;
+ return parseInt(num[0], 10);
+ };
+ // Extract a name from the string value and convert to an index
+ var getName = function(match, shortNames, longNames) {
+ var names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
+ return [ [k, v] ];
+ }).sort(function (a, b) {
+ return -(a[1].length - b[1].length);
+ });
+ var index = -1;
+ $.each(names, function (i, pair) {
+ var name = pair[1];
+ if (value.substr(iValue, name.length).toLowerCase() == name.toLowerCase()) {
+ index = pair[0];
+ iValue += name.length;
+ return false;
+ }
+ });
+ if (index != -1)
+ return index + 1;
+ else
+ throw 'Unknown name at position ' + iValue;
+ };
+ // Confirm that a literal character matches the string value
+ var checkLiteral = function() {
+ if (value.charAt(iValue) != format.charAt(iFormat))
+ throw 'Unexpected literal at position ' + iValue;
+ iValue++;
+ };
+ var iValue = 0;
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
+ if (literal)
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+ literal = false;
+ else
+ checkLiteral();
+ else
+ switch (format.charAt(iFormat)) {
+ case 'd':
+ day = getNumber('d');
+ break;
+ case 'D':
+ getName('D', dayNamesShort, dayNames);
+ break;
+ case 'o':
+ doy = getNumber('o');
+ break;
+ case 'm':
+ month = getNumber('m');
+ break;
+ case 'M':
+ month = getName('M', monthNamesShort, monthNames);
+ break;
+ case 'y':
+ year = getNumber('y');
+ break;
+ case '@':
+ var date = new Date(getNumber('@'));
+ year = date.getFullYear();
+ month = date.getMonth() + 1;
+ day = date.getDate();
+ break;
+ case '!':
+ var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
+ year = date.getFullYear();
+ month = date.getMonth() + 1;
+ day = date.getDate();
+ break;
+ case "'":
+ if (lookAhead("'"))
+ checkLiteral();
+ else
+ literal = true;
+ break;
+ default:
+ checkLiteral();
+ }
+ }
+ if (iValue < value.length){
+ var extra = value.substr(iValue);
+ if (!/^\s+/.test(extra)) {
+ throw "Extra/unparsed characters found in date: " + extra;
+ }
+ }
+ if (year == -1)
+ year = new Date().getFullYear();
+ else if (year < 100)
+ year += new Date().getFullYear() - new Date().getFullYear() % 100 +
+ (year <= shortYearCutoff ? 0 : -100);
+ if (doy > -1) {
+ month = 1;
+ day = doy;
+ do {
+ var dim = this._getDaysInMonth(year, month - 1);
+ if (day <= dim)
+ break;
+ month++;
+ day -= dim;
+ } while (true);
+ }
+ var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
+ if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
+ throw 'Invalid date'; // E.g. 31/02/00
+ return date;
+ },
+
+ /* Standard date formats. */
+ ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
+ COOKIE: 'D, dd M yy',
+ ISO_8601: 'yy-mm-dd',
+ RFC_822: 'D, d M y',
+ RFC_850: 'DD, dd-M-y',
+ RFC_1036: 'D, d M y',
+ RFC_1123: 'D, d M yy',
+ RFC_2822: 'D, d M yy',
+ RSS: 'D, d M y', // RFC 822
+ TICKS: '!',
+ TIMESTAMP: '@',
+ W3C: 'yy-mm-dd', // ISO 8601
+
+ _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
+ Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
+
+ /* Format a date object into a string value.
+ The format can be combinations of the following:
+ d - day of month (no leading zero)
+ dd - day of month (two digit)
+ o - day of year (no leading zeros)
+ oo - day of year (three digit)
+ D - day name short
+ DD - day name long
+ m - month of year (no leading zero)
+ mm - month of year (two digit)
+ M - month name short
+ MM - month name long
+ y - year (two digit)
+ yy - year (four digit)
+ @ - Unix timestamp (ms since 01/01/1970)
+ ! - Windows ticks (100ns since 01/01/0001)
+ '...' - literal text
+ '' - single quote
+
+ @param format string - the desired format of the date
+ @param date Date - the date value to format
+ @param settings Object - attributes include:
+ dayNamesShort string[7] - abbreviated names of the days from Sunday (optional)
+ dayNames string[7] - names of the days from Sunday (optional)
+ monthNamesShort string[12] - abbreviated names of the months (optional)
+ monthNames string[12] - names of the months (optional)
+ @return string - the date in the above format */
+ formatDate: function (format, date, settings) {
+ if (!date)
+ return '';
+ var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
+ var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
+ var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
+ var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
+ // Check whether a format character is doubled
+ var lookAhead = function(match) {
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+ if (matches)
+ iFormat++;
+ return matches;
+ };
+ // Format a number, with leading zero if necessary
+ var formatNumber = function(match, value, len) {
+ var num = '' + value;
+ if (lookAhead(match))
+ while (num.length < len)
+ num = '0' + num;
+ return num;
+ };
+ // Format a name, short or long as requested
+ var formatName = function(match, value, shortNames, longNames) {
+ return (lookAhead(match) ? longNames[value] : shortNames[value]);
+ };
+ var output = '';
+ var literal = false;
+ if (date)
+ for (var iFormat = 0; iFormat < format.length; iFormat++) {
+ if (literal)
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+ literal = false;
+ else
+ output += format.charAt(iFormat);
+ else
+ switch (format.charAt(iFormat)) {
+ case 'd':
+ output += formatNumber('d', date.getDate(), 2);
+ break;
+ case 'D':
+ output += formatName('D', date.getDay(), dayNamesShort, dayNames);
+ break;
+ case 'o':
+ output += formatNumber('o',
+ Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
+ break;
+ case 'm':
+ output += formatNumber('m', date.getMonth() + 1, 2);
+ break;
+ case 'M':
+ output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
+ break;
+ case 'y':
+ output += (lookAhead('y') ? date.getFullYear() :
+ (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
+ break;
+ case '@':
+ output += date.getTime();
+ break;
+ case '!':
+ output += date.getTime() * 10000 + this._ticksTo1970;
+ break;
+ case "'":
+ if (lookAhead("'"))
+ output += "'";
+ else
+ literal = true;
+ break;
+ default:
+ output += format.charAt(iFormat);
+ }
+ }
+ return output;
+ },
+
+ /* Extract all possible characters from the date format. */
+ _possibleChars: function (format) {
+ var chars = '';
+ var literal = false;
+ // Check whether a format character is doubled
+ var lookAhead = function(match) {
+ var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
+ if (matches)
+ iFormat++;
+ return matches;
+ };
+ for (var iFormat = 0; iFormat < format.length; iFormat++)
+ if (literal)
+ if (format.charAt(iFormat) == "'" && !lookAhead("'"))
+ literal = false;
+ else
+ chars += format.charAt(iFormat);
+ else
+ switch (format.charAt(iFormat)) {
+ case 'd': case 'm': case 'y': case '@':
+ chars += '0123456789';
+ break;
+ case 'D': case 'M':
+ return null; // Accept anything
+ case "'":
+ if (lookAhead("'"))
+ chars += "'";
+ else
+ literal = true;
+ break;
+ default:
+ chars += format.charAt(iFormat);
+ }
+ return chars;
+ },
+
+ /* Get a setting value, defaulting if necessary. */
+ _get: function(inst, name) {
+ return inst.settings[name] !== undefined ?
+ inst.settings[name] : this._defaults[name];
+ },
+
+ /* Parse existing date and initialise date picker. */
+ _setDateFromField: function(inst, noDefault) {
+ if (inst.input.val() == inst.lastVal) {
+ return;
+ }
+ var dateFormat = this._get(inst, 'dateFormat');
+ var dates = inst.lastVal = inst.input ? inst.input.val() : null;
+ var date, defaultDate;
+ date = defaultDate = this._getDefaultDate(inst);
+ var settings = this._getFormatConfig(inst);
+ try {
+ date = this.parseDate(dateFormat, dates, settings) || defaultDate;
+ } catch (event) {
+ this.log(event);
+ dates = (noDefault ? '' : dates);
+ }
+ inst.selectedDay = date.getDate();
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
+ inst.drawYear = inst.selectedYear = date.getFullYear();
+ inst.currentDay = (dates ? date.getDate() : 0);
+ inst.currentMonth = (dates ? date.getMonth() : 0);
+ inst.currentYear = (dates ? date.getFullYear() : 0);
+ this._adjustInstDate(inst);
+ },
+
+ /* Retrieve the default date shown on opening. */
+ _getDefaultDate: function(inst) {
+ return this._restrictMinMax(inst,
+ this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
+ },
+
+ /* A date may be specified as an exact value or a relative one. */
+ _determineDate: function(inst, date, defaultDate) {
+ var offsetNumeric = function(offset) {
+ var date = new Date();
+ date.setDate(date.getDate() + offset);
+ return date;
+ };
+ var offsetString = function(offset) {
+ try {
+ return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
+ offset, $.datepicker._getFormatConfig(inst));
+ }
+ catch (e) {
+ // Ignore
+ }
+ var date = (offset.toLowerCase().match(/^c/) ?
+ $.datepicker._getDate(inst) : null) || new Date();
+ var year = date.getFullYear();
+ var month = date.getMonth();
+ var day = date.getDate();
+ var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
+ var matches = pattern.exec(offset);
+ while (matches) {
+ switch (matches[2] || 'd') {
+ case 'd' : case 'D' :
+ day += parseInt(matches[1],10); break;
+ case 'w' : case 'W' :
+ day += parseInt(matches[1],10) * 7; break;
+ case 'm' : case 'M' :
+ month += parseInt(matches[1],10);
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
+ break;
+ case 'y': case 'Y' :
+ year += parseInt(matches[1],10);
+ day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
+ break;
+ }
+ matches = pattern.exec(offset);
+ }
+ return new Date(year, month, day);
+ };
+ var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
+ (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
+ newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
+ if (newDate) {
+ newDate.setHours(0);
+ newDate.setMinutes(0);
+ newDate.setSeconds(0);
+ newDate.setMilliseconds(0);
+ }
+ return this._daylightSavingAdjust(newDate);
+ },
+
+ /* Handle switch to/from daylight saving.
+ Hours may be non-zero on daylight saving cut-over:
+ > 12 when midnight changeover, but then cannot generate
+ midnight datetime, so jump to 1AM, otherwise reset.
+ @param date (Date) the date to check
+ @return (Date) the corrected date */
+ _daylightSavingAdjust: function(date) {
+ if (!date) return null;
+ date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
+ return date;
+ },
+
+ /* Set the date(s) directly. */
+ _setDate: function(inst, date, noChange) {
+ var clear = !date;
+ var origMonth = inst.selectedMonth;
+ var origYear = inst.selectedYear;
+ var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
+ inst.selectedDay = inst.currentDay = newDate.getDate();
+ inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
+ inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
+ if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
+ this._notifyChange(inst);
+ this._adjustInstDate(inst);
+ if (inst.input) {
+ inst.input.val(clear ? '' : this._formatDate(inst));
+ }
+ },
+
+ /* Retrieve the date(s) directly. */
+ _getDate: function(inst) {
+ var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
+ this._daylightSavingAdjust(new Date(
+ inst.currentYear, inst.currentMonth, inst.currentDay)));
+ return startDate;
+ },
+
+ /* Attach the onxxx handlers. These are declared statically so
+ * they work with static code transformers like Caja.
+ */
+ _attachHandlers: function(inst) {
+ var stepMonths = this._get(inst, 'stepMonths');
+ var id = '#' + inst.id.replace( /\\\\/g, "\\" );
+ inst.dpDiv.find('[data-handler]').map(function () {
+ var handler = {
+ prev: function () {
+ window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, -stepMonths, 'M');
+ },
+ next: function () {
+ window['DP_jQuery_' + dpuuid].datepicker._adjustDate(id, +stepMonths, 'M');
+ },
+ hide: function () {
+ window['DP_jQuery_' + dpuuid].datepicker._hideDatepicker();
+ },
+ today: function () {
+ window['DP_jQuery_' + dpuuid].datepicker._gotoToday(id);
+ },
+ selectDay: function () {
+ window['DP_jQuery_' + dpuuid].datepicker._selectDay(id, +this.getAttribute('data-month'), +this.getAttribute('data-year'), this);
+ return false;
+ },
+ selectMonth: function () {
+ window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'M');
+ return false;
+ },
+ selectYear: function () {
+ window['DP_jQuery_' + dpuuid].datepicker._selectMonthYear(id, this, 'Y');
+ return false;
+ }
+ };
+ $(this).bind(this.getAttribute('data-event'), handler[this.getAttribute('data-handler')]);
+ });
+ },
+
+ /* Generate the HTML for the current state of the date picker. */
+ _generateHTML: function(inst) {
+ var today = new Date();
+ today = this._daylightSavingAdjust(
+ new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
+ var isRTL = this._get(inst, 'isRTL');
+ var showButtonPanel = this._get(inst, 'showButtonPanel');
+ var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
+ var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
+ var numMonths = this._getNumberOfMonths(inst);
+ var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
+ var stepMonths = this._get(inst, 'stepMonths');
+ var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
+ var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
+ new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
+ var minDate = this._getMinMaxDate(inst, 'min');
+ var maxDate = this._getMinMaxDate(inst, 'max');
+ var drawMonth = inst.drawMonth - showCurrentAtPos;
+ var drawYear = inst.drawYear;
+ if (drawMonth < 0) {
+ drawMonth += 12;
+ drawYear--;
+ }
+ if (maxDate) {
+ var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
+ maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
+ maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
+ while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
+ drawMonth--;
+ if (drawMonth < 0) {
+ drawMonth = 11;
+ drawYear--;
+ }
+ }
+ }
+ inst.drawMonth = drawMonth;
+ inst.drawYear = drawYear;
+ var prevText = this._get(inst, 'prevText');
+ prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
+ this._getFormatConfig(inst)));
+ var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
+ '<a class="ui-datepicker-prev ui-corner-all" data-handler="prev" data-event="click"' +
+ ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-prev ui-corner-all ui-state-disabled" title="'+ prevText +'"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>'));
+ var nextText = this._get(inst, 'nextText');
+ nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
+ this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
+ this._getFormatConfig(inst)));
+ var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
+ '<a class="ui-datepicker-next ui-corner-all" data-handler="next" data-event="click"' +
+ ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
+ (hideIfNoPrevNext ? '' : '<a class="ui-datepicker-next ui-corner-all ui-state-disabled" title="'+ nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>'));
+ var currentText = this._get(inst, 'currentText');
+ var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
+ currentText = (!navigationAsDateFormat ? currentText :
+ this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
+ var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" data-handler="hide" data-event="click">' +
+ this._get(inst, 'closeText') + '</button>' : '');
+ var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
+ (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" data-handler="today" data-event="click"' +
+ '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
+ var firstDay = parseInt(this._get(inst, 'firstDay'),10);
+ firstDay = (isNaN(firstDay) ? 0 : firstDay);
+ var showWeek = this._get(inst, 'showWeek');
+ var dayNames = this._get(inst, 'dayNames');
+ var dayNamesShort = this._get(inst, 'dayNamesShort');
+ var dayNamesMin = this._get(inst, 'dayNamesMin');
+ var monthNames = this._get(inst, 'monthNames');
+ var monthNamesShort = this._get(inst, 'monthNamesShort');
+ var beforeShowDay = this._get(inst, 'beforeShowDay');
+ var showOtherMonths = this._get(inst, 'showOtherMonths');
+ var selectOtherMonths = this._get(inst, 'selectOtherMonths');
+ var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
+ var defaultDate = this._getDefaultDate(inst);
+ var html = '';
+ for (var row = 0; row < numMonths[0]; row++) {
+ var group = '';
+ this.maxRows = 4;
+ for (var col = 0; col < numMonths[1]; col++) {
+ var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
+ var cornerClass = ' ui-corner-all';
+ var calender = '';
+ if (isMultiMonth) {
+ calender += '<div class="ui-datepicker-group';
+ if (numMonths[1] > 1)
+ switch (col) {
+ case 0: calender += ' ui-datepicker-group-first';
+ cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
+ case numMonths[1]-1: calender += ' ui-datepicker-group-last';
+ cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
+ default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
+ }
+ calender += '">';
+ }
+ calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
+ (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
+ (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
+ this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
+ row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
+ '</div><table class="ui-datepicker-calendar"><thead>' +
+ '<tr>';
+ var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
+ for (var dow = 0; dow < 7; dow++) { // days of the week
+ var day = (dow + firstDay) % 7;
+ thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
+ '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
+ }
+ calender += thead + '</tr></thead><tbody>';
+ var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
+ if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
+ inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
+ var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
+ var curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
+ var numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
+ this.maxRows = numRows;
+ var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
+ for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
+ calender += '<tr>';
+ var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
+ this._get(inst, 'calculateWeek')(printDate) + '</td>');
+ for (var dow = 0; dow < 7; dow++) { // create date picker days
+ var daySettings = (beforeShowDay ?
+ beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
+ var otherMonth = (printDate.getMonth() != drawMonth);
+ var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
+ (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
+ tbody += '<td class="' +
+ ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
+ (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
+ ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
+ (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
+ // or defaultDate is current printedDate and defaultDate is selectedDate
+ ' ' + this._dayOverClass : '') + // highlight selected day
+ (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') + // highlight unselectable days
+ (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
+ (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
+ (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
+ ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
+ (unselectable ? '' : ' data-handler="selectDay" data-event="click" data-month="' + printDate.getMonth() + '" data-year="' + printDate.getFullYear() + '"') + '>' + // actions
+ (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
+ (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
+ (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
+ (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
+ (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
+ '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
+ printDate.setDate(printDate.getDate() + 1);
+ printDate = this._daylightSavingAdjust(printDate);
+ }
+ calender += tbody + '</tr>';
+ }
+ drawMonth++;
+ if (drawMonth > 11) {
+ drawMonth = 0;
+ drawYear++;
+ }
+ calender += '</tbody></table>' + (isMultiMonth ? '</div>' +
+ ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
+ group += calender;
+ }
+ html += group;
+ }
+ html += buttonPanel + ($.ui.ie6 && !inst.inline ?
+ '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
+ inst._keyEvent = false;
+ return html;
+ },
+
+ /* Generate the month and year header. */
+ _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
+ secondary, monthNames, monthNamesShort) {
+ var changeMonth = this._get(inst, 'changeMonth');
+ var changeYear = this._get(inst, 'changeYear');
+ var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
+ var html = '<div class="ui-datepicker-title">';
+ var monthHtml = '';
+ // month selection
+ if (secondary || !changeMonth)
+ monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
+ else {
+ var inMinYear = (minDate && minDate.getFullYear() == drawYear);
+ var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
+ monthHtml += '<select class="ui-datepicker-month" data-handler="selectMonth" data-event="change">';
+ for (var month = 0; month < 12; month++) {
+ if ((!inMinYear || month >= minDate.getMonth()) &&
+ (!inMaxYear || month <= maxDate.getMonth()))
+ monthHtml += '<option value="' + month + '"' +
+ (month == drawMonth ? ' selected="selected"' : '') +
+ '>' + monthNamesShort[month] + '</option>';
+ }
+ monthHtml += '</select>';
+ }
+ if (!showMonthAfterYear)
+ html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
+ // year selection
+ if ( !inst.yearshtml ) {
+ inst.yearshtml = '';
+ if (secondary || !changeYear)
+ html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
+ else {
+ // determine range of years to display
+ var years = this._get(inst, 'yearRange').split(':');
+ var thisYear = new Date().getFullYear();
+ var determineYear = function(value) {
+ var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
+ (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
+ parseInt(value, 10)));
+ return (isNaN(year) ? thisYear : year);
+ };
+ var year = determineYear(years[0]);
+ var endYear = Math.max(year, determineYear(years[1] || ''));
+ year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
+ endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
+ inst.yearshtml += '<select class="ui-datepicker-year" data-handler="selectYear" data-event="change">';
+ for (; year <= endYear; year++) {
+ inst.yearshtml += '<option value="' + year + '"' +
+ (year == drawYear ? ' selected="selected"' : '') +
+ '>' + year + '</option>';
+ }
+ inst.yearshtml += '</select>';
+
+ html += inst.yearshtml;
+ inst.yearshtml = null;
+ }
+ }
+ html += this._get(inst, 'yearSuffix');
+ if (showMonthAfterYear)
+ html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
+ html += '</div>'; // Close datepicker_header
+ return html;
+ },
+
+ /* Adjust one of the date sub-fields. */
+ _adjustInstDate: function(inst, offset, period) {
+ var year = inst.drawYear + (period == 'Y' ? offset : 0);
+ var month = inst.drawMonth + (period == 'M' ? offset : 0);
+ var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
+ (period == 'D' ? offset : 0);
+ var date = this._restrictMinMax(inst,
+ this._daylightSavingAdjust(new Date(year, month, day)));
+ inst.selectedDay = date.getDate();
+ inst.drawMonth = inst.selectedMonth = date.getMonth();
+ inst.drawYear = inst.selectedYear = date.getFullYear();
+ if (period == 'M' || period == 'Y')
+ this._notifyChange(inst);
+ },
+
+ /* Ensure a date is within any min/max bounds. */
+ _restrictMinMax: function(inst, date) {
+ var minDate = this._getMinMaxDate(inst, 'min');
+ var maxDate = this._getMinMaxDate(inst, 'max');
+ var newDate = (minDate && date < minDate ? minDate : date);
+ newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
+ return newDate;
+ },
+
+ /* Notify change of month/year. */
+ _notifyChange: function(inst) {
+ var onChange = this._get(inst, 'onChangeMonthYear');
+ if (onChange)
+ onChange.apply((inst.input ? inst.input[0] : null),
+ [inst.selectedYear, inst.selectedMonth + 1, inst]);
+ },
+
+ /* Determine the number of months to show. */
+ _getNumberOfMonths: function(inst) {
+ var numMonths = this._get(inst, 'numberOfMonths');
+ return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
+ },
+
+ /* Determine the current maximum date - ensure no time components are set. */
+ _getMinMaxDate: function(inst, minMax) {
+ return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
+ },
+
+ /* Find the number of days in a given month. */
+ _getDaysInMonth: function(year, month) {
+ return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
+ },
+
+ /* Find the day of the week of the first of a month. */
+ _getFirstDayOfMonth: function(year, month) {
+ return new Date(year, month, 1).getDay();
+ },
+
+ /* Determines if we should allow a "next/prev" month display change. */
+ _canAdjustMonth: function(inst, offset, curYear, curMonth) {
+ var numMonths = this._getNumberOfMonths(inst);
+ var date = this._daylightSavingAdjust(new Date(curYear,
+ curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
+ if (offset < 0)
+ date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
+ return this._isInRange(inst, date);
+ },
+
+ /* Is the given date in the accepted range? */
+ _isInRange: function(inst, date) {
+ var minDate = this._getMinMaxDate(inst, 'min');
+ var maxDate = this._getMinMaxDate(inst, 'max');
+ return ((!minDate || date.getTime() >= minDate.getTime()) &&
+ (!maxDate || date.getTime() <= maxDate.getTime()));
+ },
+
+ /* Provide the configuration settings for formatting/parsing. */
+ _getFormatConfig: function(inst) {
+ var shortYearCutoff = this._get(inst, 'shortYearCutoff');
+ shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
+ new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
+ return {shortYearCutoff: shortYearCutoff,
+ dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
+ monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
+ },
+
+ /* Format the given date for display. */
+ _formatDate: function(inst, day, month, year) {
+ if (!day) {
+ inst.currentDay = inst.selectedDay;
+ inst.currentMonth = inst.selectedMonth;
+ inst.currentYear = inst.selectedYear;
+ }
+ var date = (day ? (typeof day == 'object' ? day :
+ this._daylightSavingAdjust(new Date(year, month, day))) :
+ this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
+ return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
+ }
+});
+
+/*
+ * Bind hover events for datepicker elements.
+ * Done via delegate so the binding only occurs once in the lifetime of the parent div.
+ * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
+ */
+function bindHover(dpDiv) {
+ var selector = 'button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a';
+ return dpDiv.delegate(selector, 'mouseout', function() {
+ $(this).removeClass('ui-state-hover');
+ if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
+ if (this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
+ })
+ .delegate(selector, 'mouseover', function(){
+ if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
+ $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
+ $(this).addClass('ui-state-hover');
+ if (this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
+ if (this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
+ }
+ });
+}
+
+/* jQuery extend now ignores nulls! */
+function extendRemove(target, props) {
+ $.extend(target, props);
+ for (var name in props)
+ if (props[name] == null || props[name] == undefined)
+ target[name] = props[name];
+ return target;
+};
+
+/* Invoke the datepicker functionality.
+ @param options string - a command, optionally followed by additional parameters or
+ Object - settings for attaching new datepicker functionality
+ @return jQuery object */
+$.fn.datepicker = function(options){
+
+ /* Verify an empty collection wasn't passed - Fixes #6976 */
+ if ( !this.length ) {
+ return this;
+ }
+
+ /* Initialise the date picker. */
+ if (!$.datepicker.initialized) {
+ $(document).mousedown($.datepicker._checkExternalClick).
+ find(document.body).append($.datepicker.dpDiv);
+ $.datepicker.initialized = true;
+ }
+
+ var otherArgs = Array.prototype.slice.call(arguments, 1);
+ if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
+ return $.datepicker['_' + options + 'Datepicker'].
+ apply($.datepicker, [this[0]].concat(otherArgs));
+ if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
+ return $.datepicker['_' + options + 'Datepicker'].
+ apply($.datepicker, [this[0]].concat(otherArgs));
+ return this.each(function() {
+ typeof options == 'string' ?
+ $.datepicker['_' + options + 'Datepicker'].
+ apply($.datepicker, [this].concat(otherArgs)) :
+ $.datepicker._attachDatepicker(this, options);
+ });
+};
+
+$.datepicker = new Datepicker(); // singleton instance
+$.datepicker.initialized = false;
+$.datepicker.uuid = new Date().getTime();
+$.datepicker.version = "1.9.2";
+
+// Workaround for #4055
+// Add another global to avoid noConflict issues with inline event handlers
+window['DP_jQuery_' + dpuuid] = $;
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.dialog.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.dialog.js
new file mode 100644
index 00000000..75a9e8f9
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.dialog.js
@@ -0,0 +1,858 @@
+/*!
+ * jQuery UI Dialog 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/dialog/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.button.js
+ * jquery.ui.draggable.js
+ * jquery.ui.mouse.js
+ * jquery.ui.position.js
+ * jquery.ui.resizable.js
+ */
+(function( $, undefined ) {
+
+var uiDialogClasses = "ui-dialog ui-widget ui-widget-content ui-corner-all ",
+ sizeRelatedOptions = {
+ buttons: true,
+ height: true,
+ maxHeight: true,
+ maxWidth: true,
+ minHeight: true,
+ minWidth: true,
+ width: true
+ },
+ resizableRelatedOptions = {
+ maxHeight: true,
+ maxWidth: true,
+ minHeight: true,
+ minWidth: true
+ };
+
+$.widget("ui.dialog", {
+ version: "1.9.2",
+ options: {
+ autoOpen: true,
+ buttons: {},
+ closeOnEscape: true,
+ closeText: "close",
+ dialogClass: "",
+ draggable: true,
+ hide: null,
+ height: "auto",
+ maxHeight: false,
+ maxWidth: false,
+ minHeight: 150,
+ minWidth: 150,
+ modal: false,
+ position: {
+ my: "center",
+ at: "center",
+ of: window,
+ collision: "fit",
+ // ensure that the titlebar is never outside the document
+ using: function( pos ) {
+ var topOffset = $( this ).css( pos ).offset().top;
+ if ( topOffset < 0 ) {
+ $( this ).css( "top", pos.top - topOffset );
+ }
+ }
+ },
+ resizable: true,
+ show: null,
+ stack: true,
+ title: "",
+ width: 300,
+ zIndex: 1000
+ },
+
+ _create: function() {
+ this.originalTitle = this.element.attr( "title" );
+ // #5742 - .attr() might return a DOMElement
+ if ( typeof this.originalTitle !== "string" ) {
+ this.originalTitle = "";
+ }
+ this.oldPosition = {
+ parent: this.element.parent(),
+ index: this.element.parent().children().index( this.element )
+ };
+ this.options.title = this.options.title || this.originalTitle;
+ var that = this,
+ options = this.options,
+
+ title = options.title || "&#160;",
+ uiDialog,
+ uiDialogTitlebar,
+ uiDialogTitlebarClose,
+ uiDialogTitle,
+ uiDialogButtonPane;
+
+ uiDialog = ( this.uiDialog = $( "<div>" ) )
+ .addClass( uiDialogClasses + options.dialogClass )
+ .css({
+ display: "none",
+ outline: 0, // TODO: move to stylesheet
+ zIndex: options.zIndex
+ })
+ // setting tabIndex makes the div focusable
+ .attr( "tabIndex", -1)
+ .keydown(function( event ) {
+ if ( options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
+ event.keyCode === $.ui.keyCode.ESCAPE ) {
+ that.close( event );
+ event.preventDefault();
+ }
+ })
+ .mousedown(function( event ) {
+ that.moveToTop( false, event );
+ })
+ .appendTo( "body" );
+
+ this.element
+ .show()
+ .removeAttr( "title" )
+ .addClass( "ui-dialog-content ui-widget-content" )
+ .appendTo( uiDialog );
+
+ uiDialogTitlebar = ( this.uiDialogTitlebar = $( "<div>" ) )
+ .addClass( "ui-dialog-titlebar ui-widget-header " +
+ "ui-corner-all ui-helper-clearfix" )
+ .bind( "mousedown", function() {
+ // Dialog isn't getting focus when dragging (#8063)
+ uiDialog.focus();
+ })
+ .prependTo( uiDialog );
+
+ uiDialogTitlebarClose = $( "<a href='#'></a>" )
+ .addClass( "ui-dialog-titlebar-close ui-corner-all" )
+ .attr( "role", "button" )
+ .click(function( event ) {
+ event.preventDefault();
+ that.close( event );
+ })
+ .appendTo( uiDialogTitlebar );
+
+ ( this.uiDialogTitlebarCloseText = $( "<span>" ) )
+ .addClass( "ui-icon ui-icon-closethick" )
+ .text( options.closeText )
+ .appendTo( uiDialogTitlebarClose );
+
+ uiDialogTitle = $( "<span>" )
+ .uniqueId()
+ .addClass( "ui-dialog-title" )
+ .html( title )
+ .prependTo( uiDialogTitlebar );
+
+ uiDialogButtonPane = ( this.uiDialogButtonPane = $( "<div>" ) )
+ .addClass( "ui-dialog-buttonpane ui-widget-content ui-helper-clearfix" );
+
+ ( this.uiButtonSet = $( "<div>" ) )
+ .addClass( "ui-dialog-buttonset" )
+ .appendTo( uiDialogButtonPane );
+
+ uiDialog.attr({
+ role: "dialog",
+ "aria-labelledby": uiDialogTitle.attr( "id" )
+ });
+
+ uiDialogTitlebar.find( "*" ).add( uiDialogTitlebar ).disableSelection();
+ this._hoverable( uiDialogTitlebarClose );
+ this._focusable( uiDialogTitlebarClose );
+
+ if ( options.draggable && $.fn.draggable ) {
+ this._makeDraggable();
+ }
+ if ( options.resizable && $.fn.resizable ) {
+ this._makeResizable();
+ }
+
+ this._createButtons( options.buttons );
+ this._isOpen = false;
+
+ if ( $.fn.bgiframe ) {
+ uiDialog.bgiframe();
+ }
+
+ // prevent tabbing out of modal dialogs
+ this._on( uiDialog, { keydown: function( event ) {
+ if ( !options.modal || event.keyCode !== $.ui.keyCode.TAB ) {
+ return;
+ }
+
+ var tabbables = $( ":tabbable", uiDialog ),
+ first = tabbables.filter( ":first" ),
+ last = tabbables.filter( ":last" );
+
+ if ( event.target === last[0] && !event.shiftKey ) {
+ first.focus( 1 );
+ return false;
+ } else if ( event.target === first[0] && event.shiftKey ) {
+ last.focus( 1 );
+ return false;
+ }
+ }});
+ },
+
+ _init: function() {
+ if ( this.options.autoOpen ) {
+ this.open();
+ }
+ },
+
+ _destroy: function() {
+ var next,
+ oldPosition = this.oldPosition;
+
+ if ( this.overlay ) {
+ this.overlay.destroy();
+ }
+ this.uiDialog.hide();
+ this.element
+ .removeClass( "ui-dialog-content ui-widget-content" )
+ .hide()
+ .appendTo( "body" );
+ this.uiDialog.remove();
+
+ if ( this.originalTitle ) {
+ this.element.attr( "title", this.originalTitle );
+ }
+
+ next = oldPosition.parent.children().eq( oldPosition.index );
+ // Don't try to place the dialog next to itself (#8613)
+ if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
+ next.before( this.element );
+ } else {
+ oldPosition.parent.append( this.element );
+ }
+ },
+
+ widget: function() {
+ return this.uiDialog;
+ },
+
+ close: function( event ) {
+ var that = this,
+ maxZ, thisZ;
+
+ if ( !this._isOpen ) {
+ return;
+ }
+
+ if ( false === this._trigger( "beforeClose", event ) ) {
+ return;
+ }
+
+ this._isOpen = false;
+
+ if ( this.overlay ) {
+ this.overlay.destroy();
+ }
+
+ if ( this.options.hide ) {
+ this._hide( this.uiDialog, this.options.hide, function() {
+ that._trigger( "close", event );
+ });
+ } else {
+ this.uiDialog.hide();
+ this._trigger( "close", event );
+ }
+
+ $.ui.dialog.overlay.resize();
+
+ // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
+ if ( this.options.modal ) {
+ maxZ = 0;
+ $( ".ui-dialog" ).each(function() {
+ if ( this !== that.uiDialog[0] ) {
+ thisZ = $( this ).css( "z-index" );
+ if ( !isNaN( thisZ ) ) {
+ maxZ = Math.max( maxZ, thisZ );
+ }
+ }
+ });
+ $.ui.dialog.maxZ = maxZ;
+ }
+
+ return this;
+ },
+
+ isOpen: function() {
+ return this._isOpen;
+ },
+
+ // the force parameter allows us to move modal dialogs to their correct
+ // position on open
+ moveToTop: function( force, event ) {
+ var options = this.options,
+ saveScroll;
+
+ if ( ( options.modal && !force ) ||
+ ( !options.stack && !options.modal ) ) {
+ return this._trigger( "focus", event );
+ }
+
+ if ( options.zIndex > $.ui.dialog.maxZ ) {
+ $.ui.dialog.maxZ = options.zIndex;
+ }
+ if ( this.overlay ) {
+ $.ui.dialog.maxZ += 1;
+ $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ;
+ this.overlay.$el.css( "z-index", $.ui.dialog.overlay.maxZ );
+ }
+
+ // Save and then restore scroll
+ // Opera 9.5+ resets when parent z-index is changed.
+ // http://bugs.jqueryui.com/ticket/3193
+ saveScroll = {
+ scrollTop: this.element.scrollTop(),
+ scrollLeft: this.element.scrollLeft()
+ };
+ $.ui.dialog.maxZ += 1;
+ this.uiDialog.css( "z-index", $.ui.dialog.maxZ );
+ this.element.attr( saveScroll );
+ this._trigger( "focus", event );
+
+ return this;
+ },
+
+ open: function() {
+ if ( this._isOpen ) {
+ return;
+ }
+
+ var hasFocus,
+ options = this.options,
+ uiDialog = this.uiDialog;
+
+ this._size();
+ this._position( options.position );
+ uiDialog.show( options.show );
+ this.overlay = options.modal ? new $.ui.dialog.overlay( this ) : null;
+ this.moveToTop( true );
+
+ // set focus to the first tabbable element in the content area or the first button
+ // if there are no tabbable elements, set focus on the dialog itself
+ hasFocus = this.element.find( ":tabbable" );
+ if ( !hasFocus.length ) {
+ hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
+ if ( !hasFocus.length ) {
+ hasFocus = uiDialog;
+ }
+ }
+ hasFocus.eq( 0 ).focus();
+
+ this._isOpen = true;
+ this._trigger( "open" );
+
+ return this;
+ },
+
+ _createButtons: function( buttons ) {
+ var that = this,
+ hasButtons = false;
+
+ // if we already have a button pane, remove it
+ this.uiDialogButtonPane.remove();
+ this.uiButtonSet.empty();
+
+ if ( typeof buttons === "object" && buttons !== null ) {
+ $.each( buttons, function() {
+ return !(hasButtons = true);
+ });
+ }
+ if ( hasButtons ) {
+ $.each( buttons, function( name, props ) {
+ var button, click;
+ props = $.isFunction( props ) ?
+ { click: props, text: name } :
+ props;
+ // Default to a non-submitting button
+ props = $.extend( { type: "button" }, props );
+ // Change the context for the click callback to be the main element
+ click = props.click;
+ props.click = function() {
+ click.apply( that.element[0], arguments );
+ };
+ button = $( "<button></button>", props )
+ .appendTo( that.uiButtonSet );
+ if ( $.fn.button ) {
+ button.button();
+ }
+ });
+ this.uiDialog.addClass( "ui-dialog-buttons" );
+ this.uiDialogButtonPane.appendTo( this.uiDialog );
+ } else {
+ this.uiDialog.removeClass( "ui-dialog-buttons" );
+ }
+ },
+
+ _makeDraggable: function() {
+ var that = this,
+ options = this.options;
+
+ function filteredUi( ui ) {
+ return {
+ position: ui.position,
+ offset: ui.offset
+ };
+ }
+
+ this.uiDialog.draggable({
+ cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
+ handle: ".ui-dialog-titlebar",
+ containment: "document",
+ start: function( event, ui ) {
+ $( this )
+ .addClass( "ui-dialog-dragging" );
+ that._trigger( "dragStart", event, filteredUi( ui ) );
+ },
+ drag: function( event, ui ) {
+ that._trigger( "drag", event, filteredUi( ui ) );
+ },
+ stop: function( event, ui ) {
+ options.position = [
+ ui.position.left - that.document.scrollLeft(),
+ ui.position.top - that.document.scrollTop()
+ ];
+ $( this )
+ .removeClass( "ui-dialog-dragging" );
+ that._trigger( "dragStop", event, filteredUi( ui ) );
+ $.ui.dialog.overlay.resize();
+ }
+ });
+ },
+
+ _makeResizable: function( handles ) {
+ handles = (handles === undefined ? this.options.resizable : handles);
+ var that = this,
+ options = this.options,
+ // .ui-resizable has position: relative defined in the stylesheet
+ // but dialogs have to use absolute or fixed positioning
+ position = this.uiDialog.css( "position" ),
+ resizeHandles = typeof handles === 'string' ?
+ handles :
+ "n,e,s,w,se,sw,ne,nw";
+
+ function filteredUi( ui ) {
+ return {
+ originalPosition: ui.originalPosition,
+ originalSize: ui.originalSize,
+ position: ui.position,
+ size: ui.size
+ };
+ }
+
+ this.uiDialog.resizable({
+ cancel: ".ui-dialog-content",
+ containment: "document",
+ alsoResize: this.element,
+ maxWidth: options.maxWidth,
+ maxHeight: options.maxHeight,
+ minWidth: options.minWidth,
+ minHeight: this._minHeight(),
+ handles: resizeHandles,
+ start: function( event, ui ) {
+ $( this ).addClass( "ui-dialog-resizing" );
+ that._trigger( "resizeStart", event, filteredUi( ui ) );
+ },
+ resize: function( event, ui ) {
+ that._trigger( "resize", event, filteredUi( ui ) );
+ },
+ stop: function( event, ui ) {
+ $( this ).removeClass( "ui-dialog-resizing" );
+ options.height = $( this ).height();
+ options.width = $( this ).width();
+ that._trigger( "resizeStop", event, filteredUi( ui ) );
+ $.ui.dialog.overlay.resize();
+ }
+ })
+ .css( "position", position )
+ .find( ".ui-resizable-se" )
+ .addClass( "ui-icon ui-icon-grip-diagonal-se" );
+ },
+
+ _minHeight: function() {
+ var options = this.options;
+
+ if ( options.height === "auto" ) {
+ return options.minHeight;
+ } else {
+ return Math.min( options.minHeight, options.height );
+ }
+ },
+
+ _position: function( position ) {
+ var myAt = [],
+ offset = [ 0, 0 ],
+ isVisible;
+
+ if ( position ) {
+ // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
+ // if (typeof position == 'string' || $.isArray(position)) {
+ // myAt = $.isArray(position) ? position : position.split(' ');
+
+ if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
+ myAt = position.split ? position.split( " " ) : [ position[ 0 ], position[ 1 ] ];
+ if ( myAt.length === 1 ) {
+ myAt[ 1 ] = myAt[ 0 ];
+ }
+
+ $.each( [ "left", "top" ], function( i, offsetPosition ) {
+ if ( +myAt[ i ] === myAt[ i ] ) {
+ offset[ i ] = myAt[ i ];
+ myAt[ i ] = offsetPosition;
+ }
+ });
+
+ position = {
+ my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
+ myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
+ at: myAt.join( " " )
+ };
+ }
+
+ position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
+ } else {
+ position = $.ui.dialog.prototype.options.position;
+ }
+
+ // need to show the dialog to get the actual offset in the position plugin
+ isVisible = this.uiDialog.is( ":visible" );
+ if ( !isVisible ) {
+ this.uiDialog.show();
+ }
+ this.uiDialog.position( position );
+ if ( !isVisible ) {
+ this.uiDialog.hide();
+ }
+ },
+
+ _setOptions: function( options ) {
+ var that = this,
+ resizableOptions = {},
+ resize = false;
+
+ $.each( options, function( key, value ) {
+ that._setOption( key, value );
+
+ if ( key in sizeRelatedOptions ) {
+ resize = true;
+ }
+ if ( key in resizableRelatedOptions ) {
+ resizableOptions[ key ] = value;
+ }
+ });
+
+ if ( resize ) {
+ this._size();
+ }
+ if ( this.uiDialog.is( ":data(resizable)" ) ) {
+ this.uiDialog.resizable( "option", resizableOptions );
+ }
+ },
+
+ _setOption: function( key, value ) {
+ var isDraggable, isResizable,
+ uiDialog = this.uiDialog;
+
+ switch ( key ) {
+ case "buttons":
+ this._createButtons( value );
+ break;
+ case "closeText":
+ // ensure that we always pass a string
+ this.uiDialogTitlebarCloseText.text( "" + value );
+ break;
+ case "dialogClass":
+ uiDialog
+ .removeClass( this.options.dialogClass )
+ .addClass( uiDialogClasses + value );
+ break;
+ case "disabled":
+ if ( value ) {
+ uiDialog.addClass( "ui-dialog-disabled" );
+ } else {
+ uiDialog.removeClass( "ui-dialog-disabled" );
+ }
+ break;
+ case "draggable":
+ isDraggable = uiDialog.is( ":data(draggable)" );
+ if ( isDraggable && !value ) {
+ uiDialog.draggable( "destroy" );
+ }
+
+ if ( !isDraggable && value ) {
+ this._makeDraggable();
+ }
+ break;
+ case "position":
+ this._position( value );
+ break;
+ case "resizable":
+ // currently resizable, becoming non-resizable
+ isResizable = uiDialog.is( ":data(resizable)" );
+ if ( isResizable && !value ) {
+ uiDialog.resizable( "destroy" );
+ }
+
+ // currently resizable, changing handles
+ if ( isResizable && typeof value === "string" ) {
+ uiDialog.resizable( "option", "handles", value );
+ }
+
+ // currently non-resizable, becoming resizable
+ if ( !isResizable && value !== false ) {
+ this._makeResizable( value );
+ }
+ break;
+ case "title":
+ // convert whatever was passed in o a string, for html() to not throw up
+ $( ".ui-dialog-title", this.uiDialogTitlebar )
+ .html( "" + ( value || "&#160;" ) );
+ break;
+ }
+
+ this._super( key, value );
+ },
+
+ _size: function() {
+ /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
+ * divs will both have width and height set, so we need to reset them
+ */
+ var nonContentHeight, minContentHeight, autoHeight,
+ options = this.options,
+ isVisible = this.uiDialog.is( ":visible" );
+
+ // reset content sizing
+ this.element.show().css({
+ width: "auto",
+ minHeight: 0,
+ height: 0
+ });
+
+ if ( options.minWidth > options.width ) {
+ options.width = options.minWidth;
+ }
+
+ // reset wrapper sizing
+ // determine the height of all the non-content elements
+ nonContentHeight = this.uiDialog.css({
+ height: "auto",
+ width: options.width
+ })
+ .outerHeight();
+ minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
+
+ if ( options.height === "auto" ) {
+ // only needed for IE6 support
+ if ( $.support.minHeight ) {
+ this.element.css({
+ minHeight: minContentHeight,
+ height: "auto"
+ });
+ } else {
+ this.uiDialog.show();
+ autoHeight = this.element.css( "height", "auto" ).height();
+ if ( !isVisible ) {
+ this.uiDialog.hide();
+ }
+ this.element.height( Math.max( autoHeight, minContentHeight ) );
+ }
+ } else {
+ this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
+ }
+
+ if (this.uiDialog.is( ":data(resizable)" ) ) {
+ this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
+ }
+ }
+});
+
+$.extend($.ui.dialog, {
+ uuid: 0,
+ maxZ: 0,
+
+ getTitleId: function($el) {
+ var id = $el.attr( "id" );
+ if ( !id ) {
+ this.uuid += 1;
+ id = this.uuid;
+ }
+ return "ui-dialog-title-" + id;
+ },
+
+ overlay: function( dialog ) {
+ this.$el = $.ui.dialog.overlay.create( dialog );
+ }
+});
+
+$.extend( $.ui.dialog.overlay, {
+ instances: [],
+ // reuse old instances due to IE memory leak with alpha transparency (see #5185)
+ oldInstances: [],
+ maxZ: 0,
+ events: $.map(
+ "focus,mousedown,mouseup,keydown,keypress,click".split( "," ),
+ function( event ) {
+ return event + ".dialog-overlay";
+ }
+ ).join( " " ),
+ create: function( dialog ) {
+ if ( this.instances.length === 0 ) {
+ // prevent use of anchors and inputs
+ // we use a setTimeout in case the overlay is created from an
+ // event that we're going to be cancelling (see #2804)
+ setTimeout(function() {
+ // handle $(el).dialog().dialog('close') (see #4065)
+ if ( $.ui.dialog.overlay.instances.length ) {
+ $( document ).bind( $.ui.dialog.overlay.events, function( event ) {
+ // stop events if the z-index of the target is < the z-index of the overlay
+ // we cannot return true when we don't want to cancel the event (#3523)
+ if ( $( event.target ).zIndex() < $.ui.dialog.overlay.maxZ ) {
+ return false;
+ }
+ });
+ }
+ }, 1 );
+
+ // handle window resize
+ $( window ).bind( "resize.dialog-overlay", $.ui.dialog.overlay.resize );
+ }
+
+ var $el = ( this.oldInstances.pop() || $( "<div>" ).addClass( "ui-widget-overlay" ) );
+
+ // allow closing by pressing the escape key
+ $( document ).bind( "keydown.dialog-overlay", function( event ) {
+ var instances = $.ui.dialog.overlay.instances;
+ // only react to the event if we're the top overlay
+ if ( instances.length !== 0 && instances[ instances.length - 1 ] === $el &&
+ dialog.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
+ event.keyCode === $.ui.keyCode.ESCAPE ) {
+
+ dialog.close( event );
+ event.preventDefault();
+ }
+ });
+
+ $el.appendTo( document.body ).css({
+ width: this.width(),
+ height: this.height()
+ });
+
+ if ( $.fn.bgiframe ) {
+ $el.bgiframe();
+ }
+
+ this.instances.push( $el );
+ return $el;
+ },
+
+ destroy: function( $el ) {
+ var indexOf = $.inArray( $el, this.instances ),
+ maxZ = 0;
+
+ if ( indexOf !== -1 ) {
+ this.oldInstances.push( this.instances.splice( indexOf, 1 )[ 0 ] );
+ }
+
+ if ( this.instances.length === 0 ) {
+ $( [ document, window ] ).unbind( ".dialog-overlay" );
+ }
+
+ $el.height( 0 ).width( 0 ).remove();
+
+ // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
+ $.each( this.instances, function() {
+ maxZ = Math.max( maxZ, this.css( "z-index" ) );
+ });
+ this.maxZ = maxZ;
+ },
+
+ height: function() {
+ var scrollHeight,
+ offsetHeight;
+ // handle IE
+ if ( $.ui.ie ) {
+ scrollHeight = Math.max(
+ document.documentElement.scrollHeight,
+ document.body.scrollHeight
+ );
+ offsetHeight = Math.max(
+ document.documentElement.offsetHeight,
+ document.body.offsetHeight
+ );
+
+ if ( scrollHeight < offsetHeight ) {
+ return $( window ).height() + "px";
+ } else {
+ return scrollHeight + "px";
+ }
+ // handle "good" browsers
+ } else {
+ return $( document ).height() + "px";
+ }
+ },
+
+ width: function() {
+ var scrollWidth,
+ offsetWidth;
+ // handle IE
+ if ( $.ui.ie ) {
+ scrollWidth = Math.max(
+ document.documentElement.scrollWidth,
+ document.body.scrollWidth
+ );
+ offsetWidth = Math.max(
+ document.documentElement.offsetWidth,
+ document.body.offsetWidth
+ );
+
+ if ( scrollWidth < offsetWidth ) {
+ return $( window ).width() + "px";
+ } else {
+ return scrollWidth + "px";
+ }
+ // handle "good" browsers
+ } else {
+ return $( document ).width() + "px";
+ }
+ },
+
+ resize: function() {
+ /* If the dialog is draggable and the user drags it past the
+ * right edge of the window, the document becomes wider so we
+ * need to stretch the overlay. If the user then drags the
+ * dialog back to the left, the document will become narrower,
+ * so we need to shrink the overlay to the appropriate size.
+ * This is handled by shrinking the overlay before setting it
+ * to the full document size.
+ */
+ var $overlays = $( [] );
+ $.each( $.ui.dialog.overlay.instances, function() {
+ $overlays = $overlays.add( this );
+ });
+
+ $overlays.css({
+ width: 0,
+ height: 0
+ }).css({
+ width: $.ui.dialog.overlay.width(),
+ height: $.ui.dialog.overlay.height()
+ });
+ }
+});
+
+$.extend( $.ui.dialog.overlay.prototype, {
+ destroy: function() {
+ $.ui.dialog.overlay.destroy( this.$el );
+ }
+});
+
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.draggable.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.draggable.js
new file mode 100644
index 00000000..723dbd49
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.draggable.js
@@ -0,0 +1,840 @@
+/*!
+ * jQuery UI Draggable 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/draggable/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.draggable", $.ui.mouse, {
+ version: "1.9.2",
+ widgetEventPrefix: "drag",
+ options: {
+ addClasses: true,
+ appendTo: "parent",
+ axis: false,
+ connectToSortable: false,
+ containment: false,
+ cursor: "auto",
+ cursorAt: false,
+ grid: false,
+ handle: false,
+ helper: "original",
+ iframeFix: false,
+ opacity: false,
+ refreshPositions: false,
+ revert: false,
+ revertDuration: 500,
+ scope: "default",
+ scroll: true,
+ scrollSensitivity: 20,
+ scrollSpeed: 20,
+ snap: false,
+ snapMode: "both",
+ snapTolerance: 20,
+ stack: false,
+ zIndex: false
+ },
+ _create: function() {
+
+ if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
+ this.element[0].style.position = 'relative';
+
+ (this.options.addClasses && this.element.addClass("ui-draggable"));
+ (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
+
+ this._mouseInit();
+
+ },
+
+ _destroy: function() {
+ this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
+ this._mouseDestroy();
+ },
+
+ _mouseCapture: function(event) {
+
+ var o = this.options;
+
+ // among others, prevent a drag on a resizable-handle
+ if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
+ return false;
+
+ //Quit if we're not on a valid handle
+ this.handle = this._getHandle(event);
+ if (!this.handle)
+ return false;
+
+ $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
+ $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
+ .css({
+ width: this.offsetWidth+"px", height: this.offsetHeight+"px",
+ position: "absolute", opacity: "0.001", zIndex: 1000
+ })
+ .css($(this).offset())
+ .appendTo("body");
+ });
+
+ return true;
+
+ },
+
+ _mouseStart: function(event) {
+
+ var o = this.options;
+
+ //Create and append the visible helper
+ this.helper = this._createHelper(event);
+
+ this.helper.addClass("ui-draggable-dragging");
+
+ //Cache the helper size
+ this._cacheHelperProportions();
+
+ //If ddmanager is used for droppables, set the global draggable
+ if($.ui.ddmanager)
+ $.ui.ddmanager.current = this;
+
+ /*
+ * - Position generation -
+ * This block generates everything position related - it's the core of draggables.
+ */
+
+ //Cache the margins of the original element
+ this._cacheMargins();
+
+ //Store the helper's css position
+ this.cssPosition = this.helper.css("position");
+ this.scrollParent = this.helper.scrollParent();
+
+ //The element's absolute position on the page minus margins
+ this.offset = this.positionAbs = this.element.offset();
+ this.offset = {
+ top: this.offset.top - this.margins.top,
+ left: this.offset.left - this.margins.left
+ };
+
+ $.extend(this.offset, {
+ click: { //Where the click happened, relative to the element
+ left: event.pageX - this.offset.left,
+ top: event.pageY - this.offset.top
+ },
+ parent: this._getParentOffset(),
+ relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
+ });
+
+ //Generate the original position
+ this.originalPageX = event.pageX;
+ this.originalPageY = event.pageY;
+ this.originalPosition = this.position = this._generatePosition(event);
+ // These lines where moved up to fix an issue with with draggable, revert and grid
+ // See: https://bugs.jqueryui.com/ticket/4696 and https://gerrit.wikimedia.org/r/#/c/333224
+ // this.originalPageX = event.pageX;
+ // this.originalPageY = event.pageY;
+
+ //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+ (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
+
+ //Set a containment if given in the options
+ if(o.containment)
+ this._setContainment();
+
+ //Trigger event + callbacks
+ if(this._trigger("start", event) === false) {
+ this._clear();
+ return false;
+ }
+
+ //Recache the helper size
+ this._cacheHelperProportions();
+
+ //Prepare the droppable offsets
+ if ($.ui.ddmanager && !o.dropBehaviour)
+ $.ui.ddmanager.prepareOffsets(this, event);
+
+
+ this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+
+ //If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
+ if ( $.ui.ddmanager ) $.ui.ddmanager.dragStart(this, event);
+
+ return true;
+ },
+
+ _mouseDrag: function(event, noPropagation) {
+
+ //Compute the helpers position
+ this.position = this._generatePosition(event);
+ this.positionAbs = this._convertPositionTo("absolute");
+
+ //Call plugins and callbacks and use the resulting position if something is returned
+ if (!noPropagation) {
+ var ui = this._uiHash();
+ if(this._trigger('drag', event, ui) === false) {
+ this._mouseUp({});
+ return false;
+ }
+ this.position = ui.position;
+ }
+
+ if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
+ if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
+ if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
+
+ return false;
+ },
+
+ _mouseStop: function(event) {
+
+ //If we are using droppables, inform the manager about the drop
+ var dropped = false;
+ if ($.ui.ddmanager && !this.options.dropBehaviour)
+ dropped = $.ui.ddmanager.drop(this, event);
+
+ //if a drop comes from outside (a sortable)
+ if(this.dropped) {
+ dropped = this.dropped;
+ this.dropped = false;
+ }
+
+ //if the original element is no longer in the DOM don't bother to continue (see #8269)
+ var element = this.element[0], elementInDom = false;
+ while ( element && (element = element.parentNode) ) {
+ if (element == document ) {
+ elementInDom = true;
+ }
+ }
+ if ( !elementInDom && this.options.helper === "original" )
+ return false;
+
+ if((this.options.revert == "invalid" && !dropped) || (this.options.revert == "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
+ var that = this;
+ $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
+ if(that._trigger("stop", event) !== false) {
+ that._clear();
+ }
+ });
+ } else {
+ if(this._trigger("stop", event) !== false) {
+ this._clear();
+ }
+ }
+
+ return false;
+ },
+
+ _mouseUp: function(event) {
+ //Remove frame helpers
+ $("div.ui-draggable-iframeFix").each(function() {
+ this.parentNode.removeChild(this);
+ });
+
+ //If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
+ if( $.ui.ddmanager ) $.ui.ddmanager.dragStop(this, event);
+
+ return $.ui.mouse.prototype._mouseUp.call(this, event);
+ },
+
+ cancel: function() {
+
+ if(this.helper.is(".ui-draggable-dragging")) {
+ this._mouseUp({});
+ } else {
+ this._clear();
+ }
+
+ return this;
+
+ },
+
+ _getHandle: function(event) {
+
+ var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
+ $(this.options.handle, this.element)
+ .find("*")
+ .andSelf()
+ .each(function() {
+ if(this == event.target) handle = true;
+ });
+
+ return handle;
+
+ },
+
+ _createHelper: function(event) {
+
+ var o = this.options;
+ var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
+
+ if(!helper.parents('body').length)
+ helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
+
+ if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
+ helper.css("position", "absolute");
+
+ return helper;
+
+ },
+
+ _adjustOffsetFromHelper: function(obj) {
+ if (typeof obj == 'string') {
+ obj = obj.split(' ');
+ }
+ if ($.isArray(obj)) {
+ obj = {left: +obj[0], top: +obj[1] || 0};
+ }
+ if ('left' in obj) {
+ this.offset.click.left = obj.left + this.margins.left;
+ }
+ if ('right' in obj) {
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+ }
+ if ('top' in obj) {
+ this.offset.click.top = obj.top + this.margins.top;
+ }
+ if ('bottom' in obj) {
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+ }
+ },
+
+ _getParentOffset: function() {
+
+ //Get the offsetParent and cache its position
+ this.offsetParent = this.helper.offsetParent();
+ var po = this.offsetParent.offset();
+
+ // This is a special case where we need to modify a offset calculated on start, since the following happened:
+ // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
+ // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
+ // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
+ if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
+ po.left += this.scrollParent.scrollLeft();
+ po.top += this.scrollParent.scrollTop();
+ }
+
+ if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
+ || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix
+ po = { top: 0, left: 0 };
+
+ return {
+ top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
+ left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
+ };
+
+ },
+
+ _getRelativeOffset: function() {
+
+ if(this.cssPosition == "relative") {
+ var p = this.element.position();
+ return {
+ top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
+ left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
+ };
+ } else {
+ return { top: 0, left: 0 };
+ }
+
+ },
+
+ _cacheMargins: function() {
+ this.margins = {
+ left: (parseInt(this.element.css("marginLeft"),10) || 0),
+ top: (parseInt(this.element.css("marginTop"),10) || 0),
+ right: (parseInt(this.element.css("marginRight"),10) || 0),
+ bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
+ };
+ },
+
+ _cacheHelperProportions: function() {
+ this.helperProportions = {
+ width: this.helper.outerWidth(),
+ height: this.helper.outerHeight()
+ };
+ },
+
+ _setContainment: function() {
+
+ var o = this.options;
+ if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
+ if(o.containment == 'document' || o.containment == 'window') this.containment = [
+ o.containment == 'document' ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
+ o.containment == 'document' ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
+ (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
+ (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
+ ];
+
+ if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
+ var c = $(o.containment);
+ var ce = c[0]; if(!ce) return;
+ var co = c.offset();
+ var over = ($(ce).css("overflow") != 'hidden');
+
+ this.containment = [
+ (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
+ (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
+ (over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
+ (over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top - this.margins.bottom
+ ];
+ this.relative_container = c;
+
+ } else if(o.containment.constructor == Array) {
+ this.containment = o.containment;
+ }
+
+ },
+
+ _convertPositionTo: function(d, pos) {
+
+ if(!pos) pos = this.position;
+ var mod = d == "absolute" ? 1 : -1;
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+ return {
+ top: (
+ pos.top // The absolute mouse position
+ + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
+ - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
+ ),
+ left: (
+ pos.left // The absolute mouse position
+ + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
+ - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
+ )
+ };
+
+ },
+
+ _generatePosition: function(event) {
+
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+ var pageX = event.pageX;
+ var pageY = event.pageY;
+
+ /*
+ * - Position constraining -
+ * Constrain the position to a mix of grid, containment.
+ */
+
+ if(this.originalPosition) { //If we are not dragging yet, we won't check for options
+ var containment;
+ if(this.containment) {
+ if (this.relative_container){
+ var co = this.relative_container.offset();
+ containment = [ this.containment[0] + co.left,
+ this.containment[1] + co.top,
+ this.containment[2] + co.left,
+ this.containment[3] + co.top ];
+ }
+ else {
+ containment = this.containment;
+ }
+
+ if(event.pageX - this.offset.click.left < containment[0]) pageX = containment[0] + this.offset.click.left;
+ if(event.pageY - this.offset.click.top < containment[1]) pageY = containment[1] + this.offset.click.top;
+ if(event.pageX - this.offset.click.left > containment[2]) pageX = containment[2] + this.offset.click.left;
+ if(event.pageY - this.offset.click.top > containment[3]) pageY = containment[3] + this.offset.click.top;
+ }
+
+ if(o.grid) {
+ //Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
+ var top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
+ pageY = containment ? (!(top - this.offset.click.top < containment[1] || top - this.offset.click.top > containment[3]) ? top : (!(top - this.offset.click.top < containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
+
+ var left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
+ pageX = containment ? (!(left - this.offset.click.left < containment[0] || left - this.offset.click.left > containment[2]) ? left : (!(left - this.offset.click.left < containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
+ }
+
+ }
+
+ return {
+ top: (
+ pageY // The absolute mouse position
+ - this.offset.click.top // Click offset (relative to the element)
+ - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
+ - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
+ + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
+ ),
+ left: (
+ pageX // The absolute mouse position
+ - this.offset.click.left // Click offset (relative to the element)
+ - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
+ - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
+ + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
+ )
+ };
+
+ },
+
+ _clear: function() {
+ this.helper.removeClass("ui-draggable-dragging");
+ if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
+ //if($.ui.ddmanager) $.ui.ddmanager.current = null;
+ this.helper = null;
+ this.cancelHelperRemoval = false;
+ },
+
+ // From now on bulk stuff - mainly helpers
+
+ _trigger: function(type, event, ui) {
+ ui = ui || this._uiHash();
+ $.ui.plugin.call(this, type, [event, ui]);
+ if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
+ return $.Widget.prototype._trigger.call(this, type, event, ui);
+ },
+
+ plugins: {},
+
+ _uiHash: function(event) {
+ return {
+ helper: this.helper,
+ position: this.position,
+ originalPosition: this.originalPosition,
+ offset: this.positionAbs
+ };
+ }
+
+});
+
+$.ui.plugin.add("draggable", "connectToSortable", {
+ start: function(event, ui) {
+
+ var inst = $(this).data("draggable"), o = inst.options,
+ uiSortable = $.extend({}, ui, { item: inst.element });
+ inst.sortables = [];
+ $(o.connectToSortable).each(function() {
+ var sortable = $.data(this, 'sortable');
+ if (sortable && !sortable.options.disabled) {
+ inst.sortables.push({
+ instance: sortable,
+ shouldRevert: sortable.options.revert
+ });
+ sortable.refreshPositions(); // Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
+ sortable._trigger("activate", event, uiSortable);
+ }
+ });
+
+ },
+ stop: function(event, ui) {
+
+ //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
+ var inst = $(this).data("draggable"),
+ uiSortable = $.extend({}, ui, { item: inst.element });
+
+ $.each(inst.sortables, function() {
+ if(this.instance.isOver) {
+
+ this.instance.isOver = 0;
+
+ inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
+ this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
+
+ //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
+ if(this.shouldRevert) this.instance.options.revert = true;
+
+ //Trigger the stop of the sortable
+ this.instance._mouseStop(event);
+
+ this.instance.options.helper = this.instance.options._helper;
+
+ //If the helper has been the original item, restore properties in the sortable
+ if(inst.options.helper == 'original')
+ this.instance.currentItem.css({ top: 'auto', left: 'auto' });
+
+ } else {
+ this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
+ this.instance._trigger("deactivate", event, uiSortable);
+ }
+
+ });
+
+ },
+ drag: function(event, ui) {
+
+ var inst = $(this).data("draggable"), that = this;
+
+ var checkPos = function(o) {
+ var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
+ var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
+ var itemHeight = o.height, itemWidth = o.width;
+ var itemTop = o.top, itemLeft = o.left;
+
+ return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
+ };
+
+ $.each(inst.sortables, function(i) {
+
+ var innermostIntersecting = false;
+ var thisSortable = this;
+ //Copy over some variables to allow calling the sortable's native _intersectsWith
+ this.instance.positionAbs = inst.positionAbs;
+ this.instance.helperProportions = inst.helperProportions;
+ this.instance.offset.click = inst.offset.click;
+
+ if(this.instance._intersectsWith(this.instance.containerCache)) {
+ innermostIntersecting = true;
+ $.each(inst.sortables, function () {
+ this.instance.positionAbs = inst.positionAbs;
+ this.instance.helperProportions = inst.helperProportions;
+ this.instance.offset.click = inst.offset.click;
+ if (this != thisSortable
+ && this.instance._intersectsWith(this.instance.containerCache)
+ && $.ui.contains(thisSortable.instance.element[0], this.instance.element[0]))
+ innermostIntersecting = false;
+ return innermostIntersecting;
+ });
+ }
+
+
+ if(innermostIntersecting) {
+ //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
+ if(!this.instance.isOver) {
+
+ this.instance.isOver = 1;
+ //Now we fake the start of dragging for the sortable instance,
+ //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
+ //We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
+ this.instance.currentItem = $(that).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
+ this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
+ this.instance.options.helper = function() { return ui.helper[0]; };
+
+ event.target = this.instance.currentItem[0];
+ this.instance._mouseCapture(event, true);
+ this.instance._mouseStart(event, true, true);
+
+ //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
+ this.instance.offset.click.top = inst.offset.click.top;
+ this.instance.offset.click.left = inst.offset.click.left;
+ this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
+ this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
+
+ inst._trigger("toSortable", event);
+ inst.dropped = this.instance.element; //draggable revert needs that
+ //hack so receive/update callbacks work (mostly)
+ inst.currentItem = inst.element;
+ this.instance.fromOutside = inst;
+
+ }
+
+ //Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
+ if(this.instance.currentItem) this.instance._mouseDrag(event);
+
+ } else {
+
+ //If it doesn't intersect with the sortable, and it intersected before,
+ //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
+ if(this.instance.isOver) {
+
+ this.instance.isOver = 0;
+ this.instance.cancelHelperRemoval = true;
+
+ //Prevent reverting on this forced stop
+ this.instance.options.revert = false;
+
+ // The out event needs to be triggered independently
+ this.instance._trigger('out', event, this.instance._uiHash(this.instance));
+
+ this.instance._mouseStop(event, true);
+ this.instance.options.helper = this.instance.options._helper;
+
+ //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
+ this.instance.currentItem.remove();
+ if(this.instance.placeholder) this.instance.placeholder.remove();
+
+ inst._trigger("fromSortable", event);
+ inst.dropped = false; //draggable revert needs that
+ }
+
+ };
+
+ });
+
+ }
+});
+
+$.ui.plugin.add("draggable", "cursor", {
+ start: function(event, ui) {
+ var t = $('body'), o = $(this).data('draggable').options;
+ if (t.css("cursor")) o._cursor = t.css("cursor");
+ t.css("cursor", o.cursor);
+ },
+ stop: function(event, ui) {
+ var o = $(this).data('draggable').options;
+ if (o._cursor) $('body').css("cursor", o._cursor);
+ }
+});
+
+$.ui.plugin.add("draggable", "opacity", {
+ start: function(event, ui) {
+ var t = $(ui.helper), o = $(this).data('draggable').options;
+ if(t.css("opacity")) o._opacity = t.css("opacity");
+ t.css('opacity', o.opacity);
+ },
+ stop: function(event, ui) {
+ var o = $(this).data('draggable').options;
+ if(o._opacity) $(ui.helper).css('opacity', o._opacity);
+ }
+});
+
+$.ui.plugin.add("draggable", "scroll", {
+ start: function(event, ui) {
+ var i = $(this).data("draggable");
+ if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
+ },
+ drag: function(event, ui) {
+
+ var i = $(this).data("draggable"), o = i.options, scrolled = false;
+
+ if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
+
+ if(!o.axis || o.axis != 'x') {
+ if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
+ i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
+ else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
+ i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
+ }
+
+ if(!o.axis || o.axis != 'y') {
+ if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
+ i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
+ else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
+ i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
+ }
+
+ } else {
+
+ if(!o.axis || o.axis != 'x') {
+ if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
+ scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
+ else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
+ scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
+ }
+
+ if(!o.axis || o.axis != 'y') {
+ if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
+ else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
+ }
+
+ }
+
+ if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
+ $.ui.ddmanager.prepareOffsets(i, event);
+
+ }
+});
+
+$.ui.plugin.add("draggable", "snap", {
+ start: function(event, ui) {
+
+ var i = $(this).data("draggable"), o = i.options;
+ i.snapElements = [];
+
+ $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
+ var $t = $(this); var $o = $t.offset();
+ if(this != i.element[0]) i.snapElements.push({
+ item: this,
+ width: $t.outerWidth(), height: $t.outerHeight(),
+ top: $o.top, left: $o.left
+ });
+ });
+
+ },
+ drag: function(event, ui) {
+
+ var inst = $(this).data("draggable"), o = inst.options;
+ var d = o.snapTolerance;
+
+ var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
+ y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
+
+ for (var i = inst.snapElements.length - 1; i >= 0; i--){
+
+ var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
+ t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
+
+ //Yes, I know, this is insane ;)
+ if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
+ if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
+ inst.snapElements[i].snapping = false;
+ continue;
+ }
+
+ if(o.snapMode != 'inner') {
+ var ts = Math.abs(t - y2) <= d;
+ var bs = Math.abs(b - y1) <= d;
+ var ls = Math.abs(l - x2) <= d;
+ var rs = Math.abs(r - x1) <= d;
+ if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
+ if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
+ if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
+ if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
+ }
+
+ var first = (ts || bs || ls || rs);
+
+ if(o.snapMode != 'outer') {
+ var ts = Math.abs(t - y1) <= d;
+ var bs = Math.abs(b - y2) <= d;
+ var ls = Math.abs(l - x1) <= d;
+ var rs = Math.abs(r - x2) <= d;
+ if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
+ if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
+ if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
+ if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
+ }
+
+ if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
+ (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
+ inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
+
+ };
+
+ }
+});
+
+$.ui.plugin.add("draggable", "stack", {
+ start: function(event, ui) {
+
+ var o = $(this).data("draggable").options;
+
+ var group = $.makeArray($(o.stack)).sort(function(a,b) {
+ return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
+ });
+ if (!group.length) { return; }
+
+ var min = parseInt(group[0].style.zIndex) || 0;
+ $(group).each(function(i) {
+ this.style.zIndex = min + i;
+ });
+
+ this[0].style.zIndex = min + group.length;
+
+ }
+});
+
+$.ui.plugin.add("draggable", "zIndex", {
+ start: function(event, ui) {
+ var t = $(ui.helper), o = $(this).data("draggable").options;
+ if(t.css("zIndex")) o._zIndex = t.css("zIndex");
+ t.css('zIndex', o.zIndex);
+ },
+ stop: function(event, ui) {
+ var o = $(this).data("draggable").options;
+ if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
+ }
+});
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.droppable.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.droppable.js
new file mode 100644
index 00000000..1e9ea513
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.droppable.js
@@ -0,0 +1,294 @@
+/*!
+ * jQuery UI Droppable 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/droppable/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.mouse.js
+ * jquery.ui.draggable.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.droppable", {
+ version: "1.9.2",
+ widgetEventPrefix: "drop",
+ options: {
+ accept: '*',
+ activeClass: false,
+ addClasses: true,
+ greedy: false,
+ hoverClass: false,
+ scope: 'default',
+ tolerance: 'intersect'
+ },
+ _create: function() {
+
+ var o = this.options, accept = o.accept;
+ this.isover = 0; this.isout = 1;
+
+ this.accept = $.isFunction(accept) ? accept : function(d) {
+ return d.is(accept);
+ };
+
+ //Store the droppable's proportions
+ this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
+
+ // Add the reference and positions to the manager
+ $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
+ $.ui.ddmanager.droppables[o.scope].push(this);
+
+ (o.addClasses && this.element.addClass("ui-droppable"));
+
+ },
+
+ _destroy: function() {
+ var drop = $.ui.ddmanager.droppables[this.options.scope];
+ for ( var i = 0; i < drop.length; i++ )
+ if ( drop[i] == this )
+ drop.splice(i, 1);
+
+ this.element.removeClass("ui-droppable ui-droppable-disabled");
+ },
+
+ _setOption: function(key, value) {
+
+ if(key == 'accept') {
+ this.accept = $.isFunction(value) ? value : function(d) {
+ return d.is(value);
+ };
+ }
+ $.Widget.prototype._setOption.apply(this, arguments);
+ },
+
+ _activate: function(event) {
+ var draggable = $.ui.ddmanager.current;
+ if(this.options.activeClass) this.element.addClass(this.options.activeClass);
+ (draggable && this._trigger('activate', event, this.ui(draggable)));
+ },
+
+ _deactivate: function(event) {
+ var draggable = $.ui.ddmanager.current;
+ if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
+ (draggable && this._trigger('deactivate', event, this.ui(draggable)));
+ },
+
+ _over: function(event) {
+
+ var draggable = $.ui.ddmanager.current;
+ if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
+
+ if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
+ this._trigger('over', event, this.ui(draggable));
+ }
+
+ },
+
+ _out: function(event) {
+
+ var draggable = $.ui.ddmanager.current;
+ if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
+
+ if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
+ this._trigger('out', event, this.ui(draggable));
+ }
+
+ },
+
+ _drop: function(event,custom) {
+
+ var draggable = custom || $.ui.ddmanager.current;
+ if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
+
+ var childrenIntersection = false;
+ this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
+ var inst = $.data(this, 'droppable');
+ if(
+ inst.options.greedy
+ && !inst.options.disabled
+ && inst.options.scope == draggable.options.scope
+ && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
+ && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
+ ) { childrenIntersection = true; return false; }
+ });
+ if(childrenIntersection) return false;
+
+ if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
+ if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
+ this._trigger('drop', event, this.ui(draggable));
+ return this.element;
+ }
+
+ return false;
+
+ },
+
+ ui: function(c) {
+ return {
+ draggable: (c.currentItem || c.element),
+ helper: c.helper,
+ position: c.position,
+ offset: c.positionAbs
+ };
+ }
+
+});
+
+$.ui.intersect = function(draggable, droppable, toleranceMode) {
+
+ if (!droppable.offset) return false;
+
+ var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
+ y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
+ var l = droppable.offset.left, r = l + droppable.proportions.width,
+ t = droppable.offset.top, b = t + droppable.proportions.height;
+
+ switch (toleranceMode) {
+ case 'fit':
+ return (l <= x1 && x2 <= r
+ && t <= y1 && y2 <= b);
+ break;
+ case 'intersect':
+ return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
+ && x2 - (draggable.helperProportions.width / 2) < r // Left Half
+ && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
+ && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
+ break;
+ case 'pointer':
+ var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
+ draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
+ isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
+ return isOver;
+ break;
+ case 'touch':
+ return (
+ (y1 >= t && y1 <= b) || // Top edge touching
+ (y2 >= t && y2 <= b) || // Bottom edge touching
+ (y1 < t && y2 > b) // Surrounded vertically
+ ) && (
+ (x1 >= l && x1 <= r) || // Left edge touching
+ (x2 >= l && x2 <= r) || // Right edge touching
+ (x1 < l && x2 > r) // Surrounded horizontally
+ );
+ break;
+ default:
+ return false;
+ break;
+ }
+
+};
+
+/*
+ This manager tracks offsets of draggables and droppables
+*/
+$.ui.ddmanager = {
+ current: null,
+ droppables: { 'default': [] },
+ prepareOffsets: function(t, event) {
+
+ var m = $.ui.ddmanager.droppables[t.options.scope] || [];
+ var type = event ? event.type : null; // workaround for #2317
+ var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
+
+ droppablesLoop: for (var i = 0; i < m.length; i++) {
+
+ if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue; //No disabled and non-accepted
+ for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
+ m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue; //If the element is not visible, continue
+
+ if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
+
+ m[i].offset = m[i].element.offset();
+ m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
+
+ }
+
+ },
+ drop: function(draggable, event) {
+
+ var dropped = false;
+ $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
+
+ if(!this.options) return;
+ if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
+ dropped = this._drop.call(this, event) || dropped;
+
+ if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
+ this.isout = 1; this.isover = 0;
+ this._deactivate.call(this, event);
+ }
+
+ });
+ return dropped;
+
+ },
+ dragStart: function( draggable, event ) {
+ //Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
+ draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
+ if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
+ });
+ },
+ drag: function(draggable, event) {
+
+ //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
+ if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
+
+ //Run through all droppables and check their positions based on specific tolerance options
+ $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
+
+ if(this.options.disabled || this.greedyChild || !this.visible) return;
+ var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
+
+ var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
+ if(!c) return;
+
+ var parentInstance;
+ if (this.options.greedy) {
+ // find droppable parents with same scope
+ var scope = this.options.scope;
+ var parent = this.element.parents(':data(droppable)').filter(function () {
+ return $.data(this, 'droppable').options.scope === scope;
+ });
+
+ if (parent.length) {
+ parentInstance = $.data(parent[0], 'droppable');
+ parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
+ }
+ }
+
+ // we just moved into a greedy child
+ if (parentInstance && c == 'isover') {
+ parentInstance['isover'] = 0;
+ parentInstance['isout'] = 1;
+ parentInstance._out.call(parentInstance, event);
+ }
+
+ this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
+ this[c == "isover" ? "_over" : "_out"].call(this, event);
+
+ // we just moved out of a greedy child
+ if (parentInstance && c == 'isout') {
+ parentInstance['isout'] = 0;
+ parentInstance['isover'] = 1;
+ parentInstance._over.call(parentInstance, event);
+ }
+ });
+
+ },
+ dragStop: function( draggable, event ) {
+ draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
+ //Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
+ if( !draggable.options.refreshPositions ) $.ui.ddmanager.prepareOffsets( draggable, event );
+ }
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-blind.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-blind.js
new file mode 100644
index 00000000..e5c7331a
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-blind.js
@@ -0,0 +1,82 @@
+/*!
+ * jQuery UI Effects Blind 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/blind-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+var rvertical = /up|down|vertical/,
+ rpositivemotion = /up|left|vertical|horizontal/;
+
+$.effects.effect.blind = function( o, done ) {
+ // Create element
+ var el = $( this ),
+ props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
+ mode = $.effects.setMode( el, o.mode || "hide" ),
+ direction = o.direction || "up",
+ vertical = rvertical.test( direction ),
+ ref = vertical ? "height" : "width",
+ ref2 = vertical ? "top" : "left",
+ motion = rpositivemotion.test( direction ),
+ animation = {},
+ show = mode === "show",
+ wrapper, distance, margin;
+
+ // if already wrapped, the wrapper's properties are my property. #6245
+ if ( el.parent().is( ".ui-effects-wrapper" ) ) {
+ $.effects.save( el.parent(), props );
+ } else {
+ $.effects.save( el, props );
+ }
+ el.show();
+ wrapper = $.effects.createWrapper( el ).css({
+ overflow: "hidden"
+ });
+
+ distance = wrapper[ ref ]();
+ margin = parseFloat( wrapper.css( ref2 ) ) || 0;
+
+ animation[ ref ] = show ? distance : 0;
+ if ( !motion ) {
+ el
+ .css( vertical ? "bottom" : "right", 0 )
+ .css( vertical ? "top" : "left", "auto" )
+ .css({ position: "absolute" });
+
+ animation[ ref2 ] = show ? margin : distance + margin;
+ }
+
+ // start at 0 if we are showing
+ if ( show ) {
+ wrapper.css( ref, 0 );
+ if ( ! motion ) {
+ wrapper.css( ref2, margin + distance );
+ }
+ }
+
+ // Animate
+ wrapper.animate( animation, {
+ duration: o.duration,
+ easing: o.easing,
+ queue: false,
+ complete: function() {
+ if ( mode === "hide" ) {
+ el.hide();
+ }
+ $.effects.restore( el, props );
+ $.effects.removeWrapper( el );
+ done();
+ }
+ });
+
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-bounce.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-bounce.js
new file mode 100644
index 00000000..ab1977ef
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-bounce.js
@@ -0,0 +1,113 @@
+/*!
+ * jQuery UI Effects Bounce 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/bounce-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.bounce = function( o, done ) {
+ var el = $( this ),
+ props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
+
+ // defaults:
+ mode = $.effects.setMode( el, o.mode || "effect" ),
+ hide = mode === "hide",
+ show = mode === "show",
+ direction = o.direction || "up",
+ distance = o.distance,
+ times = o.times || 5,
+
+ // number of internal animations
+ anims = times * 2 + ( show || hide ? 1 : 0 ),
+ speed = o.duration / anims,
+ easing = o.easing,
+
+ // utility:
+ ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
+ motion = ( direction === "up" || direction === "left" ),
+ i,
+ upAnim,
+ downAnim,
+
+ // we will need to re-assemble the queue to stack our animations in place
+ queue = el.queue(),
+ queuelen = queue.length;
+
+ // Avoid touching opacity to prevent clearType and PNG issues in IE
+ if ( show || hide ) {
+ props.push( "opacity" );
+ }
+
+ $.effects.save( el, props );
+ el.show();
+ $.effects.createWrapper( el ); // Create Wrapper
+
+ // default distance for the BIGGEST bounce is the outer Distance / 3
+ if ( !distance ) {
+ distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
+ }
+
+ if ( show ) {
+ downAnim = { opacity: 1 };
+ downAnim[ ref ] = 0;
+
+ // if we are showing, force opacity 0 and set the initial position
+ // then do the "first" animation
+ el.css( "opacity", 0 )
+ .css( ref, motion ? -distance * 2 : distance * 2 )
+ .animate( downAnim, speed, easing );
+ }
+
+ // start at the smallest distance if we are hiding
+ if ( hide ) {
+ distance = distance / Math.pow( 2, times - 1 );
+ }
+
+ downAnim = {};
+ downAnim[ ref ] = 0;
+ // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
+ for ( i = 0; i < times; i++ ) {
+ upAnim = {};
+ upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
+
+ el.animate( upAnim, speed, easing )
+ .animate( downAnim, speed, easing );
+
+ distance = hide ? distance * 2 : distance / 2;
+ }
+
+ // Last Bounce when Hiding
+ if ( hide ) {
+ upAnim = { opacity: 0 };
+ upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
+
+ el.animate( upAnim, speed, easing );
+ }
+
+ el.queue(function() {
+ if ( hide ) {
+ el.hide();
+ }
+ $.effects.restore( el, props );
+ $.effects.removeWrapper( el );
+ done();
+ });
+
+ // inject all the animations we just queued to be first in line (after "inprogress")
+ if ( queuelen > 1) {
+ queue.splice.apply( queue,
+ [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
+ }
+ el.dequeue();
+
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-clip.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-clip.js
new file mode 100644
index 00000000..cce037ae
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-clip.js
@@ -0,0 +1,67 @@
+/*!
+ * jQuery UI Effects Clip 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/clip-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.clip = function( o, done ) {
+ // Create element
+ var el = $( this ),
+ props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
+ mode = $.effects.setMode( el, o.mode || "hide" ),
+ show = mode === "show",
+ direction = o.direction || "vertical",
+ vert = direction === "vertical",
+ size = vert ? "height" : "width",
+ position = vert ? "top" : "left",
+ animation = {},
+ wrapper, animate, distance;
+
+ // Save & Show
+ $.effects.save( el, props );
+ el.show();
+
+ // Create Wrapper
+ wrapper = $.effects.createWrapper( el ).css({
+ overflow: "hidden"
+ });
+ animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
+ distance = animate[ size ]();
+
+ // Shift
+ if ( show ) {
+ animate.css( size, 0 );
+ animate.css( position, distance / 2 );
+ }
+
+ // Create Animation Object:
+ animation[ size ] = show ? distance : 0;
+ animation[ position ] = show ? 0 : distance / 2;
+
+ // Animate
+ animate.animate( animation, {
+ queue: false,
+ duration: o.duration,
+ easing: o.easing,
+ complete: function() {
+ if ( !show ) {
+ el.hide();
+ }
+ $.effects.restore( el, props );
+ $.effects.removeWrapper( el );
+ done();
+ }
+ });
+
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-drop.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-drop.js
new file mode 100644
index 00000000..83c8ef4d
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-drop.js
@@ -0,0 +1,65 @@
+/*!
+ * jQuery UI Effects Drop 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/drop-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.drop = function( o, done ) {
+
+ var el = $( this ),
+ props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
+ mode = $.effects.setMode( el, o.mode || "hide" ),
+ show = mode === "show",
+ direction = o.direction || "left",
+ ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
+ motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
+ animation = {
+ opacity: show ? 1 : 0
+ },
+ distance;
+
+ // Adjust
+ $.effects.save( el, props );
+ el.show();
+ $.effects.createWrapper( el );
+
+ distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;
+
+ if ( show ) {
+ el
+ .css( "opacity", 0 )
+ .css( ref, motion === "pos" ? -distance : distance );
+ }
+
+ // Animation
+ animation[ ref ] = ( show ?
+ ( motion === "pos" ? "+=" : "-=" ) :
+ ( motion === "pos" ? "-=" : "+=" ) ) +
+ distance;
+
+ // Animate
+ el.animate( animation, {
+ queue: false,
+ duration: o.duration,
+ easing: o.easing,
+ complete: function() {
+ if ( mode === "hide" ) {
+ el.hide();
+ }
+ $.effects.restore( el, props );
+ $.effects.removeWrapper( el );
+ done();
+ }
+ });
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-explode.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-explode.js
new file mode 100644
index 00000000..98d5be5c
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-explode.js
@@ -0,0 +1,97 @@
+/*!
+ * jQuery UI Effects Explode 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/explode-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.explode = function( o, done ) {
+
+ var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
+ cells = rows,
+ el = $( this ),
+ mode = $.effects.setMode( el, o.mode || "hide" ),
+ show = mode === "show",
+
+ // show and then visibility:hidden the element before calculating offset
+ offset = el.show().css( "visibility", "hidden" ).offset(),
+
+ // width and height of a piece
+ width = Math.ceil( el.outerWidth() / cells ),
+ height = Math.ceil( el.outerHeight() / rows ),
+ pieces = [],
+
+ // loop
+ i, j, left, top, mx, my;
+
+ // children animate complete:
+ function childComplete() {
+ pieces.push( this );
+ if ( pieces.length === rows * cells ) {
+ animComplete();
+ }
+ }
+
+ // clone the element for each row and cell.
+ for( i = 0; i < rows ; i++ ) { // ===>
+ top = offset.top + i * height;
+ my = i - ( rows - 1 ) / 2 ;
+
+ for( j = 0; j < cells ; j++ ) { // |||
+ left = offset.left + j * width;
+ mx = j - ( cells - 1 ) / 2 ;
+
+ // Create a clone of the now hidden main element that will be absolute positioned
+ // within a wrapper div off the -left and -top equal to size of our pieces
+ el
+ .clone()
+ .appendTo( "body" )
+ .wrap( "<div></div>" )
+ .css({
+ position: "absolute",
+ visibility: "visible",
+ left: -j * width,
+ top: -i * height
+ })
+
+ // select the wrapper - make it overflow: hidden and absolute positioned based on
+ // where the original was located +left and +top equal to the size of pieces
+ .parent()
+ .addClass( "ui-effects-explode" )
+ .css({
+ position: "absolute",
+ overflow: "hidden",
+ width: width,
+ height: height,
+ left: left + ( show ? mx * width : 0 ),
+ top: top + ( show ? my * height : 0 ),
+ opacity: show ? 0 : 1
+ }).animate({
+ left: left + ( show ? 0 : mx * width ),
+ top: top + ( show ? 0 : my * height ),
+ opacity: show ? 1 : 0
+ }, o.duration || 500, o.easing, childComplete );
+ }
+ }
+
+ function animComplete() {
+ el.css({
+ visibility: "visible"
+ });
+ $( pieces ).remove();
+ if ( !show ) {
+ el.hide();
+ }
+ done();
+ }
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-fade.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-fade.js
new file mode 100644
index 00000000..c79c6f48
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-fade.js
@@ -0,0 +1,30 @@
+/*!
+ * jQuery UI Effects Fade 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/fade-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.fade = function( o, done ) {
+ var el = $( this ),
+ mode = $.effects.setMode( el, o.mode || "toggle" );
+
+ el.animate({
+ opacity: mode
+ }, {
+ queue: false,
+ duration: o.duration,
+ easing: o.easing,
+ complete: done
+ });
+};
+
+})( jQuery );
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-fold.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-fold.js
new file mode 100644
index 00000000..9452c5da
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-fold.js
@@ -0,0 +1,76 @@
+/*!
+ * jQuery UI Effects Fold 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/fold-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.fold = function( o, done ) {
+
+ // Create element
+ var el = $( this ),
+ props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
+ mode = $.effects.setMode( el, o.mode || "hide" ),
+ show = mode === "show",
+ hide = mode === "hide",
+ size = o.size || 15,
+ percent = /([0-9]+)%/.exec( size ),
+ horizFirst = !!o.horizFirst,
+ widthFirst = show !== horizFirst,
+ ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
+ duration = o.duration / 2,
+ wrapper, distance,
+ animation1 = {},
+ animation2 = {};
+
+ $.effects.save( el, props );
+ el.show();
+
+ // Create Wrapper
+ wrapper = $.effects.createWrapper( el ).css({
+ overflow: "hidden"
+ });
+ distance = widthFirst ?
+ [ wrapper.width(), wrapper.height() ] :
+ [ wrapper.height(), wrapper.width() ];
+
+ if ( percent ) {
+ size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
+ }
+ if ( show ) {
+ wrapper.css( horizFirst ? {
+ height: 0,
+ width: size
+ } : {
+ height: size,
+ width: 0
+ });
+ }
+
+ // Animation
+ animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
+ animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;
+
+ // Animate
+ wrapper
+ .animate( animation1, duration, o.easing )
+ .animate( animation2, duration, o.easing, function() {
+ if ( hide ) {
+ el.hide();
+ }
+ $.effects.restore( el, props );
+ $.effects.removeWrapper( el );
+ done();
+ });
+
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-highlight.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-highlight.js
new file mode 100644
index 00000000..d901f80e
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-highlight.js
@@ -0,0 +1,50 @@
+/*!
+ * jQuery UI Effects Highlight 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/highlight-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.highlight = function( o, done ) {
+ var elem = $( this ),
+ props = [ "backgroundImage", "backgroundColor", "opacity" ],
+ mode = $.effects.setMode( elem, o.mode || "show" ),
+ animation = {
+ backgroundColor: elem.css( "backgroundColor" )
+ };
+
+ if (mode === "hide") {
+ animation.opacity = 0;
+ }
+
+ $.effects.save( elem, props );
+
+ elem
+ .show()
+ .css({
+ backgroundImage: "none",
+ backgroundColor: o.color || "#ffff99"
+ })
+ .animate( animation, {
+ queue: false,
+ duration: o.duration,
+ easing: o.easing,
+ complete: function() {
+ if ( mode === "hide" ) {
+ elem.hide();
+ }
+ $.effects.restore( elem, props );
+ done();
+ }
+ });
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-pulsate.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-pulsate.js
new file mode 100644
index 00000000..20f84dd3
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-pulsate.js
@@ -0,0 +1,63 @@
+/*!
+ * jQuery UI Effects Pulsate 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/pulsate-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.pulsate = function( o, done ) {
+ var elem = $( this ),
+ mode = $.effects.setMode( elem, o.mode || "show" ),
+ show = mode === "show",
+ hide = mode === "hide",
+ showhide = ( show || mode === "hide" ),
+
+ // showing or hiding leaves of the "last" animation
+ anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
+ duration = o.duration / anims,
+ animateTo = 0,
+ queue = elem.queue(),
+ queuelen = queue.length,
+ i;
+
+ if ( show || !elem.is(":visible")) {
+ elem.css( "opacity", 0 ).show();
+ animateTo = 1;
+ }
+
+ // anims - 1 opacity "toggles"
+ for ( i = 1; i < anims; i++ ) {
+ elem.animate({
+ opacity: animateTo
+ }, duration, o.easing );
+ animateTo = 1 - animateTo;
+ }
+
+ elem.animate({
+ opacity: animateTo
+ }, duration, o.easing);
+
+ elem.queue(function() {
+ if ( hide ) {
+ elem.hide();
+ }
+ done();
+ });
+
+ // We just queued up "anims" animations, we need to put them next in the queue
+ if ( queuelen > 1 ) {
+ queue.splice.apply( queue,
+ [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
+ }
+ elem.dequeue();
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-scale.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-scale.js
new file mode 100644
index 00000000..9beac697
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-scale.js
@@ -0,0 +1,318 @@
+/*!
+ * jQuery UI Effects Scale 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/scale-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.puff = function( o, done ) {
+ var elem = $( this ),
+ mode = $.effects.setMode( elem, o.mode || "hide" ),
+ hide = mode === "hide",
+ percent = parseInt( o.percent, 10 ) || 150,
+ factor = percent / 100,
+ original = {
+ height: elem.height(),
+ width: elem.width(),
+ outerHeight: elem.outerHeight(),
+ outerWidth: elem.outerWidth()
+ };
+
+ $.extend( o, {
+ effect: "scale",
+ queue: false,
+ fade: true,
+ mode: mode,
+ complete: done,
+ percent: hide ? percent : 100,
+ from: hide ?
+ original :
+ {
+ height: original.height * factor,
+ width: original.width * factor,
+ outerHeight: original.outerHeight * factor,
+ outerWidth: original.outerWidth * factor
+ }
+ });
+
+ elem.effect( o );
+};
+
+$.effects.effect.scale = function( o, done ) {
+
+ // Create element
+ var el = $( this ),
+ options = $.extend( true, {}, o ),
+ mode = $.effects.setMode( el, o.mode || "effect" ),
+ percent = parseInt( o.percent, 10 ) ||
+ ( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
+ direction = o.direction || "both",
+ origin = o.origin,
+ original = {
+ height: el.height(),
+ width: el.width(),
+ outerHeight: el.outerHeight(),
+ outerWidth: el.outerWidth()
+ },
+ factor = {
+ y: direction !== "horizontal" ? (percent / 100) : 1,
+ x: direction !== "vertical" ? (percent / 100) : 1
+ };
+
+ // We are going to pass this effect to the size effect:
+ options.effect = "size";
+ options.queue = false;
+ options.complete = done;
+
+ // Set default origin and restore for show/hide
+ if ( mode !== "effect" ) {
+ options.origin = origin || ["middle","center"];
+ options.restore = true;
+ }
+
+ options.from = o.from || ( mode === "show" ? {
+ height: 0,
+ width: 0,
+ outerHeight: 0,
+ outerWidth: 0
+ } : original );
+ options.to = {
+ height: original.height * factor.y,
+ width: original.width * factor.x,
+ outerHeight: original.outerHeight * factor.y,
+ outerWidth: original.outerWidth * factor.x
+ };
+
+ // Fade option to support puff
+ if ( options.fade ) {
+ if ( mode === "show" ) {
+ options.from.opacity = 0;
+ options.to.opacity = 1;
+ }
+ if ( mode === "hide" ) {
+ options.from.opacity = 1;
+ options.to.opacity = 0;
+ }
+ }
+
+ // Animate
+ el.effect( options );
+
+};
+
+$.effects.effect.size = function( o, done ) {
+
+ // Create element
+ var original, baseline, factor,
+ el = $( this ),
+ props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],
+
+ // Always restore
+ props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],
+
+ // Copy for children
+ props2 = [ "width", "height", "overflow" ],
+ cProps = [ "fontSize" ],
+ vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
+ hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
+
+ // Set options
+ mode = $.effects.setMode( el, o.mode || "effect" ),
+ restore = o.restore || mode !== "effect",
+ scale = o.scale || "both",
+ origin = o.origin || [ "middle", "center" ],
+ position = el.css( "position" ),
+ props = restore ? props0 : props1,
+ zero = {
+ height: 0,
+ width: 0,
+ outerHeight: 0,
+ outerWidth: 0
+ };
+
+ if ( mode === "show" ) {
+ el.show();
+ }
+ original = {
+ height: el.height(),
+ width: el.width(),
+ outerHeight: el.outerHeight(),
+ outerWidth: el.outerWidth()
+ };
+
+ if ( o.mode === "toggle" && mode === "show" ) {
+ el.from = o.to || zero;
+ el.to = o.from || original;
+ } else {
+ el.from = o.from || ( mode === "show" ? zero : original );
+ el.to = o.to || ( mode === "hide" ? zero : original );
+ }
+
+ // Set scaling factor
+ factor = {
+ from: {
+ y: el.from.height / original.height,
+ x: el.from.width / original.width
+ },
+ to: {
+ y: el.to.height / original.height,
+ x: el.to.width / original.width
+ }
+ };
+
+ // Scale the css box
+ if ( scale === "box" || scale === "both" ) {
+
+ // Vertical props scaling
+ if ( factor.from.y !== factor.to.y ) {
+ props = props.concat( vProps );
+ el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
+ el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
+ }
+
+ // Horizontal props scaling
+ if ( factor.from.x !== factor.to.x ) {
+ props = props.concat( hProps );
+ el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
+ el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
+ }
+ }
+
+ // Scale the content
+ if ( scale === "content" || scale === "both" ) {
+
+ // Vertical props scaling
+ if ( factor.from.y !== factor.to.y ) {
+ props = props.concat( cProps ).concat( props2 );
+ el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
+ el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
+ }
+ }
+
+ $.effects.save( el, props );
+ el.show();
+ $.effects.createWrapper( el );
+ el.css( "overflow", "hidden" ).css( el.from );
+
+ // Adjust
+ if (origin) { // Calculate baseline shifts
+ baseline = $.effects.getBaseline( origin, original );
+ el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
+ el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
+ el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
+ el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
+ }
+ el.css( el.from ); // set top & left
+
+ // Animate
+ if ( scale === "content" || scale === "both" ) { // Scale the children
+
+ // Add margins/font-size
+ vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
+ hProps = hProps.concat([ "marginLeft", "marginRight" ]);
+ props2 = props0.concat(vProps).concat(hProps);
+
+ el.find( "*[width]" ).each( function(){
+ var child = $( this ),
+ c_original = {
+ height: child.height(),
+ width: child.width(),
+ outerHeight: child.outerHeight(),
+ outerWidth: child.outerWidth()
+ };
+ if (restore) {
+ $.effects.save(child, props2);
+ }
+
+ child.from = {
+ height: c_original.height * factor.from.y,
+ width: c_original.width * factor.from.x,
+ outerHeight: c_original.outerHeight * factor.from.y,
+ outerWidth: c_original.outerWidth * factor.from.x
+ };
+ child.to = {
+ height: c_original.height * factor.to.y,
+ width: c_original.width * factor.to.x,
+ outerHeight: c_original.height * factor.to.y,
+ outerWidth: c_original.width * factor.to.x
+ };
+
+ // Vertical props scaling
+ if ( factor.from.y !== factor.to.y ) {
+ child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
+ child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
+ }
+
+ // Horizontal props scaling
+ if ( factor.from.x !== factor.to.x ) {
+ child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
+ child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
+ }
+
+ // Animate children
+ child.css( child.from );
+ child.animate( child.to, o.duration, o.easing, function() {
+
+ // Restore children
+ if ( restore ) {
+ $.effects.restore( child, props2 );
+ }
+ });
+ });
+ }
+
+ // Animate
+ el.animate( el.to, {
+ queue: false,
+ duration: o.duration,
+ easing: o.easing,
+ complete: function() {
+ if ( el.to.opacity === 0 ) {
+ el.css( "opacity", el.from.opacity );
+ }
+ if( mode === "hide" ) {
+ el.hide();
+ }
+ $.effects.restore( el, props );
+ if ( !restore ) {
+
+ // we need to calculate our new positioning based on the scaling
+ if ( position === "static" ) {
+ el.css({
+ position: "relative",
+ top: el.to.top,
+ left: el.to.left
+ });
+ } else {
+ $.each([ "top", "left" ], function( idx, pos ) {
+ el.css( pos, function( _, str ) {
+ var val = parseInt( str, 10 ),
+ toRef = idx ? el.to.left : el.to.top;
+
+ // if original was "auto", recalculate the new value from wrapper
+ if ( str === "auto" ) {
+ return toRef + "px";
+ }
+
+ return val + toRef + "px";
+ });
+ });
+ }
+ }
+
+ $.effects.removeWrapper( el );
+ done();
+ }
+ });
+
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-shake.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-shake.js
new file mode 100644
index 00000000..216c08b6
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-shake.js
@@ -0,0 +1,74 @@
+/*!
+ * jQuery UI Effects Shake 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/shake-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.shake = function( o, done ) {
+
+ var el = $( this ),
+ props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
+ mode = $.effects.setMode( el, o.mode || "effect" ),
+ direction = o.direction || "left",
+ distance = o.distance || 20,
+ times = o.times || 3,
+ anims = times * 2 + 1,
+ speed = Math.round(o.duration/anims),
+ ref = (direction === "up" || direction === "down") ? "top" : "left",
+ positiveMotion = (direction === "up" || direction === "left"),
+ animation = {},
+ animation1 = {},
+ animation2 = {},
+ i,
+
+ // we will need to re-assemble the queue to stack our animations in place
+ queue = el.queue(),
+ queuelen = queue.length;
+
+ $.effects.save( el, props );
+ el.show();
+ $.effects.createWrapper( el );
+
+ // Animation
+ animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
+ animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
+ animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
+
+ // Animate
+ el.animate( animation, speed, o.easing );
+
+ // Shakes
+ for ( i = 1; i < times; i++ ) {
+ el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
+ }
+ el
+ .animate( animation1, speed, o.easing )
+ .animate( animation, speed / 2, o.easing )
+ .queue(function() {
+ if ( mode === "hide" ) {
+ el.hide();
+ }
+ $.effects.restore( el, props );
+ $.effects.removeWrapper( el );
+ done();
+ });
+
+ // inject all the animations we just queued to be first in line (after "inprogress")
+ if ( queuelen > 1) {
+ queue.splice.apply( queue,
+ [ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
+ }
+ el.dequeue();
+
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-slide.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-slide.js
new file mode 100644
index 00000000..445ec48e
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-slide.js
@@ -0,0 +1,64 @@
+/*!
+ * jQuery UI Effects Slide 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/slide-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.slide = function( o, done ) {
+
+ // Create element
+ var el = $( this ),
+ props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
+ mode = $.effects.setMode( el, o.mode || "show" ),
+ show = mode === "show",
+ direction = o.direction || "left",
+ ref = (direction === "up" || direction === "down") ? "top" : "left",
+ positiveMotion = (direction === "up" || direction === "left"),
+ distance,
+ animation = {};
+
+ // Adjust
+ $.effects.save( el, props );
+ el.show();
+ distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );
+
+ $.effects.createWrapper( el ).css({
+ overflow: "hidden"
+ });
+
+ if ( show ) {
+ el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
+ }
+
+ // Animation
+ animation[ ref ] = ( show ?
+ ( positiveMotion ? "+=" : "-=") :
+ ( positiveMotion ? "-=" : "+=")) +
+ distance;
+
+ // Animate
+ el.animate( animation, {
+ queue: false,
+ duration: o.duration,
+ easing: o.easing,
+ complete: function() {
+ if ( mode === "hide" ) {
+ el.hide();
+ }
+ $.effects.restore( el, props );
+ $.effects.removeWrapper( el );
+ done();
+ }
+ });
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-transfer.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-transfer.js
new file mode 100644
index 00000000..f133c04b
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect-transfer.js
@@ -0,0 +1,47 @@
+/*!
+ * jQuery UI Effects Transfer 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/transfer-effect/
+ *
+ * Depends:
+ * jquery.ui.effect.js
+ */
+(function( $, undefined ) {
+
+$.effects.effect.transfer = function( o, done ) {
+ var elem = $( this ),
+ target = $( o.to ),
+ targetFixed = target.css( "position" ) === "fixed",
+ body = $("body"),
+ fixTop = targetFixed ? body.scrollTop() : 0,
+ fixLeft = targetFixed ? body.scrollLeft() : 0,
+ endPosition = target.offset(),
+ animation = {
+ top: endPosition.top - fixTop ,
+ left: endPosition.left - fixLeft ,
+ height: target.innerHeight(),
+ width: target.innerWidth()
+ },
+ startPosition = elem.offset(),
+ transfer = $( '<div class="ui-effects-transfer"></div>' )
+ .appendTo( document.body )
+ .addClass( o.className )
+ .css({
+ top: startPosition.top - fixTop ,
+ left: startPosition.left - fixLeft ,
+ height: elem.innerHeight(),
+ width: elem.innerWidth(),
+ position: targetFixed ? "fixed" : "absolute"
+ })
+ .animate( animation, o.duration, o.easing, function() {
+ transfer.remove();
+ done();
+ });
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.effect.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect.js
new file mode 100644
index 00000000..c8e5818b
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.effect.js
@@ -0,0 +1,1276 @@
+/*!
+ * jQuery UI Effects 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/category/effects-core/
+ */
+;(jQuery.effects || (function($, undefined) {
+
+var backCompat = $.uiBackCompat !== false,
+ // prefix used for storing data on .data()
+ dataSpace = "ui-effects-";
+
+$.effects = {
+ effect: {}
+};
+
+/*!
+ * jQuery Color Animations v2.0.0
+ * http://jquery.com/
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * Date: Mon Aug 13 13:41:02 2012 -0500
+ */
+(function( jQuery, undefined ) {
+
+ var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor".split(" "),
+
+ // plusequals test for += 100 -= 100
+ rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
+ // a set of RE's that can match strings and generate color tuples.
+ stringParsers = [{
+ re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
+ parse: function( execResult ) {
+ return [
+ execResult[ 1 ],
+ execResult[ 2 ],
+ execResult[ 3 ],
+ execResult[ 4 ]
+ ];
+ }
+ }, {
+ re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
+ parse: function( execResult ) {
+ return [
+ execResult[ 1 ] * 2.55,
+ execResult[ 2 ] * 2.55,
+ execResult[ 3 ] * 2.55,
+ execResult[ 4 ]
+ ];
+ }
+ }, {
+ // this regex ignores A-F because it's compared against an already lowercased string
+ re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
+ parse: function( execResult ) {
+ return [
+ parseInt( execResult[ 1 ], 16 ),
+ parseInt( execResult[ 2 ], 16 ),
+ parseInt( execResult[ 3 ], 16 )
+ ];
+ }
+ }, {
+ // this regex ignores A-F because it's compared against an already lowercased string
+ re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
+ parse: function( execResult ) {
+ return [
+ parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
+ parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
+ parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
+ ];
+ }
+ }, {
+ re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d+(?:\.\d+)?)\s*)?\)/,
+ space: "hsla",
+ parse: function( execResult ) {
+ return [
+ execResult[ 1 ],
+ execResult[ 2 ] / 100,
+ execResult[ 3 ] / 100,
+ execResult[ 4 ]
+ ];
+ }
+ }],
+
+ // jQuery.Color( )
+ color = jQuery.Color = function( color, green, blue, alpha ) {
+ return new jQuery.Color.fn.parse( color, green, blue, alpha );
+ },
+ spaces = {
+ rgba: {
+ props: {
+ red: {
+ idx: 0,
+ type: "byte"
+ },
+ green: {
+ idx: 1,
+ type: "byte"
+ },
+ blue: {
+ idx: 2,
+ type: "byte"
+ }
+ }
+ },
+
+ hsla: {
+ props: {
+ hue: {
+ idx: 0,
+ type: "degrees"
+ },
+ saturation: {
+ idx: 1,
+ type: "percent"
+ },
+ lightness: {
+ idx: 2,
+ type: "percent"
+ }
+ }
+ }
+ },
+ propTypes = {
+ "byte": {
+ floor: true,
+ max: 255
+ },
+ "percent": {
+ max: 1
+ },
+ "degrees": {
+ mod: 360,
+ floor: true
+ }
+ },
+ support = color.support = {},
+
+ // element for support tests
+ supportElem = jQuery( "<p>" )[ 0 ],
+
+ // colors = jQuery.Color.names
+ colors,
+
+ // local aliases of functions called often
+ each = jQuery.each;
+
+// determine rgba support immediately
+supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
+support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
+
+// define cache name and alpha properties
+// for rgba and hsla spaces
+each( spaces, function( spaceName, space ) {
+ space.cache = "_" + spaceName;
+ space.props.alpha = {
+ idx: 3,
+ type: "percent",
+ def: 1
+ };
+});
+
+function clamp( value, prop, allowEmpty ) {
+ var type = propTypes[ prop.type ] || {};
+
+ if ( value == null ) {
+ return (allowEmpty || !prop.def) ? null : prop.def;
+ }
+
+ // ~~ is an short way of doing floor for positive numbers
+ value = type.floor ? ~~value : parseFloat( value );
+
+ // IE will pass in empty strings as value for alpha,
+ // which will hit this case
+ if ( isNaN( value ) ) {
+ return prop.def;
+ }
+
+ if ( type.mod ) {
+ // we add mod before modding to make sure that negatives values
+ // get converted properly: -10 -> 350
+ return (value + type.mod) % type.mod;
+ }
+
+ // for now all property types without mod have min and max
+ return 0 > value ? 0 : type.max < value ? type.max : value;
+}
+
+function stringParse( string ) {
+ var inst = color(),
+ rgba = inst._rgba = [];
+
+ string = string.toLowerCase();
+
+ each( stringParsers, function( i, parser ) {
+ var parsed,
+ match = parser.re.exec( string ),
+ values = match && parser.parse( match ),
+ spaceName = parser.space || "rgba";
+
+ if ( values ) {
+ parsed = inst[ spaceName ]( values );
+
+ // if this was an rgba parse the assignment might happen twice
+ // oh well....
+ inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
+ rgba = inst._rgba = parsed._rgba;
+
+ // exit each( stringParsers ) here because we matched
+ return false;
+ }
+ });
+
+ // Found a stringParser that handled it
+ if ( rgba.length ) {
+
+ // if this came from a parsed string, force "transparent" when alpha is 0
+ // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
+ if ( rgba.join() === "0,0,0,0" ) {
+ jQuery.extend( rgba, colors.transparent );
+ }
+ return inst;
+ }
+
+ // named colors
+ return colors[ string ];
+}
+
+color.fn = jQuery.extend( color.prototype, {
+ parse: function( red, green, blue, alpha ) {
+ if ( red === undefined ) {
+ this._rgba = [ null, null, null, null ];
+ return this;
+ }
+ if ( red.jquery || red.nodeType ) {
+ red = jQuery( red ).css( green );
+ green = undefined;
+ }
+
+ var inst = this,
+ type = jQuery.type( red ),
+ rgba = this._rgba = [];
+
+ // more than 1 argument specified - assume ( red, green, blue, alpha )
+ if ( green !== undefined ) {
+ red = [ red, green, blue, alpha ];
+ type = "array";
+ }
+
+ if ( type === "string" ) {
+ return this.parse( stringParse( red ) || colors._default );
+ }
+
+ if ( type === "array" ) {
+ each( spaces.rgba.props, function( key, prop ) {
+ rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
+ });
+ return this;
+ }
+
+ if ( type === "object" ) {
+ if ( red instanceof color ) {
+ each( spaces, function( spaceName, space ) {
+ if ( red[ space.cache ] ) {
+ inst[ space.cache ] = red[ space.cache ].slice();
+ }
+ });
+ } else {
+ each( spaces, function( spaceName, space ) {
+ var cache = space.cache;
+ each( space.props, function( key, prop ) {
+
+ // if the cache doesn't exist, and we know how to convert
+ if ( !inst[ cache ] && space.to ) {
+
+ // if the value was null, we don't need to copy it
+ // if the key was alpha, we don't need to copy it either
+ if ( key === "alpha" || red[ key ] == null ) {
+ return;
+ }
+ inst[ cache ] = space.to( inst._rgba );
+ }
+
+ // this is the only case where we allow nulls for ALL properties.
+ // call clamp with alwaysAllowEmpty
+ inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
+ });
+
+ // everything defined but alpha?
+ if ( inst[ cache ] && $.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
+ // use the default of 1
+ inst[ cache ][ 3 ] = 1;
+ if ( space.from ) {
+ inst._rgba = space.from( inst[ cache ] );
+ }
+ }
+ });
+ }
+ return this;
+ }
+ },
+ is: function( compare ) {
+ var is = color( compare ),
+ same = true,
+ inst = this;
+
+ each( spaces, function( _, space ) {
+ var localCache,
+ isCache = is[ space.cache ];
+ if (isCache) {
+ localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
+ each( space.props, function( _, prop ) {
+ if ( isCache[ prop.idx ] != null ) {
+ same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
+ return same;
+ }
+ });
+ }
+ return same;
+ });
+ return same;
+ },
+ _space: function() {
+ var used = [],
+ inst = this;
+ each( spaces, function( spaceName, space ) {
+ if ( inst[ space.cache ] ) {
+ used.push( spaceName );
+ }
+ });
+ return used.pop();
+ },
+ transition: function( other, distance ) {
+ var end = color( other ),
+ spaceName = end._space(),
+ space = spaces[ spaceName ],
+ startColor = this.alpha() === 0 ? color( "transparent" ) : this,
+ start = startColor[ space.cache ] || space.to( startColor._rgba ),
+ result = start.slice();
+
+ end = end[ space.cache ];
+ each( space.props, function( key, prop ) {
+ var index = prop.idx,
+ startValue = start[ index ],
+ endValue = end[ index ],
+ type = propTypes[ prop.type ] || {};
+
+ // if null, don't override start value
+ if ( endValue === null ) {
+ return;
+ }
+ // if null - use end
+ if ( startValue === null ) {
+ result[ index ] = endValue;
+ } else {
+ if ( type.mod ) {
+ if ( endValue - startValue > type.mod / 2 ) {
+ startValue += type.mod;
+ } else if ( startValue - endValue > type.mod / 2 ) {
+ startValue -= type.mod;
+ }
+ }
+ result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
+ }
+ });
+ return this[ spaceName ]( result );
+ },
+ blend: function( opaque ) {
+ // if we are already opaque - return ourself
+ if ( this._rgba[ 3 ] === 1 ) {
+ return this;
+ }
+
+ var rgb = this._rgba.slice(),
+ a = rgb.pop(),
+ blend = color( opaque )._rgba;
+
+ return color( jQuery.map( rgb, function( v, i ) {
+ return ( 1 - a ) * blend[ i ] + a * v;
+ }));
+ },
+ toRgbaString: function() {
+ var prefix = "rgba(",
+ rgba = jQuery.map( this._rgba, function( v, i ) {
+ return v == null ? ( i > 2 ? 1 : 0 ) : v;
+ });
+
+ if ( rgba[ 3 ] === 1 ) {
+ rgba.pop();
+ prefix = "rgb(";
+ }
+
+ return prefix + rgba.join() + ")";
+ },
+ toHslaString: function() {
+ var prefix = "hsla(",
+ hsla = jQuery.map( this.hsla(), function( v, i ) {
+ if ( v == null ) {
+ v = i > 2 ? 1 : 0;
+ }
+
+ // catch 1 and 2
+ if ( i && i < 3 ) {
+ v = Math.round( v * 100 ) + "%";
+ }
+ return v;
+ });
+
+ if ( hsla[ 3 ] === 1 ) {
+ hsla.pop();
+ prefix = "hsl(";
+ }
+ return prefix + hsla.join() + ")";
+ },
+ toHexString: function( includeAlpha ) {
+ var rgba = this._rgba.slice(),
+ alpha = rgba.pop();
+
+ if ( includeAlpha ) {
+ rgba.push( ~~( alpha * 255 ) );
+ }
+
+ return "#" + jQuery.map( rgba, function( v ) {
+
+ // default to 0 when nulls exist
+ v = ( v || 0 ).toString( 16 );
+ return v.length === 1 ? "0" + v : v;
+ }).join("");
+ },
+ toString: function() {
+ return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
+ }
+});
+color.fn.parse.prototype = color.fn;
+
+// hsla conversions adapted from:
+// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
+
+function hue2rgb( p, q, h ) {
+ h = ( h + 1 ) % 1;
+ if ( h * 6 < 1 ) {
+ return p + (q - p) * h * 6;
+ }
+ if ( h * 2 < 1) {
+ return q;
+ }
+ if ( h * 3 < 2 ) {
+ return p + (q - p) * ((2/3) - h) * 6;
+ }
+ return p;
+}
+
+spaces.hsla.to = function ( rgba ) {
+ if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
+ return [ null, null, null, rgba[ 3 ] ];
+ }
+ var r = rgba[ 0 ] / 255,
+ g = rgba[ 1 ] / 255,
+ b = rgba[ 2 ] / 255,
+ a = rgba[ 3 ],
+ max = Math.max( r, g, b ),
+ min = Math.min( r, g, b ),
+ diff = max - min,
+ add = max + min,
+ l = add * 0.5,
+ h, s;
+
+ if ( min === max ) {
+ h = 0;
+ } else if ( r === max ) {
+ h = ( 60 * ( g - b ) / diff ) + 360;
+ } else if ( g === max ) {
+ h = ( 60 * ( b - r ) / diff ) + 120;
+ } else {
+ h = ( 60 * ( r - g ) / diff ) + 240;
+ }
+
+ if ( l === 0 || l === 1 ) {
+ s = l;
+ } else if ( l <= 0.5 ) {
+ s = diff / add;
+ } else {
+ s = diff / ( 2 - add );
+ }
+ return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
+};
+
+spaces.hsla.from = function ( hsla ) {
+ if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
+ return [ null, null, null, hsla[ 3 ] ];
+ }
+ var h = hsla[ 0 ] / 360,
+ s = hsla[ 1 ],
+ l = hsla[ 2 ],
+ a = hsla[ 3 ],
+ q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
+ p = 2 * l - q;
+
+ return [
+ Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
+ Math.round( hue2rgb( p, q, h ) * 255 ),
+ Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
+ a
+ ];
+};
+
+
+each( spaces, function( spaceName, space ) {
+ var props = space.props,
+ cache = space.cache,
+ to = space.to,
+ from = space.from;
+
+ // makes rgba() and hsla()
+ color.fn[ spaceName ] = function( value ) {
+
+ // generate a cache for this space if it doesn't exist
+ if ( to && !this[ cache ] ) {
+ this[ cache ] = to( this._rgba );
+ }
+ if ( value === undefined ) {
+ return this[ cache ].slice();
+ }
+
+ var ret,
+ type = jQuery.type( value ),
+ arr = ( type === "array" || type === "object" ) ? value : arguments,
+ local = this[ cache ].slice();
+
+ each( props, function( key, prop ) {
+ var val = arr[ type === "object" ? key : prop.idx ];
+ if ( val == null ) {
+ val = local[ prop.idx ];
+ }
+ local[ prop.idx ] = clamp( val, prop );
+ });
+
+ if ( from ) {
+ ret = color( from( local ) );
+ ret[ cache ] = local;
+ return ret;
+ } else {
+ return color( local );
+ }
+ };
+
+ // makes red() green() blue() alpha() hue() saturation() lightness()
+ each( props, function( key, prop ) {
+ // alpha is included in more than one space
+ if ( color.fn[ key ] ) {
+ return;
+ }
+ color.fn[ key ] = function( value ) {
+ var vtype = jQuery.type( value ),
+ fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
+ local = this[ fn ](),
+ cur = local[ prop.idx ],
+ match;
+
+ if ( vtype === "undefined" ) {
+ return cur;
+ }
+
+ if ( vtype === "function" ) {
+ value = value.call( this, cur );
+ vtype = jQuery.type( value );
+ }
+ if ( value == null && prop.empty ) {
+ return this;
+ }
+ if ( vtype === "string" ) {
+ match = rplusequals.exec( value );
+ if ( match ) {
+ value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
+ }
+ }
+ local[ prop.idx ] = value;
+ return this[ fn ]( local );
+ };
+ });
+});
+
+// add .fx.step functions
+each( stepHooks, function( i, hook ) {
+ jQuery.cssHooks[ hook ] = {
+ set: function( elem, value ) {
+ var parsed, curElem,
+ backgroundColor = "";
+
+ if ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) {
+ value = color( parsed || value );
+ if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
+ curElem = hook === "backgroundColor" ? elem.parentNode : elem;
+ while (
+ (backgroundColor === "" || backgroundColor === "transparent") &&
+ curElem && curElem.style
+ ) {
+ try {
+ backgroundColor = jQuery.css( curElem, "backgroundColor" );
+ curElem = curElem.parentNode;
+ } catch ( e ) {
+ }
+ }
+
+ value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
+ backgroundColor :
+ "_default" );
+ }
+
+ value = value.toRgbaString();
+ }
+ try {
+ elem.style[ hook ] = value;
+ } catch( error ) {
+ // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
+ }
+ }
+ };
+ jQuery.fx.step[ hook ] = function( fx ) {
+ if ( !fx.colorInit ) {
+ fx.start = color( fx.elem, hook );
+ fx.end = color( fx.end );
+ fx.colorInit = true;
+ }
+ jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
+ };
+});
+
+jQuery.cssHooks.borderColor = {
+ expand: function( value ) {
+ var expanded = {};
+
+ each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
+ expanded[ "border" + part + "Color" ] = value;
+ });
+ return expanded;
+ }
+};
+
+// Basic color names only.
+// Usage of any of the other color names requires adding yourself or including
+// jquery.color.svg-names.js.
+colors = jQuery.Color.names = {
+ // 4.1. Basic color keywords
+ aqua: "#00ffff",
+ black: "#000000",
+ blue: "#0000ff",
+ fuchsia: "#ff00ff",
+ gray: "#808080",
+ green: "#008000",
+ lime: "#00ff00",
+ maroon: "#800000",
+ navy: "#000080",
+ olive: "#808000",
+ purple: "#800080",
+ red: "#ff0000",
+ silver: "#c0c0c0",
+ teal: "#008080",
+ white: "#ffffff",
+ yellow: "#ffff00",
+
+ // 4.2.3. "transparent" color keyword
+ transparent: [ null, null, null, 0 ],
+
+ _default: "#ffffff"
+};
+
+})( jQuery );
+
+
+
+/******************************************************************************/
+/****************************** CLASS ANIMATIONS ******************************/
+/******************************************************************************/
+(function() {
+
+var classAnimationActions = [ "add", "remove", "toggle" ],
+ shorthandStyles = {
+ border: 1,
+ borderBottom: 1,
+ borderColor: 1,
+ borderLeft: 1,
+ borderRight: 1,
+ borderTop: 1,
+ borderWidth: 1,
+ margin: 1,
+ padding: 1
+ };
+
+$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
+ $.fx.step[ prop ] = function( fx ) {
+ if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
+ jQuery.style( fx.elem, prop, fx.end );
+ fx.setAttr = true;
+ }
+ };
+});
+
+function getElementStyles() {
+ var style = this.ownerDocument.defaultView ?
+ this.ownerDocument.defaultView.getComputedStyle( this, null ) :
+ this.currentStyle,
+ newStyle = {},
+ key,
+ len;
+
+ // webkit enumerates style porperties
+ if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
+ len = style.length;
+ while ( len-- ) {
+ key = style[ len ];
+ if ( typeof style[ key ] === "string" ) {
+ newStyle[ $.camelCase( key ) ] = style[ key ];
+ }
+ }
+ } else {
+ for ( key in style ) {
+ if ( typeof style[ key ] === "string" ) {
+ newStyle[ key ] = style[ key ];
+ }
+ }
+ }
+
+ return newStyle;
+}
+
+
+function styleDifference( oldStyle, newStyle ) {
+ var diff = {},
+ name, value;
+
+ for ( name in newStyle ) {
+ value = newStyle[ name ];
+ if ( oldStyle[ name ] !== value ) {
+ if ( !shorthandStyles[ name ] ) {
+ if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
+ diff[ name ] = value;
+ }
+ }
+ }
+ }
+
+ return diff;
+}
+
+$.effects.animateClass = function( value, duration, easing, callback ) {
+ var o = $.speed( duration, easing, callback );
+
+ return this.queue( function() {
+ var animated = $( this ),
+ baseClass = animated.attr( "class" ) || "",
+ applyClassChange,
+ allAnimations = o.children ? animated.find( "*" ).andSelf() : animated;
+
+ // map the animated objects to store the original styles.
+ allAnimations = allAnimations.map(function() {
+ var el = $( this );
+ return {
+ el: el,
+ start: getElementStyles.call( this )
+ };
+ });
+
+ // apply class change
+ applyClassChange = function() {
+ $.each( classAnimationActions, function(i, action) {
+ if ( value[ action ] ) {
+ animated[ action + "Class" ]( value[ action ] );
+ }
+ });
+ };
+ applyClassChange();
+
+ // map all animated objects again - calculate new styles and diff
+ allAnimations = allAnimations.map(function() {
+ this.end = getElementStyles.call( this.el[ 0 ] );
+ this.diff = styleDifference( this.start, this.end );
+ return this;
+ });
+
+ // apply original class
+ animated.attr( "class", baseClass );
+
+ // map all animated objects again - this time collecting a promise
+ allAnimations = allAnimations.map(function() {
+ var styleInfo = this,
+ dfd = $.Deferred(),
+ opts = jQuery.extend({}, o, {
+ queue: false,
+ complete: function() {
+ dfd.resolve( styleInfo );
+ }
+ });
+
+ this.el.animate( this.diff, opts );
+ return dfd.promise();
+ });
+
+ // once all animations have completed:
+ $.when.apply( $, allAnimations.get() ).done(function() {
+
+ // set the final class
+ applyClassChange();
+
+ // for each animated element,
+ // clear all css properties that were animated
+ $.each( arguments, function() {
+ var el = this.el;
+ $.each( this.diff, function(key) {
+ el.css( key, '' );
+ });
+ });
+
+ // this is guarnteed to be there if you use jQuery.speed()
+ // it also handles dequeuing the next anim...
+ o.complete.call( animated[ 0 ] );
+ });
+ });
+};
+
+$.fn.extend({
+ _addClass: $.fn.addClass,
+ addClass: function( classNames, speed, easing, callback ) {
+ return speed ?
+ $.effects.animateClass.call( this,
+ { add: classNames }, speed, easing, callback ) :
+ this._addClass( classNames );
+ },
+
+ _removeClass: $.fn.removeClass,
+ removeClass: function( classNames, speed, easing, callback ) {
+ return speed ?
+ $.effects.animateClass.call( this,
+ { remove: classNames }, speed, easing, callback ) :
+ this._removeClass( classNames );
+ },
+
+ _toggleClass: $.fn.toggleClass,
+ toggleClass: function( classNames, force, speed, easing, callback ) {
+ if ( typeof force === "boolean" || force === undefined ) {
+ if ( !speed ) {
+ // without speed parameter
+ return this._toggleClass( classNames, force );
+ } else {
+ return $.effects.animateClass.call( this,
+ (force ? { add: classNames } : { remove: classNames }),
+ speed, easing, callback );
+ }
+ } else {
+ // without force parameter
+ return $.effects.animateClass.call( this,
+ { toggle: classNames }, force, speed, easing );
+ }
+ },
+
+ switchClass: function( remove, add, speed, easing, callback) {
+ return $.effects.animateClass.call( this, {
+ add: add,
+ remove: remove
+ }, speed, easing, callback );
+ }
+});
+
+})();
+
+/******************************************************************************/
+/*********************************** EFFECTS **********************************/
+/******************************************************************************/
+
+(function() {
+
+$.extend( $.effects, {
+ version: "1.9.2",
+
+ // Saves a set of properties in a data storage
+ save: function( element, set ) {
+ for( var i=0; i < set.length; i++ ) {
+ if ( set[ i ] !== null ) {
+ element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
+ }
+ }
+ },
+
+ // Restores a set of previously saved properties from a data storage
+ restore: function( element, set ) {
+ var val, i;
+ for( i=0; i < set.length; i++ ) {
+ if ( set[ i ] !== null ) {
+ val = element.data( dataSpace + set[ i ] );
+ // support: jQuery 1.6.2
+ // http://bugs.jquery.com/ticket/9917
+ // jQuery 1.6.2 incorrectly returns undefined for any falsy value.
+ // We can't differentiate between "" and 0 here, so we just assume
+ // empty string since it's likely to be a more common value...
+ if ( val === undefined ) {
+ val = "";
+ }
+ element.css( set[ i ], val );
+ }
+ }
+ },
+
+ setMode: function( el, mode ) {
+ if (mode === "toggle") {
+ mode = el.is( ":hidden" ) ? "show" : "hide";
+ }
+ return mode;
+ },
+
+ // Translates a [top,left] array into a baseline value
+ // this should be a little more flexible in the future to handle a string & hash
+ getBaseline: function( origin, original ) {
+ var y, x;
+ switch ( origin[ 0 ] ) {
+ case "top": y = 0; break;
+ case "middle": y = 0.5; break;
+ case "bottom": y = 1; break;
+ default: y = origin[ 0 ] / original.height;
+ }
+ switch ( origin[ 1 ] ) {
+ case "left": x = 0; break;
+ case "center": x = 0.5; break;
+ case "right": x = 1; break;
+ default: x = origin[ 1 ] / original.width;
+ }
+ return {
+ x: x,
+ y: y
+ };
+ },
+
+ // Wraps the element around a wrapper that copies position properties
+ createWrapper: function( element ) {
+
+ // if the element is already wrapped, return it
+ if ( element.parent().is( ".ui-effects-wrapper" )) {
+ return element.parent();
+ }
+
+ // wrap the element
+ var props = {
+ width: element.outerWidth(true),
+ height: element.outerHeight(true),
+ "float": element.css( "float" )
+ },
+ wrapper = $( "<div></div>" )
+ .addClass( "ui-effects-wrapper" )
+ .css({
+ fontSize: "100%",
+ background: "transparent",
+ border: "none",
+ margin: 0,
+ padding: 0
+ }),
+ // Store the size in case width/height are defined in % - Fixes #5245
+ size = {
+ width: element.width(),
+ height: element.height()
+ },
+ active = document.activeElement;
+
+ // support: Firefox
+ // Firefox incorrectly exposes anonymous content
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
+ try {
+ active.id;
+ } catch( e ) {
+ active = document.body;
+ }
+
+ element.wrap( wrapper );
+
+ // Fixes #7595 - Elements lose focus when wrapped.
+ if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
+ $( active ).focus();
+ }
+
+ wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element
+
+ // transfer positioning properties to the wrapper
+ if ( element.css( "position" ) === "static" ) {
+ wrapper.css({ position: "relative" });
+ element.css({ position: "relative" });
+ } else {
+ $.extend( props, {
+ position: element.css( "position" ),
+ zIndex: element.css( "z-index" )
+ });
+ $.each([ "top", "left", "bottom", "right" ], function(i, pos) {
+ props[ pos ] = element.css( pos );
+ if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
+ props[ pos ] = "auto";
+ }
+ });
+ element.css({
+ position: "relative",
+ top: 0,
+ left: 0,
+ right: "auto",
+ bottom: "auto"
+ });
+ }
+ element.css(size);
+
+ return wrapper.css( props ).show();
+ },
+
+ removeWrapper: function( element ) {
+ var active = document.activeElement;
+
+ if ( element.parent().is( ".ui-effects-wrapper" ) ) {
+ element.parent().replaceWith( element );
+
+ // Fixes #7595 - Elements lose focus when wrapped.
+ if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
+ $( active ).focus();
+ }
+ }
+
+
+ return element;
+ },
+
+ setTransition: function( element, list, factor, value ) {
+ value = value || {};
+ $.each( list, function( i, x ) {
+ var unit = element.cssUnit( x );
+ if ( unit[ 0 ] > 0 ) {
+ value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
+ }
+ });
+ return value;
+ }
+});
+
+// return an effect options object for the given parameters:
+function _normalizeArguments( effect, options, speed, callback ) {
+
+ // allow passing all options as the first parameter
+ if ( $.isPlainObject( effect ) ) {
+ options = effect;
+ effect = effect.effect;
+ }
+
+ // convert to an object
+ effect = { effect: effect };
+
+ // catch (effect, null, ...)
+ if ( options == null ) {
+ options = {};
+ }
+
+ // catch (effect, callback)
+ if ( $.isFunction( options ) ) {
+ callback = options;
+ speed = null;
+ options = {};
+ }
+
+ // catch (effect, speed, ?)
+ if ( typeof options === "number" || $.fx.speeds[ options ] ) {
+ callback = speed;
+ speed = options;
+ options = {};
+ }
+
+ // catch (effect, options, callback)
+ if ( $.isFunction( speed ) ) {
+ callback = speed;
+ speed = null;
+ }
+
+ // add options to effect
+ if ( options ) {
+ $.extend( effect, options );
+ }
+
+ speed = speed || options.duration;
+ effect.duration = $.fx.off ? 0 :
+ typeof speed === "number" ? speed :
+ speed in $.fx.speeds ? $.fx.speeds[ speed ] :
+ $.fx.speeds._default;
+
+ effect.complete = callback || options.complete;
+
+ return effect;
+}
+
+function standardSpeed( speed ) {
+ // valid standard speeds
+ if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
+ return true;
+ }
+
+ // invalid strings - treat as "normal" speed
+ if ( typeof speed === "string" && !$.effects.effect[ speed ] ) {
+ // TODO: remove in 2.0 (#7115)
+ if ( backCompat && $.effects[ speed ] ) {
+ return false;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+$.fn.extend({
+ effect: function( /* effect, options, speed, callback */ ) {
+ var args = _normalizeArguments.apply( this, arguments ),
+ mode = args.mode,
+ queue = args.queue,
+ effectMethod = $.effects.effect[ args.effect ],
+
+ // DEPRECATED: remove in 2.0 (#7115)
+ oldEffectMethod = !effectMethod && backCompat && $.effects[ args.effect ];
+
+ if ( $.fx.off || !( effectMethod || oldEffectMethod ) ) {
+ // delegate to the original method (e.g., .show()) if possible
+ if ( mode ) {
+ return this[ mode ]( args.duration, args.complete );
+ } else {
+ return this.each( function() {
+ if ( args.complete ) {
+ args.complete.call( this );
+ }
+ });
+ }
+ }
+
+ function run( next ) {
+ var elem = $( this ),
+ complete = args.complete,
+ mode = args.mode;
+
+ function done() {
+ if ( $.isFunction( complete ) ) {
+ complete.call( elem[0] );
+ }
+ if ( $.isFunction( next ) ) {
+ next();
+ }
+ }
+
+ // if the element is hiddden and mode is hide,
+ // or element is visible and mode is show
+ if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
+ done();
+ } else {
+ effectMethod.call( elem[0], args, done );
+ }
+ }
+
+ // TODO: remove this check in 2.0, effectMethod will always be true
+ if ( effectMethod ) {
+ return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
+ } else {
+ // DEPRECATED: remove in 2.0 (#7115)
+ return oldEffectMethod.call(this, {
+ options: args,
+ duration: args.duration,
+ callback: args.complete,
+ mode: args.mode
+ });
+ }
+ },
+
+ _show: $.fn.show,
+ show: function( speed ) {
+ if ( standardSpeed( speed ) ) {
+ return this._show.apply( this, arguments );
+ } else {
+ var args = _normalizeArguments.apply( this, arguments );
+ args.mode = "show";
+ return this.effect.call( this, args );
+ }
+ },
+
+ _hide: $.fn.hide,
+ hide: function( speed ) {
+ if ( standardSpeed( speed ) ) {
+ return this._hide.apply( this, arguments );
+ } else {
+ var args = _normalizeArguments.apply( this, arguments );
+ args.mode = "hide";
+ return this.effect.call( this, args );
+ }
+ },
+
+ // jQuery core overloads toggle and creates _toggle
+ __toggle: $.fn.toggle,
+ toggle: function( speed ) {
+ if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
+ return this.__toggle.apply( this, arguments );
+ } else {
+ var args = _normalizeArguments.apply( this, arguments );
+ args.mode = "toggle";
+ return this.effect.call( this, args );
+ }
+ },
+
+ // helper functions
+ cssUnit: function(key) {
+ var style = this.css( key ),
+ val = [];
+
+ $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
+ if ( style.indexOf( unit ) > 0 ) {
+ val = [ parseFloat( style ), unit ];
+ }
+ });
+ return val;
+ }
+});
+
+})();
+
+/******************************************************************************/
+/*********************************** EASING ***********************************/
+/******************************************************************************/
+
+(function() {
+
+// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
+
+var baseEasings = {};
+
+$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
+ baseEasings[ name ] = function( p ) {
+ return Math.pow( p, i + 2 );
+ };
+});
+
+$.extend( baseEasings, {
+ Sine: function ( p ) {
+ return 1 - Math.cos( p * Math.PI / 2 );
+ },
+ Circ: function ( p ) {
+ return 1 - Math.sqrt( 1 - p * p );
+ },
+ Elastic: function( p ) {
+ return p === 0 || p === 1 ? p :
+ -Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
+ },
+ Back: function( p ) {
+ return p * p * ( 3 * p - 2 );
+ },
+ Bounce: function ( p ) {
+ var pow2,
+ bounce = 4;
+
+ while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
+ return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
+ }
+});
+
+$.each( baseEasings, function( name, easeIn ) {
+ $.easing[ "easeIn" + name ] = easeIn;
+ $.easing[ "easeOut" + name ] = function( p ) {
+ return 1 - easeIn( 1 - p );
+ };
+ $.easing[ "easeInOut" + name ] = function( p ) {
+ return p < 0.5 ?
+ easeIn( p * 2 ) / 2 :
+ 1 - easeIn( p * -2 + 2 ) / 2;
+ };
+});
+
+})();
+
+})(jQuery));
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.menu.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.menu.js
new file mode 100644
index 00000000..6342f2d3
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.menu.js
@@ -0,0 +1,610 @@
+/*!
+ * jQuery UI Menu 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/menu/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.position.js
+ */
+(function( $, undefined ) {
+
+var mouseHandled = false;
+
+$.widget( "ui.menu", {
+ version: "1.9.2",
+ defaultElement: "<ul>",
+ delay: 300,
+ options: {
+ icons: {
+ submenu: "ui-icon-carat-1-e"
+ },
+ menus: "ul",
+ position: {
+ my: "left top",
+ at: "right top"
+ },
+ role: "menu",
+
+ // callbacks
+ blur: null,
+ focus: null,
+ select: null
+ },
+
+ _create: function() {
+ this.activeMenu = this.element;
+ this.element
+ .uniqueId()
+ .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
+ .toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
+ .attr({
+ role: this.options.role,
+ tabIndex: 0
+ })
+ // need to catch all clicks on disabled menu
+ // not possible through _on
+ .bind( "click" + this.eventNamespace, $.proxy(function( event ) {
+ if ( this.options.disabled ) {
+ event.preventDefault();
+ }
+ }, this ));
+
+ if ( this.options.disabled ) {
+ this.element
+ .addClass( "ui-state-disabled" )
+ .attr( "aria-disabled", "true" );
+ }
+
+ this._on({
+ // Prevent focus from sticking to links inside menu after clicking
+ // them (focus should always stay on UL during navigation).
+ "mousedown .ui-menu-item > a": function( event ) {
+ event.preventDefault();
+ },
+ "click .ui-state-disabled > a": function( event ) {
+ event.preventDefault();
+ },
+ "click .ui-menu-item:has(a)": function( event ) {
+ var target = $( event.target ).closest( ".ui-menu-item" );
+ if ( !mouseHandled && target.not( ".ui-state-disabled" ).length ) {
+ mouseHandled = true;
+
+ this.select( event );
+ // Open submenu on click
+ if ( target.has( ".ui-menu" ).length ) {
+ this.expand( event );
+ } else if ( !this.element.is( ":focus" ) ) {
+ // Redirect focus to the menu
+ this.element.trigger( "focus", [ true ] );
+
+ // If the active item is on the top level, let it stay active.
+ // Otherwise, blur the active item since it is no longer visible.
+ if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
+ clearTimeout( this.timer );
+ }
+ }
+ }
+ },
+ "mouseenter .ui-menu-item": function( event ) {
+ var target = $( event.currentTarget );
+ // Remove ui-state-active class from siblings of the newly focused menu item
+ // to avoid a jump caused by adjacent elements both having a class with a border
+ target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
+ this.focus( event, target );
+ },
+ mouseleave: "collapseAll",
+ "mouseleave .ui-menu": "collapseAll",
+ focus: function( event, keepActiveItem ) {
+ // If there's already an active item, keep it active
+ // If not, activate the first item
+ var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 );
+
+ if ( !keepActiveItem ) {
+ this.focus( event, item );
+ }
+ },
+ blur: function( event ) {
+ this._delay(function() {
+ if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
+ this.collapseAll( event );
+ }
+ });
+ },
+ keydown: "_keydown"
+ });
+
+ this.refresh();
+
+ // Clicks outside of a menu collapse any open menus
+ this._on( this.document, {
+ click: function( event ) {
+ if ( !$( event.target ).closest( ".ui-menu" ).length ) {
+ this.collapseAll( event );
+ }
+
+ // Reset the mouseHandled flag
+ mouseHandled = false;
+ }
+ });
+ },
+
+ _destroy: function() {
+ // Destroy (sub)menus
+ this.element
+ .removeAttr( "aria-activedescendant" )
+ .find( ".ui-menu" ).andSelf()
+ .removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" )
+ .removeAttr( "role" )
+ .removeAttr( "tabIndex" )
+ .removeAttr( "aria-labelledby" )
+ .removeAttr( "aria-expanded" )
+ .removeAttr( "aria-hidden" )
+ .removeAttr( "aria-disabled" )
+ .removeUniqueId()
+ .show();
+
+ // Destroy menu items
+ this.element.find( ".ui-menu-item" )
+ .removeClass( "ui-menu-item" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-disabled" )
+ .children( "a" )
+ .removeUniqueId()
+ .removeClass( "ui-corner-all ui-state-hover" )
+ .removeAttr( "tabIndex" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-haspopup" )
+ .children().each( function() {
+ var elem = $( this );
+ if ( elem.data( "ui-menu-submenu-carat" ) ) {
+ elem.remove();
+ }
+ });
+
+ // Destroy menu dividers
+ this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
+ },
+
+ _keydown: function( event ) {
+ var match, prev, character, skip, regex,
+ preventDefault = true;
+
+ function escape( value ) {
+ return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
+ }
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.PAGE_UP:
+ this.previousPage( event );
+ break;
+ case $.ui.keyCode.PAGE_DOWN:
+ this.nextPage( event );
+ break;
+ case $.ui.keyCode.HOME:
+ this._move( "first", "first", event );
+ break;
+ case $.ui.keyCode.END:
+ this._move( "last", "last", event );
+ break;
+ case $.ui.keyCode.UP:
+ this.previous( event );
+ break;
+ case $.ui.keyCode.DOWN:
+ this.next( event );
+ break;
+ case $.ui.keyCode.LEFT:
+ this.collapse( event );
+ break;
+ case $.ui.keyCode.RIGHT:
+ if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
+ this.expand( event );
+ }
+ break;
+ case $.ui.keyCode.ENTER:
+ case $.ui.keyCode.SPACE:
+ this._activate( event );
+ break;
+ case $.ui.keyCode.ESCAPE:
+ this.collapse( event );
+ break;
+ default:
+ preventDefault = false;
+ prev = this.previousFilter || "";
+ character = String.fromCharCode( event.keyCode );
+ skip = false;
+
+ clearTimeout( this.filterTimer );
+
+ if ( character === prev ) {
+ skip = true;
+ } else {
+ character = prev + character;
+ }
+
+ regex = new RegExp( "^" + escape( character ), "i" );
+ match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
+ return regex.test( $( this ).children( "a" ).text() );
+ });
+ match = skip && match.index( this.active.next() ) !== -1 ?
+ this.active.nextAll( ".ui-menu-item" ) :
+ match;
+
+ // If no matches on the current filter, reset to the last character pressed
+ // to move down the menu to the first item that starts with that character
+ if ( !match.length ) {
+ character = String.fromCharCode( event.keyCode );
+ regex = new RegExp( "^" + escape( character ), "i" );
+ match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
+ return regex.test( $( this ).children( "a" ).text() );
+ });
+ }
+
+ if ( match.length ) {
+ this.focus( event, match );
+ if ( match.length > 1 ) {
+ this.previousFilter = character;
+ this.filterTimer = this._delay(function() {
+ delete this.previousFilter;
+ }, 1000 );
+ } else {
+ delete this.previousFilter;
+ }
+ } else {
+ delete this.previousFilter;
+ }
+ }
+
+ if ( preventDefault ) {
+ event.preventDefault();
+ }
+ },
+
+ _activate: function( event ) {
+ if ( !this.active.is( ".ui-state-disabled" ) ) {
+ if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
+ this.expand( event );
+ } else {
+ this.select( event );
+ }
+ }
+ },
+
+ refresh: function() {
+ var menus,
+ icon = this.options.icons.submenu,
+ submenus = this.element.find( this.options.menus );
+
+ // Initialize nested menus
+ submenus.filter( ":not(.ui-menu)" )
+ .addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
+ .hide()
+ .attr({
+ role: this.options.role,
+ "aria-hidden": "true",
+ "aria-expanded": "false"
+ })
+ .each(function() {
+ var menu = $( this ),
+ item = menu.prev( "a" ),
+ submenuCarat = $( "<span>" )
+ .addClass( "ui-menu-icon ui-icon " + icon )
+ .data( "ui-menu-submenu-carat", true );
+
+ item
+ .attr( "aria-haspopup", "true" )
+ .prepend( submenuCarat );
+ menu.attr( "aria-labelledby", item.attr( "id" ) );
+ });
+
+ menus = submenus.add( this.element );
+
+ // Don't refresh list items that are already adapted
+ menus.children( ":not(.ui-menu-item):has(a)" )
+ .addClass( "ui-menu-item" )
+ .attr( "role", "presentation" )
+ .children( "a" )
+ .uniqueId()
+ .addClass( "ui-corner-all" )
+ .attr({
+ tabIndex: -1,
+ role: this._itemRole()
+ });
+
+ // Initialize unlinked menu-items containing spaces and/or dashes only as dividers
+ menus.children( ":not(.ui-menu-item)" ).each(function() {
+ var item = $( this );
+ // hyphen, em dash, en dash
+ if ( !/[^\-—–\s]/.test( item.text() ) ) {
+ item.addClass( "ui-widget-content ui-menu-divider" );
+ }
+ });
+
+ // Add aria-disabled attribute to any disabled menu item
+ menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
+
+ // If the active item has been removed, blur the menu
+ if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
+ this.blur();
+ }
+ },
+
+ _itemRole: function() {
+ return {
+ menu: "menuitem",
+ listbox: "option"
+ }[ this.options.role ];
+ },
+
+ focus: function( event, item ) {
+ var nested, focused;
+ this.blur( event, event && event.type === "focus" );
+
+ this._scrollIntoView( item );
+
+ this.active = item.first();
+ focused = this.active.children( "a" ).addClass( "ui-state-focus" );
+ // Only update aria-activedescendant if there's a role
+ // otherwise we assume focus is managed elsewhere
+ if ( this.options.role ) {
+ this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
+ }
+
+ // Highlight active parent menu item, if any
+ this.active
+ .parent()
+ .closest( ".ui-menu-item" )
+ .children( "a:first" )
+ .addClass( "ui-state-active" );
+
+ if ( event && event.type === "keydown" ) {
+ this._close();
+ } else {
+ this.timer = this._delay(function() {
+ this._close();
+ }, this.delay );
+ }
+
+ nested = item.children( ".ui-menu" );
+ if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
+ this._startOpening(nested);
+ }
+ this.activeMenu = item.parent();
+
+ this._trigger( "focus", event, { item: item } );
+ },
+
+ _scrollIntoView: function( item ) {
+ var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
+ if ( this._hasScroll() ) {
+ borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
+ paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
+ offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
+ scroll = this.activeMenu.scrollTop();
+ elementHeight = this.activeMenu.height();
+ itemHeight = item.height();
+
+ if ( offset < 0 ) {
+ this.activeMenu.scrollTop( scroll + offset );
+ } else if ( offset + itemHeight > elementHeight ) {
+ this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
+ }
+ }
+ },
+
+ blur: function( event, fromFocus ) {
+ if ( !fromFocus ) {
+ clearTimeout( this.timer );
+ }
+
+ if ( !this.active ) {
+ return;
+ }
+
+ this.active.children( "a" ).removeClass( "ui-state-focus" );
+ this.active = null;
+
+ this._trigger( "blur", event, { item: this.active } );
+ },
+
+ _startOpening: function( submenu ) {
+ clearTimeout( this.timer );
+
+ // Don't open if already open fixes a Firefox bug that caused a .5 pixel
+ // shift in the submenu position when mousing over the carat icon
+ if ( submenu.attr( "aria-hidden" ) !== "true" ) {
+ return;
+ }
+
+ this.timer = this._delay(function() {
+ this._close();
+ this._open( submenu );
+ }, this.delay );
+ },
+
+ _open: function( submenu ) {
+ var position = $.extend({
+ of: this.active
+ }, this.options.position );
+
+ clearTimeout( this.timer );
+ this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
+ .hide()
+ .attr( "aria-hidden", "true" );
+
+ submenu
+ .show()
+ .removeAttr( "aria-hidden" )
+ .attr( "aria-expanded", "true" )
+ .position( position );
+ },
+
+ collapseAll: function( event, all ) {
+ clearTimeout( this.timer );
+ this.timer = this._delay(function() {
+ // If we were passed an event, look for the submenu that contains the event
+ var currentMenu = all ? this.element :
+ $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
+
+ // If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
+ if ( !currentMenu.length ) {
+ currentMenu = this.element;
+ }
+
+ this._close( currentMenu );
+
+ this.blur( event );
+ this.activeMenu = currentMenu;
+ }, this.delay );
+ },
+
+ // With no arguments, closes the currently active menu - if nothing is active
+ // it closes all menus. If passed an argument, it will search for menus BELOW
+ _close: function( startMenu ) {
+ if ( !startMenu ) {
+ startMenu = this.active ? this.active.parent() : this.element;
+ }
+
+ startMenu
+ .find( ".ui-menu" )
+ .hide()
+ .attr( "aria-hidden", "true" )
+ .attr( "aria-expanded", "false" )
+ .end()
+ .find( "a.ui-state-active" )
+ .removeClass( "ui-state-active" );
+ },
+
+ collapse: function( event ) {
+ var newItem = this.active &&
+ this.active.parent().closest( ".ui-menu-item", this.element );
+ if ( newItem && newItem.length ) {
+ this._close();
+ this.focus( event, newItem );
+ }
+ },
+
+ expand: function( event ) {
+ var newItem = this.active &&
+ this.active
+ .children( ".ui-menu " )
+ .children( ".ui-menu-item" )
+ .first();
+
+ if ( newItem && newItem.length ) {
+ this._open( newItem.parent() );
+
+ // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
+ this._delay(function() {
+ this.focus( event, newItem );
+ });
+ }
+ },
+
+ next: function( event ) {
+ this._move( "next", "first", event );
+ },
+
+ previous: function( event ) {
+ this._move( "prev", "last", event );
+ },
+
+ isFirstItem: function() {
+ return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
+ },
+
+ isLastItem: function() {
+ return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
+ },
+
+ _move: function( direction, filter, event ) {
+ var next;
+ if ( this.active ) {
+ if ( direction === "first" || direction === "last" ) {
+ next = this.active
+ [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
+ .eq( -1 );
+ } else {
+ next = this.active
+ [ direction + "All" ]( ".ui-menu-item" )
+ .eq( 0 );
+ }
+ }
+ if ( !next || !next.length || !this.active ) {
+ next = this.activeMenu.children( ".ui-menu-item" )[ filter ]();
+ }
+
+ this.focus( event, next );
+ },
+
+ nextPage: function( event ) {
+ var item, base, height;
+
+ if ( !this.active ) {
+ this.next( event );
+ return;
+ }
+ if ( this.isLastItem() ) {
+ return;
+ }
+ if ( this._hasScroll() ) {
+ base = this.active.offset().top;
+ height = this.element.height();
+ this.active.nextAll( ".ui-menu-item" ).each(function() {
+ item = $( this );
+ return item.offset().top - base - height < 0;
+ });
+
+ this.focus( event, item );
+ } else {
+ this.focus( event, this.activeMenu.children( ".ui-menu-item" )
+ [ !this.active ? "first" : "last" ]() );
+ }
+ },
+
+ previousPage: function( event ) {
+ var item, base, height;
+ if ( !this.active ) {
+ this.next( event );
+ return;
+ }
+ if ( this.isFirstItem() ) {
+ return;
+ }
+ if ( this._hasScroll() ) {
+ base = this.active.offset().top;
+ height = this.element.height();
+ this.active.prevAll( ".ui-menu-item" ).each(function() {
+ item = $( this );
+ return item.offset().top - base + height > 0;
+ });
+
+ this.focus( event, item );
+ } else {
+ this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
+ }
+ },
+
+ _hasScroll: function() {
+ return this.element.outerHeight() < this.element.prop( "scrollHeight" );
+ },
+
+ select: function( event ) {
+ // TODO: It should never be possible to not have an active item at this
+ // point, but the tests don't trigger mouseenter before click.
+ this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
+ var ui = { item: this.active };
+ if ( !this.active.has( ".ui-menu" ).length ) {
+ this.collapseAll( event, true );
+ }
+ this._trigger( "select", event, ui );
+ }
+});
+
+}( jQuery ));
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.mouse.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.mouse.js
new file mode 100644
index 00000000..250365fe
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.mouse.js
@@ -0,0 +1,169 @@
+/*!
+ * jQuery UI Mouse 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/mouse/
+ *
+ * Depends:
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+var mouseHandled = false;
+$( document ).mouseup( function( e ) {
+ mouseHandled = false;
+});
+
+$.widget("ui.mouse", {
+ version: "1.9.2",
+ options: {
+ cancel: 'input,textarea,button,select,option',
+ distance: 1,
+ delay: 0
+ },
+ _mouseInit: function() {
+ var that = this;
+
+ this.element
+ .bind('mousedown.'+this.widgetName, function(event) {
+ return that._mouseDown(event);
+ })
+ .bind('click.'+this.widgetName, function(event) {
+ if (true === $.data(event.target, that.widgetName + '.preventClickEvent')) {
+ $.removeData(event.target, that.widgetName + '.preventClickEvent');
+ event.stopImmediatePropagation();
+ return false;
+ }
+ });
+
+ this.started = false;
+ },
+
+ // TODO: make sure destroying one instance of mouse doesn't mess with
+ // other instances of mouse
+ _mouseDestroy: function() {
+ this.element.unbind('.'+this.widgetName);
+ if ( this._mouseMoveDelegate ) {
+ $(document)
+ .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+ }
+ },
+
+ _mouseDown: function(event) {
+ // don't let more than one widget handle mouseStart
+ if( mouseHandled ) { return; }
+
+ // we may have missed mouseup (out of window)
+ (this._mouseStarted && this._mouseUp(event));
+
+ this._mouseDownEvent = event;
+
+ var that = this,
+ btnIsLeft = (event.which === 1),
+ // event.target.nodeName works around a bug in IE 8 with
+ // disabled inputs (#7620)
+ elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
+ if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
+ return true;
+ }
+
+ this.mouseDelayMet = !this.options.delay;
+ if (!this.mouseDelayMet) {
+ this._mouseDelayTimer = setTimeout(function() {
+ that.mouseDelayMet = true;
+ }, this.options.delay);
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted = (this._mouseStart(event) !== false);
+ if (!this._mouseStarted) {
+ event.preventDefault();
+ return true;
+ }
+ }
+
+ // Click event may never have fired (Gecko & Opera)
+ if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
+ $.removeData(event.target, this.widgetName + '.preventClickEvent');
+ }
+
+ // these delegates are required to keep context
+ this._mouseMoveDelegate = function(event) {
+ return that._mouseMove(event);
+ };
+ this._mouseUpDelegate = function(event) {
+ return that._mouseUp(event);
+ };
+ $(document)
+ .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+ event.preventDefault();
+
+ mouseHandled = true;
+ return true;
+ },
+
+ _mouseMove: function(event) {
+ // IE mouseup check - mouseup happened when mouse was out of window
+ if ($.ui.ie && !(document.documentMode >= 9) && !event.button) {
+ return this._mouseUp(event);
+ }
+
+ if (this._mouseStarted) {
+ this._mouseDrag(event);
+ return event.preventDefault();
+ }
+
+ if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
+ this._mouseStarted =
+ (this._mouseStart(this._mouseDownEvent, event) !== false);
+ (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
+ }
+
+ return !this._mouseStarted;
+ },
+
+ _mouseUp: function(event) {
+ $(document)
+ .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
+ .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
+
+ if (this._mouseStarted) {
+ this._mouseStarted = false;
+
+ if (event.target === this._mouseDownEvent.target) {
+ $.data(event.target, this.widgetName + '.preventClickEvent', true);
+ }
+
+ this._mouseStop(event);
+ }
+
+ return false;
+ },
+
+ _mouseDistanceMet: function(event) {
+ return (Math.max(
+ Math.abs(this._mouseDownEvent.pageX - event.pageX),
+ Math.abs(this._mouseDownEvent.pageY - event.pageY)
+ ) >= this.options.distance
+ );
+ },
+
+ _mouseDelayMet: function(event) {
+ return this.mouseDelayMet;
+ },
+
+ // These are placeholder methods, to be overriden by extending plugin
+ _mouseStart: function(event) {},
+ _mouseDrag: function(event) {},
+ _mouseStop: function(event) {},
+ _mouseCapture: function(event) { return true; }
+});
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.position.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.position.js
new file mode 100644
index 00000000..be99013e
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.position.js
@@ -0,0 +1,517 @@
+/*!
+ * jQuery UI Position 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/position/
+ */
+(function( $, undefined ) {
+
+$.ui = $.ui || {};
+
+var cachedScrollbarWidth,
+ max = Math.max,
+ abs = Math.abs,
+ round = Math.round,
+ rhorizontal = /left|center|right/,
+ rvertical = /top|center|bottom/,
+ roffset = /[\+\-]\d+%?/,
+ rposition = /^\w+/,
+ rpercent = /%$/,
+ _position = $.fn.position;
+
+function getOffsets( offsets, width, height ) {
+ return [
+ parseInt( offsets[ 0 ], 10 ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
+ parseInt( offsets[ 1 ], 10 ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
+ ];
+}
+function parseCss( element, property ) {
+ return parseInt( $.css( element, property ), 10 ) || 0;
+}
+
+$.position = {
+ scrollbarWidth: function() {
+ if ( cachedScrollbarWidth !== undefined ) {
+ return cachedScrollbarWidth;
+ }
+ var w1, w2,
+ div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
+ innerDiv = div.children()[0];
+
+ $( "body" ).append( div );
+ w1 = innerDiv.offsetWidth;
+ div.css( "overflow", "scroll" );
+
+ w2 = innerDiv.offsetWidth;
+
+ if ( w1 === w2 ) {
+ w2 = div[0].clientWidth;
+ }
+
+ div.remove();
+
+ return (cachedScrollbarWidth = w1 - w2);
+ },
+ getScrollInfo: function( within ) {
+ var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
+ overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
+ hasOverflowX = overflowX === "scroll" ||
+ ( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
+ hasOverflowY = overflowY === "scroll" ||
+ ( overflowY === "auto" && within.height < within.element[0].scrollHeight );
+ return {
+ width: hasOverflowX ? $.position.scrollbarWidth() : 0,
+ height: hasOverflowY ? $.position.scrollbarWidth() : 0
+ };
+ },
+ getWithinInfo: function( element ) {
+ var withinElement = $( element || window ),
+ isWindow = $.isWindow( withinElement[0] );
+ return {
+ element: withinElement,
+ isWindow: isWindow,
+ offset: withinElement.offset() || { left: 0, top: 0 },
+ scrollLeft: withinElement.scrollLeft(),
+ scrollTop: withinElement.scrollTop(),
+ width: isWindow ? withinElement.width() : withinElement.outerWidth(),
+ height: isWindow ? withinElement.height() : withinElement.outerHeight()
+ };
+ }
+};
+
+$.fn.position = function( options ) {
+ if ( !options || !options.of ) {
+ return _position.apply( this, arguments );
+ }
+
+ // make a copy, we don't want to modify arguments
+ options = $.extend( {}, options );
+
+ var atOffset, targetWidth, targetHeight, targetOffset, basePosition,
+ target = $( options.of ),
+ within = $.position.getWithinInfo( options.within ),
+ scrollInfo = $.position.getScrollInfo( within ),
+ targetElem = target[0],
+ collision = ( options.collision || "flip" ).split( " " ),
+ offsets = {};
+
+ if ( targetElem.nodeType === 9 ) {
+ targetWidth = target.width();
+ targetHeight = target.height();
+ targetOffset = { top: 0, left: 0 };
+ } else if ( $.isWindow( targetElem ) ) {
+ targetWidth = target.width();
+ targetHeight = target.height();
+ targetOffset = { top: target.scrollTop(), left: target.scrollLeft() };
+ } else if ( targetElem.preventDefault ) {
+ // force left top to allow flipping
+ options.at = "left top";
+ targetWidth = targetHeight = 0;
+ targetOffset = { top: targetElem.pageY, left: targetElem.pageX };
+ } else {
+ targetWidth = target.outerWidth();
+ targetHeight = target.outerHeight();
+ targetOffset = target.offset();
+ }
+ // clone to reuse original targetOffset later
+ basePosition = $.extend( {}, targetOffset );
+
+ // force my and at to have valid horizontal and vertical positions
+ // if a value is missing or invalid, it will be converted to center
+ $.each( [ "my", "at" ], function() {
+ var pos = ( options[ this ] || "" ).split( " " ),
+ horizontalOffset,
+ verticalOffset;
+
+ if ( pos.length === 1) {
+ pos = rhorizontal.test( pos[ 0 ] ) ?
+ pos.concat( [ "center" ] ) :
+ rvertical.test( pos[ 0 ] ) ?
+ [ "center" ].concat( pos ) :
+ [ "center", "center" ];
+ }
+ pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
+ pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
+
+ // calculate offsets
+ horizontalOffset = roffset.exec( pos[ 0 ] );
+ verticalOffset = roffset.exec( pos[ 1 ] );
+ offsets[ this ] = [
+ horizontalOffset ? horizontalOffset[ 0 ] : 0,
+ verticalOffset ? verticalOffset[ 0 ] : 0
+ ];
+
+ // reduce to just the positions without the offsets
+ options[ this ] = [
+ rposition.exec( pos[ 0 ] )[ 0 ],
+ rposition.exec( pos[ 1 ] )[ 0 ]
+ ];
+ });
+
+ // normalize collision option
+ if ( collision.length === 1 ) {
+ collision[ 1 ] = collision[ 0 ];
+ }
+
+ if ( options.at[ 0 ] === "right" ) {
+ basePosition.left += targetWidth;
+ } else if ( options.at[ 0 ] === "center" ) {
+ basePosition.left += targetWidth / 2;
+ }
+
+ if ( options.at[ 1 ] === "bottom" ) {
+ basePosition.top += targetHeight;
+ } else if ( options.at[ 1 ] === "center" ) {
+ basePosition.top += targetHeight / 2;
+ }
+
+ atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
+ basePosition.left += atOffset[ 0 ];
+ basePosition.top += atOffset[ 1 ];
+
+ return this.each(function() {
+ var collisionPosition, using,
+ elem = $( this ),
+ elemWidth = elem.outerWidth(),
+ elemHeight = elem.outerHeight(),
+ marginLeft = parseCss( this, "marginLeft" ),
+ marginTop = parseCss( this, "marginTop" ),
+ collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
+ collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
+ position = $.extend( {}, basePosition ),
+ myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
+
+ if ( options.my[ 0 ] === "right" ) {
+ position.left -= elemWidth;
+ } else if ( options.my[ 0 ] === "center" ) {
+ position.left -= elemWidth / 2;
+ }
+
+ if ( options.my[ 1 ] === "bottom" ) {
+ position.top -= elemHeight;
+ } else if ( options.my[ 1 ] === "center" ) {
+ position.top -= elemHeight / 2;
+ }
+
+ position.left += myOffset[ 0 ];
+ position.top += myOffset[ 1 ];
+
+ // if the browser doesn't support fractions, then round for consistent results
+ if ( !$.support.offsetFractions ) {
+ position.left = round( position.left );
+ position.top = round( position.top );
+ }
+
+ collisionPosition = {
+ marginLeft: marginLeft,
+ marginTop: marginTop
+ };
+
+ $.each( [ "left", "top" ], function( i, dir ) {
+ if ( $.ui.position[ collision[ i ] ] ) {
+ $.ui.position[ collision[ i ] ][ dir ]( position, {
+ targetWidth: targetWidth,
+ targetHeight: targetHeight,
+ elemWidth: elemWidth,
+ elemHeight: elemHeight,
+ collisionPosition: collisionPosition,
+ collisionWidth: collisionWidth,
+ collisionHeight: collisionHeight,
+ offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
+ my: options.my,
+ at: options.at,
+ within: within,
+ elem : elem
+ });
+ }
+ });
+
+ if ( $.fn.bgiframe ) {
+ elem.bgiframe();
+ }
+
+ if ( options.using ) {
+ // adds feedback as second argument to using callback, if present
+ using = function( props ) {
+ var left = targetOffset.left - position.left,
+ right = left + targetWidth - elemWidth,
+ top = targetOffset.top - position.top,
+ bottom = top + targetHeight - elemHeight,
+ feedback = {
+ target: {
+ element: target,
+ left: targetOffset.left,
+ top: targetOffset.top,
+ width: targetWidth,
+ height: targetHeight
+ },
+ element: {
+ element: elem,
+ left: position.left,
+ top: position.top,
+ width: elemWidth,
+ height: elemHeight
+ },
+ horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
+ vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
+ };
+ if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
+ feedback.horizontal = "center";
+ }
+ if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
+ feedback.vertical = "middle";
+ }
+ if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
+ feedback.important = "horizontal";
+ } else {
+ feedback.important = "vertical";
+ }
+ options.using.call( this, props, feedback );
+ };
+ }
+
+ elem.offset( $.extend( position, { using: using } ) );
+ });
+};
+
+$.ui.position = {
+ fit: {
+ left: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
+ outerWidth = within.width,
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+ overLeft = withinOffset - collisionPosLeft,
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
+ newOverRight;
+
+ // element is wider than within
+ if ( data.collisionWidth > outerWidth ) {
+ // element is initially over the left side of within
+ if ( overLeft > 0 && overRight <= 0 ) {
+ newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
+ position.left += overLeft - newOverRight;
+ // element is initially over right side of within
+ } else if ( overRight > 0 && overLeft <= 0 ) {
+ position.left = withinOffset;
+ // element is initially over both left and right sides of within
+ } else {
+ if ( overLeft > overRight ) {
+ position.left = withinOffset + outerWidth - data.collisionWidth;
+ } else {
+ position.left = withinOffset;
+ }
+ }
+ // too far left -> align with left edge
+ } else if ( overLeft > 0 ) {
+ position.left += overLeft;
+ // too far right -> align with right edge
+ } else if ( overRight > 0 ) {
+ position.left -= overRight;
+ // adjust based on position and margin
+ } else {
+ position.left = max( position.left - collisionPosLeft, position.left );
+ }
+ },
+ top: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
+ outerHeight = data.within.height,
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
+ overTop = withinOffset - collisionPosTop,
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
+ newOverBottom;
+
+ // element is taller than within
+ if ( data.collisionHeight > outerHeight ) {
+ // element is initially over the top of within
+ if ( overTop > 0 && overBottom <= 0 ) {
+ newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
+ position.top += overTop - newOverBottom;
+ // element is initially over bottom of within
+ } else if ( overBottom > 0 && overTop <= 0 ) {
+ position.top = withinOffset;
+ // element is initially over both top and bottom of within
+ } else {
+ if ( overTop > overBottom ) {
+ position.top = withinOffset + outerHeight - data.collisionHeight;
+ } else {
+ position.top = withinOffset;
+ }
+ }
+ // too far up -> align with top
+ } else if ( overTop > 0 ) {
+ position.top += overTop;
+ // too far down -> align with bottom edge
+ } else if ( overBottom > 0 ) {
+ position.top -= overBottom;
+ // adjust based on position and margin
+ } else {
+ position.top = max( position.top - collisionPosTop, position.top );
+ }
+ }
+ },
+ flip: {
+ left: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.offset.left + within.scrollLeft,
+ outerWidth = within.width,
+ offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
+ collisionPosLeft = position.left - data.collisionPosition.marginLeft,
+ overLeft = collisionPosLeft - offsetLeft,
+ overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
+ myOffset = data.my[ 0 ] === "left" ?
+ -data.elemWidth :
+ data.my[ 0 ] === "right" ?
+ data.elemWidth :
+ 0,
+ atOffset = data.at[ 0 ] === "left" ?
+ data.targetWidth :
+ data.at[ 0 ] === "right" ?
+ -data.targetWidth :
+ 0,
+ offset = -2 * data.offset[ 0 ],
+ newOverRight,
+ newOverLeft;
+
+ if ( overLeft < 0 ) {
+ newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
+ if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
+ position.left += myOffset + atOffset + offset;
+ }
+ }
+ else if ( overRight > 0 ) {
+ newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
+ if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
+ position.left += myOffset + atOffset + offset;
+ }
+ }
+ },
+ top: function( position, data ) {
+ var within = data.within,
+ withinOffset = within.offset.top + within.scrollTop,
+ outerHeight = within.height,
+ offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
+ collisionPosTop = position.top - data.collisionPosition.marginTop,
+ overTop = collisionPosTop - offsetTop,
+ overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
+ top = data.my[ 1 ] === "top",
+ myOffset = top ?
+ -data.elemHeight :
+ data.my[ 1 ] === "bottom" ?
+ data.elemHeight :
+ 0,
+ atOffset = data.at[ 1 ] === "top" ?
+ data.targetHeight :
+ data.at[ 1 ] === "bottom" ?
+ -data.targetHeight :
+ 0,
+ offset = -2 * data.offset[ 1 ],
+ newOverTop,
+ newOverBottom;
+ if ( overTop < 0 ) {
+ newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
+ if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
+ position.top += myOffset + atOffset + offset;
+ }
+ }
+ else if ( overBottom > 0 ) {
+ newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
+ if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
+ position.top += myOffset + atOffset + offset;
+ }
+ }
+ }
+ },
+ flipfit: {
+ left: function() {
+ $.ui.position.flip.left.apply( this, arguments );
+ $.ui.position.fit.left.apply( this, arguments );
+ },
+ top: function() {
+ $.ui.position.flip.top.apply( this, arguments );
+ $.ui.position.fit.top.apply( this, arguments );
+ }
+ }
+};
+
+// fraction support test
+(function () {
+ var testElement, testElementParent, testElementStyle, offsetLeft, i,
+ body = document.getElementsByTagName( "body" )[ 0 ],
+ div = document.createElement( "div" );
+
+ //Create a "fake body" for testing based on method used in jQuery.support
+ testElement = document.createElement( body ? "div" : "body" );
+ testElementStyle = {
+ visibility: "hidden",
+ width: 0,
+ height: 0,
+ border: 0,
+ margin: 0,
+ background: "none"
+ };
+ if ( body ) {
+ $.extend( testElementStyle, {
+ position: "absolute",
+ left: "-1000px",
+ top: "-1000px"
+ });
+ }
+ for ( i in testElementStyle ) {
+ testElement.style[ i ] = testElementStyle[ i ];
+ }
+ testElement.appendChild( div );
+ testElementParent = body || document.documentElement;
+ testElementParent.insertBefore( testElement, testElementParent.firstChild );
+
+ div.style.cssText = "position: absolute; left: 10.7432222px;";
+
+ offsetLeft = $( div ).offset().left;
+ $.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;
+
+ testElement.innerHTML = "";
+ testElementParent.removeChild( testElement );
+})();
+
+// DEPRECATED
+if ( $.uiBackCompat !== false ) {
+ // offset option
+ (function( $ ) {
+ var _position = $.fn.position;
+ $.fn.position = function( options ) {
+ if ( !options || !options.offset ) {
+ return _position.call( this, options );
+ }
+ var offset = options.offset.split( " " ),
+ at = options.at.split( " " );
+ if ( offset.length === 1 ) {
+ offset[ 1 ] = offset[ 0 ];
+ }
+ if ( /^\d/.test( offset[ 0 ] ) ) {
+ offset[ 0 ] = "+" + offset[ 0 ];
+ }
+ if ( /^\d/.test( offset[ 1 ] ) ) {
+ offset[ 1 ] = "+" + offset[ 1 ];
+ }
+ if ( at.length === 1 ) {
+ if ( /left|center|right/.test( at[ 0 ] ) ) {
+ at[ 1 ] = "center";
+ } else {
+ at[ 1 ] = at[ 0 ];
+ at[ 0 ] = "center";
+ }
+ }
+ return _position.call( this, $.extend( options, {
+ at: at[ 0 ] + offset[ 0 ] + " " + at[ 1 ] + offset[ 1 ],
+ offset: undefined
+ } ) );
+ };
+ }( jQuery ) );
+}
+
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.progressbar.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.progressbar.js
new file mode 100644
index 00000000..4aa19d83
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.progressbar.js
@@ -0,0 +1,105 @@
+/*!
+ * jQuery UI Progressbar 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/progressbar/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget( "ui.progressbar", {
+ version: "1.9.2",
+ options: {
+ value: 0,
+ max: 100
+ },
+
+ min: 0,
+
+ _create: function() {
+ this.element
+ .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
+ .attr({
+ role: "progressbar",
+ "aria-valuemin": this.min,
+ "aria-valuemax": this.options.max,
+ "aria-valuenow": this._value()
+ });
+
+ this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
+ .appendTo( this.element );
+
+ this.oldValue = this._value();
+ this._refreshValue();
+ },
+
+ _destroy: function() {
+ this.element
+ .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-valuemin" )
+ .removeAttr( "aria-valuemax" )
+ .removeAttr( "aria-valuenow" );
+
+ this.valueDiv.remove();
+ },
+
+ value: function( newValue ) {
+ if ( newValue === undefined ) {
+ return this._value();
+ }
+
+ this._setOption( "value", newValue );
+ return this;
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "value" ) {
+ this.options.value = value;
+ this._refreshValue();
+ if ( this._value() === this.options.max ) {
+ this._trigger( "complete" );
+ }
+ }
+
+ this._super( key, value );
+ },
+
+ _value: function() {
+ var val = this.options.value;
+ // normalize invalid value
+ if ( typeof val !== "number" ) {
+ val = 0;
+ }
+ return Math.min( this.options.max, Math.max( this.min, val ) );
+ },
+
+ _percentage: function() {
+ return 100 * this._value() / this.options.max;
+ },
+
+ _refreshValue: function() {
+ var value = this.value(),
+ percentage = this._percentage();
+
+ if ( this.oldValue !== value ) {
+ this.oldValue = value;
+ this._trigger( "change" );
+ }
+
+ this.valueDiv
+ .toggle( value > this.min )
+ .toggleClass( "ui-corner-right", value === this.options.max )
+ .width( percentage.toFixed(0) + "%" );
+ this.element.attr( "aria-valuenow", value );
+ }
+});
+
+})( jQuery );
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.resizable.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.resizable.js
new file mode 100644
index 00000000..bb277e23
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.resizable.js
@@ -0,0 +1,801 @@
+/*!
+ * jQuery UI Resizable 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/resizable/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.resizable", $.ui.mouse, {
+ version: "1.9.2",
+ widgetEventPrefix: "resize",
+ options: {
+ alsoResize: false,
+ animate: false,
+ animateDuration: "slow",
+ animateEasing: "swing",
+ aspectRatio: false,
+ autoHide: false,
+ containment: false,
+ ghost: false,
+ grid: false,
+ handles: "e,s,se",
+ helper: false,
+ maxHeight: null,
+ maxWidth: null,
+ minHeight: 10,
+ minWidth: 10,
+ zIndex: 1000
+ },
+ _create: function() {
+
+ var that = this, o = this.options;
+ this.element.addClass("ui-resizable");
+
+ $.extend(this, {
+ _aspectRatio: !!(o.aspectRatio),
+ aspectRatio: o.aspectRatio,
+ originalElement: this.element,
+ _proportionallyResizeElements: [],
+ _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
+ });
+
+ //Wrap the element if it cannot hold child nodes
+ if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
+
+ //Create a wrapper element and set the wrapper to the new current internal element
+ this.element.wrap(
+ $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
+ position: this.element.css('position'),
+ width: this.element.outerWidth(),
+ height: this.element.outerHeight(),
+ top: this.element.css('top'),
+ left: this.element.css('left')
+ })
+ );
+
+ //Overwrite the original this.element
+ this.element = this.element.parent().data(
+ "resizable", this.element.data('resizable')
+ );
+
+ this.elementIsWrapper = true;
+
+ //Move margins to the wrapper
+ this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
+ this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
+
+ //Prevent Safari textarea resize
+ this.originalResizeStyle = this.originalElement.css('resize');
+ this.originalElement.css('resize', 'none');
+
+ //Push the actual element to our proportionallyResize internal array
+ this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
+
+ // avoid IE jump (hard set the margin)
+ this.originalElement.css({ margin: this.originalElement.css('margin') });
+
+ // fix handlers offset
+ this._proportionallyResize();
+
+ }
+
+ this.handles = o.handles || (!$('.ui-resizable-handle', this.element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' });
+ if(this.handles.constructor == String) {
+
+ if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
+ var n = this.handles.split(","); this.handles = {};
+
+ for(var i = 0; i < n.length; i++) {
+
+ var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
+ var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
+
+ // Apply zIndex to all handles - see #7960
+ axis.css({ zIndex: o.zIndex });
+
+ //TODO : What's going on here?
+ if ('se' == handle) {
+ axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
+ };
+
+ //Insert into internal handles object and append to element
+ this.handles[handle] = '.ui-resizable-'+handle;
+ this.element.append(axis);
+ }
+
+ }
+
+ this._renderAxis = function(target) {
+
+ target = target || this.element;
+
+ for(var i in this.handles) {
+
+ if(this.handles[i].constructor == String)
+ this.handles[i] = $(this.handles[i], this.element).show();
+
+ //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
+ if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
+
+ var axis = $(this.handles[i], this.element), padWrapper = 0;
+
+ //Checking the correct pad and border
+ padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
+
+ //The padding type i have to apply...
+ var padPos = [ 'padding',
+ /ne|nw|n/.test(i) ? 'Top' :
+ /se|sw|s/.test(i) ? 'Bottom' :
+ /^e$/.test(i) ? 'Right' : 'Left' ].join("");
+
+ target.css(padPos, padWrapper);
+
+ this._proportionallyResize();
+
+ }
+
+ //TODO: What's that good for? There's not anything to be executed left
+ if(!$(this.handles[i]).length)
+ continue;
+
+ }
+ };
+
+ //TODO: make renderAxis a prototype function
+ this._renderAxis(this.element);
+
+ this._handles = $('.ui-resizable-handle', this.element)
+ .disableSelection();
+
+ //Matching axis name
+ this._handles.mouseover(function() {
+ if (!that.resizing) {
+ if (this.className)
+ var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
+ //Axis, default = se
+ that.axis = axis && axis[1] ? axis[1] : 'se';
+ }
+ });
+
+ //If we want to auto hide the elements
+ if (o.autoHide) {
+ this._handles.hide();
+ $(this.element)
+ .addClass("ui-resizable-autohide")
+ .mouseenter(function() {
+ if (o.disabled) return;
+ $(this).removeClass("ui-resizable-autohide");
+ that._handles.show();
+ })
+ .mouseleave(function(){
+ if (o.disabled) return;
+ if (!that.resizing) {
+ $(this).addClass("ui-resizable-autohide");
+ that._handles.hide();
+ }
+ });
+ }
+
+ //Initialize the mouse interaction
+ this._mouseInit();
+
+ },
+
+ _destroy: function() {
+
+ this._mouseDestroy();
+
+ var _destroy = function(exp) {
+ $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
+ .removeData("resizable").removeData("ui-resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
+ };
+
+ //TODO: Unwrap at same DOM position
+ if (this.elementIsWrapper) {
+ _destroy(this.element);
+ var wrapper = this.element;
+ this.originalElement.css({
+ position: wrapper.css('position'),
+ width: wrapper.outerWidth(),
+ height: wrapper.outerHeight(),
+ top: wrapper.css('top'),
+ left: wrapper.css('left')
+ }).insertAfter( wrapper );
+ wrapper.remove();
+ }
+
+ this.originalElement.css('resize', this.originalResizeStyle);
+ _destroy(this.originalElement);
+
+ return this;
+ },
+
+ _mouseCapture: function(event) {
+ var handle = false;
+ for (var i in this.handles) {
+ if ($(this.handles[i])[0] == event.target) {
+ handle = true;
+ }
+ }
+
+ return !this.options.disabled && handle;
+ },
+
+ _mouseStart: function(event) {
+
+ var o = this.options, iniPos = this.element.position(), el = this.element;
+
+ this.resizing = true;
+ this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
+
+ // bugfix for http://dev.jquery.com/ticket/1749
+ if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
+ el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
+ }
+
+ this._renderProxy();
+
+ var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
+
+ if (o.containment) {
+ curleft += $(o.containment).scrollLeft() || 0;
+ curtop += $(o.containment).scrollTop() || 0;
+ }
+
+ //Store needed variables
+ this.offset = this.helper.offset();
+ this.position = { left: curleft, top: curtop };
+ this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+ this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
+ this.originalPosition = { left: curleft, top: curtop };
+ this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
+ this.originalMousePosition = { left: event.pageX, top: event.pageY };
+
+ //Aspect Ratio
+ this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
+
+ var cursor = $('.ui-resizable-' + this.axis).css('cursor');
+ $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
+
+ el.addClass("ui-resizable-resizing");
+ this._propagate("start", event);
+ return true;
+ },
+
+ _mouseDrag: function(event) {
+
+ //Increase performance, avoid regex
+ var el = this.helper, o = this.options, props = {},
+ that = this, smp = this.originalMousePosition, a = this.axis;
+
+ var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
+ var trigger = this._change[a];
+ if (!trigger) return false;
+
+ // Calculate the attrs that will be change
+ var data = trigger.apply(this, [event, dx, dy]);
+
+ // Put this in the mouseDrag handler since the user can start pressing shift while resizing
+ this._updateVirtualBoundaries(event.shiftKey);
+ if (this._aspectRatio || event.shiftKey)
+ data = this._updateRatio(data, event);
+
+ data = this._respectSize(data, event);
+
+ // plugins callbacks need to be called first
+ this._propagate("resize", event);
+
+ el.css({
+ top: this.position.top + "px", left: this.position.left + "px",
+ width: this.size.width + "px", height: this.size.height + "px"
+ });
+
+ if (!this._helper && this._proportionallyResizeElements.length)
+ this._proportionallyResize();
+
+ this._updateCache(data);
+
+ // calling the user callback at the end
+ this._trigger('resize', event, this.ui());
+
+ return false;
+ },
+
+ _mouseStop: function(event) {
+
+ this.resizing = false;
+ var o = this.options, that = this;
+
+ if(this._helper) {
+ var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
+ soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height,
+ soffsetw = ista ? 0 : that.sizeDiff.width;
+
+ var s = { width: (that.helper.width() - soffsetw), height: (that.helper.height() - soffseth) },
+ left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null,
+ top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null;
+
+ if (!o.animate)
+ this.element.css($.extend(s, { top: top, left: left }));
+
+ that.helper.height(that.size.height);
+ that.helper.width(that.size.width);
+
+ if (this._helper && !o.animate) this._proportionallyResize();
+ }
+
+ $('body').css('cursor', 'auto');
+
+ this.element.removeClass("ui-resizable-resizing");
+
+ this._propagate("stop", event);
+
+ if (this._helper) this.helper.remove();
+ return false;
+
+ },
+
+ _updateVirtualBoundaries: function(forceAspectRatio) {
+ var o = this.options, pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b;
+
+ b = {
+ minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
+ maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
+ minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
+ maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
+ };
+
+ if(this._aspectRatio || forceAspectRatio) {
+ // We want to create an enclosing box whose aspect ration is the requested one
+ // First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
+ pMinWidth = b.minHeight * this.aspectRatio;
+ pMinHeight = b.minWidth / this.aspectRatio;
+ pMaxWidth = b.maxHeight * this.aspectRatio;
+ pMaxHeight = b.maxWidth / this.aspectRatio;
+
+ if(pMinWidth > b.minWidth) b.minWidth = pMinWidth;
+ if(pMinHeight > b.minHeight) b.minHeight = pMinHeight;
+ if(pMaxWidth < b.maxWidth) b.maxWidth = pMaxWidth;
+ if(pMaxHeight < b.maxHeight) b.maxHeight = pMaxHeight;
+ }
+ this._vBoundaries = b;
+ },
+
+ _updateCache: function(data) {
+ var o = this.options;
+ this.offset = this.helper.offset();
+ if (isNumber(data.left)) this.position.left = data.left;
+ if (isNumber(data.top)) this.position.top = data.top;
+ if (isNumber(data.height)) this.size.height = data.height;
+ if (isNumber(data.width)) this.size.width = data.width;
+ },
+
+ _updateRatio: function(data, event) {
+
+ var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
+
+ if (isNumber(data.height)) data.width = (data.height * this.aspectRatio);
+ else if (isNumber(data.width)) data.height = (data.width / this.aspectRatio);
+
+ if (a == 'sw') {
+ data.left = cpos.left + (csize.width - data.width);
+ data.top = null;
+ }
+ if (a == 'nw') {
+ data.top = cpos.top + (csize.height - data.height);
+ data.left = cpos.left + (csize.width - data.width);
+ }
+
+ return data;
+ },
+
+ _respectSize: function(data, event) {
+
+ var el = this.helper, o = this._vBoundaries, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
+ ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
+ isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
+
+ if (isminw) data.width = o.minWidth;
+ if (isminh) data.height = o.minHeight;
+ if (ismaxw) data.width = o.maxWidth;
+ if (ismaxh) data.height = o.maxHeight;
+
+ var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
+ var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
+
+ if (isminw && cw) data.left = dw - o.minWidth;
+ if (ismaxw && cw) data.left = dw - o.maxWidth;
+ if (isminh && ch) data.top = dh - o.minHeight;
+ if (ismaxh && ch) data.top = dh - o.maxHeight;
+
+ // fixing jump error on top/left - bug #2330
+ var isNotwh = !data.width && !data.height;
+ if (isNotwh && !data.left && data.top) data.top = null;
+ else if (isNotwh && !data.top && data.left) data.left = null;
+
+ return data;
+ },
+
+ _proportionallyResize: function() {
+
+ var o = this.options;
+ if (!this._proportionallyResizeElements.length) return;
+ var element = this.helper || this.element;
+
+ for (var i=0; i < this._proportionallyResizeElements.length; i++) {
+
+ var prel = this._proportionallyResizeElements[i];
+
+ if (!this.borderDif) {
+ var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
+ p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
+
+ this.borderDif = $.map(b, function(v, i) {
+ var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
+ return border + padding;
+ });
+ }
+
+ prel.css({
+ height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
+ width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
+ });
+
+ };
+
+ },
+
+ _renderProxy: function() {
+
+ var el = this.element, o = this.options;
+ this.elementOffset = el.offset();
+
+ if(this._helper) {
+
+ this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
+
+ // fix ie6 offset TODO: This seems broken
+ var ie6offset = ($.ui.ie6 ? 1 : 0),
+ pxyoffset = ( $.ui.ie6 ? 2 : -1 );
+
+ this.helper.addClass(this._helper).css({
+ width: this.element.outerWidth() + pxyoffset,
+ height: this.element.outerHeight() + pxyoffset,
+ position: 'absolute',
+ left: this.elementOffset.left - ie6offset +'px',
+ top: this.elementOffset.top - ie6offset +'px',
+ zIndex: ++o.zIndex //TODO: Don't modify option
+ });
+
+ this.helper
+ .appendTo("body")
+ .disableSelection();
+
+ } else {
+ this.helper = this.element;
+ }
+
+ },
+
+ _change: {
+ e: function(event, dx, dy) {
+ return { width: this.originalSize.width + dx };
+ },
+ w: function(event, dx, dy) {
+ var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+ return { left: sp.left + dx, width: cs.width - dx };
+ },
+ n: function(event, dx, dy) {
+ var o = this.options, cs = this.originalSize, sp = this.originalPosition;
+ return { top: sp.top + dy, height: cs.height - dy };
+ },
+ s: function(event, dx, dy) {
+ return { height: this.originalSize.height + dy };
+ },
+ se: function(event, dx, dy) {
+ return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
+ },
+ sw: function(event, dx, dy) {
+ return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
+ },
+ ne: function(event, dx, dy) {
+ return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
+ },
+ nw: function(event, dx, dy) {
+ return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
+ }
+ },
+
+ _propagate: function(n, event) {
+ $.ui.plugin.call(this, n, [event, this.ui()]);
+ (n != "resize" && this._trigger(n, event, this.ui()));
+ },
+
+ plugins: {},
+
+ ui: function() {
+ return {
+ originalElement: this.originalElement,
+ element: this.element,
+ helper: this.helper,
+ position: this.position,
+ size: this.size,
+ originalSize: this.originalSize,
+ originalPosition: this.originalPosition
+ };
+ }
+
+});
+
+/*
+ * Resizable Extensions
+ */
+
+$.ui.plugin.add("resizable", "alsoResize", {
+
+ start: function (event, ui) {
+ var that = $(this).data("resizable"), o = that.options;
+
+ var _store = function (exp) {
+ $(exp).each(function() {
+ var el = $(this);
+ el.data("resizable-alsoresize", {
+ width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
+ left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10)
+ });
+ });
+ };
+
+ if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
+ if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
+ else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
+ }else{
+ _store(o.alsoResize);
+ }
+ },
+
+ resize: function (event, ui) {
+ var that = $(this).data("resizable"), o = that.options, os = that.originalSize, op = that.originalPosition;
+
+ var delta = {
+ height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
+ top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
+ },
+
+ _alsoResize = function (exp, c) {
+ $(exp).each(function() {
+ var el = $(this), start = $(this).data("resizable-alsoresize"), style = {},
+ css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
+
+ $.each(css, function (i, prop) {
+ var sum = (start[prop]||0) + (delta[prop]||0);
+ if (sum && sum >= 0)
+ style[prop] = sum || null;
+ });
+
+ el.css(style);
+ });
+ };
+
+ if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
+ $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
+ }else{
+ _alsoResize(o.alsoResize);
+ }
+ },
+
+ stop: function (event, ui) {
+ $(this).removeData("resizable-alsoresize");
+ }
+});
+
+$.ui.plugin.add("resizable", "animate", {
+
+ stop: function(event, ui) {
+ var that = $(this).data("resizable"), o = that.options;
+
+ var pr = that._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
+ soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : that.sizeDiff.height,
+ soffsetw = ista ? 0 : that.sizeDiff.width;
+
+ var style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
+ left = (parseInt(that.element.css('left'), 10) + (that.position.left - that.originalPosition.left)) || null,
+ top = (parseInt(that.element.css('top'), 10) + (that.position.top - that.originalPosition.top)) || null;
+
+ that.element.animate(
+ $.extend(style, top && left ? { top: top, left: left } : {}), {
+ duration: o.animateDuration,
+ easing: o.animateEasing,
+ step: function() {
+
+ var data = {
+ width: parseInt(that.element.css('width'), 10),
+ height: parseInt(that.element.css('height'), 10),
+ top: parseInt(that.element.css('top'), 10),
+ left: parseInt(that.element.css('left'), 10)
+ };
+
+ if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
+
+ // propagating resize, and updating values for each animation step
+ that._updateCache(data);
+ that._propagate("resize", event);
+
+ }
+ }
+ );
+ }
+
+});
+
+$.ui.plugin.add("resizable", "containment", {
+
+ start: function(event, ui) {
+ var that = $(this).data("resizable"), o = that.options, el = that.element;
+ var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
+ if (!ce) return;
+
+ that.containerElement = $(ce);
+
+ if (/document/.test(oc) || oc == document) {
+ that.containerOffset = { left: 0, top: 0 };
+ that.containerPosition = { left: 0, top: 0 };
+
+ that.parentData = {
+ element: $(document), left: 0, top: 0,
+ width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
+ };
+ }
+
+ // i'm a node, so compute top, left, right, bottom
+ else {
+ var element = $(ce), p = [];
+ $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
+
+ that.containerOffset = element.offset();
+ that.containerPosition = element.position();
+ that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
+
+ var co = that.containerOffset, ch = that.containerSize.height, cw = that.containerSize.width,
+ width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
+
+ that.parentData = {
+ element: ce, left: co.left, top: co.top, width: width, height: height
+ };
+ }
+ },
+
+ resize: function(event, ui) {
+ var that = $(this).data("resizable"), o = that.options,
+ ps = that.containerSize, co = that.containerOffset, cs = that.size, cp = that.position,
+ pRatio = that._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = that.containerElement;
+
+ if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
+
+ if (cp.left < (that._helper ? co.left : 0)) {
+ that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
+ if (pRatio) that.size.height = that.size.width / that.aspectRatio;
+ that.position.left = o.helper ? co.left : 0;
+ }
+
+ if (cp.top < (that._helper ? co.top : 0)) {
+ that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
+ if (pRatio) that.size.width = that.size.height * that.aspectRatio;
+ that.position.top = that._helper ? co.top : 0;
+ }
+
+ that.offset.left = that.parentData.left+that.position.left;
+ that.offset.top = that.parentData.top+that.position.top;
+
+ var woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width ),
+ hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );
+
+ var isParent = that.containerElement.get(0) == that.element.parent().get(0),
+ isOffsetRelative = /relative|absolute/.test(that.containerElement.css('position'));
+
+ if(isParent && isOffsetRelative) woset -= that.parentData.left;
+
+ if (woset + that.size.width >= that.parentData.width) {
+ that.size.width = that.parentData.width - woset;
+ if (pRatio) that.size.height = that.size.width / that.aspectRatio;
+ }
+
+ if (hoset + that.size.height >= that.parentData.height) {
+ that.size.height = that.parentData.height - hoset;
+ if (pRatio) that.size.width = that.size.height * that.aspectRatio;
+ }
+ },
+
+ stop: function(event, ui){
+ var that = $(this).data("resizable"), o = that.options, cp = that.position,
+ co = that.containerOffset, cop = that.containerPosition, ce = that.containerElement;
+
+ var helper = $(that.helper), ho = helper.offset(), w = helper.outerWidth() - that.sizeDiff.width, h = helper.outerHeight() - that.sizeDiff.height;
+
+ if (that._helper && !o.animate && (/relative/).test(ce.css('position')))
+ $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
+
+ if (that._helper && !o.animate && (/static/).test(ce.css('position')))
+ $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
+
+ }
+});
+
+$.ui.plugin.add("resizable", "ghost", {
+
+ start: function(event, ui) {
+
+ var that = $(this).data("resizable"), o = that.options, cs = that.size;
+
+ that.ghost = that.originalElement.clone();
+ that.ghost
+ .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
+ .addClass('ui-resizable-ghost')
+ .addClass(typeof o.ghost == 'string' ? o.ghost : '');
+
+ that.ghost.appendTo(that.helper);
+
+ },
+
+ resize: function(event, ui){
+ var that = $(this).data("resizable"), o = that.options;
+ if (that.ghost) that.ghost.css({ position: 'relative', height: that.size.height, width: that.size.width });
+ },
+
+ stop: function(event, ui){
+ var that = $(this).data("resizable"), o = that.options;
+ if (that.ghost && that.helper) that.helper.get(0).removeChild(that.ghost.get(0));
+ }
+
+});
+
+$.ui.plugin.add("resizable", "grid", {
+
+ resize: function(event, ui) {
+ var that = $(this).data("resizable"), o = that.options, cs = that.size, os = that.originalSize, op = that.originalPosition, a = that.axis, ratio = o._aspectRatio || event.shiftKey;
+ o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
+ var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
+
+ if (/^(se|s|e)$/.test(a)) {
+ that.size.width = os.width + ox;
+ that.size.height = os.height + oy;
+ }
+ else if (/^(ne)$/.test(a)) {
+ that.size.width = os.width + ox;
+ that.size.height = os.height + oy;
+ that.position.top = op.top - oy;
+ }
+ else if (/^(sw)$/.test(a)) {
+ that.size.width = os.width + ox;
+ that.size.height = os.height + oy;
+ that.position.left = op.left - ox;
+ }
+ else {
+ that.size.width = os.width + ox;
+ that.size.height = os.height + oy;
+ that.position.top = op.top - oy;
+ that.position.left = op.left - ox;
+ }
+ }
+
+});
+
+var num = function(v) {
+ return parseInt(v, 10) || 0;
+};
+
+var isNumber = function(value) {
+ return !isNaN(parseInt(value, 10));
+};
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.selectable.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.selectable.js
new file mode 100644
index 00000000..3f27b732
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.selectable.js
@@ -0,0 +1,261 @@
+/*!
+ * jQuery UI Selectable 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/selectable/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.selectable", $.ui.mouse, {
+ version: "1.9.2",
+ options: {
+ appendTo: 'body',
+ autoRefresh: true,
+ distance: 0,
+ filter: '*',
+ tolerance: 'touch'
+ },
+ _create: function() {
+ var that = this;
+
+ this.element.addClass("ui-selectable");
+
+ this.dragged = false;
+
+ // cache selectee children based on filter
+ var selectees;
+ this.refresh = function() {
+ selectees = $(that.options.filter, that.element[0]);
+ selectees.addClass("ui-selectee");
+ selectees.each(function() {
+ var $this = $(this);
+ var pos = $this.offset();
+ $.data(this, "selectable-item", {
+ element: this,
+ $element: $this,
+ left: pos.left,
+ top: pos.top,
+ right: pos.left + $this.outerWidth(),
+ bottom: pos.top + $this.outerHeight(),
+ startselected: false,
+ selected: $this.hasClass('ui-selected'),
+ selecting: $this.hasClass('ui-selecting'),
+ unselecting: $this.hasClass('ui-unselecting')
+ });
+ });
+ };
+ this.refresh();
+
+ this.selectees = selectees.addClass("ui-selectee");
+
+ this._mouseInit();
+
+ this.helper = $("<div class='ui-selectable-helper'></div>");
+ },
+
+ _destroy: function() {
+ this.selectees
+ .removeClass("ui-selectee")
+ .removeData("selectable-item");
+ this.element
+ .removeClass("ui-selectable ui-selectable-disabled");
+ this._mouseDestroy();
+ },
+
+ _mouseStart: function(event) {
+ var that = this;
+
+ this.opos = [event.pageX, event.pageY];
+
+ if (this.options.disabled)
+ return;
+
+ var options = this.options;
+
+ this.selectees = $(options.filter, this.element[0]);
+
+ this._trigger("start", event);
+
+ $(options.appendTo).append(this.helper);
+ // position helper (lasso)
+ this.helper.css({
+ "left": event.clientX,
+ "top": event.clientY,
+ "width": 0,
+ "height": 0
+ });
+
+ if (options.autoRefresh) {
+ this.refresh();
+ }
+
+ this.selectees.filter('.ui-selected').each(function() {
+ var selectee = $.data(this, "selectable-item");
+ selectee.startselected = true;
+ if (!event.metaKey && !event.ctrlKey) {
+ selectee.$element.removeClass('ui-selected');
+ selectee.selected = false;
+ selectee.$element.addClass('ui-unselecting');
+ selectee.unselecting = true;
+ // selectable UNSELECTING callback
+ that._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ });
+
+ $(event.target).parents().andSelf().each(function() {
+ var selectee = $.data(this, "selectable-item");
+ if (selectee) {
+ var doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass('ui-selected');
+ selectee.$element
+ .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
+ .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
+ selectee.unselecting = !doSelect;
+ selectee.selecting = doSelect;
+ selectee.selected = doSelect;
+ // selectable (UN)SELECTING callback
+ if (doSelect) {
+ that._trigger("selecting", event, {
+ selecting: selectee.element
+ });
+ } else {
+ that._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ return false;
+ }
+ });
+
+ },
+
+ _mouseDrag: function(event) {
+ var that = this;
+ this.dragged = true;
+
+ if (this.options.disabled)
+ return;
+
+ var options = this.options;
+
+ var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
+ if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
+ if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
+ this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
+
+ this.selectees.each(function() {
+ var selectee = $.data(this, "selectable-item");
+ //prevent helper from being selected if appendTo: selectable
+ if (!selectee || selectee.element == that.element[0])
+ return;
+ var hit = false;
+ if (options.tolerance == 'touch') {
+ hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
+ } else if (options.tolerance == 'fit') {
+ hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
+ }
+
+ if (hit) {
+ // SELECT
+ if (selectee.selected) {
+ selectee.$element.removeClass('ui-selected');
+ selectee.selected = false;
+ }
+ if (selectee.unselecting) {
+ selectee.$element.removeClass('ui-unselecting');
+ selectee.unselecting = false;
+ }
+ if (!selectee.selecting) {
+ selectee.$element.addClass('ui-selecting');
+ selectee.selecting = true;
+ // selectable SELECTING callback
+ that._trigger("selecting", event, {
+ selecting: selectee.element
+ });
+ }
+ } else {
+ // UNSELECT
+ if (selectee.selecting) {
+ if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
+ selectee.$element.removeClass('ui-selecting');
+ selectee.selecting = false;
+ selectee.$element.addClass('ui-selected');
+ selectee.selected = true;
+ } else {
+ selectee.$element.removeClass('ui-selecting');
+ selectee.selecting = false;
+ if (selectee.startselected) {
+ selectee.$element.addClass('ui-unselecting');
+ selectee.unselecting = true;
+ }
+ // selectable UNSELECTING callback
+ that._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ }
+ if (selectee.selected) {
+ if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
+ selectee.$element.removeClass('ui-selected');
+ selectee.selected = false;
+
+ selectee.$element.addClass('ui-unselecting');
+ selectee.unselecting = true;
+ // selectable UNSELECTING callback
+ that._trigger("unselecting", event, {
+ unselecting: selectee.element
+ });
+ }
+ }
+ }
+ });
+
+ return false;
+ },
+
+ _mouseStop: function(event) {
+ var that = this;
+
+ this.dragged = false;
+
+ var options = this.options;
+
+ $('.ui-unselecting', this.element[0]).each(function() {
+ var selectee = $.data(this, "selectable-item");
+ selectee.$element.removeClass('ui-unselecting');
+ selectee.unselecting = false;
+ selectee.startselected = false;
+ that._trigger("unselected", event, {
+ unselected: selectee.element
+ });
+ });
+ $('.ui-selecting', this.element[0]).each(function() {
+ var selectee = $.data(this, "selectable-item");
+ selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
+ selectee.selecting = false;
+ selectee.selected = true;
+ selectee.startselected = true;
+ that._trigger("selected", event, {
+ selected: selectee.element
+ });
+ });
+ this._trigger("stop", event);
+
+ this.helper.remove();
+
+ return false;
+ }
+
+});
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.slider.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.slider.js
new file mode 100644
index 00000000..c3daa7a4
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.slider.js
@@ -0,0 +1,644 @@
+/*!
+ * jQuery UI Slider 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/slider/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+// number of pages in a slider
+// (how many times can you page up/down to go through the whole range)
+var numPages = 5;
+
+$.widget( "ui.slider", $.ui.mouse, {
+ version: "1.9.2",
+ widgetEventPrefix: "slide",
+
+ options: {
+ animate: false,
+ distance: 0,
+ max: 100,
+ min: 0,
+ orientation: "horizontal",
+ range: false,
+ step: 1,
+ value: 0,
+ values: null
+ },
+
+ _create: function() {
+ var i, handleCount,
+ o = this.options,
+ existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
+ handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
+ handles = [];
+
+ this._keySliding = false;
+ this._mouseSliding = false;
+ this._animateOff = true;
+ this._handleIndex = null;
+ this._detectOrientation();
+ this._mouseInit();
+
+ this.element
+ .addClass( "ui-slider" +
+ " ui-slider-" + this.orientation +
+ " ui-widget" +
+ " ui-widget-content" +
+ " ui-corner-all" +
+ ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
+
+ this.range = $([]);
+
+ if ( o.range ) {
+ if ( o.range === true ) {
+ if ( !o.values ) {
+ o.values = [ this._valueMin(), this._valueMin() ];
+ }
+ if ( o.values.length && o.values.length !== 2 ) {
+ o.values = [ o.values[0], o.values[0] ];
+ }
+ }
+
+ this.range = $( "<div></div>" )
+ .appendTo( this.element )
+ .addClass( "ui-slider-range" +
+ // note: this isn't the most fittingly semantic framework class for this element,
+ // but worked best visually with a variety of themes
+ " ui-widget-header" +
+ ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
+ }
+
+ handleCount = ( o.values && o.values.length ) || 1;
+
+ for ( i = existingHandles.length; i < handleCount; i++ ) {
+ handles.push( handle );
+ }
+
+ this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
+
+ this.handle = this.handles.eq( 0 );
+
+ this.handles.add( this.range ).filter( "a" )
+ .click(function( event ) {
+ event.preventDefault();
+ })
+ .mouseenter(function() {
+ if ( !o.disabled ) {
+ $( this ).addClass( "ui-state-hover" );
+ }
+ })
+ .mouseleave(function() {
+ $( this ).removeClass( "ui-state-hover" );
+ })
+ .focus(function() {
+ if ( !o.disabled ) {
+ $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
+ $( this ).addClass( "ui-state-focus" );
+ } else {
+ $( this ).blur();
+ }
+ })
+ .blur(function() {
+ $( this ).removeClass( "ui-state-focus" );
+ });
+
+ this.handles.each(function( i ) {
+ $( this ).data( "ui-slider-handle-index", i );
+ });
+
+ this._on( this.handles, {
+ keydown: function( event ) {
+ var allowed, curVal, newVal, step,
+ index = $( event.target ).data( "ui-slider-handle-index" );
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.HOME:
+ case $.ui.keyCode.END:
+ case $.ui.keyCode.PAGE_UP:
+ case $.ui.keyCode.PAGE_DOWN:
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.RIGHT:
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.LEFT:
+ event.preventDefault();
+ if ( !this._keySliding ) {
+ this._keySliding = true;
+ $( event.target ).addClass( "ui-state-active" );
+ allowed = this._start( event, index );
+ if ( allowed === false ) {
+ return;
+ }
+ }
+ break;
+ }
+
+ step = this.options.step;
+ if ( this.options.values && this.options.values.length ) {
+ curVal = newVal = this.values( index );
+ } else {
+ curVal = newVal = this.value();
+ }
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.HOME:
+ newVal = this._valueMin();
+ break;
+ case $.ui.keyCode.END:
+ newVal = this._valueMax();
+ break;
+ case $.ui.keyCode.PAGE_UP:
+ newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
+ break;
+ case $.ui.keyCode.PAGE_DOWN:
+ newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
+ break;
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.RIGHT:
+ if ( curVal === this._valueMax() ) {
+ return;
+ }
+ newVal = this._trimAlignValue( curVal + step );
+ break;
+ case $.ui.keyCode.DOWN:
+ case $.ui.keyCode.LEFT:
+ if ( curVal === this._valueMin() ) {
+ return;
+ }
+ newVal = this._trimAlignValue( curVal - step );
+ break;
+ }
+
+ this._slide( event, index, newVal );
+ },
+ keyup: function( event ) {
+ var index = $( event.target ).data( "ui-slider-handle-index" );
+
+ if ( this._keySliding ) {
+ this._keySliding = false;
+ this._stop( event, index );
+ this._change( event, index );
+ $( event.target ).removeClass( "ui-state-active" );
+ }
+ }
+ });
+
+ this._refreshValue();
+
+ this._animateOff = false;
+ },
+
+ _destroy: function() {
+ this.handles.remove();
+ this.range.remove();
+
+ this.element
+ .removeClass( "ui-slider" +
+ " ui-slider-horizontal" +
+ " ui-slider-vertical" +
+ " ui-slider-disabled" +
+ " ui-widget" +
+ " ui-widget-content" +
+ " ui-corner-all" );
+
+ this._mouseDestroy();
+ },
+
+ _mouseCapture: function( event ) {
+ var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
+ that = this,
+ o = this.options;
+
+ if ( o.disabled ) {
+ return false;
+ }
+
+ this.elementSize = {
+ width: this.element.outerWidth(),
+ height: this.element.outerHeight()
+ };
+ this.elementOffset = this.element.offset();
+
+ position = { x: event.pageX, y: event.pageY };
+ normValue = this._normValueFromMouse( position );
+ distance = this._valueMax() - this._valueMin() + 1;
+ this.handles.each(function( i ) {
+ var thisDistance = Math.abs( normValue - that.values(i) );
+ if ( distance > thisDistance ) {
+ distance = thisDistance;
+ closestHandle = $( this );
+ index = i;
+ }
+ });
+
+ // workaround for bug #3736 (if both handles of a range are at 0,
+ // the first is always used as the one with least distance,
+ // and moving it is obviously prevented by preventing negative ranges)
+ if( o.range === true && this.values(1) === o.min ) {
+ index += 1;
+ closestHandle = $( this.handles[index] );
+ }
+
+ allowed = this._start( event, index );
+ if ( allowed === false ) {
+ return false;
+ }
+ this._mouseSliding = true;
+
+ this._handleIndex = index;
+
+ closestHandle
+ .addClass( "ui-state-active" )
+ .focus();
+
+ offset = closestHandle.offset();
+ mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
+ this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
+ left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
+ top: event.pageY - offset.top -
+ ( closestHandle.height() / 2 ) -
+ ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
+ ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
+ ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
+ };
+
+ if ( !this.handles.hasClass( "ui-state-hover" ) ) {
+ this._slide( event, index, normValue );
+ }
+ this._animateOff = true;
+ return true;
+ },
+
+ _mouseStart: function() {
+ return true;
+ },
+
+ _mouseDrag: function( event ) {
+ var position = { x: event.pageX, y: event.pageY },
+ normValue = this._normValueFromMouse( position );
+
+ this._slide( event, this._handleIndex, normValue );
+
+ return false;
+ },
+
+ _mouseStop: function( event ) {
+ this.handles.removeClass( "ui-state-active" );
+ this._mouseSliding = false;
+
+ this._stop( event, this._handleIndex );
+ this._change( event, this._handleIndex );
+
+ this._handleIndex = null;
+ this._clickOffset = null;
+ this._animateOff = false;
+
+ return false;
+ },
+
+ _detectOrientation: function() {
+ this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
+ },
+
+ _normValueFromMouse: function( position ) {
+ var pixelTotal,
+ pixelMouse,
+ percentMouse,
+ valueTotal,
+ valueMouse;
+
+ if ( this.orientation === "horizontal" ) {
+ pixelTotal = this.elementSize.width;
+ pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
+ } else {
+ pixelTotal = this.elementSize.height;
+ pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
+ }
+
+ percentMouse = ( pixelMouse / pixelTotal );
+ if ( percentMouse > 1 ) {
+ percentMouse = 1;
+ }
+ if ( percentMouse < 0 ) {
+ percentMouse = 0;
+ }
+ if ( this.orientation === "vertical" ) {
+ percentMouse = 1 - percentMouse;
+ }
+
+ valueTotal = this._valueMax() - this._valueMin();
+ valueMouse = this._valueMin() + percentMouse * valueTotal;
+
+ return this._trimAlignValue( valueMouse );
+ },
+
+ _start: function( event, index ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+ return this._trigger( "start", event, uiHash );
+ },
+
+ _slide: function( event, index, newVal ) {
+ var otherVal,
+ newValues,
+ allowed;
+
+ if ( this.options.values && this.options.values.length ) {
+ otherVal = this.values( index ? 0 : 1 );
+
+ if ( ( this.options.values.length === 2 && this.options.range === true ) &&
+ ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
+ ) {
+ newVal = otherVal;
+ }
+
+ if ( newVal !== this.values( index ) ) {
+ newValues = this.values();
+ newValues[ index ] = newVal;
+ // A slide can be canceled by returning false from the slide callback
+ allowed = this._trigger( "slide", event, {
+ handle: this.handles[ index ],
+ value: newVal,
+ values: newValues
+ } );
+ otherVal = this.values( index ? 0 : 1 );
+ if ( allowed !== false ) {
+ this.values( index, newVal, true );
+ }
+ }
+ } else {
+ if ( newVal !== this.value() ) {
+ // A slide can be canceled by returning false from the slide callback
+ allowed = this._trigger( "slide", event, {
+ handle: this.handles[ index ],
+ value: newVal
+ } );
+ if ( allowed !== false ) {
+ this.value( newVal );
+ }
+ }
+ }
+ },
+
+ _stop: function( event, index ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+
+ this._trigger( "stop", event, uiHash );
+ },
+
+ _change: function( event, index ) {
+ if ( !this._keySliding && !this._mouseSliding ) {
+ var uiHash = {
+ handle: this.handles[ index ],
+ value: this.value()
+ };
+ if ( this.options.values && this.options.values.length ) {
+ uiHash.value = this.values( index );
+ uiHash.values = this.values();
+ }
+
+ this._trigger( "change", event, uiHash );
+ }
+ },
+
+ value: function( newValue ) {
+ if ( arguments.length ) {
+ this.options.value = this._trimAlignValue( newValue );
+ this._refreshValue();
+ this._change( null, 0 );
+ return;
+ }
+
+ return this._value();
+ },
+
+ values: function( index, newValue ) {
+ var vals,
+ newValues,
+ i;
+
+ if ( arguments.length > 1 ) {
+ this.options.values[ index ] = this._trimAlignValue( newValue );
+ this._refreshValue();
+ this._change( null, index );
+ return;
+ }
+
+ if ( arguments.length ) {
+ if ( $.isArray( arguments[ 0 ] ) ) {
+ vals = this.options.values;
+ newValues = arguments[ 0 ];
+ for ( i = 0; i < vals.length; i += 1 ) {
+ vals[ i ] = this._trimAlignValue( newValues[ i ] );
+ this._change( null, i );
+ }
+ this._refreshValue();
+ } else {
+ if ( this.options.values && this.options.values.length ) {
+ return this._values( index );
+ } else {
+ return this.value();
+ }
+ }
+ } else {
+ return this._values();
+ }
+ },
+
+ _setOption: function( key, value ) {
+ var i,
+ valsLength = 0;
+
+ if ( $.isArray( this.options.values ) ) {
+ valsLength = this.options.values.length;
+ }
+
+ $.Widget.prototype._setOption.apply( this, arguments );
+
+ switch ( key ) {
+ case "disabled":
+ if ( value ) {
+ this.handles.filter( ".ui-state-focus" ).blur();
+ this.handles.removeClass( "ui-state-hover" );
+ this.handles.prop( "disabled", true );
+ this.element.addClass( "ui-disabled" );
+ } else {
+ this.handles.prop( "disabled", false );
+ this.element.removeClass( "ui-disabled" );
+ }
+ break;
+ case "orientation":
+ this._detectOrientation();
+ this.element
+ .removeClass( "ui-slider-horizontal ui-slider-vertical" )
+ .addClass( "ui-slider-" + this.orientation );
+ this._refreshValue();
+ break;
+ case "value":
+ this._animateOff = true;
+ this._refreshValue();
+ this._change( null, 0 );
+ this._animateOff = false;
+ break;
+ case "values":
+ this._animateOff = true;
+ this._refreshValue();
+ for ( i = 0; i < valsLength; i += 1 ) {
+ this._change( null, i );
+ }
+ this._animateOff = false;
+ break;
+ case "min":
+ case "max":
+ this._animateOff = true;
+ this._refreshValue();
+ this._animateOff = false;
+ break;
+ }
+ },
+
+ //internal value getter
+ // _value() returns value trimmed by min and max, aligned by step
+ _value: function() {
+ var val = this.options.value;
+ val = this._trimAlignValue( val );
+
+ return val;
+ },
+
+ //internal values getter
+ // _values() returns array of values trimmed by min and max, aligned by step
+ // _values( index ) returns single value trimmed by min and max, aligned by step
+ _values: function( index ) {
+ var val,
+ vals,
+ i;
+
+ if ( arguments.length ) {
+ val = this.options.values[ index ];
+ val = this._trimAlignValue( val );
+
+ return val;
+ } else {
+ // .slice() creates a copy of the array
+ // this copy gets trimmed by min and max and then returned
+ vals = this.options.values.slice();
+ for ( i = 0; i < vals.length; i+= 1) {
+ vals[ i ] = this._trimAlignValue( vals[ i ] );
+ }
+
+ return vals;
+ }
+ },
+
+ // returns the step-aligned value that val is closest to, between (inclusive) min and max
+ _trimAlignValue: function( val ) {
+ if ( val <= this._valueMin() ) {
+ return this._valueMin();
+ }
+ if ( val >= this._valueMax() ) {
+ return this._valueMax();
+ }
+ var step = ( this.options.step > 0 ) ? this.options.step : 1,
+ valModStep = (val - this._valueMin()) % step,
+ alignValue = val - valModStep;
+
+ if ( Math.abs(valModStep) * 2 >= step ) {
+ alignValue += ( valModStep > 0 ) ? step : ( -step );
+ }
+
+ // Since JavaScript has problems with large floats, round
+ // the final value to 5 digits after the decimal point (see #4124)
+ return parseFloat( alignValue.toFixed(5) );
+ },
+
+ _valueMin: function() {
+ return this.options.min;
+ },
+
+ _valueMax: function() {
+ return this.options.max;
+ },
+
+ _refreshValue: function() {
+ var lastValPercent, valPercent, value, valueMin, valueMax,
+ oRange = this.options.range,
+ o = this.options,
+ that = this,
+ animate = ( !this._animateOff ) ? o.animate : false,
+ _set = {};
+
+ if ( this.options.values && this.options.values.length ) {
+ this.handles.each(function( i ) {
+ valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
+ _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+ $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+ if ( that.options.range === true ) {
+ if ( that.orientation === "horizontal" ) {
+ if ( i === 0 ) {
+ that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
+ }
+ if ( i === 1 ) {
+ that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ } else {
+ if ( i === 0 ) {
+ that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
+ }
+ if ( i === 1 ) {
+ that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ }
+ }
+ lastValPercent = valPercent;
+ });
+ } else {
+ value = this.value();
+ valueMin = this._valueMin();
+ valueMax = this._valueMax();
+ valPercent = ( valueMax !== valueMin ) ?
+ ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
+ 0;
+ _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
+ this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
+
+ if ( oRange === "min" && this.orientation === "horizontal" ) {
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
+ }
+ if ( oRange === "max" && this.orientation === "horizontal" ) {
+ this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ if ( oRange === "min" && this.orientation === "vertical" ) {
+ this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
+ }
+ if ( oRange === "max" && this.orientation === "vertical" ) {
+ this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
+ }
+ }
+ }
+
+});
+
+}(jQuery));
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.sortable.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.sortable.js
new file mode 100644
index 00000000..bd960df3
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.sortable.js
@@ -0,0 +1,1096 @@
+/*!
+ * jQuery UI Sortable 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/sortable/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.mouse.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+$.widget("ui.sortable", $.ui.mouse, {
+ version: "1.9.2",
+ widgetEventPrefix: "sort",
+ ready: false,
+ options: {
+ appendTo: "parent",
+ axis: false,
+ connectWith: false,
+ containment: false,
+ cursor: 'auto',
+ cursorAt: false,
+ dropOnEmpty: true,
+ forcePlaceholderSize: false,
+ forceHelperSize: false,
+ grid: false,
+ handle: false,
+ helper: "original",
+ items: '> *',
+ opacity: false,
+ placeholder: false,
+ revert: false,
+ scroll: true,
+ scrollSensitivity: 20,
+ scrollSpeed: 20,
+ scope: "default",
+ tolerance: "intersect",
+ zIndex: 1000
+ },
+ _create: function() {
+
+ var o = this.options;
+ this.containerCache = {};
+ this.element.addClass("ui-sortable");
+
+ //Get the items
+ this.refresh();
+
+ //Let's determine if the items are being displayed horizontally
+ this.floating = this.items.length ? o.axis === 'x' || (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
+
+ //Let's determine the parent's offset
+ this.offset = this.element.offset();
+
+ //Initialize mouse events for interaction
+ this._mouseInit();
+
+ //We're ready to go
+ this.ready = true
+
+ },
+
+ _destroy: function() {
+ this.element
+ .removeClass("ui-sortable ui-sortable-disabled");
+ this._mouseDestroy();
+
+ for ( var i = this.items.length - 1; i >= 0; i-- )
+ this.items[i].item.removeData(this.widgetName + "-item");
+
+ return this;
+ },
+
+ _setOption: function(key, value){
+ if ( key === "disabled" ) {
+ this.options[ key ] = value;
+
+ this.widget().toggleClass( "ui-sortable-disabled", !!value );
+ } else {
+ // Don't call widget base _setOption for disable as it adds ui-state-disabled class
+ $.Widget.prototype._setOption.apply(this, arguments);
+ }
+ },
+
+ _mouseCapture: function(event, overrideHandle) {
+ var that = this;
+
+ if (this.reverting) {
+ return false;
+ }
+
+ if(this.options.disabled || this.options.type == 'static') return false;
+
+ //We have to refresh the items data once first
+ this._refreshItems(event);
+
+ //Find out if the clicked node (or one of its parents) is a actual item in this.items
+ var currentItem = null, nodes = $(event.target).parents().each(function() {
+ if($.data(this, that.widgetName + '-item') == that) {
+ currentItem = $(this);
+ return false;
+ }
+ });
+ if($.data(event.target, that.widgetName + '-item') == that) currentItem = $(event.target);
+
+ if(!currentItem) return false;
+ if(this.options.handle && !overrideHandle) {
+ var validHandle = false;
+
+ $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
+ if(!validHandle) return false;
+ }
+
+ this.currentItem = currentItem;
+ this._removeCurrentsFromItems();
+ return true;
+
+ },
+
+ _mouseStart: function(event, overrideHandle, noActivation) {
+
+ var o = this.options;
+ this.currentContainer = this;
+
+ //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
+ this.refreshPositions();
+
+ //Create and append the visible helper
+ this.helper = this._createHelper(event);
+
+ //Cache the helper size
+ this._cacheHelperProportions();
+
+ /*
+ * - Position generation -
+ * This block generates everything position related - it's the core of draggables.
+ */
+
+ //Cache the margins of the original element
+ this._cacheMargins();
+
+ //Get the next scrolling parent
+ this.scrollParent = this.helper.scrollParent();
+
+ //The element's absolute position on the page minus margins
+ this.offset = this.currentItem.offset();
+ this.offset = {
+ top: this.offset.top - this.margins.top,
+ left: this.offset.left - this.margins.left
+ };
+
+ $.extend(this.offset, {
+ click: { //Where the click happened, relative to the element
+ left: event.pageX - this.offset.left,
+ top: event.pageY - this.offset.top
+ },
+ parent: this._getParentOffset(),
+ relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
+ });
+
+ // Only after we got the offset, we can change the helper's position to absolute
+ // TODO: Still need to figure out a way to make relative sorting possible
+ this.helper.css("position", "absolute");
+ this.cssPosition = this.helper.css("position");
+
+ //Generate the original position
+ this.originalPosition = this._generatePosition(event);
+ this.originalPageX = event.pageX;
+ this.originalPageY = event.pageY;
+
+ //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
+ (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
+
+ //Cache the former DOM position
+ this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
+
+ //If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
+ if(this.helper[0] != this.currentItem[0]) {
+ this.currentItem.hide();
+ }
+
+ //Create the placeholder
+ this._createPlaceholder();
+
+ //Set a containment if given in the options
+ if(o.containment)
+ this._setContainment();
+
+ if(o.cursor) { // cursor option
+ if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
+ $('body').css("cursor", o.cursor);
+ }
+
+ if(o.opacity) { // opacity option
+ if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
+ this.helper.css("opacity", o.opacity);
+ }
+
+ if(o.zIndex) { // zIndex option
+ if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
+ this.helper.css("zIndex", o.zIndex);
+ }
+
+ //Prepare scrolling
+ if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
+ this.overflowOffset = this.scrollParent.offset();
+
+ //Call callbacks
+ this._trigger("start", event, this._uiHash());
+
+ //Recache the helper size
+ if(!this._preserveHelperProportions)
+ this._cacheHelperProportions();
+
+
+ //Post 'activate' events to possible containers
+ if(!noActivation) {
+ for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, this._uiHash(this)); }
+ }
+
+ //Prepare possible droppables
+ if($.ui.ddmanager)
+ $.ui.ddmanager.current = this;
+
+ if ($.ui.ddmanager && !o.dropBehaviour)
+ $.ui.ddmanager.prepareOffsets(this, event);
+
+ this.dragging = true;
+
+ this.helper.addClass("ui-sortable-helper");
+ this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
+ return true;
+
+ },
+
+ _mouseDrag: function(event) {
+
+ //Compute the helpers position
+ this.position = this._generatePosition(event);
+ this.positionAbs = this._convertPositionTo("absolute");
+
+ if (!this.lastPositionAbs) {
+ this.lastPositionAbs = this.positionAbs;
+ }
+
+ //Do scrolling
+ if(this.options.scroll) {
+ var o = this.options, scrolled = false;
+ if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
+
+ if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
+ else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
+ this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
+
+ if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
+ else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
+ this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
+
+ } else {
+
+ if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
+ scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
+ else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
+ scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
+
+ if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
+ scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
+ else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
+ scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
+
+ }
+
+ if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
+ $.ui.ddmanager.prepareOffsets(this, event);
+ }
+
+ //Regenerate the absolute position used for position checks
+ this.positionAbs = this._convertPositionTo("absolute");
+
+ //Set the helper position
+ if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
+ if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
+
+ //Rearrange
+ for (var i = this.items.length - 1; i >= 0; i--) {
+
+ //Cache variables and intersection, continue if no intersection
+ var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
+ if (!intersection) continue;
+
+ // Only put the placeholder inside the current Container, skip all
+ // items form other containers. This works because when moving
+ // an item from one container to another the
+ // currentContainer is switched before the placeholder is moved.
+ //
+ // Without this moving items in "sub-sortables" can cause the placeholder to jitter
+ // beetween the outer and inner container.
+ if (item.instance !== this.currentContainer) continue;
+
+ if (itemElement != this.currentItem[0] //cannot intersect with itself
+ && this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
+ && !$.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
+ && (this.options.type == 'semi-dynamic' ? !$.contains(this.element[0], itemElement) : true)
+ //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
+ ) {
+
+ this.direction = intersection == 1 ? "down" : "up";
+
+ if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
+ this._rearrange(event, item);
+ } else {
+ break;
+ }
+
+ this._trigger("change", event, this._uiHash());
+ break;
+ }
+ }
+
+ //Post events to containers
+ this._contactContainers(event);
+
+ //Interconnect with droppables
+ if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
+
+ //Call callbacks
+ this._trigger('sort', event, this._uiHash());
+
+ this.lastPositionAbs = this.positionAbs;
+ return false;
+
+ },
+
+ _mouseStop: function(event, noPropagation) {
+
+ if(!event) return;
+
+ //If we are using droppables, inform the manager about the drop
+ if ($.ui.ddmanager && !this.options.dropBehaviour)
+ $.ui.ddmanager.drop(this, event);
+
+ if(this.options.revert) {
+ var that = this;
+ var cur = this.placeholder.offset();
+
+ this.reverting = true;
+
+ $(this.helper).animate({
+ left: cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
+ top: cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
+ }, parseInt(this.options.revert, 10) || 500, function() {
+ that._clear(event);
+ });
+ } else {
+ this._clear(event, noPropagation);
+ }
+
+ return false;
+
+ },
+
+ cancel: function() {
+
+ if(this.dragging) {
+
+ this._mouseUp({ target: null });
+
+ if(this.options.helper == "original")
+ this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
+ else
+ this.currentItem.show();
+
+ //Post deactivating events to containers
+ for (var i = this.containers.length - 1; i >= 0; i--){
+ this.containers[i]._trigger("deactivate", null, this._uiHash(this));
+ if(this.containers[i].containerCache.over) {
+ this.containers[i]._trigger("out", null, this._uiHash(this));
+ this.containers[i].containerCache.over = 0;
+ }
+ }
+
+ }
+
+ if (this.placeholder) {
+ //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
+ if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
+ if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
+
+ $.extend(this, {
+ helper: null,
+ dragging: false,
+ reverting: false,
+ _noFinalSort: null
+ });
+
+ if(this.domPosition.prev) {
+ $(this.domPosition.prev).after(this.currentItem);
+ } else {
+ $(this.domPosition.parent).prepend(this.currentItem);
+ }
+ }
+
+ return this;
+
+ },
+
+ serialize: function(o) {
+
+ var items = this._getItemsAsjQuery(o && o.connected);
+ var str = []; o = o || {};
+
+ $(items).each(function() {
+ var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
+ if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
+ });
+
+ if(!str.length && o.key) {
+ str.push(o.key + '=');
+ }
+
+ return str.join('&');
+
+ },
+
+ toArray: function(o) {
+
+ var items = this._getItemsAsjQuery(o && o.connected);
+ var ret = []; o = o || {};
+
+ items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
+ return ret;
+
+ },
+
+ /* Be careful with the following core functions */
+ _intersectsWith: function(item) {
+
+ var x1 = this.positionAbs.left,
+ x2 = x1 + this.helperProportions.width,
+ y1 = this.positionAbs.top,
+ y2 = y1 + this.helperProportions.height;
+
+ var l = item.left,
+ r = l + item.width,
+ t = item.top,
+ b = t + item.height;
+
+ var dyClick = this.offset.click.top,
+ dxClick = this.offset.click.left;
+
+ var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
+
+ if( this.options.tolerance == "pointer"
+ || this.options.forcePointerForContainers
+ || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
+ ) {
+ return isOverElement;
+ } else {
+
+ return (l < x1 + (this.helperProportions.width / 2) // Right Half
+ && x2 - (this.helperProportions.width / 2) < r // Left Half
+ && t < y1 + (this.helperProportions.height / 2) // Bottom Half
+ && y2 - (this.helperProportions.height / 2) < b ); // Top Half
+
+ }
+ },
+
+ _intersectsWithPointer: function(item) {
+
+ var isOverElementHeight = (this.options.axis === 'x') || $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
+ isOverElementWidth = (this.options.axis === 'y') || $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
+ isOverElement = isOverElementHeight && isOverElementWidth,
+ verticalDirection = this._getDragVerticalDirection(),
+ horizontalDirection = this._getDragHorizontalDirection();
+
+ if (!isOverElement)
+ return false;
+
+ return this.floating ?
+ ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
+ : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
+
+ },
+
+ _intersectsWithSides: function(item) {
+
+ var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
+ isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
+ verticalDirection = this._getDragVerticalDirection(),
+ horizontalDirection = this._getDragHorizontalDirection();
+
+ if (this.floating && horizontalDirection) {
+ return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
+ } else {
+ return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
+ }
+
+ },
+
+ _getDragVerticalDirection: function() {
+ var delta = this.positionAbs.top - this.lastPositionAbs.top;
+ return delta != 0 && (delta > 0 ? "down" : "up");
+ },
+
+ _getDragHorizontalDirection: function() {
+ var delta = this.positionAbs.left - this.lastPositionAbs.left;
+ return delta != 0 && (delta > 0 ? "right" : "left");
+ },
+
+ refresh: function(event) {
+ this._refreshItems(event);
+ this.refreshPositions();
+ return this;
+ },
+
+ _connectWith: function() {
+ var options = this.options;
+ return options.connectWith.constructor == String
+ ? [options.connectWith]
+ : options.connectWith;
+ },
+
+ _getItemsAsjQuery: function(connected) {
+
+ var items = [];
+ var queries = [];
+ var connectWith = this._connectWith();
+
+ if(connectWith && connected) {
+ for (var i = connectWith.length - 1; i >= 0; i--){
+ var cur = $(connectWith[i]);
+ for (var j = cur.length - 1; j >= 0; j--){
+ var inst = $.data(cur[j], this.widgetName);
+ if(inst && inst != this && !inst.options.disabled) {
+ queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), inst]);
+ }
+ };
+ };
+ }
+
+ queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not('.ui-sortable-placeholder'), this]);
+
+ for (var i = queries.length - 1; i >= 0; i--){
+ queries[i][0].each(function() {
+ items.push(this);
+ });
+ };
+
+ return $(items);
+
+ },
+
+ _removeCurrentsFromItems: function() {
+
+ var list = this.currentItem.find(":data(" + this.widgetName + "-item)");
+
+ this.items = $.grep(this.items, function (item) {
+ for (var j=0; j < list.length; j++) {
+ if(list[j] == item.item[0])
+ return false;
+ };
+ return true;
+ });
+
+ },
+
+ _refreshItems: function(event) {
+
+ this.items = [];
+ this.containers = [this];
+ var items = this.items;
+ var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
+ var connectWith = this._connectWith();
+
+ if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
+ for (var i = connectWith.length - 1; i >= 0; i--){
+ var cur = $(connectWith[i]);
+ for (var j = cur.length - 1; j >= 0; j--){
+ var inst = $.data(cur[j], this.widgetName);
+ if(inst && inst != this && !inst.options.disabled) {
+ queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
+ this.containers.push(inst);
+ }
+ };
+ };
+ }
+
+ for (var i = queries.length - 1; i >= 0; i--) {
+ var targetData = queries[i][1];
+ var _queries = queries[i][0];
+
+ for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
+ var item = $(_queries[j]);
+
+ item.data(this.widgetName + '-item', targetData); // Data for target checking (mouse manager)
+
+ items.push({
+ item: item,
+ instance: targetData,
+ width: 0, height: 0,
+ left: 0, top: 0
+ });
+ };
+ };
+
+ },
+
+ refreshPositions: function(fast) {
+
+ //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
+ if(this.offsetParent && this.helper) {
+ this.offset.parent = this._getParentOffset();
+ }
+
+ for (var i = this.items.length - 1; i >= 0; i--){
+ var item = this.items[i];
+
+ //We ignore calculating positions of all connected containers when we're not over them
+ if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
+ continue;
+
+ var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
+
+ if (!fast) {
+ item.width = t.outerWidth();
+ item.height = t.outerHeight();
+ }
+
+ var p = t.offset();
+ item.left = p.left;
+ item.top = p.top;
+ };
+
+ if(this.options.custom && this.options.custom.refreshContainers) {
+ this.options.custom.refreshContainers.call(this);
+ } else {
+ for (var i = this.containers.length - 1; i >= 0; i--){
+ var p = this.containers[i].element.offset();
+ this.containers[i].containerCache.left = p.left;
+ this.containers[i].containerCache.top = p.top;
+ this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
+ this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
+ };
+ }
+
+ return this;
+ },
+
+ _createPlaceholder: function(that) {
+ that = that || this;
+ var o = that.options;
+
+ if(!o.placeholder || o.placeholder.constructor == String) {
+ var className = o.placeholder;
+ o.placeholder = {
+ element: function() {
+
+ var el = $(document.createElement(that.currentItem[0].nodeName))
+ .addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
+ .removeClass("ui-sortable-helper")[0];
+
+ if(!className)
+ el.style.visibility = "hidden";
+
+ return el;
+ },
+ update: function(container, p) {
+
+ // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
+ // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
+ if(className && !o.forcePlaceholderSize) return;
+
+ //If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
+ if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css('paddingTop')||0, 10) - parseInt(that.currentItem.css('paddingBottom')||0, 10)); };
+ if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css('paddingLeft')||0, 10) - parseInt(that.currentItem.css('paddingRight')||0, 10)); };
+ }
+ };
+ }
+
+ //Create the placeholder
+ that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));
+
+ //Append it after the actual current item
+ that.currentItem.after(that.placeholder);
+
+ //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
+ o.placeholder.update(that, that.placeholder);
+
+ },
+
+ _contactContainers: function(event) {
+
+ // get innermost container that intersects with item
+ var innermostContainer = null, innermostIndex = null;
+
+
+ for (var i = this.containers.length - 1; i >= 0; i--){
+
+ // never consider a container that's located within the item itself
+ if($.contains(this.currentItem[0], this.containers[i].element[0]))
+ continue;
+
+ if(this._intersectsWith(this.containers[i].containerCache)) {
+
+ // if we've already found a container and it's more "inner" than this, then continue
+ if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0]))
+ continue;
+
+ innermostContainer = this.containers[i];
+ innermostIndex = i;
+
+ } else {
+ // container doesn't intersect. trigger "out" event if necessary
+ if(this.containers[i].containerCache.over) {
+ this.containers[i]._trigger("out", event, this._uiHash(this));
+ this.containers[i].containerCache.over = 0;
+ }
+ }
+
+ }
+
+ // if no intersecting containers found, return
+ if(!innermostContainer) return;
+
+ // move the item into the container if it's not there already
+ if(this.containers.length === 1) {
+ this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
+ this.containers[innermostIndex].containerCache.over = 1;
+ } else {
+
+ //When entering a new container, we will find the item with the least distance and append our item near it
+ var dist = 10000; var itemWithLeastDistance = null;
+ var posProperty = this.containers[innermostIndex].floating ? 'left' : 'top';
+ var sizeProperty = this.containers[innermostIndex].floating ? 'width' : 'height';
+ var base = this.positionAbs[posProperty] + this.offset.click[posProperty];
+ for (var j = this.items.length - 1; j >= 0; j--) {
+ if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue;
+ if(this.items[j].item[0] == this.currentItem[0]) continue;
+ var cur = this.items[j].item.offset()[posProperty];
+ var nearBottom = false;
+ if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
+ nearBottom = true;
+ cur += this.items[j][sizeProperty];
+ }
+
+ if(Math.abs(cur - base) < dist) {
+ dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
+ this.direction = nearBottom ? "up": "down";
+ }
+ }
+
+ if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled
+ return;
+
+ this.currentContainer = this.containers[innermostIndex];
+ itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
+ this._trigger("change", event, this._uiHash());
+ this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));
+
+ //Update the placeholder
+ this.options.placeholder.update(this.currentContainer, this.placeholder);
+
+ this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
+ this.containers[innermostIndex].containerCache.over = 1;
+ }
+
+
+ },
+
+ _createHelper: function(event) {
+
+ var o = this.options;
+ var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
+
+ if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
+ $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
+
+ if(helper[0] == this.currentItem[0])
+ this._storedCSS = { width: this.currentItem[0].style.width, height: this.currentItem[0].style.height, position: this.currentItem.css("position"), top: this.currentItem.css("top"), left: this.currentItem.css("left") };
+
+ if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
+ if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
+
+ return helper;
+
+ },
+
+ _adjustOffsetFromHelper: function(obj) {
+ if (typeof obj == 'string') {
+ obj = obj.split(' ');
+ }
+ if ($.isArray(obj)) {
+ obj = {left: +obj[0], top: +obj[1] || 0};
+ }
+ if ('left' in obj) {
+ this.offset.click.left = obj.left + this.margins.left;
+ }
+ if ('right' in obj) {
+ this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
+ }
+ if ('top' in obj) {
+ this.offset.click.top = obj.top + this.margins.top;
+ }
+ if ('bottom' in obj) {
+ this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
+ }
+ },
+
+ _getParentOffset: function() {
+
+
+ //Get the offsetParent and cache its position
+ this.offsetParent = this.helper.offsetParent();
+ var po = this.offsetParent.offset();
+
+ // This is a special case where we need to modify a offset calculated on start, since the following happened:
+ // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
+ // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
+ // the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
+ if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
+ po.left += this.scrollParent.scrollLeft();
+ po.top += this.scrollParent.scrollTop();
+ }
+
+ if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
+ || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.ui.ie)) //Ugly IE fix
+ po = { top: 0, left: 0 };
+
+ return {
+ top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
+ left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
+ };
+
+ },
+
+ _getRelativeOffset: function() {
+
+ if(this.cssPosition == "relative") {
+ var p = this.currentItem.position();
+ return {
+ top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
+ left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
+ };
+ } else {
+ return { top: 0, left: 0 };
+ }
+
+ },
+
+ _cacheMargins: function() {
+ this.margins = {
+ left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
+ top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
+ };
+ },
+
+ _cacheHelperProportions: function() {
+ this.helperProportions = {
+ width: this.helper.outerWidth(),
+ height: this.helper.outerHeight()
+ };
+ },
+
+ _setContainment: function() {
+
+ var o = this.options;
+ if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
+ if(o.containment == 'document' || o.containment == 'window') this.containment = [
+ 0 - this.offset.relative.left - this.offset.parent.left,
+ 0 - this.offset.relative.top - this.offset.parent.top,
+ $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
+ ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
+ ];
+
+ if(!(/^(document|window|parent)$/).test(o.containment)) {
+ var ce = $(o.containment)[0];
+ var co = $(o.containment).offset();
+ var over = ($(ce).css("overflow") != 'hidden');
+
+ this.containment = [
+ co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
+ co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
+ co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
+ co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
+ ];
+ }
+
+ },
+
+ _convertPositionTo: function(d, pos) {
+
+ if(!pos) pos = this.position;
+ var mod = d == "absolute" ? 1 : -1;
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+ return {
+ top: (
+ pos.top // The absolute mouse position
+ + this.offset.relative.top * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ + this.offset.parent.top * mod // The offsetParent's offset without borders (offset + border)
+ - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
+ ),
+ left: (
+ pos.left // The absolute mouse position
+ + this.offset.relative.left * mod // Only for relative positioned nodes: Relative offset from element to offset parent
+ + this.offset.parent.left * mod // The offsetParent's offset without borders (offset + border)
+ - ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
+ )
+ };
+
+ },
+
+ _generatePosition: function(event) {
+
+ var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
+
+ // This is another very weird special case that only happens for relative elements:
+ // 1. If the css position is relative
+ // 2. and the scroll parent is the document or similar to the offset parent
+ // we have to refresh the relative offset during the scroll so there are no jumps
+ if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
+ this.offset.relative = this._getRelativeOffset();
+ }
+
+ var pageX = event.pageX;
+ var pageY = event.pageY;
+
+ /*
+ * - Position constraining -
+ * Constrain the position to a mix of grid, containment.
+ */
+
+ if(this.originalPosition) { //If we are not dragging yet, we won't check for options
+
+ if(this.containment) {
+ if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
+ if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
+ if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
+ if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
+ }
+
+ if(o.grid) {
+ var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
+ pageY = this.containment ? (!(top - this.offset.click.top < this.containment[1] || top - this.offset.click.top > this.containment[3]) ? top : (!(top - this.offset.click.top < this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;
+
+ var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
+ pageX = this.containment ? (!(left - this.offset.click.left < this.containment[0] || left - this.offset.click.left > this.containment[2]) ? left : (!(left - this.offset.click.left < this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
+ }
+
+ }
+
+ return {
+ top: (
+ pageY // The absolute mouse position
+ - this.offset.click.top // Click offset (relative to the element)
+ - this.offset.relative.top // Only for relative positioned nodes: Relative offset from element to offset parent
+ - this.offset.parent.top // The offsetParent's offset without borders (offset + border)
+ + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
+ ),
+ left: (
+ pageX // The absolute mouse position
+ - this.offset.click.left // Click offset (relative to the element)
+ - this.offset.relative.left // Only for relative positioned nodes: Relative offset from element to offset parent
+ - this.offset.parent.left // The offsetParent's offset without borders (offset + border)
+ + ( ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
+ )
+ };
+
+ },
+
+ _rearrange: function(event, i, a, hardRefresh) {
+
+ a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction == 'down' ? i.item[0] : i.item[0].nextSibling));
+
+ //Various things done here to improve the performance:
+ // 1. we create a setTimeout, that calls refreshPositions
+ // 2. on the instance, we have a counter variable, that get's higher after every append
+ // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
+ // 4. this lets only the last addition to the timeout stack through
+ this.counter = this.counter ? ++this.counter : 1;
+ var counter = this.counter;
+
+ this._delay(function() {
+ if(counter == this.counter) this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
+ });
+
+ },
+
+ _clear: function(event, noPropagation) {
+
+ this.reverting = false;
+ // We delay all events that have to be triggered to after the point where the placeholder has been removed and
+ // everything else normalized again
+ var delayedTriggers = [];
+
+ // We first have to update the dom position of the actual currentItem
+ // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
+ if(!this._noFinalSort && this.currentItem.parent().length) this.placeholder.before(this.currentItem);
+ this._noFinalSort = null;
+
+ if(this.helper[0] == this.currentItem[0]) {
+ for(var i in this._storedCSS) {
+ if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
+ }
+ this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
+ } else {
+ this.currentItem.show();
+ }
+
+ if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
+ if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
+
+ // Check if the items Container has Changed and trigger appropriate
+ // events.
+ if (this !== this.currentContainer) {
+ if(!noPropagation) {
+ delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this)); }; }).call(this, this.currentContainer));
+ }
+ }
+
+
+ //Post events to containers
+ for (var i = this.containers.length - 1; i >= 0; i--){
+ if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
+ if(this.containers[i].containerCache.over) {
+ delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); }; }).call(this, this.containers[i]));
+ this.containers[i].containerCache.over = 0;
+ }
+ }
+
+ //Do what was originally in plugins
+ if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
+ if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
+ if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
+
+ this.dragging = false;
+ if(this.cancelHelperRemoval) {
+ if(!noPropagation) {
+ this._trigger("beforeStop", event, this._uiHash());
+ for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
+ this._trigger("stop", event, this._uiHash());
+ }
+
+ this.fromOutside = false;
+ return false;
+ }
+
+ if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
+
+ //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
+ this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
+
+ if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
+
+ if(!noPropagation) {
+ for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
+ this._trigger("stop", event, this._uiHash());
+ }
+
+ this.fromOutside = false;
+ return true;
+
+ },
+
+ _trigger: function() {
+ if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
+ this.cancel();
+ }
+ },
+
+ _uiHash: function(_inst) {
+ var inst = _inst || this;
+ return {
+ helper: inst.helper,
+ placeholder: inst.placeholder || $([]),
+ position: inst.position,
+ originalPosition: inst.originalPosition,
+ offset: inst.positionAbs,
+ item: inst.currentItem,
+ sender: _inst ? _inst.element : null
+ };
+ }
+
+});
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.spinner.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.spinner.js
new file mode 100644
index 00000000..98dc9dfe
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.spinner.js
@@ -0,0 +1,478 @@
+/*!
+ * jQuery UI Spinner 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/spinner/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.button.js
+ */
+(function( $ ) {
+
+function modifier( fn ) {
+ return function() {
+ var previous = this.element.val();
+ fn.apply( this, arguments );
+ this._refresh();
+ if ( previous !== this.element.val() ) {
+ this._trigger( "change" );
+ }
+ };
+}
+
+$.widget( "ui.spinner", {
+ version: "1.9.2",
+ defaultElement: "<input>",
+ widgetEventPrefix: "spin",
+ options: {
+ culture: null,
+ icons: {
+ down: "ui-icon-triangle-1-s",
+ up: "ui-icon-triangle-1-n"
+ },
+ incremental: true,
+ max: null,
+ min: null,
+ numberFormat: null,
+ page: 10,
+ step: 1,
+
+ change: null,
+ spin: null,
+ start: null,
+ stop: null
+ },
+
+ _create: function() {
+ // handle string values that need to be parsed
+ this._setOption( "max", this.options.max );
+ this._setOption( "min", this.options.min );
+ this._setOption( "step", this.options.step );
+
+ // format the value, but don't constrain
+ this._value( this.element.val(), true );
+
+ this._draw();
+ this._on( this._events );
+ this._refresh();
+
+ // turning off autocomplete prevents the browser from remembering the
+ // value when navigating through history, so we re-enable autocomplete
+ // if the page is unloaded before the widget is destroyed. #7790
+ this._on( this.window, {
+ beforeunload: function() {
+ this.element.removeAttr( "autocomplete" );
+ }
+ });
+ },
+
+ _getCreateOptions: function() {
+ var options = {},
+ element = this.element;
+
+ $.each( [ "min", "max", "step" ], function( i, option ) {
+ var value = element.attr( option );
+ if ( value !== undefined && value.length ) {
+ options[ option ] = value;
+ }
+ });
+
+ return options;
+ },
+
+ _events: {
+ keydown: function( event ) {
+ if ( this._start( event ) && this._keydown( event ) ) {
+ event.preventDefault();
+ }
+ },
+ keyup: "_stop",
+ focus: function() {
+ this.previous = this.element.val();
+ },
+ blur: function( event ) {
+ if ( this.cancelBlur ) {
+ delete this.cancelBlur;
+ return;
+ }
+
+ this._refresh();
+ if ( this.previous !== this.element.val() ) {
+ this._trigger( "change", event );
+ }
+ },
+ mousewheel: function( event, delta ) {
+ if ( !delta ) {
+ return;
+ }
+ if ( !this.spinning && !this._start( event ) ) {
+ return false;
+ }
+
+ this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
+ clearTimeout( this.mousewheelTimer );
+ this.mousewheelTimer = this._delay(function() {
+ if ( this.spinning ) {
+ this._stop( event );
+ }
+ }, 100 );
+ event.preventDefault();
+ },
+ "mousedown .ui-spinner-button": function( event ) {
+ var previous;
+
+ // We never want the buttons to have focus; whenever the user is
+ // interacting with the spinner, the focus should be on the input.
+ // If the input is focused then this.previous is properly set from
+ // when the input first received focus. If the input is not focused
+ // then we need to set this.previous based on the value before spinning.
+ previous = this.element[0] === this.document[0].activeElement ?
+ this.previous : this.element.val();
+ function checkFocus() {
+ var isActive = this.element[0] === this.document[0].activeElement;
+ if ( !isActive ) {
+ this.element.focus();
+ this.previous = previous;
+ // support: IE
+ // IE sets focus asynchronously, so we need to check if focus
+ // moved off of the input because the user clicked on the button.
+ this._delay(function() {
+ this.previous = previous;
+ });
+ }
+ }
+
+ // ensure focus is on (or stays on) the text field
+ event.preventDefault();
+ checkFocus.call( this );
+
+ // support: IE
+ // IE doesn't prevent moving focus even with event.preventDefault()
+ // so we set a flag to know when we should ignore the blur event
+ // and check (again) if focus moved off of the input.
+ this.cancelBlur = true;
+ this._delay(function() {
+ delete this.cancelBlur;
+ checkFocus.call( this );
+ });
+
+ if ( this._start( event ) === false ) {
+ return;
+ }
+
+ this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
+ },
+ "mouseup .ui-spinner-button": "_stop",
+ "mouseenter .ui-spinner-button": function( event ) {
+ // button will add ui-state-active if mouse was down while mouseleave and kept down
+ if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
+ return;
+ }
+
+ if ( this._start( event ) === false ) {
+ return false;
+ }
+ this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
+ },
+ // TODO: do we really want to consider this a stop?
+ // shouldn't we just stop the repeater and wait until mouseup before
+ // we trigger the stop event?
+ "mouseleave .ui-spinner-button": "_stop"
+ },
+
+ _draw: function() {
+ var uiSpinner = this.uiSpinner = this.element
+ .addClass( "ui-spinner-input" )
+ .attr( "autocomplete", "off" )
+ .wrap( this._uiSpinnerHtml() )
+ .parent()
+ // add buttons
+ .append( this._buttonHtml() );
+
+ this.element.attr( "role", "spinbutton" );
+
+ // button bindings
+ this.buttons = uiSpinner.find( ".ui-spinner-button" )
+ .attr( "tabIndex", -1 )
+ .button()
+ .removeClass( "ui-corner-all" );
+
+ // IE 6 doesn't understand height: 50% for the buttons
+ // unless the wrapper has an explicit height
+ if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
+ uiSpinner.height() > 0 ) {
+ uiSpinner.height( uiSpinner.height() );
+ }
+
+ // disable spinner if element was already disabled
+ if ( this.options.disabled ) {
+ this.disable();
+ }
+ },
+
+ _keydown: function( event ) {
+ var options = this.options,
+ keyCode = $.ui.keyCode;
+
+ switch ( event.keyCode ) {
+ case keyCode.UP:
+ this._repeat( null, 1, event );
+ return true;
+ case keyCode.DOWN:
+ this._repeat( null, -1, event );
+ return true;
+ case keyCode.PAGE_UP:
+ this._repeat( null, options.page, event );
+ return true;
+ case keyCode.PAGE_DOWN:
+ this._repeat( null, -options.page, event );
+ return true;
+ }
+
+ return false;
+ },
+
+ _uiSpinnerHtml: function() {
+ return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
+ },
+
+ _buttonHtml: function() {
+ return "" +
+ "<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
+ "<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
+ "</a>" +
+ "<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
+ "<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
+ "</a>";
+ },
+
+ _start: function( event ) {
+ if ( !this.spinning && this._trigger( "start", event ) === false ) {
+ return false;
+ }
+
+ if ( !this.counter ) {
+ this.counter = 1;
+ }
+ this.spinning = true;
+ return true;
+ },
+
+ _repeat: function( i, steps, event ) {
+ i = i || 500;
+
+ clearTimeout( this.timer );
+ this.timer = this._delay(function() {
+ this._repeat( 40, steps, event );
+ }, i );
+
+ this._spin( steps * this.options.step, event );
+ },
+
+ _spin: function( step, event ) {
+ var value = this.value() || 0;
+
+ if ( !this.counter ) {
+ this.counter = 1;
+ }
+
+ value = this._adjustValue( value + step * this._increment( this.counter ) );
+
+ if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
+ this._value( value );
+ this.counter++;
+ }
+ },
+
+ _increment: function( i ) {
+ var incremental = this.options.incremental;
+
+ if ( incremental ) {
+ return $.isFunction( incremental ) ?
+ incremental( i ) :
+ Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
+ }
+
+ return 1;
+ },
+
+ _precision: function() {
+ var precision = this._precisionOf( this.options.step );
+ if ( this.options.min !== null ) {
+ precision = Math.max( precision, this._precisionOf( this.options.min ) );
+ }
+ return precision;
+ },
+
+ _precisionOf: function( num ) {
+ var str = num.toString(),
+ decimal = str.indexOf( "." );
+ return decimal === -1 ? 0 : str.length - decimal - 1;
+ },
+
+ _adjustValue: function( value ) {
+ var base, aboveMin,
+ options = this.options;
+
+ // make sure we're at a valid step
+ // - find out where we are relative to the base (min or 0)
+ base = options.min !== null ? options.min : 0;
+ aboveMin = value - base;
+ // - round to the nearest step
+ aboveMin = Math.round(aboveMin / options.step) * options.step;
+ // - rounding is based on 0, so adjust back to our base
+ value = base + aboveMin;
+
+ // fix precision from bad JS floating point math
+ value = parseFloat( value.toFixed( this._precision() ) );
+
+ // clamp the value
+ if ( options.max !== null && value > options.max) {
+ return options.max;
+ }
+ if ( options.min !== null && value < options.min ) {
+ return options.min;
+ }
+
+ return value;
+ },
+
+ _stop: function( event ) {
+ if ( !this.spinning ) {
+ return;
+ }
+
+ clearTimeout( this.timer );
+ clearTimeout( this.mousewheelTimer );
+ this.counter = 0;
+ this.spinning = false;
+ this._trigger( "stop", event );
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "culture" || key === "numberFormat" ) {
+ var prevValue = this._parse( this.element.val() );
+ this.options[ key ] = value;
+ this.element.val( this._format( prevValue ) );
+ return;
+ }
+
+ if ( key === "max" || key === "min" || key === "step" ) {
+ if ( typeof value === "string" ) {
+ value = this._parse( value );
+ }
+ }
+
+ this._super( key, value );
+
+ if ( key === "disabled" ) {
+ if ( value ) {
+ this.element.prop( "disabled", true );
+ this.buttons.button( "disable" );
+ } else {
+ this.element.prop( "disabled", false );
+ this.buttons.button( "enable" );
+ }
+ }
+ },
+
+ _setOptions: modifier(function( options ) {
+ this._super( options );
+ this._value( this.element.val() );
+ }),
+
+ _parse: function( val ) {
+ if ( typeof val === "string" && val !== "" ) {
+ val = window.Globalize && this.options.numberFormat ?
+ Globalize.parseFloat( val, 10, this.options.culture ) : +val;
+ }
+ return val === "" || isNaN( val ) ? null : val;
+ },
+
+ _format: function( value ) {
+ if ( value === "" ) {
+ return "";
+ }
+ return window.Globalize && this.options.numberFormat ?
+ Globalize.format( value, this.options.numberFormat, this.options.culture ) :
+ value;
+ },
+
+ _refresh: function() {
+ this.element.attr({
+ "aria-valuemin": this.options.min,
+ "aria-valuemax": this.options.max,
+ // TODO: what should we do with values that can't be parsed?
+ "aria-valuenow": this._parse( this.element.val() )
+ });
+ },
+
+ // update the value without triggering change
+ _value: function( value, allowAny ) {
+ var parsed;
+ if ( value !== "" ) {
+ parsed = this._parse( value );
+ if ( parsed !== null ) {
+ if ( !allowAny ) {
+ parsed = this._adjustValue( parsed );
+ }
+ value = this._format( parsed );
+ }
+ }
+ this.element.val( value );
+ this._refresh();
+ },
+
+ _destroy: function() {
+ this.element
+ .removeClass( "ui-spinner-input" )
+ .prop( "disabled", false )
+ .removeAttr( "autocomplete" )
+ .removeAttr( "role" )
+ .removeAttr( "aria-valuemin" )
+ .removeAttr( "aria-valuemax" )
+ .removeAttr( "aria-valuenow" );
+ this.uiSpinner.replaceWith( this.element );
+ },
+
+ stepUp: modifier(function( steps ) {
+ this._stepUp( steps );
+ }),
+ _stepUp: function( steps ) {
+ this._spin( (steps || 1) * this.options.step );
+ },
+
+ stepDown: modifier(function( steps ) {
+ this._stepDown( steps );
+ }),
+ _stepDown: function( steps ) {
+ this._spin( (steps || 1) * -this.options.step );
+ },
+
+ pageUp: modifier(function( pages ) {
+ this._stepUp( (pages || 1) * this.options.page );
+ }),
+
+ pageDown: modifier(function( pages ) {
+ this._stepDown( (pages || 1) * this.options.page );
+ }),
+
+ value: function( newVal ) {
+ if ( !arguments.length ) {
+ return this._parse( this.element.val() );
+ }
+ modifier( this._value ).call( this, newVal );
+ },
+
+ widget: function() {
+ return this.uiSpinner;
+ }
+});
+
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.tabs.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.tabs.js
new file mode 100644
index 00000000..6ea164eb
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.tabs.js
@@ -0,0 +1,1366 @@
+/*!
+ * jQuery UI Tabs 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/tabs/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ */
+(function( $, undefined ) {
+
+var tabId = 0,
+ rhash = /#.*$/;
+
+function getNextTabId() {
+ return ++tabId;
+}
+
+function isLocal( anchor ) {
+ return anchor.hash.length > 1 &&
+ anchor.href.replace( rhash, "" ) ===
+ location.href.replace( rhash, "" )
+ // support: Safari 5.1
+ // Safari 5.1 doesn't encode spaces in window.location
+ // but it does encode spaces from anchors (#8777)
+ .replace( /\s/g, "%20" );
+}
+
+$.widget( "ui.tabs", {
+ version: "1.9.2",
+ delay: 300,
+ options: {
+ active: null,
+ collapsible: false,
+ event: "click",
+ heightStyle: "content",
+ hide: null,
+ show: null,
+
+ // callbacks
+ activate: null,
+ beforeActivate: null,
+ beforeLoad: null,
+ load: null
+ },
+
+ _create: function() {
+ var that = this,
+ options = this.options,
+ active = options.active,
+ locationHash = location.hash.substring( 1 );
+
+ this.running = false;
+
+ this.element
+ .addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
+ .toggleClass( "ui-tabs-collapsible", options.collapsible )
+ // Prevent users from focusing disabled tabs via click
+ .delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
+ if ( $( this ).is( ".ui-state-disabled" ) ) {
+ event.preventDefault();
+ }
+ })
+ // support: IE <9
+ // Preventing the default action in mousedown doesn't prevent IE
+ // from focusing the element, so if the anchor gets focused, blur.
+ // We don't have to worry about focusing the previously focused
+ // element since clicking on a non-focusable element should focus
+ // the body anyway.
+ .delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
+ if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
+ this.blur();
+ }
+ });
+
+ this._processTabs();
+
+ if ( active === null ) {
+ // check the fragment identifier in the URL
+ if ( locationHash ) {
+ this.tabs.each(function( i, tab ) {
+ if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
+ active = i;
+ return false;
+ }
+ });
+ }
+
+ // check for a tab marked active via a class
+ if ( active === null ) {
+ active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
+ }
+
+ // no active tab, set to false
+ if ( active === null || active === -1 ) {
+ active = this.tabs.length ? 0 : false;
+ }
+ }
+
+ // handle numbers: negative, out of range
+ if ( active !== false ) {
+ active = this.tabs.index( this.tabs.eq( active ) );
+ if ( active === -1 ) {
+ active = options.collapsible ? false : 0;
+ }
+ }
+ options.active = active;
+
+ // don't allow collapsible: false and active: false
+ if ( !options.collapsible && options.active === false && this.anchors.length ) {
+ options.active = 0;
+ }
+
+ // Take disabling tabs via class attribute from HTML
+ // into account and update option properly.
+ if ( $.isArray( options.disabled ) ) {
+ options.disabled = $.unique( options.disabled.concat(
+ $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
+ return that.tabs.index( li );
+ })
+ ) ).sort();
+ }
+
+ // check for length avoids error when initializing empty list
+ if ( this.options.active !== false && this.anchors.length ) {
+ this.active = this._findActive( this.options.active );
+ } else {
+ this.active = $();
+ }
+
+ this._refresh();
+
+ if ( this.active.length ) {
+ this.load( options.active );
+ }
+ },
+
+ _getCreateEventData: function() {
+ return {
+ tab: this.active,
+ panel: !this.active.length ? $() : this._getPanelForTab( this.active )
+ };
+ },
+
+ _tabKeydown: function( event ) {
+ var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
+ selectedIndex = this.tabs.index( focusedTab ),
+ goingForward = true;
+
+ if ( this._handlePageNav( event ) ) {
+ return;
+ }
+
+ switch ( event.keyCode ) {
+ case $.ui.keyCode.RIGHT:
+ case $.ui.keyCode.DOWN:
+ selectedIndex++;
+ break;
+ case $.ui.keyCode.UP:
+ case $.ui.keyCode.LEFT:
+ goingForward = false;
+ selectedIndex--;
+ break;
+ case $.ui.keyCode.END:
+ selectedIndex = this.anchors.length - 1;
+ break;
+ case $.ui.keyCode.HOME:
+ selectedIndex = 0;
+ break;
+ case $.ui.keyCode.SPACE:
+ // Activate only, no collapsing
+ event.preventDefault();
+ clearTimeout( this.activating );
+ this._activate( selectedIndex );
+ return;
+ case $.ui.keyCode.ENTER:
+ // Toggle (cancel delayed activation, allow collapsing)
+ event.preventDefault();
+ clearTimeout( this.activating );
+ // Determine if we should collapse or activate
+ this._activate( selectedIndex === this.options.active ? false : selectedIndex );
+ return;
+ default:
+ return;
+ }
+
+ // Focus the appropriate tab, based on which key was pressed
+ event.preventDefault();
+ clearTimeout( this.activating );
+ selectedIndex = this._focusNextTab( selectedIndex, goingForward );
+
+ // Navigating with control key will prevent automatic activation
+ if ( !event.ctrlKey ) {
+ // Update aria-selected immediately so that AT think the tab is already selected.
+ // Otherwise AT may confuse the user by stating that they need to activate the tab,
+ // but the tab will already be activated by the time the announcement finishes.
+ focusedTab.attr( "aria-selected", "false" );
+ this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
+
+ this.activating = this._delay(function() {
+ this.option( "active", selectedIndex );
+ }, this.delay );
+ }
+ },
+
+ _panelKeydown: function( event ) {
+ if ( this._handlePageNav( event ) ) {
+ return;
+ }
+
+ // Ctrl+up moves focus to the current tab
+ if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
+ event.preventDefault();
+ this.active.focus();
+ }
+ },
+
+ // Alt+page up/down moves focus to the previous/next tab (and activates)
+ _handlePageNav: function( event ) {
+ if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
+ this._activate( this._focusNextTab( this.options.active - 1, false ) );
+ return true;
+ }
+ if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
+ this._activate( this._focusNextTab( this.options.active + 1, true ) );
+ return true;
+ }
+ },
+
+ _findNextTab: function( index, goingForward ) {
+ var lastTabIndex = this.tabs.length - 1;
+
+ function constrain() {
+ if ( index > lastTabIndex ) {
+ index = 0;
+ }
+ if ( index < 0 ) {
+ index = lastTabIndex;
+ }
+ return index;
+ }
+
+ while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
+ index = goingForward ? index + 1 : index - 1;
+ }
+
+ return index;
+ },
+
+ _focusNextTab: function( index, goingForward ) {
+ index = this._findNextTab( index, goingForward );
+ this.tabs.eq( index ).focus();
+ return index;
+ },
+
+ _setOption: function( key, value ) {
+ if ( key === "active" ) {
+ // _activate() will handle invalid values and update this.options
+ this._activate( value );
+ return;
+ }
+
+ if ( key === "disabled" ) {
+ // don't use the widget factory's disabled handling
+ this._setupDisabled( value );
+ return;
+ }
+
+ this._super( key, value);
+
+ if ( key === "collapsible" ) {
+ this.element.toggleClass( "ui-tabs-collapsible", value );
+ // Setting collapsible: false while collapsed; open first panel
+ if ( !value && this.options.active === false ) {
+ this._activate( 0 );
+ }
+ }
+
+ if ( key === "event" ) {
+ this._setupEvents( value );
+ }
+
+ if ( key === "heightStyle" ) {
+ this._setupHeightStyle( value );
+ }
+ },
+
+ _tabId: function( tab ) {
+ return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
+ },
+
+ _sanitizeSelector: function( hash ) {
+ return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
+ },
+
+ refresh: function() {
+ var options = this.options,
+ lis = this.tablist.children( ":has(a[href])" );
+
+ // get disabled tabs from class attribute from HTML
+ // this will get converted to a boolean if needed in _refresh()
+ options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
+ return lis.index( tab );
+ });
+
+ this._processTabs();
+
+ // was collapsed or no tabs
+ if ( options.active === false || !this.anchors.length ) {
+ options.active = false;
+ this.active = $();
+ // was active, but active tab is gone
+ } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
+ // all remaining tabs are disabled
+ if ( this.tabs.length === options.disabled.length ) {
+ options.active = false;
+ this.active = $();
+ // activate previous tab
+ } else {
+ this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
+ }
+ // was active, active tab still exists
+ } else {
+ // make sure active index is correct
+ options.active = this.tabs.index( this.active );
+ }
+
+ this._refresh();
+ },
+
+ _refresh: function() {
+ this._setupDisabled( this.options.disabled );
+ this._setupEvents( this.options.event );
+ this._setupHeightStyle( this.options.heightStyle );
+
+ this.tabs.not( this.active ).attr({
+ "aria-selected": "false",
+ tabIndex: -1
+ });
+ this.panels.not( this._getPanelForTab( this.active ) )
+ .hide()
+ .attr({
+ "aria-expanded": "false",
+ "aria-hidden": "true"
+ });
+
+ // Make sure one tab is in the tab order
+ if ( !this.active.length ) {
+ this.tabs.eq( 0 ).attr( "tabIndex", 0 );
+ } else {
+ this.active
+ .addClass( "ui-tabs-active ui-state-active" )
+ .attr({
+ "aria-selected": "true",
+ tabIndex: 0
+ });
+ this._getPanelForTab( this.active )
+ .show()
+ .attr({
+ "aria-expanded": "true",
+ "aria-hidden": "false"
+ });
+ }
+ },
+
+ _processTabs: function() {
+ var that = this;
+
+ this.tablist = this._getList()
+ .addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
+ .attr( "role", "tablist" );
+
+ this.tabs = this.tablist.find( "> li:has(a[href])" )
+ .addClass( "ui-state-default ui-corner-top" )
+ .attr({
+ role: "tab",
+ tabIndex: -1
+ });
+
+ this.anchors = this.tabs.map(function() {
+ return $( "a", this )[ 0 ];
+ })
+ .addClass( "ui-tabs-anchor" )
+ .attr({
+ role: "presentation",
+ tabIndex: -1
+ });
+
+ this.panels = $();
+
+ this.anchors.each(function( i, anchor ) {
+ var selector, panel, panelId,
+ anchorId = $( anchor ).uniqueId().attr( "id" ),
+ tab = $( anchor ).closest( "li" ),
+ originalAriaControls = tab.attr( "aria-controls" );
+
+ // inline tab
+ if ( isLocal( anchor ) ) {
+ selector = anchor.hash;
+ panel = that.element.find( that._sanitizeSelector( selector ) );
+ // remote tab
+ } else {
+ panelId = that._tabId( tab );
+ selector = "#" + panelId;
+ panel = that.element.find( selector );
+ if ( !panel.length ) {
+ panel = that._createPanel( panelId );
+ panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
+ }
+ panel.attr( "aria-live", "polite" );
+ }
+
+ if ( panel.length) {
+ that.panels = that.panels.add( panel );
+ }
+ if ( originalAriaControls ) {
+ tab.data( "ui-tabs-aria-controls", originalAriaControls );
+ }
+ tab.attr({
+ "aria-controls": selector.substring( 1 ),
+ "aria-labelledby": anchorId
+ });
+ panel.attr( "aria-labelledby", anchorId );
+ });
+
+ this.panels
+ .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
+ .attr( "role", "tabpanel" );
+ },
+
+ // allow overriding how to find the list for rare usage scenarios (#7715)
+ _getList: function() {
+ return this.element.find( "ol,ul" ).eq( 0 );
+ },
+
+ _createPanel: function( id ) {
+ return $( "<div>" )
+ .attr( "id", id )
+ .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
+ .data( "ui-tabs-destroy", true );
+ },
+
+ _setupDisabled: function( disabled ) {
+ if ( $.isArray( disabled ) ) {
+ if ( !disabled.length ) {
+ disabled = false;
+ } else if ( disabled.length === this.anchors.length ) {
+ disabled = true;
+ }
+ }
+
+ // disable tabs
+ for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
+ if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
+ $( li )
+ .addClass( "ui-state-disabled" )
+ .attr( "aria-disabled", "true" );
+ } else {
+ $( li )
+ .removeClass( "ui-state-disabled" )
+ .removeAttr( "aria-disabled" );
+ }
+ }
+
+ this.options.disabled = disabled;
+ },
+
+ _setupEvents: function( event ) {
+ var events = {
+ click: function( event ) {
+ event.preventDefault();
+ }
+ };
+ if ( event ) {
+ $.each( event.split(" "), function( index, eventName ) {
+ events[ eventName ] = "_eventHandler";
+ });
+ }
+
+ this._off( this.anchors.add( this.tabs ).add( this.panels ) );
+ this._on( this.anchors, events );
+ this._on( this.tabs, { keydown: "_tabKeydown" } );
+ this._on( this.panels, { keydown: "_panelKeydown" } );
+
+ this._focusable( this.tabs );
+ this._hoverable( this.tabs );
+ },
+
+ _setupHeightStyle: function( heightStyle ) {
+ var maxHeight, overflow,
+ parent = this.element.parent();
+
+ if ( heightStyle === "fill" ) {
+ // IE 6 treats height like minHeight, so we need to turn off overflow
+ // in order to get a reliable height
+ // we use the minHeight support test because we assume that only
+ // browsers that don't support minHeight will treat height as minHeight
+ if ( !$.support.minHeight ) {
+ overflow = parent.css( "overflow" );
+ parent.css( "overflow", "hidden");
+ }
+ maxHeight = parent.height();
+ this.element.siblings( ":visible" ).each(function() {
+ var elem = $( this ),
+ position = elem.css( "position" );
+
+ if ( position === "absolute" || position === "fixed" ) {
+ return;
+ }
+ maxHeight -= elem.outerHeight( true );
+ });
+ if ( overflow ) {
+ parent.css( "overflow", overflow );
+ }
+
+ this.element.children().not( this.panels ).each(function() {
+ maxHeight -= $( this ).outerHeight( true );
+ });
+
+ this.panels.each(function() {
+ $( this ).height( Math.max( 0, maxHeight -
+ $( this ).innerHeight() + $( this ).height() ) );
+ })
+ .css( "overflow", "auto" );
+ } else if ( heightStyle === "auto" ) {
+ maxHeight = 0;
+ this.panels.each(function() {
+ maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
+ }).height( maxHeight );
+ }
+ },
+
+ _eventHandler: function( event ) {
+ var options = this.options,
+ active = this.active,
+ anchor = $( event.currentTarget ),
+ tab = anchor.closest( "li" ),
+ clickedIsActive = tab[ 0 ] === active[ 0 ],
+ collapsing = clickedIsActive && options.collapsible,
+ toShow = collapsing ? $() : this._getPanelForTab( tab ),
+ toHide = !active.length ? $() : this._getPanelForTab( active ),
+ eventData = {
+ oldTab: active,
+ oldPanel: toHide,
+ newTab: collapsing ? $() : tab,
+ newPanel: toShow
+ };
+
+ event.preventDefault();
+
+ if ( tab.hasClass( "ui-state-disabled" ) ||
+ // tab is already loading
+ tab.hasClass( "ui-tabs-loading" ) ||
+ // can't switch durning an animation
+ this.running ||
+ // click on active header, but not collapsible
+ ( clickedIsActive && !options.collapsible ) ||
+ // allow canceling activation
+ ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
+ return;
+ }
+
+ options.active = collapsing ? false : this.tabs.index( tab );
+
+ this.active = clickedIsActive ? $() : tab;
+ if ( this.xhr ) {
+ this.xhr.abort();
+ }
+
+ if ( !toHide.length && !toShow.length ) {
+ $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
+ }
+
+ if ( toShow.length ) {
+ this.load( this.tabs.index( tab ), event );
+ }
+ this._toggle( event, eventData );
+ },
+
+ // handles show/hide for selecting tabs
+ _toggle: function( event, eventData ) {
+ var that = this,
+ toShow = eventData.newPanel,
+ toHide = eventData.oldPanel;
+
+ this.running = true;
+
+ function complete() {
+ that.running = false;
+ that._trigger( "activate", event, eventData );
+ }
+
+ function show() {
+ eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
+
+ if ( toShow.length && that.options.show ) {
+ that._show( toShow, that.options.show, complete );
+ } else {
+ toShow.show();
+ complete();
+ }
+ }
+
+ // start out by hiding, then showing, then completing
+ if ( toHide.length && this.options.hide ) {
+ this._hide( toHide, this.options.hide, function() {
+ eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
+ show();
+ });
+ } else {
+ eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
+ toHide.hide();
+ show();
+ }
+
+ toHide.attr({
+ "aria-expanded": "false",
+ "aria-hidden": "true"
+ });
+ eventData.oldTab.attr( "aria-selected", "false" );
+ // If we're switching tabs, remove the old tab from the tab order.
+ // If we're opening from collapsed state, remove the previous tab from the tab order.
+ // If we're collapsing, then keep the collapsing tab in the tab order.
+ if ( toShow.length && toHide.length ) {
+ eventData.oldTab.attr( "tabIndex", -1 );
+ } else if ( toShow.length ) {
+ this.tabs.filter(function() {
+ return $( this ).attr( "tabIndex" ) === 0;
+ })
+ .attr( "tabIndex", -1 );
+ }
+
+ toShow.attr({
+ "aria-expanded": "true",
+ "aria-hidden": "false"
+ });
+ eventData.newTab.attr({
+ "aria-selected": "true",
+ tabIndex: 0
+ });
+ },
+
+ _activate: function( index ) {
+ var anchor,
+ active = this._findActive( index );
+
+ // trying to activate the already active panel
+ if ( active[ 0 ] === this.active[ 0 ] ) {
+ return;
+ }
+
+ // trying to collapse, simulate a click on the current active header
+ if ( !active.length ) {
+ active = this.active;
+ }
+
+ anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
+ this._eventHandler({
+ target: anchor,
+ currentTarget: anchor,
+ preventDefault: $.noop
+ });
+ },
+
+ _findActive: function( index ) {
+ return index === false ? $() : this.tabs.eq( index );
+ },
+
+ _getIndex: function( index ) {
+ // meta-function to give users option to provide a href string instead of a numerical index.
+ if ( typeof index === "string" ) {
+ index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
+ }
+
+ return index;
+ },
+
+ _destroy: function() {
+ if ( this.xhr ) {
+ this.xhr.abort();
+ }
+
+ this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );
+
+ this.tablist
+ .removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
+ .removeAttr( "role" );
+
+ this.anchors
+ .removeClass( "ui-tabs-anchor" )
+ .removeAttr( "role" )
+ .removeAttr( "tabIndex" )
+ .removeData( "href.tabs" )
+ .removeData( "load.tabs" )
+ .removeUniqueId();
+
+ this.tabs.add( this.panels ).each(function() {
+ if ( $.data( this, "ui-tabs-destroy" ) ) {
+ $( this ).remove();
+ } else {
+ $( this )
+ .removeClass( "ui-state-default ui-state-active ui-state-disabled " +
+ "ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
+ .removeAttr( "tabIndex" )
+ .removeAttr( "aria-live" )
+ .removeAttr( "aria-busy" )
+ .removeAttr( "aria-selected" )
+ .removeAttr( "aria-labelledby" )
+ .removeAttr( "aria-hidden" )
+ .removeAttr( "aria-expanded" )
+ .removeAttr( "role" );
+ }
+ });
+
+ this.tabs.each(function() {
+ var li = $( this ),
+ prev = li.data( "ui-tabs-aria-controls" );
+ if ( prev ) {
+ li.attr( "aria-controls", prev );
+ } else {
+ li.removeAttr( "aria-controls" );
+ }
+ });
+
+ this.panels.show();
+
+ if ( this.options.heightStyle !== "content" ) {
+ this.panels.css( "height", "" );
+ }
+ },
+
+ enable: function( index ) {
+ var disabled = this.options.disabled;
+ if ( disabled === false ) {
+ return;
+ }
+
+ if ( index === undefined ) {
+ disabled = false;
+ } else {
+ index = this._getIndex( index );
+ if ( $.isArray( disabled ) ) {
+ disabled = $.map( disabled, function( num ) {
+ return num !== index ? num : null;
+ });
+ } else {
+ disabled = $.map( this.tabs, function( li, num ) {
+ return num !== index ? num : null;
+ });
+ }
+ }
+ this._setupDisabled( disabled );
+ },
+
+ disable: function( index ) {
+ var disabled = this.options.disabled;
+ if ( disabled === true ) {
+ return;
+ }
+
+ if ( index === undefined ) {
+ disabled = true;
+ } else {
+ index = this._getIndex( index );
+ if ( $.inArray( index, disabled ) !== -1 ) {
+ return;
+ }
+ if ( $.isArray( disabled ) ) {
+ disabled = $.merge( [ index ], disabled ).sort();
+ } else {
+ disabled = [ index ];
+ }
+ }
+ this._setupDisabled( disabled );
+ },
+
+ load: function( index, event ) {
+ index = this._getIndex( index );
+ var that = this,
+ tab = this.tabs.eq( index ),
+ anchor = tab.find( ".ui-tabs-anchor" ),
+ panel = this._getPanelForTab( tab ),
+ eventData = {
+ tab: tab,
+ panel: panel
+ };
+
+ // not remote
+ if ( isLocal( anchor[ 0 ] ) ) {
+ return;
+ }
+
+ this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
+
+ // support: jQuery <1.8
+ // jQuery <1.8 returns false if the request is canceled in beforeSend,
+ // but as of 1.8, $.ajax() always returns a jqXHR object.
+ if ( this.xhr && this.xhr.statusText !== "canceled" ) {
+ tab.addClass( "ui-tabs-loading" );
+ panel.attr( "aria-busy", "true" );
+
+ this.xhr
+ .success(function( response ) {
+ // support: jQuery <1.8
+ // http://bugs.jquery.com/ticket/11778
+ setTimeout(function() {
+ panel.html( response );
+ that._trigger( "load", event, eventData );
+ }, 1 );
+ })
+ .complete(function( jqXHR, status ) {
+ // support: jQuery <1.8
+ // http://bugs.jquery.com/ticket/11778
+ setTimeout(function() {
+ if ( status === "abort" ) {
+ that.panels.stop( false, true );
+ }
+
+ tab.removeClass( "ui-tabs-loading" );
+ panel.removeAttr( "aria-busy" );
+
+ if ( jqXHR === that.xhr ) {
+ delete that.xhr;
+ }
+ }, 1 );
+ });
+ }
+ },
+
+ // TODO: Remove this function in 1.10 when ajaxOptions is removed
+ _ajaxSettings: function( anchor, event, eventData ) {
+ var that = this;
+ return {
+ url: anchor.attr( "href" ),
+ beforeSend: function( jqXHR, settings ) {
+ return that._trigger( "beforeLoad", event,
+ $.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
+ }
+ };
+ },
+
+ _getPanelForTab: function( tab ) {
+ var id = $( tab ).attr( "aria-controls" );
+ return this.element.find( this._sanitizeSelector( "#" + id ) );
+ }
+});
+
+// DEPRECATED
+if ( $.uiBackCompat !== false ) {
+
+ // helper method for a lot of the back compat extensions
+ $.ui.tabs.prototype._ui = function( tab, panel ) {
+ return {
+ tab: tab,
+ panel: panel,
+ index: this.anchors.index( tab )
+ };
+ };
+
+ // url method
+ $.widget( "ui.tabs", $.ui.tabs, {
+ url: function( index, url ) {
+ this.anchors.eq( index ).attr( "href", url );
+ }
+ });
+
+ // TODO: Remove _ajaxSettings() method when removing this extension
+ // ajaxOptions and cache options
+ $.widget( "ui.tabs", $.ui.tabs, {
+ options: {
+ ajaxOptions: null,
+ cache: false
+ },
+
+ _create: function() {
+ this._super();
+
+ var that = this;
+
+ this._on({ tabsbeforeload: function( event, ui ) {
+ // tab is already cached
+ if ( $.data( ui.tab[ 0 ], "cache.tabs" ) ) {
+ event.preventDefault();
+ return;
+ }
+
+ ui.jqXHR.success(function() {
+ if ( that.options.cache ) {
+ $.data( ui.tab[ 0 ], "cache.tabs", true );
+ }
+ });
+ }});
+ },
+
+ _ajaxSettings: function( anchor, event, ui ) {
+ var ajaxOptions = this.options.ajaxOptions;
+ return $.extend( {}, ajaxOptions, {
+ error: function( xhr, status ) {
+ try {
+ // Passing index avoid a race condition when this method is
+ // called after the user has selected another tab.
+ // Pass the anchor that initiated this request allows
+ // loadError to manipulate the tab content panel via $(a.hash)
+ ajaxOptions.error(
+ xhr, status, ui.tab.closest( "li" ).index(), ui.tab[ 0 ] );
+ }
+ catch ( error ) {}
+ }
+ }, this._superApply( arguments ) );
+ },
+
+ _setOption: function( key, value ) {
+ // reset cache if switching from cached to not cached
+ if ( key === "cache" && value === false ) {
+ this.anchors.removeData( "cache.tabs" );
+ }
+ this._super( key, value );
+ },
+
+ _destroy: function() {
+ this.anchors.removeData( "cache.tabs" );
+ this._super();
+ },
+
+ url: function( index ){
+ this.anchors.eq( index ).removeData( "cache.tabs" );
+ this._superApply( arguments );
+ }
+ });
+
+ // abort method
+ $.widget( "ui.tabs", $.ui.tabs, {
+ abort: function() {
+ if ( this.xhr ) {
+ this.xhr.abort();
+ }
+ }
+ });
+
+ // spinner
+ $.widget( "ui.tabs", $.ui.tabs, {
+ options: {
+ spinner: "<em>Loading&#8230;</em>"
+ },
+ _create: function() {
+ this._super();
+ this._on({
+ tabsbeforeload: function( event, ui ) {
+ // Don't react to nested tabs or tabs that don't use a spinner
+ if ( event.target !== this.element[ 0 ] ||
+ !this.options.spinner ) {
+ return;
+ }
+
+ var span = ui.tab.find( "span" ),
+ html = span.html();
+ span.html( this.options.spinner );
+ ui.jqXHR.complete(function() {
+ span.html( html );
+ });
+ }
+ });
+ }
+ });
+
+ // enable/disable events
+ $.widget( "ui.tabs", $.ui.tabs, {
+ options: {
+ enable: null,
+ disable: null
+ },
+
+ enable: function( index ) {
+ var options = this.options,
+ trigger;
+
+ if ( index && options.disabled === true ||
+ ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) !== -1 ) ) {
+ trigger = true;
+ }
+
+ this._superApply( arguments );
+
+ if ( trigger ) {
+ this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
+ }
+ },
+
+ disable: function( index ) {
+ var options = this.options,
+ trigger;
+
+ if ( index && options.disabled === false ||
+ ( $.isArray( options.disabled ) && $.inArray( index, options.disabled ) === -1 ) ) {
+ trigger = true;
+ }
+
+ this._superApply( arguments );
+
+ if ( trigger ) {
+ this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
+ }
+ }
+ });
+
+ // add/remove methods and events
+ $.widget( "ui.tabs", $.ui.tabs, {
+ options: {
+ add: null,
+ remove: null,
+ tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
+ },
+
+ add: function( url, label, index ) {
+ if ( index === undefined ) {
+ index = this.anchors.length;
+ }
+
+ var doInsertAfter, panel,
+ options = this.options,
+ li = $( options.tabTemplate
+ .replace( /#\{href\}/g, url )
+ .replace( /#\{label\}/g, label ) ),
+ id = !url.indexOf( "#" ) ?
+ url.replace( "#", "" ) :
+ this._tabId( li );
+
+ li.addClass( "ui-state-default ui-corner-top" ).data( "ui-tabs-destroy", true );
+ li.attr( "aria-controls", id );
+
+ doInsertAfter = index >= this.tabs.length;
+
+ // try to find an existing element before creating a new one
+ panel = this.element.find( "#" + id );
+ if ( !panel.length ) {
+ panel = this._createPanel( id );
+ if ( doInsertAfter ) {
+ if ( index > 0 ) {
+ panel.insertAfter( this.panels.eq( -1 ) );
+ } else {
+ panel.appendTo( this.element );
+ }
+ } else {
+ panel.insertBefore( this.panels[ index ] );
+ }
+ }
+ panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" ).hide();
+
+ if ( doInsertAfter ) {
+ li.appendTo( this.tablist );
+ } else {
+ li.insertBefore( this.tabs[ index ] );
+ }
+
+ options.disabled = $.map( options.disabled, function( n ) {
+ return n >= index ? ++n : n;
+ });
+
+ this.refresh();
+ if ( this.tabs.length === 1 && options.active === false ) {
+ this.option( "active", 0 );
+ }
+
+ this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
+ return this;
+ },
+
+ remove: function( index ) {
+ index = this._getIndex( index );
+ var options = this.options,
+ tab = this.tabs.eq( index ).remove(),
+ panel = this._getPanelForTab( tab ).remove();
+
+ // If selected tab was removed focus tab to the right or
+ // in case the last tab was removed the tab to the left.
+ // We check for more than 2 tabs, because if there are only 2,
+ // then when we remove this tab, there will only be one tab left
+ // so we don't need to detect which tab to activate.
+ if ( tab.hasClass( "ui-tabs-active" ) && this.anchors.length > 2 ) {
+ this._activate( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
+ }
+
+ options.disabled = $.map(
+ $.grep( options.disabled, function( n ) {
+ return n !== index;
+ }),
+ function( n ) {
+ return n >= index ? --n : n;
+ });
+
+ this.refresh();
+
+ this._trigger( "remove", null, this._ui( tab.find( "a" )[ 0 ], panel[ 0 ] ) );
+ return this;
+ }
+ });
+
+ // length method
+ $.widget( "ui.tabs", $.ui.tabs, {
+ length: function() {
+ return this.anchors.length;
+ }
+ });
+
+ // panel ids (idPrefix option + title attribute)
+ $.widget( "ui.tabs", $.ui.tabs, {
+ options: {
+ idPrefix: "ui-tabs-"
+ },
+
+ _tabId: function( tab ) {
+ var a = tab.is( "li" ) ? tab.find( "a[href]" ) : tab;
+ a = a[0];
+ return $( a ).closest( "li" ).attr( "aria-controls" ) ||
+ a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF\-]/g, "" ) ||
+ this.options.idPrefix + getNextTabId();
+ }
+ });
+
+ // _createPanel method
+ $.widget( "ui.tabs", $.ui.tabs, {
+ options: {
+ panelTemplate: "<div></div>"
+ },
+
+ _createPanel: function( id ) {
+ return $( this.options.panelTemplate )
+ .attr( "id", id )
+ .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
+ .data( "ui-tabs-destroy", true );
+ }
+ });
+
+ // selected option
+ $.widget( "ui.tabs", $.ui.tabs, {
+ _create: function() {
+ var options = this.options;
+ if ( options.active === null && options.selected !== undefined ) {
+ options.active = options.selected === -1 ? false : options.selected;
+ }
+ this._super();
+ options.selected = options.active;
+ if ( options.selected === false ) {
+ options.selected = -1;
+ }
+ },
+
+ _setOption: function( key, value ) {
+ if ( key !== "selected" ) {
+ return this._super( key, value );
+ }
+
+ var options = this.options;
+ this._super( "active", value === -1 ? false : value );
+ options.selected = options.active;
+ if ( options.selected === false ) {
+ options.selected = -1;
+ }
+ },
+
+ _eventHandler: function() {
+ this._superApply( arguments );
+ this.options.selected = this.options.active;
+ if ( this.options.selected === false ) {
+ this.options.selected = -1;
+ }
+ }
+ });
+
+ // show and select event
+ $.widget( "ui.tabs", $.ui.tabs, {
+ options: {
+ show: null,
+ select: null
+ },
+ _create: function() {
+ this._super();
+ if ( this.options.active !== false ) {
+ this._trigger( "show", null, this._ui(
+ this.active.find( ".ui-tabs-anchor" )[ 0 ],
+ this._getPanelForTab( this.active )[ 0 ] ) );
+ }
+ },
+ _trigger: function( type, event, data ) {
+ var tab, panel,
+ ret = this._superApply( arguments );
+
+ if ( !ret ) {
+ return false;
+ }
+
+ if ( type === "beforeActivate" ) {
+ tab = data.newTab.length ? data.newTab : data.oldTab;
+ panel = data.newPanel.length ? data.newPanel : data.oldPanel;
+ ret = this._super( "select", event, {
+ tab: tab.find( ".ui-tabs-anchor" )[ 0],
+ panel: panel[ 0 ],
+ index: tab.closest( "li" ).index()
+ });
+ } else if ( type === "activate" && data.newTab.length ) {
+ ret = this._super( "show", event, {
+ tab: data.newTab.find( ".ui-tabs-anchor" )[ 0 ],
+ panel: data.newPanel[ 0 ],
+ index: data.newTab.closest( "li" ).index()
+ });
+ }
+ return ret;
+ }
+ });
+
+ // select method
+ $.widget( "ui.tabs", $.ui.tabs, {
+ select: function( index ) {
+ index = this._getIndex( index );
+ if ( index === -1 ) {
+ if ( this.options.collapsible && this.options.selected !== -1 ) {
+ index = this.options.selected;
+ } else {
+ return;
+ }
+ }
+ this.anchors.eq( index ).trigger( this.options.event + this.eventNamespace );
+ }
+ });
+
+ // cookie option
+ (function() {
+
+ var listId = 0;
+
+ $.widget( "ui.tabs", $.ui.tabs, {
+ options: {
+ cookie: null // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
+ },
+ _create: function() {
+ var options = this.options,
+ active;
+ if ( options.active == null && options.cookie ) {
+ active = parseInt( this._cookie(), 10 );
+ if ( active === -1 ) {
+ active = false;
+ }
+ options.active = active;
+ }
+ this._super();
+ },
+ _cookie: function( active ) {
+ var cookie = [ this.cookie ||
+ ( this.cookie = this.options.cookie.name || "ui-tabs-" + (++listId) ) ];
+ if ( arguments.length ) {
+ cookie.push( active === false ? -1 : active );
+ cookie.push( this.options.cookie );
+ }
+ return $.cookie.apply( null, cookie );
+ },
+ _refresh: function() {
+ this._super();
+ if ( this.options.cookie ) {
+ this._cookie( this.options.active, this.options.cookie );
+ }
+ },
+ _eventHandler: function() {
+ this._superApply( arguments );
+ if ( this.options.cookie ) {
+ this._cookie( this.options.active, this.options.cookie );
+ }
+ },
+ _destroy: function() {
+ this._super();
+ if ( this.options.cookie ) {
+ this._cookie( null, this.options.cookie );
+ }
+ }
+ });
+
+ })();
+
+ // load event
+ $.widget( "ui.tabs", $.ui.tabs, {
+ _trigger: function( type, event, data ) {
+ var _data = $.extend( {}, data );
+ if ( type === "load" ) {
+ _data.panel = _data.panel[ 0 ];
+ _data.tab = _data.tab.find( ".ui-tabs-anchor" )[ 0 ];
+ }
+ return this._super( type, event, _data );
+ }
+ });
+
+ // fx option
+ // The new animation options (show, hide) conflict with the old show callback.
+ // The old fx option wins over show/hide anyway (always favor back-compat).
+ // If a user wants to use the new animation API, they must give up the old API.
+ $.widget( "ui.tabs", $.ui.tabs, {
+ options: {
+ fx: null // e.g. { height: "toggle", opacity: "toggle", duration: 200 }
+ },
+
+ _getFx: function() {
+ var hide, show,
+ fx = this.options.fx;
+
+ if ( fx ) {
+ if ( $.isArray( fx ) ) {
+ hide = fx[ 0 ];
+ show = fx[ 1 ];
+ } else {
+ hide = show = fx;
+ }
+ }
+
+ return fx ? { show: show, hide: hide } : null;
+ },
+
+ _toggle: function( event, eventData ) {
+ var that = this,
+ toShow = eventData.newPanel,
+ toHide = eventData.oldPanel,
+ fx = this._getFx();
+
+ if ( !fx ) {
+ return this._super( event, eventData );
+ }
+
+ that.running = true;
+
+ function complete() {
+ that.running = false;
+ that._trigger( "activate", event, eventData );
+ }
+
+ function show() {
+ eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );
+
+ if ( toShow.length && fx.show ) {
+ toShow
+ .animate( fx.show, fx.show.duration, function() {
+ complete();
+ });
+ } else {
+ toShow.show();
+ complete();
+ }
+ }
+
+ // start out by hiding, then showing, then completing
+ if ( toHide.length && fx.hide ) {
+ toHide.animate( fx.hide, fx.hide.duration, function() {
+ eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
+ show();
+ });
+ } else {
+ eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
+ toHide.hide();
+ show();
+ }
+ }
+ });
+}
+
+})( jQuery );
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.tooltip.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.tooltip.js
new file mode 100644
index 00000000..2b50b443
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.tooltip.js
@@ -0,0 +1,398 @@
+/*!
+ * jQuery UI Tooltip 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/tooltip/
+ *
+ * Depends:
+ * jquery.ui.core.js
+ * jquery.ui.widget.js
+ * jquery.ui.position.js
+ */
+(function( $ ) {
+
+var increments = 0;
+
+function addDescribedBy( elem, id ) {
+ var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
+ describedby.push( id );
+ elem
+ .data( "ui-tooltip-id", id )
+ .attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
+}
+
+function removeDescribedBy( elem ) {
+ var id = elem.data( "ui-tooltip-id" ),
+ describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
+ index = $.inArray( id, describedby );
+ if ( index !== -1 ) {
+ describedby.splice( index, 1 );
+ }
+
+ elem.removeData( "ui-tooltip-id" );
+ describedby = $.trim( describedby.join( " " ) );
+ if ( describedby ) {
+ elem.attr( "aria-describedby", describedby );
+ } else {
+ elem.removeAttr( "aria-describedby" );
+ }
+}
+
+$.widget( "ui.tooltip", {
+ version: "1.9.2",
+ options: {
+ content: function() {
+ return $( this ).attr( "title" );
+ },
+ hide: true,
+ // Disabled elements have inconsistent behavior across browsers (#8661)
+ items: "[title]:not([disabled])",
+ position: {
+ my: "left top+15",
+ at: "left bottom",
+ collision: "flipfit flip"
+ },
+ show: true,
+ tooltipClass: null,
+ track: false,
+
+ // callbacks
+ close: null,
+ open: null
+ },
+
+ _create: function() {
+ this._on({
+ mouseover: "open",
+ focusin: "open"
+ });
+
+ // IDs of generated tooltips, needed for destroy
+ this.tooltips = {};
+ // IDs of parent tooltips where we removed the title attribute
+ this.parents = {};
+
+ if ( this.options.disabled ) {
+ this._disable();
+ }
+ },
+
+ _setOption: function( key, value ) {
+ var that = this;
+
+ if ( key === "disabled" ) {
+ this[ value ? "_disable" : "_enable" ]();
+ this.options[ key ] = value;
+ // disable element style changes
+ return;
+ }
+
+ this._super( key, value );
+
+ if ( key === "content" ) {
+ $.each( this.tooltips, function( id, element ) {
+ that._updateContent( element );
+ });
+ }
+ },
+
+ _disable: function() {
+ var that = this;
+
+ // close open tooltips
+ $.each( this.tooltips, function( id, element ) {
+ var event = $.Event( "blur" );
+ event.target = event.currentTarget = element[0];
+ that.close( event, true );
+ });
+
+ // remove title attributes to prevent native tooltips
+ this.element.find( this.options.items ).andSelf().each(function() {
+ var element = $( this );
+ if ( element.is( "[title]" ) ) {
+ element
+ .data( "ui-tooltip-title", element.attr( "title" ) )
+ .attr( "title", "" );
+ }
+ });
+ },
+
+ _enable: function() {
+ // restore title attributes
+ this.element.find( this.options.items ).andSelf().each(function() {
+ var element = $( this );
+ if ( element.data( "ui-tooltip-title" ) ) {
+ element.attr( "title", element.data( "ui-tooltip-title" ) );
+ }
+ });
+ },
+
+ open: function( event ) {
+ var that = this,
+ target = $( event ? event.target : this.element )
+ // we need closest here due to mouseover bubbling,
+ // but always pointing at the same event target
+ .closest( this.options.items );
+
+ // No element to show a tooltip for or the tooltip is already open
+ if ( !target.length || target.data( "ui-tooltip-id" ) ) {
+ return;
+ }
+
+ if ( target.attr( "title" ) ) {
+ target.data( "ui-tooltip-title", target.attr( "title" ) );
+ }
+
+ target.data( "ui-tooltip-open", true );
+
+ // kill parent tooltips, custom or native, for hover
+ if ( event && event.type === "mouseover" ) {
+ target.parents().each(function() {
+ var parent = $( this ),
+ blurEvent;
+ if ( parent.data( "ui-tooltip-open" ) ) {
+ blurEvent = $.Event( "blur" );
+ blurEvent.target = blurEvent.currentTarget = this;
+ that.close( blurEvent, true );
+ }
+ if ( parent.attr( "title" ) ) {
+ parent.uniqueId();
+ that.parents[ this.id ] = {
+ element: this,
+ title: parent.attr( "title" )
+ };
+ parent.attr( "title", "" );
+ }
+ });
+ }
+
+ this._updateContent( target, event );
+ },
+
+ _updateContent: function( target, event ) {
+ var content,
+ contentOption = this.options.content,
+ that = this,
+ eventType = event ? event.type : null;
+
+ if ( typeof contentOption === "string" ) {
+ return this._open( event, target, contentOption );
+ }
+
+ content = contentOption.call( target[0], function( response ) {
+ // ignore async response if tooltip was closed already
+ if ( !target.data( "ui-tooltip-open" ) ) {
+ return;
+ }
+ // IE may instantly serve a cached response for ajax requests
+ // delay this call to _open so the other call to _open runs first
+ that._delay(function() {
+ // jQuery creates a special event for focusin when it doesn't
+ // exist natively. To improve performance, the native event
+ // object is reused and the type is changed. Therefore, we can't
+ // rely on the type being correct after the event finished
+ // bubbling, so we set it back to the previous value. (#8740)
+ if ( event ) {
+ event.type = eventType;
+ }
+ this._open( event, target, response );
+ });
+ });
+ if ( content ) {
+ this._open( event, target, content );
+ }
+ },
+
+ _open: function( event, target, content ) {
+ var tooltip, events, delayedShow,
+ positionOption = $.extend( {}, this.options.position );
+
+ if ( !content ) {
+ return;
+ }
+
+ // Content can be updated multiple times. If the tooltip already
+ // exists, then just update the content and bail.
+ tooltip = this._find( target );
+ if ( tooltip.length ) {
+ tooltip.find( ".ui-tooltip-content" ).html( content );
+ return;
+ }
+
+ // if we have a title, clear it to prevent the native tooltip
+ // we have to check first to avoid defining a title if none exists
+ // (we don't want to cause an element to start matching [title])
+ //
+ // We use removeAttr only for key events, to allow IE to export the correct
+ // accessible attributes. For mouse events, set to empty string to avoid
+ // native tooltip showing up (happens only when removing inside mouseover).
+ if ( target.is( "[title]" ) ) {
+ if ( event && event.type === "mouseover" ) {
+ target.attr( "title", "" );
+ } else {
+ target.removeAttr( "title" );
+ }
+ }
+
+ tooltip = this._tooltip( target );
+ addDescribedBy( target, tooltip.attr( "id" ) );
+ tooltip.find( ".ui-tooltip-content" ).html( content );
+
+ function position( event ) {
+ positionOption.of = event;
+ if ( tooltip.is( ":hidden" ) ) {
+ return;
+ }
+ tooltip.position( positionOption );
+ }
+ if ( this.options.track && event && /^mouse/.test( event.type ) ) {
+ this._on( this.document, {
+ mousemove: position
+ });
+ // trigger once to override element-relative positioning
+ position( event );
+ } else {
+ tooltip.position( $.extend({
+ of: target
+ }, this.options.position ) );
+ }
+
+ tooltip.hide();
+
+ this._show( tooltip, this.options.show );
+ // Handle tracking tooltips that are shown with a delay (#8644). As soon
+ // as the tooltip is visible, position the tooltip using the most recent
+ // event.
+ if ( this.options.show && this.options.show.delay ) {
+ delayedShow = setInterval(function() {
+ if ( tooltip.is( ":visible" ) ) {
+ position( positionOption.of );
+ clearInterval( delayedShow );
+ }
+ }, $.fx.interval );
+ }
+
+ this._trigger( "open", event, { tooltip: tooltip } );
+
+ events = {
+ keyup: function( event ) {
+ if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
+ var fakeEvent = $.Event(event);
+ fakeEvent.currentTarget = target[0];
+ this.close( fakeEvent, true );
+ }
+ },
+ remove: function() {
+ this._removeTooltip( tooltip );
+ }
+ };
+ if ( !event || event.type === "mouseover" ) {
+ events.mouseleave = "close";
+ }
+ if ( !event || event.type === "focusin" ) {
+ events.focusout = "close";
+ }
+ this._on( true, target, events );
+ },
+
+ close: function( event ) {
+ var that = this,
+ target = $( event ? event.currentTarget : this.element ),
+ tooltip = this._find( target );
+
+ // disabling closes the tooltip, so we need to track when we're closing
+ // to avoid an infinite loop in case the tooltip becomes disabled on close
+ if ( this.closing ) {
+ return;
+ }
+
+ // only set title if we had one before (see comment in _open())
+ if ( target.data( "ui-tooltip-title" ) ) {
+ target.attr( "title", target.data( "ui-tooltip-title" ) );
+ }
+
+ removeDescribedBy( target );
+
+ tooltip.stop( true );
+ this._hide( tooltip, this.options.hide, function() {
+ that._removeTooltip( $( this ) );
+ });
+
+ target.removeData( "ui-tooltip-open" );
+ this._off( target, "mouseleave focusout keyup" );
+ // Remove 'remove' binding only on delegated targets
+ if ( target[0] !== this.element[0] ) {
+ this._off( target, "remove" );
+ }
+ this._off( this.document, "mousemove" );
+
+ if ( event && event.type === "mouseleave" ) {
+ $.each( this.parents, function( id, parent ) {
+ $( parent.element ).attr( "title", parent.title );
+ delete that.parents[ id ];
+ });
+ }
+
+ this.closing = true;
+ this._trigger( "close", event, { tooltip: tooltip } );
+ this.closing = false;
+ },
+
+ _tooltip: function( element ) {
+ var id = "ui-tooltip-" + increments++,
+ tooltip = $( "<div>" )
+ .attr({
+ id: id,
+ role: "tooltip"
+ })
+ .addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
+ ( this.options.tooltipClass || "" ) );
+ $( "<div>" )
+ .addClass( "ui-tooltip-content" )
+ .appendTo( tooltip );
+ tooltip.appendTo( this.document[0].body );
+ if ( $.fn.bgiframe ) {
+ tooltip.bgiframe();
+ }
+ this.tooltips[ id ] = element;
+ return tooltip;
+ },
+
+ _find: function( target ) {
+ var id = target.data( "ui-tooltip-id" );
+ return id ? $( "#" + id ) : $();
+ },
+
+ _removeTooltip: function( tooltip ) {
+ tooltip.remove();
+ delete this.tooltips[ tooltip.attr( "id" ) ];
+ },
+
+ _destroy: function() {
+ var that = this;
+
+ // close open tooltips
+ $.each( this.tooltips, function( id, element ) {
+ // Delegate to close method to handle common cleanup
+ var event = $.Event( "blur" );
+ event.target = event.currentTarget = element[0];
+ that.close( event, true );
+
+ // Remove immediately; destroying an open tooltip doesn't use the
+ // hide animation
+ $( "#" + id ).remove();
+
+ // Restore the title
+ if ( element.data( "ui-tooltip-title" ) ) {
+ element.attr( "title", element.data( "ui-tooltip-title" ) );
+ element.removeData( "ui-tooltip-title" );
+ }
+ });
+ }
+});
+
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery.ui/jquery.ui.widget.js b/www/wiki/resources/lib/jquery.ui/jquery.ui.widget.js
new file mode 100644
index 00000000..4d84afcf
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/jquery.ui.widget.js
@@ -0,0 +1,528 @@
+/*!
+ * jQuery UI Widget 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://api.jqueryui.com/jQuery.widget/
+ */
+(function( $, undefined ) {
+
+var uuid = 0,
+ slice = Array.prototype.slice,
+ _cleanData = $.cleanData;
+$.cleanData = function( elems ) {
+ for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
+ try {
+ $( elem ).triggerHandler( "remove" );
+ // http://bugs.jquery.com/ticket/8235
+ } catch( e ) {}
+ }
+ _cleanData( elems );
+};
+
+$.widget = function( name, base, prototype ) {
+ var fullName, existingConstructor, constructor, basePrototype,
+ namespace = name.split( "." )[ 0 ];
+
+ name = name.split( "." )[ 1 ];
+ fullName = namespace + "-" + name;
+
+ if ( !prototype ) {
+ prototype = base;
+ base = $.Widget;
+ }
+
+ // create selector for plugin
+ $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
+ return !!$.data( elem, fullName );
+ };
+
+ $[ namespace ] = $[ namespace ] || {};
+ existingConstructor = $[ namespace ][ name ];
+ constructor = $[ namespace ][ name ] = function( options, element ) {
+ // allow instantiation without "new" keyword
+ if ( !this._createWidget ) {
+ return new constructor( options, element );
+ }
+
+ // allow instantiation without initializing for simple inheritance
+ // must use "new" keyword (the code above always passes args)
+ if ( arguments.length ) {
+ this._createWidget( options, element );
+ }
+ };
+ // extend with the existing constructor to carry over any static properties
+ $.extend( constructor, existingConstructor, {
+ version: prototype.version,
+ // copy the object used to create the prototype in case we need to
+ // redefine the widget later
+ _proto: $.extend( {}, prototype ),
+ // track widgets that inherit from this widget in case this widget is
+ // redefined after a widget inherits from it
+ _childConstructors: []
+ });
+
+ basePrototype = new base();
+ // we need to make the options hash a property directly on the new instance
+ // otherwise we'll modify the options hash on the prototype that we're
+ // inheriting from
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
+ $.each( prototype, function( prop, value ) {
+ if ( $.isFunction( value ) ) {
+ prototype[ prop ] = (function() {
+ var _super = function() {
+ return base.prototype[ prop ].apply( this, arguments );
+ },
+ _superApply = function( args ) {
+ return base.prototype[ prop ].apply( this, args );
+ };
+ return function() {
+ var __super = this._super,
+ __superApply = this._superApply,
+ returnValue;
+
+ this._super = _super;
+ this._superApply = _superApply;
+
+ returnValue = value.apply( this, arguments );
+
+ this._super = __super;
+ this._superApply = __superApply;
+
+ return returnValue;
+ };
+ })();
+ }
+ });
+ constructor.prototype = $.widget.extend( basePrototype, {
+ // TODO: remove support for widgetEventPrefix
+ // always use the name + a colon as the prefix, e.g., draggable:start
+ // don't prefix for widgets that aren't DOM-based
+ widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
+ }, prototype, {
+ constructor: constructor,
+ namespace: namespace,
+ widgetName: name,
+ // TODO remove widgetBaseClass, see #8155
+ widgetBaseClass: fullName,
+ widgetFullName: fullName
+ });
+
+ // If this widget is being redefined then we need to find all widgets that
+ // are inheriting from it and redefine all of them so that they inherit from
+ // the new version of this widget. We're essentially trying to replace one
+ // level in the prototype chain.
+ if ( existingConstructor ) {
+ $.each( existingConstructor._childConstructors, function( i, child ) {
+ var childPrototype = child.prototype;
+
+ // redefine the child widget using the same prototype that was
+ // originally used, but inherit from the new version of the base
+ $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
+ });
+ // remove the list of existing child constructors from the old constructor
+ // so the old child constructors can be garbage collected
+ delete existingConstructor._childConstructors;
+ } else {
+ base._childConstructors.push( constructor );
+ }
+
+ $.widget.bridge( name, constructor );
+};
+
+$.widget.extend = function( target ) {
+ var input = slice.call( arguments, 1 ),
+ inputIndex = 0,
+ inputLength = input.length,
+ key,
+ value;
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
+ for ( key in input[ inputIndex ] ) {
+ value = input[ inputIndex ][ key ];
+ if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
+ // Clone objects
+ if ( $.isPlainObject( value ) ) {
+ target[ key ] = $.isPlainObject( target[ key ] ) ?
+ $.widget.extend( {}, target[ key ], value ) :
+ // Don't extend strings, arrays, etc. with objects
+ $.widget.extend( {}, value );
+ // Copy everything else by reference
+ } else {
+ target[ key ] = value;
+ }
+ }
+ }
+ }
+ return target;
+};
+
+$.widget.bridge = function( name, object ) {
+ var fullName = object.prototype.widgetFullName || name;
+ $.fn[ name ] = function( options ) {
+ var isMethodCall = typeof options === "string",
+ args = slice.call( arguments, 1 ),
+ returnValue = this;
+
+ // allow multiple hashes to be passed on init
+ options = !isMethodCall && args.length ?
+ $.widget.extend.apply( null, [ options ].concat(args) ) :
+ options;
+
+ if ( isMethodCall ) {
+ this.each(function() {
+ var methodValue,
+ instance = $.data( this, fullName );
+ if ( !instance ) {
+ return $.error( "cannot call methods on " + name + " prior to initialization; " +
+ "attempted to call method '" + options + "'" );
+ }
+ if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
+ return $.error( "no such method '" + options + "' for " + name + " widget instance" );
+ }
+ methodValue = instance[ options ].apply( instance, args );
+ if ( methodValue !== instance && methodValue !== undefined ) {
+ returnValue = methodValue && methodValue.jquery ?
+ returnValue.pushStack( methodValue.get() ) :
+ methodValue;
+ return false;
+ }
+ });
+ } else {
+ this.each(function() {
+ var instance = $.data( this, fullName );
+ if ( instance ) {
+ instance.option( options || {} )._init();
+ } else {
+ $.data( this, fullName, new object( options, this ) );
+ }
+ });
+ }
+
+ return returnValue;
+ };
+};
+
+$.Widget = function( /* options, element */ ) {};
+$.Widget._childConstructors = [];
+
+$.Widget.prototype = {
+ widgetName: "widget",
+ widgetEventPrefix: "",
+ defaultElement: "<div>",
+ options: {
+ disabled: false,
+
+ // callbacks
+ create: null
+ },
+ _createWidget: function( options, element ) {
+ element = $( element || this.defaultElement || this )[ 0 ];
+ this.element = $( element );
+ this.uuid = uuid++;
+ this.eventNamespace = "." + this.widgetName + this.uuid;
+ this.options = $.widget.extend( {},
+ this.options,
+ this._getCreateOptions(),
+ options );
+
+ this.bindings = $();
+ this.hoverable = $();
+ this.focusable = $();
+
+ if ( element !== this ) {
+ // 1.9 BC for #7810
+ // TODO remove dual storage
+ $.data( element, this.widgetName, this );
+ $.data( element, this.widgetFullName, this );
+ this._on( true, this.element, {
+ remove: function( event ) {
+ if ( event.target === element ) {
+ this.destroy();
+ }
+ }
+ });
+ this.document = $( element.style ?
+ // element within the document
+ element.ownerDocument :
+ // element is window or document
+ element.document || element );
+ this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
+ }
+
+ this._create();
+ this._trigger( "create", null, this._getCreateEventData() );
+ this._init();
+ },
+ _getCreateOptions: $.noop,
+ _getCreateEventData: $.noop,
+ _create: $.noop,
+ _init: $.noop,
+
+ destroy: function() {
+ this._destroy();
+ // we can probably remove the unbind calls in 2.0
+ // all event bindings should go through this._on()
+ this.element
+ .unbind( this.eventNamespace )
+ // 1.9 BC for #7810
+ // TODO remove dual storage
+ .removeData( this.widgetName )
+ .removeData( this.widgetFullName )
+ // support: jquery <1.6.3
+ // http://bugs.jquery.com/ticket/9413
+ .removeData( $.camelCase( this.widgetFullName ) );
+ this.widget()
+ .unbind( this.eventNamespace )
+ .removeAttr( "aria-disabled" )
+ .removeClass(
+ this.widgetFullName + "-disabled " +
+ "ui-state-disabled" );
+
+ // clean up events and states
+ this.bindings.unbind( this.eventNamespace );
+ this.hoverable.removeClass( "ui-state-hover" );
+ this.focusable.removeClass( "ui-state-focus" );
+ },
+ _destroy: $.noop,
+
+ widget: function() {
+ return this.element;
+ },
+
+ option: function( key, value ) {
+ var options = key,
+ parts,
+ curOption,
+ i;
+
+ if ( arguments.length === 0 ) {
+ // don't return a reference to the internal hash
+ return $.widget.extend( {}, this.options );
+ }
+
+ if ( typeof key === "string" ) {
+ // handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
+ options = {};
+ parts = key.split( "." );
+ key = parts.shift();
+ if ( parts.length ) {
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
+ for ( i = 0; i < parts.length - 1; i++ ) {
+ curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
+ curOption = curOption[ parts[ i ] ];
+ }
+ key = parts.pop();
+ if ( value === undefined ) {
+ return curOption[ key ] === undefined ? null : curOption[ key ];
+ }
+ curOption[ key ] = value;
+ } else {
+ if ( value === undefined ) {
+ return this.options[ key ] === undefined ? null : this.options[ key ];
+ }
+ options[ key ] = value;
+ }
+ }
+
+ this._setOptions( options );
+
+ return this;
+ },
+ _setOptions: function( options ) {
+ var key;
+
+ for ( key in options ) {
+ this._setOption( key, options[ key ] );
+ }
+
+ return this;
+ },
+ _setOption: function( key, value ) {
+ this.options[ key ] = value;
+
+ if ( key === "disabled" ) {
+ this.widget()
+ .toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
+ .attr( "aria-disabled", value );
+ this.hoverable.removeClass( "ui-state-hover" );
+ this.focusable.removeClass( "ui-state-focus" );
+ }
+
+ return this;
+ },
+
+ enable: function() {
+ return this._setOption( "disabled", false );
+ },
+ disable: function() {
+ return this._setOption( "disabled", true );
+ },
+
+ _on: function( suppressDisabledCheck, element, handlers ) {
+ var delegateElement,
+ instance = this;
+
+ // no suppressDisabledCheck flag, shuffle arguments
+ if ( typeof suppressDisabledCheck !== "boolean" ) {
+ handlers = element;
+ element = suppressDisabledCheck;
+ suppressDisabledCheck = false;
+ }
+
+ // no element argument, shuffle and use this.element
+ if ( !handlers ) {
+ handlers = element;
+ element = this.element;
+ delegateElement = this.widget();
+ } else {
+ // accept selectors, DOM elements
+ element = delegateElement = $( element );
+ this.bindings = this.bindings.add( element );
+ }
+
+ $.each( handlers, function( event, handler ) {
+ function handlerProxy() {
+ // allow widgets to customize the disabled handling
+ // - disabled as an array instead of boolean
+ // - disabled class as method for disabling individual parts
+ if ( !suppressDisabledCheck &&
+ ( instance.options.disabled === true ||
+ $( this ).hasClass( "ui-state-disabled" ) ) ) {
+ return;
+ }
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
+ .apply( instance, arguments );
+ }
+
+ // copy the guid so direct unbinding works
+ if ( typeof handler !== "string" ) {
+ handlerProxy.guid = handler.guid =
+ handler.guid || handlerProxy.guid || $.guid++;
+ }
+
+ var match = event.match( /^(\w+)\s*(.*)$/ ),
+ eventName = match[1] + instance.eventNamespace,
+ selector = match[2];
+ if ( selector ) {
+ delegateElement.delegate( selector, eventName, handlerProxy );
+ } else {
+ element.bind( eventName, handlerProxy );
+ }
+ });
+ },
+
+ _off: function( element, eventName ) {
+ eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
+ element.unbind( eventName ).undelegate( eventName );
+ },
+
+ _delay: function( handler, delay ) {
+ function handlerProxy() {
+ return ( typeof handler === "string" ? instance[ handler ] : handler )
+ .apply( instance, arguments );
+ }
+ var instance = this;
+ return setTimeout( handlerProxy, delay || 0 );
+ },
+
+ _hoverable: function( element ) {
+ this.hoverable = this.hoverable.add( element );
+ this._on( element, {
+ mouseenter: function( event ) {
+ $( event.currentTarget ).addClass( "ui-state-hover" );
+ },
+ mouseleave: function( event ) {
+ $( event.currentTarget ).removeClass( "ui-state-hover" );
+ }
+ });
+ },
+
+ _focusable: function( element ) {
+ this.focusable = this.focusable.add( element );
+ this._on( element, {
+ focusin: function( event ) {
+ $( event.currentTarget ).addClass( "ui-state-focus" );
+ },
+ focusout: function( event ) {
+ $( event.currentTarget ).removeClass( "ui-state-focus" );
+ }
+ });
+ },
+
+ _trigger: function( type, event, data ) {
+ var prop, orig,
+ callback = this.options[ type ];
+
+ data = data || {};
+ event = $.Event( event );
+ event.type = ( type === this.widgetEventPrefix ?
+ type :
+ this.widgetEventPrefix + type ).toLowerCase();
+ // the original event may come from any element
+ // so we need to reset the target on the new event
+ event.target = this.element[ 0 ];
+
+ // copy original event properties over to the new event
+ orig = event.originalEvent;
+ if ( orig ) {
+ for ( prop in orig ) {
+ if ( !( prop in event ) ) {
+ event[ prop ] = orig[ prop ];
+ }
+ }
+ }
+
+ this.element.trigger( event, data );
+ return !( $.isFunction( callback ) &&
+ callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
+ event.isDefaultPrevented() );
+ }
+};
+
+$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
+ $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
+ if ( typeof options === "string" ) {
+ options = { effect: options };
+ }
+ var hasOptions,
+ effectName = !options ?
+ method :
+ options === true || typeof options === "number" ?
+ defaultEffect :
+ options.effect || defaultEffect;
+ options = options || {};
+ if ( typeof options === "number" ) {
+ options = { duration: options };
+ }
+ hasOptions = !$.isEmptyObject( options );
+ options.complete = callback;
+ if ( options.delay ) {
+ element.delay( options.delay );
+ }
+ if ( hasOptions && $.effects && ( $.effects.effect[ effectName ] || $.uiBackCompat !== false && $.effects[ effectName ] ) ) {
+ element[ method ]( options );
+ } else if ( effectName !== method && element[ effectName ] ) {
+ element[ effectName ]( options.duration, options.easing, callback );
+ } else {
+ element.queue(function( next ) {
+ $( this )[ method ]();
+ if ( callback ) {
+ callback.call( element[ 0 ] );
+ }
+ next();
+ });
+ }
+ };
+});
+
+// DEPRECATED
+if ( $.uiBackCompat !== false ) {
+ $.Widget.prototype._getCreateOptions = function() {
+ return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
+ };
+}
+
+})( jQuery );
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/PATCHES b/www/wiki/resources/lib/jquery.ui/themes/smoothness/PATCHES
new file mode 100644
index 00000000..53fbe1fc
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/PATCHES
@@ -0,0 +1,3 @@
+jquery.ui.theme.css
+* Removed ".ui-widget-content a { color: #222222; }" and
+ ".ui-widget-header a { color: #222222; }" due to bug T85857.
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
new file mode 100644
index 00000000..67b1fdde
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_flat_75_ffffff_40x100.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
new file mode 100644
index 00000000..efa0b15a
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_flat_75_ffffff_40x100.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
new file mode 100644
index 00000000..6467bba1
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
new file mode 100644
index 00000000..ca988a38
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_65_ffffff_1x400.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png
new file mode 100644
index 00000000..6e208033
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_75_dadada_1x400.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
new file mode 100644
index 00000000..9a11b43e
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
new file mode 100644
index 00000000..01048f8c
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
new file mode 100644
index 00000000..35976e81
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_222222_256x240.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_222222_256x240.png
new file mode 100644
index 00000000..c1cb1170
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_222222_256x240.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_2e83ff_256x240.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_2e83ff_256x240.png
new file mode 100644
index 00000000..84b601bf
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_2e83ff_256x240.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_454545_256x240.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_454545_256x240.png
new file mode 100644
index 00000000..b6db1acd
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_454545_256x240.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_888888_256x240.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_888888_256x240.png
new file mode 100644
index 00000000..feea0e20
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_888888_256x240.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.png b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.png
new file mode 100644
index 00000000..ed5b6b09
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/images/ui-icons_cd0a0a_256x240.png
Binary files differ
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.accordion.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.accordion.css
new file mode 100644
index 00000000..d429fd20
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.accordion.css
@@ -0,0 +1,16 @@
+/*!
+ * jQuery UI Accordion 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Accordion#theming
+ */
+.ui-accordion .ui-accordion-header { display: block; cursor: pointer; position: relative; margin-top: 2px; padding: .5em .5em .5em .7em; zoom: 1; }
+.ui-accordion .ui-accordion-icons { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-noicons { padding-left: .7em; }
+.ui-accordion .ui-accordion-icons .ui-accordion-icons { padding-left: 2.2em; }
+.ui-accordion .ui-accordion-header .ui-accordion-header-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
+.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; overflow: auto; zoom: 1; }
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.autocomplete.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.autocomplete.css
new file mode 100644
index 00000000..4ef3497a
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.autocomplete.css
@@ -0,0 +1,19 @@
+/*!
+ * jQuery UI Autocomplete 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Autocomplete#theming
+ */
+.ui-autocomplete {
+ position: absolute;
+ top: 0;
+ left: 0;
+ cursor: default;
+}
+
+/* workarounds */
+* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.button.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.button.css
new file mode 100644
index 00000000..44a7d9bb
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.button.css
@@ -0,0 +1,40 @@
+/*!
+ * jQuery UI Button 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Button#theming
+ */
+.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
+.ui-button, .ui-button:link, .ui-button:visited, .ui-button:hover, .ui-button:active { text-decoration: none; }
+.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
+button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
+.ui-button-icons-only { width: 3.4em; }
+button.ui-button-icons-only { width: 3.7em; }
+
+/*button text element */
+.ui-button .ui-button-text { display: block; line-height: 1.4; }
+.ui-button-text-only .ui-button-text { padding: .4em 1em; }
+.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
+.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
+.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
+.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
+/* no icon support for input elements, provide padding by default */
+input.ui-button { padding: .4em 1em; }
+
+/*button icon element(s) */
+.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
+.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
+.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
+.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
+
+/*button sets*/
+.ui-buttonset { margin-right: 7px; }
+.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
+
+/* workarounds */
+button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.core.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.core.css
new file mode 100644
index 00000000..d4f7db3b
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.core.css
@@ -0,0 +1,39 @@
+/*!
+ * jQuery UI CSS Framework 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ */
+
+/* Layout helpers
+----------------------------------*/
+.ui-helper-hidden { display: none; }
+.ui-helper-hidden-accessible { border: 0; clip: rect(0 0 0 0); height: 1px; margin: -1px; overflow: hidden; padding: 0; position: absolute; width: 1px; }
+.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
+.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; border-collapse: collapse; }
+.ui-helper-clearfix:after { clear: both; }
+.ui-helper-clearfix { zoom: 1; }
+.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
+
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-disabled { cursor: default !important; }
+
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Overlays */
+.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.datepicker.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.datepicker.css
new file mode 100644
index 00000000..f56bb75f
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.datepicker.css
@@ -0,0 +1,67 @@
+/*!
+ * jQuery UI Datepicker 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Datepicker#theming
+ */
+.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
+.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
+.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
+.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
+.ui-datepicker .ui-datepicker-prev { left:2px; }
+.ui-datepicker .ui-datepicker-next { right:2px; }
+.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
+.ui-datepicker .ui-datepicker-next-hover { right:1px; }
+.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
+.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
+.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
+.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
+.ui-datepicker select.ui-datepicker-month,
+.ui-datepicker select.ui-datepicker-year { width: 49%;}
+.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
+.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
+.ui-datepicker td { border: 0; padding: 1px; }
+.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
+.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
+.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
+.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
+
+/* with multiple calendars */
+.ui-datepicker.ui-datepicker-multi { width:auto; }
+.ui-datepicker-multi .ui-datepicker-group { float:left; }
+.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
+.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
+.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
+.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
+.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
+.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
+.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
+
+/* RTL support */
+.ui-datepicker-rtl { direction: rtl; }
+.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
+.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
+.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group { float:right; }
+.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
+
+/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
+.ui-datepicker-cover {
+ position: absolute; /*must have*/
+ z-index: -1; /*must have*/
+ filter: mask(); /*must have*/
+ top: -4px; /*must have*/
+ left: -4px; /*must have*/
+ width: 200px; /*must have*/
+ height: 200px; /*must have*/
+} \ No newline at end of file
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.dialog.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.dialog.css
new file mode 100644
index 00000000..1313a5e0
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.dialog.css
@@ -0,0 +1,22 @@
+/*!
+ * jQuery UI Dialog 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Dialog#theming
+ */
+.ui-dialog { position: absolute; top: 0; left: 0; padding: .2em; width: 300px; overflow: hidden; }
+.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
+.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
+.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
+.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
+.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
+.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
+.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
+.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
+.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
+.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
+.ui-draggable .ui-dialog-titlebar { cursor: move; }
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.menu.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.menu.css
new file mode 100644
index 00000000..83fd84e4
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.menu.css
@@ -0,0 +1,30 @@
+/*!
+ * jQuery UI Menu 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Menu#theming
+ */
+.ui-menu { list-style:none; padding: 2px; margin: 0; display:block; outline: none; }
+.ui-menu .ui-menu { margin-top: -3px; position: absolute; }
+.ui-menu .ui-menu-item { margin: 0; padding: 0; zoom: 1; width: 100%; }
+.ui-menu .ui-menu-divider { margin: 5px -2px 5px -2px; height: 0; font-size: 0; line-height: 0; border-width: 1px 0 0 0; }
+.ui-menu .ui-menu-item a { text-decoration: none; display: block; padding: 2px .4em; line-height: 1.5; zoom: 1; font-weight: normal; }
+.ui-menu .ui-menu-item a.ui-state-focus,
+.ui-menu .ui-menu-item a.ui-state-active { font-weight: normal; margin: -1px; }
+
+.ui-menu .ui-state-disabled { font-weight: normal; margin: .4em 0 .2em; line-height: 1.5; }
+.ui-menu .ui-state-disabled a { cursor: default; }
+
+/* icon support */
+.ui-menu-icons { position: relative; }
+.ui-menu-icons .ui-menu-item a { position: relative; padding-left: 2em; }
+
+/* left-aligned */
+.ui-menu .ui-icon { position: absolute; top: .2em; left: .2em; }
+
+/* right-aligned */
+.ui-menu .ui-menu-icon { position: static; float: right; }
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.progressbar.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.progressbar.css
new file mode 100644
index 00000000..bd7e4033
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.progressbar.css
@@ -0,0 +1,12 @@
+/*!
+ * jQuery UI Progressbar 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Progressbar#theming
+ */
+.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
+.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; } \ No newline at end of file
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.resizable.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.resizable.css
new file mode 100644
index 00000000..2f87843c
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.resizable.css
@@ -0,0 +1,21 @@
+/*!
+ * jQuery UI Resizable 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Resizable#theming
+ */
+.ui-resizable { position: relative;}
+.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
+.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
+.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
+.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
+.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
+.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
+.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
+.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
+.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
+.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;} \ No newline at end of file
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.selectable.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.selectable.css
new file mode 100644
index 00000000..5854c41f
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.selectable.css
@@ -0,0 +1,11 @@
+/*!
+ * jQuery UI Selectable 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Selectable#theming
+ */
+.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.slider.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.slider.css
new file mode 100644
index 00000000..e5794789
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.slider.css
@@ -0,0 +1,25 @@
+/*!
+ * jQuery UI Slider 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Slider#theming
+ */
+.ui-slider { position: relative; text-align: left; }
+.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
+.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
+
+.ui-slider-horizontal { height: .8em; }
+.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
+.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
+.ui-slider-horizontal .ui-slider-range-min { left: 0; }
+.ui-slider-horizontal .ui-slider-range-max { right: 0; }
+
+.ui-slider-vertical { width: .8em; height: 100px; }
+.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
+.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
+.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
+.ui-slider-vertical .ui-slider-range-max { top: 0; } \ No newline at end of file
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.spinner.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.spinner.css
new file mode 100644
index 00000000..e89b7206
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.spinner.css
@@ -0,0 +1,23 @@
+/*!
+ * jQuery UI Spinner 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Spinner#theming
+ */
+.ui-spinner { position:relative; display: inline-block; overflow: hidden; padding: 0; vertical-align: middle; }
+.ui-spinner-input { border: none; background: none; padding: 0; margin: .2em 0; vertical-align: middle; margin-left: .4em; margin-right: 22px; }
+.ui-spinner-button { width: 16px; height: 50%; font-size: .5em; padding: 0; margin: 0; text-align: center; position: absolute; cursor: default; display: block; overflow: hidden; right: 0; }
+.ui-spinner a.ui-spinner-button { border-top: none; border-bottom: none; border-right: none; } /* more specificity required here to overide default borders */
+.ui-spinner .ui-icon { position: absolute; margin-top: -8px; top: 50%; left: 0; } /* vertical centre icon */
+.ui-spinner-up { top: 0; }
+.ui-spinner-down { bottom: 0; }
+
+/* TR overrides */
+.ui-spinner .ui-icon-triangle-1-s {
+ /* need to fix icons sprite */
+ background-position:-65px -16px;
+}
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.tabs.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.tabs.css
new file mode 100644
index 00000000..11a000ff
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.tabs.css
@@ -0,0 +1,18 @@
+/*!
+ * jQuery UI Tabs 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Tabs#theming
+ */
+.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
+.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
+.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 0; margin: 1px .2em 0 0; border-bottom: 0; padding: 0; white-space: nowrap; }
+.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-active { margin-bottom: -1px; padding-bottom: 1px; }
+.ui-tabs .ui-tabs-nav li.ui-tabs-active a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-tabs-loading a { cursor: text; }
+.ui-tabs .ui-tabs-nav li a, .ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
+.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.theme.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.theme.css
new file mode 100644
index 00000000..1d8b8a8f
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.theme.css
@@ -0,0 +1,246 @@
+/*!
+ * jQuery UI CSS Framework 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ *
+ * http://docs.jquery.com/UI/Theming/API
+ *
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana%2CArial%2Csans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=highlight_soft&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=flat&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=glass&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=glass&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=glass&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=glass&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
+ */
+
+
+/* Component containers
+----------------------------------*/
+.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
+.ui-widget .ui-widget { font-size: 1em; }
+.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
+.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url("images/ui-bg_flat_75_ffffff_40x100.png") 50% 50% repeat-x; color: #222222; }
+.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url("images/ui-bg_highlight-soft_75_cccccc_1x100.png") 50% 50% repeat-x; color: #222222; font-weight: bold; }
+
+/* Interaction states
+----------------------------------*/
+.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url("images/ui-bg_glass_75_e6e6e6_1x400.png") 50% 50% repeat-x; font-weight: normal; color: #555555; }
+.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
+.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url("images/ui-bg_glass_75_dadada_1x400.png") 50% 50% repeat-x; font-weight: normal; color: #212121; }
+.ui-state-hover a, .ui-state-hover a:hover, .ui-state-hover a:link, .ui-state-hover a:visited { color: #212121; text-decoration: none; }
+.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url("images/ui-bg_glass_65_ffffff_1x400.png") 50% 50% repeat-x; font-weight: normal; color: #212121; }
+.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
+
+/* Interaction Cues
+----------------------------------*/
+.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url("images/ui-bg_glass_55_fbf9ee_1x400.png") 50% 50% repeat-x; color: #363636; }
+.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
+.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url("images/ui-bg_glass_95_fef1ec_1x400.png") 50% 50% repeat-x; color: #cd0a0a; }
+.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
+.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
+.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
+.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
+.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
+.ui-state-disabled .ui-icon { filter:Alpha(Opacity=35); } /* For IE8 - See #6059 */
+
+/* Icons
+----------------------------------*/
+
+/* states and images */
+.ui-icon { width: 16px; height: 16px; background-image: url("images/ui-icons_222222_256x240.png"); }
+.ui-widget-content .ui-icon {background-image: url("images/ui-icons_222222_256x240.png"); }
+.ui-widget-header .ui-icon {background-image: url("images/ui-icons_222222_256x240.png"); }
+.ui-state-default .ui-icon { background-image: url("images/ui-icons_888888_256x240.png"); }
+.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url("images/ui-icons_454545_256x240.png"); }
+.ui-state-active .ui-icon {background-image: url("images/ui-icons_454545_256x240.png"); }
+.ui-state-highlight .ui-icon {background-image: url("images/ui-icons_2e83ff_256x240.png"); }
+.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url("images/ui-icons_cd0a0a_256x240.png"); }
+
+/* positioning */
+.ui-icon-carat-1-n { background-position: 0 0; }
+.ui-icon-carat-1-ne { background-position: -16px 0; }
+.ui-icon-carat-1-e { background-position: -32px 0; }
+.ui-icon-carat-1-se { background-position: -48px 0; }
+.ui-icon-carat-1-s { background-position: -64px 0; }
+.ui-icon-carat-1-sw { background-position: -80px 0; }
+.ui-icon-carat-1-w { background-position: -96px 0; }
+.ui-icon-carat-1-nw { background-position: -112px 0; }
+.ui-icon-carat-2-n-s { background-position: -128px 0; }
+.ui-icon-carat-2-e-w { background-position: -144px 0; }
+.ui-icon-triangle-1-n { background-position: 0 -16px; }
+.ui-icon-triangle-1-ne { background-position: -16px -16px; }
+.ui-icon-triangle-1-e { background-position: -32px -16px; }
+.ui-icon-triangle-1-se { background-position: -48px -16px; }
+.ui-icon-triangle-1-s { background-position: -64px -16px; }
+.ui-icon-triangle-1-sw { background-position: -80px -16px; }
+.ui-icon-triangle-1-w { background-position: -96px -16px; }
+.ui-icon-triangle-1-nw { background-position: -112px -16px; }
+.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
+.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
+.ui-icon-arrow-1-n { background-position: 0 -32px; }
+.ui-icon-arrow-1-ne { background-position: -16px -32px; }
+.ui-icon-arrow-1-e { background-position: -32px -32px; }
+.ui-icon-arrow-1-se { background-position: -48px -32px; }
+.ui-icon-arrow-1-s { background-position: -64px -32px; }
+.ui-icon-arrow-1-sw { background-position: -80px -32px; }
+.ui-icon-arrow-1-w { background-position: -96px -32px; }
+.ui-icon-arrow-1-nw { background-position: -112px -32px; }
+.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
+.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
+.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
+.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
+.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
+.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
+.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
+.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
+.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
+.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
+.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
+.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
+.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
+.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
+.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
+.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
+.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
+.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
+.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
+.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
+.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
+.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
+.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
+.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
+.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
+.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
+.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
+.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
+.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
+.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
+.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
+.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
+.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
+.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
+.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
+.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
+.ui-icon-arrow-4 { background-position: 0 -80px; }
+.ui-icon-arrow-4-diag { background-position: -16px -80px; }
+.ui-icon-extlink { background-position: -32px -80px; }
+.ui-icon-newwin { background-position: -48px -80px; }
+.ui-icon-refresh { background-position: -64px -80px; }
+.ui-icon-shuffle { background-position: -80px -80px; }
+.ui-icon-transfer-e-w { background-position: -96px -80px; }
+.ui-icon-transferthick-e-w { background-position: -112px -80px; }
+.ui-icon-folder-collapsed { background-position: 0 -96px; }
+.ui-icon-folder-open { background-position: -16px -96px; }
+.ui-icon-document { background-position: -32px -96px; }
+.ui-icon-document-b { background-position: -48px -96px; }
+.ui-icon-note { background-position: -64px -96px; }
+.ui-icon-mail-closed { background-position: -80px -96px; }
+.ui-icon-mail-open { background-position: -96px -96px; }
+.ui-icon-suitcase { background-position: -112px -96px; }
+.ui-icon-comment { background-position: -128px -96px; }
+.ui-icon-person { background-position: -144px -96px; }
+.ui-icon-print { background-position: -160px -96px; }
+.ui-icon-trash { background-position: -176px -96px; }
+.ui-icon-locked { background-position: -192px -96px; }
+.ui-icon-unlocked { background-position: -208px -96px; }
+.ui-icon-bookmark { background-position: -224px -96px; }
+.ui-icon-tag { background-position: -240px -96px; }
+.ui-icon-home { background-position: 0 -112px; }
+.ui-icon-flag { background-position: -16px -112px; }
+.ui-icon-calendar { background-position: -32px -112px; }
+.ui-icon-cart { background-position: -48px -112px; }
+.ui-icon-pencil { background-position: -64px -112px; }
+.ui-icon-clock { background-position: -80px -112px; }
+.ui-icon-disk { background-position: -96px -112px; }
+.ui-icon-calculator { background-position: -112px -112px; }
+.ui-icon-zoomin { background-position: -128px -112px; }
+.ui-icon-zoomout { background-position: -144px -112px; }
+.ui-icon-search { background-position: -160px -112px; }
+.ui-icon-wrench { background-position: -176px -112px; }
+.ui-icon-gear { background-position: -192px -112px; }
+.ui-icon-heart { background-position: -208px -112px; }
+.ui-icon-star { background-position: -224px -112px; }
+.ui-icon-link { background-position: -240px -112px; }
+.ui-icon-cancel { background-position: 0 -128px; }
+.ui-icon-plus { background-position: -16px -128px; }
+.ui-icon-plusthick { background-position: -32px -128px; }
+.ui-icon-minus { background-position: -48px -128px; }
+.ui-icon-minusthick { background-position: -64px -128px; }
+.ui-icon-close { background-position: -80px -128px; }
+.ui-icon-closethick { background-position: -96px -128px; }
+.ui-icon-key { background-position: -112px -128px; }
+.ui-icon-lightbulb { background-position: -128px -128px; }
+.ui-icon-scissors { background-position: -144px -128px; }
+.ui-icon-clipboard { background-position: -160px -128px; }
+.ui-icon-copy { background-position: -176px -128px; }
+.ui-icon-contact { background-position: -192px -128px; }
+.ui-icon-image { background-position: -208px -128px; }
+.ui-icon-video { background-position: -224px -128px; }
+.ui-icon-script { background-position: -240px -128px; }
+.ui-icon-alert { background-position: 0 -144px; }
+.ui-icon-info { background-position: -16px -144px; }
+.ui-icon-notice { background-position: -32px -144px; }
+.ui-icon-help { background-position: -48px -144px; }
+.ui-icon-check { background-position: -64px -144px; }
+.ui-icon-bullet { background-position: -80px -144px; }
+.ui-icon-radio-on { background-position: -96px -144px; }
+.ui-icon-radio-off { background-position: -112px -144px; }
+.ui-icon-pin-w { background-position: -128px -144px; }
+.ui-icon-pin-s { background-position: -144px -144px; }
+.ui-icon-play { background-position: 0 -160px; }
+.ui-icon-pause { background-position: -16px -160px; }
+.ui-icon-seek-next { background-position: -32px -160px; }
+.ui-icon-seek-prev { background-position: -48px -160px; }
+.ui-icon-seek-end { background-position: -64px -160px; }
+.ui-icon-seek-start { background-position: -80px -160px; }
+/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
+.ui-icon-seek-first { background-position: -80px -160px; }
+.ui-icon-stop { background-position: -96px -160px; }
+.ui-icon-eject { background-position: -112px -160px; }
+.ui-icon-volume-off { background-position: -128px -160px; }
+.ui-icon-volume-on { background-position: -144px -160px; }
+.ui-icon-power { background-position: 0 -176px; }
+.ui-icon-signal-diag { background-position: -16px -176px; }
+.ui-icon-signal { background-position: -32px -176px; }
+.ui-icon-battery-0 { background-position: -48px -176px; }
+.ui-icon-battery-1 { background-position: -64px -176px; }
+.ui-icon-battery-2 { background-position: -80px -176px; }
+.ui-icon-battery-3 { background-position: -96px -176px; }
+.ui-icon-circle-plus { background-position: 0 -192px; }
+.ui-icon-circle-minus { background-position: -16px -192px; }
+.ui-icon-circle-close { background-position: -32px -192px; }
+.ui-icon-circle-triangle-e { background-position: -48px -192px; }
+.ui-icon-circle-triangle-s { background-position: -64px -192px; }
+.ui-icon-circle-triangle-w { background-position: -80px -192px; }
+.ui-icon-circle-triangle-n { background-position: -96px -192px; }
+.ui-icon-circle-arrow-e { background-position: -112px -192px; }
+.ui-icon-circle-arrow-s { background-position: -128px -192px; }
+.ui-icon-circle-arrow-w { background-position: -144px -192px; }
+.ui-icon-circle-arrow-n { background-position: -160px -192px; }
+.ui-icon-circle-zoomin { background-position: -176px -192px; }
+.ui-icon-circle-zoomout { background-position: -192px -192px; }
+.ui-icon-circle-check { background-position: -208px -192px; }
+.ui-icon-circlesmall-plus { background-position: 0 -208px; }
+.ui-icon-circlesmall-minus { background-position: -16px -208px; }
+.ui-icon-circlesmall-close { background-position: -32px -208px; }
+.ui-icon-squaresmall-plus { background-position: -48px -208px; }
+.ui-icon-squaresmall-minus { background-position: -64px -208px; }
+.ui-icon-squaresmall-close { background-position: -80px -208px; }
+.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
+.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
+.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
+.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
+.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
+.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
+
+
+/* Misc visuals
+----------------------------------*/
+
+/* Corner radius */
+.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
+.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
+.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
+
+/* Overlays */
+.ui-widget-overlay { background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); }
+.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url("images/ui-bg_flat_0_aaaaaa_40x100.png") 50% 50% repeat-x; opacity: .3;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }
diff --git a/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.tooltip.css b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.tooltip.css
new file mode 100644
index 00000000..88b0d02e
--- /dev/null
+++ b/www/wiki/resources/lib/jquery.ui/themes/smoothness/jquery.ui.tooltip.css
@@ -0,0 +1,21 @@
+/*!
+ * jQuery UI Tooltip 1.9.2
+ * http://jqueryui.com
+ *
+ * Copyright 2012 jQuery Foundation and other contributors
+ * Released under the MIT license.
+ * http://jquery.org/license
+ */
+.ui-tooltip {
+ padding: 8px;
+ position: absolute;
+ z-index: 9999;
+ max-width: 300px;
+ -webkit-box-shadow: 0 0 5px #aaa;
+ box-shadow: 0 0 5px #aaa;
+}
+/* Fades and background-images don't work well together in IE6, drop the image */
+* html .ui-tooltip {
+ background-image: none;
+}
+body .ui-tooltip { border-width: 2px; }
diff --git a/www/wiki/resources/lib/jquery/jquery.appear.js b/www/wiki/resources/lib/jquery/jquery.appear.js
new file mode 100644
index 00000000..4f77886c
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.appear.js
@@ -0,0 +1,138 @@
+/*
+ * jQuery.appear
+ * http://code.google.com/p/jquery-appear/
+ *
+ * Copyright (c) 2009 Michael Hixson
+ * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
+*/
+(function($) {
+
+ $.fn.appear = function(fn, options) {
+
+ var settings = $.extend({
+
+ //arbitrary data to pass to fn
+ data: undefined,
+
+ //call fn only on the first appear?
+ one: true
+
+ }, options);
+
+ return this.each(function() {
+
+ var t = $(this);
+
+ //whether the element is currently visible
+ t.appeared = false;
+
+ if (!fn) {
+
+ //trigger the custom event
+ t.trigger('appear', settings.data);
+ return;
+ }
+
+ var w = $(window);
+
+ //fires the appear event when appropriate
+ var check = function() {
+
+ //is the element hidden?
+ if (!t.is(':visible')) {
+
+ //it became hidden
+ t.appeared = false;
+ return;
+ }
+
+ //is the element inside the visible window?
+ var a = w.scrollLeft();
+ var b = w.scrollTop();
+ var o = t.offset();
+ var x = o.left;
+ var y = o.top;
+
+ if (y + t.height() >= b &&
+ y <= b + w.height() &&
+ x + t.width() >= a &&
+ x <= a + w.width()) {
+
+ //trigger the custom event
+ if (!t.appeared) t.trigger('appear', settings.data);
+
+ } else {
+
+ //it scrolled out of view
+ t.appeared = false;
+ }
+ };
+
+ //create a modified fn with some additional logic
+ var modifiedFn = function() {
+
+ //mark the element as visible
+ t.appeared = true;
+
+ //is this supposed to happen only once?
+ if (settings.one) {
+
+ //remove the check
+ w.unbind('scroll', check);
+ var i = $.inArray(check, $.fn.appear.checks);
+ if (i >= 0) $.fn.appear.checks.splice(i, 1);
+ }
+
+ //trigger the original fn
+ fn.apply(this, arguments);
+ };
+
+ //bind the modified fn to the element
+ if (settings.one) t.one('appear', settings.data, modifiedFn);
+ else t.bind('appear', settings.data, modifiedFn);
+
+ //check whenever the window scrolls
+ w.scroll(check);
+
+ //check whenever the dom changes
+ $.fn.appear.checks.push(check);
+
+ //check now
+ (check)();
+ });
+ };
+
+ //keep a queue of appearance checks
+ $.extend($.fn.appear, {
+
+ checks: [],
+ timeout: null,
+
+ //process the queue
+ checkAll: function() {
+ var length = $.fn.appear.checks.length;
+ if (length > 0) while (length--) ($.fn.appear.checks[length])();
+ },
+
+ //check the queue asynchronously
+ run: function() {
+ if ($.fn.appear.timeout) clearTimeout($.fn.appear.timeout);
+ $.fn.appear.timeout = setTimeout($.fn.appear.checkAll, 20);
+ }
+ });
+
+ //run checks when these methods are called
+ $.each(['append', 'prepend', 'after', 'before', 'attr',
+ 'removeAttr', 'addClass', 'removeClass', 'toggleClass',
+ 'remove', 'css', 'show', 'hide'], function(i, n) {
+ var old = $.fn[n];
+ if (old) {
+ $.fn[n] = function() {
+ var r = old.apply(this, arguments);
+ $.fn.appear.run();
+ return r;
+ }
+ }
+ });
+
+})(jQuery); \ No newline at end of file
diff --git a/www/wiki/resources/lib/jquery/jquery.async.js b/www/wiki/resources/lib/jquery/jquery.async.js
new file mode 100644
index 00000000..2161f6b9
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.async.js
@@ -0,0 +1,69 @@
+/*
+ * jQuery Asynchronous Plugin 1.0
+ *
+ * Copyright (c) 2008 Vincent Robert (genezys.net)
+ * Dual licensed under the MIT (MIT-LICENSE.txt)
+ * and GPL (GPL-LICENSE.txt) licenses.
+ *
+ */
+(function($){
+
+// opts.delay : (default 10) delay between async call in ms
+// opts.bulk : (default 500) delay during which the loop can continue synchronously without yielding the CPU
+// opts.test : (default true) function to test in the while test part
+// opts.loop : (default empty) function to call in the while loop part
+// opts.end : (default empty) function to call at the end of the while loop
+$.whileAsync = function(opts) {
+ var delay = Math.abs(opts.delay) || 10,
+ bulk = isNaN(opts.bulk) ? 500 : Math.abs(opts.bulk),
+ test = opts.test || function(){ return true; },
+ loop = opts.loop || function(){},
+ end = opts.end || function(){};
+
+ (function(){
+
+ var t = false,
+ begin = new Date();
+
+ while( t = test() ) {
+ loop();
+ if( bulk === 0 || (new Date() - begin) > bulk ) {
+ break;
+ }
+ }
+ if( t ) {
+ setTimeout(arguments.callee, delay);
+ }
+ else {
+ end();
+ }
+
+ })();
+};
+
+// opts.delay : (default 10) delay between async call in ms
+// opts.bulk : (default 500) delay during which the loop can continue synchronously without yielding the CPU
+// opts.loop : (default empty) function to call in the each loop part, signature: function(index, value) this = value
+// opts.end : (default empty) function to call at the end of the each loop
+$.eachAsync = function(array, opts) {
+ var i = 0,
+ l = array.length,
+ loop = opts.loop || function(){};
+
+ $.whileAsync(
+ $.extend(opts, {
+ test: function() { return i < l; },
+ loop: function() {
+ var val = array[i];
+ return loop.call(val, i++, val);
+ }
+ })
+ );
+};
+
+$.fn.eachAsync = function(opts) {
+ $.eachAsync(this, opts);
+ return this;
+}
+
+})(jQuery); \ No newline at end of file
diff --git a/www/wiki/resources/lib/jquery/jquery.ba-throttle-debounce.js b/www/wiki/resources/lib/jquery/jquery.ba-throttle-debounce.js
new file mode 100644
index 00000000..fa30bdff
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.ba-throttle-debounce.js
@@ -0,0 +1,252 @@
+/*!
+ * jQuery throttle / debounce - v1.1 - 3/7/2010
+ * http://benalman.com/projects/jquery-throttle-debounce-plugin/
+ *
+ * Copyright (c) 2010 "Cowboy" Ben Alman
+ * Dual licensed under the MIT and GPL licenses.
+ * http://benalman.com/about/license/
+ */
+
+// Script: jQuery throttle / debounce: Sometimes, less is more!
+//
+// *Version: 1.1, Last updated: 3/7/2010*
+//
+// Project Home - http://benalman.com/projects/jquery-throttle-debounce-plugin/
+// GitHub - http://github.com/cowboy/jquery-throttle-debounce/
+// Source - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.js
+// (Minified) - http://github.com/cowboy/jquery-throttle-debounce/raw/master/jquery.ba-throttle-debounce.min.js (0.7kb)
+//
+// About: License
+//
+// Copyright (c) 2010 "Cowboy" Ben Alman,
+// Dual licensed under the MIT and GPL licenses.
+// http://benalman.com/about/license/
+//
+// About: Examples
+//
+// These working examples, complete with fully commented code, illustrate a few
+// ways in which this plugin can be used.
+//
+// Throttle - http://benalman.com/code/projects/jquery-throttle-debounce/examples/throttle/
+// Debounce - http://benalman.com/code/projects/jquery-throttle-debounce/examples/debounce/
+//
+// About: Support and Testing
+//
+// Information about what version or versions of jQuery this plugin has been
+// tested with, what browsers it has been tested in, and where the unit tests
+// reside (so you can test it yourself).
+//
+// jQuery Versions - none, 1.3.2, 1.4.2
+// Browsers Tested - Internet Explorer 6-8, Firefox 2-3.6, Safari 3-4, Chrome 4-5, Opera 9.6-10.1.
+// Unit Tests - http://benalman.com/code/projects/jquery-throttle-debounce/unit/
+//
+// About: Release History
+//
+// 1.1 - (3/7/2010) Fixed a bug in <jQuery.throttle> where trailing callbacks
+// executed later than they should. Reworked a fair amount of internal
+// logic as well.
+// 1.0 - (3/6/2010) Initial release as a stand-alone project. Migrated over
+// from jquery-misc repo v0.4 to jquery-throttle repo v1.0, added the
+// no_trailing throttle parameter and debounce functionality.
+//
+// Topic: Note for non-jQuery users
+//
+// jQuery isn't actually required for this plugin, because nothing internal
+// uses any jQuery methods or properties. jQuery is just used as a namespace
+// under which these methods can exist.
+//
+// Since jQuery isn't actually required for this plugin, if jQuery doesn't exist
+// when this plugin is loaded, the method described below will be created in
+// the `Cowboy` namespace. Usage will be exactly the same, but instead of
+// $.method() or jQuery.method(), you'll need to use Cowboy.method().
+
+(function(window,undefined){
+ '$:nomunge'; // Used by YUI compressor.
+
+ // Since jQuery really isn't required for this plugin, use `jQuery` as the
+ // namespace only if it already exists, otherwise use the `Cowboy` namespace,
+ // creating it if necessary.
+ var $ = window.jQuery || window.Cowboy || ( window.Cowboy = {} ),
+
+ // Internal method reference.
+ jq_throttle;
+
+ // Method: jQuery.throttle
+ //
+ // Throttle execution of a function. Especially useful for rate limiting
+ // execution of handlers on events like resize and scroll. If you want to
+ // rate-limit execution of a function to a single time, see the
+ // <jQuery.debounce> method.
+ //
+ // In this visualization, | is a throttled-function call and X is the actual
+ // callback execution:
+ //
+ // > Throttled with `no_trailing` specified as false or unspecified:
+ // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
+ // > X X X X X X X X X X X X
+ // >
+ // > Throttled with `no_trailing` specified as true:
+ // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
+ // > X X X X X X X X X X
+ //
+ // Usage:
+ //
+ // > var throttled = jQuery.throttle( delay, [ no_trailing, ] callback );
+ // >
+ // > jQuery('selector').bind( 'someevent', throttled );
+ // > jQuery('selector').unbind( 'someevent', throttled );
+ //
+ // This also works in jQuery 1.4+:
+ //
+ // > jQuery('selector').bind( 'someevent', jQuery.throttle( delay, [ no_trailing, ] callback ) );
+ // > jQuery('selector').unbind( 'someevent', callback );
+ //
+ // Arguments:
+ //
+ // delay - (Number) A zero-or-greater delay in milliseconds. For event
+ // callbacks, values around 100 or 250 (or even higher) are most useful.
+ // no_trailing - (Boolean) Optional, defaults to false. If no_trailing is
+ // true, callback will only execute every `delay` milliseconds while the
+ // throttled-function is being called. If no_trailing is false or
+ // unspecified, callback will be executed one final time after the last
+ // throttled-function call. (After the throttled-function has not been
+ // called for `delay` milliseconds, the internal counter is reset)
+ // callback - (Function) A function to be executed after delay milliseconds.
+ // The `this` context and all arguments are passed through, as-is, to
+ // `callback` when the throttled-function is executed.
+ //
+ // Returns:
+ //
+ // (Function) A new, throttled, function.
+
+ $.throttle = jq_throttle = function( delay, no_trailing, callback, debounce_mode ) {
+ // After wrapper has stopped being called, this timeout ensures that
+ // `callback` is executed at the proper times in `throttle` and `end`
+ // debounce modes.
+ var timeout_id,
+
+ // Keep track of the last time `callback` was executed.
+ last_exec = 0;
+
+ // `no_trailing` defaults to falsy.
+ if ( typeof no_trailing !== 'boolean' ) {
+ debounce_mode = callback;
+ callback = no_trailing;
+ no_trailing = undefined;
+ }
+
+ // The `wrapper` function encapsulates all of the throttling / debouncing
+ // functionality and when executed will limit the rate at which `callback`
+ // is executed.
+ function wrapper() {
+ var that = this,
+ elapsed = +new Date() - last_exec,
+ args = arguments;
+
+ // Execute `callback` and update the `last_exec` timestamp.
+ function exec() {
+ last_exec = +new Date();
+ callback.apply( that, args );
+ };
+
+ // If `debounce_mode` is true (at_begin) this is used to clear the flag
+ // to allow future `callback` executions.
+ function clear() {
+ timeout_id = undefined;
+ };
+
+ if ( debounce_mode && !timeout_id ) {
+ // Since `wrapper` is being called for the first time and
+ // `debounce_mode` is true (at_begin), execute `callback`.
+ exec();
+ }
+
+ // Clear any existing timeout.
+ timeout_id && clearTimeout( timeout_id );
+
+ if ( debounce_mode === undefined && elapsed > delay ) {
+ // In throttle mode, if `delay` time has been exceeded, execute
+ // `callback`.
+ exec();
+
+ } else if ( no_trailing !== true ) {
+ // In trailing throttle mode, since `delay` time has not been
+ // exceeded, schedule `callback` to execute `delay` ms after most
+ // recent execution.
+ //
+ // If `debounce_mode` is true (at_begin), schedule `clear` to execute
+ // after `delay` ms.
+ //
+ // If `debounce_mode` is false (at end), schedule `callback` to
+ // execute after `delay` ms.
+ timeout_id = setTimeout( debounce_mode ? clear : exec, debounce_mode === undefined ? delay - elapsed : delay );
+ }
+ };
+
+ // Set the guid of `wrapper` function to the same of original callback, so
+ // it can be removed in jQuery 1.4+ .unbind or .die by using the original
+ // callback as a reference.
+ if ( $.guid ) {
+ wrapper.guid = callback.guid = callback.guid || $.guid++;
+ }
+
+ // Return the wrapper function.
+ return wrapper;
+ };
+
+ // Method: jQuery.debounce
+ //
+ // Debounce execution of a function. Debouncing, unlike throttling,
+ // guarantees that a function is only executed a single time, either at the
+ // very beginning of a series of calls, or at the very end. If you want to
+ // simply rate-limit execution of a function, see the <jQuery.throttle>
+ // method.
+ //
+ // In this visualization, | is a debounced-function call and X is the actual
+ // callback execution:
+ //
+ // > Debounced with `at_begin` specified as false or unspecified:
+ // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
+ // > X X
+ // >
+ // > Debounced with `at_begin` specified as true:
+ // > ||||||||||||||||||||||||| (pause) |||||||||||||||||||||||||
+ // > X X
+ //
+ // Usage:
+ //
+ // > var debounced = jQuery.debounce( delay, [ at_begin, ] callback );
+ // >
+ // > jQuery('selector').bind( 'someevent', debounced );
+ // > jQuery('selector').unbind( 'someevent', debounced );
+ //
+ // This also works in jQuery 1.4+:
+ //
+ // > jQuery('selector').bind( 'someevent', jQuery.debounce( delay, [ at_begin, ] callback ) );
+ // > jQuery('selector').unbind( 'someevent', callback );
+ //
+ // Arguments:
+ //
+ // delay - (Number) A zero-or-greater delay in milliseconds. For event
+ // callbacks, values around 100 or 250 (or even higher) are most useful.
+ // at_begin - (Boolean) Optional, defaults to false. If at_begin is false or
+ // unspecified, callback will only be executed `delay` milliseconds after
+ // the last debounced-function call. If at_begin is true, callback will be
+ // executed only at the first debounced-function call. (After the
+ // throttled-function has not been called for `delay` milliseconds, the
+ // internal counter is reset)
+ // callback - (Function) A function to be executed after delay milliseconds.
+ // The `this` context and all arguments are passed through, as-is, to
+ // `callback` when the debounced-function is executed.
+ //
+ // Returns:
+ //
+ // (Function) A new, debounced, function.
+
+ $.debounce = function( delay, at_begin, callback ) {
+ return callback === undefined
+ ? jq_throttle( delay, at_begin, false )
+ : jq_throttle( delay, callback, at_begin !== false );
+ };
+
+})(this);
diff --git a/www/wiki/resources/lib/jquery/jquery.cookie.js b/www/wiki/resources/lib/jquery/jquery.cookie.js
new file mode 100644
index 00000000..3fb201c6
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.cookie.js
@@ -0,0 +1,90 @@
+/*!
+ * jQuery Cookie Plugin v1.3.1
+ * https://github.com/carhartl/jquery-cookie
+ *
+ * Copyright 2013 Klaus Hartl
+ * Released under the MIT license
+ */
+(function ($, document, undefined) {
+
+ var pluses = /\+/g;
+
+ function raw(s) {
+ return s;
+ }
+
+ function decoded(s) {
+ return unRfc2068(decodeURIComponent(s.replace(pluses, ' ')));
+ }
+
+ function unRfc2068(value) {
+ if (value.indexOf('"') === 0) {
+ // This is a quoted cookie as according to RFC2068, unescape
+ value = value.slice(1, -1).replace(/\\"/g, '"').replace(/\\\\/g, '\\');
+ }
+ return value;
+ }
+
+ function fromJSON(value) {
+ return config.json ? JSON.parse(value) : value;
+ }
+
+ var config = $.cookie = function (key, value, options) {
+
+ // write
+ if (value !== undefined) {
+ options = $.extend({}, config.defaults, options);
+
+ if (value === null) {
+ options.expires = -1;
+ }
+
+ if (typeof options.expires === 'number') {
+ var days = options.expires, t = options.expires = new Date();
+ t.setDate(t.getDate() + days);
+ }
+
+ value = config.json ? JSON.stringify(value) : String(value);
+
+ return (document.cookie = [
+ encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value),
+ options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
+ options.path ? '; path=' + options.path : '',
+ options.domain ? '; domain=' + options.domain : '',
+ options.secure ? '; secure' : ''
+ ].join(''));
+ }
+
+ // read
+ var decode = config.raw ? raw : decoded;
+ var cookies = document.cookie.split('; ');
+ var result = key ? null : {};
+ for (var i = 0, l = cookies.length; i < l; i++) {
+ var parts = cookies[i].split('=');
+ var name = decode(parts.shift());
+ var cookie = decode(parts.join('='));
+
+ if (key && key === name) {
+ result = fromJSON(cookie);
+ break;
+ }
+
+ if (!key) {
+ result[name] = fromJSON(cookie);
+ }
+ }
+
+ return result;
+ };
+
+ config.defaults = {};
+
+ $.removeCookie = function (key, options) {
+ if ($.cookie(key) !== null) {
+ $.cookie(key, null, options);
+ return true;
+ }
+ return false;
+ };
+
+})(jQuery, document);
diff --git a/www/wiki/resources/lib/jquery/jquery.form.js b/www/wiki/resources/lib/jquery/jquery.form.js
new file mode 100644
index 00000000..13e9a55c
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.form.js
@@ -0,0 +1,1089 @@
+/*!
+ * jQuery Form Plugin
+ * version: 3.14 (30-JUL-2012)
+ * @requires jQuery v1.3.2 or later
+ *
+ * Examples and documentation at: http://malsup.com/jquery/form/
+ * Project repository: https://github.com/malsup/form
+ * Dual licensed under the MIT and GPL licenses:
+ * http://malsup.github.com/mit-license.txt
+ * http://malsup.github.com/gpl-license-v2.txt
+ */
+/*global ActiveXObject alert */
+;(function($) {
+"use strict";
+
+/*
+ Usage Note:
+ -----------
+ Do not use both ajaxSubmit and ajaxForm on the same form. These
+ functions are mutually exclusive. Use ajaxSubmit if you want
+ to bind your own submit handler to the form. For example,
+
+ $(document).ready(function() {
+ $('#myForm').on('submit', function(e) {
+ e.preventDefault(); // <-- important
+ $(this).ajaxSubmit({
+ target: '#output'
+ });
+ });
+ });
+
+ Use ajaxForm when you want the plugin to manage all the event binding
+ for you. For example,
+
+ $(document).ready(function() {
+ $('#myForm').ajaxForm({
+ target: '#output'
+ });
+ });
+
+ You can also use ajaxForm with delegation (requires jQuery v1.7+), so the
+ form does not have to exist when you invoke ajaxForm:
+
+ $('#myForm').ajaxForm({
+ delegation: true,
+ target: '#output'
+ });
+
+ When using ajaxForm, the ajaxSubmit function will be invoked for you
+ at the appropriate time.
+*/
+
+/**
+ * Feature detection
+ */
+var feature = {};
+feature.fileapi = $("<input type='file'/>").get(0).files !== undefined;
+feature.formdata = window.FormData !== undefined;
+
+/**
+ * ajaxSubmit() provides a mechanism for immediately submitting
+ * an HTML form using AJAX.
+ */
+$.fn.ajaxSubmit = function(options) {
+ /*jshint scripturl:true */
+
+ // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
+ if (!this.length) {
+ log('ajaxSubmit: skipping submit process - no element selected');
+ return this;
+ }
+
+ var method, action, url, $form = this;
+
+ if (typeof options == 'function') {
+ options = { success: options };
+ }
+
+ method = this.attr('method');
+ action = this.attr('action');
+ url = (typeof action === 'string') ? $.trim(action) : '';
+ url = url || window.location.href || '';
+ if (url) {
+ // clean url (don't include hash vaue)
+ url = (url.match(/^([^#]+)/)||[])[1];
+ }
+
+ options = $.extend(true, {
+ url: url,
+ success: $.ajaxSettings.success,
+ type: method || 'GET',
+ iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
+ }, options);
+
+ // hook for manipulating the form data before it is extracted;
+ // convenient for use with rich editors like tinyMCE or FCKEditor
+ var veto = {};
+ this.trigger('form-pre-serialize', [this, options, veto]);
+ if (veto.veto) {
+ log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
+ return this;
+ }
+
+ // provide opportunity to alter form data before it is serialized
+ if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
+ log('ajaxSubmit: submit aborted via beforeSerialize callback');
+ return this;
+ }
+
+ var traditional = options.traditional;
+ if ( traditional === undefined ) {
+ traditional = $.ajaxSettings.traditional;
+ }
+
+ var elements = [];
+ var qx, a = this.formToArray(options.semantic, elements);
+ if (options.data) {
+ options.extraData = options.data;
+ qx = $.param(options.data, traditional);
+ }
+
+ // give pre-submit callback an opportunity to abort the submit
+ if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
+ log('ajaxSubmit: submit aborted via beforeSubmit callback');
+ return this;
+ }
+
+ // fire vetoable 'validate' event
+ this.trigger('form-submit-validate', [a, this, options, veto]);
+ if (veto.veto) {
+ log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
+ return this;
+ }
+
+ var q = $.param(a, traditional);
+ if (qx) {
+ q = ( q ? (q + '&' + qx) : qx );
+ }
+ if (options.type.toUpperCase() == 'GET') {
+ options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
+ options.data = null; // data is null for 'get'
+ }
+ else {
+ options.data = q; // data is the query string for 'post'
+ }
+
+ var callbacks = [];
+ if (options.resetForm) {
+ callbacks.push(function() { $form.resetForm(); });
+ }
+ if (options.clearForm) {
+ callbacks.push(function() { $form.clearForm(options.includeHidden); });
+ }
+
+ // perform a load on the target only if dataType is not provided
+ if (!options.dataType && options.target) {
+ var oldSuccess = options.success || function(){};
+ callbacks.push(function(data) {
+ var fn = options.replaceTarget ? 'replaceWith' : 'html';
+ $(options.target)[fn](data).each(oldSuccess, arguments);
+ });
+ }
+ else if (options.success) {
+ callbacks.push(options.success);
+ }
+
+ options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
+ var context = options.context || this ; // jQuery 1.4+ supports scope context
+ for (var i=0, max=callbacks.length; i < max; i++) {
+ callbacks[i].apply(context, [data, status, xhr || $form, $form]);
+ }
+ };
+
+ // are there files to upload?
+ var fileInputs = $('input:file:enabled[value]', this); // [value] (issue #113)
+ var hasFileInputs = fileInputs.length > 0;
+ var mp = 'multipart/form-data';
+ var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);
+
+ var fileAPI = feature.fileapi && feature.formdata;
+ log("fileAPI :" + fileAPI);
+ var shouldUseFrame = (hasFileInputs || multipart) && !fileAPI;
+
+ // options.iframe allows user to force iframe mode
+ // 06-NOV-09: now defaulting to iframe mode if file input is detected
+ if (options.iframe !== false && (options.iframe || shouldUseFrame)) {
+ // hack to fix Safari hang (thanks to Tim Molendijk for this)
+ // see: http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
+ if (options.closeKeepAlive) {
+ $.get(options.closeKeepAlive, function() {
+ fileUploadIframe(a);
+ });
+ }
+ else {
+ fileUploadIframe(a);
+ }
+ }
+ else if ((hasFileInputs || multipart) && fileAPI) {
+ fileUploadXhr(a);
+ }
+ else {
+ $.ajax(options);
+ }
+
+ // clear element array
+ for (var k=0; k < elements.length; k++)
+ elements[k] = null;
+
+ // fire 'notify' event
+ this.trigger('form-submit-notify', [this, options]);
+ return this;
+
+ // XMLHttpRequest Level 2 file uploads (big hat tip to francois2metz)
+ function fileUploadXhr(a) {
+ var formdata = new FormData();
+
+ for (var i=0; i < a.length; i++) {
+ formdata.append(a[i].name, a[i].value);
+ }
+
+ if (options.extraData) {
+ for (var p in options.extraData)
+ if (options.extraData.hasOwnProperty(p))
+ formdata.append(p, options.extraData[p]);
+ }
+
+ options.data = null;
+
+ var s = $.extend(true, {}, $.ajaxSettings, options, {
+ contentType: false,
+ processData: false,
+ cache: false,
+ type: 'POST'
+ });
+
+ if (options.uploadProgress) {
+ // workaround because jqXHR does not expose upload property
+ s.xhr = function() {
+ var xhr = jQuery.ajaxSettings.xhr();
+ if (xhr.upload) {
+ xhr.upload.onprogress = function(event) {
+ var percent = 0;
+ var position = event.loaded || event.position; /*event.position is deprecated*/
+ var total = event.total;
+ if (event.lengthComputable) {
+ percent = Math.ceil(position / total * 100);
+ }
+ options.uploadProgress(event, position, total, percent);
+ };
+ }
+ return xhr;
+ };
+ }
+
+ s.data = null;
+ var beforeSend = s.beforeSend;
+ s.beforeSend = function(xhr, o) {
+ o.data = formdata;
+ if(beforeSend)
+ beforeSend.call(this, xhr, o);
+ };
+ $.ajax(s);
+ }
+
+ // private function for handling file uploads (hat tip to YAHOO!)
+ function fileUploadIframe(a) {
+ var form = $form[0], el, i, s, g, id, $io, io, xhr, sub, n, timedOut, timeoutHandle;
+ var useProp = !!$.fn.prop;
+
+ if ($(':input[name=submit],:input[id=submit]', form).length) {
+ // if there is an input with a name or id of 'submit' then we won't be
+ // able to invoke the submit fn on the form (at least not x-browser)
+ alert('Error: Form elements must not have name or id of "submit".');
+ return;
+ }
+
+ if (a) {
+ // ensure that every serialized input is still enabled
+ for (i=0; i < elements.length; i++) {
+ el = $(elements[i]);
+ if ( useProp )
+ el.prop('disabled', false);
+ else
+ el.removeAttr('disabled');
+ }
+ }
+
+ s = $.extend(true, {}, $.ajaxSettings, options);
+ s.context = s.context || s;
+ id = 'jqFormIO' + (new Date().getTime());
+ if (s.iframeTarget) {
+ $io = $(s.iframeTarget);
+ n = $io.attr('name');
+ if (!n)
+ $io.attr('name', id);
+ else
+ id = n;
+ }
+ else {
+ $io = $('<iframe name="' + id + '" src="'+ s.iframeSrc +'" />');
+ $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });
+ }
+ io = $io[0];
+
+
+ xhr = { // mock object
+ aborted: 0,
+ responseText: null,
+ responseXML: null,
+ status: 0,
+ statusText: 'n/a',
+ getAllResponseHeaders: function() {},
+ getResponseHeader: function() {},
+ setRequestHeader: function() {},
+ abort: function(status) {
+ var e = (status === 'timeout' ? 'timeout' : 'aborted');
+ log('aborting upload... ' + e);
+ this.aborted = 1;
+ // #214
+ if (io.contentWindow.document.execCommand) {
+ try { // #214
+ io.contentWindow.document.execCommand('Stop');
+ } catch(ignore) {}
+ }
+ $io.attr('src', s.iframeSrc); // abort op in progress
+ xhr.error = e;
+ if (s.error)
+ s.error.call(s.context, xhr, e, status);
+ if (g)
+ $.event.trigger("ajaxError", [xhr, s, e]);
+ if (s.complete)
+ s.complete.call(s.context, xhr, e);
+ }
+ };
+
+ g = s.global;
+ // trigger ajax global events so that activity/block indicators work like normal
+ if (g && 0 === $.active++) {
+ $.event.trigger("ajaxStart");
+ }
+ if (g) {
+ $.event.trigger("ajaxSend", [xhr, s]);
+ }
+
+ if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
+ if (s.global) {
+ $.active--;
+ }
+ return;
+ }
+ if (xhr.aborted) {
+ return;
+ }
+
+ // add submitting element to data if we know it
+ sub = form.clk;
+ if (sub) {
+ n = sub.name;
+ if (n && !sub.disabled) {
+ s.extraData = s.extraData || {};
+ s.extraData[n] = sub.value;
+ if (sub.type == "image") {
+ s.extraData[n+'.x'] = form.clk_x;
+ s.extraData[n+'.y'] = form.clk_y;
+ }
+ }
+ }
+
+ var CLIENT_TIMEOUT_ABORT = 1;
+ var SERVER_ABORT = 2;
+
+ function getDoc(frame) {
+ var doc = frame.contentWindow ? frame.contentWindow.document : frame.contentDocument ? frame.contentDocument : frame.document;
+ return doc;
+ }
+
+ // Rails CSRF hack (thanks to Yvan Barthelemy)
+ var csrf_token = $('meta[name=csrf-token]').attr('content');
+ var csrf_param = $('meta[name=csrf-param]').attr('content');
+ if (csrf_param && csrf_token) {
+ s.extraData = s.extraData || {};
+ s.extraData[csrf_param] = csrf_token;
+ }
+
+ // take a breath so that pending repaints get some cpu time before the upload starts
+ function doSubmit() {
+ // make sure form attrs are set
+ var t = $form.attr('target'), a = $form.attr('action');
+
+ // update form attrs in IE friendly way
+ form.setAttribute('target',id);
+ if (!method) {
+ form.setAttribute('method', 'POST');
+ }
+ if (a != s.url) {
+ form.setAttribute('action', s.url);
+ }
+
+ // ie borks in some cases when setting encoding
+ if (! s.skipEncodingOverride && (!method || /post/i.test(method))) {
+ $form.attr({
+ encoding: 'multipart/form-data',
+ enctype: 'multipart/form-data'
+ });
+ }
+
+ // support timout
+ if (s.timeout) {
+ timeoutHandle = setTimeout(function() { timedOut = true; cb(CLIENT_TIMEOUT_ABORT); }, s.timeout);
+ }
+
+ // look for server aborts
+ function checkState() {
+ try {
+ var state = getDoc(io).readyState;
+ log('state = ' + state);
+ if (state && state.toLowerCase() == 'uninitialized')
+ setTimeout(checkState,50);
+ }
+ catch(e) {
+ log('Server abort: ' , e, ' (', e.name, ')');
+ cb(SERVER_ABORT);
+ if (timeoutHandle)
+ clearTimeout(timeoutHandle);
+ timeoutHandle = undefined;
+ }
+ }
+
+ // add "extra" data to form if provided in options
+ var extraInputs = [];
+ try {
+ if (s.extraData) {
+ for (var n in s.extraData) {
+ if (s.extraData.hasOwnProperty(n)) {
+ // if using the $.param format that allows for multiple values with the same name
+ if($.isPlainObject(s.extraData[n]) && s.extraData[n].hasOwnProperty('name') && s.extraData[n].hasOwnProperty('value')) {
+ extraInputs.push(
+ $('<input type="hidden" name="'+s.extraData[n].name+'">').attr('value',s.extraData[n].value)
+ .appendTo(form)[0]);
+ } else {
+ extraInputs.push(
+ $('<input type="hidden" name="'+n+'">').attr('value',s.extraData[n])
+ .appendTo(form)[0]);
+ }
+ }
+ }
+ }
+
+ if (!s.iframeTarget) {
+ // add iframe to doc and submit the form
+ $io.appendTo('body');
+ if (io.attachEvent)
+ io.attachEvent('onload', cb);
+ else
+ io.addEventListener('load', cb, false);
+ }
+ setTimeout(checkState,15);
+ form.submit();
+ }
+ finally {
+ // reset attrs and remove "extra" input elements
+ form.setAttribute('action',a);
+ if(t) {
+ form.setAttribute('target', t);
+ } else {
+ $form.removeAttr('target');
+ }
+ $(extraInputs).remove();
+ }
+ }
+
+ if (s.forceSync) {
+ doSubmit();
+ }
+ else {
+ setTimeout(doSubmit, 10); // this lets dom updates render
+ }
+
+ var data, doc, domCheckCount = 50, callbackProcessed;
+
+ function cb(e) {
+ if (xhr.aborted || callbackProcessed) {
+ return;
+ }
+ try {
+ doc = getDoc(io);
+ }
+ catch(ex) {
+ log('cannot access response document: ', ex);
+ e = SERVER_ABORT;
+ }
+ if (e === CLIENT_TIMEOUT_ABORT && xhr) {
+ xhr.abort('timeout');
+ return;
+ }
+ else if (e == SERVER_ABORT && xhr) {
+ xhr.abort('server abort');
+ return;
+ }
+
+ if (!doc || doc.location.href == s.iframeSrc) {
+ // response not received yet
+ if (!timedOut)
+ return;
+ }
+ if (io.detachEvent)
+ io.detachEvent('onload', cb);
+ else
+ io.removeEventListener('load', cb, false);
+
+ var status = 'success', errMsg;
+ try {
+ if (timedOut) {
+ throw 'timeout';
+ }
+
+ var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
+ log('isXml='+isXml);
+ if (!isXml && window.opera && (doc.body === null || !doc.body.innerHTML)) {
+ if (--domCheckCount) {
+ // in some browsers (Opera) the iframe DOM is not always traversable when
+ // the onload callback fires, so we loop a bit to accommodate
+ log('requeing onLoad callback, DOM not available');
+ setTimeout(cb, 250);
+ return;
+ }
+ // let this fall through because server response could be an empty document
+ //log('Could not access iframe DOM after mutiple tries.');
+ //throw 'DOMException: not available';
+ }
+
+ //log('response detected');
+ var docRoot = doc.body ? doc.body : doc.documentElement;
+ xhr.responseText = docRoot ? docRoot.innerHTML : null;
+ xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
+ if (isXml)
+ s.dataType = 'xml';
+ xhr.getResponseHeader = function(header){
+ var headers = {'content-type': s.dataType};
+ return headers[header];
+ };
+ // support for XHR 'status' & 'statusText' emulation :
+ if (docRoot) {
+ xhr.status = Number( docRoot.getAttribute('status') ) || xhr.status;
+ xhr.statusText = docRoot.getAttribute('statusText') || xhr.statusText;
+ }
+
+ var dt = (s.dataType || '').toLowerCase();
+ var scr = /(json|script|text)/.test(dt);
+ if (scr || s.textarea) {
+ // see if user embedded response in textarea
+ var ta = doc.getElementsByTagName('textarea')[0];
+ if (ta) {
+ xhr.responseText = ta.value;
+ // support for XHR 'status' & 'statusText' emulation :
+ xhr.status = Number( ta.getAttribute('status') ) || xhr.status;
+ xhr.statusText = ta.getAttribute('statusText') || xhr.statusText;
+ }
+ else if (scr) {
+ // account for browsers injecting pre around json response
+ var pre = doc.getElementsByTagName('pre')[0];
+ var b = doc.getElementsByTagName('body')[0];
+ if (pre) {
+ xhr.responseText = pre.textContent ? pre.textContent : pre.innerText;
+ }
+ else if (b) {
+ xhr.responseText = b.textContent ? b.textContent : b.innerText;
+ }
+ }
+ }
+ else if (dt == 'xml' && !xhr.responseXML && xhr.responseText) {
+ xhr.responseXML = toXml(xhr.responseText);
+ }
+
+ try {
+ data = httpData(xhr, dt, s);
+ }
+ catch (e) {
+ status = 'parsererror';
+ xhr.error = errMsg = (e || status);
+ }
+ }
+ catch (e) {
+ log('error caught: ',e);
+ status = 'error';
+ xhr.error = errMsg = (e || status);
+ }
+
+ if (xhr.aborted) {
+ log('upload aborted');
+ status = null;
+ }
+
+ if (xhr.status) { // we've set xhr.status
+ status = (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) ? 'success' : 'error';
+ }
+
+ // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
+ if (status === 'success') {
+ if (s.success)
+ s.success.call(s.context, data, 'success', xhr);
+ if (g)
+ $.event.trigger("ajaxSuccess", [xhr, s]);
+ }
+ else if (status) {
+ if (errMsg === undefined)
+ errMsg = xhr.statusText;
+ if (s.error)
+ s.error.call(s.context, xhr, status, errMsg);
+ if (g)
+ $.event.trigger("ajaxError", [xhr, s, errMsg]);
+ }
+
+ if (g)
+ $.event.trigger("ajaxComplete", [xhr, s]);
+
+ if (g && ! --$.active) {
+ $.event.trigger("ajaxStop");
+ }
+
+ if (s.complete)
+ s.complete.call(s.context, xhr, status);
+
+ callbackProcessed = true;
+ if (s.timeout)
+ clearTimeout(timeoutHandle);
+
+ // clean up
+ setTimeout(function() {
+ if (!s.iframeTarget)
+ $io.remove();
+ xhr.responseXML = null;
+ }, 100);
+ }
+
+ var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
+ if (window.ActiveXObject) {
+ doc = new ActiveXObject('Microsoft.XMLDOM');
+ doc.async = 'false';
+ doc.loadXML(s);
+ }
+ else {
+ doc = (new DOMParser()).parseFromString(s, 'text/xml');
+ }
+ return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
+ };
+ var parseJSON = $.parseJSON || function(s) {
+ /*jslint evil:true */
+ return window['eval']('(' + s + ')');
+ };
+
+ var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
+
+ var ct = xhr.getResponseHeader('content-type') || '',
+ xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
+ data = xml ? xhr.responseXML : xhr.responseText;
+
+ if (xml && data.documentElement.nodeName === 'parsererror') {
+ if ($.error)
+ $.error('parsererror');
+ }
+ if (s && s.dataFilter) {
+ data = s.dataFilter(data, type);
+ }
+ if (typeof data === 'string') {
+ if (type === 'json' || !type && ct.indexOf('json') >= 0) {
+ data = parseJSON(data);
+ } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
+ $.globalEval(data);
+ }
+ }
+ return data;
+ };
+ }
+};
+
+/**
+ * ajaxForm() provides a mechanism for fully automating form submission.
+ *
+ * The advantages of using this method instead of ajaxSubmit() are:
+ *
+ * 1: This method will include coordinates for <input type="image" /> elements (if the element
+ * is used to submit the form).
+ * 2. This method will include the submit element's name/value data (for the element that was
+ * used to submit the form).
+ * 3. This method binds the submit() method to the form for you.
+ *
+ * The options argument for ajaxForm works exactly as it does for ajaxSubmit. ajaxForm merely
+ * passes the options argument along after properly binding events for submit elements and
+ * the form itself.
+ */
+$.fn.ajaxForm = function(options) {
+ options = options || {};
+ options.delegation = options.delegation && $.isFunction($.fn.on);
+
+ // in jQuery 1.3+ we can fix mistakes with the ready state
+ if (!options.delegation && this.length === 0) {
+ var o = { s: this.selector, c: this.context };
+ if (!$.isReady && o.s) {
+ log('DOM not ready, queuing ajaxForm');
+ $(function() {
+ $(o.s,o.c).ajaxForm(options);
+ });
+ return this;
+ }
+ // is your DOM ready? http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
+ log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
+ return this;
+ }
+
+ if ( options.delegation ) {
+ $(document)
+ .off('submit.form-plugin', this.selector, doAjaxSubmit)
+ .off('click.form-plugin', this.selector, captureSubmittingElement)
+ .on('submit.form-plugin', this.selector, options, doAjaxSubmit)
+ .on('click.form-plugin', this.selector, options, captureSubmittingElement);
+ return this;
+ }
+
+ return this.ajaxFormUnbind()
+ .bind('submit.form-plugin', options, doAjaxSubmit)
+ .bind('click.form-plugin', options, captureSubmittingElement);
+};
+
+// private event handlers
+function doAjaxSubmit(e) {
+ /*jshint validthis:true */
+ var options = e.data;
+ if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
+ e.preventDefault();
+ $(this).ajaxSubmit(options);
+ }
+}
+
+function captureSubmittingElement(e) {
+ /*jshint validthis:true */
+ var target = e.target;
+ var $el = $(target);
+ if (!($el.is(":submit,input:image"))) {
+ // is this a child element of the submit el? (ex: a span within a button)
+ var t = $el.closest(':submit');
+ if (t.length === 0) {
+ return;
+ }
+ target = t[0];
+ }
+ var form = this;
+ form.clk = target;
+ if (target.type == 'image') {
+ if (e.offsetX !== undefined) {
+ form.clk_x = e.offsetX;
+ form.clk_y = e.offsetY;
+ } else if (typeof $.fn.offset == 'function') {
+ var offset = $el.offset();
+ form.clk_x = e.pageX - offset.left;
+ form.clk_y = e.pageY - offset.top;
+ } else {
+ form.clk_x = e.pageX - target.offsetLeft;
+ form.clk_y = e.pageY - target.offsetTop;
+ }
+ }
+ // clear form vars
+ setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
+}
+
+
+// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
+$.fn.ajaxFormUnbind = function() {
+ return this.unbind('submit.form-plugin click.form-plugin');
+};
+
+/**
+ * formToArray() gathers form element data into an array of objects that can
+ * be passed to any of the following ajax functions: $.get, $.post, or load.
+ * Each object in the array has both a 'name' and 'value' property. An example of
+ * an array for a simple login form might be:
+ *
+ * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
+ *
+ * It is this array that is passed to pre-submit callback functions provided to the
+ * ajaxSubmit() and ajaxForm() methods.
+ */
+$.fn.formToArray = function(semantic, elements) {
+ var a = [];
+ if (this.length === 0) {
+ return a;
+ }
+
+ var form = this[0];
+ var els = semantic ? form.getElementsByTagName('*') : form.elements;
+ if (!els) {
+ return a;
+ }
+
+ var i,j,n,v,el,max,jmax;
+ for(i=0, max=els.length; i < max; i++) {
+ el = els[i];
+ n = el.name;
+ if (!n) {
+ continue;
+ }
+
+ if (semantic && form.clk && el.type == "image") {
+ // handle image inputs on the fly when semantic == true
+ if(!el.disabled && form.clk == el) {
+ a.push({name: n, value: $(el).val(), type: el.type });
+ a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+ }
+ continue;
+ }
+
+ v = $.fieldValue(el, true);
+ if (v && v.constructor == Array) {
+ if (elements)
+ elements.push(el);
+ for(j=0, jmax=v.length; j < jmax; j++) {
+ a.push({name: n, value: v[j]});
+ }
+ }
+ else if (feature.fileapi && el.type == 'file' && !el.disabled) {
+ if (elements)
+ elements.push(el);
+ var files = el.files;
+ if (files.length) {
+ for (j=0; j < files.length; j++) {
+ a.push({name: n, value: files[j], type: el.type});
+ }
+ }
+ else {
+ // #180
+ a.push({ name: n, value: '', type: el.type });
+ }
+ }
+ else if (v !== null && typeof v != 'undefined') {
+ if (elements)
+ elements.push(el);
+ a.push({name: n, value: v, type: el.type, required: el.required});
+ }
+ }
+
+ if (!semantic && form.clk) {
+ // input type=='image' are not found in elements array! handle it here
+ var $input = $(form.clk), input = $input[0];
+ n = input.name;
+ if (n && !input.disabled && input.type == 'image') {
+ a.push({name: n, value: $input.val()});
+ a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
+ }
+ }
+ return a;
+};
+
+/**
+ * Serializes form data into a 'submittable' string. This method will return a string
+ * in the format: name1=value1&amp;name2=value2
+ */
+$.fn.formSerialize = function(semantic) {
+ //hand off to jQuery.param for proper encoding
+ return $.param(this.formToArray(semantic));
+};
+
+/**
+ * Serializes all field elements in the jQuery object into a query string.
+ * This method will return a string in the format: name1=value1&amp;name2=value2
+ */
+$.fn.fieldSerialize = function(successful) {
+ var a = [];
+ this.each(function() {
+ var n = this.name;
+ if (!n) {
+ return;
+ }
+ var v = $.fieldValue(this, successful);
+ if (v && v.constructor == Array) {
+ for (var i=0,max=v.length; i < max; i++) {
+ a.push({name: n, value: v[i]});
+ }
+ }
+ else if (v !== null && typeof v != 'undefined') {
+ a.push({name: this.name, value: v});
+ }
+ });
+ //hand off to jQuery.param for proper encoding
+ return $.param(a);
+};
+
+/**
+ * Returns the value(s) of the element in the matched set. For example, consider the following form:
+ *
+ * <form><fieldset>
+ * <input name="A" type="text" />
+ * <input name="A" type="text" />
+ * <input name="B" type="checkbox" value="B1" />
+ * <input name="B" type="checkbox" value="B2"/>
+ * <input name="C" type="radio" value="C1" />
+ * <input name="C" type="radio" value="C2" />
+ * </fieldset></form>
+ *
+ * var v = $(':text').fieldValue();
+ * // if no values are entered into the text inputs
+ * v == ['','']
+ * // if values entered into the text inputs are 'foo' and 'bar'
+ * v == ['foo','bar']
+ *
+ * var v = $(':checkbox').fieldValue();
+ * // if neither checkbox is checked
+ * v === undefined
+ * // if both checkboxes are checked
+ * v == ['B1', 'B2']
+ *
+ * var v = $(':radio').fieldValue();
+ * // if neither radio is checked
+ * v === undefined
+ * // if first radio is checked
+ * v == ['C1']
+ *
+ * The successful argument controls whether or not the field element must be 'successful'
+ * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
+ * The default value of the successful argument is true. If this value is false the value(s)
+ * for each element is returned.
+ *
+ * Note: This method *always* returns an array. If no valid value can be determined the
+ * array will be empty, otherwise it will contain one or more values.
+ */
+$.fn.fieldValue = function(successful) {
+ for (var val=[], i=0, max=this.length; i < max; i++) {
+ var el = this[i];
+ var v = $.fieldValue(el, successful);
+ if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
+ continue;
+ }
+ if (v.constructor == Array)
+ $.merge(val, v);
+ else
+ val.push(v);
+ }
+ return val;
+};
+
+/**
+ * Returns the value of the field element.
+ */
+$.fieldValue = function(el, successful) {
+ var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
+ if (successful === undefined) {
+ successful = true;
+ }
+
+ if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
+ (t == 'checkbox' || t == 'radio') && !el.checked ||
+ (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
+ tag == 'select' && el.selectedIndex == -1)) {
+ return null;
+ }
+
+ if (tag == 'select') {
+ var index = el.selectedIndex;
+ if (index < 0) {
+ return null;
+ }
+ var a = [], ops = el.options;
+ var one = (t == 'select-one');
+ var max = (one ? index+1 : ops.length);
+ for(var i=(one ? index : 0); i < max; i++) {
+ var op = ops[i];
+ if (op.selected) {
+ var v = op.value;
+ if (!v) { // extra pain for IE...
+ v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
+ }
+ if (one) {
+ return v;
+ }
+ a.push(v);
+ }
+ }
+ return a;
+ }
+ return $(el).val();
+};
+
+/**
+ * Clears the form data. Takes the following actions on the form's input fields:
+ * - input text fields will have their 'value' property set to the empty string
+ * - select elements will have their 'selectedIndex' property set to -1
+ * - checkbox and radio inputs will have their 'checked' property set to false
+ * - inputs of type submit, button, reset, and hidden will *not* be effected
+ * - button elements will *not* be effected
+ */
+$.fn.clearForm = function(includeHidden) {
+ return this.each(function() {
+ $('input,select,textarea', this).clearFields(includeHidden);
+ });
+};
+
+/**
+ * Clears the selected form elements.
+ */
+$.fn.clearFields = $.fn.clearInputs = function(includeHidden) {
+ var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' is not in this list
+ return this.each(function() {
+ var t = this.type, tag = this.tagName.toLowerCase();
+ if (re.test(t) || tag == 'textarea') {
+ this.value = '';
+ }
+ else if (t == 'checkbox' || t == 'radio') {
+ this.checked = false;
+ }
+ else if (tag == 'select') {
+ this.selectedIndex = -1;
+ }
+ else if (includeHidden) {
+ // includeHidden can be the value true, or it can be a selector string
+ // indicating a special test; for example:
+ // $('#myForm').clearForm('.special:hidden')
+ // the above would clean hidden inputs that have the class of 'special'
+ if ( (includeHidden === true && /hidden/.test(t)) ||
+ (typeof includeHidden == 'string' && $(this).is(includeHidden)) )
+ this.value = '';
+ }
+ });
+};
+
+/**
+ * Resets the form data. Causes all form elements to be reset to their original value.
+ */
+$.fn.resetForm = function() {
+ return this.each(function() {
+ // guard against an input with the name of 'reset'
+ // note that IE reports the reset function as an 'object'
+ if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
+ this.reset();
+ }
+ });
+};
+
+/**
+ * Enables or disables any matching elements.
+ */
+$.fn.enable = function(b) {
+ if (b === undefined) {
+ b = true;
+ }
+ return this.each(function() {
+ this.disabled = !b;
+ });
+};
+
+/**
+ * Checks/unchecks any matching checkboxes or radio buttons and
+ * selects/deselects and matching option elements.
+ */
+$.fn.selected = function(select) {
+ if (select === undefined) {
+ select = true;
+ }
+ return this.each(function() {
+ var t = this.type;
+ if (t == 'checkbox' || t == 'radio') {
+ this.checked = select;
+ }
+ else if (this.tagName.toLowerCase() == 'option') {
+ var $sel = $(this).parent('select');
+ if (select && $sel[0] && $sel[0].type == 'select-one') {
+ // deselect all other options
+ $sel.find('option').selected(false);
+ }
+ this.selected = select;
+ }
+ });
+};
+
+// expose debug var
+$.fn.ajaxSubmit.debug = false;
+
+// helper fn for console logging
+function log() {
+ if (!$.fn.ajaxSubmit.debug)
+ return;
+ var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
+ if (window.console && window.console.log) {
+ window.console.log(msg);
+ }
+ else if (window.opera && window.opera.postError) {
+ window.opera.postError(msg);
+ }
+}
+
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery/jquery.fullscreen.js b/www/wiki/resources/lib/jquery/jquery.fullscreen.js
new file mode 100644
index 00000000..30e44846
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.fullscreen.js
@@ -0,0 +1,175 @@
+/**
+ * jQuery fullscreen plugin v2.0.0-git (9f8f97d127)
+ * https://github.com/theopolisme/jquery-fullscreen
+ *
+ * Copyright (c) 2013 Theopolisme <theopolismewiki@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+( function ( $ ) {
+ var setupFullscreen,
+ fsClass = 'jq-fullscreened';
+
+ /**
+ * On fullscreenchange, trigger a jq-fullscreen-change event
+ * The event is given an object, which contains the fullscreened DOM element (element), if any
+ * and a boolean value (fullscreen) indicating if we've entered or exited fullscreen mode
+ * Also remove the 'fullscreened' class from elements that are no longer fullscreen
+ */
+ function handleFullscreenChange () {
+ var fullscreenElement = document.fullscreenElement ||
+ document.mozFullScreenElement ||
+ document.webkitFullscreenElement ||
+ document.msFullscreenElement;
+
+ if ( !fullscreenElement ) {
+ $( '.' + fsClass ).data( 'isFullscreened', false ).removeClass( fsClass );
+ }
+
+ $( document ).trigger( $.Event( 'jq-fullscreen-change', { element: fullscreenElement, fullscreen: !!fullscreenElement } ) );
+ }
+
+ /**
+ * Enters full screen with the "this" element in focus.
+ * Check the .data( 'isFullscreened' ) of the return value to check
+ * success or failure, if you're into that sort of thing.
+ * @chainable
+ * @return {jQuery}
+ */
+ function enterFullscreen () {
+ var element = this.get(0),
+ $element = this.first();
+ if ( element ) {
+ if ( element.requestFullscreen ) {
+ element.requestFullscreen();
+ } else if ( element.mozRequestFullScreen ) {
+ element.mozRequestFullScreen();
+ } else if ( element.webkitRequestFullscreen ) {
+ element.webkitRequestFullscreen();
+ } else if ( element.msRequestFullscreen ) {
+ element.msRequestFullscreen();
+ } else {
+ // Unable to make fullscreen
+ $element.data( 'isFullscreened', false );
+ return this;
+ }
+ // Add the fullscreen class and data attribute to `element`
+ $element.addClass( fsClass ).data( 'isFullscreened', true );
+ return this;
+ } else {
+ $element.data( 'isFullscreened', false );
+ return this;
+ }
+ }
+
+ /**
+ * Brings the "this" element out of fullscreen.
+ * Check the .data( 'isFullscreened' ) of the return value to check
+ * success or failure, if you're into that sort of thing.
+ * @chainable
+ * @return {jQuery}
+ */
+ function exitFullscreen () {
+ var fullscreenElement = ( document.fullscreenElement ||
+ document.mozFullScreenElement ||
+ document.webkitFullscreenElement ||
+ document.msFullscreenElement );
+
+ // Ensure that we only exit fullscreen if exitFullscreen() is being called on the same element that is currently fullscreen
+ if ( fullscreenElement && this.get(0) === fullscreenElement ) {
+ if ( document.exitFullscreen ) {
+ document.exitFullscreen();
+ } else if ( document.mozCancelFullScreen ) {
+ document.mozCancelFullScreen();
+ } else if ( document.webkitCancelFullScreen ) {
+ document.webkitCancelFullScreen();
+ } else if ( document.msExitFullscreen ) {
+ document.msExitFullscreen();
+ } else {
+ // Unable to cancel fullscreen mode
+ return this;
+ }
+ // We don't need to remove the fullscreen class here,
+ // because it will be removed in handleFullscreenChange.
+ // But we should change the data on the element so the
+ // caller can check for success.
+ this.first().data( 'isFullscreened', false );
+ }
+
+ return this;
+ }
+
+ /**
+ * Set up fullscreen handling and install necessary event handlers.
+ * Return false if fullscreen is not supported.
+ */
+ setupFullscreen = function () {
+ if ( $.support.fullscreen ) {
+ // When the fullscreen mode is changed, trigger the
+ // fullscreen events (and when exiting,
+ // also remove the fullscreen class)
+ $( document ).on( 'fullscreenchange webkitfullscreenchange mozfullscreenchange MSFullscreenChange', handleFullscreenChange);
+ // Convenience wrapper so that one only needs to listen for
+ // 'fullscreenerror', not all of the prefixed versions
+ $( document ).on( 'webkitfullscreenerror mozfullscreenerror MSFullscreenError', function () {
+ $( document ).trigger( $.Event( 'fullscreenerror' ) );
+ } );
+ // Fullscreen has been set up, so always return true
+ setupFullscreen = function () { return true; };
+ return true;
+ } else {
+ // Always return false from now on, since fullscreen is not supported
+ setupFullscreen = function () { return false; };
+ return false;
+ }
+ };
+
+ /**
+ * Set up fullscreen handling if necessary, then make the first element
+ * matching the given selector fullscreen
+ * @chainable
+ * @return {jQuery}
+ */
+ $.fn.enterFullscreen = function () {
+ if ( setupFullscreen() ) {
+ $.fn.enterFullscreen = enterFullscreen;
+ return this.enterFullscreen();
+ } else {
+ $.fn.enterFullscreen = function () { return this; };
+ return this;
+ }
+ };
+
+ /**
+ * Set up fullscreen handling if necessary, then cancel fullscreen mode
+ * for the first element matching the given selector.
+ * @chainable
+ * @return {jQuery}
+ */
+ $.fn.exitFullscreen = function () {
+ if ( setupFullscreen() ) {
+ $.fn.exitFullscreen = exitFullscreen;
+ return this.exitFullscreen();
+ } else {
+ $.fn.exitFullscreen = function () { return this; };
+ return this;
+ }
+ };
+
+ $.support.fullscreen = document.fullscreenEnabled ||
+ document.webkitFullscreenEnabled ||
+ document.mozFullScreenEnabled ||
+ document.msFullscreenEnabled;
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/jquery/jquery.hoverIntent.js b/www/wiki/resources/lib/jquery/jquery.hoverIntent.js
new file mode 100644
index 00000000..adf948df
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.hoverIntent.js
@@ -0,0 +1,111 @@
+/**
+* hoverIntent is similar to jQuery's built-in "hover" function except that
+* instead of firing the onMouseOver event immediately, hoverIntent checks
+* to see if the user's mouse has slowed down (beneath the sensitivity
+* threshold) before firing the onMouseOver event.
+*
+* hoverIntent r5 // 2007.03.27 // jQuery 1.1.2+
+* <http://cherne.net/brian/resources/jquery.hoverIntent.html>
+*
+* hoverIntent is currently available for use in all personal or commercial
+* projects under both MIT and GPL licenses. This means that you can choose
+* the license that best suits your project, and use it accordingly.
+*
+* // basic usage (just like .hover) receives onMouseOver and onMouseOut functions
+* $("ul li").hoverIntent( showNav , hideNav );
+*
+* // advanced usage receives configuration object only
+* $("ul li").hoverIntent({
+* sensitivity: 7, // number = sensitivity threshold (must be 1 or higher)
+* interval: 100, // number = milliseconds of polling interval
+* over: showNav, // function = onMouseOver callback (required)
+* timeout: 0, // number = milliseconds delay before onMouseOut function call
+* out: hideNav // function = onMouseOut callback (required)
+* });
+*
+* @param f onMouseOver function || An object with configuration options
+* @param g onMouseOut function || Nothing (use configuration options object)
+* @author Brian Cherne <brian@cherne.net>
+*/
+(function($) {
+ $.fn.hoverIntent = function(f,g) {
+ // default configuration options
+ var cfg = {
+ sensitivity: 7,
+ interval: 100,
+ timeout: 0
+ };
+ // override configuration options with user supplied object
+ cfg = $.extend(cfg, g ? { over: f, out: g } : f );
+
+ // instantiate variables
+ // cX, cY = current X and Y position of mouse, updated by mousemove event
+ // pX, pY = previous X and Y position of mouse, set by mouseover and polling interval
+ var cX, cY, pX, pY;
+
+ // A private function for getting mouse position
+ var track = function(ev) {
+ cX = ev.pageX;
+ cY = ev.pageY;
+ };
+
+ // A private function for comparing current and previous mouse position
+ var compare = function(ev,ob) {
+ ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
+ // compare mouse positions to see if they've crossed the threshold
+ if ( ( Math.abs(pX-cX) + Math.abs(pY-cY) ) < cfg.sensitivity ) {
+ $(ob).unbind("mousemove",track);
+ // set hoverIntent state to true (so mouseOut can be called)
+ ob.hoverIntent_s = 1;
+ return cfg.over.apply(ob,[ev]);
+ } else {
+ // set previous coordinates for next time
+ pX = cX; pY = cY;
+ // use self-calling timeout, guarantees intervals are spaced out properly (avoids JavaScript timer bugs)
+ ob.hoverIntent_t = setTimeout( function(){compare(ev, ob);} , cfg.interval );
+ }
+ };
+
+ // A private function for delaying the mouseOut function
+ var delay = function(ev,ob) {
+ ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t);
+ ob.hoverIntent_s = 0;
+ return cfg.out.apply(ob,[ev]);
+ };
+
+ // A private function for handling mouse 'hovering'
+ var handleHover = function(e) {
+ // next three lines copied from jQuery.hover, ignore children onMouseOver/onMouseOut
+ var p = (e.type == "mouseover" ? e.fromElement : e.toElement) || e.relatedTarget;
+ while ( p && p != this ) { try { p = p.parentNode; } catch(e) { p = this; } }
+ if ( p == this ) { return false; }
+
+ // copy objects to be passed into t (required for event object to be passed in IE)
+ var ev = $.extend({},e);
+ var ob = this;
+
+ // cancel hoverIntent timer if it exists
+ if (ob.hoverIntent_t) { ob.hoverIntent_t = clearTimeout(ob.hoverIntent_t); }
+
+ // else e.type == "onmouseover"
+ if (e.type == "mouseover") {
+ // set "previous" X and Y position based on initial entry point
+ pX = ev.pageX; pY = ev.pageY;
+ // update "current" X and Y position based on mousemove
+ $(ob).bind("mousemove",track);
+ // start polling interval (self-calling timeout) to compare mouse coordinates over time
+ if (ob.hoverIntent_s != 1) { ob.hoverIntent_t = setTimeout( function(){compare(ev,ob);} , cfg.interval );}
+
+ // else e.type == "onmouseout"
+ } else {
+ // unbind expensive mousemove event
+ $(ob).unbind("mousemove",track);
+ // if hoverIntent state is true, then call the mouseOut function after the specified delay
+ if (ob.hoverIntent_s == 1) { ob.hoverIntent_t = setTimeout( function(){delay(ev,ob);} , cfg.timeout );}
+ }
+ };
+
+ // bind the function to the two event listeners
+ return this.mouseover(handleHover).mouseout(handleHover);
+ };
+})(jQuery); \ No newline at end of file
diff --git a/www/wiki/resources/lib/jquery/jquery.jStorage.js b/www/wiki/resources/lib/jquery/jquery.jStorage.js
new file mode 100644
index 00000000..45e19ac6
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.jStorage.js
@@ -0,0 +1,996 @@
+/*
+ * ----------------------------- JSTORAGE -------------------------------------
+ * Simple local storage wrapper to save data on the browser side, supporting
+ * all major browsers - IE6+, Firefox2+, Safari4+, Chrome4+ and Opera 10.5+
+ *
+ * Author: Andris Reinman, andris.reinman@gmail.com
+ * Project homepage: www.jstorage.info
+ *
+ * Licensed under Unlicense:
+ *
+ * This is free and unencumbered software released into the public domain.
+ *
+ * Anyone is free to copy, modify, publish, use, compile, sell, or
+ * distribute this software, either in source code form or as a compiled
+ * binary, for any purpose, commercial or non-commercial, and by any
+ * means.
+ *
+ * In jurisdictions that recognize copyright laws, the author or authors
+ * of this software dedicate any and all copyright interest in the
+ * software to the public domain. We make this dedication for the benefit
+ * of the public at large and to the detriment of our heirs and
+ * successors. We intend this dedication to be an overt act of
+ * relinquishment in perpetuity of all present and future rights to this
+ * software under copyright law.
+ *
+ * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * For more information, please refer to <http://unlicense.org/>
+ */
+
+/* global ActiveXObject: false */
+/* jshint browser: true */
+
+(function() {
+ 'use strict';
+
+ var
+ /* jStorage version */
+ JSTORAGE_VERSION = '0.4.12',
+
+ /* detect a dollar object or create one if not found */
+ $ = window.jQuery || window.$ || (window.$ = {}),
+
+ /* check for a JSON handling support */
+ JSON = {
+ parse: window.JSON && (window.JSON.parse || window.JSON.decode) ||
+ String.prototype.evalJSON && function(str) {
+ return String(str).evalJSON();
+ } ||
+ $.parseJSON ||
+ $.evalJSON,
+ stringify: Object.toJSON ||
+ window.JSON && (window.JSON.stringify || window.JSON.encode) ||
+ $.toJSON
+ };
+
+ // Break if no JSON support was found
+ if (typeof JSON.parse !== 'function' || typeof JSON.stringify !== 'function') {
+ throw new Error('No JSON support found, include //cdnjs.cloudflare.com/ajax/libs/json2/20110223/json2.js to page');
+ }
+
+ var
+ /* This is the object, that holds the cached values */
+ _storage = {
+ __jstorage_meta: {
+ CRC32: {}
+ }
+ },
+
+ /* Actual browser storage (localStorage or globalStorage['domain']) */
+ _storage_service = {
+ jStorage: '{}'
+ },
+
+ /* DOM element for older IE versions, holds userData behavior */
+ _storage_elm = null,
+
+ /* How much space does the storage take */
+ _storage_size = 0,
+
+ /* which backend is currently used */
+ _backend = false,
+
+ /* onchange observers */
+ _observers = {},
+
+ /* timeout to wait after onchange event */
+ _observer_timeout = false,
+
+ /* last update time */
+ _observer_update = 0,
+
+ /* pubsub observers */
+ _pubsub_observers = {},
+
+ /* skip published items older than current timestamp */
+ _pubsub_last = +new Date(),
+
+ /* Next check for TTL */
+ _ttl_timeout,
+
+ /**
+ * XML encoding and decoding as XML nodes can't be JSON'ized
+ * XML nodes are encoded and decoded if the node is the value to be saved
+ * but not if it's as a property of another object
+ * Eg. -
+ * $.jStorage.set('key', xmlNode); // IS OK
+ * $.jStorage.set('key', {xml: xmlNode}); // NOT OK
+ */
+ _XMLService = {
+
+ /**
+ * Validates a XML node to be XML
+ * based on jQuery.isXML function
+ */
+ isXML: function(elm) {
+ var documentElement = (elm ? elm.ownerDocument || elm : 0).documentElement;
+ return documentElement ? documentElement.nodeName !== 'HTML' : false;
+ },
+
+ /**
+ * Encodes a XML node to string
+ * based on http://www.mercurytide.co.uk/news/article/issues-when-working-ajax/
+ */
+ encode: function(xmlNode) {
+ if (!this.isXML(xmlNode)) {
+ return false;
+ }
+ try { // Mozilla, Webkit, Opera
+ return new XMLSerializer().serializeToString(xmlNode);
+ } catch (E1) {
+ try { // IE
+ return xmlNode.xml;
+ } catch (E2) {}
+ }
+ return false;
+ },
+
+ /**
+ * Decodes a XML node from string
+ * loosely based on http://outwestmedia.com/jquery-plugins/xmldom/
+ */
+ decode: function(xmlString) {
+ var dom_parser = ('DOMParser' in window && (new DOMParser()).parseFromString) ||
+ (window.ActiveXObject && function(_xmlString) {
+ var xml_doc = new ActiveXObject('Microsoft.XMLDOM');
+ xml_doc.async = 'false';
+ xml_doc.loadXML(_xmlString);
+ return xml_doc;
+ }),
+ resultXML;
+ if (!dom_parser) {
+ return false;
+ }
+ resultXML = dom_parser.call('DOMParser' in window && (new DOMParser()) || window, xmlString, 'text/xml');
+ return this.isXML(resultXML) ? resultXML : false;
+ }
+ };
+
+
+ ////////////////////////// PRIVATE METHODS ////////////////////////
+
+ /**
+ * Initialization function. Detects if the browser supports DOM Storage
+ * or userData behavior and behaves accordingly.
+ */
+ function _init() {
+ /* Check if browser supports localStorage */
+ var localStorageReallyWorks = false;
+ if ('localStorage' in window) {
+ try {
+ window.localStorage.setItem('_tmptest', 'tmpval');
+ localStorageReallyWorks = true;
+ window.localStorage.removeItem('_tmptest');
+ } catch (BogusQuotaExceededErrorOnIos5) {
+ // Thanks be to iOS5 Private Browsing mode which throws
+ // QUOTA_EXCEEDED_ERRROR DOM Exception 22.
+ }
+ }
+
+ if (localStorageReallyWorks) {
+ try {
+ if (window.localStorage) {
+ _storage_service = window.localStorage;
+ _backend = 'localStorage';
+ _observer_update = _storage_service.jStorage_update;
+ }
+ } catch (E3) { /* Firefox fails when touching localStorage and cookies are disabled */ }
+ }
+ /* Check if browser supports globalStorage */
+ else if ('globalStorage' in window) {
+ try {
+ if (window.globalStorage) {
+ if (window.location.hostname == 'localhost') {
+ _storage_service = window.globalStorage['localhost.localdomain'];
+ } else {
+ _storage_service = window.globalStorage[window.location.hostname];
+ }
+ _backend = 'globalStorage';
+ _observer_update = _storage_service.jStorage_update;
+ }
+ } catch (E4) { /* Firefox fails when touching localStorage and cookies are disabled */ }
+ }
+ /* Check if browser supports userData behavior */
+ else {
+ _storage_elm = document.createElement('link');
+ if (_storage_elm.addBehavior) {
+
+ /* Use a DOM element to act as userData storage */
+ _storage_elm.style.behavior = 'url(#default#userData)';
+
+ /* userData element needs to be inserted into the DOM! */
+ document.getElementsByTagName('head')[0].appendChild(_storage_elm);
+
+ try {
+ _storage_elm.load('jStorage');
+ } catch (E) {
+ // try to reset cache
+ _storage_elm.setAttribute('jStorage', '{}');
+ _storage_elm.save('jStorage');
+ _storage_elm.load('jStorage');
+ }
+
+ var data = '{}';
+ try {
+ data = _storage_elm.getAttribute('jStorage');
+ } catch (E5) {}
+
+ try {
+ _observer_update = _storage_elm.getAttribute('jStorage_update');
+ } catch (E6) {}
+
+ _storage_service.jStorage = data;
+ _backend = 'userDataBehavior';
+ } else {
+ _storage_elm = null;
+ return;
+ }
+ }
+
+ // Load data from storage
+ _load_storage();
+
+ // remove dead keys
+ _handleTTL();
+
+ // start listening for changes
+ _setupObserver();
+
+ // initialize publish-subscribe service
+ _handlePubSub();
+
+ // handle cached navigation
+ if ('addEventListener' in window) {
+ window.addEventListener('pageshow', function(event) {
+ if (event.persisted) {
+ _storageObserver();
+ }
+ }, false);
+ }
+ }
+
+ /**
+ * Reload data from storage when needed
+ */
+ function _reloadData() {
+ var data = '{}';
+
+ if (_backend == 'userDataBehavior') {
+ _storage_elm.load('jStorage');
+
+ try {
+ data = _storage_elm.getAttribute('jStorage');
+ } catch (E5) {}
+
+ try {
+ _observer_update = _storage_elm.getAttribute('jStorage_update');
+ } catch (E6) {}
+
+ _storage_service.jStorage = data;
+ }
+
+ _load_storage();
+
+ // remove dead keys
+ _handleTTL();
+
+ _handlePubSub();
+ }
+
+ /**
+ * Sets up a storage change observer
+ */
+ function _setupObserver() {
+ if (_backend == 'localStorage' || _backend == 'globalStorage') {
+ if ('addEventListener' in window) {
+ window.addEventListener('storage', _storageObserver, false);
+ } else {
+ document.attachEvent('onstorage', _storageObserver);
+ }
+ } else if (_backend == 'userDataBehavior') {
+ setInterval(_storageObserver, 1000);
+ }
+ }
+
+ /**
+ * Fired on any kind of data change, needs to check if anything has
+ * really been changed
+ */
+ function _storageObserver() {
+ var updateTime;
+ // cumulate change notifications with timeout
+ clearTimeout(_observer_timeout);
+ _observer_timeout = setTimeout(function() {
+
+ if (_backend == 'localStorage' || _backend == 'globalStorage') {
+ updateTime = _storage_service.jStorage_update;
+ } else if (_backend == 'userDataBehavior') {
+ _storage_elm.load('jStorage');
+ try {
+ updateTime = _storage_elm.getAttribute('jStorage_update');
+ } catch (E5) {}
+ }
+
+ if (updateTime && updateTime != _observer_update) {
+ _observer_update = updateTime;
+ _checkUpdatedKeys();
+ }
+
+ }, 25);
+ }
+
+ /**
+ * Reloads the data and checks if any keys are changed
+ */
+ function _checkUpdatedKeys() {
+ var oldCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32)),
+ newCrc32List;
+
+ _reloadData();
+ newCrc32List = JSON.parse(JSON.stringify(_storage.__jstorage_meta.CRC32));
+
+ var key,
+ updated = [],
+ removed = [];
+
+ for (key in oldCrc32List) {
+ if (oldCrc32List.hasOwnProperty(key)) {
+ if (!newCrc32List[key]) {
+ removed.push(key);
+ continue;
+ }
+ if (oldCrc32List[key] != newCrc32List[key] && String(oldCrc32List[key]).substr(0, 2) == '2.') {
+ updated.push(key);
+ }
+ }
+ }
+
+ for (key in newCrc32List) {
+ if (newCrc32List.hasOwnProperty(key)) {
+ if (!oldCrc32List[key]) {
+ updated.push(key);
+ }
+ }
+ }
+
+ _fireObservers(updated, 'updated');
+ _fireObservers(removed, 'deleted');
+ }
+
+ /**
+ * Fires observers for updated keys
+ *
+ * @param {Array|String} keys Array of key names or a key
+ * @param {String} action What happened with the value (updated, deleted, flushed)
+ */
+ function _fireObservers(keys, action) {
+ keys = [].concat(keys || []);
+
+ var i, j, len, jlen;
+
+ if (action == 'flushed') {
+ keys = [];
+ for (var key in _observers) {
+ if (_observers.hasOwnProperty(key)) {
+ keys.push(key);
+ }
+ }
+ action = 'deleted';
+ }
+ for (i = 0, len = keys.length; i < len; i++) {
+ if (_observers[keys[i]]) {
+ for (j = 0, jlen = _observers[keys[i]].length; j < jlen; j++) {
+ _observers[keys[i]][j](keys[i], action);
+ }
+ }
+ if (_observers['*']) {
+ for (j = 0, jlen = _observers['*'].length; j < jlen; j++) {
+ _observers['*'][j](keys[i], action);
+ }
+ }
+ }
+ }
+
+ /**
+ * Publishes key change to listeners
+ */
+ function _publishChange() {
+ var updateTime = (+new Date()).toString();
+
+ if (_backend == 'localStorage' || _backend == 'globalStorage') {
+ try {
+ _storage_service.jStorage_update = updateTime;
+ } catch (E8) {
+ // safari private mode has been enabled after the jStorage initialization
+ _backend = false;
+ }
+ } else if (_backend == 'userDataBehavior') {
+ _storage_elm.setAttribute('jStorage_update', updateTime);
+ _storage_elm.save('jStorage');
+ }
+
+ _storageObserver();
+ }
+
+ /**
+ * Loads the data from the storage based on the supported mechanism
+ */
+ function _load_storage() {
+ /* if jStorage string is retrieved, then decode it */
+ if (_storage_service.jStorage) {
+ try {
+ _storage = JSON.parse(String(_storage_service.jStorage));
+ } catch (E6) {
+ _storage_service.jStorage = '{}';
+ }
+ } else {
+ _storage_service.jStorage = '{}';
+ }
+ _storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0;
+
+ if (!_storage.__jstorage_meta) {
+ _storage.__jstorage_meta = {};
+ }
+ if (!_storage.__jstorage_meta.CRC32) {
+ _storage.__jstorage_meta.CRC32 = {};
+ }
+ }
+
+ /**
+ * This functions provides the 'save' mechanism to store the jStorage object
+ */
+ function _save() {
+ _dropOldEvents(); // remove expired events
+ try {
+ _storage_service.jStorage = JSON.stringify(_storage);
+ // If userData is used as the storage engine, additional
+ if (_storage_elm) {
+ _storage_elm.setAttribute('jStorage', _storage_service.jStorage);
+ _storage_elm.save('jStorage');
+ }
+ _storage_size = _storage_service.jStorage ? String(_storage_service.jStorage).length : 0;
+ } catch (E7) { /* probably cache is full, nothing is saved this way*/ }
+ }
+
+ /**
+ * Function checks if a key is set and is string or numberic
+ *
+ * @param {String} key Key name
+ */
+ function _checkKey(key) {
+ if (typeof key != 'string' && typeof key != 'number') {
+ throw new TypeError('Key name must be string or numeric');
+ }
+ if (key == '__jstorage_meta') {
+ throw new TypeError('Reserved key name');
+ }
+ return true;
+ }
+
+ /**
+ * Removes expired keys
+ */
+ function _handleTTL() {
+ var curtime, i, TTL, CRC32, nextExpire = Infinity,
+ changed = false,
+ deleted = [];
+
+ clearTimeout(_ttl_timeout);
+
+ if (!_storage.__jstorage_meta || typeof _storage.__jstorage_meta.TTL != 'object') {
+ // nothing to do here
+ return;
+ }
+
+ curtime = +new Date();
+ TTL = _storage.__jstorage_meta.TTL;
+
+ CRC32 = _storage.__jstorage_meta.CRC32;
+ for (i in TTL) {
+ if (TTL.hasOwnProperty(i)) {
+ if (TTL[i] <= curtime) {
+ delete TTL[i];
+ delete CRC32[i];
+ delete _storage[i];
+ changed = true;
+ deleted.push(i);
+ } else if (TTL[i] < nextExpire) {
+ nextExpire = TTL[i];
+ }
+ }
+ }
+
+ // set next check
+ if (nextExpire != Infinity) {
+ _ttl_timeout = setTimeout(_handleTTL, Math.min(nextExpire - curtime, 0x7FFFFFFF));
+ }
+
+ // save changes
+ if (changed) {
+ _save();
+ _publishChange();
+ _fireObservers(deleted, 'deleted');
+ }
+ }
+
+ /**
+ * Checks if there's any events on hold to be fired to listeners
+ */
+ function _handlePubSub() {
+ var i, len;
+ if (!_storage.__jstorage_meta.PubSub) {
+ return;
+ }
+ var pubelm,
+ _pubsubCurrent = _pubsub_last,
+ needFired = [];
+
+ for (i = len = _storage.__jstorage_meta.PubSub.length - 1; i >= 0; i--) {
+ pubelm = _storage.__jstorage_meta.PubSub[i];
+ if (pubelm[0] > _pubsub_last) {
+ _pubsubCurrent = pubelm[0];
+ needFired.unshift(pubelm);
+ }
+ }
+
+ for (i = needFired.length - 1; i >= 0; i--) {
+ _fireSubscribers(needFired[i][1], needFired[i][2]);
+ }
+
+ _pubsub_last = _pubsubCurrent;
+ }
+
+ /**
+ * Fires all subscriber listeners for a pubsub channel
+ *
+ * @param {String} channel Channel name
+ * @param {Mixed} payload Payload data to deliver
+ */
+ function _fireSubscribers(channel, payload) {
+ if (_pubsub_observers[channel]) {
+ for (var i = 0, len = _pubsub_observers[channel].length; i < len; i++) {
+ // send immutable data that can't be modified by listeners
+ try {
+ _pubsub_observers[channel][i](channel, JSON.parse(JSON.stringify(payload)));
+ } catch (E) {}
+ }
+ }
+ }
+
+ /**
+ * Remove old events from the publish stream (at least 2sec old)
+ */
+ function _dropOldEvents() {
+ if (!_storage.__jstorage_meta.PubSub) {
+ return;
+ }
+
+ var retire = +new Date() - 2000;
+
+ for (var i = 0, len = _storage.__jstorage_meta.PubSub.length; i < len; i++) {
+ if (_storage.__jstorage_meta.PubSub[i][0] <= retire) {
+ // deleteCount is needed for IE6
+ _storage.__jstorage_meta.PubSub.splice(i, _storage.__jstorage_meta.PubSub.length - i);
+ break;
+ }
+ }
+
+ if (!_storage.__jstorage_meta.PubSub.length) {
+ delete _storage.__jstorage_meta.PubSub;
+ }
+
+ }
+
+ /**
+ * Publish payload to a channel
+ *
+ * @param {String} channel Channel name
+ * @param {Mixed} payload Payload to send to the subscribers
+ */
+ function _publish(channel, payload) {
+ if (!_storage.__jstorage_meta) {
+ _storage.__jstorage_meta = {};
+ }
+ if (!_storage.__jstorage_meta.PubSub) {
+ _storage.__jstorage_meta.PubSub = [];
+ }
+
+ _storage.__jstorage_meta.PubSub.unshift([+new Date(), channel, payload]);
+
+ _save();
+ _publishChange();
+ }
+
+
+ /**
+ * JS Implementation of MurmurHash2
+ *
+ * SOURCE: https://github.com/garycourt/murmurhash-js (MIT licensed)
+ *
+ * @author <a href='mailto:gary.court@gmail.com'>Gary Court</a>
+ * @see http://github.com/garycourt/murmurhash-js
+ * @author <a href='mailto:aappleby@gmail.com'>Austin Appleby</a>
+ * @see http://sites.google.com/site/murmurhash/
+ *
+ * @param {string} str ASCII only
+ * @param {number} seed Positive integer only
+ * @return {number} 32-bit positive integer hash
+ */
+
+ function murmurhash2_32_gc(str, seed) {
+ var
+ l = str.length,
+ h = seed ^ l,
+ i = 0,
+ k;
+
+ while (l >= 4) {
+ k =
+ ((str.charCodeAt(i) & 0xff)) |
+ ((str.charCodeAt(++i) & 0xff) << 8) |
+ ((str.charCodeAt(++i) & 0xff) << 16) |
+ ((str.charCodeAt(++i) & 0xff) << 24);
+
+ k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
+ k ^= k >>> 24;
+ k = (((k & 0xffff) * 0x5bd1e995) + ((((k >>> 16) * 0x5bd1e995) & 0xffff) << 16));
+
+ h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16)) ^ k;
+
+ l -= 4;
+ ++i;
+ }
+
+ switch (l) {
+ case 3:
+ h ^= (str.charCodeAt(i + 2) & 0xff) << 16;
+ /* falls through */
+ case 2:
+ h ^= (str.charCodeAt(i + 1) & 0xff) << 8;
+ /* falls through */
+ case 1:
+ h ^= (str.charCodeAt(i) & 0xff);
+ h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
+ }
+
+ h ^= h >>> 13;
+ h = (((h & 0xffff) * 0x5bd1e995) + ((((h >>> 16) * 0x5bd1e995) & 0xffff) << 16));
+ h ^= h >>> 15;
+
+ return h >>> 0;
+ }
+
+ ////////////////////////// PUBLIC INTERFACE /////////////////////////
+
+ $.jStorage = {
+ /* Version number */
+ version: JSTORAGE_VERSION,
+
+ /**
+ * Sets a key's value.
+ *
+ * @param {String} key Key to set. If this value is not set or not
+ * a string an exception is raised.
+ * @param {Mixed} value Value to set. This can be any value that is JSON
+ * compatible (Numbers, Strings, Objects etc.).
+ * @param {Object} [options] - possible options to use
+ * @param {Number} [options.TTL] - optional TTL value, in milliseconds
+ * @return {Mixed} the used value
+ */
+ set: function(key, value, options) {
+ _checkKey(key);
+
+ options = options || {};
+
+ // undefined values are deleted automatically
+ if (typeof value == 'undefined') {
+ this.deleteKey(key);
+ return value;
+ }
+
+ if (_XMLService.isXML(value)) {
+ value = {
+ _is_xml: true,
+ xml: _XMLService.encode(value)
+ };
+ } else if (typeof value == 'function') {
+ return undefined; // functions can't be saved!
+ } else if (value && typeof value == 'object') {
+ // clone the object before saving to _storage tree
+ value = JSON.parse(JSON.stringify(value));
+ }
+
+ _storage[key] = value;
+
+ _storage.__jstorage_meta.CRC32[key] = '2.' + murmurhash2_32_gc(JSON.stringify(value), 0x9747b28c);
+
+ this.setTTL(key, options.TTL || 0); // also handles saving and _publishChange
+
+ _fireObservers(key, 'updated');
+ return value;
+ },
+
+ /**
+ * Looks up a key in cache
+ *
+ * @param {String} key - Key to look up.
+ * @param {mixed} def - Default value to return, if key didn't exist.
+ * @return {Mixed} the key value, default value or null
+ */
+ get: function(key, def) {
+ _checkKey(key);
+ if (key in _storage) {
+ if (_storage[key] && typeof _storage[key] == 'object' && _storage[key]._is_xml) {
+ return _XMLService.decode(_storage[key].xml);
+ } else {
+ return _storage[key];
+ }
+ }
+ return typeof(def) == 'undefined' ? null : def;
+ },
+
+ /**
+ * Deletes a key from cache.
+ *
+ * @param {String} key - Key to delete.
+ * @return {Boolean} true if key existed or false if it didn't
+ */
+ deleteKey: function(key) {
+ _checkKey(key);
+ if (key in _storage) {
+ delete _storage[key];
+ // remove from TTL list
+ if (typeof _storage.__jstorage_meta.TTL == 'object' &&
+ key in _storage.__jstorage_meta.TTL) {
+ delete _storage.__jstorage_meta.TTL[key];
+ }
+
+ delete _storage.__jstorage_meta.CRC32[key];
+
+ _save();
+ _publishChange();
+ _fireObservers(key, 'deleted');
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Sets a TTL for a key, or remove it if ttl value is 0 or below
+ *
+ * @param {String} key - key to set the TTL for
+ * @param {Number} ttl - TTL timeout in milliseconds
+ * @return {Boolean} true if key existed or false if it didn't
+ */
+ setTTL: function(key, ttl) {
+ var curtime = +new Date();
+ _checkKey(key);
+ ttl = Number(ttl) || 0;
+ if (key in _storage) {
+
+ if (!_storage.__jstorage_meta.TTL) {
+ _storage.__jstorage_meta.TTL = {};
+ }
+
+ // Set TTL value for the key
+ if (ttl > 0) {
+ _storage.__jstorage_meta.TTL[key] = curtime + ttl;
+ } else {
+ delete _storage.__jstorage_meta.TTL[key];
+ }
+
+ _save();
+
+ _handleTTL();
+
+ _publishChange();
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Gets remaining TTL (in milliseconds) for a key or 0 when no TTL has been set
+ *
+ * @param {String} key Key to check
+ * @return {Number} Remaining TTL in milliseconds
+ */
+ getTTL: function(key) {
+ var curtime = +new Date(),
+ ttl;
+ _checkKey(key);
+ if (key in _storage && _storage.__jstorage_meta.TTL && _storage.__jstorage_meta.TTL[key]) {
+ ttl = _storage.__jstorage_meta.TTL[key] - curtime;
+ return ttl || 0;
+ }
+ return 0;
+ },
+
+ /**
+ * Deletes everything in cache.
+ *
+ * @return {Boolean} Always true
+ */
+ flush: function() {
+ _storage = {
+ __jstorage_meta: {
+ CRC32: {}
+ }
+ };
+ _save();
+ _publishChange();
+ _fireObservers(null, 'flushed');
+ return true;
+ },
+
+ /**
+ * Returns a read-only copy of _storage
+ *
+ * @return {Object} Read-only copy of _storage
+ */
+ storageObj: function() {
+ function F() {}
+ F.prototype = _storage;
+ return new F();
+ },
+
+ /**
+ * Returns an index of all used keys as an array
+ * ['key1', 'key2',..'keyN']
+ *
+ * @return {Array} Used keys
+ */
+ index: function() {
+ var index = [],
+ i;
+ for (i in _storage) {
+ if (_storage.hasOwnProperty(i) && i != '__jstorage_meta') {
+ index.push(i);
+ }
+ }
+ return index;
+ },
+
+ /**
+ * How much space in bytes does the storage take?
+ *
+ * @return {Number} Storage size in chars (not the same as in bytes,
+ * since some chars may take several bytes)
+ */
+ storageSize: function() {
+ return _storage_size;
+ },
+
+ /**
+ * Which backend is currently in use?
+ *
+ * @return {String} Backend name
+ */
+ currentBackend: function() {
+ return _backend;
+ },
+
+ /**
+ * Test if storage is available
+ *
+ * @return {Boolean} True if storage can be used
+ */
+ storageAvailable: function() {
+ return !!_backend;
+ },
+
+ /**
+ * Register change listeners
+ *
+ * @param {String} key Key name
+ * @param {Function} callback Function to run when the key changes
+ */
+ listenKeyChange: function(key, callback) {
+ _checkKey(key);
+ if (!_observers[key]) {
+ _observers[key] = [];
+ }
+ _observers[key].push(callback);
+ },
+
+ /**
+ * Remove change listeners
+ *
+ * @param {String} key Key name to unregister listeners against
+ * @param {Function} [callback] If set, unregister the callback, if not - unregister all
+ */
+ stopListening: function(key, callback) {
+ _checkKey(key);
+
+ if (!_observers[key]) {
+ return;
+ }
+
+ if (!callback) {
+ delete _observers[key];
+ return;
+ }
+
+ for (var i = _observers[key].length - 1; i >= 0; i--) {
+ if (_observers[key][i] == callback) {
+ _observers[key].splice(i, 1);
+ }
+ }
+ },
+
+ /**
+ * Subscribe to a Publish/Subscribe event stream
+ *
+ * @param {String} channel Channel name
+ * @param {Function} callback Function to run when the something is published to the channel
+ */
+ subscribe: function(channel, callback) {
+ channel = (channel || '').toString();
+ if (!channel) {
+ throw new TypeError('Channel not defined');
+ }
+ if (!_pubsub_observers[channel]) {
+ _pubsub_observers[channel] = [];
+ }
+ _pubsub_observers[channel].push(callback);
+ },
+
+ /**
+ * Publish data to an event stream
+ *
+ * @param {String} channel Channel name
+ * @param {Mixed} payload Payload to deliver
+ */
+ publish: function(channel, payload) {
+ channel = (channel || '').toString();
+ if (!channel) {
+ throw new TypeError('Channel not defined');
+ }
+
+ _publish(channel, payload);
+ },
+
+ /**
+ * Reloads the data from browser storage
+ */
+ reInit: function() {
+ _reloadData();
+ },
+
+ /**
+ * Removes reference from global objects and saves it as jStorage
+ *
+ * @param {Boolean} option if needed to save object as simple 'jStorage' in windows context
+ */
+ noConflict: function(saveInGlobal) {
+ delete window.$.jStorage;
+
+ if (saveInGlobal) {
+ window.jStorage = this;
+ }
+
+ return this;
+ }
+ };
+
+ // Initialize jStorage
+ _init();
+
+})();
diff --git a/www/wiki/resources/lib/jquery/jquery.js b/www/wiki/resources/lib/jquery/jquery.js
new file mode 100644
index 00000000..6feb1108
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.js
@@ -0,0 +1,10351 @@
+/*!
+ * jQuery JavaScript Library v1.11.3
+ * http://jquery.com/
+ *
+ * Includes Sizzle.js
+ * http://sizzlejs.com/
+ *
+ * Copyright 2005, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2015-04-28T16:19Z
+ */
+
+(function( global, factory ) {
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+ // For CommonJS and CommonJS-like environments where a proper window is present,
+ // execute the factory and get jQuery
+ // For environments that do not inherently posses a window with a document
+ // (such as Node.js), expose a jQuery-making factory as module.exports
+ // This accentuates the need for the creation of a real window
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket #14549 for more info
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+// Pass this if window is not defined yet
+}(typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Can't do this because several apps including ASP.NET trace
+// the stack via arguments.caller.callee and Firefox dies if
+// you try to trace through "use strict" call chains. (#13335)
+// Support: Firefox 18+
+//
+
+var deletedIds = [];
+
+var slice = deletedIds.slice;
+
+var concat = deletedIds.concat;
+
+var push = deletedIds.push;
+
+var indexOf = deletedIds.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var support = {};
+
+
+
+var
+ version = "1.11.3",
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+ // The jQuery object is actually just the init constructor 'enhanced'
+ // Need init if jQuery is called (just allow error to be thrown if not included)
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // Support: Android<4.1, IE<9
+ // Make sure we trim BOM and NBSP
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([\da-z])/gi,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ };
+
+jQuery.fn = jQuery.prototype = {
+ // The current version of jQuery being used
+ jquery: version,
+
+ constructor: jQuery,
+
+ // Start with an empty selector
+ selector: "",
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ toArray: function() {
+ return slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+ return num != null ?
+
+ // Return just the one element from the set
+ ( num < 0 ? this[ num + this.length ] : this[ num ] ) :
+
+ // Return all the elements in a clean array
+ slice.call( this );
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+ ret.context = this.context;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ // (You can seed the arguments with an array of args, but this is
+ // only used internally.)
+ each: function( callback, args ) {
+ return jQuery.each( this, callback, args );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map(this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ }));
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[j] ] : [] );
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor(null);
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: deletedIds.sort,
+ splice: deletedIds.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var src, copyIsArray, copy, name, options, clone,
+ target = arguments[0] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+
+ // skip the boolean and the target
+ target = arguments[ i ] || {};
+ i++;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
+ target = {};
+ }
+
+ // extend jQuery itself if only one argument is passed
+ if ( i === length ) {
+ target = this;
+ i--;
+ }
+
+ for ( ; i < length; i++ ) {
+ // Only deal with non-null/undefined values
+ if ( (options = arguments[ i ]) != null ) {
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && jQuery.isArray(src) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject(src) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend({
+ // Unique for each copy of jQuery on the page
+ expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+ // Assume jQuery is ready without the ready module
+ isReady: true,
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ noop: function() {},
+
+ // See test/unit/core.js for details concerning isFunction.
+ // Since version 1.3, DOM methods and functions like alert
+ // aren't supported. They return false on IE (#2968).
+ isFunction: function( obj ) {
+ return jQuery.type(obj) === "function";
+ },
+
+ isArray: Array.isArray || function( obj ) {
+ return jQuery.type(obj) === "array";
+ },
+
+ isWindow: function( obj ) {
+ /* jshint eqeqeq: false */
+ return obj != null && obj == obj.window;
+ },
+
+ isNumeric: function( obj ) {
+ // parseFloat NaNs numeric-cast false positives (null|true|false|"")
+ // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+ // subtraction forces infinities to NaN
+ // adding 1 corrects loss of precision from parseFloat (#15100)
+ return !jQuery.isArray( obj ) && (obj - parseFloat( obj ) + 1) >= 0;
+ },
+
+ isEmptyObject: function( obj ) {
+ var name;
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ isPlainObject: function( obj ) {
+ var key;
+
+ // Must be an Object.
+ // Because of IE, we also have to check the presence of the constructor property.
+ // Make sure that DOM nodes and window objects don't pass through, as well
+ if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ try {
+ // Not own constructor property must be Object
+ if ( obj.constructor &&
+ !hasOwn.call(obj, "constructor") &&
+ !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
+ return false;
+ }
+ } catch ( e ) {
+ // IE8,9 Will throw exceptions on certain host objects #9897
+ return false;
+ }
+
+ // Support: IE<9
+ // Handle iteration over inherited properties before own properties.
+ if ( support.ownLast ) {
+ for ( key in obj ) {
+ return hasOwn.call( obj, key );
+ }
+ }
+
+ // Own properties are enumerated firstly, so to speed up,
+ // if last one is own, then all properties are own.
+ for ( key in obj ) {}
+
+ return key === undefined || hasOwn.call( obj, key );
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return obj + "";
+ }
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ toString.call(obj) ] || "object" :
+ typeof obj;
+ },
+
+ // Evaluates a script in a global context
+ // Workarounds based on findings by Jim Driscoll
+ // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
+ globalEval: function( data ) {
+ if ( data && jQuery.trim( data ) ) {
+ // We use execScript on Internet Explorer
+ // We use an anonymous function so that context is window
+ // rather than jQuery in Firefox
+ ( window.execScript || function( data ) {
+ window[ "eval" ].call( window, data );
+ } )( data );
+ }
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ nodeName: function( elem, name ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+ },
+
+ // args is for internal usage only
+ each: function( obj, callback, args ) {
+ var value,
+ i = 0,
+ length = obj.length,
+ isArray = isArraylike( obj );
+
+ if ( args ) {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.apply( obj[ i ], args );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+
+ // A special, fast, case for the most common use of each
+ } else {
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ value = callback.call( obj[ i ], i, obj[ i ] );
+
+ if ( value === false ) {
+ break;
+ }
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Support: Android<4.1, IE<9
+ trim: function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArraylike( Object(arr) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ var len;
+
+ if ( arr ) {
+ if ( indexOf ) {
+ return indexOf.call( arr, elem, i );
+ }
+
+ len = arr.length;
+ i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;
+
+ for ( ; i < len; i++ ) {
+ // Skip accessing in sparse arrays
+ if ( i in arr && arr[ i ] === elem ) {
+ return i;
+ }
+ }
+ }
+
+ return -1;
+ },
+
+ merge: function( first, second ) {
+ var len = +second.length,
+ j = 0,
+ i = first.length;
+
+ while ( j < len ) {
+ first[ i++ ] = second[ j++ ];
+ }
+
+ // Support: IE<9
+ // Workaround casting of .length to NaN on otherwise arraylike objects (e.g., NodeLists)
+ if ( len !== len ) {
+ while ( second[j] !== undefined ) {
+ first[ i++ ] = second[ j++ ];
+ }
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, invert ) {
+ var callbackInverse,
+ matches = [],
+ i = 0,
+ length = elems.length,
+ callbackExpect = !invert;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ callbackInverse = !callback( elems[ i ], i );
+ if ( callbackInverse !== callbackExpect ) {
+ matches.push( elems[ i ] );
+ }
+ }
+
+ return matches;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var value,
+ i = 0,
+ length = elems.length,
+ isArray = isArraylike( elems ),
+ ret = [];
+
+ // Go through the array, translating each of the items to their new values
+ if ( isArray ) {
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var args, proxy, tmp;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ now: function() {
+ return +( new Date() );
+ },
+
+ // jQuery.support is not used in Core but other projects attach their
+ // properties to it so it needs to exist.
+ support: support
+});
+
+// Populate the class2type map
+jQuery.each("Boolean Number String Function Array Date RegExp Object Error".split(" "), function(i, name) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+});
+
+function isArraylike( obj ) {
+
+ // Support: iOS 8.2 (not reproducible in simulator)
+ // `in` check used to prevent JIT error (gh-2145)
+ // hasOwn isn't used here due to false negatives
+ // regarding Nodelist length in IE
+ var length = "length" in obj && obj.length,
+ type = jQuery.type( obj );
+
+ if ( type === "function" || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ if ( obj.nodeType === 1 && length ) {
+ return true;
+ }
+
+ return type === "array" || length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.2.0-pre
+ * http://sizzlejs.com/
+ *
+ * Copyright 2008, 2014 jQuery Foundation, Inc. and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2014-12-16
+ */
+(function( window ) {
+
+var i,
+ support,
+ Expr,
+ getText,
+ isXML,
+ tokenize,
+ compile,
+ select,
+ outermostContext,
+ sortInput,
+ hasDuplicate,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsHTML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+
+ // Instance-specific data
+ expando = "sizzle" + 1 * new Date(),
+ preferredDoc = window.document,
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ }
+ return 0;
+ },
+
+ // General-purpose constants
+ MAX_NEGATIVE = 1 << 31,
+
+ // Instance methods
+ hasOwn = ({}).hasOwnProperty,
+ arr = [],
+ pop = arr.pop,
+ push_native = arr.push,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf as it's faster than native
+ // http://jsperf.com/thor-indexof-vs-for/5
+ indexOf = function( list, elem ) {
+ var i = 0,
+ len = list.length;
+ for ( ; i < len; i++ ) {
+ if ( list[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+ // Regular expressions
+
+ // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+ // http://www.w3.org/TR/css3-syntax/#characters
+ characterEncoding = "(?:\\\\.|[\\w-]|[^\\x00-\\xa0])+",
+
+ // Loosely modeled on CSS identifier characters
+ // An unquoted value should be a CSS identifier http://www.w3.org/TR/css3-selectors/#attribute-selectors
+ // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = characterEncoding.replace( "w", "w#" ),
+
+ // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+ attributes = "\\[" + whitespace + "*(" + characterEncoding + ")(?:" + whitespace +
+ // Operator (capture 2)
+ "*([*^$|!~]?=)" + whitespace +
+ // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+ "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+ "*\\]",
+
+ pseudos = ":(" + characterEncoding + ")(?:\\((" +
+ // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+ // 1. quoted (capture 3; capture 4 or capture 5)
+ "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+ // 2. simple (capture 6)
+ "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+ // 3. anything else (capture 2)
+ ".*" +
+ ")\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rwhitespace = new RegExp( whitespace + "+", "g" ),
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+ rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + characterEncoding + ")" ),
+ "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ),
+ "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rnative = /^[^{]+\{\s*\[native \w/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rsibling = /[+~]/,
+ rescape = /'|\\/g,
+
+ // CSS escapes http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+ funescape = function( _, escaped, escapedWhitespace ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ // Support: Firefox<24
+ // Workaround erroneous numeric interpretation of +"0x"
+ return high !== high || escapedWhitespace ?
+ escaped :
+ high < 0 ?
+ // BMP codepoint
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ },
+
+ // Used for iframes
+ // See setDocument()
+ // Removing the function wrapper causes a "Permission Denied"
+ // error in IE
+ unloadHandler = function() {
+ setDocument();
+ };
+
+// Optimize for push.apply( _, NodeList )
+try {
+ push.apply(
+ (arr = slice.call( preferredDoc.childNodes )),
+ preferredDoc.childNodes
+ );
+ // Support: Android<4.0
+ // Detect silently failing push.apply
+ arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+ push = { apply: arr.length ?
+
+ // Leverage slice if possible
+ function( target, els ) {
+ push_native.apply( target, slice.call(els) );
+ } :
+
+ // Support: IE<9
+ // Otherwise append directly
+ function( target, els ) {
+ var j = target.length,
+ i = 0;
+ // Can't trust NodeList.length
+ while ( (target[j++] = els[i++]) ) {}
+ target.length = j - 1;
+ }
+ };
+}
+
+function Sizzle( selector, context, results, seed ) {
+ var match, elem, m, nodeType,
+ // QSA vars
+ i, groups, old, nid, newContext, newSelector;
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+
+ context = context || document;
+ results = results || [];
+ nodeType = context.nodeType;
+
+ if ( typeof selector !== "string" || !selector ||
+ nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+ return results;
+ }
+
+ if ( !seed && documentIsHTML ) {
+
+ // Try to shortcut find operations when possible (e.g., not under DocumentFragment)
+ if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+ // Speed-up: Sizzle("#ID")
+ if ( (m = match[1]) ) {
+ if ( nodeType === 9 ) {
+ elem = context.getElementById( m );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document (jQuery #6963)
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE, Opera, and Webkit return items
+ // by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+ } else {
+ // Context is not a document
+ if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) &&
+ contains( context, elem ) && elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Speed-up: Sizzle("TAG")
+ } else if ( match[2] ) {
+ push.apply( results, context.getElementsByTagName( selector ) );
+ return results;
+
+ // Speed-up: Sizzle(".CLASS")
+ } else if ( (m = match[3]) && support.getElementsByClassName ) {
+ push.apply( results, context.getElementsByClassName( m ) );
+ return results;
+ }
+ }
+
+ // QSA path
+ if ( support.qsa && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+ nid = old = expando;
+ newContext = context;
+ newSelector = nodeType !== 1 && selector;
+
+ // qSA works strangely on Element-rooted queries
+ // We can work around this by specifying an extra ID on the root
+ // and working up from there (Thanks to Andrew Dupont for the technique)
+ // IE 8 doesn't work on object elements
+ if ( nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
+ groups = tokenize( selector );
+
+ if ( (old = context.getAttribute("id")) ) {
+ nid = old.replace( rescape, "\\$&" );
+ } else {
+ context.setAttribute( "id", nid );
+ }
+ nid = "[id='" + nid + "'] ";
+
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = nid + toSelector( groups[i] );
+ }
+ newContext = rsibling.test( selector ) && testContext( context.parentNode ) || context;
+ newSelector = groups.join(",");
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch(qsaError) {
+ } finally {
+ if ( !old ) {
+ context.removeAttribute("id");
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {Function(string, Object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+function createCache() {
+ var keys = [];
+
+ function cache( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key + " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key + " " ] = value);
+ }
+ return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created div and expects a boolean result
+ */
+function assert( fn ) {
+ var div = document.createElement("div");
+
+ try {
+ return !!fn( div );
+ } catch (e) {
+ return false;
+ } finally {
+ // Remove from its parent by default
+ if ( div.parentNode ) {
+ div.parentNode.removeChild( div );
+ }
+ // release memory in IE
+ div = null;
+ }
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+ var arr = attrs.split("|"),
+ i = attrs.length;
+
+ while ( i-- ) {
+ Expr.attrHandle[ arr[i] ] = handler;
+ }
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+ ( ~b.sourceIndex || MAX_NEGATIVE ) -
+ ( ~a.sourceIndex || MAX_NEGATIVE );
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+ return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+ var hasCompare, parent,
+ doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // If no document and documentElement is available, return
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Set our document
+ document = doc;
+ docElem = doc.documentElement;
+ parent = doc.defaultView;
+
+ // Support: IE>8
+ // If iframe document is assigned to "document" variable and if iframe has been reloaded,
+ // IE will throw "permission denied" error when accessing "document" variable, see jQuery #13936
+ // IE6-8 do not support the defaultView property so parent will be undefined
+ if ( parent && parent !== parent.top ) {
+ // IE11 does not have attachEvent, so all must suffer
+ if ( parent.addEventListener ) {
+ parent.addEventListener( "unload", unloadHandler, false );
+ } else if ( parent.attachEvent ) {
+ parent.attachEvent( "onunload", unloadHandler );
+ }
+ }
+
+ /* Support tests
+ ---------------------------------------------------------------------- */
+ documentIsHTML = !isXML( doc );
+
+ /* Attributes
+ ---------------------------------------------------------------------- */
+
+ // Support: IE<8
+ // Verify that getAttribute really returns attributes and not properties
+ // (excepting IE8 booleans)
+ support.attributes = assert(function( div ) {
+ div.className = "i";
+ return !div.getAttribute("className");
+ });
+
+ /* getElement(s)By*
+ ---------------------------------------------------------------------- */
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.getElementsByTagName = assert(function( div ) {
+ div.appendChild( doc.createComment("") );
+ return !div.getElementsByTagName("*").length;
+ });
+
+ // Support: IE<9
+ support.getElementsByClassName = rnative.test( doc.getElementsByClassName );
+
+ // Support: IE<10
+ // Check if getElementById returns elements by name
+ // The broken getElementById methods don't pick up programatically-set names,
+ // so use a roundabout getElementsByName test
+ support.getById = assert(function( div ) {
+ docElem.appendChild( div ).id = expando;
+ return !doc.getElementsByName || !doc.getElementsByName( expando ).length;
+ });
+
+ // ID find and filter
+ if ( support.getById ) {
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+ var m = context.getElementById( id );
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ return m && m.parentNode ? [ m ] : [];
+ }
+ };
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ } else {
+ // Support: IE6/7
+ // getElementById is not reliable as a find shortcut
+ delete Expr.find["ID"];
+
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.getElementsByTagName ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( tag );
+
+ // DocumentFragment nodes don't have gEBTN
+ } else if ( support.qsa ) {
+ return context.querySelectorAll( tag );
+ }
+ } :
+
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+ if ( documentIsHTML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ /* QSA/matchesSelector
+ ---------------------------------------------------------------------- */
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21)
+ // We allow this because of a bug in IE8/9 that throws an error
+ // whenever `document.activeElement` is accessed on an iframe
+ // So, we allow :focus to pass through QSA all the time to avoid the IE error
+ // See http://bugs.jquery.com/ticket/13378
+ rbuggyQSA = [];
+
+ if ( (support.qsa = rnative.test( doc.querySelectorAll )) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( div ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explicitly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // http://bugs.jquery.com/ticket/12359
+ docElem.appendChild( div ).innerHTML = "<a id='" + expando + "'></a>" +
+ "<select id='" + expando + "-\f]' msallowcapture=''>" +
+ "<option selected=''></option></select>";
+
+ // Support: IE8, Opera 11-12.16
+ // Nothing should be selected when empty strings follow ^= or $= or *=
+ // The test attribute must be unknown in Opera but "safe" for WinRT
+ // http://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+ if ( div.querySelectorAll("[msallowcapture^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+ }
+
+ // Support: IE8
+ // Boolean attributes and "value" are not treated correctly
+ if ( !div.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+ }
+
+ // Support: Chrome<29, Android<4.2+, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.7+
+ if ( !div.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+ rbuggyQSA.push("~=");
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+
+ // Support: Safari 8+, iOS 8+
+ // https://bugs.webkit.org/show_bug.cgi?id=136851
+ // In-page `selector#id sibing-combinator selector` fails
+ if ( !div.querySelectorAll( "a#" + expando + "+*" ).length ) {
+ rbuggyQSA.push(".#.+[+~]");
+ }
+ });
+
+ assert(function( div ) {
+ // Support: Windows 8 Native Apps
+ // The type and name attributes are restricted during .innerHTML assignment
+ var input = doc.createElement("input");
+ input.setAttribute( "type", "hidden" );
+ div.appendChild( input ).setAttribute( "name", "D" );
+
+ // Support: IE8
+ // Enforce case-sensitivity of name attribute
+ if ( div.querySelectorAll("[name=d]").length ) {
+ rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( !div.querySelectorAll(":enabled").length ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ div.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+ docElem.webkitMatchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( div ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( div, "div" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( div, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+ /* Contains
+ ---------------------------------------------------------------------- */
+ hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+ // Element contains another
+ // Purposefully does not implement inclusive descendent
+ // As in, an element does not contain itself
+ contains = hasCompare || rnative.test( docElem.contains ) ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ /* Sorting
+ ---------------------------------------------------------------------- */
+
+ // Document order sorting
+ sortOrder = hasCompare ?
+ function( a, b ) {
+
+ // Flag for duplicate removal
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ // Sort on method existence if only one input has compareDocumentPosition
+ var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+ if ( compare ) {
+ return compare;
+ }
+
+ // Calculate position if both inputs belong to the same document
+ compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+ a.compareDocumentPosition( b ) :
+
+ // Otherwise we know they are disconnected
+ 1;
+
+ // Disconnected nodes
+ if ( compare & 1 ||
+ (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+ // Choose the first element that is related to our preferred document
+ if ( a === doc || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+ return -1;
+ }
+ if ( b === doc || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+ return 1;
+ }
+
+ // Maintain original order
+ return sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+ }
+
+ return compare & 4 ? -1 : 1;
+ } :
+ function( a, b ) {
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Parentless nodes are either documents or disconnected
+ if ( !aup || !bup ) {
+ return a === doc ? -1 :
+ b === doc ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ return doc;
+};
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ if ( support.matchesSelector && documentIsHTML &&
+ ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+ ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
+
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch (e) {}
+ }
+
+ return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ var fn = Expr.attrHandle[ name.toLowerCase() ],
+ // Don't get fooled by Object.prototype properties (jQuery #13807)
+ val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+ fn( elem, name, !documentIsHTML ) :
+ undefined;
+
+ return val !== undefined ?
+ val :
+ support.attributes || !documentIsHTML ?
+ elem.getAttribute( name ) :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null;
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ j = 0,
+ i = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ sortInput = !support.sortStable && results.slice( 0 );
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem === results[ i ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ // Clear input after sorting to release objects
+ // See https://github.com/jquery/sizzle/pull/225
+ sortInput = null;
+
+ return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ while ( (node = elem[i++]) ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (jQuery #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ attrHandle: {},
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[6] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[3] ) {
+ match[2] = match[4] || match[5] || "";
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeNameSelector ) {
+ var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+ return nodeNameSelector === "*" ?
+ function() { return true; } :
+ function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, outerCache, node, diff, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) {
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+ // Seek `elem` from a previously-cached index
+ outerCache = parent[ expando ] || (parent[ expando ] = {});
+ cache = outerCache[ type ] || [];
+ nodeIndex = cache[0] === dirruns && cache[1];
+ diff = cache[0] === dirruns && cache[2];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ outerCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ // Use previously-cached element index if available
+ } else if ( useCache && (cache = (elem[ expando ] || (elem[ expando ] = {}))[ type ]) && cache[0] === dirruns ) {
+ diff = cache[1];
+
+ // xml :nth-child(...) or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ } else {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ? node.nodeName.toLowerCase() === name : node.nodeType === 1 ) && ++diff ) {
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ (node[ expando ] || (node[ expando ] = {}))[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ // Don't keep the element (issue #299)
+ input[0] = null;
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ text = text.replace( runescape, funescape );
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifier
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsHTML ?
+ elem.lang :
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": function( elem ) {
+ return elem.disabled === false;
+ },
+
+ "disabled": function( elem ) {
+ return elem.disabled === true;
+ },
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+ // but not by others (comment: 8; processing instruction: 7; etc.)
+ // nodeType < 6 works because attributes (2) do not appear as children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeType < 6 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+
+ // Support: IE<8
+ // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( (tokens = []) );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ });
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ type: type,
+ matches: match
+ });
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ checkNonElements = base && dir === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var oldCache, outerCache,
+ newCache = [ dirruns, doneName ];
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+ if ( (oldCache = outerCache[ dir ]) &&
+ oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+ // Assign to newCache so results back-propagate to previous elements
+ return (newCache[ 2 ] = oldCache[ 2 ]);
+ } else {
+ // Reuse newcache so results back-propagate to previous elements
+ outerCache[ dir ] = newCache;
+
+ // A match means we're done; a fail means we have to keep checking
+ if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ // Avoid hanging onto element (issue #299)
+ checkContext = null;
+ return ret;
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector(
+ // If the preceding token was a descendant combinator, insert an implicit any-element `*`
+ tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+ ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ var bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, outermost ) {
+ var elem, j, matcher,
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ setMatched = [],
+ contextBackup = outermostContext,
+ // We must always have either seed elements or outermost context
+ elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+ len = elems.length;
+
+ if ( outermost ) {
+ outermostContext = context !== document && context;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Keep `i` a string if there are no elements so `matchedCount` will be "00" below
+ // Support: IE<9, Safari
+ // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+ for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context, xml ) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // Apply set filters to unmatched elements
+ matchedCount += i;
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !match ) {
+ match = tokenize( selector );
+ }
+ i = match.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( match[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+ // Save selector and tokenization
+ cached.selector = selector;
+ }
+ return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ * selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ * selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ compiled = typeof selector === "function" && selector,
+ match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+ results = results || [];
+
+ // Try to minimize operations if there is no seed and only one group
+ if ( match.length === 1 ) {
+
+ // Take a shortcut and set the context if the root selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ support.getById && context.nodeType === 9 && documentIsHTML &&
+ Expr.relative[ tokens[1].type ] ) {
+
+ context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+ if ( !context ) {
+ return results;
+
+ // Precompiled matchers will still verify ancestry, so step up a level
+ } else if ( compiled ) {
+ context = context.parentNode;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, seed );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function if one is not provided
+ // Provide `match` to avoid retokenization if we modified the selector above
+ ( compiled || compile( selector, match ) )(
+ seed,
+ context,
+ !documentIsHTML,
+ results,
+ rsibling.test( selector ) && testContext( context.parentNode ) || context
+ );
+ return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome 14-35+
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( div1 ) {
+ // Should return 1, but returns 4 (following)
+ return div1.compareDocumentPosition( document.createElement("div") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( div ) {
+ div.innerHTML = "<a href='#'></a>";
+ return div.firstChild.getAttribute("href") === "#" ;
+}) ) {
+ addHandle( "type|href|height|width", function( elem, name, isXML ) {
+ if ( !isXML ) {
+ return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+ }
+ });
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( div ) {
+ div.innerHTML = "<input/>";
+ div.firstChild.setAttribute( "value", "" );
+ return div.firstChild.getAttribute( "value" ) === "";
+}) ) {
+ addHandle( "value", function( elem, name, isXML ) {
+ if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+ return elem.defaultValue;
+ }
+ });
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( div ) {
+ return div.getAttribute("disabled") == null;
+}) ) {
+ addHandle( booleans, function( elem, name, isXML ) {
+ var val;
+ if ( !isXML ) {
+ return elem[ name ] === true ? name.toLowerCase() :
+ (val = elem.getAttributeNode( name )) && val.specified ?
+ val.value :
+ null;
+ }
+ });
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+jQuery.expr[":"] = jQuery.expr.pseudos;
+jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+var rsingleTag = (/^<(\w+)\s*\/?>(?:<\/\1>|)$/);
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep( elements, function( elem, i ) {
+ /* jshint -W018 */
+ return !!qualifier.call( elem, i, elem ) !== not;
+ });
+
+ }
+
+ if ( qualifier.nodeType ) {
+ return jQuery.grep( elements, function( elem ) {
+ return ( elem === qualifier ) !== not;
+ });
+
+ }
+
+ if ( typeof qualifier === "string" ) {
+ if ( risSimple.test( qualifier ) ) {
+ return jQuery.filter( qualifier, elements, not );
+ }
+
+ qualifier = jQuery.filter( qualifier, elements );
+ }
+
+ return jQuery.grep( elements, function( elem ) {
+ return ( jQuery.inArray( elem, qualifier ) >= 0 ) !== not;
+ });
+}
+
+jQuery.filter = function( expr, elems, not ) {
+ var elem = elems[ 0 ];
+
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ return elems.length === 1 && elem.nodeType === 1 ?
+ jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [] :
+ jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+ return elem.nodeType === 1;
+ }));
+};
+
+jQuery.fn.extend({
+ find: function( selector ) {
+ var i,
+ ret = [],
+ self = this,
+ len = self.length;
+
+ if ( typeof selector !== "string" ) {
+ return this.pushStack( jQuery( selector ).filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ }) );
+ }
+
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, self[ i ], ret );
+ }
+
+ // Needed because $( selector, context ) becomes $( context ).find( selector )
+ ret = this.pushStack( len > 1 ? jQuery.unique( ret ) : ret );
+ ret.selector = this.selector ? this.selector + " " + selector : selector;
+ return ret;
+ },
+ filter: function( selector ) {
+ return this.pushStack( winnow(this, selector || [], false) );
+ },
+ not: function( selector ) {
+ return this.pushStack( winnow(this, selector || [], true) );
+ },
+ is: function( selector ) {
+ return !!winnow(
+ this,
+
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ typeof selector === "string" && rneedsContext.test( selector ) ?
+ jQuery( selector ) :
+ selector || [],
+ false
+ ).length;
+ }
+});
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+ // Use the correct document accordingly with window argument (sandbox)
+ document = window.document,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]*))$/,
+
+ init = jQuery.fn.init = function( selector, context ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && (match[1] || !context) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[1] ) {
+ context = context instanceof jQuery ? context[0] : context;
+
+ // scripts is true for back-compat
+ // Intentionally let the error be thrown if parseHTML is not present
+ jQuery.merge( this, jQuery.parseHTML(
+ match[1],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[2] );
+
+ // Check parentNode to catch when Blackberry 4.6 returns
+ // nodes that are no longer in the document #6963
+ if ( elem && elem.parentNode ) {
+ // Handle the case where IE and Opera return items
+ // by name instead of ID
+ if ( elem.id !== match[2] ) {
+ return rootjQuery.find( selector );
+ }
+
+ // Otherwise, we inject the element directly into the jQuery object
+ this.length = 1;
+ this[0] = elem;
+ }
+
+ this.context = document;
+ this.selector = selector;
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || rootjQuery ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this.context = this[0] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return typeof rootjQuery.ready !== "undefined" ?
+ rootjQuery.ready( selector ) :
+ // Execute immediately if ready is not present
+ selector( jQuery );
+ }
+
+ if ( selector.selector !== undefined ) {
+ this.selector = selector.selector;
+ this.context = selector.context;
+ }
+
+ return jQuery.makeArray( selector, this );
+ };
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+ // methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.extend({
+ dir: function( elem, dir, until ) {
+ var matched = [],
+ cur = elem[ dir ];
+
+ while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
+ if ( cur.nodeType === 1 ) {
+ matched.push( cur );
+ }
+ cur = cur[dir];
+ }
+ return matched;
+ },
+
+ sibling: function( n, elem ) {
+ var r = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ r.push( n );
+ }
+ }
+
+ return r;
+ }
+});
+
+jQuery.fn.extend({
+ has: function( target ) {
+ var i,
+ targets = jQuery( target, this ),
+ len = targets.length;
+
+ return this.filter(function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( this, targets[i] ) ) {
+ return true;
+ }
+ }
+ });
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ matched = [],
+ pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ?
+ jQuery( selectors, context || this.context ) :
+ 0;
+
+ for ( ; i < l; i++ ) {
+ for ( cur = this[i]; cur && cur !== context; cur = cur.parentNode ) {
+ // Always skip document fragments
+ if ( cur.nodeType < 11 && (pos ?
+ pos.index(cur) > -1 :
+
+ // Don't pass non-elements to Sizzle
+ cur.nodeType === 1 &&
+ jQuery.find.matchesSelector(cur, selectors)) ) {
+
+ matched.push( cur );
+ break;
+ }
+ }
+ }
+
+ return this.pushStack( matched.length > 1 ? jQuery.unique( matched ) : matched );
+ },
+
+ // Determine the position of an element within
+ // the matched set of elements
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[0] && this[0].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // index in selector
+ if ( typeof elem === "string" ) {
+ return jQuery.inArray( this[0], jQuery( elem ) );
+ }
+
+ // Locate the position of the desired element
+ return jQuery.inArray(
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[0] : elem, this );
+ },
+
+ add: function( selector, context ) {
+ return this.pushStack(
+ jQuery.unique(
+ jQuery.merge( this.get(), jQuery( selector, context ) )
+ )
+ );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter(selector)
+ );
+ }
+});
+
+function sibling( cur, dir ) {
+ do {
+ cur = cur[ dir ];
+ } while ( cur && cur.nodeType !== 1 );
+
+ return cur;
+}
+
+jQuery.each({
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return jQuery.dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return jQuery.dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return jQuery.dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return jQuery.dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return jQuery.sibling( elem.firstChild );
+ },
+ contents: function( elem ) {
+ return jQuery.nodeName( elem, "iframe" ) ?
+ elem.contentDocument || elem.contentWindow.document :
+ jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var ret = jQuery.map( this, fn, until );
+
+ if ( name.slice( -5 ) !== "Until" ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ ret = jQuery.filter( selector, ret );
+ }
+
+ if ( this.length > 1 ) {
+ // Remove duplicates
+ if ( !guaranteedUnique[ name ] ) {
+ ret = jQuery.unique( ret );
+ }
+
+ // Reverse order for parents* and prev-derivatives
+ if ( rparentsprev.test( name ) ) {
+ ret = ret.reverse();
+ }
+ }
+
+ return this.pushStack( ret );
+ };
+});
+var rnotwhite = (/\S+/g);
+
+
+
+// String to Object options format cache
+var optionsCache = {};
+
+// Convert String-formatted options into Object-formatted ones and store in cache
+function createOptions( options ) {
+ var object = optionsCache[ options ] = {};
+ jQuery.each( options.match( rnotwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ });
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ ( optionsCache[ options ] || createOptions( options ) ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+ // Last fire value (for non-forgettable lists)
+ memory,
+ // Flag to know if list was already fired
+ fired,
+ // End of the loop when firing
+ firingLength,
+ // Index of currently firing callback (modified by remove if needed)
+ firingIndex,
+ // First callback to fire (used internally by add and fireWith)
+ firingStart,
+ // Actual callback list
+ list = [],
+ // Stack of fire calls for repeatable lists
+ stack = !options.once && [],
+ // Fire callbacks
+ fire = function( data ) {
+ memory = options.memory && data;
+ fired = true;
+ firingIndex = firingStart || 0;
+ firingStart = 0;
+ firingLength = list.length;
+ firing = true;
+ for ( ; list && firingIndex < firingLength; firingIndex++ ) {
+ if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) {
+ memory = false; // To prevent further calls using add
+ break;
+ }
+ }
+ firing = false;
+ if ( list ) {
+ if ( stack ) {
+ if ( stack.length ) {
+ fire( stack.shift() );
+ }
+ } else if ( memory ) {
+ list = [];
+ } else {
+ self.disable();
+ }
+ }
+ },
+ // Actual Callbacks object
+ self = {
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+ // First, we save the current length
+ var start = list.length;
+ (function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ var type = jQuery.type( arg );
+ if ( type === "function" ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && type !== "string" ) {
+ // Inspect recursively
+ add( arg );
+ }
+ });
+ })( arguments );
+ // Do we need to add the callbacks to the
+ // current firing batch?
+ if ( firing ) {
+ firingLength = list.length;
+ // With memory, if we're not firing then
+ // we should call right away
+ } else if ( memory ) {
+ firingStart = start;
+ fire( memory );
+ }
+ }
+ return this;
+ },
+ // Remove a callback from the list
+ remove: function() {
+ if ( list ) {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+ // Handle firing indexes
+ if ( firing ) {
+ if ( index <= firingLength ) {
+ firingLength--;
+ }
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ }
+ });
+ }
+ return this;
+ },
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ? jQuery.inArray( fn, list ) > -1 : !!( list && list.length );
+ },
+ // Remove all callbacks from the list
+ empty: function() {
+ list = [];
+ firingLength = 0;
+ return this;
+ },
+ // Have the list do nothing anymore
+ disable: function() {
+ list = stack = memory = undefined;
+ return this;
+ },
+ // Is it disabled?
+ disabled: function() {
+ return !list;
+ },
+ // Lock the list in its current state
+ lock: function() {
+ stack = undefined;
+ if ( !memory ) {
+ self.disable();
+ }
+ return this;
+ },
+ // Is it locked?
+ locked: function() {
+ return !stack;
+ },
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( list && ( !fired || stack ) ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ if ( firing ) {
+ stack.push( args );
+ } else {
+ fire( args );
+ }
+ }
+ return this;
+ },
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+
+
+jQuery.extend({
+
+ Deferred: function( func ) {
+ var tuples = [
+ // action, add listener, listener list, final state
+ [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks("memory") ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ then: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+ return jQuery.Deferred(function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+ // deferred[ done | fail | progress ] for forwarding actions to newDefer
+ deferred[ tuple[1] ](function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .done( newDefer.resolve )
+ .fail( newDefer.reject )
+ .progress( newDefer.notify );
+ } else {
+ newDefer[ tuple[ 0 ] + "With" ]( this === promise ? newDefer.promise() : this, fn ? [ returned ] : arguments );
+ }
+ });
+ });
+ fns = null;
+ }).promise();
+ },
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Keep pipe for back-compat
+ promise.pipe = promise.then;
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 3 ];
+
+ // promise[ done | fail | progress ] = list.add
+ promise[ tuple[1] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(function() {
+ // state = [ resolved | rejected ]
+ state = stateString;
+
+ // [ reject_list | resolve_list ].disable; progress_list.lock
+ }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock );
+ }
+
+ // deferred[ resolve | reject | notify ]
+ deferred[ tuple[0] ] = function() {
+ deferred[ tuple[0] + "With" ]( this === deferred ? promise : this, arguments );
+ return this;
+ };
+ deferred[ tuple[0] + "With" ] = list.fireWith;
+ });
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( subordinate /* , ..., subordinateN */ ) {
+ var i = 0,
+ resolveValues = slice.call( arguments ),
+ length = resolveValues.length,
+
+ // the count of uncompleted subordinates
+ remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0,
+
+ // the master Deferred. If resolveValues consist of only a single Deferred, just use that.
+ deferred = remaining === 1 ? subordinate : jQuery.Deferred(),
+
+ // Update function for both resolve and progress values
+ updateFunc = function( i, contexts, values ) {
+ return function( value ) {
+ contexts[ i ] = this;
+ values[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+ if ( values === progressValues ) {
+ deferred.notifyWith( contexts, values );
+
+ } else if ( !(--remaining) ) {
+ deferred.resolveWith( contexts, values );
+ }
+ };
+ },
+
+ progressValues, progressContexts, resolveContexts;
+
+ // add listeners to Deferred subordinates; treat others as resolved
+ if ( length > 1 ) {
+ progressValues = new Array( length );
+ progressContexts = new Array( length );
+ resolveContexts = new Array( length );
+ for ( ; i < length; i++ ) {
+ if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) {
+ resolveValues[ i ].promise()
+ .done( updateFunc( i, resolveContexts, resolveValues ) )
+ .fail( deferred.reject )
+ .progress( updateFunc( i, progressContexts, progressValues ) );
+ } else {
+ --remaining;
+ }
+ }
+ }
+
+ // if we're not waiting on anything, resolve the master
+ if ( !remaining ) {
+ deferred.resolveWith( resolveContexts, resolveValues );
+ }
+
+ return deferred.promise();
+ }
+});
+
+
+// The deferred used on DOM ready
+var readyList;
+
+jQuery.fn.ready = function( fn ) {
+ // Add the callback
+ jQuery.ready.promise().done( fn );
+
+ return this;
+};
+
+jQuery.extend({
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Hold (or release) the ready event
+ holdReady: function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+ },
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
+ if ( !document.body ) {
+ return setTimeout( jQuery.ready );
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+
+ // Trigger any bound ready events
+ if ( jQuery.fn.triggerHandler ) {
+ jQuery( document ).triggerHandler( "ready" );
+ jQuery( document ).off( "ready" );
+ }
+ }
+});
+
+/**
+ * Clean-up method for dom ready events
+ */
+function detach() {
+ if ( document.addEventListener ) {
+ document.removeEventListener( "DOMContentLoaded", completed, false );
+ window.removeEventListener( "load", completed, false );
+
+ } else {
+ document.detachEvent( "onreadystatechange", completed );
+ window.detachEvent( "onload", completed );
+ }
+}
+
+/**
+ * The ready event handler and self cleanup method
+ */
+function completed() {
+ // readyState === "complete" is good enough for us to call the dom ready in oldIE
+ if ( document.addEventListener || event.type === "load" || document.readyState === "complete" ) {
+ detach();
+ jQuery.ready();
+ }
+}
+
+jQuery.ready.promise = function( obj ) {
+ if ( !readyList ) {
+
+ readyList = jQuery.Deferred();
+
+ // Catch cases where $(document).ready() is called after the browser event has already occurred.
+ // we once tried to use readyState "interactive" here, but it caused issues like the one
+ // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15
+ if ( document.readyState === "complete" ) {
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ setTimeout( jQuery.ready );
+
+ // Standards-based browsers support DOMContentLoaded
+ } else if ( document.addEventListener ) {
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed, false );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed, false );
+
+ // If IE event model is used
+ } else {
+ // Ensure firing before onload, maybe late but safe also for iframes
+ document.attachEvent( "onreadystatechange", completed );
+
+ // A fallback to window.onload, that will always work
+ window.attachEvent( "onload", completed );
+
+ // If IE and not a frame
+ // continually check to see if the document is ready
+ var top = false;
+
+ try {
+ top = window.frameElement == null && document.documentElement;
+ } catch(e) {}
+
+ if ( top && top.doScroll ) {
+ (function doScrollCheck() {
+ if ( !jQuery.isReady ) {
+
+ try {
+ // Use the trick by Diego Perini
+ // http://javascript.nwbox.com/IEContentLoaded/
+ top.doScroll("left");
+ } catch(e) {
+ return setTimeout( doScrollCheck, 50 );
+ }
+
+ // detach all dom ready events
+ detach();
+
+ // and execute any waiting functions
+ jQuery.ready();
+ }
+ })();
+ }
+ }
+ }
+ return readyList.promise( obj );
+};
+
+
+var strundefined = typeof undefined;
+
+
+
+// Support: IE<9
+// Iteration over object's inherited properties before its own
+var i;
+for ( i in jQuery( support ) ) {
+ break;
+}
+support.ownLast = i !== "0";
+
+// Note: most support tests are defined in their respective modules.
+// false until the test is run
+support.inlineBlockNeedsLayout = false;
+
+// Execute ASAP in case we need to set body.style.zoom
+jQuery(function() {
+ // Minified: var a,b,c,d
+ var val, div, body, container;
+
+ body = document.getElementsByTagName( "body" )[ 0 ];
+ if ( !body || !body.style ) {
+ // Return for frameset docs that don't have a body
+ return;
+ }
+
+ // Setup
+ div = document.createElement( "div" );
+ container = document.createElement( "div" );
+ container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+ body.appendChild( container ).appendChild( div );
+
+ if ( typeof div.style.zoom !== strundefined ) {
+ // Support: IE<8
+ // Check if natively block-level elements act like inline-block
+ // elements when setting their display to 'inline' and giving
+ // them layout
+ div.style.cssText = "display:inline;margin:0;border:0;padding:1px;width:1px;zoom:1";
+
+ support.inlineBlockNeedsLayout = val = div.offsetWidth === 3;
+ if ( val ) {
+ // Prevent IE 6 from affecting layout for positioned elements #11048
+ // Prevent IE from shrinking the body in IE 7 mode #12869
+ // Support: IE<8
+ body.style.zoom = 1;
+ }
+ }
+
+ body.removeChild( container );
+});
+
+
+
+
+(function() {
+ var div = document.createElement( "div" );
+
+ // Execute the test only if not already executed in another module.
+ if (support.deleteExpando == null) {
+ // Support: IE<9
+ support.deleteExpando = true;
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+ }
+
+ // Null elements to avoid leaks in IE.
+ div = null;
+})();
+
+
+/**
+ * Determines whether an object can have data
+ */
+jQuery.acceptData = function( elem ) {
+ var noData = jQuery.noData[ (elem.nodeName + " ").toLowerCase() ],
+ nodeType = +elem.nodeType || 1;
+
+ // Do not set data on non-element DOM nodes because it will not be cleared (#8335).
+ return nodeType !== 1 && nodeType !== 9 ?
+ false :
+
+ // Nodes accept data unless otherwise specified; rejection can be conditional
+ !noData || noData !== true && elem.getAttribute("classid") === noData;
+};
+
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+ rmultiDash = /([A-Z])/g;
+
+function dataAttr( elem, key, data ) {
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+
+ var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();
+
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = data === "true" ? true :
+ data === "false" ? false :
+ data === "null" ? null :
+ // Only convert to a number if it doesn't change the string
+ +data + "" === data ? +data :
+ rbrace.test( data ) ? jQuery.parseJSON( data ) :
+ data;
+ } catch( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ jQuery.data( elem, key, data );
+
+ } else {
+ data = undefined;
+ }
+ }
+
+ return data;
+}
+
+// checks a cache object for emptiness
+function isEmptyDataObject( obj ) {
+ var name;
+ for ( name in obj ) {
+
+ // if the public data object is empty, the private is still empty
+ if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
+ continue;
+ }
+ if ( name !== "toJSON" ) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+function internalData( elem, name, data, pvt /* Internal Use Only */ ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var ret, thisCache,
+ internalKey = jQuery.expando,
+
+ // We have to handle DOM nodes and JS objects differently because IE6-7
+ // can't GC object references properly across the DOM-JS boundary
+ isNode = elem.nodeType,
+
+ // Only DOM nodes need the global jQuery cache; JS object data is
+ // attached directly to the object so GC can occur automatically
+ cache = isNode ? jQuery.cache : elem,
+
+ // Only defining an ID for JS objects if its cache already exists allows
+ // the code to shortcut on the same path as a DOM node with no cache
+ id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey;
+
+ // Avoid doing any more work than we need to when trying to get data on an
+ // object that has no data at all
+ if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && data === undefined && typeof name === "string" ) {
+ return;
+ }
+
+ if ( !id ) {
+ // Only DOM nodes need a new unique ID for each element since their data
+ // ends up in the global cache
+ if ( isNode ) {
+ id = elem[ internalKey ] = deletedIds.pop() || jQuery.guid++;
+ } else {
+ id = internalKey;
+ }
+ }
+
+ if ( !cache[ id ] ) {
+ // Avoid exposing jQuery metadata on plain JS objects when the object
+ // is serialized using JSON.stringify
+ cache[ id ] = isNode ? {} : { toJSON: jQuery.noop };
+ }
+
+ // An object can be passed to jQuery.data instead of a key/value pair; this gets
+ // shallow copied over onto the existing cache
+ if ( typeof name === "object" || typeof name === "function" ) {
+ if ( pvt ) {
+ cache[ id ] = jQuery.extend( cache[ id ], name );
+ } else {
+ cache[ id ].data = jQuery.extend( cache[ id ].data, name );
+ }
+ }
+
+ thisCache = cache[ id ];
+
+ // jQuery data() is stored in a separate object inside the object's internal data
+ // cache in order to avoid key collisions between internal data and user-defined
+ // data.
+ if ( !pvt ) {
+ if ( !thisCache.data ) {
+ thisCache.data = {};
+ }
+
+ thisCache = thisCache.data;
+ }
+
+ if ( data !== undefined ) {
+ thisCache[ jQuery.camelCase( name ) ] = data;
+ }
+
+ // Check for both converted-to-camel and non-converted data property names
+ // If a data property was specified
+ if ( typeof name === "string" ) {
+
+ // First Try to find as-is property data
+ ret = thisCache[ name ];
+
+ // Test for null|undefined property data
+ if ( ret == null ) {
+
+ // Try to find the camelCased property
+ ret = thisCache[ jQuery.camelCase( name ) ];
+ }
+ } else {
+ ret = thisCache;
+ }
+
+ return ret;
+}
+
+function internalRemoveData( elem, name, pvt ) {
+ if ( !jQuery.acceptData( elem ) ) {
+ return;
+ }
+
+ var thisCache, i,
+ isNode = elem.nodeType,
+
+ // See jQuery.data for more information
+ cache = isNode ? jQuery.cache : elem,
+ id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
+
+ // If there is already no cache entry for this object, there is no
+ // purpose in continuing
+ if ( !cache[ id ] ) {
+ return;
+ }
+
+ if ( name ) {
+
+ thisCache = pvt ? cache[ id ] : cache[ id ].data;
+
+ if ( thisCache ) {
+
+ // Support array or space separated string names for data keys
+ if ( !jQuery.isArray( name ) ) {
+
+ // try the string as a key before any manipulation
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+
+ // split the camel cased version by spaces unless a key with the spaces exists
+ name = jQuery.camelCase( name );
+ if ( name in thisCache ) {
+ name = [ name ];
+ } else {
+ name = name.split(" ");
+ }
+ }
+ } else {
+ // If "name" is an array of keys...
+ // When data is initially created, via ("key", "val") signature,
+ // keys will be converted to camelCase.
+ // Since there is no way to tell _how_ a key was added, remove
+ // both plain key and camelCase key. #12786
+ // This will only penalize the array argument path.
+ name = name.concat( jQuery.map( name, jQuery.camelCase ) );
+ }
+
+ i = name.length;
+ while ( i-- ) {
+ delete thisCache[ name[i] ];
+ }
+
+ // If there is no data left in the cache, we want to continue
+ // and let the cache object itself get destroyed
+ if ( pvt ? !isEmptyDataObject(thisCache) : !jQuery.isEmptyObject(thisCache) ) {
+ return;
+ }
+ }
+ }
+
+ // See jQuery.data for more information
+ if ( !pvt ) {
+ delete cache[ id ].data;
+
+ // Don't destroy the parent cache unless the internal data object
+ // had been the only thing left in it
+ if ( !isEmptyDataObject( cache[ id ] ) ) {
+ return;
+ }
+ }
+
+ // Destroy the cache
+ if ( isNode ) {
+ jQuery.cleanData( [ elem ], true );
+
+ // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080)
+ /* jshint eqeqeq: false */
+ } else if ( support.deleteExpando || cache != cache.window ) {
+ /* jshint eqeqeq: true */
+ delete cache[ id ];
+
+ // When all else fails, null
+ } else {
+ cache[ id ] = null;
+ }
+}
+
+jQuery.extend({
+ cache: {},
+
+ // The following elements (space-suffixed to avoid Object.prototype collisions)
+ // throw uncatchable exceptions if you attempt to set expando properties
+ noData: {
+ "applet ": true,
+ "embed ": true,
+ // ...but Flash objects (which have this classid) *can* handle expandos
+ "object ": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"
+ },
+
+ hasData: function( elem ) {
+ elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
+ return !!elem && !isEmptyDataObject( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return internalData( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ return internalRemoveData( elem, name );
+ },
+
+ // For internal use only.
+ _data: function( elem, name, data ) {
+ return internalData( elem, name, data, true );
+ },
+
+ _removeData: function( elem, name ) {
+ return internalRemoveData( elem, name, true );
+ }
+});
+
+jQuery.fn.extend({
+ data: function( key, value ) {
+ var i, name, data,
+ elem = this[0],
+ attrs = elem && elem.attributes;
+
+ // Special expections of .data basically thwart jQuery.access,
+ // so implement the relevant behavior ourselves
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = jQuery.data( elem );
+
+ if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) {
+ i = attrs.length;
+ while ( i-- ) {
+
+ // Support: IE11+
+ // The attrs elements can be null (#14894)
+ if ( attrs[ i ] ) {
+ name = attrs[ i ].name;
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.slice(5) );
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ }
+ jQuery._data( elem, "parsedAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each(function() {
+ jQuery.data( this, key );
+ });
+ }
+
+ return arguments.length > 1 ?
+
+ // Sets one value
+ this.each(function() {
+ jQuery.data( this, key, value );
+ }) :
+
+ // Gets one value
+ // Try to fetch any internally stored data first
+ elem ? dataAttr( elem, key, jQuery.data( elem, key ) ) : undefined;
+ },
+
+ removeData: function( key ) {
+ return this.each(function() {
+ jQuery.removeData( this, key );
+ });
+ }
+});
+
+
+jQuery.extend({
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = jQuery._data( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || jQuery.isArray(data) ) {
+ queue = jQuery._data( elem, type, jQuery.makeArray(data) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // not intended for public consumption - generates a queueHooks object, or returns the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return jQuery._data( elem, key ) || jQuery._data( elem, key, {
+ empty: jQuery.Callbacks("once memory").add(function() {
+ jQuery._removeData( elem, type + "queue" );
+ jQuery._removeData( elem, key );
+ })
+ });
+ }
+});
+
+jQuery.fn.extend({
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[0], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each(function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[0] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ dequeue: function( type ) {
+ return this.each(function() {
+ jQuery.dequeue( this, type );
+ });
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while ( i-- ) {
+ tmp = jQuery._data( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+});
+var pnum = (/[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/).source;
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHidden = function( elem, el ) {
+ // isHidden might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+ return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem );
+ };
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = jQuery.access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ length = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ jQuery.access( elems, fn, i, key[i], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < length; i++ ) {
+ fn( elems[i], key, raw ? value : value.call( elems[i], i, fn( elems[i], key ) ) );
+ }
+ }
+ }
+
+ return chainable ?
+ elems :
+
+ // Gets
+ bulk ?
+ fn.call( elems ) :
+ length ? fn( elems[0], key ) : emptyGet;
+};
+var rcheckableType = (/^(?:checkbox|radio)$/i);
+
+
+
+(function() {
+ // Minified: var a,b,c
+ var input = document.createElement( "input" ),
+ div = document.createElement( "div" ),
+ fragment = document.createDocumentFragment();
+
+ // Setup
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+
+ // IE strips leading whitespace when .innerHTML is used
+ support.leadingWhitespace = div.firstChild.nodeType === 3;
+
+ // Make sure that tbody elements aren't automatically inserted
+ // IE will insert them into empty tables
+ support.tbody = !div.getElementsByTagName( "tbody" ).length;
+
+ // Make sure that link elements get serialized correctly by innerHTML
+ // This requires a wrapper element in IE
+ support.htmlSerialize = !!div.getElementsByTagName( "link" ).length;
+
+ // Makes sure cloning an html5 element does not cause problems
+ // Where outerHTML is undefined, this still works
+ support.html5Clone =
+ document.createElement( "nav" ).cloneNode( true ).outerHTML !== "<:nav></:nav>";
+
+ // Check if a disconnected checkbox will retain its checked
+ // value of true after appended to the DOM (IE6/7)
+ input.type = "checkbox";
+ input.checked = true;
+ fragment.appendChild( input );
+ support.appendChecked = input.checked;
+
+ // Make sure textarea (and checkbox) defaultValue is properly cloned
+ // Support: IE6-IE11+
+ div.innerHTML = "<textarea>x</textarea>";
+ support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+
+ // #11217 - WebKit loses check when the name is after the checked attribute
+ fragment.appendChild( div );
+ div.innerHTML = "<input type='radio' checked='checked' name='t'/>";
+
+ // Support: Safari 5.1, iOS 5.1, Android 4.x, Android 2.3
+ // old WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE<9
+ // Opera does not clone events (and typeof div.attachEvent === undefined).
+ // IE9-10 clones events bound via attachEvent, but they don't trigger with .click()
+ support.noCloneEvent = true;
+ if ( div.attachEvent ) {
+ div.attachEvent( "onclick", function() {
+ support.noCloneEvent = false;
+ });
+
+ div.cloneNode( true ).click();
+ }
+
+ // Execute the test only if not already executed in another module.
+ if (support.deleteExpando == null) {
+ // Support: IE<9
+ support.deleteExpando = true;
+ try {
+ delete div.test;
+ } catch( e ) {
+ support.deleteExpando = false;
+ }
+ }
+})();
+
+
+(function() {
+ var i, eventName,
+ div = document.createElement( "div" );
+
+ // Support: IE<9 (lack submit/change bubble), Firefox 23+ (lack focusin event)
+ for ( i in { submit: true, change: true, focusin: true }) {
+ eventName = "on" + i;
+
+ if ( !(support[ i + "Bubbles" ] = eventName in window) ) {
+ // Beware of CSP restrictions (https://developer.mozilla.org/en/Security/CSP)
+ div.setAttribute( eventName, "t" );
+ support[ i + "Bubbles" ] = div.attributes[ eventName ].expando === false;
+ }
+ }
+
+ // Null elements to avoid leaks in IE.
+ div = null;
+})();
+
+
+var rformElems = /^(?:input|select|textarea)$/i,
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|pointer|contextmenu)|click/,
+ rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)$/;
+
+function returnTrue() {
+ return true;
+}
+
+function returnFalse() {
+ return false;
+}
+
+function safeActiveElement() {
+ try {
+ return document.activeElement;
+ } catch ( err ) { }
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+ var tmp, events, t, handleObjIn,
+ special, eventHandle, handleObj,
+ handlers, type, namespaces, origType,
+ elemData = jQuery._data( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !(events = elemData.events) ) {
+ events = elemData.events = {};
+ }
+ if ( !(eventHandle = elemData.handle) ) {
+ eventHandle = elemData.handle = function( e ) {
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== strundefined && (!e || jQuery.event.triggered !== e.type) ?
+ jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
+ undefined;
+ };
+ // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
+ eventHandle.elem = elem;
+ }
+
+ // Handle multiple events separated by a space
+ types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // There *must* be a type, no attaching namespace-only handlers
+ if ( !type ) {
+ continue;
+ }
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend({
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join(".")
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !(handlers = events[ type ]) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener/attachEvent if the special events handler returns false
+ if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+ // Bind the global event handler to the element
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle, false );
+
+ } else if ( elem.attachEvent ) {
+ elem.attachEvent( "on" + type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ // Nullify elem to prevent memory leaks in IE
+ elem = null;
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+ var j, handleObj, tmp,
+ origCount, t, events,
+ special, handlers, type,
+ namespaces, origType,
+ elemData = jQuery.hasData( elem ) && jQuery._data( elem );
+
+ if ( !elemData || !(events = elemData.events) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( rnotwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[t] ) || [];
+ type = origType = tmp[1];
+ namespaces = ( tmp[2] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[2] && new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ delete elemData.handle;
+
+ // removeData also checks for emptiness and clears the expando if empty
+ // so use it instead of delete
+ jQuery._removeData( elem, "events" );
+ }
+ },
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+ var handle, ontype, cur,
+ bubbleType, special, tmp, i,
+ eventPath = [ elem || document ],
+ type = hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split(".") : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf(".") >= 0 ) {
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split(".");
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf(":") < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+ event.isTrigger = onlyHandlers ? 2 : 3;
+ event.namespace = namespaces.join(".");
+ event.namespace_re = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === (elem.ownerDocument || document) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( (cur = eventPath[i++]) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && handle.apply && jQuery.acceptData( cur ) ) {
+ event.result = handle.apply( cur, data );
+ if ( event.result === false ) {
+ event.preventDefault();
+ }
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( (!special._default || special._default.apply( eventPath.pop(), data ) === false) &&
+ jQuery.acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name name as the event.
+ // Can't use an .isFunction() check here because IE6/7 fails that test.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && elem[ type ] && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ try {
+ elem[ type ]();
+ } catch ( e ) {
+ // IE<9 dies on focus/blur to hidden element (#1486,#12518)
+ // only reproducible on winXP IE8 native, not IE9 in IE8 mode
+ }
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ dispatch: function( event ) {
+
+ // Make a writable jQuery.Event from the native event object
+ event = jQuery.event.fix( event );
+
+ var i, ret, handleObj, matched, j,
+ handlerQueue = [],
+ args = slice.call( arguments ),
+ handlers = ( jQuery._data( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[0] = event;
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( (matched = handlerQueue[ i++ ]) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( (handleObj = matched.handlers[ j++ ]) && !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or
+ // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.namespace_re || event.namespace_re.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
+ .apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ if ( (event.result = ret) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var sel, handleObj, matches, i,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Find delegate handlers
+ // Black-hole SVG <use> instance trees (#13180)
+ // Avoid non-left-click bubbling in Firefox (#3861)
+ if ( delegateCount && cur.nodeType && (!event.button || event.type !== "click") ) {
+
+ /* jshint eqeqeq: false */
+ for ( ; cur != this; cur = cur.parentNode || this ) {
+ /* jshint eqeqeq: true */
+
+ // Don't check non-elements (#13208)
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.nodeType === 1 && (cur.disabled !== true || event.type !== "click") ) {
+ matches = [];
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+
+ // Don't conflict with Object.prototype properties (#13203)
+ sel = handleObj.selector + " ";
+
+ if ( matches[ sel ] === undefined ) {
+ matches[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) >= 0 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( matches[ sel ] ) {
+ matches.push( handleObj );
+ }
+ }
+ if ( matches.length ) {
+ handlerQueue.push({ elem: cur, handlers: matches });
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ if ( delegateCount < handlers.length ) {
+ handlerQueue.push({ elem: this, handlers: handlers.slice( delegateCount ) });
+ }
+
+ return handlerQueue;
+ },
+
+ fix: function( event ) {
+ if ( event[ jQuery.expando ] ) {
+ return event;
+ }
+
+ // Create a writable copy of the event object and normalize some properties
+ var i, prop, copy,
+ type = event.type,
+ originalEvent = event,
+ fixHook = this.fixHooks[ type ];
+
+ if ( !fixHook ) {
+ this.fixHooks[ type ] = fixHook =
+ rmouseEvent.test( type ) ? this.mouseHooks :
+ rkeyEvent.test( type ) ? this.keyHooks :
+ {};
+ }
+ copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;
+
+ event = new jQuery.Event( originalEvent );
+
+ i = copy.length;
+ while ( i-- ) {
+ prop = copy[ i ];
+ event[ prop ] = originalEvent[ prop ];
+ }
+
+ // Support: IE<9
+ // Fix target property (#1925)
+ if ( !event.target ) {
+ event.target = originalEvent.srcElement || document;
+ }
+
+ // Support: Chrome 23+, Safari?
+ // Target should not be a text node (#504, #13143)
+ if ( event.target.nodeType === 3 ) {
+ event.target = event.target.parentNode;
+ }
+
+ // Support: IE<9
+ // For mouse/key events, metaKey==false if it's undefined (#3368, #11328)
+ event.metaKey = !!event.metaKey;
+
+ return fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+ },
+
+ // Includes some event props shared by KeyEvent and MouseEvent
+ props: "altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),
+
+ fixHooks: {},
+
+ keyHooks: {
+ props: "char charCode key keyCode".split(" "),
+ filter: function( event, original ) {
+
+ // Add which for key events
+ if ( event.which == null ) {
+ event.which = original.charCode != null ? original.charCode : original.keyCode;
+ }
+
+ return event;
+ }
+ },
+
+ mouseHooks: {
+ props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
+ filter: function( event, original ) {
+ var body, eventDoc, doc,
+ button = original.button,
+ fromElement = original.fromElement;
+
+ // Calculate pageX/Y if missing and clientX/Y available
+ if ( event.pageX == null && original.clientX != null ) {
+ eventDoc = event.target.ownerDocument || document;
+ doc = eventDoc.documentElement;
+ body = eventDoc.body;
+
+ event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
+ event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 );
+ }
+
+ // Add relatedTarget, if necessary
+ if ( !event.relatedTarget && fromElement ) {
+ event.relatedTarget = fromElement === event.target ? original.toElement : fromElement;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ // Note: button is not normalized, so don't use it
+ if ( !event.which && button !== undefined ) {
+ event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
+ }
+
+ return event;
+ }
+ },
+
+ special: {
+ load: {
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+ focus: {
+ // Fire native event if possible so blur/focus sequence is correct
+ trigger: function() {
+ if ( this !== safeActiveElement() && this.focus ) {
+ try {
+ this.focus();
+ return false;
+ } catch ( e ) {
+ // Support: IE<9
+ // If we error on focus to hidden element (#1486, #12518),
+ // let .trigger() run the handlers
+ }
+ }
+ },
+ delegateType: "focusin"
+ },
+ blur: {
+ trigger: function() {
+ if ( this === safeActiveElement() && this.blur ) {
+ this.blur();
+ return false;
+ }
+ },
+ delegateType: "focusout"
+ },
+ click: {
+ // For checkbox, fire native event so checked state will be right
+ trigger: function() {
+ if ( jQuery.nodeName( this, "input" ) && this.type === "checkbox" && this.click ) {
+ this.click();
+ return false;
+ }
+ },
+
+ // For cross-browser consistency, don't fire native .click() on links
+ _default: function( event ) {
+ return jQuery.nodeName( event.target, "a" );
+ }
+ },
+
+ beforeunload: {
+ postDispatch: function( event ) {
+
+ // Support: Firefox 20+
+ // Firefox doesn't alert if the returnValue field is not set.
+ if ( event.result !== undefined && event.originalEvent ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ },
+
+ simulate: function( type, elem, event, bubble ) {
+ // Piggyback on a donor event to simulate a different one.
+ // Fake originalEvent to avoid donor's stopPropagation, but if the
+ // simulated event prevents default then we do the same on the donor.
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ {
+ type: type,
+ isSimulated: true,
+ originalEvent: {}
+ }
+ );
+ if ( bubble ) {
+ jQuery.event.trigger( e, null, elem );
+ } else {
+ jQuery.event.dispatch.call( elem, e );
+ }
+ if ( e.isDefaultPrevented() ) {
+ event.preventDefault();
+ }
+ }
+};
+
+jQuery.removeEvent = document.removeEventListener ?
+ function( elem, type, handle ) {
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle, false );
+ }
+ } :
+ function( elem, type, handle ) {
+ var name = "on" + type;
+
+ if ( elem.detachEvent ) {
+
+ // #8545, #7054, preventing memory leaks for custom events in IE6-8
+ // detachEvent needed property on element, by name of that event, to properly expose it to GC
+ if ( typeof elem[ name ] === strundefined ) {
+ elem[ name ] = null;
+ }
+
+ elem.detachEvent( name, handle );
+ }
+ };
+
+jQuery.Event = function( src, props ) {
+ // Allow instantiation without the 'new' keyword
+ if ( !(this instanceof jQuery.Event) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = src.defaultPrevented ||
+ src.defaultPrevented === undefined &&
+ // Support: IE < 9, Android < 4.0
+ src.returnValue === false ?
+ returnTrue :
+ returnFalse;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+ if ( !e ) {
+ return;
+ }
+
+ // If preventDefault exists, run it on the original event
+ if ( e.preventDefault ) {
+ e.preventDefault();
+
+ // Support: IE
+ // Otherwise set the returnValue property of the original event to false
+ } else {
+ e.returnValue = false;
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+ if ( !e ) {
+ return;
+ }
+ // If stopPropagation exists, run it on the original event
+ if ( e.stopPropagation ) {
+ e.stopPropagation();
+ }
+
+ // Support: IE
+ // Set the cancelBubble property of the original event to true
+ e.cancelBubble = true;
+ },
+ stopImmediatePropagation: function() {
+ var e = this.originalEvent;
+
+ this.isImmediatePropagationStopped = returnTrue;
+
+ if ( e && e.stopImmediatePropagation ) {
+ e.stopImmediatePropagation();
+ }
+
+ this.stopPropagation();
+ }
+};
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+jQuery.each({
+ mouseenter: "mouseover",
+ mouseleave: "mouseout",
+ pointerenter: "pointerover",
+ pointerleave: "pointerout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj;
+
+ // For mousenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+});
+
+// IE submit delegation
+if ( !support.submitBubbles ) {
+
+ jQuery.event.special.submit = {
+ setup: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Lazy-add a submit handler when a descendant form may potentially be submitted
+ jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
+ // Node name check avoids a VML-related crash in IE (#9807)
+ var elem = e.target,
+ form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
+ if ( form && !jQuery._data( form, "submitBubbles" ) ) {
+ jQuery.event.add( form, "submit._submit", function( event ) {
+ event._submit_bubble = true;
+ });
+ jQuery._data( form, "submitBubbles", true );
+ }
+ });
+ // return undefined since we don't need an event listener
+ },
+
+ postDispatch: function( event ) {
+ // If form was submitted by the user, bubble the event up the tree
+ if ( event._submit_bubble ) {
+ delete event._submit_bubble;
+ if ( this.parentNode && !event.isTrigger ) {
+ jQuery.event.simulate( "submit", this.parentNode, event, true );
+ }
+ }
+ },
+
+ teardown: function() {
+ // Only need this for delegated form submit events
+ if ( jQuery.nodeName( this, "form" ) ) {
+ return false;
+ }
+
+ // Remove delegated handlers; cleanData eventually reaps submit handlers attached above
+ jQuery.event.remove( this, "._submit" );
+ }
+ };
+}
+
+// IE change delegation and checkbox/radio fix
+if ( !support.changeBubbles ) {
+
+ jQuery.event.special.change = {
+
+ setup: function() {
+
+ if ( rformElems.test( this.nodeName ) ) {
+ // IE doesn't fire change on a check/radio until blur; trigger it on click
+ // after a propertychange. Eat the blur-change in special.change.handle.
+ // This still fires onchange a second time for check/radio after blur.
+ if ( this.type === "checkbox" || this.type === "radio" ) {
+ jQuery.event.add( this, "propertychange._change", function( event ) {
+ if ( event.originalEvent.propertyName === "checked" ) {
+ this._just_changed = true;
+ }
+ });
+ jQuery.event.add( this, "click._change", function( event ) {
+ if ( this._just_changed && !event.isTrigger ) {
+ this._just_changed = false;
+ }
+ // Allow triggered, simulated change events (#11500)
+ jQuery.event.simulate( "change", this, event, true );
+ });
+ }
+ return false;
+ }
+ // Delegated event; lazy-add a change handler on descendant inputs
+ jQuery.event.add( this, "beforeactivate._change", function( e ) {
+ var elem = e.target;
+
+ if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "changeBubbles" ) ) {
+ jQuery.event.add( elem, "change._change", function( event ) {
+ if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
+ jQuery.event.simulate( "change", this.parentNode, event, true );
+ }
+ });
+ jQuery._data( elem, "changeBubbles", true );
+ }
+ });
+ },
+
+ handle: function( event ) {
+ var elem = event.target;
+
+ // Swallow native change events from checkbox/radio, we already triggered them above
+ if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
+ return event.handleObj.handler.apply( this, arguments );
+ }
+ },
+
+ teardown: function() {
+ jQuery.event.remove( this, "._change" );
+
+ return !rformElems.test( this.nodeName );
+ }
+ };
+}
+
+// Create "bubbling" focus and blur events
+if ( !support.focusinBubbles ) {
+ jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler on the document while someone wants focusin/focusout
+ var handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ var doc = this.ownerDocument || this,
+ attaches = jQuery._data( doc, fix );
+
+ if ( !attaches ) {
+ doc.addEventListener( orig, handler, true );
+ }
+ jQuery._data( doc, fix, ( attaches || 0 ) + 1 );
+ },
+ teardown: function() {
+ var doc = this.ownerDocument || this,
+ attaches = jQuery._data( doc, fix ) - 1;
+
+ if ( !attaches ) {
+ doc.removeEventListener( orig, handler, true );
+ jQuery._removeData( doc, fix );
+ } else {
+ jQuery._data( doc, fix, attaches );
+ }
+ }
+ };
+ });
+}
+
+jQuery.fn.extend({
+
+ on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
+ var type, origFn;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ this.on( type, selector, data, types[ type ], one );
+ }
+ return this;
+ }
+
+ if ( data == null && fn == null ) {
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return this;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return this.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ });
+ },
+ one: function( types, selector, data, fn ) {
+ return this.on( types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each(function() {
+ jQuery.event.remove( this, types, fn, selector );
+ });
+ },
+
+ trigger: function( type, data ) {
+ return this.each(function() {
+ jQuery.event.trigger( type, data, this );
+ });
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[0];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+});
+
+
+function createSafeFragment( document ) {
+ var list = nodeNames.split( "|" ),
+ safeFrag = document.createDocumentFragment();
+
+ if ( safeFrag.createElement ) {
+ while ( list.length ) {
+ safeFrag.createElement(
+ list.pop()
+ );
+ }
+ }
+ return safeFrag;
+}
+
+var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" +
+ "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
+ rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g,
+ rnoshimcache = new RegExp("<(?:" + nodeNames + ")[\\s/>]", "i"),
+ rleadingWhitespace = /^\s+/,
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi,
+ rtagName = /<([\w:]+)/,
+ rtbody = /<tbody/i,
+ rhtml = /<|&#?\w+;/,
+ rnoInnerhtml = /<(?:script|style|link)/i,
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptType = /^$|\/(?:java|ecma)script/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g,
+
+ // We have to close these tags to support XHTML (#13200)
+ wrapMap = {
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+ legend: [ 1, "<fieldset>", "</fieldset>" ],
+ area: [ 1, "<map>", "</map>" ],
+ param: [ 1, "<object>", "</object>" ],
+ thead: [ 1, "<table>", "</table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+ // IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags,
+ // unless wrapped in a div with non-breaking characters in front of it.
+ _default: support.htmlSerialize ? [ 0, "", "" ] : [ 1, "X<div>", "</div>" ]
+ },
+ safeFragment = createSafeFragment( document ),
+ fragmentDiv = safeFragment.appendChild( document.createElement("div") );
+
+wrapMap.optgroup = wrapMap.option;
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+function getAll( context, tag ) {
+ var elems, elem,
+ i = 0,
+ found = typeof context.getElementsByTagName !== strundefined ? context.getElementsByTagName( tag || "*" ) :
+ typeof context.querySelectorAll !== strundefined ? context.querySelectorAll( tag || "*" ) :
+ undefined;
+
+ if ( !found ) {
+ for ( found = [], elems = context.childNodes || context; (elem = elems[i]) != null; i++ ) {
+ if ( !tag || jQuery.nodeName( elem, tag ) ) {
+ found.push( elem );
+ } else {
+ jQuery.merge( found, getAll( elem, tag ) );
+ }
+ }
+ }
+
+ return tag === undefined || tag && jQuery.nodeName( context, tag ) ?
+ jQuery.merge( [ context ], found ) :
+ found;
+}
+
+// Used in buildFragment, fixes the defaultChecked property
+function fixDefaultChecked( elem ) {
+ if ( rcheckableType.test( elem.type ) ) {
+ elem.defaultChecked = elem.checked;
+ }
+}
+
+// Support: IE<8
+// Manipulating tables requires a tbody
+function manipulationTarget( elem, content ) {
+ return jQuery.nodeName( elem, "table" ) &&
+ jQuery.nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ?
+
+ elem.getElementsByTagName("tbody")[0] ||
+ elem.appendChild( elem.ownerDocument.createElement("tbody") ) :
+ elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+ elem.type = (jQuery.find.attr( elem, "type" ) !== null) + "/" + elem.type;
+ return elem;
+}
+function restoreScript( elem ) {
+ var match = rscriptTypeMasked.exec( elem.type );
+ if ( match ) {
+ elem.type = match[1];
+ } else {
+ elem.removeAttribute("type");
+ }
+ return elem;
+}
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+ var elem,
+ i = 0;
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ jQuery._data( elem, "globalEval", !refElements || jQuery._data( refElements[i], "globalEval" ) );
+ }
+}
+
+function cloneCopyEvent( src, dest ) {
+
+ if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
+ return;
+ }
+
+ var type, i, l,
+ oldData = jQuery._data( src ),
+ curData = jQuery._data( dest, oldData ),
+ events = oldData.events;
+
+ if ( events ) {
+ delete curData.handle;
+ curData.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+
+ // make the cloned public data object a copy from the original
+ if ( curData.data ) {
+ curData.data = jQuery.extend( {}, curData.data );
+ }
+}
+
+function fixCloneNodeIssues( src, dest ) {
+ var nodeName, e, data;
+
+ // We do not need to do anything for non-Elements
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ nodeName = dest.nodeName.toLowerCase();
+
+ // IE6-8 copies events bound via attachEvent when using cloneNode.
+ if ( !support.noCloneEvent && dest[ jQuery.expando ] ) {
+ data = jQuery._data( dest );
+
+ for ( e in data.events ) {
+ jQuery.removeEvent( dest, e, data.handle );
+ }
+
+ // Event data gets referenced instead of copied if the expando gets copied too
+ dest.removeAttribute( jQuery.expando );
+ }
+
+ // IE blanks contents when cloning scripts, and tries to evaluate newly-set text
+ if ( nodeName === "script" && dest.text !== src.text ) {
+ disableScript( dest ).text = src.text;
+ restoreScript( dest );
+
+ // IE6-10 improperly clones children of object elements using classid.
+ // IE10 throws NoModificationAllowedError if parent is null, #12132.
+ } else if ( nodeName === "object" ) {
+ if ( dest.parentNode ) {
+ dest.outerHTML = src.outerHTML;
+ }
+
+ // This path appears unavoidable for IE9. When cloning an object
+ // element in IE9, the outerHTML strategy above is not sufficient.
+ // If the src has innerHTML and the destination does not,
+ // copy the src.innerHTML into the dest.innerHTML. #10324
+ if ( support.html5Clone && ( src.innerHTML && !jQuery.trim(dest.innerHTML) ) ) {
+ dest.innerHTML = src.innerHTML;
+ }
+
+ } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+ // IE6-8 fails to persist the checked state of a cloned checkbox
+ // or radio button. Worse, IE6-7 fail to give the cloned element
+ // a checked appearance if the defaultChecked value isn't also set
+
+ dest.defaultChecked = dest.checked = src.checked;
+
+ // IE6-7 get confused and end up setting the value of a cloned
+ // checkbox/radio button to an empty string instead of "on"
+ if ( dest.value !== src.value ) {
+ dest.value = src.value;
+ }
+
+ // IE6-8 fails to return the selected option to the default selected
+ // state when cloning options
+ } else if ( nodeName === "option" ) {
+ dest.defaultSelected = dest.selected = src.defaultSelected;
+
+ // IE6-8 fails to set the defaultValue to the correct value when
+ // cloning other types of input fields
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+}
+
+jQuery.extend({
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var destElements, node, clone, i, srcElements,
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ if ( support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) {
+ clone = elem.cloneNode( true );
+
+ // IE<=8 does not properly clone detached, unknown element nodes
+ } else {
+ fragmentDiv.innerHTML = elem.outerHTML;
+ fragmentDiv.removeChild( clone = fragmentDiv.firstChild );
+ }
+
+ if ( (!support.noCloneEvent || !support.noCloneChecked) &&
+ (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
+
+ // We eschew Sizzle here for performance reasons: http://jsperf.com/getall-vs-sizzle/2
+ destElements = getAll( clone );
+ srcElements = getAll( elem );
+
+ // Fix all IE cloning issues
+ for ( i = 0; (node = srcElements[i]) != null; ++i ) {
+ // Ensure that the destination node is not null; Fixes #9587
+ if ( destElements[i] ) {
+ fixCloneNodeIssues( node, destElements[i] );
+ }
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ if ( deepDataAndEvents ) {
+ srcElements = srcElements || getAll( elem );
+ destElements = destElements || getAll( clone );
+
+ for ( i = 0; (node = srcElements[i]) != null; i++ ) {
+ cloneCopyEvent( node, destElements[i] );
+ }
+ } else {
+ cloneCopyEvent( elem, clone );
+ }
+ }
+
+ // Preserve script evaluation history
+ destElements = getAll( clone, "script" );
+ if ( destElements.length > 0 ) {
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+ }
+
+ destElements = srcElements = node = null;
+
+ // Return the cloned set
+ return clone;
+ },
+
+ buildFragment: function( elems, context, scripts, selection ) {
+ var j, elem, contains,
+ tmp, tag, tbody, wrap,
+ l = elems.length,
+
+ // Ensure a safe fragment
+ safe = createSafeFragment( context ),
+
+ nodes = [],
+ i = 0;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || safe.appendChild( context.createElement("div") );
+
+ // Deserialize a standard representation
+ tag = (rtagName.exec( elem ) || [ "", "" ])[ 1 ].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+
+ tmp.innerHTML = wrap[1] + elem.replace( rxhtmlTag, "<$1></$2>" ) + wrap[2];
+
+ // Descend through wrappers to the right content
+ j = wrap[0];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Manually add leading whitespace removed by IE
+ if ( !support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
+ nodes.push( context.createTextNode( rleadingWhitespace.exec( elem )[0] ) );
+ }
+
+ // Remove IE's autoinserted <tbody> from table fragments
+ if ( !support.tbody ) {
+
+ // String was a <table>, *may* have spurious <tbody>
+ elem = tag === "table" && !rtbody.test( elem ) ?
+ tmp.firstChild :
+
+ // String was a bare <thead> or <tfoot>
+ wrap[1] === "<table>" && !rtbody.test( elem ) ?
+ tmp :
+ 0;
+
+ j = elem && elem.childNodes.length;
+ while ( j-- ) {
+ if ( jQuery.nodeName( (tbody = elem.childNodes[j]), "tbody" ) && !tbody.childNodes.length ) {
+ elem.removeChild( tbody );
+ }
+ }
+ }
+
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Fix #12392 for WebKit and IE > 9
+ tmp.textContent = "";
+
+ // Fix #12392 for oldIE
+ while ( tmp.firstChild ) {
+ tmp.removeChild( tmp.firstChild );
+ }
+
+ // Remember the top-level container for proper cleanup
+ tmp = safe.lastChild;
+ }
+ }
+ }
+
+ // Fix #11356: Clear elements from fragment
+ if ( tmp ) {
+ safe.removeChild( tmp );
+ }
+
+ // Reset defaultChecked for any radios and checkboxes
+ // about to be appended to the DOM in IE 6/7 (#8060)
+ if ( !support.appendChecked ) {
+ jQuery.grep( getAll( nodes, "input" ), fixDefaultChecked );
+ }
+
+ i = 0;
+ while ( (elem = nodes[ i++ ]) ) {
+
+ // #4087 - If origin and destination elements are the same, and this is
+ // that element, do not do anything
+ if ( selection && jQuery.inArray( elem, selection ) !== -1 ) {
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
+
+ // Append to fragment
+ tmp = getAll( safe.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( (elem = tmp[ j++ ]) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
+ }
+ }
+
+ tmp = null;
+
+ return safe;
+ },
+
+ cleanData: function( elems, /* internal */ acceptData ) {
+ var elem, type, id, data,
+ i = 0,
+ internalKey = jQuery.expando,
+ cache = jQuery.cache,
+ deleteExpando = support.deleteExpando,
+ special = jQuery.event.special;
+
+ for ( ; (elem = elems[i]) != null; i++ ) {
+ if ( acceptData || jQuery.acceptData( elem ) ) {
+
+ id = elem[ internalKey ];
+ data = id && cache[ id ];
+
+ if ( data ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ // Remove cache only if it was not already removed by jQuery.event.remove
+ if ( cache[ id ] ) {
+
+ delete cache[ id ];
+
+ // IE does not allow us to delete expando properties from nodes,
+ // nor does it have a removeAttribute function on Document nodes;
+ // we must handle all of these cases
+ if ( deleteExpando ) {
+ delete elem[ internalKey ];
+
+ } else if ( typeof elem.removeAttribute !== strundefined ) {
+ elem.removeAttribute( internalKey );
+
+ } else {
+ elem[ internalKey ] = null;
+ }
+
+ deletedIds.push( id );
+ }
+ }
+ }
+ }
+ }
+});
+
+jQuery.fn.extend({
+ text: function( value ) {
+ return access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) );
+ }, null, value, arguments.length );
+ },
+
+ append: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.appendChild( elem );
+ }
+ });
+ },
+
+ prepend: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.insertBefore( elem, target.firstChild );
+ }
+ });
+ },
+
+ before: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ });
+ },
+
+ after: function() {
+ return this.domManip( arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ });
+ },
+
+ remove: function( selector, keepData /* Internal Use Only */ ) {
+ var elem,
+ elems = selector ? jQuery.filter( selector, this ) : this,
+ i = 0;
+
+ for ( ; (elem = elems[i]) != null; i++ ) {
+
+ if ( !keepData && elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem ) );
+ }
+
+ if ( elem.parentNode ) {
+ if ( keepData && jQuery.contains( elem.ownerDocument, elem ) ) {
+ setGlobalEval( getAll( elem, "script" ) );
+ }
+ elem.parentNode.removeChild( elem );
+ }
+ }
+
+ return this;
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; (elem = this[i]) != null; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ }
+
+ // Remove any remaining nodes
+ while ( elem.firstChild ) {
+ elem.removeChild( elem.firstChild );
+ }
+
+ // If this is a select, ensure that it displays empty (#12336)
+ // Support: IE<9
+ if ( elem.options && jQuery.nodeName( elem, "select" ) ) {
+ elem.options.length = 0;
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map(function() {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ });
+ },
+
+ html: function( value ) {
+ return access( this, function( value ) {
+ var elem = this[ 0 ] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined ) {
+ return elem.nodeType === 1 ?
+ elem.innerHTML.replace( rinlinejQuery, "" ) :
+ undefined;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ ( support.htmlSerialize || !rnoshimcache.test( value ) ) &&
+ ( support.leadingWhitespace || !rleadingWhitespace.test( value ) ) &&
+ !wrapMap[ (rtagName.exec( value ) || [ "", "" ])[ 1 ].toLowerCase() ] ) {
+
+ value = value.replace( rxhtmlTag, "<$1></$2>" );
+
+ try {
+ for (; i < l; i++ ) {
+ // Remove element nodes and prevent memory leaks
+ elem = this[i] || {};
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch(e) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function() {
+ var arg = arguments[ 0 ];
+
+ // Make the changes, replacing each context element with the new content
+ this.domManip( arguments, function( elem ) {
+ arg = this.parentNode;
+
+ jQuery.cleanData( getAll( this ) );
+
+ if ( arg ) {
+ arg.replaceChild( elem, this );
+ }
+ });
+
+ // Force removal if there was no new content (e.g., from empty arguments)
+ return arg && (arg.length || arg.nodeType) ? this : this.remove();
+ },
+
+ detach: function( selector ) {
+ return this.remove( selector, true );
+ },
+
+ domManip: function( args, callback ) {
+
+ // Flatten any nested arrays
+ args = concat.apply( [], args );
+
+ var first, node, hasScripts,
+ scripts, doc, fragment,
+ i = 0,
+ l = this.length,
+ set = this,
+ iNoClone = l - 1,
+ value = args[0],
+ isFunction = jQuery.isFunction( value );
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction ||
+ ( l > 1 && typeof value === "string" &&
+ !support.checkClone && rchecked.test( value ) ) ) {
+ return this.each(function( index ) {
+ var self = set.eq( index );
+ if ( isFunction ) {
+ args[0] = value.call( this, index, self.html() );
+ }
+ self.domManip( args, callback );
+ });
+ }
+
+ if ( l ) {
+ fragment = jQuery.buildFragment( args, this[ 0 ].ownerDocument, false, this );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ if ( first ) {
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
+
+ // Use the original fragment for the last item instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
+
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
+
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call( this[i], node, i );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !jQuery._data( node, "globalEval" ) && jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+ // Optional AJAX dependency, but won't run scripts if not present
+ if ( jQuery._evalUrl ) {
+ jQuery._evalUrl( node.src );
+ }
+ } else {
+ jQuery.globalEval( ( node.text || node.textContent || node.innerHTML || "" ).replace( rcleanScript, "" ) );
+ }
+ }
+ }
+ }
+
+ // Fix #11809: Avoid leaking memory
+ fragment = first = null;
+ }
+ }
+
+ return this;
+ }
+});
+
+jQuery.each({
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ i = 0,
+ ret = [],
+ insert = jQuery( selector ),
+ last = insert.length - 1;
+
+ for ( ; i <= last; i++ ) {
+ elems = i === last ? this : this.clone(true);
+ jQuery( insert[i] )[ original ]( elems );
+
+ // Modern browsers can apply jQuery collections as arrays, but oldIE needs a .get()
+ push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+});
+
+
+var iframe,
+ elemdisplay = {};
+
+/**
+ * Retrieve the actual display of a element
+ * @param {String} name nodeName of the element
+ * @param {Object} doc Document object
+ */
+// Called only from within defaultDisplay
+function actualDisplay( name, doc ) {
+ var style,
+ elem = jQuery( doc.createElement( name ) ).appendTo( doc.body ),
+
+ // getDefaultComputedStyle might be reliably used only on attached element
+ display = window.getDefaultComputedStyle && ( style = window.getDefaultComputedStyle( elem[ 0 ] ) ) ?
+
+ // Use of this method is a temporary fix (more like optmization) until something better comes along,
+ // since it was removed from specification and supported only in FF
+ style.display : jQuery.css( elem[ 0 ], "display" );
+
+ // We don't have any data stored on the element,
+ // so use "detach" method as fast way to get rid of the element
+ elem.detach();
+
+ return display;
+}
+
+/**
+ * Try to determine the default display value of an element
+ * @param {String} nodeName
+ */
+function defaultDisplay( nodeName ) {
+ var doc = document,
+ display = elemdisplay[ nodeName ];
+
+ if ( !display ) {
+ display = actualDisplay( nodeName, doc );
+
+ // If the simple way fails, read from inside an iframe
+ if ( display === "none" || !display ) {
+
+ // Use the already-created iframe if possible
+ iframe = (iframe || jQuery( "<iframe frameborder='0' width='0' height='0'/>" )).appendTo( doc.documentElement );
+
+ // Always write a new HTML skeleton so Webkit and Firefox don't choke on reuse
+ doc = ( iframe[ 0 ].contentWindow || iframe[ 0 ].contentDocument ).document;
+
+ // Support: IE
+ doc.write();
+ doc.close();
+
+ display = actualDisplay( nodeName, doc );
+ iframe.detach();
+ }
+
+ // Store the correct default display
+ elemdisplay[ nodeName ] = display;
+ }
+
+ return display;
+}
+
+
+(function() {
+ var shrinkWrapBlocksVal;
+
+ support.shrinkWrapBlocks = function() {
+ if ( shrinkWrapBlocksVal != null ) {
+ return shrinkWrapBlocksVal;
+ }
+
+ // Will be changed later if needed.
+ shrinkWrapBlocksVal = false;
+
+ // Minified: var b,c,d
+ var div, body, container;
+
+ body = document.getElementsByTagName( "body" )[ 0 ];
+ if ( !body || !body.style ) {
+ // Test fired too early or in an unsupported environment, exit.
+ return;
+ }
+
+ // Setup
+ div = document.createElement( "div" );
+ container = document.createElement( "div" );
+ container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+ body.appendChild( container ).appendChild( div );
+
+ // Support: IE6
+ // Check if elements with layout shrink-wrap their children
+ if ( typeof div.style.zoom !== strundefined ) {
+ // Reset CSS: box-sizing; display; margin; border
+ div.style.cssText =
+ // Support: Firefox<29, Android 2.3
+ // Vendor-prefix box-sizing
+ "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+ "box-sizing:content-box;display:block;margin:0;border:0;" +
+ "padding:1px;width:1px;zoom:1";
+ div.appendChild( document.createElement( "div" ) ).style.width = "5px";
+ shrinkWrapBlocksVal = div.offsetWidth !== 3;
+ }
+
+ body.removeChild( container );
+
+ return shrinkWrapBlocksVal;
+ };
+
+})();
+var rmargin = (/^margin/);
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+
+
+var getStyles, curCSS,
+ rposition = /^(top|right|bottom|left)$/;
+
+if ( window.getComputedStyle ) {
+ getStyles = function( elem ) {
+ // Support: IE<=11+, Firefox<=30+ (#15098, #14150)
+ // IE throws on elements created in popups
+ // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
+ if ( elem.ownerDocument.defaultView.opener ) {
+ return elem.ownerDocument.defaultView.getComputedStyle( elem, null );
+ }
+
+ return window.getComputedStyle( elem, null );
+ };
+
+ curCSS = function( elem, name, computed ) {
+ var width, minWidth, maxWidth, ret,
+ style = elem.style;
+
+ computed = computed || getStyles( elem );
+
+ // getPropertyValue is only needed for .css('filter') in IE9, see #12537
+ ret = computed ? computed.getPropertyValue( name ) || computed[ name ] : undefined;
+
+ if ( computed ) {
+
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right
+ // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels
+ // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values
+ if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+ // Remember the original values
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ // Put in the new values to get a computed value out
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ // Revert the changed values
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ // Support: IE
+ // IE returns zIndex value as an integer.
+ return ret === undefined ?
+ ret :
+ ret + "";
+ };
+} else if ( document.documentElement.currentStyle ) {
+ getStyles = function( elem ) {
+ return elem.currentStyle;
+ };
+
+ curCSS = function( elem, name, computed ) {
+ var left, rs, rsLeft, ret,
+ style = elem.style;
+
+ computed = computed || getStyles( elem );
+ ret = computed ? computed[ name ] : undefined;
+
+ // Avoid setting ret to empty string here
+ // so we don't default to auto
+ if ( ret == null && style && style[ name ] ) {
+ ret = style[ name ];
+ }
+
+ // From the awesome hack by Dean Edwards
+ // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
+
+ // If we're not dealing with a regular pixel number
+ // but a number that has a weird ending, we need to convert it to pixels
+ // but not position css attributes, as those are proportional to the parent element instead
+ // and we can't measure the parent instead because it might trigger a "stacking dolls" problem
+ if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) {
+
+ // Remember the original values
+ left = style.left;
+ rs = elem.runtimeStyle;
+ rsLeft = rs && rs.left;
+
+ // Put in the new values to get a computed value out
+ if ( rsLeft ) {
+ rs.left = elem.currentStyle.left;
+ }
+ style.left = name === "fontSize" ? "1em" : ret;
+ ret = style.pixelLeft + "px";
+
+ // Revert the changed values
+ style.left = left;
+ if ( rsLeft ) {
+ rs.left = rsLeft;
+ }
+ }
+
+ // Support: IE
+ // IE returns zIndex value as an integer.
+ return ret === undefined ?
+ ret :
+ ret + "" || "auto";
+ };
+}
+
+
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+ // Define the hook, we'll check on the first run if it's really needed.
+ return {
+ get: function() {
+ var condition = conditionFn();
+
+ if ( condition == null ) {
+ // The test was not ready at this point; screw the hook this time
+ // but check again when needed next time.
+ return;
+ }
+
+ if ( condition ) {
+ // Hook not needed (or it's not possible to use it due to missing dependency),
+ // remove it.
+ // Since there are no other hooks for marginRight, remove the whole object.
+ delete this.get;
+ return;
+ }
+
+ // Hook needed; redefine it so that the support test is not executed again.
+
+ return (this.get = hookFn).apply( this, arguments );
+ }
+ };
+}
+
+
+(function() {
+ // Minified: var b,c,d,e,f,g, h,i
+ var div, style, a, pixelPositionVal, boxSizingReliableVal,
+ reliableHiddenOffsetsVal, reliableMarginRightVal;
+
+ // Setup
+ div = document.createElement( "div" );
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+ a = div.getElementsByTagName( "a" )[ 0 ];
+ style = a && a.style;
+
+ // Finish early in limited (non-browser) environments
+ if ( !style ) {
+ return;
+ }
+
+ style.cssText = "float:left;opacity:.5";
+
+ // Support: IE<9
+ // Make sure that element opacity exists (as opposed to filter)
+ support.opacity = style.opacity === "0.5";
+
+ // Verify style float existence
+ // (IE uses styleFloat instead of cssFloat)
+ support.cssFloat = !!style.cssFloat;
+
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ // Support: Firefox<29, Android 2.3
+ // Vendor-prefix box-sizing
+ support.boxSizing = style.boxSizing === "" || style.MozBoxSizing === "" ||
+ style.WebkitBoxSizing === "";
+
+ jQuery.extend(support, {
+ reliableHiddenOffsets: function() {
+ if ( reliableHiddenOffsetsVal == null ) {
+ computeStyleTests();
+ }
+ return reliableHiddenOffsetsVal;
+ },
+
+ boxSizingReliable: function() {
+ if ( boxSizingReliableVal == null ) {
+ computeStyleTests();
+ }
+ return boxSizingReliableVal;
+ },
+
+ pixelPosition: function() {
+ if ( pixelPositionVal == null ) {
+ computeStyleTests();
+ }
+ return pixelPositionVal;
+ },
+
+ // Support: Android 2.3
+ reliableMarginRight: function() {
+ if ( reliableMarginRightVal == null ) {
+ computeStyleTests();
+ }
+ return reliableMarginRightVal;
+ }
+ });
+
+ function computeStyleTests() {
+ // Minified: var b,c,d,j
+ var div, body, container, contents;
+
+ body = document.getElementsByTagName( "body" )[ 0 ];
+ if ( !body || !body.style ) {
+ // Test fired too early or in an unsupported environment, exit.
+ return;
+ }
+
+ // Setup
+ div = document.createElement( "div" );
+ container = document.createElement( "div" );
+ container.style.cssText = "position:absolute;border:0;width:0;height:0;top:0;left:-9999px";
+ body.appendChild( container ).appendChild( div );
+
+ div.style.cssText =
+ // Support: Firefox<29, Android 2.3
+ // Vendor-prefix box-sizing
+ "-webkit-box-sizing:border-box;-moz-box-sizing:border-box;" +
+ "box-sizing:border-box;display:block;margin-top:1%;top:1%;" +
+ "border:1px;padding:1px;width:4px;position:absolute";
+
+ // Support: IE<9
+ // Assume reasonable values in the absence of getComputedStyle
+ pixelPositionVal = boxSizingReliableVal = false;
+ reliableMarginRightVal = true;
+
+ // Check for getComputedStyle so that this code is not run in IE<9.
+ if ( window.getComputedStyle ) {
+ pixelPositionVal = ( window.getComputedStyle( div, null ) || {} ).top !== "1%";
+ boxSizingReliableVal =
+ ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px";
+
+ // Support: Android 2.3
+ // Div with explicit width and no margin-right incorrectly
+ // gets computed margin-right based on width of container (#3333)
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ contents = div.appendChild( document.createElement( "div" ) );
+
+ // Reset CSS: box-sizing; display; margin; border; padding
+ contents.style.cssText = div.style.cssText =
+ // Support: Firefox<29, Android 2.3
+ // Vendor-prefix box-sizing
+ "-webkit-box-sizing:content-box;-moz-box-sizing:content-box;" +
+ "box-sizing:content-box;display:block;margin:0;border:0;padding:0";
+ contents.style.marginRight = contents.style.width = "0";
+ div.style.width = "1px";
+
+ reliableMarginRightVal =
+ !parseFloat( ( window.getComputedStyle( contents, null ) || {} ).marginRight );
+
+ div.removeChild( contents );
+ }
+
+ // Support: IE8
+ // Check if table cells still have offsetWidth/Height when they are set
+ // to display:none and there are still other visible table cells in a
+ // table row; if so, offsetWidth/Height are not reliable for use when
+ // determining if an element has been hidden directly using
+ // display:none (it is still safe to use offsets if a parent element is
+ // hidden; don safety goggles and see bug #4512 for more information).
+ div.innerHTML = "<table><tr><td></td><td>t</td></tr></table>";
+ contents = div.getElementsByTagName( "td" );
+ contents[ 0 ].style.cssText = "margin:0;border:0;padding:0;display:none";
+ reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
+ if ( reliableHiddenOffsetsVal ) {
+ contents[ 0 ].style.display = "";
+ contents[ 1 ].style.display = "none";
+ reliableHiddenOffsetsVal = contents[ 0 ].offsetHeight === 0;
+ }
+
+ body.removeChild( container );
+ }
+
+})();
+
+
+// A method for quickly swapping in/out CSS properties to get correct calculations.
+jQuery.swap = function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+};
+
+
+var
+ ralpha = /alpha\([^)]*\)/i,
+ ropacity = /opacity\s*=\s*([^)]*)/,
+
+ // swappable if display is none or starts with table except "table", "table-cell", or "table-caption"
+ // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+ rnumsplit = new RegExp( "^(" + pnum + ")(.*)$", "i" ),
+ rrelNum = new RegExp( "^([+-])=(" + pnum + ")", "i" ),
+
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: "0",
+ fontWeight: "400"
+ },
+
+ cssPrefixes = [ "Webkit", "O", "Moz", "ms" ];
+
+
+// return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( style, name ) {
+
+ // shortcut for names that are not vendor prefixed
+ if ( name in style ) {
+ return name;
+ }
+
+ // check for vendor prefixed names
+ var capName = name.charAt(0).toUpperCase() + name.slice(1),
+ origName = name,
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in style ) {
+ return name;
+ }
+ }
+
+ return origName;
+}
+
+function showHide( elements, show ) {
+ var display, elem, hidden,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+
+ values[ index ] = jQuery._data( elem, "olddisplay" );
+ display = elem.style.display;
+ if ( show ) {
+ // Reset the inline display of this element to learn if it is
+ // being hidden by cascaded rules or not
+ if ( !values[ index ] && display === "none" ) {
+ elem.style.display = "";
+ }
+
+ // Set elements which have been overridden with display: none
+ // in a stylesheet to whatever the default browser style is
+ // for such an element
+ if ( elem.style.display === "" && isHidden( elem ) ) {
+ values[ index ] = jQuery._data( elem, "olddisplay", defaultDisplay(elem.nodeName) );
+ }
+ } else {
+ hidden = isHidden( elem );
+
+ if ( display && display !== "none" || !hidden ) {
+ jQuery._data( elem, "olddisplay", hidden ? display : jQuery.css( elem, "display" ) );
+ }
+ }
+ }
+
+ // Set the display of most of the elements in a second loop
+ // to avoid the constant reflow
+ for ( index = 0; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+ if ( !show || elem.style.display === "none" || elem.style.display === "" ) {
+ elem.style.display = show ? values[ index ] || "" : "none";
+ }
+ }
+
+ return elements;
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+ var matches = rnumsplit.exec( value );
+ return matches ?
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) :
+ value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i = extra === ( isBorderBox ? "border" : "content" ) ?
+ // If we already have the right measurement, avoid augmentation
+ 4 :
+ // Otherwise initialize for horizontal or vertical properties
+ name === "width" ? 1 : 0,
+
+ val = 0;
+
+ for ( ; i < 4; i += 2 ) {
+ // both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+ }
+
+ if ( isBorderBox ) {
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+ }
+
+ // at this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ } else {
+ // at this point, extra isn't content, so add padding
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+ // at this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ }
+ }
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with offset property, which is equivalent to the border-box value
+ var valueIsBorderBox = true,
+ val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
+ styles = getStyles( elem ),
+ isBorderBox = support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+ // some non-html elements return undefined for offsetWidth, so check for null/undefined
+ // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285
+ // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668
+ if ( val <= 0 || val == null ) {
+ // Fall back to computed then uncomputed css if necessary
+ val = curCSS( elem, name, styles );
+ if ( val < 0 || val == null ) {
+ val = elem.style[ name ];
+ }
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test(val) ) {
+ return val;
+ }
+
+ // we need the check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox && ( support.boxSizingReliable() || val === elem.style[ name ] );
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+ }
+
+ // use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ ) + "px";
+}
+
+jQuery.extend({
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+ }
+ }
+ }
+ },
+
+ // Don't automatically add "px" to these possibly-unitless properties
+ cssNumber: {
+ "columnCount": true,
+ "fillOpacity": true,
+ "flexGrow": true,
+ "flexShrink": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "order": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ // normalize float css property
+ "float": support.cssFloat ? "cssFloat" : "styleFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ style = elem.style;
+
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // convert relative number strings (+= or -=) to relative numbers. #7345
+ if ( type === "string" && (ret = rrelNum.exec( value )) ) {
+ value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) );
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that null and NaN values aren't set. See: #7116
+ if ( value == null || value !== value ) {
+ return;
+ }
+
+ // If a number was passed in, add 'px' to the (except for certain CSS properties)
+ if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
+ value += "px";
+ }
+
+ // Fixes #8908, it can be done more correctly by specifing setters in cssHooks,
+ // but it would mean to define eight (for every problematic property) identical functions
+ if ( !support.clearCloneStyle && value === "" && name.indexOf("background") === 0 ) {
+ style[ name ] = "inherit";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) {
+
+ // Support: IE
+ // Swallow errors from 'invalid' CSS values (#5509)
+ try {
+ style[ name ] = value;
+ } catch(e) {}
+ }
+
+ } else {
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra, styles ) {
+ var num, val, hooks,
+ origName = jQuery.camelCase( name );
+
+ // Make sure that we're working with the right name
+ name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) );
+
+ // gets hook for the prefixed version
+ // followed by the unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name, styles );
+ }
+
+ //convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Return, converting to number if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || jQuery.isNumeric( num ) ? num || 0 : val;
+ }
+ return val;
+ }
+});
+
+jQuery.each([ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+ // certain elements can have dimension info if we invisibly show them
+ // however, it must have a current display style that would benefit from this
+ return rdisplayswap.test( jQuery.css( elem, "display" ) ) && elem.offsetWidth === 0 ?
+ jQuery.swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ }) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var styles = extra && getStyles( elem );
+ return setPositiveNumber( elem, value, extra ?
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ support.boxSizing && jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ ) : 0
+ );
+ }
+ };
+});
+
+if ( !support.opacity ) {
+ jQuery.cssHooks.opacity = {
+ get: function( elem, computed ) {
+ // IE uses filters for opacity
+ return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
+ ( 0.01 * parseFloat( RegExp.$1 ) ) + "" :
+ computed ? "1" : "";
+ },
+
+ set: function( elem, value ) {
+ var style = elem.style,
+ currentStyle = elem.currentStyle,
+ opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
+ filter = currentStyle && currentStyle.filter || style.filter || "";
+
+ // IE has trouble with opacity if it does not have layout
+ // Force it by setting the zoom level
+ style.zoom = 1;
+
+ // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
+ // if value === "", then remove inline opacity #12685
+ if ( ( value >= 1 || value === "" ) &&
+ jQuery.trim( filter.replace( ralpha, "" ) ) === "" &&
+ style.removeAttribute ) {
+
+ // Setting style.filter to null, "" & " " still leave "filter:" in the cssText
+ // if "filter:" is present at all, clearType is disabled, we want to avoid this
+ // style.removeAttribute is IE Only, but so apparently is this code path...
+ style.removeAttribute( "filter" );
+
+ // if there is no filter style applied in a css rule or unset inline opacity, we are done
+ if ( value === "" || currentStyle && !currentStyle.filter ) {
+ return;
+ }
+ }
+
+ // otherwise, set new filter values
+ style.filter = ralpha.test( filter ) ?
+ filter.replace( ralpha, opacity ) :
+ filter + " " + opacity;
+ }
+ };
+}
+
+jQuery.cssHooks.marginRight = addGetHookIf( support.reliableMarginRight,
+ function( elem, computed ) {
+ if ( computed ) {
+ // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
+ // Work around by temporarily setting element display to inline-block
+ return jQuery.swap( elem, { "display": "inline-block" },
+ curCSS, [ elem, "marginRight" ] );
+ }
+ }
+);
+
+// These hooks are used by animate to expand properties
+jQuery.each({
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i = 0,
+ expanded = {},
+
+ // assumes a single number if not a string
+ parts = typeof value === "string" ? value.split(" ") : [ value ];
+
+ for ( ; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+});
+
+jQuery.fn.extend({
+ css: function( name, value ) {
+ return access( this, function( elem, name, value ) {
+ var styles, len,
+ map = {},
+ i = 0;
+
+ if ( jQuery.isArray( name ) ) {
+ styles = getStyles( elem );
+ len = name.length;
+
+ for ( ; i < len; i++ ) {
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+ }
+
+ return map;
+ }
+
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ },
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ if ( typeof state === "boolean" ) {
+ return state ? this.show() : this.hide();
+ }
+
+ return this.each(function() {
+ if ( isHidden( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ });
+ }
+});
+
+
+function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || "swing";
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ if ( tween.elem[ tween.prop ] != null &&
+ (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails
+ // so, simple values such as "10px" are parsed to Float.
+ // complex values such as "rotate(1rad)" are returned as is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+ // use step hook for back compat - use cssHook if its there - use .style if its
+ // available and use plain properties where available
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+};
+
+// Support: IE <=9
+// Panic based approach to setting things on disconnected nodes
+
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+};
+
+jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p * Math.PI ) / 2;
+ }
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back Compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+ fxNow, timerId,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rfxnum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" ),
+ rrun = /queueHooks$/,
+ animationPrefilters = [ defaultPrefilter ],
+ tweeners = {
+ "*": [ function( prop, value ) {
+ var tween = this.createTween( prop, value ),
+ target = tween.cur(),
+ parts = rfxnum.exec( value ),
+ unit = parts && parts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+ // Starting value computation is required for potential unit mismatches
+ start = ( jQuery.cssNumber[ prop ] || unit !== "px" && +target ) &&
+ rfxnum.exec( jQuery.css( tween.elem, prop ) ),
+ scale = 1,
+ maxIterations = 20;
+
+ if ( start && start[ 3 ] !== unit ) {
+ // Trust units reported by jQuery.css
+ unit = unit || start[ 3 ];
+
+ // Make sure we update the tween properties later on
+ parts = parts || [];
+
+ // Iteratively approximate from a nonzero starting point
+ start = +target || 1;
+
+ do {
+ // If previous iteration zeroed out, double until we get *something*
+ // Use a string for doubling factor so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ start = start / scale;
+ jQuery.style( tween.elem, prop, start + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // And breaking the loop if scale is unchanged or perfect, or if we've just had enough
+ } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations );
+ }
+
+ // Update tween properties
+ if ( parts ) {
+ start = tween.start = +start || +target || 0;
+ tween.unit = unit;
+ // If a +=/-= token was provided, we're doing a relative animation
+ tween.end = parts[ 1 ] ?
+ start + ( parts[ 1 ] + 1 ) * parts[ 2 ] :
+ +parts[ 2 ];
+ }
+
+ return tween;
+ } ]
+ };
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ setTimeout(function() {
+ fxNow = undefined;
+ });
+ return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+ var which,
+ attrs = { height: type },
+ i = 0;
+
+ // if we include width, step value is 1 to do all cssExpand values,
+ // if we don't include width, step value is 2 to skip over Left and Right
+ includeWidth = includeWidth ? 1 : 0;
+ for ( ; i < 4 ; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+}
+
+function createTween( value, prop, animation ) {
+ var tween,
+ collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( (tween = collection[ index ].call( animation, prop, value )) ) {
+
+ // we're done with this property
+ return tween;
+ }
+ }
+}
+
+function defaultPrefilter( elem, props, opts ) {
+ /* jshint validthis: true */
+ var prop, value, toggle, tween, hooks, oldfire, display, checkDisplay,
+ anim = this,
+ orig = {},
+ style = elem.style,
+ hidden = elem.nodeType && isHidden( elem ),
+ dataShow = jQuery._data( elem, "fxshow" );
+
+ // handle queue: false promises
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always(function() {
+ // doing this makes sure that the complete handler will be called
+ // before this completes
+ anim.always(function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ });
+ });
+ }
+
+ // height/width overflow pass
+ if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) {
+ // Make sure that nothing sneaks out
+ // Record all 3 overflow attributes because IE does not
+ // change the overflow attribute when overflowX and
+ // overflowY are set to the same value
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Set display property to inline-block for height/width
+ // animations on inline elements that are having width/height animated
+ display = jQuery.css( elem, "display" );
+
+ // Test default display if display is currently "none"
+ checkDisplay = display === "none" ?
+ jQuery._data( elem, "olddisplay" ) || defaultDisplay( elem.nodeName ) : display;
+
+ if ( checkDisplay === "inline" && jQuery.css( elem, "float" ) === "none" ) {
+
+ // inline-level elements accept inline-block;
+ // block-level elements need to be inline with layout
+ if ( !support.inlineBlockNeedsLayout || defaultDisplay( elem.nodeName ) === "inline" ) {
+ style.display = "inline-block";
+ } else {
+ style.zoom = 1;
+ }
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ if ( !support.shrinkWrapBlocks() ) {
+ anim.always(function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ });
+ }
+ }
+
+ // show/hide pass
+ for ( prop in props ) {
+ value = props[ prop ];
+ if ( rfxtypes.exec( value ) ) {
+ delete props[ prop ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+
+ // If there is dataShow left over from a stopped hide or show and we are going to proceed with show, we should pretend to be hidden
+ if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+ hidden = true;
+ } else {
+ continue;
+ }
+ }
+ orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+
+ // Any non-fx value stops us from restoring the original display value
+ } else {
+ display = undefined;
+ }
+ }
+
+ if ( !jQuery.isEmptyObject( orig ) ) {
+ if ( dataShow ) {
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+ } else {
+ dataShow = jQuery._data( elem, "fxshow", {} );
+ }
+
+ // store state if its toggle - enables .stop().toggle() to "reverse"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+ if ( hidden ) {
+ jQuery( elem ).show();
+ } else {
+ anim.done(function() {
+ jQuery( elem ).hide();
+ });
+ }
+ anim.done(function() {
+ var prop;
+ jQuery._removeData( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ });
+ for ( prop in orig ) {
+ tween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = tween.start;
+ if ( hidden ) {
+ tween.end = tween.start;
+ tween.start = prop === "width" || prop === "height" ? 1 : 0;
+ }
+ }
+ }
+
+ // If this is a noop like .hide().hide(), restore an overwritten display value
+ } else if ( (display === "none" ? defaultDisplay( elem.nodeName ) : display) === "inline" ) {
+ style.display = display;
+ }
+}
+
+function propFilter( props, specialEasing ) {
+ var index, name, easing, value, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( jQuery.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // not quite $.extend, this wont overwrite keys already present.
+ // also - reusing 'index' from above because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+}
+
+function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = animationPrefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+ // don't match elem in the :animated selector
+ delete tick.elem;
+ }),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+ // archaic crash bug won't allow us to use 1 - ( 0.5 || 0 ) (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ]);
+
+ if ( percent < 1 && length ) {
+ return remaining;
+ } else {
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ }
+ },
+ animation = deferred.promise({
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, { specialEasing: {} }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+ // if we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length ; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // resolve when we played the last frame
+ // otherwise, reject
+ if ( gotoEnd ) {
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ }),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length ; index++ ) {
+ result = animationPrefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ return result;
+ }
+ }
+
+ jQuery.map( props, createTween, animation );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ })
+ );
+
+ // attach callbacks from options
+ return animation.progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.split(" ");
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length ; index++ ) {
+ prop = props[ index ];
+ tweeners[ prop ] = tweeners[ prop ] || [];
+ tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ animationPrefilters.unshift( callback );
+ } else {
+ animationPrefilters.push( callback );
+ }
+ }
+});
+
+jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
+ opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default;
+
+ // normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+};
+
+jQuery.fn.extend({
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // show any hidden elements after setting opacity to 0
+ return this.filter( isHidden ).css( "opacity", 0 ).show()
+
+ // animate to the value specified
+ .end().animate({ opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+ // Empty animations, or finishing resolves immediately
+ if ( empty || jQuery._data( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each(function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = jQuery._data( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // start the next in the queue if the last step wasn't forced
+ // timers currently will call their complete callbacks, which will dequeue
+ // but only if they were gotoEnd
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ });
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each(function() {
+ var index,
+ data = jQuery._data( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // enable finishing flag on private data
+ data.finish = true;
+
+ // empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.stop ) {
+ hooks.stop.call( this, true );
+ }
+
+ // look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // turn off finishing flag
+ delete data.finish;
+ });
+ }
+});
+
+jQuery.each([ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+});
+
+// Generate shortcuts for custom animations
+jQuery.each({
+ slideDown: genFx("show"),
+ slideUp: genFx("hide"),
+ slideToggle: genFx("toggle"),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+});
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+ var timer,
+ timers = jQuery.timers,
+ i = 0;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+ // Checks the timer has not already been removed
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+ jQuery.timers.push( timer );
+ if ( timer() ) {
+ jQuery.fx.start();
+ } else {
+ jQuery.timers.pop();
+ }
+};
+
+jQuery.fx.interval = 13;
+
+jQuery.fx.start = function() {
+ if ( !timerId ) {
+ timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval );
+ }
+};
+
+jQuery.fx.stop = function() {
+ clearInterval( timerId );
+ timerId = null;
+};
+
+jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+ // Default speed
+ _default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = setTimeout( next, time );
+ hooks.stop = function() {
+ clearTimeout( timeout );
+ };
+ });
+};
+
+
+(function() {
+ // Minified: var a,b,c,d,e
+ var input, div, select, a, opt;
+
+ // Setup
+ div = document.createElement( "div" );
+ div.setAttribute( "className", "t" );
+ div.innerHTML = " <link/><table></table><a href='/a'>a</a><input type='checkbox'/>";
+ a = div.getElementsByTagName("a")[ 0 ];
+
+ // First batch of tests.
+ select = document.createElement("select");
+ opt = select.appendChild( document.createElement("option") );
+ input = div.getElementsByTagName("input")[ 0 ];
+
+ a.style.cssText = "top:1px";
+
+ // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
+ support.getSetAttribute = div.className !== "t";
+
+ // Get the style information from getAttribute
+ // (IE uses .cssText instead)
+ support.style = /top/.test( a.getAttribute("style") );
+
+ // Make sure that URLs aren't manipulated
+ // (IE normalizes it by default)
+ support.hrefNormalized = a.getAttribute("href") === "/a";
+
+ // Check the default checkbox/radio value ("" on WebKit; "on" elsewhere)
+ support.checkOn = !!input.value;
+
+ // Make sure that a selected-by-default option has a working selected property.
+ // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
+ support.optSelected = opt.selected;
+
+ // Tests for enctype support on a form (#6743)
+ support.enctype = !!document.createElement("form").enctype;
+
+ // Make sure that the options inside disabled selects aren't marked as disabled
+ // (WebKit marks them as disabled)
+ select.disabled = true;
+ support.optDisabled = !opt.disabled;
+
+ // Support: IE8 only
+ // Check if we can trust getAttribute("value")
+ input = document.createElement( "input" );
+ input.setAttribute( "value", "" );
+ support.input = input.getAttribute( "value" ) === "";
+
+ // Check if an input maintains its value after becoming a radio
+ input.value = "t";
+ input.setAttribute( "type", "radio" );
+ support.radioValue = input.value === "t";
+})();
+
+
+var rreturn = /\r/g;
+
+jQuery.fn.extend({
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[0];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ return typeof ret === "string" ?
+ // handle most common string cases
+ ret.replace(rreturn, "") :
+ // handle cases where value is null/undef or number
+ ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each(function( i ) {
+ var val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, jQuery( this ).val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+ } else if ( typeof val === "number" ) {
+ val += "";
+ } else if ( jQuery.isArray( val ) ) {
+ val = jQuery.map( val, function( value ) {
+ return value == null ? "" : value + "";
+ });
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ });
+ }
+});
+
+jQuery.extend({
+ valHooks: {
+ option: {
+ get: function( elem ) {
+ var val = jQuery.find.attr( elem, "value" );
+ return val != null ?
+ val :
+ // Support: IE10-11+
+ // option.text throws exceptions (#14686, #14858)
+ jQuery.trim( jQuery.text( elem ) );
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one" || index < 0,
+ values = one ? null : [],
+ max = one ? index + 1 : options.length,
+ i = index < 0 ?
+ max :
+ one ? index : 0;
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // oldIE doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+ // Don't return options that are disabled or in a disabled optgroup
+ ( support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null ) &&
+ ( !option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var optionSet, option,
+ options = elem.options,
+ values = jQuery.makeArray( value ),
+ i = options.length;
+
+ while ( i-- ) {
+ option = options[ i ];
+
+ if ( jQuery.inArray( jQuery.valHooks.option.get( option ), values ) >= 0 ) {
+
+ // Support: IE6
+ // When new option element is added to select box we need to
+ // force reflow of newly added node in order to workaround delay
+ // of initialization properties
+ try {
+ option.selected = optionSet = true;
+
+ } catch ( _ ) {
+
+ // Will be executed only in IE6
+ option.scrollHeight;
+ }
+
+ } else {
+ option.selected = false;
+ }
+ }
+
+ // Force browsers to behave consistently when non-matching value is set
+ if ( !optionSet ) {
+ elem.selectedIndex = -1;
+ }
+
+ return options;
+ }
+ }
+ }
+});
+
+// Radios and checkboxes getter/setter
+jQuery.each([ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ set: function( elem, value ) {
+ if ( jQuery.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
+ }
+ }
+ };
+ if ( !support.checkOn ) {
+ jQuery.valHooks[ this ].get = function( elem ) {
+ // Support: Webkit
+ // "" is returned instead of "on" if a value isn't specified
+ return elem.getAttribute("value") === null ? "on" : elem.value;
+ };
+ }
+});
+
+
+
+
+var nodeHook, boolHook,
+ attrHandle = jQuery.expr.attrHandle,
+ ruseDefault = /^(?:checked|selected)$/i,
+ getSetAttribute = support.getSetAttribute,
+ getSetInput = support.input;
+
+jQuery.fn.extend({
+ attr: function( name, value ) {
+ return access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each(function() {
+ jQuery.removeAttr( this, name );
+ });
+ }
+});
+
+jQuery.extend({
+ attr: function( elem, name, value ) {
+ var hooks, ret,
+ nType = elem.nodeType;
+
+ // don't get/set attributes on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === strundefined ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ // All attributes are lowercase
+ // Grab necessary hook if one is defined
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+ name = name.toLowerCase();
+ hooks = jQuery.attrHooks[ name ] ||
+ ( jQuery.expr.match.bool.test( name ) ? boolHook : nodeHook );
+ }
+
+ if ( value !== undefined ) {
+
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+
+ } else if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
+ return ret;
+
+ } else {
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ } else if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
+ return ret;
+
+ } else {
+ ret = jQuery.find.attr( elem, name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ?
+ undefined :
+ ret;
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name, propName,
+ i = 0,
+ attrNames = value && value.match( rnotwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( (name = attrNames[i++]) ) {
+ propName = jQuery.propFix[ name ] || name;
+
+ // Boolean attributes get special treatment (#10870)
+ if ( jQuery.expr.match.bool.test( name ) ) {
+ // Set corresponding property to false
+ if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+ elem[ propName ] = false;
+ // Support: IE<9
+ // Also clear defaultChecked/defaultSelected (if appropriate)
+ } else {
+ elem[ jQuery.camelCase( "default-" + name ) ] =
+ elem[ propName ] = false;
+ }
+
+ // See #9699 for explanation of this approach (setting first, then removal)
+ } else {
+ jQuery.attr( elem, name, "" );
+ }
+
+ elem.removeAttribute( getSetAttribute ? name : propName );
+ }
+ }
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
+ // Setting the type on a radio button after the value resets the value in IE6-9
+ // Reset value to default in case type is set after value during creation
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ }
+});
+
+// Hook for boolean attributes
+boolHook = {
+ set: function( elem, value, name ) {
+ if ( value === false ) {
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else if ( getSetInput && getSetAttribute || !ruseDefault.test( name ) ) {
+ // IE<8 needs the *property* name
+ elem.setAttribute( !getSetAttribute && jQuery.propFix[ name ] || name, name );
+
+ // Use defaultChecked and defaultSelected for oldIE
+ } else {
+ elem[ jQuery.camelCase( "default-" + name ) ] = elem[ name ] = true;
+ }
+
+ return name;
+ }
+};
+
+// Retrieve booleans specially
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+
+ var getter = attrHandle[ name ] || jQuery.find.attr;
+
+ attrHandle[ name ] = getSetInput && getSetAttribute || !ruseDefault.test( name ) ?
+ function( elem, name, isXML ) {
+ var ret, handle;
+ if ( !isXML ) {
+ // Avoid an infinite loop by temporarily removing this function from the getter
+ handle = attrHandle[ name ];
+ attrHandle[ name ] = ret;
+ ret = getter( elem, name, isXML ) != null ?
+ name.toLowerCase() :
+ null;
+ attrHandle[ name ] = handle;
+ }
+ return ret;
+ } :
+ function( elem, name, isXML ) {
+ if ( !isXML ) {
+ return elem[ jQuery.camelCase( "default-" + name ) ] ?
+ name.toLowerCase() :
+ null;
+ }
+ };
+});
+
+// fix oldIE attroperties
+if ( !getSetInput || !getSetAttribute ) {
+ jQuery.attrHooks.value = {
+ set: function( elem, value, name ) {
+ if ( jQuery.nodeName( elem, "input" ) ) {
+ // Does not return so that setAttribute is also used
+ elem.defaultValue = value;
+ } else {
+ // Use nodeHook if defined (#1954); otherwise setAttribute is fine
+ return nodeHook && nodeHook.set( elem, value, name );
+ }
+ }
+ };
+}
+
+// IE6/7 do not support getting/setting some attributes with get/setAttribute
+if ( !getSetAttribute ) {
+
+ // Use this for any attribute in IE6/7
+ // This fixes almost every IE6/7 issue
+ nodeHook = {
+ set: function( elem, value, name ) {
+ // Set the existing or create a new attribute node
+ var ret = elem.getAttributeNode( name );
+ if ( !ret ) {
+ elem.setAttributeNode(
+ (ret = elem.ownerDocument.createAttribute( name ))
+ );
+ }
+
+ ret.value = value += "";
+
+ // Break association with cloned elements by also using setAttribute (#9646)
+ if ( name === "value" || value === elem.getAttribute( name ) ) {
+ return value;
+ }
+ }
+ };
+
+ // Some attributes are constructed with empty-string values when not defined
+ attrHandle.id = attrHandle.name = attrHandle.coords =
+ function( elem, name, isXML ) {
+ var ret;
+ if ( !isXML ) {
+ return (ret = elem.getAttributeNode( name )) && ret.value !== "" ?
+ ret.value :
+ null;
+ }
+ };
+
+ // Fixing value retrieval on a button requires this module
+ jQuery.valHooks.button = {
+ get: function( elem, name ) {
+ var ret = elem.getAttributeNode( name );
+ if ( ret && ret.specified ) {
+ return ret.value;
+ }
+ },
+ set: nodeHook.set
+ };
+
+ // Set contenteditable to false on removals(#10429)
+ // Setting to empty string throws an error as an invalid value
+ jQuery.attrHooks.contenteditable = {
+ set: function( elem, value, name ) {
+ nodeHook.set( elem, value === "" ? false : value, name );
+ }
+ };
+
+ // Set width and height to auto instead of 0 on empty string( Bug #8150 )
+ // This is for removals
+ jQuery.each([ "width", "height" ], function( i, name ) {
+ jQuery.attrHooks[ name ] = {
+ set: function( elem, value ) {
+ if ( value === "" ) {
+ elem.setAttribute( name, "auto" );
+ return value;
+ }
+ }
+ };
+ });
+}
+
+if ( !support.style ) {
+ jQuery.attrHooks.style = {
+ get: function( elem ) {
+ // Return undefined in the case of empty string
+ // Note: IE uppercases css property names, but if we were to .toLowerCase()
+ // .cssText, that would destroy case senstitivity in URL's, like in "background"
+ return elem.style.cssText || undefined;
+ },
+ set: function( elem, value ) {
+ return ( elem.style.cssText = value + "" );
+ }
+ };
+}
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button|object)$/i,
+ rclickable = /^(?:a|area)$/i;
+
+jQuery.fn.extend({
+ prop: function( name, value ) {
+ return access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ name = jQuery.propFix[ name ] || name;
+ return this.each(function() {
+ // try/catch handles cases where IE balks (such as removing a property on window)
+ try {
+ this[ name ] = undefined;
+ delete this[ name ];
+ } catch( e ) {}
+ });
+ }
+});
+
+jQuery.extend({
+ propFix: {
+ "for": "htmlFor",
+ "class": "className"
+ },
+
+ prop: function( elem, name, value ) {
+ var ret, hooks, notxml,
+ nType = elem.nodeType;
+
+ // don't get/set properties on text, comment and attribute nodes
+ if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
+
+ if ( notxml ) {
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ return hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ?
+ ret :
+ ( elem[ name ] = value );
+
+ } else {
+ return hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ?
+ ret :
+ elem[ name ];
+ }
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+ // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
+ // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ // Use proper attribute retrieval(#12072)
+ var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+ return tabindex ?
+ parseInt( tabindex, 10 ) :
+ rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
+ 0 :
+ -1;
+ }
+ }
+ }
+});
+
+// Some attributes require a special call on IE
+// http://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !support.hrefNormalized ) {
+ // href/src property should get the full normalized URL (#10299/#12915)
+ jQuery.each([ "href", "src" ], function( i, name ) {
+ jQuery.propHooks[ name ] = {
+ get: function( elem ) {
+ return elem.getAttribute( name, 4 );
+ }
+ };
+ });
+}
+
+// Support: Safari, IE9+
+// mis-reports the default selected property of an option
+// Accessing the parent's selectedIndex property fixes it
+if ( !support.optSelected ) {
+ jQuery.propHooks.selected = {
+ get: function( elem ) {
+ var parent = elem.parentNode;
+
+ if ( parent ) {
+ parent.selectedIndex;
+
+ // Make sure that it also works with optgroups, see #5701
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ return null;
+ }
+ };
+}
+
+jQuery.each([
+ "tabIndex",
+ "readOnly",
+ "maxLength",
+ "cellSpacing",
+ "cellPadding",
+ "rowSpan",
+ "colSpan",
+ "useMap",
+ "frameBorder",
+ "contentEditable"
+], function() {
+ jQuery.propFix[ this.toLowerCase() ] = this;
+});
+
+// IE6/7 call enctype encoding
+if ( !support.enctype ) {
+ jQuery.propFix.enctype = "encoding";
+}
+
+
+
+
+var rclass = /[\t\r\n\f]/g;
+
+jQuery.fn.extend({
+ addClass: function( value ) {
+ var classes, elem, cur, clazz, j, finalValue,
+ i = 0,
+ len = this.length,
+ proceed = typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).addClass( value.call( this, j, this.className ) );
+ });
+ }
+
+ if ( proceed ) {
+ // The disjunction here is for better compressibility (see removeClass)
+ classes = ( value || "" ).match( rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ " "
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+
+ // only assign if different to avoid unneeded rendering.
+ finalValue = jQuery.trim( cur );
+ if ( elem.className !== finalValue ) {
+ elem.className = finalValue;
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, clazz, j, finalValue,
+ i = 0,
+ len = this.length,
+ proceed = arguments.length === 0 || typeof value === "string" && value;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, this.className ) );
+ });
+ }
+ if ( proceed ) {
+ classes = ( value || "" ).match( rnotwhite ) || [];
+
+ for ( ; i < len; i++ ) {
+ elem = this[ i ];
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 && ( elem.className ?
+ ( " " + elem.className + " " ).replace( rclass, " " ) :
+ ""
+ );
+
+ if ( cur ) {
+ j = 0;
+ while ( (clazz = classes[j++]) ) {
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) >= 0 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+
+ // only assign if different to avoid unneeded rendering.
+ finalValue = value ? jQuery.trim( cur ) : "";
+ if ( elem.className !== finalValue ) {
+ elem.className = finalValue;
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value;
+
+ if ( typeof stateVal === "boolean" && type === "string" ) {
+ return stateVal ? this.addClass( value ) : this.removeClass( value );
+ }
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each(function( i ) {
+ jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal );
+ });
+ }
+
+ return this.each(function() {
+ if ( type === "string" ) {
+ // toggle individual class names
+ var className,
+ i = 0,
+ self = jQuery( this ),
+ classNames = value.match( rnotwhite ) || [];
+
+ while ( (className = classNames[ i++ ]) ) {
+ // check each className given, space separated list
+ if ( self.hasClass( className ) ) {
+ self.removeClass( className );
+ } else {
+ self.addClass( className );
+ }
+ }
+
+ // Toggle whole class name
+ } else if ( type === strundefined || type === "boolean" ) {
+ if ( this.className ) {
+ // store className if set
+ jQuery._data( this, "__className__", this.className );
+ }
+
+ // If the element has a class name or if we're passed "false",
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
+ }
+ });
+ },
+
+ hasClass: function( selector ) {
+ var className = " " + selector + " ",
+ i = 0,
+ l = this.length;
+ for ( ; i < l; i++ ) {
+ if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+});
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+});
+
+jQuery.fn.extend({
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ },
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn );
+ }
+});
+
+
+var nonce = jQuery.now();
+
+var rquery = (/\?/);
+
+
+
+var rvalidtokens = /(,)|(\[|{)|(}|])|"(?:[^"\\\r\n]|\\["\\\/bfnrt]|\\u[\da-fA-F]{4})*"\s*:?|true|false|null|-?(?!0\d)\d+(?:\.\d+|)(?:[eE][+-]?\d+|)/g;
+
+jQuery.parseJSON = function( data ) {
+ // Attempt to parse using the native JSON parser first
+ if ( window.JSON && window.JSON.parse ) {
+ // Support: Android 2.3
+ // Workaround failure to string-cast null input
+ return window.JSON.parse( data + "" );
+ }
+
+ var requireNonComma,
+ depth = null,
+ str = jQuery.trim( data + "" );
+
+ // Guard against invalid (and possibly dangerous) input by ensuring that nothing remains
+ // after removing valid tokens
+ return str && !jQuery.trim( str.replace( rvalidtokens, function( token, comma, open, close ) {
+
+ // Force termination if we see a misplaced comma
+ if ( requireNonComma && comma ) {
+ depth = 0;
+ }
+
+ // Perform no more replacements after returning to outermost depth
+ if ( depth === 0 ) {
+ return token;
+ }
+
+ // Commas must not follow "[", "{", or ","
+ requireNonComma = open || comma;
+
+ // Determine new depth
+ // array/object open ("[" or "{"): depth += true - false (increment)
+ // array/object close ("]" or "}"): depth += false - true (decrement)
+ // other cases ("," or primitive): depth += true - true (numeric cast)
+ depth += !close - !open;
+
+ // Remove this token
+ return "";
+ }) ) ?
+ ( Function( "return " + str ) )() :
+ jQuery.error( "Invalid JSON: " + data );
+};
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+ var xml, tmp;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ try {
+ if ( window.DOMParser ) { // Standard
+ tmp = new DOMParser();
+ xml = tmp.parseFromString( data, "text/xml" );
+ } else { // IE
+ xml = new ActiveXObject( "Microsoft.XMLDOM" );
+ xml.async = "false";
+ xml.loadXML( data );
+ }
+ } catch( e ) {
+ xml = undefined;
+ }
+ if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+};
+
+
+var
+ // Document location
+ ajaxLocParts,
+ ajaxLocation,
+
+ rhash = /#.*$/,
+ rts = /([?&])_=[^&]*/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+ rurl = /^([\w.+-]+:)(?:\/\/(?:[^\/?#]*@|)([^\/?#:]*)(?::(\d+)|)|)/,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = "*/".concat("*");
+
+// #8138, IE may throw an exception when accessing
+// a field from window.location if document.domain has been set
+try {
+ ajaxLocation = location.href;
+} catch( e ) {
+ // Use the href attribute of an A element
+ // since IE will modify it given document.location
+ ajaxLocation = document.createElement( "a" );
+ ajaxLocation.href = "";
+ ajaxLocation = ajaxLocation.href;
+}
+
+// Segment location into parts
+ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ var dataType,
+ i = 0,
+ dataTypes = dataTypeExpression.toLowerCase().match( rnotwhite ) || [];
+
+ if ( jQuery.isFunction( func ) ) {
+ // For each dataType in the dataTypeExpression
+ while ( (dataType = dataTypes[i++]) ) {
+ // Prepend if requested
+ if ( dataType.charAt( 0 ) === "+" ) {
+ dataType = dataType.slice( 1 ) || "*";
+ (structure[ dataType ] = structure[ dataType ] || []).unshift( func );
+
+ // Otherwise append
+ } else {
+ (structure[ dataType ] = structure[ dataType ] || []).push( func );
+ }
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+ var inspected = {},
+ seekingTransport = ( structure === transports );
+
+ function inspect( dataType ) {
+ var selected;
+ inspected[ dataType ] = true;
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+ if ( typeof dataTypeOrTransport === "string" && !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+ options.dataTypes.unshift( dataTypeOrTransport );
+ inspect( dataTypeOrTransport );
+ return false;
+ } else if ( seekingTransport ) {
+ return !( selected = dataTypeOrTransport );
+ }
+ });
+ return selected;
+ }
+
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var deep, key,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || (deep = {}) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+
+ return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+ var firstDataType, ct, finalDataType, type,
+ contents = s.contents,
+ dataTypes = s.dataTypes;
+
+ // Remove auto dataType and get content-type in the process
+ while ( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader("Content-Type");
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+ var conv2, current, conv, tmp, prev,
+ converters = {},
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice();
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ current = dataTypes.shift();
+
+ // Convert to each sequential dataType
+ while ( current ) {
+
+ if ( s.responseFields[ current ] ) {
+ jqXHR[ s.responseFields[ current ] ] = response;
+ }
+
+ // Apply the dataFilter if provided
+ if ( !prev && isSuccess && s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ prev = current;
+ current = dataTypes.shift();
+
+ if ( current ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current === "*" ) {
+
+ current = prev;
+
+ // Convert response if prev dataType is non-auto and differs from current
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split( " " );
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.unshift( tmp[ 1 ] );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s[ "throws" ] ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current };
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return { state: "success", data: response };
+}
+
+jQuery.extend({
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: ajaxLocation,
+ type: "GET",
+ isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /xml/,
+ html: /html/,
+ json: /json/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText",
+ json: "responseJSON"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": jQuery.parseJSON,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var // Cross-domain detection vars
+ parts,
+ // Loop variable
+ i,
+ // URL without anti-cache param
+ cacheURL,
+ // Response headers as string
+ responseHeadersString,
+ // timeout handle
+ timeoutTimer,
+
+ // To know if global events are to be dispatched
+ fireGlobals,
+
+ transport,
+ // Response headers
+ responseHeaders,
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+ // Callbacks context
+ callbackContext = s.context || s,
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context && ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks("once memory"),
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+ // The jqXHR state
+ state = 0,
+ // Default abort message
+ strAbort = "canceled",
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( state === 2 ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( (match = rheaders.exec( responseHeadersString )) ) {
+ responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return state === 2 ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ var lname = name.toLowerCase();
+ if ( !state ) {
+ name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( !state ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( state < 2 ) {
+ for ( code in map ) {
+ // Lazy-add the new callback in a way that preserves old ones
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ } else {
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR ).complete = completeDeferred.add;
+ jqXHR.success = jqXHR.done;
+ jqXHR.error = jqXHR.fail;
+
+ // Remove hash character (#7531: and string promotion)
+ // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || ajaxLocation ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().match( rnotwhite ) || [ "" ];
+
+ // A cross-domain request is in order when we have a protocol:host:port mismatch
+ if ( s.crossDomain == null ) {
+ parts = rurl.exec( s.url.toLowerCase() );
+ s.crossDomain = !!( parts &&
+ ( parts[ 1 ] !== ajaxLocParts[ 1 ] || parts[ 2 ] !== ajaxLocParts[ 2 ] ||
+ ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? "80" : "443" ) ) !==
+ ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? "80" : "443" ) ) )
+ );
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( state === 2 ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
+ fireGlobals = jQuery.event && s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger("ajaxStart");
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ cacheURL = s.url;
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL = ( s.url += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data );
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add anti-cache in url if needed
+ if ( s.cache === false ) {
+ s.url = rts.test( cacheURL ) ?
+
+ // If there is already a '_' parameter, set its value
+ cacheURL.replace( rts, "$1_=" + nonce++ ) :
+
+ // Otherwise add one to the end
+ cacheURL + ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + nonce++;
+ }
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
+ s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ for ( i in { success: 1, error: 1, complete: 1 } ) {
+ jqXHR[ i ]( s[ i ] );
+ }
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = setTimeout(function() {
+ jqXHR.abort("timeout");
+ }, s.timeout );
+ }
+
+ try {
+ state = 1;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+ // Propagate exception as error if not done
+ if ( state < 2 ) {
+ done( -1, e );
+ // Simply rethrow otherwise
+ } else {
+ throw e;
+ }
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Called once
+ if ( state === 2 ) {
+ return;
+ }
+
+ // State is "done" now
+ state = 2;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Determine if successful
+ isSuccess = status >= 200 && status < 300 || status === 304;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // Convert no matter what (that way responseXXX fields are always set)
+ response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+ // If successful, handle type chaining
+ if ( isSuccess ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader("Last-Modified");
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader("etag");
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 || s.type === "HEAD" ) {
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ statusText = response.state;
+ success = response.data;
+ error = response.error;
+ isSuccess = !error;
+ }
+ } else {
+ // We extract error from statusText
+ // then normalize statusText and status for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger("ajaxStop");
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ }
+});
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+ // shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ return jQuery.ajax({
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ });
+ };
+});
+
+
+jQuery._evalUrl = function( url ) {
+ return jQuery.ajax({
+ url: url,
+ type: "GET",
+ dataType: "script",
+ async: false,
+ global: false,
+ "throws": true
+ });
+};
+
+
+jQuery.fn.extend({
+ wrapAll: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapAll( html.call(this, i) );
+ });
+ }
+
+ if ( this[0] ) {
+ // The elements to wrap the target around
+ var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
+
+ if ( this[0].parentNode ) {
+ wrap.insertBefore( this[0] );
+ }
+
+ wrap.map(function() {
+ var elem = this;
+
+ while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
+ elem = elem.firstChild;
+ }
+
+ return elem;
+ }).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each(function(i) {
+ jQuery(this).wrapInner( html.call(this, i) );
+ });
+ }
+
+ return this.each(function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ });
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each(function(i) {
+ jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html );
+ });
+ },
+
+ unwrap: function() {
+ return this.parent().each(function() {
+ if ( !jQuery.nodeName( this, "body" ) ) {
+ jQuery( this ).replaceWith( this.childNodes );
+ }
+ }).end();
+ }
+});
+
+
+jQuery.expr.filters.hidden = function( elem ) {
+ // Support: Opera <= 12.12
+ // Opera reports offsetWidths and offsetHeights less than zero on some elements
+ return elem.offsetWidth <= 0 && elem.offsetHeight <= 0 ||
+ (!support.reliableHiddenOffsets() &&
+ ((elem.style && elem.style.display) || jQuery.css( elem, "display" )) === "none");
+};
+
+jQuery.expr.filters.visible = function( elem ) {
+ return !jQuery.expr.filters.hidden( elem );
+};
+
+
+
+
+var r20 = /%20/g,
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( jQuery.isArray( obj ) ) {
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add );
+ }
+ });
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, value ) {
+ // If value is a function, invoke it and return its value
+ value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
+ s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
+ };
+
+ // Set traditional to true for jQuery <= 1.3.2 behavior.
+ if ( traditional === undefined ) {
+ traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+ }
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ });
+
+ } else {
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" ).replace( r20, "+" );
+};
+
+jQuery.fn.extend({
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map(function() {
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ })
+ .filter(function() {
+ var type = this.type;
+ // Use .is(":disabled") so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !rcheckableType.test( type ) );
+ })
+ .map(function( i, elem ) {
+ var val = jQuery( this ).val();
+
+ return val == null ?
+ null :
+ jQuery.isArray( val ) ?
+ jQuery.map( val, function( val ) {
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }) :
+ { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ }).get();
+ }
+});
+
+
+// Create the request object
+// (This is still attached to ajaxSettings for backward compatibility)
+jQuery.ajaxSettings.xhr = window.ActiveXObject !== undefined ?
+ // Support: IE6+
+ function() {
+
+ // XHR cannot access local files, always use ActiveX for that case
+ return !this.isLocal &&
+
+ // Support: IE7-8
+ // oldIE XHR does not support non-RFC2616 methods (#13240)
+ // See http://msdn.microsoft.com/en-us/library/ie/ms536648(v=vs.85).aspx
+ // and http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9
+ // Although this check for six methods instead of eight
+ // since IE also does not support "trace" and "connect"
+ /^(get|post|head|put|delete|options)$/i.test( this.type ) &&
+
+ createStandardXHR() || createActiveXHR();
+ } :
+ // For all other browsers, use the standard XMLHttpRequest object
+ createStandardXHR;
+
+var xhrId = 0,
+ xhrCallbacks = {},
+ xhrSupported = jQuery.ajaxSettings.xhr();
+
+// Support: IE<10
+// Open requests must be manually aborted on unload (#5280)
+// See https://support.microsoft.com/kb/2856746 for more info
+if ( window.attachEvent ) {
+ window.attachEvent( "onunload", function() {
+ for ( var key in xhrCallbacks ) {
+ xhrCallbacks[ key ]( undefined, true );
+ }
+ });
+}
+
+// Determine support properties
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+xhrSupported = support.ajax = !!xhrSupported;
+
+// Create transport if the browser can provide an xhr
+if ( xhrSupported ) {
+
+ jQuery.ajaxTransport(function( options ) {
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( !options.crossDomain || support.cors ) {
+
+ var callback;
+
+ return {
+ send: function( headers, complete ) {
+ var i,
+ xhr = options.xhr(),
+ id = ++xhrId;
+
+ // Open the socket
+ xhr.open( options.type, options.url, options.async, options.username, options.password );
+
+ // Apply custom fields if provided
+ if ( options.xhrFields ) {
+ for ( i in options.xhrFields ) {
+ xhr[ i ] = options.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( options.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( options.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !options.crossDomain && !headers["X-Requested-With"] ) {
+ headers["X-Requested-With"] = "XMLHttpRequest";
+ }
+
+ // Set headers
+ for ( i in headers ) {
+ // Support: IE<9
+ // IE's ActiveXObject throws a 'Type Mismatch' exception when setting
+ // request header to a null-value.
+ //
+ // To keep consistent with other XHR implementations, cast the value
+ // to string and ignore `undefined`.
+ if ( headers[ i ] !== undefined ) {
+ xhr.setRequestHeader( i, headers[ i ] + "" );
+ }
+ }
+
+ // Do send the request
+ // This may raise an exception which is actually
+ // handled in jQuery.ajax (so no try/catch here)
+ xhr.send( ( options.hasContent && options.data ) || null );
+
+ // Listener
+ callback = function( _, isAbort ) {
+ var status, statusText, responses;
+
+ // Was never called and is aborted or complete
+ if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
+ // Clean up
+ delete xhrCallbacks[ id ];
+ callback = undefined;
+ xhr.onreadystatechange = jQuery.noop;
+
+ // Abort manually if needed
+ if ( isAbort ) {
+ if ( xhr.readyState !== 4 ) {
+ xhr.abort();
+ }
+ } else {
+ responses = {};
+ status = xhr.status;
+
+ // Support: IE<10
+ // Accessing binary-data responseText throws an exception
+ // (#11426)
+ if ( typeof xhr.responseText === "string" ) {
+ responses.text = xhr.responseText;
+ }
+
+ // Firefox throws an exception when accessing
+ // statusText for faulty cross-domain requests
+ try {
+ statusText = xhr.statusText;
+ } catch( e ) {
+ // We normalize with Webkit giving an empty statusText
+ statusText = "";
+ }
+
+ // Filter status for non standard behaviors
+
+ // If the request is local and we have data: assume a success
+ // (success with no data won't get notified, that's the best we
+ // can do given current implementations)
+ if ( !status && options.isLocal && !options.crossDomain ) {
+ status = responses.text ? 200 : 404;
+ // IE - #1450: sometimes returns 1223 when it should be 204
+ } else if ( status === 1223 ) {
+ status = 204;
+ }
+ }
+ }
+
+ // Call complete if needed
+ if ( responses ) {
+ complete( status, statusText, responses, xhr.getAllResponseHeaders() );
+ }
+ };
+
+ if ( !options.async ) {
+ // if we're in sync mode we fire the callback
+ callback();
+ } else if ( xhr.readyState === 4 ) {
+ // (IE6 & IE7) if it's in cache and has been
+ // retrieved directly we need to fire the callback
+ setTimeout( callback );
+ } else {
+ // Add to the list of active xhr callbacks
+ xhr.onreadystatechange = xhrCallbacks[ id ] = callback;
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback( undefined, true );
+ }
+ }
+ };
+ }
+ });
+}
+
+// Functions to create xhrs
+function createStandardXHR() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch( e ) {}
+}
+
+function createActiveXHR() {
+ try {
+ return new window.ActiveXObject( "Microsoft.XMLHTTP" );
+ } catch( e ) {}
+}
+
+
+
+
+// Install script dataType
+jQuery.ajaxSetup({
+ accepts: {
+ script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /(?:java|ecma)script/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+});
+
+// Handle cache's special case and global
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ s.global = false;
+ }
+});
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function(s) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+
+ var script,
+ head = document.head || jQuery("head")[0] || document.documentElement;
+
+ return {
+
+ send: function( _, callback ) {
+
+ script = document.createElement("script");
+
+ script.async = true;
+
+ if ( s.scriptCharset ) {
+ script.charset = s.scriptCharset;
+ }
+
+ script.src = s.url;
+
+ // Attach handlers for all browsers
+ script.onload = script.onreadystatechange = function( _, isAbort ) {
+
+ if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+
+ // Handle memory leak in IE
+ script.onload = script.onreadystatechange = null;
+
+ // Remove the script
+ if ( script.parentNode ) {
+ script.parentNode.removeChild( script );
+ }
+
+ // Dereference the script
+ script = null;
+
+ // Callback if not abort
+ if ( !isAbort ) {
+ callback( 200, "success" );
+ }
+ }
+ };
+
+ // Circumvent IE6 bugs with base elements (#2709 and #4378) by prepending
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ head.insertBefore( script, head.firstChild );
+ },
+
+ abort: function() {
+ if ( script ) {
+ script.onload( undefined, true );
+ }
+ }
+ };
+ }
+});
+
+
+
+
+var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup({
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+});
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" && !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters["script json"] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always(function() {
+ // Restore preexisting value
+ window[ callbackName ] = overwritten;
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+ // make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ });
+
+ // Delegate to script
+ return "script";
+ }
+});
+
+
+
+
+// data: string of html
+// context (optional): If specified, the fragment will be created in this context, defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+ if ( typeof context === "boolean" ) {
+ keepScripts = context;
+ context = false;
+ }
+ context = context || document;
+
+ var parsed = rsingleTag.exec( data ),
+ scripts = !keepScripts && [];
+
+ // Single tag
+ if ( parsed ) {
+ return [ context.createElement( parsed[1] ) ];
+ }
+
+ parsed = jQuery.buildFragment( [ data ], context, scripts );
+
+ if ( scripts && scripts.length ) {
+ jQuery( scripts ).remove();
+ }
+
+ return jQuery.merge( [], parsed.childNodes );
+};
+
+
+// Keep a copy of the old load method
+var _load = jQuery.fn.load;
+
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+ if ( typeof url !== "string" && _load ) {
+ return _load.apply( this, arguments );
+ }
+
+ var selector, response, type,
+ self = this,
+ off = url.indexOf(" ");
+
+ if ( off >= 0 ) {
+ selector = jQuery.trim( url.slice( off, url.length ) );
+ url = url.slice( 0, off );
+ }
+
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( params && typeof params === "object" ) {
+ type = "POST";
+ }
+
+ // If we have elements to modify, make the request
+ if ( self.length > 0 ) {
+ jQuery.ajax({
+ url: url,
+
+ // if "type" variable is undefined, then "GET" method will be used
+ type: type,
+ dataType: "html",
+ data: params
+ }).done(function( responseText ) {
+
+ // Save response for use in complete callback
+ response = arguments;
+
+ self.html( selector ?
+
+ // If a selector was specified, locate the right elements in a dummy div
+ // Exclude scripts to avoid IE 'Permission Denied' errors
+ jQuery("<div>").append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ }).complete( callback && function( jqXHR, status ) {
+ self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] );
+ });
+ }
+
+ return this;
+};
+
+
+
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [ "ajaxStart", "ajaxStop", "ajaxComplete", "ajaxError", "ajaxSuccess", "ajaxSend" ], function( i, type ) {
+ jQuery.fn[ type ] = function( fn ) {
+ return this.on( type, fn );
+ };
+});
+
+
+
+
+jQuery.expr.filters.animated = function( elem ) {
+ return jQuery.grep(jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ }).length;
+};
+
+
+
+
+
+var docElem = window.document.documentElement;
+
+/**
+ * Gets a window from an element
+ */
+function getWindow( elem ) {
+ return jQuery.isWindow( elem ) ?
+ elem :
+ elem.nodeType === 9 ?
+ elem.defaultView || elem.parentWindow :
+ false;
+}
+
+jQuery.offset = {
+ setOffset: function( elem, options, i ) {
+ var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+ position = jQuery.css( elem, "position" ),
+ curElem = jQuery( elem ),
+ props = {};
+
+ // set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ curOffset = curElem.offset();
+ curCSSTop = jQuery.css( elem, "top" );
+ curCSSLeft = jQuery.css( elem, "left" );
+ calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+ jQuery.inArray("auto", [ curCSSTop, curCSSLeft ] ) > -1;
+
+ // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+ options = options.call( elem, i, curOffset );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+jQuery.fn.extend({
+ offset: function( options ) {
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each(function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ });
+ }
+
+ var docElem, win,
+ box = { top: 0, left: 0 },
+ elem = this[ 0 ],
+ doc = elem && elem.ownerDocument;
+
+ if ( !doc ) {
+ return;
+ }
+
+ docElem = doc.documentElement;
+
+ // Make sure it's not a disconnected DOM node
+ if ( !jQuery.contains( docElem, elem ) ) {
+ return box;
+ }
+
+ // If we don't have gBCR, just use 0,0 rather than error
+ // BlackBerry 5, iOS 3 (original iPhone)
+ if ( typeof elem.getBoundingClientRect !== strundefined ) {
+ box = elem.getBoundingClientRect();
+ }
+ win = getWindow( doc );
+ return {
+ top: box.top + ( win.pageYOffset || docElem.scrollTop ) - ( docElem.clientTop || 0 ),
+ left: box.left + ( win.pageXOffset || docElem.scrollLeft ) - ( docElem.clientLeft || 0 )
+ };
+ },
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ parentOffset = { top: 0, left: 0 },
+ elem = this[ 0 ];
+
+ // fixed elements are offset from window (parentOffset = {top:0, left: 0}, because it is its only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+ // we assume that getBoundingClientRect is available when computed position is fixed
+ offset = elem.getBoundingClientRect();
+ } else {
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !jQuery.nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset.top += jQuery.css( offsetParent[ 0 ], "borderTopWidth", true );
+ parentOffset.left += jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true );
+ }
+
+ // Subtract parent offsets and element margins
+ // note: when an element has margin: auto the offsetLeft and marginLeft
+ // are the same in Safari causing offset.left to incorrectly be 0
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true)
+ };
+ },
+
+ offsetParent: function() {
+ return this.map(function() {
+ var offsetParent = this.offsetParent || docElem;
+
+ while ( offsetParent && ( !jQuery.nodeName( offsetParent, "html" ) && jQuery.css( offsetParent, "position" ) === "static" ) ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+ return offsetParent || docElem;
+ });
+ }
+});
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+ var top = /Y/.test( prop );
+
+ jQuery.fn[ method ] = function( val ) {
+ return access( this, function( elem, method, val ) {
+ var win = getWindow( elem );
+
+ if ( val === undefined ) {
+ return win ? (prop in win) ? win[ prop ] :
+ win.document.documentElement[ method ] :
+ elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : jQuery( win ).scrollLeft(),
+ top ? val : jQuery( win ).scrollTop()
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length, null );
+ };
+});
+
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// getComputedStyle returns percent when specified for top/left/bottom/right
+// rather than make the css module depend on the offset module, we just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+ function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+ // if curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ );
+});
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) {
+ // margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+ // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there
+ // isn't a whole lot we can do. See pull request at this URL for discussion:
+ // https://github.com/jquery/jquery/pull/764
+ return elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest
+ // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it.
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable, null );
+ };
+ });
+});
+
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+ return this.length;
+};
+
+jQuery.fn.andSelf = jQuery.fn.addBack;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+ define( "jquery", [], function() {
+ return jQuery;
+ });
+}
+
+
+
+
+var
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in
+// AMD (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( typeof noGlobal === strundefined ) {
+ window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
+
+}));
diff --git a/www/wiki/resources/lib/jquery/jquery.migrate.js b/www/wiki/resources/lib/jquery/jquery.migrate.js
new file mode 100644
index 00000000..70512e00
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.migrate.js
@@ -0,0 +1,621 @@
+/*!
+ * jQuery Migrate - v3.0.1-pre - 2017-08-17
+ * Copyright jQuery Foundation and other contributors
+ *
+ * Patched for MediaWiki:
+ * - Preserve handler of uncaught exceptions in promise chains
+ * https://gerrit.wikimedia.org/r/#/c/360999/
+ * https://github.com/jquery/jquery-migrate/pull/262
+ * - Add mw.track instrumentation for statistics.
+ */
+;( function( factory ) {
+ if ( typeof define === "function" && define.amd ) {
+
+ // AMD. Register as an anonymous module.
+ define( [ "jquery" ], window, factory );
+ } else if ( typeof module === "object" && module.exports ) {
+
+ // Node/CommonJS
+ // eslint-disable-next-line no-undef
+ module.exports = factory( require( "jquery" ), window );
+ } else {
+
+ // Browser globals
+ factory( jQuery, window );
+ }
+} )( function( jQuery, window ) {
+"use strict";
+
+
+jQuery.migrateVersion = "3.0.1-pre";
+
+/* exported migrateWarn, migrateWarnFunc, migrateWarnProp */
+
+( function() {
+
+ // Support: IE9 only
+ // IE9 only creates console object when dev tools are first opened
+ // Also, avoid Function#bind here to simplify PhantomJS usage
+ var log = window.console && window.console.log &&
+ function() {
+ window.console.log.apply( window.console, arguments );
+ },
+ rbadVersions = /^[12]\./;
+
+ if ( !log ) {
+ return;
+ }
+
+ // Need jQuery 3.0.0+ and no older Migrate loaded
+ if ( !jQuery || rbadVersions.test( jQuery.fn.jquery ) ) {
+ log( "JQMIGRATE: jQuery 3.0.0+ REQUIRED" );
+ }
+ if ( jQuery.migrateWarnings ) {
+ log( "JQMIGRATE: Migrate plugin loaded multiple times" );
+ }
+
+ // Show a message on the console so devs know we're active
+ log( "JQMIGRATE: Migrate is installed" +
+ ( jQuery.migrateMute ? "" : " with logging active" ) +
+ ", version " + jQuery.migrateVersion );
+
+} )();
+
+var warnedAbout = {};
+
+// List of warnings already given; public read only
+jQuery.migrateWarnings = [];
+
+// Set to false to disable traces that appear with warnings
+if ( jQuery.migrateTrace === undefined ) {
+ jQuery.migrateTrace = true;
+}
+
+// Forget any warnings we've already given; public
+jQuery.migrateReset = function() {
+ warnedAbout = {};
+ jQuery.migrateWarnings.length = 0;
+};
+
+function migrateWarn( msg ) {
+ var console = window.console;
+ if ( !warnedAbout[ msg ] ) {
+ warnedAbout[ msg ] = true;
+ jQuery.migrateWarnings.push( msg );
+ // PATCH: Add instrumentation for statistics --Krinkle
+ if ( window.mw && window.mw.track ) {
+ window.mw.track( "mw.deprecate", "jquery-migrate" );
+ }
+ if ( console && console.warn && !jQuery.migrateMute ) {
+ console.warn( "JQMIGRATE: " + msg );
+ if ( jQuery.migrateTrace && console.trace ) {
+ console.trace();
+ }
+ }
+ }
+}
+
+function migrateWarnProp( obj, prop, value, msg ) {
+ Object.defineProperty( obj, prop, {
+ configurable: true,
+ enumerable: true,
+ get: function() {
+ migrateWarn( msg );
+ return value;
+ },
+ set: function( newValue ) {
+ migrateWarn( msg );
+ value = newValue;
+ }
+ } );
+}
+
+function migrateWarnFunc( obj, prop, newFunc, msg ) {
+ obj[ prop ] = function() {
+ migrateWarn( msg );
+ return newFunc.apply( this, arguments );
+ };
+}
+
+if ( window.document.compatMode === "BackCompat" ) {
+
+ // JQuery has never supported or tested Quirks Mode
+ migrateWarn( "jQuery is not compatible with Quirks Mode" );
+}
+
+
+var oldInit = jQuery.fn.init,
+ oldIsNumeric = jQuery.isNumeric,
+ oldFind = jQuery.find,
+ rattrHashTest = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/,
+ rattrHashGlob = /\[(\s*[-\w]+\s*)([~|^$*]?=)\s*([-\w#]*?#[-\w#]*)\s*\]/g;
+
+jQuery.fn.init = function( arg1 ) {
+ var args = Array.prototype.slice.call( arguments );
+
+ if ( typeof arg1 === "string" && arg1 === "#" ) {
+
+ // JQuery( "#" ) is a bogus ID selector, but it returned an empty set before jQuery 3.0
+ migrateWarn( "jQuery( '#' ) is not a valid selector" );
+ args[ 0 ] = [];
+ }
+
+ return oldInit.apply( this, args );
+};
+jQuery.fn.init.prototype = jQuery.fn;
+
+jQuery.find = function( selector ) {
+ var args = Array.prototype.slice.call( arguments );
+
+ // Support: PhantomJS 1.x
+ // String#match fails to match when used with a //g RegExp, only on some strings
+ if ( typeof selector === "string" && rattrHashTest.test( selector ) ) {
+
+ // The nonstandard and undocumented unquoted-hash was removed in jQuery 1.12.0
+ // First see if qS thinks it's a valid selector, if so avoid a false positive
+ try {
+ window.document.querySelector( selector );
+ } catch ( err1 ) {
+
+ // Didn't *look* valid to qSA, warn and try quoting what we think is the value
+ selector = selector.replace( rattrHashGlob, function( _, attr, op, value ) {
+ return "[" + attr + op + "\"" + value + "\"]";
+ } );
+
+ // If the regexp *may* have created an invalid selector, don't update it
+ // Note that there may be false alarms if selector uses jQuery extensions
+ try {
+ window.document.querySelector( selector );
+ migrateWarn( "Attribute selector with '#' must be quoted: " + args[ 0 ] );
+ args[ 0 ] = selector;
+ } catch ( err2 ) {
+ migrateWarn( "Attribute selector with '#' was not fixed: " + args[ 0 ] );
+ }
+ }
+ }
+
+ return oldFind.apply( this, args );
+};
+
+// Copy properties attached to original jQuery.find method (e.g. .attr, .isXML)
+var findProp;
+for ( findProp in oldFind ) {
+ if ( Object.prototype.hasOwnProperty.call( oldFind, findProp ) ) {
+ jQuery.find[ findProp ] = oldFind[ findProp ];
+ }
+}
+
+// The number of elements contained in the matched element set
+jQuery.fn.size = function() {
+ migrateWarn( "jQuery.fn.size() is deprecated and removed; use the .length property" );
+ return this.length;
+};
+
+jQuery.parseJSON = function() {
+ migrateWarn( "jQuery.parseJSON is deprecated; use JSON.parse" );
+ return JSON.parse.apply( null, arguments );
+};
+
+jQuery.isNumeric = function( val ) {
+
+ // The jQuery 2.2.3 implementation of isNumeric
+ function isNumeric2( obj ) {
+ var realStringObj = obj && obj.toString();
+ return !jQuery.isArray( obj ) && ( realStringObj - parseFloat( realStringObj ) + 1 ) >= 0;
+ }
+
+ var newValue = oldIsNumeric( val ),
+ oldValue = isNumeric2( val );
+
+ if ( newValue !== oldValue ) {
+ migrateWarn( "jQuery.isNumeric() should not be called on constructed objects" );
+ }
+
+ return oldValue;
+};
+
+migrateWarnFunc( jQuery, "unique", jQuery.uniqueSort,
+ "jQuery.unique is deprecated; use jQuery.uniqueSort" );
+
+// Now jQuery.expr.pseudos is the standard incantation
+migrateWarnProp( jQuery.expr, "filters", jQuery.expr.pseudos,
+ "jQuery.expr.filters is deprecated; use jQuery.expr.pseudos" );
+migrateWarnProp( jQuery.expr, ":", jQuery.expr.pseudos,
+ "jQuery.expr[':'] is deprecated; use jQuery.expr.pseudos" );
+
+
+var oldAjax = jQuery.ajax;
+
+jQuery.ajax = function( ) {
+ var jQXHR = oldAjax.apply( this, arguments );
+
+ // Be sure we got a jQXHR (e.g., not sync)
+ if ( jQXHR.promise ) {
+ migrateWarnFunc( jQXHR, "success", jQXHR.done,
+ "jQXHR.success is deprecated and removed" );
+ migrateWarnFunc( jQXHR, "error", jQXHR.fail,
+ "jQXHR.error is deprecated and removed" );
+ migrateWarnFunc( jQXHR, "complete", jQXHR.always,
+ "jQXHR.complete is deprecated and removed" );
+ }
+
+ return jQXHR;
+};
+
+
+var oldRemoveAttr = jQuery.fn.removeAttr,
+ oldToggleClass = jQuery.fn.toggleClass,
+ rmatchNonSpace = /\S+/g;
+
+jQuery.fn.removeAttr = function( name ) {
+ var self = this;
+
+ jQuery.each( name.match( rmatchNonSpace ), function( i, attr ) {
+ if ( jQuery.expr.match.bool.test( attr ) ) {
+ migrateWarn( "jQuery.fn.removeAttr no longer sets boolean properties: " + attr );
+ self.prop( attr, false );
+ }
+ } );
+
+ return oldRemoveAttr.apply( this, arguments );
+};
+
+jQuery.fn.toggleClass = function( state ) {
+
+ // Only deprecating no-args or single boolean arg
+ if ( state !== undefined && typeof state !== "boolean" ) {
+ return oldToggleClass.apply( this, arguments );
+ }
+
+ migrateWarn( "jQuery.fn.toggleClass( boolean ) is deprecated" );
+
+ // Toggle entire class name of each element
+ return this.each( function() {
+ var className = this.getAttribute && this.getAttribute( "class" ) || "";
+
+ if ( className ) {
+ jQuery.data( this, "__className__", className );
+ }
+
+ // If the element has a class name or if we're passed `false`,
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ if ( this.setAttribute ) {
+ this.setAttribute( "class",
+ className || state === false ?
+ "" :
+ jQuery.data( this, "__className__" ) || ""
+ );
+ }
+ } );
+};
+
+
+var internalSwapCall = false;
+
+// If this version of jQuery has .swap(), don't false-alarm on internal uses
+if ( jQuery.swap ) {
+ jQuery.each( [ "height", "width", "reliableMarginRight" ], function( _, name ) {
+ var oldHook = jQuery.cssHooks[ name ] && jQuery.cssHooks[ name ].get;
+
+ if ( oldHook ) {
+ jQuery.cssHooks[ name ].get = function() {
+ var ret;
+
+ internalSwapCall = true;
+ ret = oldHook.apply( this, arguments );
+ internalSwapCall = false;
+ return ret;
+ };
+ }
+ } );
+}
+
+jQuery.swap = function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ if ( !internalSwapCall ) {
+ migrateWarn( "jQuery.swap() is undocumented and deprecated" );
+ }
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+};
+
+var oldData = jQuery.data;
+
+jQuery.data = function( elem, name, value ) {
+ var curData;
+
+ // Name can be an object, and each entry in the object is meant to be set as data
+ if ( name && typeof name === "object" && arguments.length === 2 ) {
+ curData = jQuery.hasData( elem ) && oldData.call( this, elem );
+ var sameKeys = {};
+ for ( var key in name ) {
+ if ( key !== jQuery.camelCase( key ) ) {
+ migrateWarn( "jQuery.data() always sets/gets camelCased names: " + key );
+ curData[ key ] = name[ key ];
+ } else {
+ sameKeys[ key ] = name[ key ];
+ }
+ }
+
+ oldData.call( this, elem, sameKeys );
+
+ return name;
+ }
+
+ // If the name is transformed, look for the un-transformed name in the data object
+ if ( name && typeof name === "string" && name !== jQuery.camelCase( name ) ) {
+ curData = jQuery.hasData( elem ) && oldData.call( this, elem );
+ if ( curData && name in curData ) {
+ migrateWarn( "jQuery.data() always sets/gets camelCased names: " + name );
+ if ( arguments.length > 2 ) {
+ curData[ name ] = value;
+ }
+ return curData[ name ];
+ }
+ }
+
+ return oldData.apply( this, arguments );
+};
+
+var oldTweenRun = jQuery.Tween.prototype.run;
+
+jQuery.Tween.prototype.run = function( ) {
+ if ( jQuery.easing[ this.easing ].length > 1 ) {
+ migrateWarn(
+ "easing function " +
+ "\"jQuery.easing." + this.easing.toString() +
+ "\" should use only first argument"
+ );
+
+ var oldEasing = jQuery.easing[ this.easing ];
+ jQuery.easing[ this.easing ] = function( percent ) {
+ return oldEasing.call( jQuery.easing, percent, percent, 0, 1, 1 );
+ }.bind( this );
+ }
+
+ oldTweenRun.apply( this, arguments );
+};
+
+jQuery.fx.interval = jQuery.fx.interval || 13;
+
+// Support: IE9, Android <=4.4
+// Avoid false positives on browsers that lack rAF
+if ( window.requestAnimationFrame ) {
+ migrateWarnProp( jQuery.fx, "interval", jQuery.fx.interval,
+ "jQuery.fx.interval is deprecated" );
+}
+
+var oldLoad = jQuery.fn.load,
+ oldEventAdd = jQuery.event.add,
+ originalFix = jQuery.event.fix;
+
+jQuery.event.props = [];
+jQuery.event.fixHooks = {};
+
+migrateWarnProp( jQuery.event.props, "concat", jQuery.event.props.concat,
+ "jQuery.event.props.concat() is deprecated and removed" );
+
+jQuery.event.fix = function( originalEvent ) {
+ var event,
+ type = originalEvent.type,
+ fixHook = this.fixHooks[ type ],
+ props = jQuery.event.props;
+
+ if ( props.length ) {
+ migrateWarn( "jQuery.event.props are deprecated and removed: " + props.join() );
+ while ( props.length ) {
+ jQuery.event.addProp( props.pop() );
+ }
+ }
+
+ if ( fixHook && !fixHook._migrated_ ) {
+ fixHook._migrated_ = true;
+ migrateWarn( "jQuery.event.fixHooks are deprecated and removed: " + type );
+ if ( ( props = fixHook.props ) && props.length ) {
+ while ( props.length ) {
+ jQuery.event.addProp( props.pop() );
+ }
+ }
+ }
+
+ event = originalFix.call( this, originalEvent );
+
+ return fixHook && fixHook.filter ? fixHook.filter( event, originalEvent ) : event;
+};
+
+jQuery.event.add = function( elem, types ) {
+
+ // This misses the multiple-types case but that seems awfully rare
+ if ( elem === window && types === "load" && window.document.readyState === "complete" ) {
+ migrateWarn( "jQuery(window).on('load'...) called after load event occurred" );
+ }
+ return oldEventAdd.apply( this, arguments );
+};
+
+jQuery.each( [ "load", "unload", "error" ], function( _, name ) {
+
+ jQuery.fn[ name ] = function() {
+ var args = Array.prototype.slice.call( arguments, 0 );
+
+ // If this is an ajax load() the first arg should be the string URL;
+ // technically this could also be the "Anything" arg of the event .load()
+ // which just goes to show why this dumb signature has been deprecated!
+ // jQuery custom builds that exclude the Ajax module justifiably die here.
+ if ( name === "load" && typeof args[ 0 ] === "string" ) {
+ return oldLoad.apply( this, args );
+ }
+
+ migrateWarn( "jQuery.fn." + name + "() is deprecated" );
+
+ args.splice( 0, 0, name );
+ if ( arguments.length ) {
+ return this.on.apply( this, args );
+ }
+
+ // Use .triggerHandler here because:
+ // - load and unload events don't need to bubble, only applied to window or image
+ // - error event should not bubble to window, although it does pre-1.7
+ // See http://bugs.jquery.com/ticket/11820
+ this.triggerHandler.apply( this, args );
+ return this;
+ };
+
+} );
+
+// Trigger "ready" event only once, on document ready
+jQuery( function() {
+ jQuery( window.document ).triggerHandler( "ready" );
+} );
+
+jQuery.event.special.ready = {
+ setup: function() {
+ if ( this === window.document ) {
+ migrateWarn( "'ready' event is deprecated" );
+ }
+ }
+};
+
+jQuery.fn.extend( {
+
+ bind: function( types, data, fn ) {
+ migrateWarn( "jQuery.fn.bind() is deprecated" );
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ migrateWarn( "jQuery.fn.unbind() is deprecated" );
+ return this.off( types, null, fn );
+ },
+ delegate: function( selector, types, data, fn ) {
+ migrateWarn( "jQuery.fn.delegate() is deprecated" );
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+ migrateWarn( "jQuery.fn.undelegate() is deprecated" );
+ return arguments.length === 1 ?
+ this.off( selector, "**" ) :
+ this.off( types, selector || "**", fn );
+ }
+} );
+
+
+var oldOffset = jQuery.fn.offset;
+
+jQuery.fn.offset = function() {
+ var docElem,
+ elem = this[ 0 ],
+ origin = { top: 0, left: 0 };
+
+ if ( !elem || !elem.nodeType ) {
+ migrateWarn( "jQuery.fn.offset() requires a valid DOM element" );
+ return origin;
+ }
+
+ docElem = ( elem.ownerDocument || window.document ).documentElement;
+ if ( !jQuery.contains( docElem, elem ) ) {
+ migrateWarn( "jQuery.fn.offset() requires an element connected to a document" );
+ return origin;
+ }
+
+ return oldOffset.apply( this, arguments );
+};
+
+
+var oldParam = jQuery.param;
+
+jQuery.param = function( data, traditional ) {
+ var ajaxTraditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional;
+
+ if ( traditional === undefined && ajaxTraditional ) {
+
+ migrateWarn( "jQuery.param() no longer uses jQuery.ajaxSettings.traditional" );
+ traditional = ajaxTraditional;
+ }
+
+ return oldParam.call( this, data, traditional );
+};
+
+var oldSelf = jQuery.fn.andSelf || jQuery.fn.addBack;
+
+jQuery.fn.andSelf = function() {
+ migrateWarn( "jQuery.fn.andSelf() is deprecated and removed, use jQuery.fn.addBack()" );
+ return oldSelf.apply( this, arguments );
+};
+
+
+var oldDeferred = jQuery.Deferred,
+ tuples = [
+
+ // Action, add listener, callbacks, .then handlers, final state
+ [ "resolve", "done", jQuery.Callbacks( "once memory" ),
+ jQuery.Callbacks( "once memory" ), "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks( "once memory" ),
+ jQuery.Callbacks( "once memory" ), "rejected" ],
+ [ "notify", "progress", jQuery.Callbacks( "memory" ),
+ jQuery.Callbacks( "memory" ) ]
+ ];
+
+jQuery.Deferred = function( func ) {
+ var deferred = oldDeferred(),
+ promise = deferred.promise();
+
+ deferred.pipe = promise.pipe = function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+
+ migrateWarn( "deferred.pipe() is deprecated" );
+
+ return jQuery.Deferred( function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+ var fn = jQuery.isFunction( fns[ i ] ) && fns[ i ];
+
+ // Deferred.done(function() { bind to newDefer or newDefer.resolve })
+ // deferred.fail(function() { bind to newDefer or newDefer.reject })
+ // deferred.progress(function() { bind to newDefer or newDefer.notify })
+ deferred[ tuple[ 1 ] ]( function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .done( newDefer.resolve )
+ .fail( newDefer.reject )
+ .progress( newDefer.notify );
+ } else {
+ newDefer[ tuple[ 0 ] + "With" ](
+ this === promise ? newDefer.promise() : this,
+ fn ? [ returned ] : arguments
+ );
+ }
+ } );
+ } );
+ fns = null;
+ } ).promise();
+
+ };
+
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ return deferred;
+};
+
+// Preserve handler of uncaught exceptions in promise chains
+jQuery.Deferred.exceptionHook = oldDeferred.exceptionHook;
+
+return jQuery;
+} );
diff --git a/www/wiki/resources/lib/jquery/jquery.mockjax.js b/www/wiki/resources/lib/jquery/jquery.mockjax.js
new file mode 100644
index 00000000..5f6e1306
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.mockjax.js
@@ -0,0 +1,382 @@
+/*!
+ * MockJax - jQuery Plugin to Mock Ajax requests
+ *
+ * Version: 1.4.0
+ * Released: 2011-02-04
+ * Source: http://github.com/appendto/jquery-mockjax
+ * Docs: http://enterprisejquery.com/2010/07/mock-your-ajax-requests-with-mockjax-for-rapid-development
+ * Plugin: mockjax
+ * Author: Jonathan Sharp (http://jdsharp.com)
+ * License: MIT,GPL
+ *
+ * Copyright (c) 2010 appendTo LLC.
+ * Dual licensed under the MIT or GPL licenses.
+ * http://appendto.com/open-source-licenses
+ */
+(function($) {
+ var _ajax = $.ajax,
+ mockHandlers = [];
+
+ function parseXML(xml) {
+ if ( window['DOMParser'] == undefined && window.ActiveXObject ) {
+ DOMParser = function() { };
+ DOMParser.prototype.parseFromString = function( xmlString ) {
+ var doc = new ActiveXObject('Microsoft.XMLDOM');
+ doc.async = 'false';
+ doc.loadXML( xmlString );
+ return doc;
+ };
+ }
+
+ try {
+ var xmlDoc = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
+ if ( $.isXMLDoc( xmlDoc ) ) {
+ var err = $('parsererror', xmlDoc);
+ if ( err.length == 1 ) {
+ throw('Error: ' + $(xmlDoc).text() );
+ }
+ } else {
+ throw('Unable to parse XML');
+ }
+ } catch( e ) {
+ var msg = ( e.name == undefined ? e : e.name + ': ' + e.message );
+ $(document).trigger('xmlParseError', [ msg ]);
+ return undefined;
+ }
+ return xmlDoc;
+ }
+
+ $.extend({
+ ajax: function(origSettings) {
+ var s = jQuery.extend(true, {}, jQuery.ajaxSettings, origSettings),
+ mock = false;
+ // Iterate over our mock handlers (in registration order) until we find
+ // one that is willing to intercept the request
+ $.each(mockHandlers, function(k, v) {
+ if ( !mockHandlers[k] ) {
+ return;
+ }
+ var m = null;
+ // If the mock was registered with a function, let the function decide if we
+ // want to mock this request
+ if ( $.isFunction(mockHandlers[k]) ) {
+ m = mockHandlers[k](s);
+ } else {
+ m = mockHandlers[k];
+ // Inspect the URL of the request and check if the mock handler's url
+ // matches the url for this ajax request
+ if ( $.isFunction(m.url.test) ) {
+ // The user provided a regex for the url, test it
+ if ( !m.url.test( s.url ) ) {
+ m = null;
+ }
+ } else {
+ // Look for a simple wildcard '*' or a direct URL match
+ var star = m.url.indexOf('*');
+ if ( ( m.url != '*' && m.url != s.url && star == -1 ) ||
+ ( star > -1 && m.url.substr(0, star) != s.url.substr(0, star) ) ) {
+ // The url we tested did not match the wildcard *
+ m = null;
+ }
+ }
+ if ( m ) {
+ // Inspect the data submitted in the request (either POST body or GET query string)
+ if ( m.data && s.data ) {
+ var identical = false;
+ // Deep inspect the identity of the objects
+ (function ident(mock, live) {
+ // Test for situations where the data is a querystring (not an object)
+ if (typeof live === 'string') {
+ // Querystring may be a regex
+ identical = $.isFunction( mock.test ) ? mock.test(live) : mock == live;
+ return identical;
+ }
+ $.each(mock, function(k, v) {
+ if ( live[k] === undefined ) {
+ identical = false;
+ return false;
+ } else {
+ identical = true;
+ if ( typeof live[k] == 'object' ) {
+ return ident(mock[k], live[k]);
+ } else {
+ if ( $.isFunction( mock[k].test ) ) {
+ identical = mock[k].test(live[k]);
+ } else {
+ identical = ( mock[k] == live[k] );
+ }
+ return identical;
+ }
+ }
+ });
+ })(m.data, s.data);
+ // They're not identical, do not mock this request
+ if ( identical == false ) {
+ m = null;
+ }
+ }
+ // Inspect the request type
+ if ( m && m.type && m.type != s.type ) {
+ // The request type doesn't match (GET vs. POST)
+ m = null;
+ }
+ }
+ }
+ if ( m ) {
+ mock = true;
+
+ // Handle console logging
+ var c = $.extend({}, $.mockjaxSettings, m);
+ if ( c.log && $.isFunction(c.log) ) {
+ c.log('MOCK ' + s.type.toUpperCase() + ': ' + s.url, $.extend({}, s));
+ }
+
+ var jsre = /=\?(&|$)/, jsc = (new Date()).getTime();
+
+ // Handle JSONP Parameter Callbacks, we need to replicate some of the jQuery core here
+ // because there isn't an easy hook for the cross domain script tag of jsonp
+ if ( s.dataType === "jsonp" ) {
+ if ( s.type.toUpperCase() === "GET" ) {
+ if ( !jsre.test( s.url ) ) {
+ s.url += (rquery.test( s.url ) ? "&" : "?") + (s.jsonp || "callback") + "=?";
+ }
+ } else if ( !s.data || !jsre.test(s.data) ) {
+ s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
+ }
+ s.dataType = "json";
+ }
+
+ // Build temporary JSONP function
+ if ( s.dataType === "json" && (s.data && jsre.test(s.data) || jsre.test(s.url)) ) {
+ jsonp = s.jsonpCallback || ("jsonp" + jsc++);
+
+ // Replace the =? sequence both in the query string and the data
+ if ( s.data ) {
+ s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
+ }
+
+ s.url = s.url.replace(jsre, "=" + jsonp + "$1");
+
+ // We need to make sure
+ // that a JSONP style response is executed properly
+ s.dataType = "script";
+
+ // Handle JSONP-style loading
+ window[ jsonp ] = window[ jsonp ] || function( tmp ) {
+ data = tmp;
+ success();
+ complete();
+ // Garbage collect
+ window[ jsonp ] = undefined;
+
+ try {
+ delete window[ jsonp ];
+ } catch(e) {}
+
+ if ( head ) {
+ head.removeChild( script );
+ }
+ };
+ }
+
+ var rurl = /^(\w+:)?\/\/([^\/?#]+)/,
+ parts = rurl.exec( s.url ),
+ remote = parts && (parts[1] && parts[1] !== location.protocol || parts[2] !== location.host);
+
+ // Test if we are going to create a script tag (if so, intercept & mock)
+ if ( s.dataType === "script" && s.type.toUpperCase() === "GET" && remote ) {
+ // Synthesize the mock request for adding a script tag
+ var callbackContext = origSettings && origSettings.context || s;
+
+ function success() {
+ // If a local callback was specified, fire it and pass it the data
+ if ( s.success ) {
+ s.success.call( callbackContext, ( m.response ? m.response.toString() : m.responseText || ''), status, {} );
+ }
+
+ // Fire the global callback
+ if ( s.global ) {
+ trigger( "ajaxSuccess", [{}, s] );
+ }
+ }
+
+ function complete() {
+ // Process result
+ if ( s.complete ) {
+ s.complete.call( callbackContext, {} , status );
+ }
+
+ // The request was completed
+ if ( s.global ) {
+ trigger( "ajaxComplete", [{}, s] );
+ }
+
+ // Handle the global AJAX counter
+ if ( s.global && ! --jQuery.active ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ }
+
+ function trigger(type, args) {
+ (s.context ? jQuery(s.context) : jQuery.event).trigger(type, args);
+ }
+
+ if ( m.response && $.isFunction(m.response) ) {
+ m.response(origSettings);
+ } else {
+ $.globalEval(m.responseText);
+ }
+ success();
+ complete();
+ return false;
+ }
+ mock = _ajax.call($, $.extend(true, {}, origSettings, {
+ // Mock the XHR object
+ xhr: function() {
+ // Extend with our default mockjax settings
+ m = $.extend({}, $.mockjaxSettings, m);
+
+ if ( m.contentType ) {
+ m.headers['content-type'] = m.contentType;
+ }
+
+ // Return our mock xhr object
+ return {
+ status: m.status,
+ readyState: 1,
+ open: function() { },
+ send: function() {
+ // This is a substitute for < 1.4 which lacks $.proxy
+ var process = (function(that) {
+ return function() {
+ return (function() {
+ // The request has returned
+ this.status = m.status;
+ this.readyState = 4;
+
+ // We have an executable function, call it to give
+ // the mock handler a chance to update it's data
+ if ( $.isFunction(m.response) ) {
+ m.response(origSettings);
+ }
+ // Copy over our mock to our xhr object before passing control back to
+ // jQuery's onreadystatechange callback
+ if ( s.dataType == 'json' && ( typeof m.responseText == 'object' ) ) {
+ this.responseText = JSON.stringify(m.responseText);
+ } else if ( s.dataType == 'xml' ) {
+ if ( typeof m.responseXML == 'string' ) {
+ this.responseXML = parseXML(m.responseXML);
+ } else {
+ this.responseXML = m.responseXML;
+ }
+ } else {
+ this.responseText = m.responseText;
+ }
+ // jQuery < 1.4 doesn't have onreadystate change for xhr
+ if ( $.isFunction(this.onreadystatechange) ) {
+ this.onreadystatechange( m.isTimeout ? 'timeout' : undefined );
+ }
+ }).apply(that);
+ };
+ })(this);
+
+ if ( m.proxy ) {
+ // We're proxying this request and loading in an external file instead
+ _ajax({
+ global: false,
+ url: m.proxy,
+ type: m.proxyType,
+ data: m.data,
+ dataType: s.dataType,
+ complete: function(xhr, txt) {
+ m.responseXML = xhr.responseXML;
+ m.responseText = xhr.responseText;
+ this.responseTimer = setTimeout(process, m.responseTime || 0);
+ }
+ });
+ } else {
+ // type == 'POST' || 'GET' || 'DELETE'
+ if ( s.async === false ) {
+ // TODO: Blocking delay
+ process();
+ } else {
+ this.responseTimer = setTimeout(process, m.responseTime || 50);
+ }
+ }
+ },
+ abort: function() {
+ clearTimeout(this.responseTimer);
+ },
+ setRequestHeader: function() { },
+ getResponseHeader: function(header) {
+ // 'Last-modified', 'Etag', 'content-type' are all checked by jQuery
+ if ( m.headers && m.headers[header] ) {
+ // Return arbitrary headers
+ return m.headers[header];
+ } else if ( header.toLowerCase() == 'last-modified' ) {
+ return m.lastModified || (new Date()).toString();
+ } else if ( header.toLowerCase() == 'etag' ) {
+ return m.etag || '';
+ } else if ( header.toLowerCase() == 'content-type' ) {
+ return m.contentType || 'text/plain';
+ }
+ },
+ getAllResponseHeaders: function() {
+ var headers = '';
+ $.each(m.headers, function(k, v) {
+ headers += k + ': ' + v + "\n";
+ });
+ return headers;
+ }
+ };
+ }
+ }));
+ return false;
+ }
+ });
+ // We don't have a mock request, trigger a normal request
+ if ( !mock ) {
+ return _ajax.apply($, arguments);
+ } else {
+ return mock;
+ }
+ }
+ });
+
+ $.mockjaxSettings = {
+ //url: null,
+ //type: 'GET',
+ log: function(msg) {
+ window['console'] && window.console.log && window.console.log(msg);
+ },
+ status: 200,
+ responseTime: 500,
+ isTimeout: false,
+ contentType: 'text/plain',
+ response: '',
+ responseText: '',
+ responseXML: '',
+ proxy: '',
+ proxyType: 'GET',
+
+ lastModified: null,
+ etag: '',
+ headers: {
+ etag: 'IJF@H#@923uf8023hFO@I#H#',
+ 'content-type' : 'text/plain'
+ }
+ };
+
+ $.mockjax = function(settings) {
+ var i = mockHandlers.length;
+ mockHandlers[i] = settings;
+ return i;
+ };
+ $.mockjaxClear = function(i) {
+ if ( arguments.length == 1 ) {
+ mockHandlers[i] = null;
+ } else {
+ mockHandlers = [];
+ }
+ };
+})(jQuery);
diff --git a/www/wiki/resources/lib/jquery/jquery.xmldom.js b/www/wiki/resources/lib/jquery/jquery.xmldom.js
new file mode 100644
index 00000000..85d0083d
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery.xmldom.js
@@ -0,0 +1,46 @@
+/*!
+ * jQuery xmlDOM Plugin v1.0
+ * http://outwestmedia.com/jquery-plugins/xmldom/
+ *
+ * Released: 2009-04-06
+ * Version: 1.0
+ *
+ * Copyright (c) 2009 Jonathan Sharp, Out West Media LLC.
+ * Dual licensed under the MIT and GPL licenses.
+ * http://docs.jquery.com/License
+ */
+(function($) {
+ // IE DOMParser wrapper
+ if ( window['DOMParser'] == undefined && window.ActiveXObject ) {
+ DOMParser = function() { };
+ DOMParser.prototype.parseFromString = function( xmlString ) {
+ var doc = new ActiveXObject('Microsoft.XMLDOM');
+ doc.async = 'false';
+ doc.loadXML( xmlString );
+ return doc;
+ };
+ }
+
+ $.xmlDOM = function(xml, onErrorFn) {
+ try {
+ var xmlDoc = ( new DOMParser() ).parseFromString( xml, 'text/xml' );
+ if ( $.isXMLDoc( xmlDoc ) ) {
+ var err = $('parsererror', xmlDoc);
+ if ( err.length == 1 ) {
+ throw('Error: ' + $(xmlDoc).text() );
+ }
+ } else {
+ throw('Unable to parse XML');
+ }
+ } catch( e ) {
+ var msg = ( e.name == undefined ? e : e.name + ': ' + e.message );
+ if ( $.isFunction( onErrorFn ) ) {
+ onErrorFn( msg );
+ } else {
+ $(document).trigger('xmlParseError', [ msg ]);
+ }
+ return $([]);
+ }
+ return $( xmlDoc );
+ };
+})(jQuery); \ No newline at end of file
diff --git a/www/wiki/resources/lib/jquery/jquery3.js b/www/wiki/resources/lib/jquery/jquery3.js
new file mode 100644
index 00000000..d2d8ca47
--- /dev/null
+++ b/www/wiki/resources/lib/jquery/jquery3.js
@@ -0,0 +1,10253 @@
+/*!
+ * jQuery JavaScript Library v3.2.1
+ * https://jquery.com/
+ *
+ * Includes Sizzle.js
+ * https://sizzlejs.com/
+ *
+ * Copyright JS Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2017-03-20T18:59Z
+ */
+( function( global, factory ) {
+
+ "use strict";
+
+ if ( typeof module === "object" && typeof module.exports === "object" ) {
+
+ // For CommonJS and CommonJS-like environments where a proper `window`
+ // is present, execute the factory and get jQuery.
+ // For environments that do not have a `window` with a `document`
+ // (such as Node.js), expose a factory as module.exports.
+ // This accentuates the need for the creation of a real `window`.
+ // e.g. var jQuery = require("jquery")(window);
+ // See ticket #14549 for more info.
+ module.exports = global.document ?
+ factory( global, true ) :
+ function( w ) {
+ if ( !w.document ) {
+ throw new Error( "jQuery requires a window with a document" );
+ }
+ return factory( w );
+ };
+ } else {
+ factory( global );
+ }
+
+// Pass this if window is not defined yet
+} )( typeof window !== "undefined" ? window : this, function( window, noGlobal ) {
+
+// Edge <= 12 - 13+, Firefox <=18 - 45+, IE 10 - 11, Safari 5.1 - 9+, iOS 6 - 9.1
+// throw exceptions when non-strict code (e.g., ASP.NET 4.5) accesses strict mode
+// arguments.callee.caller (trac-13335). But as of jQuery 3.0 (2016), strict mode should be common
+// enough that all such attempts are guarded in a try block.
+"use strict";
+
+var arr = [];
+
+var document = window.document;
+
+var getProto = Object.getPrototypeOf;
+
+var slice = arr.slice;
+
+var concat = arr.concat;
+
+var push = arr.push;
+
+var indexOf = arr.indexOf;
+
+var class2type = {};
+
+var toString = class2type.toString;
+
+var hasOwn = class2type.hasOwnProperty;
+
+var fnToString = hasOwn.toString;
+
+var ObjectFunctionString = fnToString.call( Object );
+
+var support = {};
+
+
+
+ function DOMEval( code, doc ) {
+ doc = doc || document;
+
+ var script = doc.createElement( "script" );
+
+ script.text = code;
+ doc.head.appendChild( script ).parentNode.removeChild( script );
+ }
+/* global Symbol */
+// Defining this global in .eslintrc.json would create a danger of using the global
+// unguarded in another place, it seems safer to define global only for this module
+
+
+
+var
+ version = "3.2.1",
+
+ // Define a local copy of jQuery
+ jQuery = function( selector, context ) {
+
+ // The jQuery object is actually just the init constructor 'enhanced'
+ // Need init if jQuery is called (just allow error to be thrown if not included)
+ return new jQuery.fn.init( selector, context );
+ },
+
+ // Support: Android <=4.0 only
+ // Make sure we trim BOM and NBSP
+ rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g,
+
+ // Matches dashed string for camelizing
+ rmsPrefix = /^-ms-/,
+ rdashAlpha = /-([a-z])/g,
+
+ // Used by jQuery.camelCase as callback to replace()
+ fcamelCase = function( all, letter ) {
+ return letter.toUpperCase();
+ };
+
+jQuery.fn = jQuery.prototype = {
+
+ // The current version of jQuery being used
+ jquery: version,
+
+ constructor: jQuery,
+
+ // The default length of a jQuery object is 0
+ length: 0,
+
+ toArray: function() {
+ return slice.call( this );
+ },
+
+ // Get the Nth element in the matched element set OR
+ // Get the whole matched element set as a clean array
+ get: function( num ) {
+
+ // Return all the elements in a clean array
+ if ( num == null ) {
+ return slice.call( this );
+ }
+
+ // Return just the one element from the set
+ return num < 0 ? this[ num + this.length ] : this[ num ];
+ },
+
+ // Take an array of elements and push it onto the stack
+ // (returning the new matched element set)
+ pushStack: function( elems ) {
+
+ // Build a new jQuery matched element set
+ var ret = jQuery.merge( this.constructor(), elems );
+
+ // Add the old object onto the stack (as a reference)
+ ret.prevObject = this;
+
+ // Return the newly-formed element set
+ return ret;
+ },
+
+ // Execute a callback for every element in the matched set.
+ each: function( callback ) {
+ return jQuery.each( this, callback );
+ },
+
+ map: function( callback ) {
+ return this.pushStack( jQuery.map( this, function( elem, i ) {
+ return callback.call( elem, i, elem );
+ } ) );
+ },
+
+ slice: function() {
+ return this.pushStack( slice.apply( this, arguments ) );
+ },
+
+ first: function() {
+ return this.eq( 0 );
+ },
+
+ last: function() {
+ return this.eq( -1 );
+ },
+
+ eq: function( i ) {
+ var len = this.length,
+ j = +i + ( i < 0 ? len : 0 );
+ return this.pushStack( j >= 0 && j < len ? [ this[ j ] ] : [] );
+ },
+
+ end: function() {
+ return this.prevObject || this.constructor();
+ },
+
+ // For internal use only.
+ // Behaves like an Array's method, not like a jQuery method.
+ push: push,
+ sort: arr.sort,
+ splice: arr.splice
+};
+
+jQuery.extend = jQuery.fn.extend = function() {
+ var options, name, src, copy, copyIsArray, clone,
+ target = arguments[ 0 ] || {},
+ i = 1,
+ length = arguments.length,
+ deep = false;
+
+ // Handle a deep copy situation
+ if ( typeof target === "boolean" ) {
+ deep = target;
+
+ // Skip the boolean and the target
+ target = arguments[ i ] || {};
+ i++;
+ }
+
+ // Handle case when target is a string or something (possible in deep copy)
+ if ( typeof target !== "object" && !jQuery.isFunction( target ) ) {
+ target = {};
+ }
+
+ // Extend jQuery itself if only one argument is passed
+ if ( i === length ) {
+ target = this;
+ i--;
+ }
+
+ for ( ; i < length; i++ ) {
+
+ // Only deal with non-null/undefined values
+ if ( ( options = arguments[ i ] ) != null ) {
+
+ // Extend the base object
+ for ( name in options ) {
+ src = target[ name ];
+ copy = options[ name ];
+
+ // Prevent never-ending loop
+ if ( target === copy ) {
+ continue;
+ }
+
+ // Recurse if we're merging plain objects or arrays
+ if ( deep && copy && ( jQuery.isPlainObject( copy ) ||
+ ( copyIsArray = Array.isArray( copy ) ) ) ) {
+
+ if ( copyIsArray ) {
+ copyIsArray = false;
+ clone = src && Array.isArray( src ) ? src : [];
+
+ } else {
+ clone = src && jQuery.isPlainObject( src ) ? src : {};
+ }
+
+ // Never move original objects, clone them
+ target[ name ] = jQuery.extend( deep, clone, copy );
+
+ // Don't bring in undefined values
+ } else if ( copy !== undefined ) {
+ target[ name ] = copy;
+ }
+ }
+ }
+ }
+
+ // Return the modified object
+ return target;
+};
+
+jQuery.extend( {
+
+ // Unique for each copy of jQuery on the page
+ expando: "jQuery" + ( version + Math.random() ).replace( /\D/g, "" ),
+
+ // Assume jQuery is ready without the ready module
+ isReady: true,
+
+ error: function( msg ) {
+ throw new Error( msg );
+ },
+
+ noop: function() {},
+
+ isFunction: function( obj ) {
+ return jQuery.type( obj ) === "function";
+ },
+
+ isWindow: function( obj ) {
+ return obj != null && obj === obj.window;
+ },
+
+ isNumeric: function( obj ) {
+
+ // As of jQuery 3.0, isNumeric is limited to
+ // strings and numbers (primitives or objects)
+ // that can be coerced to finite numbers (gh-2662)
+ var type = jQuery.type( obj );
+ return ( type === "number" || type === "string" ) &&
+
+ // parseFloat NaNs numeric-cast false positives ("")
+ // ...but misinterprets leading-number strings, particularly hex literals ("0x...")
+ // subtraction forces infinities to NaN
+ !isNaN( obj - parseFloat( obj ) );
+ },
+
+ isPlainObject: function( obj ) {
+ var proto, Ctor;
+
+ // Detect obvious negatives
+ // Use toString instead of jQuery.type to catch host objects
+ if ( !obj || toString.call( obj ) !== "[object Object]" ) {
+ return false;
+ }
+
+ proto = getProto( obj );
+
+ // Objects with no prototype (e.g., `Object.create( null )`) are plain
+ if ( !proto ) {
+ return true;
+ }
+
+ // Objects with prototype are plain iff they were constructed by a global Object function
+ Ctor = hasOwn.call( proto, "constructor" ) && proto.constructor;
+ return typeof Ctor === "function" && fnToString.call( Ctor ) === ObjectFunctionString;
+ },
+
+ isEmptyObject: function( obj ) {
+
+ /* eslint-disable no-unused-vars */
+ // See https://github.com/eslint/eslint/issues/6125
+ var name;
+
+ for ( name in obj ) {
+ return false;
+ }
+ return true;
+ },
+
+ type: function( obj ) {
+ if ( obj == null ) {
+ return obj + "";
+ }
+
+ // Support: Android <=2.3 only (functionish RegExp)
+ return typeof obj === "object" || typeof obj === "function" ?
+ class2type[ toString.call( obj ) ] || "object" :
+ typeof obj;
+ },
+
+ // Evaluates a script in a global context
+ globalEval: function( code ) {
+ DOMEval( code );
+ },
+
+ // Convert dashed to camelCase; used by the css and data modules
+ // Support: IE <=9 - 11, Edge 12 - 13
+ // Microsoft forgot to hump their vendor prefix (#9572)
+ camelCase: function( string ) {
+ return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
+ },
+
+ each: function( obj, callback ) {
+ var length, i = 0;
+
+ if ( isArrayLike( obj ) ) {
+ length = obj.length;
+ for ( ; i < length; i++ ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
+ }
+ }
+ } else {
+ for ( i in obj ) {
+ if ( callback.call( obj[ i ], i, obj[ i ] ) === false ) {
+ break;
+ }
+ }
+ }
+
+ return obj;
+ },
+
+ // Support: Android <=4.0 only
+ trim: function( text ) {
+ return text == null ?
+ "" :
+ ( text + "" ).replace( rtrim, "" );
+ },
+
+ // results is for internal usage only
+ makeArray: function( arr, results ) {
+ var ret = results || [];
+
+ if ( arr != null ) {
+ if ( isArrayLike( Object( arr ) ) ) {
+ jQuery.merge( ret,
+ typeof arr === "string" ?
+ [ arr ] : arr
+ );
+ } else {
+ push.call( ret, arr );
+ }
+ }
+
+ return ret;
+ },
+
+ inArray: function( elem, arr, i ) {
+ return arr == null ? -1 : indexOf.call( arr, elem, i );
+ },
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ merge: function( first, second ) {
+ var len = +second.length,
+ j = 0,
+ i = first.length;
+
+ for ( ; j < len; j++ ) {
+ first[ i++ ] = second[ j ];
+ }
+
+ first.length = i;
+
+ return first;
+ },
+
+ grep: function( elems, callback, invert ) {
+ var callbackInverse,
+ matches = [],
+ i = 0,
+ length = elems.length,
+ callbackExpect = !invert;
+
+ // Go through the array, only saving the items
+ // that pass the validator function
+ for ( ; i < length; i++ ) {
+ callbackInverse = !callback( elems[ i ], i );
+ if ( callbackInverse !== callbackExpect ) {
+ matches.push( elems[ i ] );
+ }
+ }
+
+ return matches;
+ },
+
+ // arg is for internal usage only
+ map: function( elems, callback, arg ) {
+ var length, value,
+ i = 0,
+ ret = [];
+
+ // Go through the array, translating each of the items to their new values
+ if ( isArrayLike( elems ) ) {
+ length = elems.length;
+ for ( ; i < length; i++ ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+
+ // Go through every key on the object,
+ } else {
+ for ( i in elems ) {
+ value = callback( elems[ i ], i, arg );
+
+ if ( value != null ) {
+ ret.push( value );
+ }
+ }
+ }
+
+ // Flatten any nested arrays
+ return concat.apply( [], ret );
+ },
+
+ // A global GUID counter for objects
+ guid: 1,
+
+ // Bind a function to a context, optionally partially applying any
+ // arguments.
+ proxy: function( fn, context ) {
+ var tmp, args, proxy;
+
+ if ( typeof context === "string" ) {
+ tmp = fn[ context ];
+ context = fn;
+ fn = tmp;
+ }
+
+ // Quick check to determine if target is callable, in the spec
+ // this throws a TypeError, but we will just return undefined.
+ if ( !jQuery.isFunction( fn ) ) {
+ return undefined;
+ }
+
+ // Simulated bind
+ args = slice.call( arguments, 2 );
+ proxy = function() {
+ return fn.apply( context || this, args.concat( slice.call( arguments ) ) );
+ };
+
+ // Set the guid of unique handler to the same of original handler, so it can be removed
+ proxy.guid = fn.guid = fn.guid || jQuery.guid++;
+
+ return proxy;
+ },
+
+ now: Date.now,
+
+ // jQuery.support is not used in Core but other projects attach their
+ // properties to it so it needs to exist.
+ support: support
+} );
+
+if ( typeof Symbol === "function" ) {
+ jQuery.fn[ Symbol.iterator ] = arr[ Symbol.iterator ];
+}
+
+// Populate the class2type map
+jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
+function( i, name ) {
+ class2type[ "[object " + name + "]" ] = name.toLowerCase();
+} );
+
+function isArrayLike( obj ) {
+
+ // Support: real iOS 8.2 only (not reproducible in simulator)
+ // `in` check used to prevent JIT error (gh-2145)
+ // hasOwn isn't used here due to false negatives
+ // regarding Nodelist length in IE
+ var length = !!obj && "length" in obj && obj.length,
+ type = jQuery.type( obj );
+
+ if ( type === "function" || jQuery.isWindow( obj ) ) {
+ return false;
+ }
+
+ return type === "array" || length === 0 ||
+ typeof length === "number" && length > 0 && ( length - 1 ) in obj;
+}
+var Sizzle =
+/*!
+ * Sizzle CSS Selector Engine v2.3.3
+ * https://sizzlejs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * http://jquery.org/license
+ *
+ * Date: 2016-08-08
+ */
+(function( window ) {
+
+var i,
+ support,
+ Expr,
+ getText,
+ isXML,
+ tokenize,
+ compile,
+ select,
+ outermostContext,
+ sortInput,
+ hasDuplicate,
+
+ // Local document vars
+ setDocument,
+ document,
+ docElem,
+ documentIsHTML,
+ rbuggyQSA,
+ rbuggyMatches,
+ matches,
+ contains,
+
+ // Instance-specific data
+ expando = "sizzle" + 1 * new Date(),
+ preferredDoc = window.document,
+ dirruns = 0,
+ done = 0,
+ classCache = createCache(),
+ tokenCache = createCache(),
+ compilerCache = createCache(),
+ sortOrder = function( a, b ) {
+ if ( a === b ) {
+ hasDuplicate = true;
+ }
+ return 0;
+ },
+
+ // Instance methods
+ hasOwn = ({}).hasOwnProperty,
+ arr = [],
+ pop = arr.pop,
+ push_native = arr.push,
+ push = arr.push,
+ slice = arr.slice,
+ // Use a stripped-down indexOf as it's faster than native
+ // https://jsperf.com/thor-indexof-vs-for/5
+ indexOf = function( list, elem ) {
+ var i = 0,
+ len = list.length;
+ for ( ; i < len; i++ ) {
+ if ( list[i] === elem ) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|loop|multiple|open|readonly|required|scoped",
+
+ // Regular expressions
+
+ // http://www.w3.org/TR/css3-selectors/#whitespace
+ whitespace = "[\\x20\\t\\r\\n\\f]",
+
+ // http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier
+ identifier = "(?:\\\\.|[\\w-]|[^\0-\\xa0])+",
+
+ // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors
+ attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace +
+ // Operator (capture 2)
+ "*([*^$|!~]?=)" + whitespace +
+ // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]"
+ "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace +
+ "*\\]",
+
+ pseudos = ":(" + identifier + ")(?:\\((" +
+ // To reduce the number of selectors needing tokenize in the preFilter, prefer arguments:
+ // 1. quoted (capture 3; capture 4 or capture 5)
+ "('((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\")|" +
+ // 2. simple (capture 6)
+ "((?:\\\\.|[^\\\\()[\\]]|" + attributes + ")*)|" +
+ // 3. anything else (capture 2)
+ ".*" +
+ ")\\)|)",
+
+ // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter
+ rwhitespace = new RegExp( whitespace + "+", "g" ),
+ rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ),
+
+ rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ),
+ rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + "*" ),
+
+ rattributeQuotes = new RegExp( "=" + whitespace + "*([^\\]'\"]*?)" + whitespace + "*\\]", "g" ),
+
+ rpseudo = new RegExp( pseudos ),
+ ridentifier = new RegExp( "^" + identifier + "$" ),
+
+ matchExpr = {
+ "ID": new RegExp( "^#(" + identifier + ")" ),
+ "CLASS": new RegExp( "^\\.(" + identifier + ")" ),
+ "TAG": new RegExp( "^(" + identifier + "|[*])" ),
+ "ATTR": new RegExp( "^" + attributes ),
+ "PSEUDO": new RegExp( "^" + pseudos ),
+ "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + whitespace +
+ "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace +
+ "*(\\d+)|))" + whitespace + "*\\)|)", "i" ),
+ "bool": new RegExp( "^(?:" + booleans + ")$", "i" ),
+ // For use in libraries implementing .is()
+ // We use this for POS matching in `select`
+ "needsContext": new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" +
+ whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" )
+ },
+
+ rinputs = /^(?:input|select|textarea|button)$/i,
+ rheader = /^h\d$/i,
+
+ rnative = /^[^{]+\{\s*\[native \w/,
+
+ // Easily-parseable/retrievable ID or TAG or CLASS selectors
+ rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,
+
+ rsibling = /[+~]/,
+
+ // CSS escapes
+ // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters
+ runescape = new RegExp( "\\\\([\\da-f]{1,6}" + whitespace + "?|(" + whitespace + ")|.)", "ig" ),
+ funescape = function( _, escaped, escapedWhitespace ) {
+ var high = "0x" + escaped - 0x10000;
+ // NaN means non-codepoint
+ // Support: Firefox<24
+ // Workaround erroneous numeric interpretation of +"0x"
+ return high !== high || escapedWhitespace ?
+ escaped :
+ high < 0 ?
+ // BMP codepoint
+ String.fromCharCode( high + 0x10000 ) :
+ // Supplemental Plane codepoint (surrogate pair)
+ String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 );
+ },
+
+ // CSS string/identifier serialization
+ // https://drafts.csswg.org/cssom/#common-serializing-idioms
+ rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,
+ fcssescape = function( ch, asCodePoint ) {
+ if ( asCodePoint ) {
+
+ // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
+ if ( ch === "\0" ) {
+ return "\uFFFD";
+ }
+
+ // Control characters and (dependent upon position) numbers get escaped as code points
+ return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
+ }
+
+ // Other potentially-special ASCII characters get backslash-escaped
+ return "\\" + ch;
+ },
+
+ // Used for iframes
+ // See setDocument()
+ // Removing the function wrapper causes a "Permission Denied"
+ // error in IE
+ unloadHandler = function() {
+ setDocument();
+ },
+
+ disabledAncestor = addCombinator(
+ function( elem ) {
+ return elem.disabled === true && ("form" in elem || "label" in elem);
+ },
+ { dir: "parentNode", next: "legend" }
+ );
+
+// Optimize for push.apply( _, NodeList )
+try {
+ push.apply(
+ (arr = slice.call( preferredDoc.childNodes )),
+ preferredDoc.childNodes
+ );
+ // Support: Android<4.0
+ // Detect silently failing push.apply
+ arr[ preferredDoc.childNodes.length ].nodeType;
+} catch ( e ) {
+ push = { apply: arr.length ?
+
+ // Leverage slice if possible
+ function( target, els ) {
+ push_native.apply( target, slice.call(els) );
+ } :
+
+ // Support: IE<9
+ // Otherwise append directly
+ function( target, els ) {
+ var j = target.length,
+ i = 0;
+ // Can't trust NodeList.length
+ while ( (target[j++] = els[i++]) ) {}
+ target.length = j - 1;
+ }
+ };
+}
+
+function Sizzle( selector, context, results, seed ) {
+ var m, i, elem, nid, match, groups, newSelector,
+ newContext = context && context.ownerDocument,
+
+ // nodeType defaults to 9, since context defaults to document
+ nodeType = context ? context.nodeType : 9;
+
+ results = results || [];
+
+ // Return early from calls with invalid selector or context
+ if ( typeof selector !== "string" || !selector ||
+ nodeType !== 1 && nodeType !== 9 && nodeType !== 11 ) {
+
+ return results;
+ }
+
+ // Try to shortcut find operations (as opposed to filters) in HTML documents
+ if ( !seed ) {
+
+ if ( ( context ? context.ownerDocument || context : preferredDoc ) !== document ) {
+ setDocument( context );
+ }
+ context = context || document;
+
+ if ( documentIsHTML ) {
+
+ // If the selector is sufficiently simple, try using a "get*By*" DOM method
+ // (excepting DocumentFragment context, where the methods don't exist)
+ if ( nodeType !== 11 && (match = rquickExpr.exec( selector )) ) {
+
+ // ID selector
+ if ( (m = match[1]) ) {
+
+ // Document context
+ if ( nodeType === 9 ) {
+ if ( (elem = context.getElementById( m )) ) {
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( elem.id === m ) {
+ results.push( elem );
+ return results;
+ }
+ } else {
+ return results;
+ }
+
+ // Element context
+ } else {
+
+ // Support: IE, Opera, Webkit
+ // TODO: identify versions
+ // getElementById can match elements by name instead of ID
+ if ( newContext && (elem = newContext.getElementById( m )) &&
+ contains( context, elem ) &&
+ elem.id === m ) {
+
+ results.push( elem );
+ return results;
+ }
+ }
+
+ // Type selector
+ } else if ( match[2] ) {
+ push.apply( results, context.getElementsByTagName( selector ) );
+ return results;
+
+ // Class selector
+ } else if ( (m = match[3]) && support.getElementsByClassName &&
+ context.getElementsByClassName ) {
+
+ push.apply( results, context.getElementsByClassName( m ) );
+ return results;
+ }
+ }
+
+ // Take advantage of querySelectorAll
+ if ( support.qsa &&
+ !compilerCache[ selector + " " ] &&
+ (!rbuggyQSA || !rbuggyQSA.test( selector )) ) {
+
+ if ( nodeType !== 1 ) {
+ newContext = context;
+ newSelector = selector;
+
+ // qSA looks outside Element context, which is not what we want
+ // Thanks to Andrew Dupont for this workaround technique
+ // Support: IE <=8
+ // Exclude object elements
+ } else if ( context.nodeName.toLowerCase() !== "object" ) {
+
+ // Capture the context ID, setting it first if necessary
+ if ( (nid = context.getAttribute( "id" )) ) {
+ nid = nid.replace( rcssescape, fcssescape );
+ } else {
+ context.setAttribute( "id", (nid = expando) );
+ }
+
+ // Prefix every selector in the list
+ groups = tokenize( selector );
+ i = groups.length;
+ while ( i-- ) {
+ groups[i] = "#" + nid + " " + toSelector( groups[i] );
+ }
+ newSelector = groups.join( "," );
+
+ // Expand context for sibling selectors
+ newContext = rsibling.test( selector ) && testContext( context.parentNode ) ||
+ context;
+ }
+
+ if ( newSelector ) {
+ try {
+ push.apply( results,
+ newContext.querySelectorAll( newSelector )
+ );
+ return results;
+ } catch ( qsaError ) {
+ } finally {
+ if ( nid === expando ) {
+ context.removeAttribute( "id" );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ // All others
+ return select( selector.replace( rtrim, "$1" ), context, results, seed );
+}
+
+/**
+ * Create key-value caches of limited size
+ * @returns {function(string, object)} Returns the Object data after storing it on itself with
+ * property name the (space-suffixed) string and (if the cache is larger than Expr.cacheLength)
+ * deleting the oldest entry
+ */
+function createCache() {
+ var keys = [];
+
+ function cache( key, value ) {
+ // Use (key + " ") to avoid collision with native prototype properties (see Issue #157)
+ if ( keys.push( key + " " ) > Expr.cacheLength ) {
+ // Only keep the most recent entries
+ delete cache[ keys.shift() ];
+ }
+ return (cache[ key + " " ] = value);
+ }
+ return cache;
+}
+
+/**
+ * Mark a function for special use by Sizzle
+ * @param {Function} fn The function to mark
+ */
+function markFunction( fn ) {
+ fn[ expando ] = true;
+ return fn;
+}
+
+/**
+ * Support testing using an element
+ * @param {Function} fn Passed the created element and returns a boolean result
+ */
+function assert( fn ) {
+ var el = document.createElement("fieldset");
+
+ try {
+ return !!fn( el );
+ } catch (e) {
+ return false;
+ } finally {
+ // Remove from its parent by default
+ if ( el.parentNode ) {
+ el.parentNode.removeChild( el );
+ }
+ // release memory in IE
+ el = null;
+ }
+}
+
+/**
+ * Adds the same handler for all of the specified attrs
+ * @param {String} attrs Pipe-separated list of attributes
+ * @param {Function} handler The method that will be applied
+ */
+function addHandle( attrs, handler ) {
+ var arr = attrs.split("|"),
+ i = arr.length;
+
+ while ( i-- ) {
+ Expr.attrHandle[ arr[i] ] = handler;
+ }
+}
+
+/**
+ * Checks document order of two siblings
+ * @param {Element} a
+ * @param {Element} b
+ * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b
+ */
+function siblingCheck( a, b ) {
+ var cur = b && a,
+ diff = cur && a.nodeType === 1 && b.nodeType === 1 &&
+ a.sourceIndex - b.sourceIndex;
+
+ // Use IE sourceIndex if available on both nodes
+ if ( diff ) {
+ return diff;
+ }
+
+ // Check if b follows a
+ if ( cur ) {
+ while ( (cur = cur.nextSibling) ) {
+ if ( cur === b ) {
+ return -1;
+ }
+ }
+ }
+
+ return a ? 1 : -1;
+}
+
+/**
+ * Returns a function to use in pseudos for input types
+ * @param {String} type
+ */
+function createInputPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for buttons
+ * @param {String} type
+ */
+function createButtonPseudo( type ) {
+ return function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return (name === "input" || name === "button") && elem.type === type;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for :enabled/:disabled
+ * @param {Boolean} disabled true for :disabled; false for :enabled
+ */
+function createDisabledPseudo( disabled ) {
+
+ // Known :disabled false positives: fieldset[disabled] > legend:nth-of-type(n+2) :can-disable
+ return function( elem ) {
+
+ // Only certain elements can match :enabled or :disabled
+ // https://html.spec.whatwg.org/multipage/scripting.html#selector-enabled
+ // https://html.spec.whatwg.org/multipage/scripting.html#selector-disabled
+ if ( "form" in elem ) {
+
+ // Check for inherited disabledness on relevant non-disabled elements:
+ // * listed form-associated elements in a disabled fieldset
+ // https://html.spec.whatwg.org/multipage/forms.html#category-listed
+ // https://html.spec.whatwg.org/multipage/forms.html#concept-fe-disabled
+ // * option elements in a disabled optgroup
+ // https://html.spec.whatwg.org/multipage/forms.html#concept-option-disabled
+ // All such elements have a "form" property.
+ if ( elem.parentNode && elem.disabled === false ) {
+
+ // Option elements defer to a parent optgroup if present
+ if ( "label" in elem ) {
+ if ( "label" in elem.parentNode ) {
+ return elem.parentNode.disabled === disabled;
+ } else {
+ return elem.disabled === disabled;
+ }
+ }
+
+ // Support: IE 6 - 11
+ // Use the isDisabled shortcut property to check for disabled fieldset ancestors
+ return elem.isDisabled === disabled ||
+
+ // Where there is no isDisabled, check manually
+ /* jshint -W018 */
+ elem.isDisabled !== !disabled &&
+ disabledAncestor( elem ) === disabled;
+ }
+
+ return elem.disabled === disabled;
+
+ // Try to winnow out elements that can't be disabled before trusting the disabled property.
+ // Some victims get caught in our net (label, legend, menu, track), but it shouldn't
+ // even exist on them, let alone have a boolean value.
+ } else if ( "label" in elem ) {
+ return elem.disabled === disabled;
+ }
+
+ // Remaining elements are neither :enabled nor :disabled
+ return false;
+ };
+}
+
+/**
+ * Returns a function to use in pseudos for positionals
+ * @param {Function} fn
+ */
+function createPositionalPseudo( fn ) {
+ return markFunction(function( argument ) {
+ argument = +argument;
+ return markFunction(function( seed, matches ) {
+ var j,
+ matchIndexes = fn( [], seed.length, argument ),
+ i = matchIndexes.length;
+
+ // Match elements found at the specified indexes
+ while ( i-- ) {
+ if ( seed[ (j = matchIndexes[i]) ] ) {
+ seed[j] = !(matches[j] = seed[j]);
+ }
+ }
+ });
+ });
+}
+
+/**
+ * Checks a node for validity as a Sizzle context
+ * @param {Element|Object=} context
+ * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value
+ */
+function testContext( context ) {
+ return context && typeof context.getElementsByTagName !== "undefined" && context;
+}
+
+// Expose support vars for convenience
+support = Sizzle.support = {};
+
+/**
+ * Detects XML nodes
+ * @param {Element|Object} elem An element or a document
+ * @returns {Boolean} True iff elem is a non-HTML XML node
+ */
+isXML = Sizzle.isXML = function( elem ) {
+ // documentElement is verified for cases where it doesn't yet exist
+ // (such as loading iframes in IE - #4833)
+ var documentElement = elem && (elem.ownerDocument || elem).documentElement;
+ return documentElement ? documentElement.nodeName !== "HTML" : false;
+};
+
+/**
+ * Sets document-related variables once based on the current document
+ * @param {Element|Object} [doc] An element or document object to use to set the document
+ * @returns {Object} Returns the current document
+ */
+setDocument = Sizzle.setDocument = function( node ) {
+ var hasCompare, subWindow,
+ doc = node ? node.ownerDocument || node : preferredDoc;
+
+ // Return early if doc is invalid or already selected
+ if ( doc === document || doc.nodeType !== 9 || !doc.documentElement ) {
+ return document;
+ }
+
+ // Update global variables
+ document = doc;
+ docElem = document.documentElement;
+ documentIsHTML = !isXML( document );
+
+ // Support: IE 9-11, Edge
+ // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936)
+ if ( preferredDoc !== document &&
+ (subWindow = document.defaultView) && subWindow.top !== subWindow ) {
+
+ // Support: IE 11, Edge
+ if ( subWindow.addEventListener ) {
+ subWindow.addEventListener( "unload", unloadHandler, false );
+
+ // Support: IE 9 - 10 only
+ } else if ( subWindow.attachEvent ) {
+ subWindow.attachEvent( "onunload", unloadHandler );
+ }
+ }
+
+ /* Attributes
+ ---------------------------------------------------------------------- */
+
+ // Support: IE<8
+ // Verify that getAttribute really returns attributes and not properties
+ // (excepting IE8 booleans)
+ support.attributes = assert(function( el ) {
+ el.className = "i";
+ return !el.getAttribute("className");
+ });
+
+ /* getElement(s)By*
+ ---------------------------------------------------------------------- */
+
+ // Check if getElementsByTagName("*") returns only elements
+ support.getElementsByTagName = assert(function( el ) {
+ el.appendChild( document.createComment("") );
+ return !el.getElementsByTagName("*").length;
+ });
+
+ // Support: IE<9
+ support.getElementsByClassName = rnative.test( document.getElementsByClassName );
+
+ // Support: IE<10
+ // Check if getElementById returns elements by name
+ // The broken getElementById methods don't pick up programmatically-set names,
+ // so use a roundabout getElementsByName test
+ support.getById = assert(function( el ) {
+ docElem.appendChild( el ).id = expando;
+ return !document.getElementsByName || !document.getElementsByName( expando ).length;
+ });
+
+ // ID filter and find
+ if ( support.getById ) {
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ return elem.getAttribute("id") === attrId;
+ };
+ };
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+ var elem = context.getElementById( id );
+ return elem ? [ elem ] : [];
+ }
+ };
+ } else {
+ Expr.filter["ID"] = function( id ) {
+ var attrId = id.replace( runescape, funescape );
+ return function( elem ) {
+ var node = typeof elem.getAttributeNode !== "undefined" &&
+ elem.getAttributeNode("id");
+ return node && node.value === attrId;
+ };
+ };
+
+ // Support: IE 6 - 7 only
+ // getElementById is not reliable as a find shortcut
+ Expr.find["ID"] = function( id, context ) {
+ if ( typeof context.getElementById !== "undefined" && documentIsHTML ) {
+ var node, i, elems,
+ elem = context.getElementById( id );
+
+ if ( elem ) {
+
+ // Verify the id attribute
+ node = elem.getAttributeNode("id");
+ if ( node && node.value === id ) {
+ return [ elem ];
+ }
+
+ // Fall back on getElementsByName
+ elems = context.getElementsByName( id );
+ i = 0;
+ while ( (elem = elems[i++]) ) {
+ node = elem.getAttributeNode("id");
+ if ( node && node.value === id ) {
+ return [ elem ];
+ }
+ }
+ }
+
+ return [];
+ }
+ };
+ }
+
+ // Tag
+ Expr.find["TAG"] = support.getElementsByTagName ?
+ function( tag, context ) {
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ return context.getElementsByTagName( tag );
+
+ // DocumentFragment nodes don't have gEBTN
+ } else if ( support.qsa ) {
+ return context.querySelectorAll( tag );
+ }
+ } :
+
+ function( tag, context ) {
+ var elem,
+ tmp = [],
+ i = 0,
+ // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too
+ results = context.getElementsByTagName( tag );
+
+ // Filter out possible comments
+ if ( tag === "*" ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem.nodeType === 1 ) {
+ tmp.push( elem );
+ }
+ }
+
+ return tmp;
+ }
+ return results;
+ };
+
+ // Class
+ Expr.find["CLASS"] = support.getElementsByClassName && function( className, context ) {
+ if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) {
+ return context.getElementsByClassName( className );
+ }
+ };
+
+ /* QSA/matchesSelector
+ ---------------------------------------------------------------------- */
+
+ // QSA and matchesSelector support
+
+ // matchesSelector(:active) reports false when true (IE9/Opera 11.5)
+ rbuggyMatches = [];
+
+ // qSa(:focus) reports false when true (Chrome 21)
+ // We allow this because of a bug in IE8/9 that throws an error
+ // whenever `document.activeElement` is accessed on an iframe
+ // So, we allow :focus to pass through QSA all the time to avoid the IE error
+ // See https://bugs.jquery.com/ticket/13378
+ rbuggyQSA = [];
+
+ if ( (support.qsa = rnative.test( document.querySelectorAll )) ) {
+ // Build QSA regex
+ // Regex strategy adopted from Diego Perini
+ assert(function( el ) {
+ // Select is set to empty string on purpose
+ // This is to test IE's treatment of not explicitly
+ // setting a boolean content attribute,
+ // since its presence should be enough
+ // https://bugs.jquery.com/ticket/12359
+ docElem.appendChild( el ).innerHTML = "<a id='" + expando + "'></a>" +
+ "<select id='" + expando + "-\r\\' msallowcapture=''>" +
+ "<option selected=''></option></select>";
+
+ // Support: IE8, Opera 11-12.16
+ // Nothing should be selected when empty strings follow ^= or $= or *=
+ // The test attribute must be unknown in Opera but "safe" for WinRT
+ // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section
+ if ( el.querySelectorAll("[msallowcapture^='']").length ) {
+ rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" );
+ }
+
+ // Support: IE8
+ // Boolean attributes and "value" are not treated correctly
+ if ( !el.querySelectorAll("[selected]").length ) {
+ rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" );
+ }
+
+ // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+
+ if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) {
+ rbuggyQSA.push("~=");
+ }
+
+ // Webkit/Opera - :checked should return selected option elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ // IE8 throws error here and will not see later tests
+ if ( !el.querySelectorAll(":checked").length ) {
+ rbuggyQSA.push(":checked");
+ }
+
+ // Support: Safari 8+, iOS 8+
+ // https://bugs.webkit.org/show_bug.cgi?id=136851
+ // In-page `selector#id sibling-combinator selector` fails
+ if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) {
+ rbuggyQSA.push(".#.+[+~]");
+ }
+ });
+
+ assert(function( el ) {
+ el.innerHTML = "<a href='' disabled='disabled'></a>" +
+ "<select disabled='disabled'><option/></select>";
+
+ // Support: Windows 8 Native Apps
+ // The type and name attributes are restricted during .innerHTML assignment
+ var input = document.createElement("input");
+ input.setAttribute( "type", "hidden" );
+ el.appendChild( input ).setAttribute( "name", "D" );
+
+ // Support: IE8
+ // Enforce case-sensitivity of name attribute
+ if ( el.querySelectorAll("[name=d]").length ) {
+ rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" );
+ }
+
+ // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled)
+ // IE8 throws error here and will not see later tests
+ if ( el.querySelectorAll(":enabled").length !== 2 ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Support: IE9-11+
+ // IE's :disabled selector does not pick up the children of disabled fieldsets
+ docElem.appendChild( el ).disabled = true;
+ if ( el.querySelectorAll(":disabled").length !== 2 ) {
+ rbuggyQSA.push( ":enabled", ":disabled" );
+ }
+
+ // Opera 10-11 does not throw on post-comma invalid pseudos
+ el.querySelectorAll("*,:x");
+ rbuggyQSA.push(",.*:");
+ });
+ }
+
+ if ( (support.matchesSelector = rnative.test( (matches = docElem.matches ||
+ docElem.webkitMatchesSelector ||
+ docElem.mozMatchesSelector ||
+ docElem.oMatchesSelector ||
+ docElem.msMatchesSelector) )) ) {
+
+ assert(function( el ) {
+ // Check to see if it's possible to do matchesSelector
+ // on a disconnected node (IE 9)
+ support.disconnectedMatch = matches.call( el, "*" );
+
+ // This should fail with an exception
+ // Gecko does not error, returns false instead
+ matches.call( el, "[s!='']:x" );
+ rbuggyMatches.push( "!=", pseudos );
+ });
+ }
+
+ rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join("|") );
+ rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join("|") );
+
+ /* Contains
+ ---------------------------------------------------------------------- */
+ hasCompare = rnative.test( docElem.compareDocumentPosition );
+
+ // Element contains another
+ // Purposefully self-exclusive
+ // As in, an element does not contain itself
+ contains = hasCompare || rnative.test( docElem.contains ) ?
+ function( a, b ) {
+ var adown = a.nodeType === 9 ? a.documentElement : a,
+ bup = b && b.parentNode;
+ return a === bup || !!( bup && bup.nodeType === 1 && (
+ adown.contains ?
+ adown.contains( bup ) :
+ a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16
+ ));
+ } :
+ function( a, b ) {
+ if ( b ) {
+ while ( (b = b.parentNode) ) {
+ if ( b === a ) {
+ return true;
+ }
+ }
+ }
+ return false;
+ };
+
+ /* Sorting
+ ---------------------------------------------------------------------- */
+
+ // Document order sorting
+ sortOrder = hasCompare ?
+ function( a, b ) {
+
+ // Flag for duplicate removal
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ // Sort on method existence if only one input has compareDocumentPosition
+ var compare = !a.compareDocumentPosition - !b.compareDocumentPosition;
+ if ( compare ) {
+ return compare;
+ }
+
+ // Calculate position if both inputs belong to the same document
+ compare = ( a.ownerDocument || a ) === ( b.ownerDocument || b ) ?
+ a.compareDocumentPosition( b ) :
+
+ // Otherwise we know they are disconnected
+ 1;
+
+ // Disconnected nodes
+ if ( compare & 1 ||
+ (!support.sortDetached && b.compareDocumentPosition( a ) === compare) ) {
+
+ // Choose the first element that is related to our preferred document
+ if ( a === document || a.ownerDocument === preferredDoc && contains(preferredDoc, a) ) {
+ return -1;
+ }
+ if ( b === document || b.ownerDocument === preferredDoc && contains(preferredDoc, b) ) {
+ return 1;
+ }
+
+ // Maintain original order
+ return sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+ }
+
+ return compare & 4 ? -1 : 1;
+ } :
+ function( a, b ) {
+ // Exit early if the nodes are identical
+ if ( a === b ) {
+ hasDuplicate = true;
+ return 0;
+ }
+
+ var cur,
+ i = 0,
+ aup = a.parentNode,
+ bup = b.parentNode,
+ ap = [ a ],
+ bp = [ b ];
+
+ // Parentless nodes are either documents or disconnected
+ if ( !aup || !bup ) {
+ return a === document ? -1 :
+ b === document ? 1 :
+ aup ? -1 :
+ bup ? 1 :
+ sortInput ?
+ ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) :
+ 0;
+
+ // If the nodes are siblings, we can do a quick check
+ } else if ( aup === bup ) {
+ return siblingCheck( a, b );
+ }
+
+ // Otherwise we need full lists of their ancestors for comparison
+ cur = a;
+ while ( (cur = cur.parentNode) ) {
+ ap.unshift( cur );
+ }
+ cur = b;
+ while ( (cur = cur.parentNode) ) {
+ bp.unshift( cur );
+ }
+
+ // Walk down the tree looking for a discrepancy
+ while ( ap[i] === bp[i] ) {
+ i++;
+ }
+
+ return i ?
+ // Do a sibling check if the nodes have a common ancestor
+ siblingCheck( ap[i], bp[i] ) :
+
+ // Otherwise nodes in our document sort first
+ ap[i] === preferredDoc ? -1 :
+ bp[i] === preferredDoc ? 1 :
+ 0;
+ };
+
+ return document;
+};
+
+Sizzle.matches = function( expr, elements ) {
+ return Sizzle( expr, null, null, elements );
+};
+
+Sizzle.matchesSelector = function( elem, expr ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ // Make sure that attribute selectors are quoted
+ expr = expr.replace( rattributeQuotes, "='$1']" );
+
+ if ( support.matchesSelector && documentIsHTML &&
+ !compilerCache[ expr + " " ] &&
+ ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) &&
+ ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) {
+
+ try {
+ var ret = matches.call( elem, expr );
+
+ // IE 9's matchesSelector returns false on disconnected nodes
+ if ( ret || support.disconnectedMatch ||
+ // As well, disconnected nodes are said to be in a document
+ // fragment in IE 9
+ elem.document && elem.document.nodeType !== 11 ) {
+ return ret;
+ }
+ } catch (e) {}
+ }
+
+ return Sizzle( expr, document, null, [ elem ] ).length > 0;
+};
+
+Sizzle.contains = function( context, elem ) {
+ // Set document vars if needed
+ if ( ( context.ownerDocument || context ) !== document ) {
+ setDocument( context );
+ }
+ return contains( context, elem );
+};
+
+Sizzle.attr = function( elem, name ) {
+ // Set document vars if needed
+ if ( ( elem.ownerDocument || elem ) !== document ) {
+ setDocument( elem );
+ }
+
+ var fn = Expr.attrHandle[ name.toLowerCase() ],
+ // Don't get fooled by Object.prototype properties (jQuery #13807)
+ val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ?
+ fn( elem, name, !documentIsHTML ) :
+ undefined;
+
+ return val !== undefined ?
+ val :
+ support.attributes || !documentIsHTML ?
+ elem.getAttribute( name ) :
+ (val = elem.getAttributeNode(name)) && val.specified ?
+ val.value :
+ null;
+};
+
+Sizzle.escape = function( sel ) {
+ return (sel + "").replace( rcssescape, fcssescape );
+};
+
+Sizzle.error = function( msg ) {
+ throw new Error( "Syntax error, unrecognized expression: " + msg );
+};
+
+/**
+ * Document sorting and removing duplicates
+ * @param {ArrayLike} results
+ */
+Sizzle.uniqueSort = function( results ) {
+ var elem,
+ duplicates = [],
+ j = 0,
+ i = 0;
+
+ // Unless we *know* we can detect duplicates, assume their presence
+ hasDuplicate = !support.detectDuplicates;
+ sortInput = !support.sortStable && results.slice( 0 );
+ results.sort( sortOrder );
+
+ if ( hasDuplicate ) {
+ while ( (elem = results[i++]) ) {
+ if ( elem === results[ i ] ) {
+ j = duplicates.push( i );
+ }
+ }
+ while ( j-- ) {
+ results.splice( duplicates[ j ], 1 );
+ }
+ }
+
+ // Clear input after sorting to release objects
+ // See https://github.com/jquery/sizzle/pull/225
+ sortInput = null;
+
+ return results;
+};
+
+/**
+ * Utility function for retrieving the text value of an array of DOM nodes
+ * @param {Array|Element} elem
+ */
+getText = Sizzle.getText = function( elem ) {
+ var node,
+ ret = "",
+ i = 0,
+ nodeType = elem.nodeType;
+
+ if ( !nodeType ) {
+ // If no nodeType, this is expected to be an array
+ while ( (node = elem[i++]) ) {
+ // Do not traverse comment nodes
+ ret += getText( node );
+ }
+ } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) {
+ // Use textContent for elements
+ // innerText usage removed for consistency of new lines (jQuery #11153)
+ if ( typeof elem.textContent === "string" ) {
+ return elem.textContent;
+ } else {
+ // Traverse its children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ ret += getText( elem );
+ }
+ }
+ } else if ( nodeType === 3 || nodeType === 4 ) {
+ return elem.nodeValue;
+ }
+ // Do not include comment or processing instruction nodes
+
+ return ret;
+};
+
+Expr = Sizzle.selectors = {
+
+ // Can be adjusted by the user
+ cacheLength: 50,
+
+ createPseudo: markFunction,
+
+ match: matchExpr,
+
+ attrHandle: {},
+
+ find: {},
+
+ relative: {
+ ">": { dir: "parentNode", first: true },
+ " ": { dir: "parentNode" },
+ "+": { dir: "previousSibling", first: true },
+ "~": { dir: "previousSibling" }
+ },
+
+ preFilter: {
+ "ATTR": function( match ) {
+ match[1] = match[1].replace( runescape, funescape );
+
+ // Move the given value to match[3] whether quoted or unquoted
+ match[3] = ( match[3] || match[4] || match[5] || "" ).replace( runescape, funescape );
+
+ if ( match[2] === "~=" ) {
+ match[3] = " " + match[3] + " ";
+ }
+
+ return match.slice( 0, 4 );
+ },
+
+ "CHILD": function( match ) {
+ /* matches from matchExpr["CHILD"]
+ 1 type (only|nth|...)
+ 2 what (child|of-type)
+ 3 argument (even|odd|\d*|\d*n([+-]\d+)?|...)
+ 4 xn-component of xn+y argument ([+-]?\d*n|)
+ 5 sign of xn-component
+ 6 x of xn-component
+ 7 sign of y-component
+ 8 y of y-component
+ */
+ match[1] = match[1].toLowerCase();
+
+ if ( match[1].slice( 0, 3 ) === "nth" ) {
+ // nth-* requires argument
+ if ( !match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ // numeric x and y parameters for Expr.filter.CHILD
+ // remember that false/true cast respectively to 0/1
+ match[4] = +( match[4] ? match[5] + (match[6] || 1) : 2 * ( match[3] === "even" || match[3] === "odd" ) );
+ match[5] = +( ( match[7] + match[8] ) || match[3] === "odd" );
+
+ // other types prohibit arguments
+ } else if ( match[3] ) {
+ Sizzle.error( match[0] );
+ }
+
+ return match;
+ },
+
+ "PSEUDO": function( match ) {
+ var excess,
+ unquoted = !match[6] && match[2];
+
+ if ( matchExpr["CHILD"].test( match[0] ) ) {
+ return null;
+ }
+
+ // Accept quoted arguments as-is
+ if ( match[3] ) {
+ match[2] = match[4] || match[5] || "";
+
+ // Strip excess characters from unquoted arguments
+ } else if ( unquoted && rpseudo.test( unquoted ) &&
+ // Get excess from tokenize (recursively)
+ (excess = tokenize( unquoted, true )) &&
+ // advance to the next closing parenthesis
+ (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) {
+
+ // excess is a negative index
+ match[0] = match[0].slice( 0, excess );
+ match[2] = unquoted.slice( 0, excess );
+ }
+
+ // Return only captures needed by the pseudo filter method (type and argument)
+ return match.slice( 0, 3 );
+ }
+ },
+
+ filter: {
+
+ "TAG": function( nodeNameSelector ) {
+ var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase();
+ return nodeNameSelector === "*" ?
+ function() { return true; } :
+ function( elem ) {
+ return elem.nodeName && elem.nodeName.toLowerCase() === nodeName;
+ };
+ },
+
+ "CLASS": function( className ) {
+ var pattern = classCache[ className + " " ];
+
+ return pattern ||
+ (pattern = new RegExp( "(^|" + whitespace + ")" + className + "(" + whitespace + "|$)" )) &&
+ classCache( className, function( elem ) {
+ return pattern.test( typeof elem.className === "string" && elem.className || typeof elem.getAttribute !== "undefined" && elem.getAttribute("class") || "" );
+ });
+ },
+
+ "ATTR": function( name, operator, check ) {
+ return function( elem ) {
+ var result = Sizzle.attr( elem, name );
+
+ if ( result == null ) {
+ return operator === "!=";
+ }
+ if ( !operator ) {
+ return true;
+ }
+
+ result += "";
+
+ return operator === "=" ? result === check :
+ operator === "!=" ? result !== check :
+ operator === "^=" ? check && result.indexOf( check ) === 0 :
+ operator === "*=" ? check && result.indexOf( check ) > -1 :
+ operator === "$=" ? check && result.slice( -check.length ) === check :
+ operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 :
+ operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" :
+ false;
+ };
+ },
+
+ "CHILD": function( type, what, argument, first, last ) {
+ var simple = type.slice( 0, 3 ) !== "nth",
+ forward = type.slice( -4 ) !== "last",
+ ofType = what === "of-type";
+
+ return first === 1 && last === 0 ?
+
+ // Shortcut for :nth-*(n)
+ function( elem ) {
+ return !!elem.parentNode;
+ } :
+
+ function( elem, context, xml ) {
+ var cache, uniqueCache, outerCache, node, nodeIndex, start,
+ dir = simple !== forward ? "nextSibling" : "previousSibling",
+ parent = elem.parentNode,
+ name = ofType && elem.nodeName.toLowerCase(),
+ useCache = !xml && !ofType,
+ diff = false;
+
+ if ( parent ) {
+
+ // :(first|last|only)-(child|of-type)
+ if ( simple ) {
+ while ( dir ) {
+ node = elem;
+ while ( (node = node[ dir ]) ) {
+ if ( ofType ?
+ node.nodeName.toLowerCase() === name :
+ node.nodeType === 1 ) {
+
+ return false;
+ }
+ }
+ // Reverse direction for :only-* (if we haven't yet done so)
+ start = dir = type === "only" && !start && "nextSibling";
+ }
+ return true;
+ }
+
+ start = [ forward ? parent.firstChild : parent.lastChild ];
+
+ // non-xml :nth-child(...) stores cache data on `parent`
+ if ( forward && useCache ) {
+
+ // Seek `elem` from a previously-cached index
+
+ // ...in a gzip-friendly way
+ node = parent;
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex && cache[ 2 ];
+ node = nodeIndex && parent.childNodes[ nodeIndex ];
+
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+
+ // Fallback to seeking `elem` from the start
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ // When found, cache indexes on `parent` and break
+ if ( node.nodeType === 1 && ++diff && node === elem ) {
+ uniqueCache[ type ] = [ dirruns, nodeIndex, diff ];
+ break;
+ }
+ }
+
+ } else {
+ // Use previously-cached element index if available
+ if ( useCache ) {
+ // ...in a gzip-friendly way
+ node = elem;
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ cache = uniqueCache[ type ] || [];
+ nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ];
+ diff = nodeIndex;
+ }
+
+ // xml :nth-child(...)
+ // or :nth-last-child(...) or :nth(-last)?-of-type(...)
+ if ( diff === false ) {
+ // Use the same loop as above to seek `elem` from the start
+ while ( (node = ++nodeIndex && node && node[ dir ] ||
+ (diff = nodeIndex = 0) || start.pop()) ) {
+
+ if ( ( ofType ?
+ node.nodeName.toLowerCase() === name :
+ node.nodeType === 1 ) &&
+ ++diff ) {
+
+ // Cache the index of each encountered element
+ if ( useCache ) {
+ outerCache = node[ expando ] || (node[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ node.uniqueID ] ||
+ (outerCache[ node.uniqueID ] = {});
+
+ uniqueCache[ type ] = [ dirruns, diff ];
+ }
+
+ if ( node === elem ) {
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ // Incorporate the offset, then check against cycle size
+ diff -= last;
+ return diff === first || ( diff % first === 0 && diff / first >= 0 );
+ }
+ };
+ },
+
+ "PSEUDO": function( pseudo, argument ) {
+ // pseudo-class names are case-insensitive
+ // http://www.w3.org/TR/selectors/#pseudo-classes
+ // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters
+ // Remember that setFilters inherits from pseudos
+ var args,
+ fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] ||
+ Sizzle.error( "unsupported pseudo: " + pseudo );
+
+ // The user may use createPseudo to indicate that
+ // arguments are needed to create the filter function
+ // just as Sizzle does
+ if ( fn[ expando ] ) {
+ return fn( argument );
+ }
+
+ // But maintain support for old signatures
+ if ( fn.length > 1 ) {
+ args = [ pseudo, pseudo, "", argument ];
+ return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ?
+ markFunction(function( seed, matches ) {
+ var idx,
+ matched = fn( seed, argument ),
+ i = matched.length;
+ while ( i-- ) {
+ idx = indexOf( seed, matched[i] );
+ seed[ idx ] = !( matches[ idx ] = matched[i] );
+ }
+ }) :
+ function( elem ) {
+ return fn( elem, 0, args );
+ };
+ }
+
+ return fn;
+ }
+ },
+
+ pseudos: {
+ // Potentially complex pseudos
+ "not": markFunction(function( selector ) {
+ // Trim the selector passed to compile
+ // to avoid treating leading and trailing
+ // spaces as combinators
+ var input = [],
+ results = [],
+ matcher = compile( selector.replace( rtrim, "$1" ) );
+
+ return matcher[ expando ] ?
+ markFunction(function( seed, matches, context, xml ) {
+ var elem,
+ unmatched = matcher( seed, null, xml, [] ),
+ i = seed.length;
+
+ // Match elements unmatched by `matcher`
+ while ( i-- ) {
+ if ( (elem = unmatched[i]) ) {
+ seed[i] = !(matches[i] = elem);
+ }
+ }
+ }) :
+ function( elem, context, xml ) {
+ input[0] = elem;
+ matcher( input, null, xml, results );
+ // Don't keep the element (issue #299)
+ input[0] = null;
+ return !results.pop();
+ };
+ }),
+
+ "has": markFunction(function( selector ) {
+ return function( elem ) {
+ return Sizzle( selector, elem ).length > 0;
+ };
+ }),
+
+ "contains": markFunction(function( text ) {
+ text = text.replace( runescape, funescape );
+ return function( elem ) {
+ return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1;
+ };
+ }),
+
+ // "Whether an element is represented by a :lang() selector
+ // is based solely on the element's language value
+ // being equal to the identifier C,
+ // or beginning with the identifier C immediately followed by "-".
+ // The matching of C against the element's language value is performed case-insensitively.
+ // The identifier C does not have to be a valid language name."
+ // http://www.w3.org/TR/selectors/#lang-pseudo
+ "lang": markFunction( function( lang ) {
+ // lang value must be a valid identifier
+ if ( !ridentifier.test(lang || "") ) {
+ Sizzle.error( "unsupported lang: " + lang );
+ }
+ lang = lang.replace( runescape, funescape ).toLowerCase();
+ return function( elem ) {
+ var elemLang;
+ do {
+ if ( (elemLang = documentIsHTML ?
+ elem.lang :
+ elem.getAttribute("xml:lang") || elem.getAttribute("lang")) ) {
+
+ elemLang = elemLang.toLowerCase();
+ return elemLang === lang || elemLang.indexOf( lang + "-" ) === 0;
+ }
+ } while ( (elem = elem.parentNode) && elem.nodeType === 1 );
+ return false;
+ };
+ }),
+
+ // Miscellaneous
+ "target": function( elem ) {
+ var hash = window.location && window.location.hash;
+ return hash && hash.slice( 1 ) === elem.id;
+ },
+
+ "root": function( elem ) {
+ return elem === docElem;
+ },
+
+ "focus": function( elem ) {
+ return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
+ },
+
+ // Boolean properties
+ "enabled": createDisabledPseudo( false ),
+ "disabled": createDisabledPseudo( true ),
+
+ "checked": function( elem ) {
+ // In CSS3, :checked should return both checked and selected elements
+ // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked
+ var nodeName = elem.nodeName.toLowerCase();
+ return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected);
+ },
+
+ "selected": function( elem ) {
+ // Accessing this property makes selected-by-default
+ // options in Safari work properly
+ if ( elem.parentNode ) {
+ elem.parentNode.selectedIndex;
+ }
+
+ return elem.selected === true;
+ },
+
+ // Contents
+ "empty": function( elem ) {
+ // http://www.w3.org/TR/selectors/#empty-pseudo
+ // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5),
+ // but not by others (comment: 8; processing instruction: 7; etc.)
+ // nodeType < 6 works because attributes (2) do not appear as children
+ for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) {
+ if ( elem.nodeType < 6 ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ "parent": function( elem ) {
+ return !Expr.pseudos["empty"]( elem );
+ },
+
+ // Element/input types
+ "header": function( elem ) {
+ return rheader.test( elem.nodeName );
+ },
+
+ "input": function( elem ) {
+ return rinputs.test( elem.nodeName );
+ },
+
+ "button": function( elem ) {
+ var name = elem.nodeName.toLowerCase();
+ return name === "input" && elem.type === "button" || name === "button";
+ },
+
+ "text": function( elem ) {
+ var attr;
+ return elem.nodeName.toLowerCase() === "input" &&
+ elem.type === "text" &&
+
+ // Support: IE<8
+ // New HTML5 attribute values (e.g., "search") appear with elem.type === "text"
+ ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === "text" );
+ },
+
+ // Position-in-collection
+ "first": createPositionalPseudo(function() {
+ return [ 0 ];
+ }),
+
+ "last": createPositionalPseudo(function( matchIndexes, length ) {
+ return [ length - 1 ];
+ }),
+
+ "eq": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ return [ argument < 0 ? argument + length : argument ];
+ }),
+
+ "even": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 0;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "odd": createPositionalPseudo(function( matchIndexes, length ) {
+ var i = 1;
+ for ( ; i < length; i += 2 ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "lt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; --i >= 0; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ }),
+
+ "gt": createPositionalPseudo(function( matchIndexes, length, argument ) {
+ var i = argument < 0 ? argument + length : argument;
+ for ( ; ++i < length; ) {
+ matchIndexes.push( i );
+ }
+ return matchIndexes;
+ })
+ }
+};
+
+Expr.pseudos["nth"] = Expr.pseudos["eq"];
+
+// Add button/input type pseudos
+for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) {
+ Expr.pseudos[ i ] = createInputPseudo( i );
+}
+for ( i in { submit: true, reset: true } ) {
+ Expr.pseudos[ i ] = createButtonPseudo( i );
+}
+
+// Easy API for creating new setFilters
+function setFilters() {}
+setFilters.prototype = Expr.filters = Expr.pseudos;
+Expr.setFilters = new setFilters();
+
+tokenize = Sizzle.tokenize = function( selector, parseOnly ) {
+ var matched, match, tokens, type,
+ soFar, groups, preFilters,
+ cached = tokenCache[ selector + " " ];
+
+ if ( cached ) {
+ return parseOnly ? 0 : cached.slice( 0 );
+ }
+
+ soFar = selector;
+ groups = [];
+ preFilters = Expr.preFilter;
+
+ while ( soFar ) {
+
+ // Comma and first run
+ if ( !matched || (match = rcomma.exec( soFar )) ) {
+ if ( match ) {
+ // Don't consume trailing commas as valid
+ soFar = soFar.slice( match[0].length ) || soFar;
+ }
+ groups.push( (tokens = []) );
+ }
+
+ matched = false;
+
+ // Combinators
+ if ( (match = rcombinators.exec( soFar )) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ // Cast descendant combinators to space
+ type: match[0].replace( rtrim, " " )
+ });
+ soFar = soFar.slice( matched.length );
+ }
+
+ // Filters
+ for ( type in Expr.filter ) {
+ if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] ||
+ (match = preFilters[ type ]( match ))) ) {
+ matched = match.shift();
+ tokens.push({
+ value: matched,
+ type: type,
+ matches: match
+ });
+ soFar = soFar.slice( matched.length );
+ }
+ }
+
+ if ( !matched ) {
+ break;
+ }
+ }
+
+ // Return the length of the invalid excess
+ // if we're just parsing
+ // Otherwise, throw an error or return tokens
+ return parseOnly ?
+ soFar.length :
+ soFar ?
+ Sizzle.error( selector ) :
+ // Cache the tokens
+ tokenCache( selector, groups ).slice( 0 );
+};
+
+function toSelector( tokens ) {
+ var i = 0,
+ len = tokens.length,
+ selector = "";
+ for ( ; i < len; i++ ) {
+ selector += tokens[i].value;
+ }
+ return selector;
+}
+
+function addCombinator( matcher, combinator, base ) {
+ var dir = combinator.dir,
+ skip = combinator.next,
+ key = skip || dir,
+ checkNonElements = base && key === "parentNode",
+ doneName = done++;
+
+ return combinator.first ?
+ // Check against closest ancestor/preceding element
+ function( elem, context, xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ return matcher( elem, context, xml );
+ }
+ }
+ return false;
+ } :
+
+ // Check against all ancestor/preceding elements
+ function( elem, context, xml ) {
+ var oldCache, uniqueCache, outerCache,
+ newCache = [ dirruns, doneName ];
+
+ // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching
+ if ( xml ) {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ if ( matcher( elem, context, xml ) ) {
+ return true;
+ }
+ }
+ }
+ } else {
+ while ( (elem = elem[ dir ]) ) {
+ if ( elem.nodeType === 1 || checkNonElements ) {
+ outerCache = elem[ expando ] || (elem[ expando ] = {});
+
+ // Support: IE <9 only
+ // Defend against cloned attroperties (jQuery gh-1709)
+ uniqueCache = outerCache[ elem.uniqueID ] || (outerCache[ elem.uniqueID ] = {});
+
+ if ( skip && skip === elem.nodeName.toLowerCase() ) {
+ elem = elem[ dir ] || elem;
+ } else if ( (oldCache = uniqueCache[ key ]) &&
+ oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) {
+
+ // Assign to newCache so results back-propagate to previous elements
+ return (newCache[ 2 ] = oldCache[ 2 ]);
+ } else {
+ // Reuse newcache so results back-propagate to previous elements
+ uniqueCache[ key ] = newCache;
+
+ // A match means we're done; a fail means we have to keep checking
+ if ( (newCache[ 2 ] = matcher( elem, context, xml )) ) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+ };
+}
+
+function elementMatcher( matchers ) {
+ return matchers.length > 1 ?
+ function( elem, context, xml ) {
+ var i = matchers.length;
+ while ( i-- ) {
+ if ( !matchers[i]( elem, context, xml ) ) {
+ return false;
+ }
+ }
+ return true;
+ } :
+ matchers[0];
+}
+
+function multipleContexts( selector, contexts, results ) {
+ var i = 0,
+ len = contexts.length;
+ for ( ; i < len; i++ ) {
+ Sizzle( selector, contexts[i], results );
+ }
+ return results;
+}
+
+function condense( unmatched, map, filter, context, xml ) {
+ var elem,
+ newUnmatched = [],
+ i = 0,
+ len = unmatched.length,
+ mapped = map != null;
+
+ for ( ; i < len; i++ ) {
+ if ( (elem = unmatched[i]) ) {
+ if ( !filter || filter( elem, context, xml ) ) {
+ newUnmatched.push( elem );
+ if ( mapped ) {
+ map.push( i );
+ }
+ }
+ }
+ }
+
+ return newUnmatched;
+}
+
+function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) {
+ if ( postFilter && !postFilter[ expando ] ) {
+ postFilter = setMatcher( postFilter );
+ }
+ if ( postFinder && !postFinder[ expando ] ) {
+ postFinder = setMatcher( postFinder, postSelector );
+ }
+ return markFunction(function( seed, results, context, xml ) {
+ var temp, i, elem,
+ preMap = [],
+ postMap = [],
+ preexisting = results.length,
+
+ // Get initial elements from seed or context
+ elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [] ),
+
+ // Prefilter to get matcher input, preserving a map for seed-results synchronization
+ matcherIn = preFilter && ( seed || !selector ) ?
+ condense( elems, preMap, preFilter, context, xml ) :
+ elems,
+
+ matcherOut = matcher ?
+ // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results,
+ postFinder || ( seed ? preFilter : preexisting || postFilter ) ?
+
+ // ...intermediate processing is necessary
+ [] :
+
+ // ...otherwise use results directly
+ results :
+ matcherIn;
+
+ // Find primary matches
+ if ( matcher ) {
+ matcher( matcherIn, matcherOut, context, xml );
+ }
+
+ // Apply postFilter
+ if ( postFilter ) {
+ temp = condense( matcherOut, postMap );
+ postFilter( temp, [], context, xml );
+
+ // Un-match failing elements by moving them back to matcherIn
+ i = temp.length;
+ while ( i-- ) {
+ if ( (elem = temp[i]) ) {
+ matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem);
+ }
+ }
+ }
+
+ if ( seed ) {
+ if ( postFinder || preFilter ) {
+ if ( postFinder ) {
+ // Get the final matcherOut by condensing this intermediate into postFinder contexts
+ temp = [];
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) ) {
+ // Restore matcherIn since elem is not yet a final match
+ temp.push( (matcherIn[i] = elem) );
+ }
+ }
+ postFinder( null, (matcherOut = []), temp, xml );
+ }
+
+ // Move matched elements from seed to results to keep them synchronized
+ i = matcherOut.length;
+ while ( i-- ) {
+ if ( (elem = matcherOut[i]) &&
+ (temp = postFinder ? indexOf( seed, elem ) : preMap[i]) > -1 ) {
+
+ seed[temp] = !(results[temp] = elem);
+ }
+ }
+ }
+
+ // Add elements to results, through postFinder if defined
+ } else {
+ matcherOut = condense(
+ matcherOut === results ?
+ matcherOut.splice( preexisting, matcherOut.length ) :
+ matcherOut
+ );
+ if ( postFinder ) {
+ postFinder( null, results, matcherOut, xml );
+ } else {
+ push.apply( results, matcherOut );
+ }
+ }
+ });
+}
+
+function matcherFromTokens( tokens ) {
+ var checkContext, matcher, j,
+ len = tokens.length,
+ leadingRelative = Expr.relative[ tokens[0].type ],
+ implicitRelative = leadingRelative || Expr.relative[" "],
+ i = leadingRelative ? 1 : 0,
+
+ // The foundational matcher ensures that elements are reachable from top-level context(s)
+ matchContext = addCombinator( function( elem ) {
+ return elem === checkContext;
+ }, implicitRelative, true ),
+ matchAnyContext = addCombinator( function( elem ) {
+ return indexOf( checkContext, elem ) > -1;
+ }, implicitRelative, true ),
+ matchers = [ function( elem, context, xml ) {
+ var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || (
+ (checkContext = context).nodeType ?
+ matchContext( elem, context, xml ) :
+ matchAnyContext( elem, context, xml ) );
+ // Avoid hanging onto element (issue #299)
+ checkContext = null;
+ return ret;
+ } ];
+
+ for ( ; i < len; i++ ) {
+ if ( (matcher = Expr.relative[ tokens[i].type ]) ) {
+ matchers = [ addCombinator(elementMatcher( matchers ), matcher) ];
+ } else {
+ matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches );
+
+ // Return special upon seeing a positional matcher
+ if ( matcher[ expando ] ) {
+ // Find the next relative operator (if any) for proper handling
+ j = ++i;
+ for ( ; j < len; j++ ) {
+ if ( Expr.relative[ tokens[j].type ] ) {
+ break;
+ }
+ }
+ return setMatcher(
+ i > 1 && elementMatcher( matchers ),
+ i > 1 && toSelector(
+ // If the preceding token was a descendant combinator, insert an implicit any-element `*`
+ tokens.slice( 0, i - 1 ).concat({ value: tokens[ i - 2 ].type === " " ? "*" : "" })
+ ).replace( rtrim, "$1" ),
+ matcher,
+ i < j && matcherFromTokens( tokens.slice( i, j ) ),
+ j < len && matcherFromTokens( (tokens = tokens.slice( j )) ),
+ j < len && toSelector( tokens )
+ );
+ }
+ matchers.push( matcher );
+ }
+ }
+
+ return elementMatcher( matchers );
+}
+
+function matcherFromGroupMatchers( elementMatchers, setMatchers ) {
+ var bySet = setMatchers.length > 0,
+ byElement = elementMatchers.length > 0,
+ superMatcher = function( seed, context, xml, results, outermost ) {
+ var elem, j, matcher,
+ matchedCount = 0,
+ i = "0",
+ unmatched = seed && [],
+ setMatched = [],
+ contextBackup = outermostContext,
+ // We must always have either seed elements or outermost context
+ elems = seed || byElement && Expr.find["TAG"]( "*", outermost ),
+ // Use integer dirruns iff this is the outermost matcher
+ dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.random() || 0.1),
+ len = elems.length;
+
+ if ( outermost ) {
+ outermostContext = context === document || context || outermost;
+ }
+
+ // Add elements passing elementMatchers directly to results
+ // Support: IE<9, Safari
+ // Tolerate NodeList properties (IE: "length"; Safari: <number>) matching elements by id
+ for ( ; i !== len && (elem = elems[i]) != null; i++ ) {
+ if ( byElement && elem ) {
+ j = 0;
+ if ( !context && elem.ownerDocument !== document ) {
+ setDocument( elem );
+ xml = !documentIsHTML;
+ }
+ while ( (matcher = elementMatchers[j++]) ) {
+ if ( matcher( elem, context || document, xml) ) {
+ results.push( elem );
+ break;
+ }
+ }
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ }
+ }
+
+ // Track unmatched elements for set filters
+ if ( bySet ) {
+ // They will have gone through all possible matchers
+ if ( (elem = !matcher && elem) ) {
+ matchedCount--;
+ }
+
+ // Lengthen the array for every element, matched or not
+ if ( seed ) {
+ unmatched.push( elem );
+ }
+ }
+ }
+
+ // `i` is now the count of elements visited above, and adding it to `matchedCount`
+ // makes the latter nonnegative.
+ matchedCount += i;
+
+ // Apply set filters to unmatched elements
+ // NOTE: This can be skipped if there are no unmatched elements (i.e., `matchedCount`
+ // equals `i`), unless we didn't visit _any_ elements in the above loop because we have
+ // no element matchers and no seed.
+ // Incrementing an initially-string "0" `i` allows `i` to remain a string only in that
+ // case, which will result in a "00" `matchedCount` that differs from `i` but is also
+ // numerically zero.
+ if ( bySet && i !== matchedCount ) {
+ j = 0;
+ while ( (matcher = setMatchers[j++]) ) {
+ matcher( unmatched, setMatched, context, xml );
+ }
+
+ if ( seed ) {
+ // Reintegrate element matches to eliminate the need for sorting
+ if ( matchedCount > 0 ) {
+ while ( i-- ) {
+ if ( !(unmatched[i] || setMatched[i]) ) {
+ setMatched[i] = pop.call( results );
+ }
+ }
+ }
+
+ // Discard index placeholder values to get only actual matches
+ setMatched = condense( setMatched );
+ }
+
+ // Add matches to results
+ push.apply( results, setMatched );
+
+ // Seedless set matches succeeding multiple successful matchers stipulate sorting
+ if ( outermost && !seed && setMatched.length > 0 &&
+ ( matchedCount + setMatchers.length ) > 1 ) {
+
+ Sizzle.uniqueSort( results );
+ }
+ }
+
+ // Override manipulation of globals by nested matchers
+ if ( outermost ) {
+ dirruns = dirrunsUnique;
+ outermostContext = contextBackup;
+ }
+
+ return unmatched;
+ };
+
+ return bySet ?
+ markFunction( superMatcher ) :
+ superMatcher;
+}
+
+compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) {
+ var i,
+ setMatchers = [],
+ elementMatchers = [],
+ cached = compilerCache[ selector + " " ];
+
+ if ( !cached ) {
+ // Generate a function of recursive functions that can be used to check each element
+ if ( !match ) {
+ match = tokenize( selector );
+ }
+ i = match.length;
+ while ( i-- ) {
+ cached = matcherFromTokens( match[i] );
+ if ( cached[ expando ] ) {
+ setMatchers.push( cached );
+ } else {
+ elementMatchers.push( cached );
+ }
+ }
+
+ // Cache the compiled function
+ cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) );
+
+ // Save selector and tokenization
+ cached.selector = selector;
+ }
+ return cached;
+};
+
+/**
+ * A low-level selection function that works with Sizzle's compiled
+ * selector functions
+ * @param {String|Function} selector A selector or a pre-compiled
+ * selector function built with Sizzle.compile
+ * @param {Element} context
+ * @param {Array} [results]
+ * @param {Array} [seed] A set of elements to match against
+ */
+select = Sizzle.select = function( selector, context, results, seed ) {
+ var i, tokens, token, type, find,
+ compiled = typeof selector === "function" && selector,
+ match = !seed && tokenize( (selector = compiled.selector || selector) );
+
+ results = results || [];
+
+ // Try to minimize operations if there is only one selector in the list and no seed
+ // (the latter of which guarantees us context)
+ if ( match.length === 1 ) {
+
+ // Reduce context if the leading compound selector is an ID
+ tokens = match[0] = match[0].slice( 0 );
+ if ( tokens.length > 2 && (token = tokens[0]).type === "ID" &&
+ context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[1].type ] ) {
+
+ context = ( Expr.find["ID"]( token.matches[0].replace(runescape, funescape), context ) || [] )[0];
+ if ( !context ) {
+ return results;
+
+ // Precompiled matchers will still verify ancestry, so step up a level
+ } else if ( compiled ) {
+ context = context.parentNode;
+ }
+
+ selector = selector.slice( tokens.shift().value.length );
+ }
+
+ // Fetch a seed set for right-to-left matching
+ i = matchExpr["needsContext"].test( selector ) ? 0 : tokens.length;
+ while ( i-- ) {
+ token = tokens[i];
+
+ // Abort if we hit a combinator
+ if ( Expr.relative[ (type = token.type) ] ) {
+ break;
+ }
+ if ( (find = Expr.find[ type ]) ) {
+ // Search, expanding context for leading sibling combinators
+ if ( (seed = find(
+ token.matches[0].replace( runescape, funescape ),
+ rsibling.test( tokens[0].type ) && testContext( context.parentNode ) || context
+ )) ) {
+
+ // If seed is empty or no tokens remain, we can return early
+ tokens.splice( i, 1 );
+ selector = seed.length && toSelector( tokens );
+ if ( !selector ) {
+ push.apply( results, seed );
+ return results;
+ }
+
+ break;
+ }
+ }
+ }
+ }
+
+ // Compile and execute a filtering function if one is not provided
+ // Provide `match` to avoid retokenization if we modified the selector above
+ ( compiled || compile( selector, match ) )(
+ seed,
+ context,
+ !documentIsHTML,
+ results,
+ !context || rsibling.test( selector ) && testContext( context.parentNode ) || context
+ );
+ return results;
+};
+
+// One-time assignments
+
+// Sort stability
+support.sortStable = expando.split("").sort( sortOrder ).join("") === expando;
+
+// Support: Chrome 14-35+
+// Always assume duplicates if they aren't passed to the comparison function
+support.detectDuplicates = !!hasDuplicate;
+
+// Initialize against the default document
+setDocument();
+
+// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27)
+// Detached nodes confoundingly follow *each other*
+support.sortDetached = assert(function( el ) {
+ // Should return 1, but returns 4 (following)
+ return el.compareDocumentPosition( document.createElement("fieldset") ) & 1;
+});
+
+// Support: IE<8
+// Prevent attribute/property "interpolation"
+// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx
+if ( !assert(function( el ) {
+ el.innerHTML = "<a href='#'></a>";
+ return el.firstChild.getAttribute("href") === "#" ;
+}) ) {
+ addHandle( "type|href|height|width", function( elem, name, isXML ) {
+ if ( !isXML ) {
+ return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 );
+ }
+ });
+}
+
+// Support: IE<9
+// Use defaultValue in place of getAttribute("value")
+if ( !support.attributes || !assert(function( el ) {
+ el.innerHTML = "<input/>";
+ el.firstChild.setAttribute( "value", "" );
+ return el.firstChild.getAttribute( "value" ) === "";
+}) ) {
+ addHandle( "value", function( elem, name, isXML ) {
+ if ( !isXML && elem.nodeName.toLowerCase() === "input" ) {
+ return elem.defaultValue;
+ }
+ });
+}
+
+// Support: IE<9
+// Use getAttributeNode to fetch booleans when getAttribute lies
+if ( !assert(function( el ) {
+ return el.getAttribute("disabled") == null;
+}) ) {
+ addHandle( booleans, function( elem, name, isXML ) {
+ var val;
+ if ( !isXML ) {
+ return elem[ name ] === true ? name.toLowerCase() :
+ (val = elem.getAttributeNode( name )) && val.specified ?
+ val.value :
+ null;
+ }
+ });
+}
+
+return Sizzle;
+
+})( window );
+
+
+
+jQuery.find = Sizzle;
+jQuery.expr = Sizzle.selectors;
+
+// Deprecated
+jQuery.expr[ ":" ] = jQuery.expr.pseudos;
+jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort;
+jQuery.text = Sizzle.getText;
+jQuery.isXMLDoc = Sizzle.isXML;
+jQuery.contains = Sizzle.contains;
+jQuery.escapeSelector = Sizzle.escape;
+
+
+
+
+var dir = function( elem, dir, until ) {
+ var matched = [],
+ truncate = until !== undefined;
+
+ while ( ( elem = elem[ dir ] ) && elem.nodeType !== 9 ) {
+ if ( elem.nodeType === 1 ) {
+ if ( truncate && jQuery( elem ).is( until ) ) {
+ break;
+ }
+ matched.push( elem );
+ }
+ }
+ return matched;
+};
+
+
+var siblings = function( n, elem ) {
+ var matched = [];
+
+ for ( ; n; n = n.nextSibling ) {
+ if ( n.nodeType === 1 && n !== elem ) {
+ matched.push( n );
+ }
+ }
+
+ return matched;
+};
+
+
+var rneedsContext = jQuery.expr.match.needsContext;
+
+
+
+function nodeName( elem, name ) {
+
+ return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase();
+
+};
+var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i );
+
+
+
+var risSimple = /^.[^:#\[\.,]*$/;
+
+// Implement the identical functionality for filter and not
+function winnow( elements, qualifier, not ) {
+ if ( jQuery.isFunction( qualifier ) ) {
+ return jQuery.grep( elements, function( elem, i ) {
+ return !!qualifier.call( elem, i, elem ) !== not;
+ } );
+ }
+
+ // Single element
+ if ( qualifier.nodeType ) {
+ return jQuery.grep( elements, function( elem ) {
+ return ( elem === qualifier ) !== not;
+ } );
+ }
+
+ // Arraylike of elements (jQuery, arguments, Array)
+ if ( typeof qualifier !== "string" ) {
+ return jQuery.grep( elements, function( elem ) {
+ return ( indexOf.call( qualifier, elem ) > -1 ) !== not;
+ } );
+ }
+
+ // Simple selector that can be filtered directly, removing non-Elements
+ if ( risSimple.test( qualifier ) ) {
+ return jQuery.filter( qualifier, elements, not );
+ }
+
+ // Complex selector, compare the two sets, removing non-Elements
+ qualifier = jQuery.filter( qualifier, elements );
+ return jQuery.grep( elements, function( elem ) {
+ return ( indexOf.call( qualifier, elem ) > -1 ) !== not && elem.nodeType === 1;
+ } );
+}
+
+jQuery.filter = function( expr, elems, not ) {
+ var elem = elems[ 0 ];
+
+ if ( not ) {
+ expr = ":not(" + expr + ")";
+ }
+
+ if ( elems.length === 1 && elem.nodeType === 1 ) {
+ return jQuery.find.matchesSelector( elem, expr ) ? [ elem ] : [];
+ }
+
+ return jQuery.find.matches( expr, jQuery.grep( elems, function( elem ) {
+ return elem.nodeType === 1;
+ } ) );
+};
+
+jQuery.fn.extend( {
+ find: function( selector ) {
+ var i, ret,
+ len = this.length,
+ self = this;
+
+ if ( typeof selector !== "string" ) {
+ return this.pushStack( jQuery( selector ).filter( function() {
+ for ( i = 0; i < len; i++ ) {
+ if ( jQuery.contains( self[ i ], this ) ) {
+ return true;
+ }
+ }
+ } ) );
+ }
+
+ ret = this.pushStack( [] );
+
+ for ( i = 0; i < len; i++ ) {
+ jQuery.find( selector, self[ i ], ret );
+ }
+
+ return len > 1 ? jQuery.uniqueSort( ret ) : ret;
+ },
+ filter: function( selector ) {
+ return this.pushStack( winnow( this, selector || [], false ) );
+ },
+ not: function( selector ) {
+ return this.pushStack( winnow( this, selector || [], true ) );
+ },
+ is: function( selector ) {
+ return !!winnow(
+ this,
+
+ // If this is a positional/relative selector, check membership in the returned set
+ // so $("p:first").is("p:last") won't return true for a doc with two "p".
+ typeof selector === "string" && rneedsContext.test( selector ) ?
+ jQuery( selector ) :
+ selector || [],
+ false
+ ).length;
+ }
+} );
+
+
+// Initialize a jQuery object
+
+
+// A central reference to the root jQuery(document)
+var rootjQuery,
+
+ // A simple way to check for HTML strings
+ // Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
+ // Strict HTML recognition (#11290: must start with <)
+ // Shortcut simple #id case for speed
+ rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/,
+
+ init = jQuery.fn.init = function( selector, context, root ) {
+ var match, elem;
+
+ // HANDLE: $(""), $(null), $(undefined), $(false)
+ if ( !selector ) {
+ return this;
+ }
+
+ // Method init() accepts an alternate rootjQuery
+ // so migrate can support jQuery.sub (gh-2101)
+ root = root || rootjQuery;
+
+ // Handle HTML strings
+ if ( typeof selector === "string" ) {
+ if ( selector[ 0 ] === "<" &&
+ selector[ selector.length - 1 ] === ">" &&
+ selector.length >= 3 ) {
+
+ // Assume that strings that start and end with <> are HTML and skip the regex check
+ match = [ null, selector, null ];
+
+ } else {
+ match = rquickExpr.exec( selector );
+ }
+
+ // Match html or make sure no context is specified for #id
+ if ( match && ( match[ 1 ] || !context ) ) {
+
+ // HANDLE: $(html) -> $(array)
+ if ( match[ 1 ] ) {
+ context = context instanceof jQuery ? context[ 0 ] : context;
+
+ // Option to run scripts is true for back-compat
+ // Intentionally let the error be thrown if parseHTML is not present
+ jQuery.merge( this, jQuery.parseHTML(
+ match[ 1 ],
+ context && context.nodeType ? context.ownerDocument || context : document,
+ true
+ ) );
+
+ // HANDLE: $(html, props)
+ if ( rsingleTag.test( match[ 1 ] ) && jQuery.isPlainObject( context ) ) {
+ for ( match in context ) {
+
+ // Properties of context are called as methods if possible
+ if ( jQuery.isFunction( this[ match ] ) ) {
+ this[ match ]( context[ match ] );
+
+ // ...and otherwise set as attributes
+ } else {
+ this.attr( match, context[ match ] );
+ }
+ }
+ }
+
+ return this;
+
+ // HANDLE: $(#id)
+ } else {
+ elem = document.getElementById( match[ 2 ] );
+
+ if ( elem ) {
+
+ // Inject the element directly into the jQuery object
+ this[ 0 ] = elem;
+ this.length = 1;
+ }
+ return this;
+ }
+
+ // HANDLE: $(expr, $(...))
+ } else if ( !context || context.jquery ) {
+ return ( context || root ).find( selector );
+
+ // HANDLE: $(expr, context)
+ // (which is just equivalent to: $(context).find(expr)
+ } else {
+ return this.constructor( context ).find( selector );
+ }
+
+ // HANDLE: $(DOMElement)
+ } else if ( selector.nodeType ) {
+ this[ 0 ] = selector;
+ this.length = 1;
+ return this;
+
+ // HANDLE: $(function)
+ // Shortcut for document ready
+ } else if ( jQuery.isFunction( selector ) ) {
+ return root.ready !== undefined ?
+ root.ready( selector ) :
+
+ // Execute immediately if ready is not present
+ selector( jQuery );
+ }
+
+ return jQuery.makeArray( selector, this );
+ };
+
+// Give the init function the jQuery prototype for later instantiation
+init.prototype = jQuery.fn;
+
+// Initialize central reference
+rootjQuery = jQuery( document );
+
+
+var rparentsprev = /^(?:parents|prev(?:Until|All))/,
+
+ // Methods guaranteed to produce a unique set when starting from a unique set
+ guaranteedUnique = {
+ children: true,
+ contents: true,
+ next: true,
+ prev: true
+ };
+
+jQuery.fn.extend( {
+ has: function( target ) {
+ var targets = jQuery( target, this ),
+ l = targets.length;
+
+ return this.filter( function() {
+ var i = 0;
+ for ( ; i < l; i++ ) {
+ if ( jQuery.contains( this, targets[ i ] ) ) {
+ return true;
+ }
+ }
+ } );
+ },
+
+ closest: function( selectors, context ) {
+ var cur,
+ i = 0,
+ l = this.length,
+ matched = [],
+ targets = typeof selectors !== "string" && jQuery( selectors );
+
+ // Positional selectors never match, since there's no _selection_ context
+ if ( !rneedsContext.test( selectors ) ) {
+ for ( ; i < l; i++ ) {
+ for ( cur = this[ i ]; cur && cur !== context; cur = cur.parentNode ) {
+
+ // Always skip document fragments
+ if ( cur.nodeType < 11 && ( targets ?
+ targets.index( cur ) > -1 :
+
+ // Don't pass non-elements to Sizzle
+ cur.nodeType === 1 &&
+ jQuery.find.matchesSelector( cur, selectors ) ) ) {
+
+ matched.push( cur );
+ break;
+ }
+ }
+ }
+ }
+
+ return this.pushStack( matched.length > 1 ? jQuery.uniqueSort( matched ) : matched );
+ },
+
+ // Determine the position of an element within the set
+ index: function( elem ) {
+
+ // No argument, return index in parent
+ if ( !elem ) {
+ return ( this[ 0 ] && this[ 0 ].parentNode ) ? this.first().prevAll().length : -1;
+ }
+
+ // Index in selector
+ if ( typeof elem === "string" ) {
+ return indexOf.call( jQuery( elem ), this[ 0 ] );
+ }
+
+ // Locate the position of the desired element
+ return indexOf.call( this,
+
+ // If it receives a jQuery object, the first element is used
+ elem.jquery ? elem[ 0 ] : elem
+ );
+ },
+
+ add: function( selector, context ) {
+ return this.pushStack(
+ jQuery.uniqueSort(
+ jQuery.merge( this.get(), jQuery( selector, context ) )
+ )
+ );
+ },
+
+ addBack: function( selector ) {
+ return this.add( selector == null ?
+ this.prevObject : this.prevObject.filter( selector )
+ );
+ }
+} );
+
+function sibling( cur, dir ) {
+ while ( ( cur = cur[ dir ] ) && cur.nodeType !== 1 ) {}
+ return cur;
+}
+
+jQuery.each( {
+ parent: function( elem ) {
+ var parent = elem.parentNode;
+ return parent && parent.nodeType !== 11 ? parent : null;
+ },
+ parents: function( elem ) {
+ return dir( elem, "parentNode" );
+ },
+ parentsUntil: function( elem, i, until ) {
+ return dir( elem, "parentNode", until );
+ },
+ next: function( elem ) {
+ return sibling( elem, "nextSibling" );
+ },
+ prev: function( elem ) {
+ return sibling( elem, "previousSibling" );
+ },
+ nextAll: function( elem ) {
+ return dir( elem, "nextSibling" );
+ },
+ prevAll: function( elem ) {
+ return dir( elem, "previousSibling" );
+ },
+ nextUntil: function( elem, i, until ) {
+ return dir( elem, "nextSibling", until );
+ },
+ prevUntil: function( elem, i, until ) {
+ return dir( elem, "previousSibling", until );
+ },
+ siblings: function( elem ) {
+ return siblings( ( elem.parentNode || {} ).firstChild, elem );
+ },
+ children: function( elem ) {
+ return siblings( elem.firstChild );
+ },
+ contents: function( elem ) {
+ if ( nodeName( elem, "iframe" ) ) {
+ return elem.contentDocument;
+ }
+
+ // Support: IE 9 - 11 only, iOS 7 only, Android Browser <=4.3 only
+ // Treat the template element as a regular one in browsers that
+ // don't support it.
+ if ( nodeName( elem, "template" ) ) {
+ elem = elem.content || elem;
+ }
+
+ return jQuery.merge( [], elem.childNodes );
+ }
+}, function( name, fn ) {
+ jQuery.fn[ name ] = function( until, selector ) {
+ var matched = jQuery.map( this, fn, until );
+
+ if ( name.slice( -5 ) !== "Until" ) {
+ selector = until;
+ }
+
+ if ( selector && typeof selector === "string" ) {
+ matched = jQuery.filter( selector, matched );
+ }
+
+ if ( this.length > 1 ) {
+
+ // Remove duplicates
+ if ( !guaranteedUnique[ name ] ) {
+ jQuery.uniqueSort( matched );
+ }
+
+ // Reverse order for parents* and prev-derivatives
+ if ( rparentsprev.test( name ) ) {
+ matched.reverse();
+ }
+ }
+
+ return this.pushStack( matched );
+ };
+} );
+var rnothtmlwhite = ( /[^\x20\t\r\n\f]+/g );
+
+
+
+// Convert String-formatted options into Object-formatted ones
+function createOptions( options ) {
+ var object = {};
+ jQuery.each( options.match( rnothtmlwhite ) || [], function( _, flag ) {
+ object[ flag ] = true;
+ } );
+ return object;
+}
+
+/*
+ * Create a callback list using the following parameters:
+ *
+ * options: an optional list of space-separated options that will change how
+ * the callback list behaves or a more traditional option object
+ *
+ * By default a callback list will act like an event callback list and can be
+ * "fired" multiple times.
+ *
+ * Possible options:
+ *
+ * once: will ensure the callback list can only be fired once (like a Deferred)
+ *
+ * memory: will keep track of previous values and will call any callback added
+ * after the list has been fired right away with the latest "memorized"
+ * values (like a Deferred)
+ *
+ * unique: will ensure a callback can only be added once (no duplicate in the list)
+ *
+ * stopOnFalse: interrupt callings when a callback returns false
+ *
+ */
+jQuery.Callbacks = function( options ) {
+
+ // Convert options from String-formatted to Object-formatted if needed
+ // (we check in cache first)
+ options = typeof options === "string" ?
+ createOptions( options ) :
+ jQuery.extend( {}, options );
+
+ var // Flag to know if list is currently firing
+ firing,
+
+ // Last fire value for non-forgettable lists
+ memory,
+
+ // Flag to know if list was already fired
+ fired,
+
+ // Flag to prevent firing
+ locked,
+
+ // Actual callback list
+ list = [],
+
+ // Queue of execution data for repeatable lists
+ queue = [],
+
+ // Index of currently firing callback (modified by add/remove as needed)
+ firingIndex = -1,
+
+ // Fire callbacks
+ fire = function() {
+
+ // Enforce single-firing
+ locked = locked || options.once;
+
+ // Execute callbacks for all pending executions,
+ // respecting firingIndex overrides and runtime changes
+ fired = firing = true;
+ for ( ; queue.length; firingIndex = -1 ) {
+ memory = queue.shift();
+ while ( ++firingIndex < list.length ) {
+
+ // Run callback and check for early termination
+ if ( list[ firingIndex ].apply( memory[ 0 ], memory[ 1 ] ) === false &&
+ options.stopOnFalse ) {
+
+ // Jump to end and forget the data so .add doesn't re-fire
+ firingIndex = list.length;
+ memory = false;
+ }
+ }
+ }
+
+ // Forget the data if we're done with it
+ if ( !options.memory ) {
+ memory = false;
+ }
+
+ firing = false;
+
+ // Clean up if we're done firing for good
+ if ( locked ) {
+
+ // Keep an empty list if we have data for future add calls
+ if ( memory ) {
+ list = [];
+
+ // Otherwise, this object is spent
+ } else {
+ list = "";
+ }
+ }
+ },
+
+ // Actual Callbacks object
+ self = {
+
+ // Add a callback or a collection of callbacks to the list
+ add: function() {
+ if ( list ) {
+
+ // If we have memory from a past run, we should fire after adding
+ if ( memory && !firing ) {
+ firingIndex = list.length - 1;
+ queue.push( memory );
+ }
+
+ ( function add( args ) {
+ jQuery.each( args, function( _, arg ) {
+ if ( jQuery.isFunction( arg ) ) {
+ if ( !options.unique || !self.has( arg ) ) {
+ list.push( arg );
+ }
+ } else if ( arg && arg.length && jQuery.type( arg ) !== "string" ) {
+
+ // Inspect recursively
+ add( arg );
+ }
+ } );
+ } )( arguments );
+
+ if ( memory && !firing ) {
+ fire();
+ }
+ }
+ return this;
+ },
+
+ // Remove a callback from the list
+ remove: function() {
+ jQuery.each( arguments, function( _, arg ) {
+ var index;
+ while ( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) {
+ list.splice( index, 1 );
+
+ // Handle firing indexes
+ if ( index <= firingIndex ) {
+ firingIndex--;
+ }
+ }
+ } );
+ return this;
+ },
+
+ // Check if a given callback is in the list.
+ // If no argument is given, return whether or not list has callbacks attached.
+ has: function( fn ) {
+ return fn ?
+ jQuery.inArray( fn, list ) > -1 :
+ list.length > 0;
+ },
+
+ // Remove all callbacks from the list
+ empty: function() {
+ if ( list ) {
+ list = [];
+ }
+ return this;
+ },
+
+ // Disable .fire and .add
+ // Abort any current/pending executions
+ // Clear all callbacks and values
+ disable: function() {
+ locked = queue = [];
+ list = memory = "";
+ return this;
+ },
+ disabled: function() {
+ return !list;
+ },
+
+ // Disable .fire
+ // Also disable .add unless we have memory (since it would have no effect)
+ // Abort any pending executions
+ lock: function() {
+ locked = queue = [];
+ if ( !memory && !firing ) {
+ list = memory = "";
+ }
+ return this;
+ },
+ locked: function() {
+ return !!locked;
+ },
+
+ // Call all callbacks with the given context and arguments
+ fireWith: function( context, args ) {
+ if ( !locked ) {
+ args = args || [];
+ args = [ context, args.slice ? args.slice() : args ];
+ queue.push( args );
+ if ( !firing ) {
+ fire();
+ }
+ }
+ return this;
+ },
+
+ // Call all the callbacks with the given arguments
+ fire: function() {
+ self.fireWith( this, arguments );
+ return this;
+ },
+
+ // To know if the callbacks have already been called at least once
+ fired: function() {
+ return !!fired;
+ }
+ };
+
+ return self;
+};
+
+
+function Identity( v ) {
+ return v;
+}
+function Thrower( ex ) {
+ throw ex;
+}
+
+function adoptValue( value, resolve, reject, noValue ) {
+ var method;
+
+ try {
+
+ // Check for promise aspect first to privilege synchronous behavior
+ if ( value && jQuery.isFunction( ( method = value.promise ) ) ) {
+ method.call( value ).done( resolve ).fail( reject );
+
+ // Other thenables
+ } else if ( value && jQuery.isFunction( ( method = value.then ) ) ) {
+ method.call( value, resolve, reject );
+
+ // Other non-thenables
+ } else {
+
+ // Control `resolve` arguments by letting Array#slice cast boolean `noValue` to integer:
+ // * false: [ value ].slice( 0 ) => resolve( value )
+ // * true: [ value ].slice( 1 ) => resolve()
+ resolve.apply( undefined, [ value ].slice( noValue ) );
+ }
+
+ // For Promises/A+, convert exceptions into rejections
+ // Since jQuery.when doesn't unwrap thenables, we can skip the extra checks appearing in
+ // Deferred#then to conditionally suppress rejection.
+ } catch ( value ) {
+
+ // Support: Android 4.0 only
+ // Strict mode functions invoked without .call/.apply get global-object context
+ reject.apply( undefined, [ value ] );
+ }
+}
+
+jQuery.extend( {
+
+ Deferred: function( func ) {
+ var tuples = [
+
+ // action, add listener, callbacks,
+ // ... .then handlers, argument index, [final state]
+ [ "notify", "progress", jQuery.Callbacks( "memory" ),
+ jQuery.Callbacks( "memory" ), 2 ],
+ [ "resolve", "done", jQuery.Callbacks( "once memory" ),
+ jQuery.Callbacks( "once memory" ), 0, "resolved" ],
+ [ "reject", "fail", jQuery.Callbacks( "once memory" ),
+ jQuery.Callbacks( "once memory" ), 1, "rejected" ]
+ ],
+ state = "pending",
+ promise = {
+ state: function() {
+ return state;
+ },
+ always: function() {
+ deferred.done( arguments ).fail( arguments );
+ return this;
+ },
+ "catch": function( fn ) {
+ return promise.then( null, fn );
+ },
+
+ // Keep pipe for back-compat
+ pipe: function( /* fnDone, fnFail, fnProgress */ ) {
+ var fns = arguments;
+
+ return jQuery.Deferred( function( newDefer ) {
+ jQuery.each( tuples, function( i, tuple ) {
+
+ // Map tuples (progress, done, fail) to arguments (done, fail, progress)
+ var fn = jQuery.isFunction( fns[ tuple[ 4 ] ] ) && fns[ tuple[ 4 ] ];
+
+ // deferred.progress(function() { bind to newDefer or newDefer.notify })
+ // deferred.done(function() { bind to newDefer or newDefer.resolve })
+ // deferred.fail(function() { bind to newDefer or newDefer.reject })
+ deferred[ tuple[ 1 ] ]( function() {
+ var returned = fn && fn.apply( this, arguments );
+ if ( returned && jQuery.isFunction( returned.promise ) ) {
+ returned.promise()
+ .progress( newDefer.notify )
+ .done( newDefer.resolve )
+ .fail( newDefer.reject );
+ } else {
+ newDefer[ tuple[ 0 ] + "With" ](
+ this,
+ fn ? [ returned ] : arguments
+ );
+ }
+ } );
+ } );
+ fns = null;
+ } ).promise();
+ },
+ then: function( onFulfilled, onRejected, onProgress ) {
+ var maxDepth = 0;
+ function resolve( depth, deferred, handler, special ) {
+ return function() {
+ var that = this,
+ args = arguments,
+ mightThrow = function() {
+ var returned, then;
+
+ // Support: Promises/A+ section 2.3.3.3.3
+ // https://promisesaplus.com/#point-59
+ // Ignore double-resolution attempts
+ if ( depth < maxDepth ) {
+ return;
+ }
+
+ returned = handler.apply( that, args );
+
+ // Support: Promises/A+ section 2.3.1
+ // https://promisesaplus.com/#point-48
+ if ( returned === deferred.promise() ) {
+ throw new TypeError( "Thenable self-resolution" );
+ }
+
+ // Support: Promises/A+ sections 2.3.3.1, 3.5
+ // https://promisesaplus.com/#point-54
+ // https://promisesaplus.com/#point-75
+ // Retrieve `then` only once
+ then = returned &&
+
+ // Support: Promises/A+ section 2.3.4
+ // https://promisesaplus.com/#point-64
+ // Only check objects and functions for thenability
+ ( typeof returned === "object" ||
+ typeof returned === "function" ) &&
+ returned.then;
+
+ // Handle a returned thenable
+ if ( jQuery.isFunction( then ) ) {
+
+ // Special processors (notify) just wait for resolution
+ if ( special ) {
+ then.call(
+ returned,
+ resolve( maxDepth, deferred, Identity, special ),
+ resolve( maxDepth, deferred, Thrower, special )
+ );
+
+ // Normal processors (resolve) also hook into progress
+ } else {
+
+ // ...and disregard older resolution values
+ maxDepth++;
+
+ then.call(
+ returned,
+ resolve( maxDepth, deferred, Identity, special ),
+ resolve( maxDepth, deferred, Thrower, special ),
+ resolve( maxDepth, deferred, Identity,
+ deferred.notifyWith )
+ );
+ }
+
+ // Handle all other returned values
+ } else {
+
+ // Only substitute handlers pass on context
+ // and multiple values (non-spec behavior)
+ if ( handler !== Identity ) {
+ that = undefined;
+ args = [ returned ];
+ }
+
+ // Process the value(s)
+ // Default process is resolve
+ ( special || deferred.resolveWith )( that, args );
+ }
+ },
+
+ // Only normal processors (resolve) catch and reject exceptions
+ process = special ?
+ mightThrow :
+ function() {
+ try {
+ mightThrow();
+ } catch ( e ) {
+
+ if ( jQuery.Deferred.exceptionHook ) {
+ jQuery.Deferred.exceptionHook( e,
+ process.stackTrace );
+ }
+
+ // Support: Promises/A+ section 2.3.3.3.4.1
+ // https://promisesaplus.com/#point-61
+ // Ignore post-resolution exceptions
+ if ( depth + 1 >= maxDepth ) {
+
+ // Only substitute handlers pass on context
+ // and multiple values (non-spec behavior)
+ if ( handler !== Thrower ) {
+ that = undefined;
+ args = [ e ];
+ }
+
+ deferred.rejectWith( that, args );
+ }
+ }
+ };
+
+ // Support: Promises/A+ section 2.3.3.3.1
+ // https://promisesaplus.com/#point-57
+ // Re-resolve promises immediately to dodge false rejection from
+ // subsequent errors
+ if ( depth ) {
+ process();
+ } else {
+
+ // Call an optional hook to record the stack, in case of exception
+ // since it's otherwise lost when execution goes async
+ if ( jQuery.Deferred.getStackHook ) {
+ process.stackTrace = jQuery.Deferred.getStackHook();
+ }
+ window.setTimeout( process );
+ }
+ };
+ }
+
+ return jQuery.Deferred( function( newDefer ) {
+
+ // progress_handlers.add( ... )
+ tuples[ 0 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onProgress ) ?
+ onProgress :
+ Identity,
+ newDefer.notifyWith
+ )
+ );
+
+ // fulfilled_handlers.add( ... )
+ tuples[ 1 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onFulfilled ) ?
+ onFulfilled :
+ Identity
+ )
+ );
+
+ // rejected_handlers.add( ... )
+ tuples[ 2 ][ 3 ].add(
+ resolve(
+ 0,
+ newDefer,
+ jQuery.isFunction( onRejected ) ?
+ onRejected :
+ Thrower
+ )
+ );
+ } ).promise();
+ },
+
+ // Get a promise for this deferred
+ // If obj is provided, the promise aspect is added to the object
+ promise: function( obj ) {
+ return obj != null ? jQuery.extend( obj, promise ) : promise;
+ }
+ },
+ deferred = {};
+
+ // Add list-specific methods
+ jQuery.each( tuples, function( i, tuple ) {
+ var list = tuple[ 2 ],
+ stateString = tuple[ 5 ];
+
+ // promise.progress = list.add
+ // promise.done = list.add
+ // promise.fail = list.add
+ promise[ tuple[ 1 ] ] = list.add;
+
+ // Handle state
+ if ( stateString ) {
+ list.add(
+ function() {
+
+ // state = "resolved" (i.e., fulfilled)
+ // state = "rejected"
+ state = stateString;
+ },
+
+ // rejected_callbacks.disable
+ // fulfilled_callbacks.disable
+ tuples[ 3 - i ][ 2 ].disable,
+
+ // progress_callbacks.lock
+ tuples[ 0 ][ 2 ].lock
+ );
+ }
+
+ // progress_handlers.fire
+ // fulfilled_handlers.fire
+ // rejected_handlers.fire
+ list.add( tuple[ 3 ].fire );
+
+ // deferred.notify = function() { deferred.notifyWith(...) }
+ // deferred.resolve = function() { deferred.resolveWith(...) }
+ // deferred.reject = function() { deferred.rejectWith(...) }
+ deferred[ tuple[ 0 ] ] = function() {
+ deferred[ tuple[ 0 ] + "With" ]( this === deferred ? undefined : this, arguments );
+ return this;
+ };
+
+ // deferred.notifyWith = list.fireWith
+ // deferred.resolveWith = list.fireWith
+ // deferred.rejectWith = list.fireWith
+ deferred[ tuple[ 0 ] + "With" ] = list.fireWith;
+ } );
+
+ // Make the deferred a promise
+ promise.promise( deferred );
+
+ // Call given func if any
+ if ( func ) {
+ func.call( deferred, deferred );
+ }
+
+ // All done!
+ return deferred;
+ },
+
+ // Deferred helper
+ when: function( singleValue ) {
+ var
+
+ // count of uncompleted subordinates
+ remaining = arguments.length,
+
+ // count of unprocessed arguments
+ i = remaining,
+
+ // subordinate fulfillment data
+ resolveContexts = Array( i ),
+ resolveValues = slice.call( arguments ),
+
+ // the master Deferred
+ master = jQuery.Deferred(),
+
+ // subordinate callback factory
+ updateFunc = function( i ) {
+ return function( value ) {
+ resolveContexts[ i ] = this;
+ resolveValues[ i ] = arguments.length > 1 ? slice.call( arguments ) : value;
+ if ( !( --remaining ) ) {
+ master.resolveWith( resolveContexts, resolveValues );
+ }
+ };
+ };
+
+ // Single- and empty arguments are adopted like Promise.resolve
+ if ( remaining <= 1 ) {
+ adoptValue( singleValue, master.done( updateFunc( i ) ).resolve, master.reject,
+ !remaining );
+
+ // Use .then() to unwrap secondary thenables (cf. gh-3000)
+ if ( master.state() === "pending" ||
+ jQuery.isFunction( resolveValues[ i ] && resolveValues[ i ].then ) ) {
+
+ return master.then();
+ }
+ }
+
+ // Multiple arguments are aggregated like Promise.all array elements
+ while ( i-- ) {
+ adoptValue( resolveValues[ i ], updateFunc( i ), master.reject );
+ }
+
+ return master.promise();
+ }
+} );
+
+
+// These usually indicate a programmer mistake during development,
+// warn about them ASAP rather than swallowing them by default.
+var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/;
+
+jQuery.Deferred.exceptionHook = function( error, stack ) {
+
+ // Support: IE 8 - 9 only
+ // Console exists when dev tools are open, which can happen at any time
+ if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) {
+ window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack );
+ }
+};
+
+
+
+
+jQuery.readyException = function( error ) {
+ window.setTimeout( function() {
+ throw error;
+ } );
+};
+
+
+
+
+// The deferred used on DOM ready
+var readyList = jQuery.Deferred();
+
+jQuery.fn.ready = function( fn ) {
+
+ readyList
+ .then( fn )
+
+ // Wrap jQuery.readyException in a function so that the lookup
+ // happens at the time of error handling instead of callback
+ // registration.
+ .catch( function( error ) {
+ jQuery.readyException( error );
+ } );
+
+ return this;
+};
+
+jQuery.extend( {
+
+ // Is the DOM ready to be used? Set to true once it occurs.
+ isReady: false,
+
+ // A counter to track how many items to wait for before
+ // the ready event fires. See #6781
+ readyWait: 1,
+
+ // Handle when the DOM is ready
+ ready: function( wait ) {
+
+ // Abort if there are pending holds or we're already ready
+ if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) {
+ return;
+ }
+
+ // Remember that the DOM is ready
+ jQuery.isReady = true;
+
+ // If a normal DOM Ready event fired, decrement, and wait if need be
+ if ( wait !== true && --jQuery.readyWait > 0 ) {
+ return;
+ }
+
+ // If there are functions bound, to execute
+ readyList.resolveWith( document, [ jQuery ] );
+ }
+} );
+
+jQuery.ready.then = readyList.then;
+
+// The ready event handler and self cleanup method
+function completed() {
+ document.removeEventListener( "DOMContentLoaded", completed );
+ window.removeEventListener( "load", completed );
+ jQuery.ready();
+}
+
+// Catch cases where $(document).ready() is called
+// after the browser event has already occurred.
+// Support: IE <=9 - 10 only
+// Older IE sometimes signals "interactive" too soon
+if ( document.readyState === "complete" ||
+ ( document.readyState !== "loading" && !document.documentElement.doScroll ) ) {
+
+ // Handle it asynchronously to allow scripts the opportunity to delay ready
+ window.setTimeout( jQuery.ready );
+
+} else {
+
+ // Use the handy event callback
+ document.addEventListener( "DOMContentLoaded", completed );
+
+ // A fallback to window.onload, that will always work
+ window.addEventListener( "load", completed );
+}
+
+
+
+
+// Multifunctional method to get and set values of a collection
+// The value/s can optionally be executed if it's a function
+var access = function( elems, fn, key, value, chainable, emptyGet, raw ) {
+ var i = 0,
+ len = elems.length,
+ bulk = key == null;
+
+ // Sets many values
+ if ( jQuery.type( key ) === "object" ) {
+ chainable = true;
+ for ( i in key ) {
+ access( elems, fn, i, key[ i ], true, emptyGet, raw );
+ }
+
+ // Sets one value
+ } else if ( value !== undefined ) {
+ chainable = true;
+
+ if ( !jQuery.isFunction( value ) ) {
+ raw = true;
+ }
+
+ if ( bulk ) {
+
+ // Bulk operations run against the entire set
+ if ( raw ) {
+ fn.call( elems, value );
+ fn = null;
+
+ // ...except when executing function values
+ } else {
+ bulk = fn;
+ fn = function( elem, key, value ) {
+ return bulk.call( jQuery( elem ), value );
+ };
+ }
+ }
+
+ if ( fn ) {
+ for ( ; i < len; i++ ) {
+ fn(
+ elems[ i ], key, raw ?
+ value :
+ value.call( elems[ i ], i, fn( elems[ i ], key ) )
+ );
+ }
+ }
+ }
+
+ if ( chainable ) {
+ return elems;
+ }
+
+ // Gets
+ if ( bulk ) {
+ return fn.call( elems );
+ }
+
+ return len ? fn( elems[ 0 ], key ) : emptyGet;
+};
+var acceptData = function( owner ) {
+
+ // Accepts only:
+ // - Node
+ // - Node.ELEMENT_NODE
+ // - Node.DOCUMENT_NODE
+ // - Object
+ // - Any
+ return owner.nodeType === 1 || owner.nodeType === 9 || !( +owner.nodeType );
+};
+
+
+
+
+function Data() {
+ this.expando = jQuery.expando + Data.uid++;
+}
+
+Data.uid = 1;
+
+Data.prototype = {
+
+ cache: function( owner ) {
+
+ // Check if the owner object already has a cache
+ var value = owner[ this.expando ];
+
+ // If not, create one
+ if ( !value ) {
+ value = {};
+
+ // We can accept data for non-element nodes in modern browsers,
+ // but we should not, see #8335.
+ // Always return an empty object.
+ if ( acceptData( owner ) ) {
+
+ // If it is a node unlikely to be stringify-ed or looped over
+ // use plain assignment
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = value;
+
+ // Otherwise secure it in a non-enumerable property
+ // configurable must be true to allow the property to be
+ // deleted when data is removed
+ } else {
+ Object.defineProperty( owner, this.expando, {
+ value: value,
+ configurable: true
+ } );
+ }
+ }
+ }
+
+ return value;
+ },
+ set: function( owner, data, value ) {
+ var prop,
+ cache = this.cache( owner );
+
+ // Handle: [ owner, key, value ] args
+ // Always use camelCase key (gh-2257)
+ if ( typeof data === "string" ) {
+ cache[ jQuery.camelCase( data ) ] = value;
+
+ // Handle: [ owner, { properties } ] args
+ } else {
+
+ // Copy the properties one-by-one to the cache object
+ for ( prop in data ) {
+ cache[ jQuery.camelCase( prop ) ] = data[ prop ];
+ }
+ }
+ return cache;
+ },
+ get: function( owner, key ) {
+ return key === undefined ?
+ this.cache( owner ) :
+
+ // Always use camelCase key (gh-2257)
+ owner[ this.expando ] && owner[ this.expando ][ jQuery.camelCase( key ) ];
+ },
+ access: function( owner, key, value ) {
+
+ // In cases where either:
+ //
+ // 1. No key was specified
+ // 2. A string key was specified, but no value provided
+ //
+ // Take the "read" path and allow the get method to determine
+ // which value to return, respectively either:
+ //
+ // 1. The entire cache object
+ // 2. The data stored at the key
+ //
+ if ( key === undefined ||
+ ( ( key && typeof key === "string" ) && value === undefined ) ) {
+
+ return this.get( owner, key );
+ }
+
+ // When the key is not a string, or both a key and value
+ // are specified, set or extend (existing objects) with either:
+ //
+ // 1. An object of properties
+ // 2. A key and value
+ //
+ this.set( owner, key, value );
+
+ // Since the "set" path can have two possible entry points
+ // return the expected data based on which path was taken[*]
+ return value !== undefined ? value : key;
+ },
+ remove: function( owner, key ) {
+ var i,
+ cache = owner[ this.expando ];
+
+ if ( cache === undefined ) {
+ return;
+ }
+
+ if ( key !== undefined ) {
+
+ // Support array or space separated string of keys
+ if ( Array.isArray( key ) ) {
+
+ // If key is an array of keys...
+ // We always set camelCase keys, so remove that.
+ key = key.map( jQuery.camelCase );
+ } else {
+ key = jQuery.camelCase( key );
+
+ // If a key with the spaces exists, use it.
+ // Otherwise, create an array by matching non-whitespace
+ key = key in cache ?
+ [ key ] :
+ ( key.match( rnothtmlwhite ) || [] );
+ }
+
+ i = key.length;
+
+ while ( i-- ) {
+ delete cache[ key[ i ] ];
+ }
+ }
+
+ // Remove the expando if there's no more data
+ if ( key === undefined || jQuery.isEmptyObject( cache ) ) {
+
+ // Support: Chrome <=35 - 45
+ // Webkit & Blink performance suffers when deleting properties
+ // from DOM nodes, so set to undefined instead
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=378607 (bug restricted)
+ if ( owner.nodeType ) {
+ owner[ this.expando ] = undefined;
+ } else {
+ delete owner[ this.expando ];
+ }
+ }
+ },
+ hasData: function( owner ) {
+ var cache = owner[ this.expando ];
+ return cache !== undefined && !jQuery.isEmptyObject( cache );
+ }
+};
+var dataPriv = new Data();
+
+var dataUser = new Data();
+
+
+
+// Implementation Summary
+//
+// 1. Enforce API surface and semantic compatibility with 1.9.x branch
+// 2. Improve the module's maintainability by reducing the storage
+// paths to a single mechanism.
+// 3. Use the same single mechanism to support "private" and "user" data.
+// 4. _Never_ expose "private" data to user code (TODO: Drop _data, _removeData)
+// 5. Avoid exposing implementation details on user objects (eg. expando properties)
+// 6. Provide a clear path for implementation upgrade to WeakMap in 2014
+
+var rbrace = /^(?:\{[\w\W]*\}|\[[\w\W]*\])$/,
+ rmultiDash = /[A-Z]/g;
+
+function getData( data ) {
+ if ( data === "true" ) {
+ return true;
+ }
+
+ if ( data === "false" ) {
+ return false;
+ }
+
+ if ( data === "null" ) {
+ return null;
+ }
+
+ // Only convert to a number if it doesn't change the string
+ if ( data === +data + "" ) {
+ return +data;
+ }
+
+ if ( rbrace.test( data ) ) {
+ return JSON.parse( data );
+ }
+
+ return data;
+}
+
+function dataAttr( elem, key, data ) {
+ var name;
+
+ // If nothing was found internally, try to fetch any
+ // data from the HTML5 data-* attribute
+ if ( data === undefined && elem.nodeType === 1 ) {
+ name = "data-" + key.replace( rmultiDash, "-$&" ).toLowerCase();
+ data = elem.getAttribute( name );
+
+ if ( typeof data === "string" ) {
+ try {
+ data = getData( data );
+ } catch ( e ) {}
+
+ // Make sure we set the data so it isn't changed later
+ dataUser.set( elem, key, data );
+ } else {
+ data = undefined;
+ }
+ }
+ return data;
+}
+
+jQuery.extend( {
+ hasData: function( elem ) {
+ return dataUser.hasData( elem ) || dataPriv.hasData( elem );
+ },
+
+ data: function( elem, name, data ) {
+ return dataUser.access( elem, name, data );
+ },
+
+ removeData: function( elem, name ) {
+ dataUser.remove( elem, name );
+ },
+
+ // TODO: Now that all calls to _data and _removeData have been replaced
+ // with direct calls to dataPriv methods, these can be deprecated.
+ _data: function( elem, name, data ) {
+ return dataPriv.access( elem, name, data );
+ },
+
+ _removeData: function( elem, name ) {
+ dataPriv.remove( elem, name );
+ }
+} );
+
+jQuery.fn.extend( {
+ data: function( key, value ) {
+ var i, name, data,
+ elem = this[ 0 ],
+ attrs = elem && elem.attributes;
+
+ // Gets all values
+ if ( key === undefined ) {
+ if ( this.length ) {
+ data = dataUser.get( elem );
+
+ if ( elem.nodeType === 1 && !dataPriv.get( elem, "hasDataAttrs" ) ) {
+ i = attrs.length;
+ while ( i-- ) {
+
+ // Support: IE 11 only
+ // The attrs elements can be null (#14894)
+ if ( attrs[ i ] ) {
+ name = attrs[ i ].name;
+ if ( name.indexOf( "data-" ) === 0 ) {
+ name = jQuery.camelCase( name.slice( 5 ) );
+ dataAttr( elem, name, data[ name ] );
+ }
+ }
+ }
+ dataPriv.set( elem, "hasDataAttrs", true );
+ }
+ }
+
+ return data;
+ }
+
+ // Sets multiple values
+ if ( typeof key === "object" ) {
+ return this.each( function() {
+ dataUser.set( this, key );
+ } );
+ }
+
+ return access( this, function( value ) {
+ var data;
+
+ // The calling jQuery object (element matches) is not empty
+ // (and therefore has an element appears at this[ 0 ]) and the
+ // `value` parameter was not undefined. An empty jQuery object
+ // will result in `undefined` for elem = this[ 0 ] which will
+ // throw an exception if an attempt to read a data cache is made.
+ if ( elem && value === undefined ) {
+
+ // Attempt to get data from the cache
+ // The key will always be camelCased in Data
+ data = dataUser.get( elem, key );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // Attempt to "discover" the data in
+ // HTML5 custom data-* attrs
+ data = dataAttr( elem, key );
+ if ( data !== undefined ) {
+ return data;
+ }
+
+ // We tried really hard, but the data doesn't exist.
+ return;
+ }
+
+ // Set the data...
+ this.each( function() {
+
+ // We always store the camelCased key
+ dataUser.set( this, key, value );
+ } );
+ }, null, value, arguments.length > 1, null, true );
+ },
+
+ removeData: function( key ) {
+ return this.each( function() {
+ dataUser.remove( this, key );
+ } );
+ }
+} );
+
+
+jQuery.extend( {
+ queue: function( elem, type, data ) {
+ var queue;
+
+ if ( elem ) {
+ type = ( type || "fx" ) + "queue";
+ queue = dataPriv.get( elem, type );
+
+ // Speed up dequeue by getting out quickly if this is just a lookup
+ if ( data ) {
+ if ( !queue || Array.isArray( data ) ) {
+ queue = dataPriv.access( elem, type, jQuery.makeArray( data ) );
+ } else {
+ queue.push( data );
+ }
+ }
+ return queue || [];
+ }
+ },
+
+ dequeue: function( elem, type ) {
+ type = type || "fx";
+
+ var queue = jQuery.queue( elem, type ),
+ startLength = queue.length,
+ fn = queue.shift(),
+ hooks = jQuery._queueHooks( elem, type ),
+ next = function() {
+ jQuery.dequeue( elem, type );
+ };
+
+ // If the fx queue is dequeued, always remove the progress sentinel
+ if ( fn === "inprogress" ) {
+ fn = queue.shift();
+ startLength--;
+ }
+
+ if ( fn ) {
+
+ // Add a progress sentinel to prevent the fx queue from being
+ // automatically dequeued
+ if ( type === "fx" ) {
+ queue.unshift( "inprogress" );
+ }
+
+ // Clear up the last queue stop function
+ delete hooks.stop;
+ fn.call( elem, next, hooks );
+ }
+
+ if ( !startLength && hooks ) {
+ hooks.empty.fire();
+ }
+ },
+
+ // Not public - generate a queueHooks object, or return the current one
+ _queueHooks: function( elem, type ) {
+ var key = type + "queueHooks";
+ return dataPriv.get( elem, key ) || dataPriv.access( elem, key, {
+ empty: jQuery.Callbacks( "once memory" ).add( function() {
+ dataPriv.remove( elem, [ type + "queue", key ] );
+ } )
+ } );
+ }
+} );
+
+jQuery.fn.extend( {
+ queue: function( type, data ) {
+ var setter = 2;
+
+ if ( typeof type !== "string" ) {
+ data = type;
+ type = "fx";
+ setter--;
+ }
+
+ if ( arguments.length < setter ) {
+ return jQuery.queue( this[ 0 ], type );
+ }
+
+ return data === undefined ?
+ this :
+ this.each( function() {
+ var queue = jQuery.queue( this, type, data );
+
+ // Ensure a hooks for this queue
+ jQuery._queueHooks( this, type );
+
+ if ( type === "fx" && queue[ 0 ] !== "inprogress" ) {
+ jQuery.dequeue( this, type );
+ }
+ } );
+ },
+ dequeue: function( type ) {
+ return this.each( function() {
+ jQuery.dequeue( this, type );
+ } );
+ },
+ clearQueue: function( type ) {
+ return this.queue( type || "fx", [] );
+ },
+
+ // Get a promise resolved when queues of a certain type
+ // are emptied (fx is the type by default)
+ promise: function( type, obj ) {
+ var tmp,
+ count = 1,
+ defer = jQuery.Deferred(),
+ elements = this,
+ i = this.length,
+ resolve = function() {
+ if ( !( --count ) ) {
+ defer.resolveWith( elements, [ elements ] );
+ }
+ };
+
+ if ( typeof type !== "string" ) {
+ obj = type;
+ type = undefined;
+ }
+ type = type || "fx";
+
+ while ( i-- ) {
+ tmp = dataPriv.get( elements[ i ], type + "queueHooks" );
+ if ( tmp && tmp.empty ) {
+ count++;
+ tmp.empty.add( resolve );
+ }
+ }
+ resolve();
+ return defer.promise( obj );
+ }
+} );
+var pnum = ( /[+-]?(?:\d*\.|)\d+(?:[eE][+-]?\d+|)/ ).source;
+
+var rcssNum = new RegExp( "^(?:([+-])=|)(" + pnum + ")([a-z%]*)$", "i" );
+
+
+var cssExpand = [ "Top", "Right", "Bottom", "Left" ];
+
+var isHiddenWithinTree = function( elem, el ) {
+
+ // isHiddenWithinTree might be called from jQuery#filter function;
+ // in that case, element will be second argument
+ elem = el || elem;
+
+ // Inline style trumps all
+ return elem.style.display === "none" ||
+ elem.style.display === "" &&
+
+ // Otherwise, check computed style
+ // Support: Firefox <=43 - 45
+ // Disconnected elements can have computed display: none, so first confirm that elem is
+ // in the document.
+ jQuery.contains( elem.ownerDocument, elem ) &&
+
+ jQuery.css( elem, "display" ) === "none";
+ };
+
+var swap = function( elem, options, callback, args ) {
+ var ret, name,
+ old = {};
+
+ // Remember the old values, and insert the new ones
+ for ( name in options ) {
+ old[ name ] = elem.style[ name ];
+ elem.style[ name ] = options[ name ];
+ }
+
+ ret = callback.apply( elem, args || [] );
+
+ // Revert the old values
+ for ( name in options ) {
+ elem.style[ name ] = old[ name ];
+ }
+
+ return ret;
+};
+
+
+
+
+function adjustCSS( elem, prop, valueParts, tween ) {
+ var adjusted,
+ scale = 1,
+ maxIterations = 20,
+ currentValue = tween ?
+ function() {
+ return tween.cur();
+ } :
+ function() {
+ return jQuery.css( elem, prop, "" );
+ },
+ initial = currentValue(),
+ unit = valueParts && valueParts[ 3 ] || ( jQuery.cssNumber[ prop ] ? "" : "px" ),
+
+ // Starting value computation is required for potential unit mismatches
+ initialInUnit = ( jQuery.cssNumber[ prop ] || unit !== "px" && +initial ) &&
+ rcssNum.exec( jQuery.css( elem, prop ) );
+
+ if ( initialInUnit && initialInUnit[ 3 ] !== unit ) {
+
+ // Trust units reported by jQuery.css
+ unit = unit || initialInUnit[ 3 ];
+
+ // Make sure we update the tween properties later on
+ valueParts = valueParts || [];
+
+ // Iteratively approximate from a nonzero starting point
+ initialInUnit = +initial || 1;
+
+ do {
+
+ // If previous iteration zeroed out, double until we get *something*.
+ // Use string for doubling so we don't accidentally see scale as unchanged below
+ scale = scale || ".5";
+
+ // Adjust and apply
+ initialInUnit = initialInUnit / scale;
+ jQuery.style( elem, prop, initialInUnit + unit );
+
+ // Update scale, tolerating zero or NaN from tween.cur()
+ // Break the loop if scale is unchanged or perfect, or if we've just had enough.
+ } while (
+ scale !== ( scale = currentValue() / initial ) && scale !== 1 && --maxIterations
+ );
+ }
+
+ if ( valueParts ) {
+ initialInUnit = +initialInUnit || +initial || 0;
+
+ // Apply relative offset (+=/-=) if specified
+ adjusted = valueParts[ 1 ] ?
+ initialInUnit + ( valueParts[ 1 ] + 1 ) * valueParts[ 2 ] :
+ +valueParts[ 2 ];
+ if ( tween ) {
+ tween.unit = unit;
+ tween.start = initialInUnit;
+ tween.end = adjusted;
+ }
+ }
+ return adjusted;
+}
+
+
+var defaultDisplayMap = {};
+
+function getDefaultDisplay( elem ) {
+ var temp,
+ doc = elem.ownerDocument,
+ nodeName = elem.nodeName,
+ display = defaultDisplayMap[ nodeName ];
+
+ if ( display ) {
+ return display;
+ }
+
+ temp = doc.body.appendChild( doc.createElement( nodeName ) );
+ display = jQuery.css( temp, "display" );
+
+ temp.parentNode.removeChild( temp );
+
+ if ( display === "none" ) {
+ display = "block";
+ }
+ defaultDisplayMap[ nodeName ] = display;
+
+ return display;
+}
+
+function showHide( elements, show ) {
+ var display, elem,
+ values = [],
+ index = 0,
+ length = elements.length;
+
+ // Determine new display value for elements that need to change
+ for ( ; index < length; index++ ) {
+ elem = elements[ index ];
+ if ( !elem.style ) {
+ continue;
+ }
+
+ display = elem.style.display;
+ if ( show ) {
+
+ // Since we force visibility upon cascade-hidden elements, an immediate (and slow)
+ // check is required in this first loop unless we have a nonempty display value (either
+ // inline or about-to-be-restored)
+ if ( display === "none" ) {
+ values[ index ] = dataPriv.get( elem, "display" ) || null;
+ if ( !values[ index ] ) {
+ elem.style.display = "";
+ }
+ }
+ if ( elem.style.display === "" && isHiddenWithinTree( elem ) ) {
+ values[ index ] = getDefaultDisplay( elem );
+ }
+ } else {
+ if ( display !== "none" ) {
+ values[ index ] = "none";
+
+ // Remember what we're overwriting
+ dataPriv.set( elem, "display", display );
+ }
+ }
+ }
+
+ // Set the display of the elements in a second loop to avoid constant reflow
+ for ( index = 0; index < length; index++ ) {
+ if ( values[ index ] != null ) {
+ elements[ index ].style.display = values[ index ];
+ }
+ }
+
+ return elements;
+}
+
+jQuery.fn.extend( {
+ show: function() {
+ return showHide( this, true );
+ },
+ hide: function() {
+ return showHide( this );
+ },
+ toggle: function( state ) {
+ if ( typeof state === "boolean" ) {
+ return state ? this.show() : this.hide();
+ }
+
+ return this.each( function() {
+ if ( isHiddenWithinTree( this ) ) {
+ jQuery( this ).show();
+ } else {
+ jQuery( this ).hide();
+ }
+ } );
+ }
+} );
+var rcheckableType = ( /^(?:checkbox|radio)$/i );
+
+var rtagName = ( /<([a-z][^\/\0>\x20\t\r\n\f]+)/i );
+
+var rscriptType = ( /^$|\/(?:java|ecma)script/i );
+
+
+
+// We have to close these tags to support XHTML (#13200)
+var wrapMap = {
+
+ // Support: IE <=9 only
+ option: [ 1, "<select multiple='multiple'>", "</select>" ],
+
+ // XHTML parsers do not magically insert elements in the
+ // same way that tag soup parsers do. So we cannot shorten
+ // this by omitting <tbody> or other required elements.
+ thead: [ 1, "<table>", "</table>" ],
+ col: [ 2, "<table><colgroup>", "</colgroup></table>" ],
+ tr: [ 2, "<table><tbody>", "</tbody></table>" ],
+ td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
+
+ _default: [ 0, "", "" ]
+};
+
+// Support: IE <=9 only
+wrapMap.optgroup = wrapMap.option;
+
+wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
+wrapMap.th = wrapMap.td;
+
+
+function getAll( context, tag ) {
+
+ // Support: IE <=9 - 11 only
+ // Use typeof to avoid zero-argument method invocation on host objects (#15151)
+ var ret;
+
+ if ( typeof context.getElementsByTagName !== "undefined" ) {
+ ret = context.getElementsByTagName( tag || "*" );
+
+ } else if ( typeof context.querySelectorAll !== "undefined" ) {
+ ret = context.querySelectorAll( tag || "*" );
+
+ } else {
+ ret = [];
+ }
+
+ if ( tag === undefined || tag && nodeName( context, tag ) ) {
+ return jQuery.merge( [ context ], ret );
+ }
+
+ return ret;
+}
+
+
+// Mark scripts as having already been evaluated
+function setGlobalEval( elems, refElements ) {
+ var i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ dataPriv.set(
+ elems[ i ],
+ "globalEval",
+ !refElements || dataPriv.get( refElements[ i ], "globalEval" )
+ );
+ }
+}
+
+
+var rhtml = /<|&#?\w+;/;
+
+function buildFragment( elems, context, scripts, selection, ignored ) {
+ var elem, tmp, tag, wrap, contains, j,
+ fragment = context.createDocumentFragment(),
+ nodes = [],
+ i = 0,
+ l = elems.length;
+
+ for ( ; i < l; i++ ) {
+ elem = elems[ i ];
+
+ if ( elem || elem === 0 ) {
+
+ // Add nodes directly
+ if ( jQuery.type( elem ) === "object" ) {
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( nodes, elem.nodeType ? [ elem ] : elem );
+
+ // Convert non-html into a text node
+ } else if ( !rhtml.test( elem ) ) {
+ nodes.push( context.createTextNode( elem ) );
+
+ // Convert html into DOM nodes
+ } else {
+ tmp = tmp || fragment.appendChild( context.createElement( "div" ) );
+
+ // Deserialize a standard representation
+ tag = ( rtagName.exec( elem ) || [ "", "" ] )[ 1 ].toLowerCase();
+ wrap = wrapMap[ tag ] || wrapMap._default;
+ tmp.innerHTML = wrap[ 1 ] + jQuery.htmlPrefilter( elem ) + wrap[ 2 ];
+
+ // Descend through wrappers to the right content
+ j = wrap[ 0 ];
+ while ( j-- ) {
+ tmp = tmp.lastChild;
+ }
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( nodes, tmp.childNodes );
+
+ // Remember the top-level container
+ tmp = fragment.firstChild;
+
+ // Ensure the created nodes are orphaned (#12392)
+ tmp.textContent = "";
+ }
+ }
+ }
+
+ // Remove wrapper from fragment
+ fragment.textContent = "";
+
+ i = 0;
+ while ( ( elem = nodes[ i++ ] ) ) {
+
+ // Skip elements already in the context collection (trac-4087)
+ if ( selection && jQuery.inArray( elem, selection ) > -1 ) {
+ if ( ignored ) {
+ ignored.push( elem );
+ }
+ continue;
+ }
+
+ contains = jQuery.contains( elem.ownerDocument, elem );
+
+ // Append to fragment
+ tmp = getAll( fragment.appendChild( elem ), "script" );
+
+ // Preserve script evaluation history
+ if ( contains ) {
+ setGlobalEval( tmp );
+ }
+
+ // Capture executables
+ if ( scripts ) {
+ j = 0;
+ while ( ( elem = tmp[ j++ ] ) ) {
+ if ( rscriptType.test( elem.type || "" ) ) {
+ scripts.push( elem );
+ }
+ }
+ }
+ }
+
+ return fragment;
+}
+
+
+( function() {
+ var fragment = document.createDocumentFragment(),
+ div = fragment.appendChild( document.createElement( "div" ) ),
+ input = document.createElement( "input" );
+
+ // Support: Android 4.0 - 4.3 only
+ // Check state lost if the name is set (#11217)
+ // Support: Windows Web Apps (WWA)
+ // `name` and `type` must use .setAttribute for WWA (#14901)
+ input.setAttribute( "type", "radio" );
+ input.setAttribute( "checked", "checked" );
+ input.setAttribute( "name", "t" );
+
+ div.appendChild( input );
+
+ // Support: Android <=4.1 only
+ // Older WebKit doesn't clone checked state correctly in fragments
+ support.checkClone = div.cloneNode( true ).cloneNode( true ).lastChild.checked;
+
+ // Support: IE <=11 only
+ // Make sure textarea (and checkbox) defaultValue is properly cloned
+ div.innerHTML = "<textarea>x</textarea>";
+ support.noCloneChecked = !!div.cloneNode( true ).lastChild.defaultValue;
+} )();
+var documentElement = document.documentElement;
+
+
+
+var
+ rkeyEvent = /^key/,
+ rmouseEvent = /^(?:mouse|pointer|contextmenu|drag|drop)|click/,
+ rtypenamespace = /^([^.]*)(?:\.(.+)|)/;
+
+function returnTrue() {
+ return true;
+}
+
+function returnFalse() {
+ return false;
+}
+
+// Support: IE <=9 only
+// See #13393 for more info
+function safeActiveElement() {
+ try {
+ return document.activeElement;
+ } catch ( err ) { }
+}
+
+function on( elem, types, selector, data, fn, one ) {
+ var origFn, type;
+
+ // Types can be a map of types/handlers
+ if ( typeof types === "object" ) {
+
+ // ( types-Object, selector, data )
+ if ( typeof selector !== "string" ) {
+
+ // ( types-Object, data )
+ data = data || selector;
+ selector = undefined;
+ }
+ for ( type in types ) {
+ on( elem, type, selector, data, types[ type ], one );
+ }
+ return elem;
+ }
+
+ if ( data == null && fn == null ) {
+
+ // ( types, fn )
+ fn = selector;
+ data = selector = undefined;
+ } else if ( fn == null ) {
+ if ( typeof selector === "string" ) {
+
+ // ( types, selector, fn )
+ fn = data;
+ data = undefined;
+ } else {
+
+ // ( types, data, fn )
+ fn = data;
+ data = selector;
+ selector = undefined;
+ }
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ } else if ( !fn ) {
+ return elem;
+ }
+
+ if ( one === 1 ) {
+ origFn = fn;
+ fn = function( event ) {
+
+ // Can use an empty set, since event contains the info
+ jQuery().off( event );
+ return origFn.apply( this, arguments );
+ };
+
+ // Use same guid so caller can remove using origFn
+ fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
+ }
+ return elem.each( function() {
+ jQuery.event.add( this, types, fn, data, selector );
+ } );
+}
+
+/*
+ * Helper functions for managing events -- not part of the public interface.
+ * Props to Dean Edwards' addEvent library for many of the ideas.
+ */
+jQuery.event = {
+
+ global: {},
+
+ add: function( elem, types, handler, data, selector ) {
+
+ var handleObjIn, eventHandle, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = dataPriv.get( elem );
+
+ // Don't attach events to noData or text/comment nodes (but allow plain objects)
+ if ( !elemData ) {
+ return;
+ }
+
+ // Caller can pass in an object of custom data in lieu of the handler
+ if ( handler.handler ) {
+ handleObjIn = handler;
+ handler = handleObjIn.handler;
+ selector = handleObjIn.selector;
+ }
+
+ // Ensure that invalid selectors throw exceptions at attach time
+ // Evaluate against documentElement in case elem is a non-element node (e.g., document)
+ if ( selector ) {
+ jQuery.find.matchesSelector( documentElement, selector );
+ }
+
+ // Make sure that the handler has a unique ID, used to find/remove it later
+ if ( !handler.guid ) {
+ handler.guid = jQuery.guid++;
+ }
+
+ // Init the element's event structure and main handler, if this is the first
+ if ( !( events = elemData.events ) ) {
+ events = elemData.events = {};
+ }
+ if ( !( eventHandle = elemData.handle ) ) {
+ eventHandle = elemData.handle = function( e ) {
+
+ // Discard the second event of a jQuery.event.trigger() and
+ // when an event is called after a page has unloaded
+ return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ?
+ jQuery.event.dispatch.apply( elem, arguments ) : undefined;
+ };
+ }
+
+ // Handle multiple events separated by a space
+ types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[ t ] ) || [];
+ type = origType = tmp[ 1 ];
+ namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
+
+ // There *must* be a type, no attaching namespace-only handlers
+ if ( !type ) {
+ continue;
+ }
+
+ // If event changes its type, use the special event handlers for the changed type
+ special = jQuery.event.special[ type ] || {};
+
+ // If selector defined, determine special event api type, otherwise given type
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+
+ // Update special based on newly reset type
+ special = jQuery.event.special[ type ] || {};
+
+ // handleObj is passed to all event handlers
+ handleObj = jQuery.extend( {
+ type: type,
+ origType: origType,
+ data: data,
+ handler: handler,
+ guid: handler.guid,
+ selector: selector,
+ needsContext: selector && jQuery.expr.match.needsContext.test( selector ),
+ namespace: namespaces.join( "." )
+ }, handleObjIn );
+
+ // Init the event handler queue if we're the first
+ if ( !( handlers = events[ type ] ) ) {
+ handlers = events[ type ] = [];
+ handlers.delegateCount = 0;
+
+ // Only use addEventListener if the special events handler returns false
+ if ( !special.setup ||
+ special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
+
+ if ( elem.addEventListener ) {
+ elem.addEventListener( type, eventHandle );
+ }
+ }
+ }
+
+ if ( special.add ) {
+ special.add.call( elem, handleObj );
+
+ if ( !handleObj.handler.guid ) {
+ handleObj.handler.guid = handler.guid;
+ }
+ }
+
+ // Add to the element's handler list, delegates in front
+ if ( selector ) {
+ handlers.splice( handlers.delegateCount++, 0, handleObj );
+ } else {
+ handlers.push( handleObj );
+ }
+
+ // Keep track of which events have ever been used, for event optimization
+ jQuery.event.global[ type ] = true;
+ }
+
+ },
+
+ // Detach an event or set of events from an element
+ remove: function( elem, types, handler, selector, mappedTypes ) {
+
+ var j, origCount, tmp,
+ events, t, handleObj,
+ special, handlers, type, namespaces, origType,
+ elemData = dataPriv.hasData( elem ) && dataPriv.get( elem );
+
+ if ( !elemData || !( events = elemData.events ) ) {
+ return;
+ }
+
+ // Once for each type.namespace in types; type may be omitted
+ types = ( types || "" ).match( rnothtmlwhite ) || [ "" ];
+ t = types.length;
+ while ( t-- ) {
+ tmp = rtypenamespace.exec( types[ t ] ) || [];
+ type = origType = tmp[ 1 ];
+ namespaces = ( tmp[ 2 ] || "" ).split( "." ).sort();
+
+ // Unbind all events (on this namespace, if provided) for the element
+ if ( !type ) {
+ for ( type in events ) {
+ jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
+ }
+ continue;
+ }
+
+ special = jQuery.event.special[ type ] || {};
+ type = ( selector ? special.delegateType : special.bindType ) || type;
+ handlers = events[ type ] || [];
+ tmp = tmp[ 2 ] &&
+ new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" );
+
+ // Remove matching events
+ origCount = j = handlers.length;
+ while ( j-- ) {
+ handleObj = handlers[ j ];
+
+ if ( ( mappedTypes || origType === handleObj.origType ) &&
+ ( !handler || handler.guid === handleObj.guid ) &&
+ ( !tmp || tmp.test( handleObj.namespace ) ) &&
+ ( !selector || selector === handleObj.selector ||
+ selector === "**" && handleObj.selector ) ) {
+ handlers.splice( j, 1 );
+
+ if ( handleObj.selector ) {
+ handlers.delegateCount--;
+ }
+ if ( special.remove ) {
+ special.remove.call( elem, handleObj );
+ }
+ }
+ }
+
+ // Remove generic event handler if we removed something and no more handlers exist
+ // (avoids potential for endless recursion during removal of special event handlers)
+ if ( origCount && !handlers.length ) {
+ if ( !special.teardown ||
+ special.teardown.call( elem, namespaces, elemData.handle ) === false ) {
+
+ jQuery.removeEvent( elem, type, elemData.handle );
+ }
+
+ delete events[ type ];
+ }
+ }
+
+ // Remove data and the expando if it's no longer used
+ if ( jQuery.isEmptyObject( events ) ) {
+ dataPriv.remove( elem, "handle events" );
+ }
+ },
+
+ dispatch: function( nativeEvent ) {
+
+ // Make a writable jQuery.Event from the native event object
+ var event = jQuery.event.fix( nativeEvent );
+
+ var i, j, ret, matched, handleObj, handlerQueue,
+ args = new Array( arguments.length ),
+ handlers = ( dataPriv.get( this, "events" ) || {} )[ event.type ] || [],
+ special = jQuery.event.special[ event.type ] || {};
+
+ // Use the fix-ed jQuery.Event rather than the (read-only) native event
+ args[ 0 ] = event;
+
+ for ( i = 1; i < arguments.length; i++ ) {
+ args[ i ] = arguments[ i ];
+ }
+
+ event.delegateTarget = this;
+
+ // Call the preDispatch hook for the mapped type, and let it bail if desired
+ if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) {
+ return;
+ }
+
+ // Determine handlers
+ handlerQueue = jQuery.event.handlers.call( this, event, handlers );
+
+ // Run delegates first; they may want to stop propagation beneath us
+ i = 0;
+ while ( ( matched = handlerQueue[ i++ ] ) && !event.isPropagationStopped() ) {
+ event.currentTarget = matched.elem;
+
+ j = 0;
+ while ( ( handleObj = matched.handlers[ j++ ] ) &&
+ !event.isImmediatePropagationStopped() ) {
+
+ // Triggered event must either 1) have no namespace, or 2) have namespace(s)
+ // a subset or equal to those in the bound event (both can have no namespace).
+ if ( !event.rnamespace || event.rnamespace.test( handleObj.namespace ) ) {
+
+ event.handleObj = handleObj;
+ event.data = handleObj.data;
+
+ ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||
+ handleObj.handler ).apply( matched.elem, args );
+
+ if ( ret !== undefined ) {
+ if ( ( event.result = ret ) === false ) {
+ event.preventDefault();
+ event.stopPropagation();
+ }
+ }
+ }
+ }
+ }
+
+ // Call the postDispatch hook for the mapped type
+ if ( special.postDispatch ) {
+ special.postDispatch.call( this, event );
+ }
+
+ return event.result;
+ },
+
+ handlers: function( event, handlers ) {
+ var i, handleObj, sel, matchedHandlers, matchedSelectors,
+ handlerQueue = [],
+ delegateCount = handlers.delegateCount,
+ cur = event.target;
+
+ // Find delegate handlers
+ if ( delegateCount &&
+
+ // Support: IE <=9
+ // Black-hole SVG <use> instance trees (trac-13180)
+ cur.nodeType &&
+
+ // Support: Firefox <=42
+ // Suppress spec-violating clicks indicating a non-primary pointer button (trac-3861)
+ // https://www.w3.org/TR/DOM-Level-3-Events/#event-type-click
+ // Support: IE 11 only
+ // ...but not arrow key "clicks" of radio inputs, which can have `button` -1 (gh-2343)
+ !( event.type === "click" && event.button >= 1 ) ) {
+
+ for ( ; cur !== this; cur = cur.parentNode || this ) {
+
+ // Don't check non-elements (#13208)
+ // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764)
+ if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) {
+ matchedHandlers = [];
+ matchedSelectors = {};
+ for ( i = 0; i < delegateCount; i++ ) {
+ handleObj = handlers[ i ];
+
+ // Don't conflict with Object.prototype properties (#13203)
+ sel = handleObj.selector + " ";
+
+ if ( matchedSelectors[ sel ] === undefined ) {
+ matchedSelectors[ sel ] = handleObj.needsContext ?
+ jQuery( sel, this ).index( cur ) > -1 :
+ jQuery.find( sel, this, null, [ cur ] ).length;
+ }
+ if ( matchedSelectors[ sel ] ) {
+ matchedHandlers.push( handleObj );
+ }
+ }
+ if ( matchedHandlers.length ) {
+ handlerQueue.push( { elem: cur, handlers: matchedHandlers } );
+ }
+ }
+ }
+ }
+
+ // Add the remaining (directly-bound) handlers
+ cur = this;
+ if ( delegateCount < handlers.length ) {
+ handlerQueue.push( { elem: cur, handlers: handlers.slice( delegateCount ) } );
+ }
+
+ return handlerQueue;
+ },
+
+ addProp: function( name, hook ) {
+ Object.defineProperty( jQuery.Event.prototype, name, {
+ enumerable: true,
+ configurable: true,
+
+ get: jQuery.isFunction( hook ) ?
+ function() {
+ if ( this.originalEvent ) {
+ return hook( this.originalEvent );
+ }
+ } :
+ function() {
+ if ( this.originalEvent ) {
+ return this.originalEvent[ name ];
+ }
+ },
+
+ set: function( value ) {
+ Object.defineProperty( this, name, {
+ enumerable: true,
+ configurable: true,
+ writable: true,
+ value: value
+ } );
+ }
+ } );
+ },
+
+ fix: function( originalEvent ) {
+ return originalEvent[ jQuery.expando ] ?
+ originalEvent :
+ new jQuery.Event( originalEvent );
+ },
+
+ special: {
+ load: {
+
+ // Prevent triggered image.load events from bubbling to window.load
+ noBubble: true
+ },
+ focus: {
+
+ // Fire native event if possible so blur/focus sequence is correct
+ trigger: function() {
+ if ( this !== safeActiveElement() && this.focus ) {
+ this.focus();
+ return false;
+ }
+ },
+ delegateType: "focusin"
+ },
+ blur: {
+ trigger: function() {
+ if ( this === safeActiveElement() && this.blur ) {
+ this.blur();
+ return false;
+ }
+ },
+ delegateType: "focusout"
+ },
+ click: {
+
+ // For checkbox, fire native event so checked state will be right
+ trigger: function() {
+ if ( this.type === "checkbox" && this.click && nodeName( this, "input" ) ) {
+ this.click();
+ return false;
+ }
+ },
+
+ // For cross-browser consistency, don't fire native .click() on links
+ _default: function( event ) {
+ return nodeName( event.target, "a" );
+ }
+ },
+
+ beforeunload: {
+ postDispatch: function( event ) {
+
+ // Support: Firefox 20+
+ // Firefox doesn't alert if the returnValue field is not set.
+ if ( event.result !== undefined && event.originalEvent ) {
+ event.originalEvent.returnValue = event.result;
+ }
+ }
+ }
+ }
+};
+
+jQuery.removeEvent = function( elem, type, handle ) {
+
+ // This "if" is needed for plain objects
+ if ( elem.removeEventListener ) {
+ elem.removeEventListener( type, handle );
+ }
+};
+
+jQuery.Event = function( src, props ) {
+
+ // Allow instantiation without the 'new' keyword
+ if ( !( this instanceof jQuery.Event ) ) {
+ return new jQuery.Event( src, props );
+ }
+
+ // Event object
+ if ( src && src.type ) {
+ this.originalEvent = src;
+ this.type = src.type;
+
+ // Events bubbling up the document may have been marked as prevented
+ // by a handler lower down the tree; reflect the correct value.
+ this.isDefaultPrevented = src.defaultPrevented ||
+ src.defaultPrevented === undefined &&
+
+ // Support: Android <=2.3 only
+ src.returnValue === false ?
+ returnTrue :
+ returnFalse;
+
+ // Create target properties
+ // Support: Safari <=6 - 7 only
+ // Target should not be a text node (#504, #13143)
+ this.target = ( src.target && src.target.nodeType === 3 ) ?
+ src.target.parentNode :
+ src.target;
+
+ this.currentTarget = src.currentTarget;
+ this.relatedTarget = src.relatedTarget;
+
+ // Event type
+ } else {
+ this.type = src;
+ }
+
+ // Put explicitly provided properties onto the event object
+ if ( props ) {
+ jQuery.extend( this, props );
+ }
+
+ // Create a timestamp if incoming event doesn't have one
+ this.timeStamp = src && src.timeStamp || jQuery.now();
+
+ // Mark it as fixed
+ this[ jQuery.expando ] = true;
+};
+
+// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
+// https://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
+jQuery.Event.prototype = {
+ constructor: jQuery.Event,
+ isDefaultPrevented: returnFalse,
+ isPropagationStopped: returnFalse,
+ isImmediatePropagationStopped: returnFalse,
+ isSimulated: false,
+
+ preventDefault: function() {
+ var e = this.originalEvent;
+
+ this.isDefaultPrevented = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.preventDefault();
+ }
+ },
+ stopPropagation: function() {
+ var e = this.originalEvent;
+
+ this.isPropagationStopped = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.stopPropagation();
+ }
+ },
+ stopImmediatePropagation: function() {
+ var e = this.originalEvent;
+
+ this.isImmediatePropagationStopped = returnTrue;
+
+ if ( e && !this.isSimulated ) {
+ e.stopImmediatePropagation();
+ }
+
+ this.stopPropagation();
+ }
+};
+
+// Includes all common event props including KeyEvent and MouseEvent specific props
+jQuery.each( {
+ altKey: true,
+ bubbles: true,
+ cancelable: true,
+ changedTouches: true,
+ ctrlKey: true,
+ detail: true,
+ eventPhase: true,
+ metaKey: true,
+ pageX: true,
+ pageY: true,
+ shiftKey: true,
+ view: true,
+ "char": true,
+ charCode: true,
+ key: true,
+ keyCode: true,
+ button: true,
+ buttons: true,
+ clientX: true,
+ clientY: true,
+ offsetX: true,
+ offsetY: true,
+ pointerId: true,
+ pointerType: true,
+ screenX: true,
+ screenY: true,
+ targetTouches: true,
+ toElement: true,
+ touches: true,
+
+ which: function( event ) {
+ var button = event.button;
+
+ // Add which for key events
+ if ( event.which == null && rkeyEvent.test( event.type ) ) {
+ return event.charCode != null ? event.charCode : event.keyCode;
+ }
+
+ // Add which for click: 1 === left; 2 === middle; 3 === right
+ if ( !event.which && button !== undefined && rmouseEvent.test( event.type ) ) {
+ if ( button & 1 ) {
+ return 1;
+ }
+
+ if ( button & 2 ) {
+ return 3;
+ }
+
+ if ( button & 4 ) {
+ return 2;
+ }
+
+ return 0;
+ }
+
+ return event.which;
+ }
+}, jQuery.event.addProp );
+
+// Create mouseenter/leave events using mouseover/out and event-time checks
+// so that event delegation works in jQuery.
+// Do the same for pointerenter/pointerleave and pointerover/pointerout
+//
+// Support: Safari 7 only
+// Safari sends mouseenter too often; see:
+// https://bugs.chromium.org/p/chromium/issues/detail?id=470258
+// for the description of the bug (it existed in older Chrome versions as well).
+jQuery.each( {
+ mouseenter: "mouseover",
+ mouseleave: "mouseout",
+ pointerenter: "pointerover",
+ pointerleave: "pointerout"
+}, function( orig, fix ) {
+ jQuery.event.special[ orig ] = {
+ delegateType: fix,
+ bindType: fix,
+
+ handle: function( event ) {
+ var ret,
+ target = this,
+ related = event.relatedTarget,
+ handleObj = event.handleObj;
+
+ // For mouseenter/leave call the handler if related is outside the target.
+ // NB: No relatedTarget if the mouse left/entered the browser window
+ if ( !related || ( related !== target && !jQuery.contains( target, related ) ) ) {
+ event.type = handleObj.origType;
+ ret = handleObj.handler.apply( this, arguments );
+ event.type = fix;
+ }
+ return ret;
+ }
+ };
+} );
+
+jQuery.fn.extend( {
+
+ on: function( types, selector, data, fn ) {
+ return on( this, types, selector, data, fn );
+ },
+ one: function( types, selector, data, fn ) {
+ return on( this, types, selector, data, fn, 1 );
+ },
+ off: function( types, selector, fn ) {
+ var handleObj, type;
+ if ( types && types.preventDefault && types.handleObj ) {
+
+ // ( event ) dispatched jQuery.Event
+ handleObj = types.handleObj;
+ jQuery( types.delegateTarget ).off(
+ handleObj.namespace ?
+ handleObj.origType + "." + handleObj.namespace :
+ handleObj.origType,
+ handleObj.selector,
+ handleObj.handler
+ );
+ return this;
+ }
+ if ( typeof types === "object" ) {
+
+ // ( types-object [, selector] )
+ for ( type in types ) {
+ this.off( type, selector, types[ type ] );
+ }
+ return this;
+ }
+ if ( selector === false || typeof selector === "function" ) {
+
+ // ( types [, fn] )
+ fn = selector;
+ selector = undefined;
+ }
+ if ( fn === false ) {
+ fn = returnFalse;
+ }
+ return this.each( function() {
+ jQuery.event.remove( this, types, fn, selector );
+ } );
+ }
+} );
+
+
+var
+
+ /* eslint-disable max-len */
+
+ // See https://github.com/eslint/eslint/issues/3229
+ rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([a-z][^\/\0>\x20\t\r\n\f]*)[^>]*)\/>/gi,
+
+ /* eslint-enable */
+
+ // Support: IE <=10 - 11, Edge 12 - 13
+ // In IE/Edge using regex groups here causes severe slowdowns.
+ // See https://connect.microsoft.com/IE/feedback/details/1736512/
+ rnoInnerhtml = /<script|<style|<link/i,
+
+ // checked="checked" or checked
+ rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
+ rscriptTypeMasked = /^true\/(.*)/,
+ rcleanScript = /^\s*<!(?:\[CDATA\[|--)|(?:\]\]|--)>\s*$/g;
+
+// Prefer a tbody over its parent table for containing new rows
+function manipulationTarget( elem, content ) {
+ if ( nodeName( elem, "table" ) &&
+ nodeName( content.nodeType !== 11 ? content : content.firstChild, "tr" ) ) {
+
+ return jQuery( ">tbody", elem )[ 0 ] || elem;
+ }
+
+ return elem;
+}
+
+// Replace/restore the type attribute of script elements for safe DOM manipulation
+function disableScript( elem ) {
+ elem.type = ( elem.getAttribute( "type" ) !== null ) + "/" + elem.type;
+ return elem;
+}
+function restoreScript( elem ) {
+ var match = rscriptTypeMasked.exec( elem.type );
+
+ if ( match ) {
+ elem.type = match[ 1 ];
+ } else {
+ elem.removeAttribute( "type" );
+ }
+
+ return elem;
+}
+
+function cloneCopyEvent( src, dest ) {
+ var i, l, type, pdataOld, pdataCur, udataOld, udataCur, events;
+
+ if ( dest.nodeType !== 1 ) {
+ return;
+ }
+
+ // 1. Copy private data: events, handlers, etc.
+ if ( dataPriv.hasData( src ) ) {
+ pdataOld = dataPriv.access( src );
+ pdataCur = dataPriv.set( dest, pdataOld );
+ events = pdataOld.events;
+
+ if ( events ) {
+ delete pdataCur.handle;
+ pdataCur.events = {};
+
+ for ( type in events ) {
+ for ( i = 0, l = events[ type ].length; i < l; i++ ) {
+ jQuery.event.add( dest, type, events[ type ][ i ] );
+ }
+ }
+ }
+ }
+
+ // 2. Copy user data
+ if ( dataUser.hasData( src ) ) {
+ udataOld = dataUser.access( src );
+ udataCur = jQuery.extend( {}, udataOld );
+
+ dataUser.set( dest, udataCur );
+ }
+}
+
+// Fix IE bugs, see support tests
+function fixInput( src, dest ) {
+ var nodeName = dest.nodeName.toLowerCase();
+
+ // Fails to persist the checked state of a cloned checkbox or radio button.
+ if ( nodeName === "input" && rcheckableType.test( src.type ) ) {
+ dest.checked = src.checked;
+
+ // Fails to return the selected option to the default selected state when cloning options
+ } else if ( nodeName === "input" || nodeName === "textarea" ) {
+ dest.defaultValue = src.defaultValue;
+ }
+}
+
+function domManip( collection, args, callback, ignored ) {
+
+ // Flatten any nested arrays
+ args = concat.apply( [], args );
+
+ var fragment, first, scripts, hasScripts, node, doc,
+ i = 0,
+ l = collection.length,
+ iNoClone = l - 1,
+ value = args[ 0 ],
+ isFunction = jQuery.isFunction( value );
+
+ // We can't cloneNode fragments that contain checked, in WebKit
+ if ( isFunction ||
+ ( l > 1 && typeof value === "string" &&
+ !support.checkClone && rchecked.test( value ) ) ) {
+ return collection.each( function( index ) {
+ var self = collection.eq( index );
+ if ( isFunction ) {
+ args[ 0 ] = value.call( this, index, self.html() );
+ }
+ domManip( self, args, callback, ignored );
+ } );
+ }
+
+ if ( l ) {
+ fragment = buildFragment( args, collection[ 0 ].ownerDocument, false, collection, ignored );
+ first = fragment.firstChild;
+
+ if ( fragment.childNodes.length === 1 ) {
+ fragment = first;
+ }
+
+ // Require either new content or an interest in ignored elements to invoke the callback
+ if ( first || ignored ) {
+ scripts = jQuery.map( getAll( fragment, "script" ), disableScript );
+ hasScripts = scripts.length;
+
+ // Use the original fragment for the last item
+ // instead of the first because it can end up
+ // being emptied incorrectly in certain situations (#8070).
+ for ( ; i < l; i++ ) {
+ node = fragment;
+
+ if ( i !== iNoClone ) {
+ node = jQuery.clone( node, true, true );
+
+ // Keep references to cloned scripts for later restoration
+ if ( hasScripts ) {
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // push.apply(_, arraylike) throws on ancient WebKit
+ jQuery.merge( scripts, getAll( node, "script" ) );
+ }
+ }
+
+ callback.call( collection[ i ], node, i );
+ }
+
+ if ( hasScripts ) {
+ doc = scripts[ scripts.length - 1 ].ownerDocument;
+
+ // Reenable scripts
+ jQuery.map( scripts, restoreScript );
+
+ // Evaluate executable scripts on first document insertion
+ for ( i = 0; i < hasScripts; i++ ) {
+ node = scripts[ i ];
+ if ( rscriptType.test( node.type || "" ) &&
+ !dataPriv.access( node, "globalEval" ) &&
+ jQuery.contains( doc, node ) ) {
+
+ if ( node.src ) {
+
+ // Optional AJAX dependency, but won't run scripts if not present
+ if ( jQuery._evalUrl ) {
+ jQuery._evalUrl( node.src );
+ }
+ } else {
+ DOMEval( node.textContent.replace( rcleanScript, "" ), doc );
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return collection;
+}
+
+function remove( elem, selector, keepData ) {
+ var node,
+ nodes = selector ? jQuery.filter( selector, elem ) : elem,
+ i = 0;
+
+ for ( ; ( node = nodes[ i ] ) != null; i++ ) {
+ if ( !keepData && node.nodeType === 1 ) {
+ jQuery.cleanData( getAll( node ) );
+ }
+
+ if ( node.parentNode ) {
+ if ( keepData && jQuery.contains( node.ownerDocument, node ) ) {
+ setGlobalEval( getAll( node, "script" ) );
+ }
+ node.parentNode.removeChild( node );
+ }
+ }
+
+ return elem;
+}
+
+jQuery.extend( {
+ htmlPrefilter: function( html ) {
+ return html.replace( rxhtmlTag, "<$1></$2>" );
+ },
+
+ clone: function( elem, dataAndEvents, deepDataAndEvents ) {
+ var i, l, srcElements, destElements,
+ clone = elem.cloneNode( true ),
+ inPage = jQuery.contains( elem.ownerDocument, elem );
+
+ // Fix IE cloning issues
+ if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) &&
+ !jQuery.isXMLDoc( elem ) ) {
+
+ // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2
+ destElements = getAll( clone );
+ srcElements = getAll( elem );
+
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ fixInput( srcElements[ i ], destElements[ i ] );
+ }
+ }
+
+ // Copy the events from the original to the clone
+ if ( dataAndEvents ) {
+ if ( deepDataAndEvents ) {
+ srcElements = srcElements || getAll( elem );
+ destElements = destElements || getAll( clone );
+
+ for ( i = 0, l = srcElements.length; i < l; i++ ) {
+ cloneCopyEvent( srcElements[ i ], destElements[ i ] );
+ }
+ } else {
+ cloneCopyEvent( elem, clone );
+ }
+ }
+
+ // Preserve script evaluation history
+ destElements = getAll( clone, "script" );
+ if ( destElements.length > 0 ) {
+ setGlobalEval( destElements, !inPage && getAll( elem, "script" ) );
+ }
+
+ // Return the cloned set
+ return clone;
+ },
+
+ cleanData: function( elems ) {
+ var data, elem, type,
+ special = jQuery.event.special,
+ i = 0;
+
+ for ( ; ( elem = elems[ i ] ) !== undefined; i++ ) {
+ if ( acceptData( elem ) ) {
+ if ( ( data = elem[ dataPriv.expando ] ) ) {
+ if ( data.events ) {
+ for ( type in data.events ) {
+ if ( special[ type ] ) {
+ jQuery.event.remove( elem, type );
+
+ // This is a shortcut to avoid jQuery.event.remove's overhead
+ } else {
+ jQuery.removeEvent( elem, type, data.handle );
+ }
+ }
+ }
+
+ // Support: Chrome <=35 - 45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataPriv.expando ] = undefined;
+ }
+ if ( elem[ dataUser.expando ] ) {
+
+ // Support: Chrome <=35 - 45+
+ // Assign undefined instead of using delete, see Data#remove
+ elem[ dataUser.expando ] = undefined;
+ }
+ }
+ }
+ }
+} );
+
+jQuery.fn.extend( {
+ detach: function( selector ) {
+ return remove( this, selector, true );
+ },
+
+ remove: function( selector ) {
+ return remove( this, selector );
+ },
+
+ text: function( value ) {
+ return access( this, function( value ) {
+ return value === undefined ?
+ jQuery.text( this ) :
+ this.empty().each( function() {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ this.textContent = value;
+ }
+ } );
+ }, null, value, arguments.length );
+ },
+
+ append: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.appendChild( elem );
+ }
+ } );
+ },
+
+ prepend: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.nodeType === 1 || this.nodeType === 11 || this.nodeType === 9 ) {
+ var target = manipulationTarget( this, elem );
+ target.insertBefore( elem, target.firstChild );
+ }
+ } );
+ },
+
+ before: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this );
+ }
+ } );
+ },
+
+ after: function() {
+ return domManip( this, arguments, function( elem ) {
+ if ( this.parentNode ) {
+ this.parentNode.insertBefore( elem, this.nextSibling );
+ }
+ } );
+ },
+
+ empty: function() {
+ var elem,
+ i = 0;
+
+ for ( ; ( elem = this[ i ] ) != null; i++ ) {
+ if ( elem.nodeType === 1 ) {
+
+ // Prevent memory leaks
+ jQuery.cleanData( getAll( elem, false ) );
+
+ // Remove any remaining nodes
+ elem.textContent = "";
+ }
+ }
+
+ return this;
+ },
+
+ clone: function( dataAndEvents, deepDataAndEvents ) {
+ dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
+ deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
+
+ return this.map( function() {
+ return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
+ } );
+ },
+
+ html: function( value ) {
+ return access( this, function( value ) {
+ var elem = this[ 0 ] || {},
+ i = 0,
+ l = this.length;
+
+ if ( value === undefined && elem.nodeType === 1 ) {
+ return elem.innerHTML;
+ }
+
+ // See if we can take a shortcut and just use innerHTML
+ if ( typeof value === "string" && !rnoInnerhtml.test( value ) &&
+ !wrapMap[ ( rtagName.exec( value ) || [ "", "" ] )[ 1 ].toLowerCase() ] ) {
+
+ value = jQuery.htmlPrefilter( value );
+
+ try {
+ for ( ; i < l; i++ ) {
+ elem = this[ i ] || {};
+
+ // Remove element nodes and prevent memory leaks
+ if ( elem.nodeType === 1 ) {
+ jQuery.cleanData( getAll( elem, false ) );
+ elem.innerHTML = value;
+ }
+ }
+
+ elem = 0;
+
+ // If using innerHTML throws an exception, use the fallback method
+ } catch ( e ) {}
+ }
+
+ if ( elem ) {
+ this.empty().append( value );
+ }
+ }, null, value, arguments.length );
+ },
+
+ replaceWith: function() {
+ var ignored = [];
+
+ // Make the changes, replacing each non-ignored context element with the new content
+ return domManip( this, arguments, function( elem ) {
+ var parent = this.parentNode;
+
+ if ( jQuery.inArray( this, ignored ) < 0 ) {
+ jQuery.cleanData( getAll( this ) );
+ if ( parent ) {
+ parent.replaceChild( elem, this );
+ }
+ }
+
+ // Force callback invocation
+ }, ignored );
+ }
+} );
+
+jQuery.each( {
+ appendTo: "append",
+ prependTo: "prepend",
+ insertBefore: "before",
+ insertAfter: "after",
+ replaceAll: "replaceWith"
+}, function( name, original ) {
+ jQuery.fn[ name ] = function( selector ) {
+ var elems,
+ ret = [],
+ insert = jQuery( selector ),
+ last = insert.length - 1,
+ i = 0;
+
+ for ( ; i <= last; i++ ) {
+ elems = i === last ? this : this.clone( true );
+ jQuery( insert[ i ] )[ original ]( elems );
+
+ // Support: Android <=4.0 only, PhantomJS 1 only
+ // .get() because push.apply(_, arraylike) throws on ancient WebKit
+ push.apply( ret, elems.get() );
+ }
+
+ return this.pushStack( ret );
+ };
+} );
+var rmargin = ( /^margin/ );
+
+var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" );
+
+var getStyles = function( elem ) {
+
+ // Support: IE <=11 only, Firefox <=30 (#15098, #14150)
+ // IE throws on elements created in popups
+ // FF meanwhile throws on frame elements through "defaultView.getComputedStyle"
+ var view = elem.ownerDocument.defaultView;
+
+ if ( !view || !view.opener ) {
+ view = window;
+ }
+
+ return view.getComputedStyle( elem );
+ };
+
+
+
+( function() {
+
+ // Executing both pixelPosition & boxSizingReliable tests require only one layout
+ // so they're executed at the same time to save the second computation.
+ function computeStyleTests() {
+
+ // This is a singleton, we need to execute it only once
+ if ( !div ) {
+ return;
+ }
+
+ div.style.cssText =
+ "box-sizing:border-box;" +
+ "position:relative;display:block;" +
+ "margin:auto;border:1px;padding:1px;" +
+ "top:1%;width:50%";
+ div.innerHTML = "";
+ documentElement.appendChild( container );
+
+ var divStyle = window.getComputedStyle( div );
+ pixelPositionVal = divStyle.top !== "1%";
+
+ // Support: Android 4.0 - 4.3 only, Firefox <=3 - 44
+ reliableMarginLeftVal = divStyle.marginLeft === "2px";
+ boxSizingReliableVal = divStyle.width === "4px";
+
+ // Support: Android 4.0 - 4.3 only
+ // Some styles come back with percentage values, even though they shouldn't
+ div.style.marginRight = "50%";
+ pixelMarginRightVal = divStyle.marginRight === "4px";
+
+ documentElement.removeChild( container );
+
+ // Nullify the div so it wouldn't be stored in the memory and
+ // it will also be a sign that checks already performed
+ div = null;
+ }
+
+ var pixelPositionVal, boxSizingReliableVal, pixelMarginRightVal, reliableMarginLeftVal,
+ container = document.createElement( "div" ),
+ div = document.createElement( "div" );
+
+ // Finish early in limited (non-browser) environments
+ if ( !div.style ) {
+ return;
+ }
+
+ // Support: IE <=9 - 11 only
+ // Style of cloned element affects source element cloned (#8908)
+ div.style.backgroundClip = "content-box";
+ div.cloneNode( true ).style.backgroundClip = "";
+ support.clearCloneStyle = div.style.backgroundClip === "content-box";
+
+ container.style.cssText = "border:0;width:8px;height:0;top:0;left:-9999px;" +
+ "padding:0;margin-top:1px;position:absolute";
+ container.appendChild( div );
+
+ jQuery.extend( support, {
+ pixelPosition: function() {
+ computeStyleTests();
+ return pixelPositionVal;
+ },
+ boxSizingReliable: function() {
+ computeStyleTests();
+ return boxSizingReliableVal;
+ },
+ pixelMarginRight: function() {
+ computeStyleTests();
+ return pixelMarginRightVal;
+ },
+ reliableMarginLeft: function() {
+ computeStyleTests();
+ return reliableMarginLeftVal;
+ }
+ } );
+} )();
+
+
+function curCSS( elem, name, computed ) {
+ var width, minWidth, maxWidth, ret,
+
+ // Support: Firefox 51+
+ // Retrieving style before computed somehow
+ // fixes an issue with getting wrong values
+ // on detached elements
+ style = elem.style;
+
+ computed = computed || getStyles( elem );
+
+ // getPropertyValue is needed for:
+ // .css('filter') (IE 9 only, #12537)
+ // .css('--customProperty) (#3144)
+ if ( computed ) {
+ ret = computed.getPropertyValue( name ) || computed[ name ];
+
+ if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) {
+ ret = jQuery.style( elem, name );
+ }
+
+ // A tribute to the "awesome hack by Dean Edwards"
+ // Android Browser returns percentage for some values,
+ // but width seems to be reliably pixels.
+ // This is against the CSSOM draft spec:
+ // https://drafts.csswg.org/cssom/#resolved-values
+ if ( !support.pixelMarginRight() && rnumnonpx.test( ret ) && rmargin.test( name ) ) {
+
+ // Remember the original values
+ width = style.width;
+ minWidth = style.minWidth;
+ maxWidth = style.maxWidth;
+
+ // Put in the new values to get a computed value out
+ style.minWidth = style.maxWidth = style.width = ret;
+ ret = computed.width;
+
+ // Revert the changed values
+ style.width = width;
+ style.minWidth = minWidth;
+ style.maxWidth = maxWidth;
+ }
+ }
+
+ return ret !== undefined ?
+
+ // Support: IE <=9 - 11 only
+ // IE returns zIndex value as an integer.
+ ret + "" :
+ ret;
+}
+
+
+function addGetHookIf( conditionFn, hookFn ) {
+
+ // Define the hook, we'll check on the first run if it's really needed.
+ return {
+ get: function() {
+ if ( conditionFn() ) {
+
+ // Hook not needed (or it's not possible to use it due
+ // to missing dependency), remove it.
+ delete this.get;
+ return;
+ }
+
+ // Hook needed; redefine it so that the support test is not executed again.
+ return ( this.get = hookFn ).apply( this, arguments );
+ }
+ };
+}
+
+
+var
+
+ // Swappable if display is none or starts with table
+ // except "table", "table-cell", or "table-caption"
+ // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display
+ rdisplayswap = /^(none|table(?!-c[ea]).+)/,
+ rcustomProp = /^--/,
+ cssShow = { position: "absolute", visibility: "hidden", display: "block" },
+ cssNormalTransform = {
+ letterSpacing: "0",
+ fontWeight: "400"
+ },
+
+ cssPrefixes = [ "Webkit", "Moz", "ms" ],
+ emptyStyle = document.createElement( "div" ).style;
+
+// Return a css property mapped to a potentially vendor prefixed property
+function vendorPropName( name ) {
+
+ // Shortcut for names that are not vendor prefixed
+ if ( name in emptyStyle ) {
+ return name;
+ }
+
+ // Check for vendor prefixed names
+ var capName = name[ 0 ].toUpperCase() + name.slice( 1 ),
+ i = cssPrefixes.length;
+
+ while ( i-- ) {
+ name = cssPrefixes[ i ] + capName;
+ if ( name in emptyStyle ) {
+ return name;
+ }
+ }
+}
+
+// Return a property mapped along what jQuery.cssProps suggests or to
+// a vendor prefixed property.
+function finalPropName( name ) {
+ var ret = jQuery.cssProps[ name ];
+ if ( !ret ) {
+ ret = jQuery.cssProps[ name ] = vendorPropName( name ) || name;
+ }
+ return ret;
+}
+
+function setPositiveNumber( elem, value, subtract ) {
+
+ // Any relative (+/-) values have already been
+ // normalized at this point
+ var matches = rcssNum.exec( value );
+ return matches ?
+
+ // Guard against undefined "subtract", e.g., when used as in cssHooks
+ Math.max( 0, matches[ 2 ] - ( subtract || 0 ) ) + ( matches[ 3 ] || "px" ) :
+ value;
+}
+
+function augmentWidthOrHeight( elem, name, extra, isBorderBox, styles ) {
+ var i,
+ val = 0;
+
+ // If we already have the right measurement, avoid augmentation
+ if ( extra === ( isBorderBox ? "border" : "content" ) ) {
+ i = 4;
+
+ // Otherwise initialize for horizontal or vertical properties
+ } else {
+ i = name === "width" ? 1 : 0;
+ }
+
+ for ( ; i < 4; i += 2 ) {
+
+ // Both box models exclude margin, so add it if we want it
+ if ( extra === "margin" ) {
+ val += jQuery.css( elem, extra + cssExpand[ i ], true, styles );
+ }
+
+ if ( isBorderBox ) {
+
+ // border-box includes padding, so remove it if we want content
+ if ( extra === "content" ) {
+ val -= jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+ }
+
+ // At this point, extra isn't border nor margin, so remove border
+ if ( extra !== "margin" ) {
+ val -= jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ } else {
+
+ // At this point, extra isn't content, so add padding
+ val += jQuery.css( elem, "padding" + cssExpand[ i ], true, styles );
+
+ // At this point, extra isn't content nor padding, so add border
+ if ( extra !== "padding" ) {
+ val += jQuery.css( elem, "border" + cssExpand[ i ] + "Width", true, styles );
+ }
+ }
+ }
+
+ return val;
+}
+
+function getWidthOrHeight( elem, name, extra ) {
+
+ // Start with computed style
+ var valueIsBorderBox,
+ styles = getStyles( elem ),
+ val = curCSS( elem, name, styles ),
+ isBorderBox = jQuery.css( elem, "boxSizing", false, styles ) === "border-box";
+
+ // Computed unit is not pixels. Stop here and return.
+ if ( rnumnonpx.test( val ) ) {
+ return val;
+ }
+
+ // Check for style in case a browser which returns unreliable values
+ // for getComputedStyle silently falls back to the reliable elem.style
+ valueIsBorderBox = isBorderBox &&
+ ( support.boxSizingReliable() || val === elem.style[ name ] );
+
+ // Fall back to offsetWidth/Height when value is "auto"
+ // This happens for inline elements with no explicit setting (gh-3571)
+ if ( val === "auto" ) {
+ val = elem[ "offset" + name[ 0 ].toUpperCase() + name.slice( 1 ) ];
+ }
+
+ // Normalize "", auto, and prepare for extra
+ val = parseFloat( val ) || 0;
+
+ // Use the active box-sizing model to add/subtract irrelevant styles
+ return ( val +
+ augmentWidthOrHeight(
+ elem,
+ name,
+ extra || ( isBorderBox ? "border" : "content" ),
+ valueIsBorderBox,
+ styles
+ )
+ ) + "px";
+}
+
+jQuery.extend( {
+
+ // Add in style property hooks for overriding the default
+ // behavior of getting and setting a style property
+ cssHooks: {
+ opacity: {
+ get: function( elem, computed ) {
+ if ( computed ) {
+
+ // We should always get a number back from opacity
+ var ret = curCSS( elem, "opacity" );
+ return ret === "" ? "1" : ret;
+ }
+ }
+ }
+ },
+
+ // Don't automatically add "px" to these possibly-unitless properties
+ cssNumber: {
+ "animationIterationCount": true,
+ "columnCount": true,
+ "fillOpacity": true,
+ "flexGrow": true,
+ "flexShrink": true,
+ "fontWeight": true,
+ "lineHeight": true,
+ "opacity": true,
+ "order": true,
+ "orphans": true,
+ "widows": true,
+ "zIndex": true,
+ "zoom": true
+ },
+
+ // Add in properties whose names you wish to fix before
+ // setting or getting the value
+ cssProps: {
+ "float": "cssFloat"
+ },
+
+ // Get and set the style property on a DOM Node
+ style: function( elem, name, value, extra ) {
+
+ // Don't set styles on text and comment nodes
+ if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
+ return;
+ }
+
+ // Make sure that we're working with the right name
+ var ret, type, hooks,
+ origName = jQuery.camelCase( name ),
+ isCustomProp = rcustomProp.test( name ),
+ style = elem.style;
+
+ // Make sure that we're working with the right name. We don't
+ // want to query the value if it is a CSS custom property
+ // since they are user-defined.
+ if ( !isCustomProp ) {
+ name = finalPropName( origName );
+ }
+
+ // Gets hook for the prefixed version, then unprefixed version
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // Check if we're setting a value
+ if ( value !== undefined ) {
+ type = typeof value;
+
+ // Convert "+=" or "-=" to relative numbers (#7345)
+ if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) {
+ value = adjustCSS( elem, name, ret );
+
+ // Fixes bug #9237
+ type = "number";
+ }
+
+ // Make sure that null and NaN values aren't set (#7116)
+ if ( value == null || value !== value ) {
+ return;
+ }
+
+ // If a number was passed in, add the unit (except for certain CSS properties)
+ if ( type === "number" ) {
+ value += ret && ret[ 3 ] || ( jQuery.cssNumber[ origName ] ? "" : "px" );
+ }
+
+ // background-* props affect original clone's values
+ if ( !support.clearCloneStyle && value === "" && name.indexOf( "background" ) === 0 ) {
+ style[ name ] = "inherit";
+ }
+
+ // If a hook was provided, use that value, otherwise just set the specified value
+ if ( !hooks || !( "set" in hooks ) ||
+ ( value = hooks.set( elem, value, extra ) ) !== undefined ) {
+
+ if ( isCustomProp ) {
+ style.setProperty( name, value );
+ } else {
+ style[ name ] = value;
+ }
+ }
+
+ } else {
+
+ // If a hook was provided get the non-computed value from there
+ if ( hooks && "get" in hooks &&
+ ( ret = hooks.get( elem, false, extra ) ) !== undefined ) {
+
+ return ret;
+ }
+
+ // Otherwise just get the value from the style object
+ return style[ name ];
+ }
+ },
+
+ css: function( elem, name, extra, styles ) {
+ var val, num, hooks,
+ origName = jQuery.camelCase( name ),
+ isCustomProp = rcustomProp.test( name );
+
+ // Make sure that we're working with the right name. We don't
+ // want to modify the value if it is a CSS custom property
+ // since they are user-defined.
+ if ( !isCustomProp ) {
+ name = finalPropName( origName );
+ }
+
+ // Try prefixed name followed by the unprefixed name
+ hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ];
+
+ // If a hook was provided get the computed value from there
+ if ( hooks && "get" in hooks ) {
+ val = hooks.get( elem, true, extra );
+ }
+
+ // Otherwise, if a way to get the computed value exists, use that
+ if ( val === undefined ) {
+ val = curCSS( elem, name, styles );
+ }
+
+ // Convert "normal" to computed value
+ if ( val === "normal" && name in cssNormalTransform ) {
+ val = cssNormalTransform[ name ];
+ }
+
+ // Make numeric if forced or a qualifier was provided and val looks numeric
+ if ( extra === "" || extra ) {
+ num = parseFloat( val );
+ return extra === true || isFinite( num ) ? num || 0 : val;
+ }
+
+ return val;
+ }
+} );
+
+jQuery.each( [ "height", "width" ], function( i, name ) {
+ jQuery.cssHooks[ name ] = {
+ get: function( elem, computed, extra ) {
+ if ( computed ) {
+
+ // Certain elements can have dimension info if we invisibly show them
+ // but it must have a current display style that would benefit
+ return rdisplayswap.test( jQuery.css( elem, "display" ) ) &&
+
+ // Support: Safari 8+
+ // Table columns in Safari have non-zero offsetWidth & zero
+ // getBoundingClientRect().width unless display is changed.
+ // Support: IE <=11 only
+ // Running getBoundingClientRect on a disconnected node
+ // in IE throws an error.
+ ( !elem.getClientRects().length || !elem.getBoundingClientRect().width ) ?
+ swap( elem, cssShow, function() {
+ return getWidthOrHeight( elem, name, extra );
+ } ) :
+ getWidthOrHeight( elem, name, extra );
+ }
+ },
+
+ set: function( elem, value, extra ) {
+ var matches,
+ styles = extra && getStyles( elem ),
+ subtract = extra && augmentWidthOrHeight(
+ elem,
+ name,
+ extra,
+ jQuery.css( elem, "boxSizing", false, styles ) === "border-box",
+ styles
+ );
+
+ // Convert to pixels if value adjustment is needed
+ if ( subtract && ( matches = rcssNum.exec( value ) ) &&
+ ( matches[ 3 ] || "px" ) !== "px" ) {
+
+ elem.style[ name ] = value;
+ value = jQuery.css( elem, name );
+ }
+
+ return setPositiveNumber( elem, value, subtract );
+ }
+ };
+} );
+
+jQuery.cssHooks.marginLeft = addGetHookIf( support.reliableMarginLeft,
+ function( elem, computed ) {
+ if ( computed ) {
+ return ( parseFloat( curCSS( elem, "marginLeft" ) ) ||
+ elem.getBoundingClientRect().left -
+ swap( elem, { marginLeft: 0 }, function() {
+ return elem.getBoundingClientRect().left;
+ } )
+ ) + "px";
+ }
+ }
+);
+
+// These hooks are used by animate to expand properties
+jQuery.each( {
+ margin: "",
+ padding: "",
+ border: "Width"
+}, function( prefix, suffix ) {
+ jQuery.cssHooks[ prefix + suffix ] = {
+ expand: function( value ) {
+ var i = 0,
+ expanded = {},
+
+ // Assumes a single number if not a string
+ parts = typeof value === "string" ? value.split( " " ) : [ value ];
+
+ for ( ; i < 4; i++ ) {
+ expanded[ prefix + cssExpand[ i ] + suffix ] =
+ parts[ i ] || parts[ i - 2 ] || parts[ 0 ];
+ }
+
+ return expanded;
+ }
+ };
+
+ if ( !rmargin.test( prefix ) ) {
+ jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber;
+ }
+} );
+
+jQuery.fn.extend( {
+ css: function( name, value ) {
+ return access( this, function( elem, name, value ) {
+ var styles, len,
+ map = {},
+ i = 0;
+
+ if ( Array.isArray( name ) ) {
+ styles = getStyles( elem );
+ len = name.length;
+
+ for ( ; i < len; i++ ) {
+ map[ name[ i ] ] = jQuery.css( elem, name[ i ], false, styles );
+ }
+
+ return map;
+ }
+
+ return value !== undefined ?
+ jQuery.style( elem, name, value ) :
+ jQuery.css( elem, name );
+ }, name, value, arguments.length > 1 );
+ }
+} );
+
+
+function Tween( elem, options, prop, end, easing ) {
+ return new Tween.prototype.init( elem, options, prop, end, easing );
+}
+jQuery.Tween = Tween;
+
+Tween.prototype = {
+ constructor: Tween,
+ init: function( elem, options, prop, end, easing, unit ) {
+ this.elem = elem;
+ this.prop = prop;
+ this.easing = easing || jQuery.easing._default;
+ this.options = options;
+ this.start = this.now = this.cur();
+ this.end = end;
+ this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" );
+ },
+ cur: function() {
+ var hooks = Tween.propHooks[ this.prop ];
+
+ return hooks && hooks.get ?
+ hooks.get( this ) :
+ Tween.propHooks._default.get( this );
+ },
+ run: function( percent ) {
+ var eased,
+ hooks = Tween.propHooks[ this.prop ];
+
+ if ( this.options.duration ) {
+ this.pos = eased = jQuery.easing[ this.easing ](
+ percent, this.options.duration * percent, 0, 1, this.options.duration
+ );
+ } else {
+ this.pos = eased = percent;
+ }
+ this.now = ( this.end - this.start ) * eased + this.start;
+
+ if ( this.options.step ) {
+ this.options.step.call( this.elem, this.now, this );
+ }
+
+ if ( hooks && hooks.set ) {
+ hooks.set( this );
+ } else {
+ Tween.propHooks._default.set( this );
+ }
+ return this;
+ }
+};
+
+Tween.prototype.init.prototype = Tween.prototype;
+
+Tween.propHooks = {
+ _default: {
+ get: function( tween ) {
+ var result;
+
+ // Use a property on the element directly when it is not a DOM element,
+ // or when there is no matching style property that exists.
+ if ( tween.elem.nodeType !== 1 ||
+ tween.elem[ tween.prop ] != null && tween.elem.style[ tween.prop ] == null ) {
+ return tween.elem[ tween.prop ];
+ }
+
+ // Passing an empty string as a 3rd parameter to .css will automatically
+ // attempt a parseFloat and fallback to a string if the parse fails.
+ // Simple values such as "10px" are parsed to Float;
+ // complex values such as "rotate(1rad)" are returned as-is.
+ result = jQuery.css( tween.elem, tween.prop, "" );
+
+ // Empty strings, null, undefined and "auto" are converted to 0.
+ return !result || result === "auto" ? 0 : result;
+ },
+ set: function( tween ) {
+
+ // Use step hook for back compat.
+ // Use cssHook if its there.
+ // Use .style if available and use plain properties where available.
+ if ( jQuery.fx.step[ tween.prop ] ) {
+ jQuery.fx.step[ tween.prop ]( tween );
+ } else if ( tween.elem.nodeType === 1 &&
+ ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null ||
+ jQuery.cssHooks[ tween.prop ] ) ) {
+ jQuery.style( tween.elem, tween.prop, tween.now + tween.unit );
+ } else {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+ }
+};
+
+// Support: IE <=9 only
+// Panic based approach to setting things on disconnected nodes
+Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = {
+ set: function( tween ) {
+ if ( tween.elem.nodeType && tween.elem.parentNode ) {
+ tween.elem[ tween.prop ] = tween.now;
+ }
+ }
+};
+
+jQuery.easing = {
+ linear: function( p ) {
+ return p;
+ },
+ swing: function( p ) {
+ return 0.5 - Math.cos( p * Math.PI ) / 2;
+ },
+ _default: "swing"
+};
+
+jQuery.fx = Tween.prototype.init;
+
+// Back compat <1.8 extension point
+jQuery.fx.step = {};
+
+
+
+
+var
+ fxNow, inProgress,
+ rfxtypes = /^(?:toggle|show|hide)$/,
+ rrun = /queueHooks$/;
+
+function schedule() {
+ if ( inProgress ) {
+ if ( document.hidden === false && window.requestAnimationFrame ) {
+ window.requestAnimationFrame( schedule );
+ } else {
+ window.setTimeout( schedule, jQuery.fx.interval );
+ }
+
+ jQuery.fx.tick();
+ }
+}
+
+// Animations created synchronously will run synchronously
+function createFxNow() {
+ window.setTimeout( function() {
+ fxNow = undefined;
+ } );
+ return ( fxNow = jQuery.now() );
+}
+
+// Generate parameters to create a standard animation
+function genFx( type, includeWidth ) {
+ var which,
+ i = 0,
+ attrs = { height: type };
+
+ // If we include width, step value is 1 to do all cssExpand values,
+ // otherwise step value is 2 to skip over Left and Right
+ includeWidth = includeWidth ? 1 : 0;
+ for ( ; i < 4; i += 2 - includeWidth ) {
+ which = cssExpand[ i ];
+ attrs[ "margin" + which ] = attrs[ "padding" + which ] = type;
+ }
+
+ if ( includeWidth ) {
+ attrs.opacity = attrs.width = type;
+ }
+
+ return attrs;
+}
+
+function createTween( value, prop, animation ) {
+ var tween,
+ collection = ( Animation.tweeners[ prop ] || [] ).concat( Animation.tweeners[ "*" ] ),
+ index = 0,
+ length = collection.length;
+ for ( ; index < length; index++ ) {
+ if ( ( tween = collection[ index ].call( animation, prop, value ) ) ) {
+
+ // We're done with this property
+ return tween;
+ }
+ }
+}
+
+function defaultPrefilter( elem, props, opts ) {
+ var prop, value, toggle, hooks, oldfire, propTween, restoreDisplay, display,
+ isBox = "width" in props || "height" in props,
+ anim = this,
+ orig = {},
+ style = elem.style,
+ hidden = elem.nodeType && isHiddenWithinTree( elem ),
+ dataShow = dataPriv.get( elem, "fxshow" );
+
+ // Queue-skipping animations hijack the fx hooks
+ if ( !opts.queue ) {
+ hooks = jQuery._queueHooks( elem, "fx" );
+ if ( hooks.unqueued == null ) {
+ hooks.unqueued = 0;
+ oldfire = hooks.empty.fire;
+ hooks.empty.fire = function() {
+ if ( !hooks.unqueued ) {
+ oldfire();
+ }
+ };
+ }
+ hooks.unqueued++;
+
+ anim.always( function() {
+
+ // Ensure the complete handler is called before this completes
+ anim.always( function() {
+ hooks.unqueued--;
+ if ( !jQuery.queue( elem, "fx" ).length ) {
+ hooks.empty.fire();
+ }
+ } );
+ } );
+ }
+
+ // Detect show/hide animations
+ for ( prop in props ) {
+ value = props[ prop ];
+ if ( rfxtypes.test( value ) ) {
+ delete props[ prop ];
+ toggle = toggle || value === "toggle";
+ if ( value === ( hidden ? "hide" : "show" ) ) {
+
+ // Pretend to be hidden if this is a "show" and
+ // there is still data from a stopped show/hide
+ if ( value === "show" && dataShow && dataShow[ prop ] !== undefined ) {
+ hidden = true;
+
+ // Ignore all other no-op show/hide data
+ } else {
+ continue;
+ }
+ }
+ orig[ prop ] = dataShow && dataShow[ prop ] || jQuery.style( elem, prop );
+ }
+ }
+
+ // Bail out if this is a no-op like .hide().hide()
+ propTween = !jQuery.isEmptyObject( props );
+ if ( !propTween && jQuery.isEmptyObject( orig ) ) {
+ return;
+ }
+
+ // Restrict "overflow" and "display" styles during box animations
+ if ( isBox && elem.nodeType === 1 ) {
+
+ // Support: IE <=9 - 11, Edge 12 - 13
+ // Record all 3 overflow attributes because IE does not infer the shorthand
+ // from identically-valued overflowX and overflowY
+ opts.overflow = [ style.overflow, style.overflowX, style.overflowY ];
+
+ // Identify a display type, preferring old show/hide data over the CSS cascade
+ restoreDisplay = dataShow && dataShow.display;
+ if ( restoreDisplay == null ) {
+ restoreDisplay = dataPriv.get( elem, "display" );
+ }
+ display = jQuery.css( elem, "display" );
+ if ( display === "none" ) {
+ if ( restoreDisplay ) {
+ display = restoreDisplay;
+ } else {
+
+ // Get nonempty value(s) by temporarily forcing visibility
+ showHide( [ elem ], true );
+ restoreDisplay = elem.style.display || restoreDisplay;
+ display = jQuery.css( elem, "display" );
+ showHide( [ elem ] );
+ }
+ }
+
+ // Animate inline elements as inline-block
+ if ( display === "inline" || display === "inline-block" && restoreDisplay != null ) {
+ if ( jQuery.css( elem, "float" ) === "none" ) {
+
+ // Restore the original display value at the end of pure show/hide animations
+ if ( !propTween ) {
+ anim.done( function() {
+ style.display = restoreDisplay;
+ } );
+ if ( restoreDisplay == null ) {
+ display = style.display;
+ restoreDisplay = display === "none" ? "" : display;
+ }
+ }
+ style.display = "inline-block";
+ }
+ }
+ }
+
+ if ( opts.overflow ) {
+ style.overflow = "hidden";
+ anim.always( function() {
+ style.overflow = opts.overflow[ 0 ];
+ style.overflowX = opts.overflow[ 1 ];
+ style.overflowY = opts.overflow[ 2 ];
+ } );
+ }
+
+ // Implement show/hide animations
+ propTween = false;
+ for ( prop in orig ) {
+
+ // General show/hide setup for this element animation
+ if ( !propTween ) {
+ if ( dataShow ) {
+ if ( "hidden" in dataShow ) {
+ hidden = dataShow.hidden;
+ }
+ } else {
+ dataShow = dataPriv.access( elem, "fxshow", { display: restoreDisplay } );
+ }
+
+ // Store hidden/visible for toggle so `.stop().toggle()` "reverses"
+ if ( toggle ) {
+ dataShow.hidden = !hidden;
+ }
+
+ // Show elements before animating them
+ if ( hidden ) {
+ showHide( [ elem ], true );
+ }
+
+ /* eslint-disable no-loop-func */
+
+ anim.done( function() {
+
+ /* eslint-enable no-loop-func */
+
+ // The final step of a "hide" animation is actually hiding the element
+ if ( !hidden ) {
+ showHide( [ elem ] );
+ }
+ dataPriv.remove( elem, "fxshow" );
+ for ( prop in orig ) {
+ jQuery.style( elem, prop, orig[ prop ] );
+ }
+ } );
+ }
+
+ // Per-property setup
+ propTween = createTween( hidden ? dataShow[ prop ] : 0, prop, anim );
+ if ( !( prop in dataShow ) ) {
+ dataShow[ prop ] = propTween.start;
+ if ( hidden ) {
+ propTween.end = propTween.start;
+ propTween.start = 0;
+ }
+ }
+ }
+}
+
+function propFilter( props, specialEasing ) {
+ var index, name, easing, value, hooks;
+
+ // camelCase, specialEasing and expand cssHook pass
+ for ( index in props ) {
+ name = jQuery.camelCase( index );
+ easing = specialEasing[ name ];
+ value = props[ index ];
+ if ( Array.isArray( value ) ) {
+ easing = value[ 1 ];
+ value = props[ index ] = value[ 0 ];
+ }
+
+ if ( index !== name ) {
+ props[ name ] = value;
+ delete props[ index ];
+ }
+
+ hooks = jQuery.cssHooks[ name ];
+ if ( hooks && "expand" in hooks ) {
+ value = hooks.expand( value );
+ delete props[ name ];
+
+ // Not quite $.extend, this won't overwrite existing keys.
+ // Reusing 'index' because we have the correct "name"
+ for ( index in value ) {
+ if ( !( index in props ) ) {
+ props[ index ] = value[ index ];
+ specialEasing[ index ] = easing;
+ }
+ }
+ } else {
+ specialEasing[ name ] = easing;
+ }
+ }
+}
+
+function Animation( elem, properties, options ) {
+ var result,
+ stopped,
+ index = 0,
+ length = Animation.prefilters.length,
+ deferred = jQuery.Deferred().always( function() {
+
+ // Don't match elem in the :animated selector
+ delete tick.elem;
+ } ),
+ tick = function() {
+ if ( stopped ) {
+ return false;
+ }
+ var currentTime = fxNow || createFxNow(),
+ remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ),
+
+ // Support: Android 2.3 only
+ // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497)
+ temp = remaining / animation.duration || 0,
+ percent = 1 - temp,
+ index = 0,
+ length = animation.tweens.length;
+
+ for ( ; index < length; index++ ) {
+ animation.tweens[ index ].run( percent );
+ }
+
+ deferred.notifyWith( elem, [ animation, percent, remaining ] );
+
+ // If there's more to do, yield
+ if ( percent < 1 && length ) {
+ return remaining;
+ }
+
+ // If this was an empty animation, synthesize a final progress notification
+ if ( !length ) {
+ deferred.notifyWith( elem, [ animation, 1, 0 ] );
+ }
+
+ // Resolve the animation and report its conclusion
+ deferred.resolveWith( elem, [ animation ] );
+ return false;
+ },
+ animation = deferred.promise( {
+ elem: elem,
+ props: jQuery.extend( {}, properties ),
+ opts: jQuery.extend( true, {
+ specialEasing: {},
+ easing: jQuery.easing._default
+ }, options ),
+ originalProperties: properties,
+ originalOptions: options,
+ startTime: fxNow || createFxNow(),
+ duration: options.duration,
+ tweens: [],
+ createTween: function( prop, end ) {
+ var tween = jQuery.Tween( elem, animation.opts, prop, end,
+ animation.opts.specialEasing[ prop ] || animation.opts.easing );
+ animation.tweens.push( tween );
+ return tween;
+ },
+ stop: function( gotoEnd ) {
+ var index = 0,
+
+ // If we are going to the end, we want to run all the tweens
+ // otherwise we skip this part
+ length = gotoEnd ? animation.tweens.length : 0;
+ if ( stopped ) {
+ return this;
+ }
+ stopped = true;
+ for ( ; index < length; index++ ) {
+ animation.tweens[ index ].run( 1 );
+ }
+
+ // Resolve when we played the last frame; otherwise, reject
+ if ( gotoEnd ) {
+ deferred.notifyWith( elem, [ animation, 1, 0 ] );
+ deferred.resolveWith( elem, [ animation, gotoEnd ] );
+ } else {
+ deferred.rejectWith( elem, [ animation, gotoEnd ] );
+ }
+ return this;
+ }
+ } ),
+ props = animation.props;
+
+ propFilter( props, animation.opts.specialEasing );
+
+ for ( ; index < length; index++ ) {
+ result = Animation.prefilters[ index ].call( animation, elem, props, animation.opts );
+ if ( result ) {
+ if ( jQuery.isFunction( result.stop ) ) {
+ jQuery._queueHooks( animation.elem, animation.opts.queue ).stop =
+ jQuery.proxy( result.stop, result );
+ }
+ return result;
+ }
+ }
+
+ jQuery.map( props, createTween, animation );
+
+ if ( jQuery.isFunction( animation.opts.start ) ) {
+ animation.opts.start.call( elem, animation );
+ }
+
+ // Attach callbacks from options
+ animation
+ .progress( animation.opts.progress )
+ .done( animation.opts.done, animation.opts.complete )
+ .fail( animation.opts.fail )
+ .always( animation.opts.always );
+
+ jQuery.fx.timer(
+ jQuery.extend( tick, {
+ elem: elem,
+ anim: animation,
+ queue: animation.opts.queue
+ } )
+ );
+
+ return animation;
+}
+
+jQuery.Animation = jQuery.extend( Animation, {
+
+ tweeners: {
+ "*": [ function( prop, value ) {
+ var tween = this.createTween( prop, value );
+ adjustCSS( tween.elem, prop, rcssNum.exec( value ), tween );
+ return tween;
+ } ]
+ },
+
+ tweener: function( props, callback ) {
+ if ( jQuery.isFunction( props ) ) {
+ callback = props;
+ props = [ "*" ];
+ } else {
+ props = props.match( rnothtmlwhite );
+ }
+
+ var prop,
+ index = 0,
+ length = props.length;
+
+ for ( ; index < length; index++ ) {
+ prop = props[ index ];
+ Animation.tweeners[ prop ] = Animation.tweeners[ prop ] || [];
+ Animation.tweeners[ prop ].unshift( callback );
+ }
+ },
+
+ prefilters: [ defaultPrefilter ],
+
+ prefilter: function( callback, prepend ) {
+ if ( prepend ) {
+ Animation.prefilters.unshift( callback );
+ } else {
+ Animation.prefilters.push( callback );
+ }
+ }
+} );
+
+jQuery.speed = function( speed, easing, fn ) {
+ var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : {
+ complete: fn || !fn && easing ||
+ jQuery.isFunction( speed ) && speed,
+ duration: speed,
+ easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing
+ };
+
+ // Go to the end state if fx are off
+ if ( jQuery.fx.off ) {
+ opt.duration = 0;
+
+ } else {
+ if ( typeof opt.duration !== "number" ) {
+ if ( opt.duration in jQuery.fx.speeds ) {
+ opt.duration = jQuery.fx.speeds[ opt.duration ];
+
+ } else {
+ opt.duration = jQuery.fx.speeds._default;
+ }
+ }
+ }
+
+ // Normalize opt.queue - true/undefined/null -> "fx"
+ if ( opt.queue == null || opt.queue === true ) {
+ opt.queue = "fx";
+ }
+
+ // Queueing
+ opt.old = opt.complete;
+
+ opt.complete = function() {
+ if ( jQuery.isFunction( opt.old ) ) {
+ opt.old.call( this );
+ }
+
+ if ( opt.queue ) {
+ jQuery.dequeue( this, opt.queue );
+ }
+ };
+
+ return opt;
+};
+
+jQuery.fn.extend( {
+ fadeTo: function( speed, to, easing, callback ) {
+
+ // Show any hidden elements after setting opacity to 0
+ return this.filter( isHiddenWithinTree ).css( "opacity", 0 ).show()
+
+ // Animate to the value specified
+ .end().animate( { opacity: to }, speed, easing, callback );
+ },
+ animate: function( prop, speed, easing, callback ) {
+ var empty = jQuery.isEmptyObject( prop ),
+ optall = jQuery.speed( speed, easing, callback ),
+ doAnimation = function() {
+
+ // Operate on a copy of prop so per-property easing won't be lost
+ var anim = Animation( this, jQuery.extend( {}, prop ), optall );
+
+ // Empty animations, or finishing resolves immediately
+ if ( empty || dataPriv.get( this, "finish" ) ) {
+ anim.stop( true );
+ }
+ };
+ doAnimation.finish = doAnimation;
+
+ return empty || optall.queue === false ?
+ this.each( doAnimation ) :
+ this.queue( optall.queue, doAnimation );
+ },
+ stop: function( type, clearQueue, gotoEnd ) {
+ var stopQueue = function( hooks ) {
+ var stop = hooks.stop;
+ delete hooks.stop;
+ stop( gotoEnd );
+ };
+
+ if ( typeof type !== "string" ) {
+ gotoEnd = clearQueue;
+ clearQueue = type;
+ type = undefined;
+ }
+ if ( clearQueue && type !== false ) {
+ this.queue( type || "fx", [] );
+ }
+
+ return this.each( function() {
+ var dequeue = true,
+ index = type != null && type + "queueHooks",
+ timers = jQuery.timers,
+ data = dataPriv.get( this );
+
+ if ( index ) {
+ if ( data[ index ] && data[ index ].stop ) {
+ stopQueue( data[ index ] );
+ }
+ } else {
+ for ( index in data ) {
+ if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) {
+ stopQueue( data[ index ] );
+ }
+ }
+ }
+
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this &&
+ ( type == null || timers[ index ].queue === type ) ) {
+
+ timers[ index ].anim.stop( gotoEnd );
+ dequeue = false;
+ timers.splice( index, 1 );
+ }
+ }
+
+ // Start the next in the queue if the last step wasn't forced.
+ // Timers currently will call their complete callbacks, which
+ // will dequeue but only if they were gotoEnd.
+ if ( dequeue || !gotoEnd ) {
+ jQuery.dequeue( this, type );
+ }
+ } );
+ },
+ finish: function( type ) {
+ if ( type !== false ) {
+ type = type || "fx";
+ }
+ return this.each( function() {
+ var index,
+ data = dataPriv.get( this ),
+ queue = data[ type + "queue" ],
+ hooks = data[ type + "queueHooks" ],
+ timers = jQuery.timers,
+ length = queue ? queue.length : 0;
+
+ // Enable finishing flag on private data
+ data.finish = true;
+
+ // Empty the queue first
+ jQuery.queue( this, type, [] );
+
+ if ( hooks && hooks.stop ) {
+ hooks.stop.call( this, true );
+ }
+
+ // Look for any active animations, and finish them
+ for ( index = timers.length; index--; ) {
+ if ( timers[ index ].elem === this && timers[ index ].queue === type ) {
+ timers[ index ].anim.stop( true );
+ timers.splice( index, 1 );
+ }
+ }
+
+ // Look for any animations in the old queue and finish them
+ for ( index = 0; index < length; index++ ) {
+ if ( queue[ index ] && queue[ index ].finish ) {
+ queue[ index ].finish.call( this );
+ }
+ }
+
+ // Turn off finishing flag
+ delete data.finish;
+ } );
+ }
+} );
+
+jQuery.each( [ "toggle", "show", "hide" ], function( i, name ) {
+ var cssFn = jQuery.fn[ name ];
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return speed == null || typeof speed === "boolean" ?
+ cssFn.apply( this, arguments ) :
+ this.animate( genFx( name, true ), speed, easing, callback );
+ };
+} );
+
+// Generate shortcuts for custom animations
+jQuery.each( {
+ slideDown: genFx( "show" ),
+ slideUp: genFx( "hide" ),
+ slideToggle: genFx( "toggle" ),
+ fadeIn: { opacity: "show" },
+ fadeOut: { opacity: "hide" },
+ fadeToggle: { opacity: "toggle" }
+}, function( name, props ) {
+ jQuery.fn[ name ] = function( speed, easing, callback ) {
+ return this.animate( props, speed, easing, callback );
+ };
+} );
+
+jQuery.timers = [];
+jQuery.fx.tick = function() {
+ var timer,
+ i = 0,
+ timers = jQuery.timers;
+
+ fxNow = jQuery.now();
+
+ for ( ; i < timers.length; i++ ) {
+ timer = timers[ i ];
+
+ // Run the timer and safely remove it when done (allowing for external removal)
+ if ( !timer() && timers[ i ] === timer ) {
+ timers.splice( i--, 1 );
+ }
+ }
+
+ if ( !timers.length ) {
+ jQuery.fx.stop();
+ }
+ fxNow = undefined;
+};
+
+jQuery.fx.timer = function( timer ) {
+ jQuery.timers.push( timer );
+ jQuery.fx.start();
+};
+
+jQuery.fx.interval = 13;
+jQuery.fx.start = function() {
+ if ( inProgress ) {
+ return;
+ }
+
+ inProgress = true;
+ schedule();
+};
+
+jQuery.fx.stop = function() {
+ inProgress = null;
+};
+
+jQuery.fx.speeds = {
+ slow: 600,
+ fast: 200,
+
+ // Default speed
+ _default: 400
+};
+
+
+// Based off of the plugin by Clint Helfers, with permission.
+// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/
+jQuery.fn.delay = function( time, type ) {
+ time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time;
+ type = type || "fx";
+
+ return this.queue( type, function( next, hooks ) {
+ var timeout = window.setTimeout( next, time );
+ hooks.stop = function() {
+ window.clearTimeout( timeout );
+ };
+ } );
+};
+
+
+( function() {
+ var input = document.createElement( "input" ),
+ select = document.createElement( "select" ),
+ opt = select.appendChild( document.createElement( "option" ) );
+
+ input.type = "checkbox";
+
+ // Support: Android <=4.3 only
+ // Default value for a checkbox should be "on"
+ support.checkOn = input.value !== "";
+
+ // Support: IE <=11 only
+ // Must access selectedIndex to make default options select
+ support.optSelected = opt.selected;
+
+ // Support: IE <=11 only
+ // An input loses its value after becoming a radio
+ input = document.createElement( "input" );
+ input.value = "t";
+ input.type = "radio";
+ support.radioValue = input.value === "t";
+} )();
+
+
+var boolHook,
+ attrHandle = jQuery.expr.attrHandle;
+
+jQuery.fn.extend( {
+ attr: function( name, value ) {
+ return access( this, jQuery.attr, name, value, arguments.length > 1 );
+ },
+
+ removeAttr: function( name ) {
+ return this.each( function() {
+ jQuery.removeAttr( this, name );
+ } );
+ }
+} );
+
+jQuery.extend( {
+ attr: function( elem, name, value ) {
+ var ret, hooks,
+ nType = elem.nodeType;
+
+ // Don't get/set attributes on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ // Fallback to prop when attributes are not supported
+ if ( typeof elem.getAttribute === "undefined" ) {
+ return jQuery.prop( elem, name, value );
+ }
+
+ // Attribute hooks are determined by the lowercase version
+ // Grab necessary hook if one is defined
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+ hooks = jQuery.attrHooks[ name.toLowerCase() ] ||
+ ( jQuery.expr.match.bool.test( name ) ? boolHook : undefined );
+ }
+
+ if ( value !== undefined ) {
+ if ( value === null ) {
+ jQuery.removeAttr( elem, name );
+ return;
+ }
+
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+ return ret;
+ }
+
+ elem.setAttribute( name, value + "" );
+ return value;
+ }
+
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
+
+ ret = jQuery.find.attr( elem, name );
+
+ // Non-existent attributes return null, we normalize to undefined
+ return ret == null ? undefined : ret;
+ },
+
+ attrHooks: {
+ type: {
+ set: function( elem, value ) {
+ if ( !support.radioValue && value === "radio" &&
+ nodeName( elem, "input" ) ) {
+ var val = elem.value;
+ elem.setAttribute( "type", value );
+ if ( val ) {
+ elem.value = val;
+ }
+ return value;
+ }
+ }
+ }
+ },
+
+ removeAttr: function( elem, value ) {
+ var name,
+ i = 0,
+
+ // Attribute names can contain non-HTML whitespace characters
+ // https://html.spec.whatwg.org/multipage/syntax.html#attributes-2
+ attrNames = value && value.match( rnothtmlwhite );
+
+ if ( attrNames && elem.nodeType === 1 ) {
+ while ( ( name = attrNames[ i++ ] ) ) {
+ elem.removeAttribute( name );
+ }
+ }
+ }
+} );
+
+// Hooks for boolean attributes
+boolHook = {
+ set: function( elem, value, name ) {
+ if ( value === false ) {
+
+ // Remove boolean attributes when set to false
+ jQuery.removeAttr( elem, name );
+ } else {
+ elem.setAttribute( name, name );
+ }
+ return name;
+ }
+};
+
+jQuery.each( jQuery.expr.match.bool.source.match( /\w+/g ), function( i, name ) {
+ var getter = attrHandle[ name ] || jQuery.find.attr;
+
+ attrHandle[ name ] = function( elem, name, isXML ) {
+ var ret, handle,
+ lowercaseName = name.toLowerCase();
+
+ if ( !isXML ) {
+
+ // Avoid an infinite loop by temporarily removing this function from the getter
+ handle = attrHandle[ lowercaseName ];
+ attrHandle[ lowercaseName ] = ret;
+ ret = getter( elem, name, isXML ) != null ?
+ lowercaseName :
+ null;
+ attrHandle[ lowercaseName ] = handle;
+ }
+ return ret;
+ };
+} );
+
+
+
+
+var rfocusable = /^(?:input|select|textarea|button)$/i,
+ rclickable = /^(?:a|area)$/i;
+
+jQuery.fn.extend( {
+ prop: function( name, value ) {
+ return access( this, jQuery.prop, name, value, arguments.length > 1 );
+ },
+
+ removeProp: function( name ) {
+ return this.each( function() {
+ delete this[ jQuery.propFix[ name ] || name ];
+ } );
+ }
+} );
+
+jQuery.extend( {
+ prop: function( elem, name, value ) {
+ var ret, hooks,
+ nType = elem.nodeType;
+
+ // Don't get/set properties on text, comment and attribute nodes
+ if ( nType === 3 || nType === 8 || nType === 2 ) {
+ return;
+ }
+
+ if ( nType !== 1 || !jQuery.isXMLDoc( elem ) ) {
+
+ // Fix name and attach hooks
+ name = jQuery.propFix[ name ] || name;
+ hooks = jQuery.propHooks[ name ];
+ }
+
+ if ( value !== undefined ) {
+ if ( hooks && "set" in hooks &&
+ ( ret = hooks.set( elem, value, name ) ) !== undefined ) {
+ return ret;
+ }
+
+ return ( elem[ name ] = value );
+ }
+
+ if ( hooks && "get" in hooks && ( ret = hooks.get( elem, name ) ) !== null ) {
+ return ret;
+ }
+
+ return elem[ name ];
+ },
+
+ propHooks: {
+ tabIndex: {
+ get: function( elem ) {
+
+ // Support: IE <=9 - 11 only
+ // elem.tabIndex doesn't always return the
+ // correct value when it hasn't been explicitly set
+ // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
+ // Use proper attribute retrieval(#12072)
+ var tabindex = jQuery.find.attr( elem, "tabindex" );
+
+ if ( tabindex ) {
+ return parseInt( tabindex, 10 );
+ }
+
+ if (
+ rfocusable.test( elem.nodeName ) ||
+ rclickable.test( elem.nodeName ) &&
+ elem.href
+ ) {
+ return 0;
+ }
+
+ return -1;
+ }
+ }
+ },
+
+ propFix: {
+ "for": "htmlFor",
+ "class": "className"
+ }
+} );
+
+// Support: IE <=11 only
+// Accessing the selectedIndex property
+// forces the browser to respect setting selected
+// on the option
+// The getter ensures a default option is selected
+// when in an optgroup
+// eslint rule "no-unused-expressions" is disabled for this code
+// since it considers such accessions noop
+if ( !support.optSelected ) {
+ jQuery.propHooks.selected = {
+ get: function( elem ) {
+
+ /* eslint no-unused-expressions: "off" */
+
+ var parent = elem.parentNode;
+ if ( parent && parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ return null;
+ },
+ set: function( elem ) {
+
+ /* eslint no-unused-expressions: "off" */
+
+ var parent = elem.parentNode;
+ if ( parent ) {
+ parent.selectedIndex;
+
+ if ( parent.parentNode ) {
+ parent.parentNode.selectedIndex;
+ }
+ }
+ }
+ };
+}
+
+jQuery.each( [
+ "tabIndex",
+ "readOnly",
+ "maxLength",
+ "cellSpacing",
+ "cellPadding",
+ "rowSpan",
+ "colSpan",
+ "useMap",
+ "frameBorder",
+ "contentEditable"
+], function() {
+ jQuery.propFix[ this.toLowerCase() ] = this;
+} );
+
+
+
+
+ // Strip and collapse whitespace according to HTML spec
+ // https://html.spec.whatwg.org/multipage/infrastructure.html#strip-and-collapse-whitespace
+ function stripAndCollapse( value ) {
+ var tokens = value.match( rnothtmlwhite ) || [];
+ return tokens.join( " " );
+ }
+
+
+function getClass( elem ) {
+ return elem.getAttribute && elem.getAttribute( "class" ) || "";
+}
+
+jQuery.fn.extend( {
+ addClass: function( value ) {
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( j ) {
+ jQuery( this ).addClass( value.call( this, j, getClass( this ) ) );
+ } );
+ }
+
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnothtmlwhite ) || [];
+
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+ cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
+
+ if ( cur ) {
+ j = 0;
+ while ( ( clazz = classes[ j++ ] ) ) {
+ if ( cur.indexOf( " " + clazz + " " ) < 0 ) {
+ cur += clazz + " ";
+ }
+ }
+
+ // Only assign if different to avoid unneeded rendering.
+ finalValue = stripAndCollapse( cur );
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ removeClass: function( value ) {
+ var classes, elem, cur, curValue, clazz, j, finalValue,
+ i = 0;
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( j ) {
+ jQuery( this ).removeClass( value.call( this, j, getClass( this ) ) );
+ } );
+ }
+
+ if ( !arguments.length ) {
+ return this.attr( "class", "" );
+ }
+
+ if ( typeof value === "string" && value ) {
+ classes = value.match( rnothtmlwhite ) || [];
+
+ while ( ( elem = this[ i++ ] ) ) {
+ curValue = getClass( elem );
+
+ // This expression is here for better compressibility (see addClass)
+ cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " );
+
+ if ( cur ) {
+ j = 0;
+ while ( ( clazz = classes[ j++ ] ) ) {
+
+ // Remove *all* instances
+ while ( cur.indexOf( " " + clazz + " " ) > -1 ) {
+ cur = cur.replace( " " + clazz + " ", " " );
+ }
+ }
+
+ // Only assign if different to avoid unneeded rendering.
+ finalValue = stripAndCollapse( cur );
+ if ( curValue !== finalValue ) {
+ elem.setAttribute( "class", finalValue );
+ }
+ }
+ }
+ }
+
+ return this;
+ },
+
+ toggleClass: function( value, stateVal ) {
+ var type = typeof value;
+
+ if ( typeof stateVal === "boolean" && type === "string" ) {
+ return stateVal ? this.addClass( value ) : this.removeClass( value );
+ }
+
+ if ( jQuery.isFunction( value ) ) {
+ return this.each( function( i ) {
+ jQuery( this ).toggleClass(
+ value.call( this, i, getClass( this ), stateVal ),
+ stateVal
+ );
+ } );
+ }
+
+ return this.each( function() {
+ var className, i, self, classNames;
+
+ if ( type === "string" ) {
+
+ // Toggle individual class names
+ i = 0;
+ self = jQuery( this );
+ classNames = value.match( rnothtmlwhite ) || [];
+
+ while ( ( className = classNames[ i++ ] ) ) {
+
+ // Check each className given, space separated list
+ if ( self.hasClass( className ) ) {
+ self.removeClass( className );
+ } else {
+ self.addClass( className );
+ }
+ }
+
+ // Toggle whole class name
+ } else if ( value === undefined || type === "boolean" ) {
+ className = getClass( this );
+ if ( className ) {
+
+ // Store className if set
+ dataPriv.set( this, "__className__", className );
+ }
+
+ // If the element has a class name or if we're passed `false`,
+ // then remove the whole classname (if there was one, the above saved it).
+ // Otherwise bring back whatever was previously saved (if anything),
+ // falling back to the empty string if nothing was stored.
+ if ( this.setAttribute ) {
+ this.setAttribute( "class",
+ className || value === false ?
+ "" :
+ dataPriv.get( this, "__className__" ) || ""
+ );
+ }
+ }
+ } );
+ },
+
+ hasClass: function( selector ) {
+ var className, elem,
+ i = 0;
+
+ className = " " + selector + " ";
+ while ( ( elem = this[ i++ ] ) ) {
+ if ( elem.nodeType === 1 &&
+ ( " " + stripAndCollapse( getClass( elem ) ) + " " ).indexOf( className ) > -1 ) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+} );
+
+
+
+
+var rreturn = /\r/g;
+
+jQuery.fn.extend( {
+ val: function( value ) {
+ var hooks, ret, isFunction,
+ elem = this[ 0 ];
+
+ if ( !arguments.length ) {
+ if ( elem ) {
+ hooks = jQuery.valHooks[ elem.type ] ||
+ jQuery.valHooks[ elem.nodeName.toLowerCase() ];
+
+ if ( hooks &&
+ "get" in hooks &&
+ ( ret = hooks.get( elem, "value" ) ) !== undefined
+ ) {
+ return ret;
+ }
+
+ ret = elem.value;
+
+ // Handle most common string cases
+ if ( typeof ret === "string" ) {
+ return ret.replace( rreturn, "" );
+ }
+
+ // Handle cases where value is null/undef or number
+ return ret == null ? "" : ret;
+ }
+
+ return;
+ }
+
+ isFunction = jQuery.isFunction( value );
+
+ return this.each( function( i ) {
+ var val;
+
+ if ( this.nodeType !== 1 ) {
+ return;
+ }
+
+ if ( isFunction ) {
+ val = value.call( this, i, jQuery( this ).val() );
+ } else {
+ val = value;
+ }
+
+ // Treat null/undefined as ""; convert numbers to string
+ if ( val == null ) {
+ val = "";
+
+ } else if ( typeof val === "number" ) {
+ val += "";
+
+ } else if ( Array.isArray( val ) ) {
+ val = jQuery.map( val, function( value ) {
+ return value == null ? "" : value + "";
+ } );
+ }
+
+ hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ];
+
+ // If set returns undefined, fall back to normal setting
+ if ( !hooks || !( "set" in hooks ) || hooks.set( this, val, "value" ) === undefined ) {
+ this.value = val;
+ }
+ } );
+ }
+} );
+
+jQuery.extend( {
+ valHooks: {
+ option: {
+ get: function( elem ) {
+
+ var val = jQuery.find.attr( elem, "value" );
+ return val != null ?
+ val :
+
+ // Support: IE <=10 - 11 only
+ // option.text throws exceptions (#14686, #14858)
+ // Strip and collapse whitespace
+ // https://html.spec.whatwg.org/#strip-and-collapse-whitespace
+ stripAndCollapse( jQuery.text( elem ) );
+ }
+ },
+ select: {
+ get: function( elem ) {
+ var value, option, i,
+ options = elem.options,
+ index = elem.selectedIndex,
+ one = elem.type === "select-one",
+ values = one ? null : [],
+ max = one ? index + 1 : options.length;
+
+ if ( index < 0 ) {
+ i = max;
+
+ } else {
+ i = one ? index : 0;
+ }
+
+ // Loop through all the selected options
+ for ( ; i < max; i++ ) {
+ option = options[ i ];
+
+ // Support: IE <=9 only
+ // IE8-9 doesn't update selected after form reset (#2551)
+ if ( ( option.selected || i === index ) &&
+
+ // Don't return options that are disabled or in a disabled optgroup
+ !option.disabled &&
+ ( !option.parentNode.disabled ||
+ !nodeName( option.parentNode, "optgroup" ) ) ) {
+
+ // Get the specific value for the option
+ value = jQuery( option ).val();
+
+ // We don't need an array for one selects
+ if ( one ) {
+ return value;
+ }
+
+ // Multi-Selects return an array
+ values.push( value );
+ }
+ }
+
+ return values;
+ },
+
+ set: function( elem, value ) {
+ var optionSet, option,
+ options = elem.options,
+ values = jQuery.makeArray( value ),
+ i = options.length;
+
+ while ( i-- ) {
+ option = options[ i ];
+
+ /* eslint-disable no-cond-assign */
+
+ if ( option.selected =
+ jQuery.inArray( jQuery.valHooks.option.get( option ), values ) > -1
+ ) {
+ optionSet = true;
+ }
+
+ /* eslint-enable no-cond-assign */
+ }
+
+ // Force browsers to behave consistently when non-matching value is set
+ if ( !optionSet ) {
+ elem.selectedIndex = -1;
+ }
+ return values;
+ }
+ }
+ }
+} );
+
+// Radios and checkboxes getter/setter
+jQuery.each( [ "radio", "checkbox" ], function() {
+ jQuery.valHooks[ this ] = {
+ set: function( elem, value ) {
+ if ( Array.isArray( value ) ) {
+ return ( elem.checked = jQuery.inArray( jQuery( elem ).val(), value ) > -1 );
+ }
+ }
+ };
+ if ( !support.checkOn ) {
+ jQuery.valHooks[ this ].get = function( elem ) {
+ return elem.getAttribute( "value" ) === null ? "on" : elem.value;
+ };
+ }
+} );
+
+
+
+
+// Return jQuery for attributes-only inclusion
+
+
+var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/;
+
+jQuery.extend( jQuery.event, {
+
+ trigger: function( event, data, elem, onlyHandlers ) {
+
+ var i, cur, tmp, bubbleType, ontype, handle, special,
+ eventPath = [ elem || document ],
+ type = hasOwn.call( event, "type" ) ? event.type : event,
+ namespaces = hasOwn.call( event, "namespace" ) ? event.namespace.split( "." ) : [];
+
+ cur = tmp = elem = elem || document;
+
+ // Don't do events on text and comment nodes
+ if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
+ return;
+ }
+
+ // focus/blur morphs to focusin/out; ensure we're not firing them right now
+ if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
+ return;
+ }
+
+ if ( type.indexOf( "." ) > -1 ) {
+
+ // Namespaced trigger; create a regexp to match event type in handle()
+ namespaces = type.split( "." );
+ type = namespaces.shift();
+ namespaces.sort();
+ }
+ ontype = type.indexOf( ":" ) < 0 && "on" + type;
+
+ // Caller can pass in a jQuery.Event object, Object, or just an event type string
+ event = event[ jQuery.expando ] ?
+ event :
+ new jQuery.Event( type, typeof event === "object" && event );
+
+ // Trigger bitmask: & 1 for native handlers; & 2 for jQuery (always true)
+ event.isTrigger = onlyHandlers ? 2 : 3;
+ event.namespace = namespaces.join( "." );
+ event.rnamespace = event.namespace ?
+ new RegExp( "(^|\\.)" + namespaces.join( "\\.(?:.*\\.|)" ) + "(\\.|$)" ) :
+ null;
+
+ // Clean up the event in case it is being reused
+ event.result = undefined;
+ if ( !event.target ) {
+ event.target = elem;
+ }
+
+ // Clone any incoming data and prepend the event, creating the handler arg list
+ data = data == null ?
+ [ event ] :
+ jQuery.makeArray( data, [ event ] );
+
+ // Allow special events to draw outside the lines
+ special = jQuery.event.special[ type ] || {};
+ if ( !onlyHandlers && special.trigger && special.trigger.apply( elem, data ) === false ) {
+ return;
+ }
+
+ // Determine event propagation path in advance, per W3C events spec (#9951)
+ // Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
+ if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {
+
+ bubbleType = special.delegateType || type;
+ if ( !rfocusMorph.test( bubbleType + type ) ) {
+ cur = cur.parentNode;
+ }
+ for ( ; cur; cur = cur.parentNode ) {
+ eventPath.push( cur );
+ tmp = cur;
+ }
+
+ // Only add window if we got to document (e.g., not plain obj or detached DOM)
+ if ( tmp === ( elem.ownerDocument || document ) ) {
+ eventPath.push( tmp.defaultView || tmp.parentWindow || window );
+ }
+ }
+
+ // Fire handlers on the event path
+ i = 0;
+ while ( ( cur = eventPath[ i++ ] ) && !event.isPropagationStopped() ) {
+
+ event.type = i > 1 ?
+ bubbleType :
+ special.bindType || type;
+
+ // jQuery handler
+ handle = ( dataPriv.get( cur, "events" ) || {} )[ event.type ] &&
+ dataPriv.get( cur, "handle" );
+ if ( handle ) {
+ handle.apply( cur, data );
+ }
+
+ // Native handler
+ handle = ontype && cur[ ontype ];
+ if ( handle && handle.apply && acceptData( cur ) ) {
+ event.result = handle.apply( cur, data );
+ if ( event.result === false ) {
+ event.preventDefault();
+ }
+ }
+ }
+ event.type = type;
+
+ // If nobody prevented the default action, do it now
+ if ( !onlyHandlers && !event.isDefaultPrevented() ) {
+
+ if ( ( !special._default ||
+ special._default.apply( eventPath.pop(), data ) === false ) &&
+ acceptData( elem ) ) {
+
+ // Call a native DOM method on the target with the same name as the event.
+ // Don't do default actions on window, that's where global variables be (#6170)
+ if ( ontype && jQuery.isFunction( elem[ type ] ) && !jQuery.isWindow( elem ) ) {
+
+ // Don't re-trigger an onFOO event when we call its FOO() method
+ tmp = elem[ ontype ];
+
+ if ( tmp ) {
+ elem[ ontype ] = null;
+ }
+
+ // Prevent re-triggering of the same event, since we already bubbled it above
+ jQuery.event.triggered = type;
+ elem[ type ]();
+ jQuery.event.triggered = undefined;
+
+ if ( tmp ) {
+ elem[ ontype ] = tmp;
+ }
+ }
+ }
+ }
+
+ return event.result;
+ },
+
+ // Piggyback on a donor event to simulate a different one
+ // Used only for `focus(in | out)` events
+ simulate: function( type, elem, event ) {
+ var e = jQuery.extend(
+ new jQuery.Event(),
+ event,
+ {
+ type: type,
+ isSimulated: true
+ }
+ );
+
+ jQuery.event.trigger( e, null, elem );
+ }
+
+} );
+
+jQuery.fn.extend( {
+
+ trigger: function( type, data ) {
+ return this.each( function() {
+ jQuery.event.trigger( type, data, this );
+ } );
+ },
+ triggerHandler: function( type, data ) {
+ var elem = this[ 0 ];
+ if ( elem ) {
+ return jQuery.event.trigger( type, data, elem, true );
+ }
+ }
+} );
+
+
+jQuery.each( ( "blur focus focusin focusout resize scroll click dblclick " +
+ "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
+ "change select submit keydown keypress keyup contextmenu" ).split( " " ),
+ function( i, name ) {
+
+ // Handle event binding
+ jQuery.fn[ name ] = function( data, fn ) {
+ return arguments.length > 0 ?
+ this.on( name, null, data, fn ) :
+ this.trigger( name );
+ };
+} );
+
+jQuery.fn.extend( {
+ hover: function( fnOver, fnOut ) {
+ return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
+ }
+} );
+
+
+
+
+support.focusin = "onfocusin" in window;
+
+
+// Support: Firefox <=44
+// Firefox doesn't have focus(in | out) events
+// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787
+//
+// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1
+// focus(in | out) events fire after focus & blur events,
+// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order
+// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857
+if ( !support.focusin ) {
+ jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) {
+
+ // Attach a single capturing handler on the document while someone wants focusin/focusout
+ var handler = function( event ) {
+ jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) );
+ };
+
+ jQuery.event.special[ fix ] = {
+ setup: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix );
+
+ if ( !attaches ) {
+ doc.addEventListener( orig, handler, true );
+ }
+ dataPriv.access( doc, fix, ( attaches || 0 ) + 1 );
+ },
+ teardown: function() {
+ var doc = this.ownerDocument || this,
+ attaches = dataPriv.access( doc, fix ) - 1;
+
+ if ( !attaches ) {
+ doc.removeEventListener( orig, handler, true );
+ dataPriv.remove( doc, fix );
+
+ } else {
+ dataPriv.access( doc, fix, attaches );
+ }
+ }
+ };
+ } );
+}
+var location = window.location;
+
+var nonce = jQuery.now();
+
+var rquery = ( /\?/ );
+
+
+
+// Cross-browser xml parsing
+jQuery.parseXML = function( data ) {
+ var xml;
+ if ( !data || typeof data !== "string" ) {
+ return null;
+ }
+
+ // Support: IE 9 - 11 only
+ // IE throws on parseFromString with invalid input.
+ try {
+ xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" );
+ } catch ( e ) {
+ xml = undefined;
+ }
+
+ if ( !xml || xml.getElementsByTagName( "parsererror" ).length ) {
+ jQuery.error( "Invalid XML: " + data );
+ }
+ return xml;
+};
+
+
+var
+ rbracket = /\[\]$/,
+ rCRLF = /\r?\n/g,
+ rsubmitterTypes = /^(?:submit|button|image|reset|file)$/i,
+ rsubmittable = /^(?:input|select|textarea|keygen)/i;
+
+function buildParams( prefix, obj, traditional, add ) {
+ var name;
+
+ if ( Array.isArray( obj ) ) {
+
+ // Serialize array item.
+ jQuery.each( obj, function( i, v ) {
+ if ( traditional || rbracket.test( prefix ) ) {
+
+ // Treat each array item as a scalar.
+ add( prefix, v );
+
+ } else {
+
+ // Item is non-scalar (array or object), encode its numeric index.
+ buildParams(
+ prefix + "[" + ( typeof v === "object" && v != null ? i : "" ) + "]",
+ v,
+ traditional,
+ add
+ );
+ }
+ } );
+
+ } else if ( !traditional && jQuery.type( obj ) === "object" ) {
+
+ // Serialize object item.
+ for ( name in obj ) {
+ buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
+ }
+
+ } else {
+
+ // Serialize scalar item.
+ add( prefix, obj );
+ }
+}
+
+// Serialize an array of form elements or a set of
+// key/values into a query string
+jQuery.param = function( a, traditional ) {
+ var prefix,
+ s = [],
+ add = function( key, valueOrFunction ) {
+
+ // If value is a function, invoke it and use its return value
+ var value = jQuery.isFunction( valueOrFunction ) ?
+ valueOrFunction() :
+ valueOrFunction;
+
+ s[ s.length ] = encodeURIComponent( key ) + "=" +
+ encodeURIComponent( value == null ? "" : value );
+ };
+
+ // If an array was passed in, assume that it is an array of form elements.
+ if ( Array.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
+
+ // Serialize the form elements
+ jQuery.each( a, function() {
+ add( this.name, this.value );
+ } );
+
+ } else {
+
+ // If traditional, encode the "old" way (the way 1.3.2 or older
+ // did it), otherwise encode params recursively.
+ for ( prefix in a ) {
+ buildParams( prefix, a[ prefix ], traditional, add );
+ }
+ }
+
+ // Return the resulting serialization
+ return s.join( "&" );
+};
+
+jQuery.fn.extend( {
+ serialize: function() {
+ return jQuery.param( this.serializeArray() );
+ },
+ serializeArray: function() {
+ return this.map( function() {
+
+ // Can add propHook for "elements" to filter or add form elements
+ var elements = jQuery.prop( this, "elements" );
+ return elements ? jQuery.makeArray( elements ) : this;
+ } )
+ .filter( function() {
+ var type = this.type;
+
+ // Use .is( ":disabled" ) so that fieldset[disabled] works
+ return this.name && !jQuery( this ).is( ":disabled" ) &&
+ rsubmittable.test( this.nodeName ) && !rsubmitterTypes.test( type ) &&
+ ( this.checked || !rcheckableType.test( type ) );
+ } )
+ .map( function( i, elem ) {
+ var val = jQuery( this ).val();
+
+ if ( val == null ) {
+ return null;
+ }
+
+ if ( Array.isArray( val ) ) {
+ return jQuery.map( val, function( val ) {
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ } );
+ }
+
+ return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
+ } ).get();
+ }
+} );
+
+
+var
+ r20 = /%20/g,
+ rhash = /#.*$/,
+ rantiCache = /([?&])_=[^&]*/,
+ rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg,
+
+ // #7653, #8125, #8152: local protocol detection
+ rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/,
+ rnoContent = /^(?:GET|HEAD)$/,
+ rprotocol = /^\/\//,
+
+ /* Prefilters
+ * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
+ * 2) These are called:
+ * - BEFORE asking for a transport
+ * - AFTER param serialization (s.data is a string if s.processData is true)
+ * 3) key is the dataType
+ * 4) the catchall symbol "*" can be used
+ * 5) execution will start with transport dataType and THEN continue down to "*" if needed
+ */
+ prefilters = {},
+
+ /* Transports bindings
+ * 1) key is the dataType
+ * 2) the catchall symbol "*" can be used
+ * 3) selection will start with transport dataType and THEN go to "*" if needed
+ */
+ transports = {},
+
+ // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
+ allTypes = "*/".concat( "*" ),
+
+ // Anchor tag for parsing the document origin
+ originAnchor = document.createElement( "a" );
+ originAnchor.href = location.href;
+
+// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
+function addToPrefiltersOrTransports( structure ) {
+
+ // dataTypeExpression is optional and defaults to "*"
+ return function( dataTypeExpression, func ) {
+
+ if ( typeof dataTypeExpression !== "string" ) {
+ func = dataTypeExpression;
+ dataTypeExpression = "*";
+ }
+
+ var dataType,
+ i = 0,
+ dataTypes = dataTypeExpression.toLowerCase().match( rnothtmlwhite ) || [];
+
+ if ( jQuery.isFunction( func ) ) {
+
+ // For each dataType in the dataTypeExpression
+ while ( ( dataType = dataTypes[ i++ ] ) ) {
+
+ // Prepend if requested
+ if ( dataType[ 0 ] === "+" ) {
+ dataType = dataType.slice( 1 ) || "*";
+ ( structure[ dataType ] = structure[ dataType ] || [] ).unshift( func );
+
+ // Otherwise append
+ } else {
+ ( structure[ dataType ] = structure[ dataType ] || [] ).push( func );
+ }
+ }
+ }
+ };
+}
+
+// Base inspection function for prefilters and transports
+function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR ) {
+
+ var inspected = {},
+ seekingTransport = ( structure === transports );
+
+ function inspect( dataType ) {
+ var selected;
+ inspected[ dataType ] = true;
+ jQuery.each( structure[ dataType ] || [], function( _, prefilterOrFactory ) {
+ var dataTypeOrTransport = prefilterOrFactory( options, originalOptions, jqXHR );
+ if ( typeof dataTypeOrTransport === "string" &&
+ !seekingTransport && !inspected[ dataTypeOrTransport ] ) {
+
+ options.dataTypes.unshift( dataTypeOrTransport );
+ inspect( dataTypeOrTransport );
+ return false;
+ } else if ( seekingTransport ) {
+ return !( selected = dataTypeOrTransport );
+ }
+ } );
+ return selected;
+ }
+
+ return inspect( options.dataTypes[ 0 ] ) || !inspected[ "*" ] && inspect( "*" );
+}
+
+// A special extend for ajax options
+// that takes "flat" options (not to be deep extended)
+// Fixes #9887
+function ajaxExtend( target, src ) {
+ var key, deep,
+ flatOptions = jQuery.ajaxSettings.flatOptions || {};
+
+ for ( key in src ) {
+ if ( src[ key ] !== undefined ) {
+ ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
+ }
+ }
+ if ( deep ) {
+ jQuery.extend( true, target, deep );
+ }
+
+ return target;
+}
+
+/* Handles responses to an ajax request:
+ * - finds the right dataType (mediates between content-type and expected dataType)
+ * - returns the corresponding response
+ */
+function ajaxHandleResponses( s, jqXHR, responses ) {
+
+ var ct, type, finalDataType, firstDataType,
+ contents = s.contents,
+ dataTypes = s.dataTypes;
+
+ // Remove auto dataType and get content-type in the process
+ while ( dataTypes[ 0 ] === "*" ) {
+ dataTypes.shift();
+ if ( ct === undefined ) {
+ ct = s.mimeType || jqXHR.getResponseHeader( "Content-Type" );
+ }
+ }
+
+ // Check if we're dealing with a known content-type
+ if ( ct ) {
+ for ( type in contents ) {
+ if ( contents[ type ] && contents[ type ].test( ct ) ) {
+ dataTypes.unshift( type );
+ break;
+ }
+ }
+ }
+
+ // Check to see if we have a response for the expected dataType
+ if ( dataTypes[ 0 ] in responses ) {
+ finalDataType = dataTypes[ 0 ];
+ } else {
+
+ // Try convertible dataTypes
+ for ( type in responses ) {
+ if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[ 0 ] ] ) {
+ finalDataType = type;
+ break;
+ }
+ if ( !firstDataType ) {
+ firstDataType = type;
+ }
+ }
+
+ // Or just use first one
+ finalDataType = finalDataType || firstDataType;
+ }
+
+ // If we found a dataType
+ // We add the dataType to the list if needed
+ // and return the corresponding response
+ if ( finalDataType ) {
+ if ( finalDataType !== dataTypes[ 0 ] ) {
+ dataTypes.unshift( finalDataType );
+ }
+ return responses[ finalDataType ];
+ }
+}
+
+/* Chain conversions given the request and the original response
+ * Also sets the responseXXX fields on the jqXHR instance
+ */
+function ajaxConvert( s, response, jqXHR, isSuccess ) {
+ var conv2, current, conv, tmp, prev,
+ converters = {},
+
+ // Work with a copy of dataTypes in case we need to modify it for conversion
+ dataTypes = s.dataTypes.slice();
+
+ // Create converters map with lowercased keys
+ if ( dataTypes[ 1 ] ) {
+ for ( conv in s.converters ) {
+ converters[ conv.toLowerCase() ] = s.converters[ conv ];
+ }
+ }
+
+ current = dataTypes.shift();
+
+ // Convert to each sequential dataType
+ while ( current ) {
+
+ if ( s.responseFields[ current ] ) {
+ jqXHR[ s.responseFields[ current ] ] = response;
+ }
+
+ // Apply the dataFilter if provided
+ if ( !prev && isSuccess && s.dataFilter ) {
+ response = s.dataFilter( response, s.dataType );
+ }
+
+ prev = current;
+ current = dataTypes.shift();
+
+ if ( current ) {
+
+ // There's only work to do if current dataType is non-auto
+ if ( current === "*" ) {
+
+ current = prev;
+
+ // Convert response if prev dataType is non-auto and differs from current
+ } else if ( prev !== "*" && prev !== current ) {
+
+ // Seek a direct converter
+ conv = converters[ prev + " " + current ] || converters[ "* " + current ];
+
+ // If none found, seek a pair
+ if ( !conv ) {
+ for ( conv2 in converters ) {
+
+ // If conv2 outputs current
+ tmp = conv2.split( " " );
+ if ( tmp[ 1 ] === current ) {
+
+ // If prev can be converted to accepted input
+ conv = converters[ prev + " " + tmp[ 0 ] ] ||
+ converters[ "* " + tmp[ 0 ] ];
+ if ( conv ) {
+
+ // Condense equivalence converters
+ if ( conv === true ) {
+ conv = converters[ conv2 ];
+
+ // Otherwise, insert the intermediate dataType
+ } else if ( converters[ conv2 ] !== true ) {
+ current = tmp[ 0 ];
+ dataTypes.unshift( tmp[ 1 ] );
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ // Apply converter (if not an equivalence)
+ if ( conv !== true ) {
+
+ // Unless errors are allowed to bubble, catch and return them
+ if ( conv && s.throws ) {
+ response = conv( response );
+ } else {
+ try {
+ response = conv( response );
+ } catch ( e ) {
+ return {
+ state: "parsererror",
+ error: conv ? e : "No conversion from " + prev + " to " + current
+ };
+ }
+ }
+ }
+ }
+ }
+ }
+
+ return { state: "success", data: response };
+}
+
+jQuery.extend( {
+
+ // Counter for holding the number of active queries
+ active: 0,
+
+ // Last-Modified header cache for next request
+ lastModified: {},
+ etag: {},
+
+ ajaxSettings: {
+ url: location.href,
+ type: "GET",
+ isLocal: rlocalProtocol.test( location.protocol ),
+ global: true,
+ processData: true,
+ async: true,
+ contentType: "application/x-www-form-urlencoded; charset=UTF-8",
+
+ /*
+ timeout: 0,
+ data: null,
+ dataType: null,
+ username: null,
+ password: null,
+ cache: null,
+ throws: false,
+ traditional: false,
+ headers: {},
+ */
+
+ accepts: {
+ "*": allTypes,
+ text: "text/plain",
+ html: "text/html",
+ xml: "application/xml, text/xml",
+ json: "application/json, text/javascript"
+ },
+
+ contents: {
+ xml: /\bxml\b/,
+ html: /\bhtml/,
+ json: /\bjson\b/
+ },
+
+ responseFields: {
+ xml: "responseXML",
+ text: "responseText",
+ json: "responseJSON"
+ },
+
+ // Data converters
+ // Keys separate source (or catchall "*") and destination types with a single space
+ converters: {
+
+ // Convert anything to text
+ "* text": String,
+
+ // Text to html (true = no transformation)
+ "text html": true,
+
+ // Evaluate text as a json expression
+ "text json": JSON.parse,
+
+ // Parse text as xml
+ "text xml": jQuery.parseXML
+ },
+
+ // For options that shouldn't be deep extended:
+ // you can add your own custom options here if
+ // and when you create one that shouldn't be
+ // deep extended (see ajaxExtend)
+ flatOptions: {
+ url: true,
+ context: true
+ }
+ },
+
+ // Creates a full fledged settings object into target
+ // with both ajaxSettings and settings fields.
+ // If target is omitted, writes into ajaxSettings.
+ ajaxSetup: function( target, settings ) {
+ return settings ?
+
+ // Building a settings object
+ ajaxExtend( ajaxExtend( target, jQuery.ajaxSettings ), settings ) :
+
+ // Extending ajaxSettings
+ ajaxExtend( jQuery.ajaxSettings, target );
+ },
+
+ ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
+ ajaxTransport: addToPrefiltersOrTransports( transports ),
+
+ // Main method
+ ajax: function( url, options ) {
+
+ // If url is an object, simulate pre-1.5 signature
+ if ( typeof url === "object" ) {
+ options = url;
+ url = undefined;
+ }
+
+ // Force options to be an object
+ options = options || {};
+
+ var transport,
+
+ // URL without anti-cache param
+ cacheURL,
+
+ // Response headers
+ responseHeadersString,
+ responseHeaders,
+
+ // timeout handle
+ timeoutTimer,
+
+ // Url cleanup var
+ urlAnchor,
+
+ // Request state (becomes false upon send and true upon completion)
+ completed,
+
+ // To know if global events are to be dispatched
+ fireGlobals,
+
+ // Loop variable
+ i,
+
+ // uncached part of the url
+ uncached,
+
+ // Create the final options object
+ s = jQuery.ajaxSetup( {}, options ),
+
+ // Callbacks context
+ callbackContext = s.context || s,
+
+ // Context for global events is callbackContext if it is a DOM node or jQuery collection
+ globalEventContext = s.context &&
+ ( callbackContext.nodeType || callbackContext.jquery ) ?
+ jQuery( callbackContext ) :
+ jQuery.event,
+
+ // Deferreds
+ deferred = jQuery.Deferred(),
+ completeDeferred = jQuery.Callbacks( "once memory" ),
+
+ // Status-dependent callbacks
+ statusCode = s.statusCode || {},
+
+ // Headers (they are sent all at once)
+ requestHeaders = {},
+ requestHeadersNames = {},
+
+ // Default abort message
+ strAbort = "canceled",
+
+ // Fake xhr
+ jqXHR = {
+ readyState: 0,
+
+ // Builds headers hashtable if needed
+ getResponseHeader: function( key ) {
+ var match;
+ if ( completed ) {
+ if ( !responseHeaders ) {
+ responseHeaders = {};
+ while ( ( match = rheaders.exec( responseHeadersString ) ) ) {
+ responseHeaders[ match[ 1 ].toLowerCase() ] = match[ 2 ];
+ }
+ }
+ match = responseHeaders[ key.toLowerCase() ];
+ }
+ return match == null ? null : match;
+ },
+
+ // Raw string
+ getAllResponseHeaders: function() {
+ return completed ? responseHeadersString : null;
+ },
+
+ // Caches the header
+ setRequestHeader: function( name, value ) {
+ if ( completed == null ) {
+ name = requestHeadersNames[ name.toLowerCase() ] =
+ requestHeadersNames[ name.toLowerCase() ] || name;
+ requestHeaders[ name ] = value;
+ }
+ return this;
+ },
+
+ // Overrides response content-type header
+ overrideMimeType: function( type ) {
+ if ( completed == null ) {
+ s.mimeType = type;
+ }
+ return this;
+ },
+
+ // Status-dependent callbacks
+ statusCode: function( map ) {
+ var code;
+ if ( map ) {
+ if ( completed ) {
+
+ // Execute the appropriate callbacks
+ jqXHR.always( map[ jqXHR.status ] );
+ } else {
+
+ // Lazy-add the new callbacks in a way that preserves old ones
+ for ( code in map ) {
+ statusCode[ code ] = [ statusCode[ code ], map[ code ] ];
+ }
+ }
+ }
+ return this;
+ },
+
+ // Cancel the request
+ abort: function( statusText ) {
+ var finalText = statusText || strAbort;
+ if ( transport ) {
+ transport.abort( finalText );
+ }
+ done( 0, finalText );
+ return this;
+ }
+ };
+
+ // Attach deferreds
+ deferred.promise( jqXHR );
+
+ // Add protocol if not provided (prefilters might expect it)
+ // Handle falsy url in the settings object (#10093: consistency with old signature)
+ // We also use the url parameter if available
+ s.url = ( ( url || s.url || location.href ) + "" )
+ .replace( rprotocol, location.protocol + "//" );
+
+ // Alias method option to type as per ticket #12004
+ s.type = options.method || options.type || s.method || s.type;
+
+ // Extract dataTypes list
+ s.dataTypes = ( s.dataType || "*" ).toLowerCase().match( rnothtmlwhite ) || [ "" ];
+
+ // A cross-domain request is in order when the origin doesn't match the current origin.
+ if ( s.crossDomain == null ) {
+ urlAnchor = document.createElement( "a" );
+
+ // Support: IE <=8 - 11, Edge 12 - 13
+ // IE throws exception on accessing the href property if url is malformed,
+ // e.g. http://example.com:80x/
+ try {
+ urlAnchor.href = s.url;
+
+ // Support: IE <=8 - 11 only
+ // Anchor's host property isn't correctly set when s.url is relative
+ urlAnchor.href = urlAnchor.href;
+ s.crossDomain = originAnchor.protocol + "//" + originAnchor.host !==
+ urlAnchor.protocol + "//" + urlAnchor.host;
+ } catch ( e ) {
+
+ // If there is an error parsing the URL, assume it is crossDomain,
+ // it can be rejected by the transport if it is invalid
+ s.crossDomain = true;
+ }
+ }
+
+ // Convert data if not already a string
+ if ( s.data && s.processData && typeof s.data !== "string" ) {
+ s.data = jQuery.param( s.data, s.traditional );
+ }
+
+ // Apply prefilters
+ inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
+
+ // If request was aborted inside a prefilter, stop there
+ if ( completed ) {
+ return jqXHR;
+ }
+
+ // We can fire global events as of now if asked to
+ // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118)
+ fireGlobals = jQuery.event && s.global;
+
+ // Watch for a new set of requests
+ if ( fireGlobals && jQuery.active++ === 0 ) {
+ jQuery.event.trigger( "ajaxStart" );
+ }
+
+ // Uppercase the type
+ s.type = s.type.toUpperCase();
+
+ // Determine if request has content
+ s.hasContent = !rnoContent.test( s.type );
+
+ // Save the URL in case we're toying with the If-Modified-Since
+ // and/or If-None-Match header later on
+ // Remove hash to simplify url manipulation
+ cacheURL = s.url.replace( rhash, "" );
+
+ // More options handling for requests with no content
+ if ( !s.hasContent ) {
+
+ // Remember the hash so we can put it back
+ uncached = s.url.slice( cacheURL.length );
+
+ // If data is available, append data to url
+ if ( s.data ) {
+ cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data;
+
+ // #9682: remove data so that it's not used in an eventual retry
+ delete s.data;
+ }
+
+ // Add or update anti-cache param if needed
+ if ( s.cache === false ) {
+ cacheURL = cacheURL.replace( rantiCache, "$1" );
+ uncached = ( rquery.test( cacheURL ) ? "&" : "?" ) + "_=" + ( nonce++ ) + uncached;
+ }
+
+ // Put hash and anti-cache on the URL that will be requested (gh-1732)
+ s.url = cacheURL + uncached;
+
+ // Change '%20' to '+' if this is encoded form body content (gh-2658)
+ } else if ( s.data && s.processData &&
+ ( s.contentType || "" ).indexOf( "application/x-www-form-urlencoded" ) === 0 ) {
+ s.data = s.data.replace( r20, "+" );
+ }
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ if ( jQuery.lastModified[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ cacheURL ] );
+ }
+ if ( jQuery.etag[ cacheURL ] ) {
+ jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ cacheURL ] );
+ }
+ }
+
+ // Set the correct header, if data is being sent
+ if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
+ jqXHR.setRequestHeader( "Content-Type", s.contentType );
+ }
+
+ // Set the Accepts header for the server, depending on the dataType
+ jqXHR.setRequestHeader(
+ "Accept",
+ s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[ 0 ] ] ?
+ s.accepts[ s.dataTypes[ 0 ] ] +
+ ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) :
+ s.accepts[ "*" ]
+ );
+
+ // Check for headers option
+ for ( i in s.headers ) {
+ jqXHR.setRequestHeader( i, s.headers[ i ] );
+ }
+
+ // Allow custom headers/mimetypes and early abort
+ if ( s.beforeSend &&
+ ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || completed ) ) {
+
+ // Abort if not done already and return
+ return jqXHR.abort();
+ }
+
+ // Aborting is no longer a cancellation
+ strAbort = "abort";
+
+ // Install callbacks on deferreds
+ completeDeferred.add( s.complete );
+ jqXHR.done( s.success );
+ jqXHR.fail( s.error );
+
+ // Get transport
+ transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
+
+ // If no transport, we auto-abort
+ if ( !transport ) {
+ done( -1, "No Transport" );
+ } else {
+ jqXHR.readyState = 1;
+
+ // Send global event
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
+ }
+
+ // If request was aborted inside ajaxSend, stop there
+ if ( completed ) {
+ return jqXHR;
+ }
+
+ // Timeout
+ if ( s.async && s.timeout > 0 ) {
+ timeoutTimer = window.setTimeout( function() {
+ jqXHR.abort( "timeout" );
+ }, s.timeout );
+ }
+
+ try {
+ completed = false;
+ transport.send( requestHeaders, done );
+ } catch ( e ) {
+
+ // Rethrow post-completion exceptions
+ if ( completed ) {
+ throw e;
+ }
+
+ // Propagate others as results
+ done( -1, e );
+ }
+ }
+
+ // Callback for when everything is done
+ function done( status, nativeStatusText, responses, headers ) {
+ var isSuccess, success, error, response, modified,
+ statusText = nativeStatusText;
+
+ // Ignore repeat invocations
+ if ( completed ) {
+ return;
+ }
+
+ completed = true;
+
+ // Clear timeout if it exists
+ if ( timeoutTimer ) {
+ window.clearTimeout( timeoutTimer );
+ }
+
+ // Dereference transport for early garbage collection
+ // (no matter how long the jqXHR object will be used)
+ transport = undefined;
+
+ // Cache response headers
+ responseHeadersString = headers || "";
+
+ // Set readyState
+ jqXHR.readyState = status > 0 ? 4 : 0;
+
+ // Determine if successful
+ isSuccess = status >= 200 && status < 300 || status === 304;
+
+ // Get response data
+ if ( responses ) {
+ response = ajaxHandleResponses( s, jqXHR, responses );
+ }
+
+ // Convert no matter what (that way responseXXX fields are always set)
+ response = ajaxConvert( s, response, jqXHR, isSuccess );
+
+ // If successful, handle type chaining
+ if ( isSuccess ) {
+
+ // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
+ if ( s.ifModified ) {
+ modified = jqXHR.getResponseHeader( "Last-Modified" );
+ if ( modified ) {
+ jQuery.lastModified[ cacheURL ] = modified;
+ }
+ modified = jqXHR.getResponseHeader( "etag" );
+ if ( modified ) {
+ jQuery.etag[ cacheURL ] = modified;
+ }
+ }
+
+ // if no content
+ if ( status === 204 || s.type === "HEAD" ) {
+ statusText = "nocontent";
+
+ // if not modified
+ } else if ( status === 304 ) {
+ statusText = "notmodified";
+
+ // If we have data, let's convert it
+ } else {
+ statusText = response.state;
+ success = response.data;
+ error = response.error;
+ isSuccess = !error;
+ }
+ } else {
+
+ // Extract error from statusText and normalize for non-aborts
+ error = statusText;
+ if ( status || !statusText ) {
+ statusText = "error";
+ if ( status < 0 ) {
+ status = 0;
+ }
+ }
+ }
+
+ // Set data for the fake xhr object
+ jqXHR.status = status;
+ jqXHR.statusText = ( nativeStatusText || statusText ) + "";
+
+ // Success/Error
+ if ( isSuccess ) {
+ deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
+ } else {
+ deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
+ }
+
+ // Status-dependent callbacks
+ jqXHR.statusCode( statusCode );
+ statusCode = undefined;
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( isSuccess ? "ajaxSuccess" : "ajaxError",
+ [ jqXHR, s, isSuccess ? success : error ] );
+ }
+
+ // Complete
+ completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] );
+
+ if ( fireGlobals ) {
+ globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] );
+
+ // Handle the global AJAX counter
+ if ( !( --jQuery.active ) ) {
+ jQuery.event.trigger( "ajaxStop" );
+ }
+ }
+ }
+
+ return jqXHR;
+ },
+
+ getJSON: function( url, data, callback ) {
+ return jQuery.get( url, data, callback, "json" );
+ },
+
+ getScript: function( url, callback ) {
+ return jQuery.get( url, undefined, callback, "script" );
+ }
+} );
+
+jQuery.each( [ "get", "post" ], function( i, method ) {
+ jQuery[ method ] = function( url, data, callback, type ) {
+
+ // Shift arguments if data argument was omitted
+ if ( jQuery.isFunction( data ) ) {
+ type = type || callback;
+ callback = data;
+ data = undefined;
+ }
+
+ // The url can be an options object (which then must have .url)
+ return jQuery.ajax( jQuery.extend( {
+ url: url,
+ type: method,
+ dataType: type,
+ data: data,
+ success: callback
+ }, jQuery.isPlainObject( url ) && url ) );
+ };
+} );
+
+
+jQuery._evalUrl = function( url ) {
+ return jQuery.ajax( {
+ url: url,
+
+ // Make this explicit, since user can override this through ajaxSetup (#11264)
+ type: "GET",
+ dataType: "script",
+ cache: true,
+ async: false,
+ global: false,
+ "throws": true
+ } );
+};
+
+
+jQuery.fn.extend( {
+ wrapAll: function( html ) {
+ var wrap;
+
+ if ( this[ 0 ] ) {
+ if ( jQuery.isFunction( html ) ) {
+ html = html.call( this[ 0 ] );
+ }
+
+ // The elements to wrap the target around
+ wrap = jQuery( html, this[ 0 ].ownerDocument ).eq( 0 ).clone( true );
+
+ if ( this[ 0 ].parentNode ) {
+ wrap.insertBefore( this[ 0 ] );
+ }
+
+ wrap.map( function() {
+ var elem = this;
+
+ while ( elem.firstElementChild ) {
+ elem = elem.firstElementChild;
+ }
+
+ return elem;
+ } ).append( this );
+ }
+
+ return this;
+ },
+
+ wrapInner: function( html ) {
+ if ( jQuery.isFunction( html ) ) {
+ return this.each( function( i ) {
+ jQuery( this ).wrapInner( html.call( this, i ) );
+ } );
+ }
+
+ return this.each( function() {
+ var self = jQuery( this ),
+ contents = self.contents();
+
+ if ( contents.length ) {
+ contents.wrapAll( html );
+
+ } else {
+ self.append( html );
+ }
+ } );
+ },
+
+ wrap: function( html ) {
+ var isFunction = jQuery.isFunction( html );
+
+ return this.each( function( i ) {
+ jQuery( this ).wrapAll( isFunction ? html.call( this, i ) : html );
+ } );
+ },
+
+ unwrap: function( selector ) {
+ this.parent( selector ).not( "body" ).each( function() {
+ jQuery( this ).replaceWith( this.childNodes );
+ } );
+ return this;
+ }
+} );
+
+
+jQuery.expr.pseudos.hidden = function( elem ) {
+ return !jQuery.expr.pseudos.visible( elem );
+};
+jQuery.expr.pseudos.visible = function( elem ) {
+ return !!( elem.offsetWidth || elem.offsetHeight || elem.getClientRects().length );
+};
+
+
+
+
+jQuery.ajaxSettings.xhr = function() {
+ try {
+ return new window.XMLHttpRequest();
+ } catch ( e ) {}
+};
+
+var xhrSuccessStatus = {
+
+ // File protocol always yields status code 0, assume 200
+ 0: 200,
+
+ // Support: IE <=9 only
+ // #1450: sometimes IE returns 1223 when it should be 204
+ 1223: 204
+ },
+ xhrSupported = jQuery.ajaxSettings.xhr();
+
+support.cors = !!xhrSupported && ( "withCredentials" in xhrSupported );
+support.ajax = xhrSupported = !!xhrSupported;
+
+jQuery.ajaxTransport( function( options ) {
+ var callback, errorCallback;
+
+ // Cross domain only allowed if supported through XMLHttpRequest
+ if ( support.cors || xhrSupported && !options.crossDomain ) {
+ return {
+ send: function( headers, complete ) {
+ var i,
+ xhr = options.xhr();
+
+ xhr.open(
+ options.type,
+ options.url,
+ options.async,
+ options.username,
+ options.password
+ );
+
+ // Apply custom fields if provided
+ if ( options.xhrFields ) {
+ for ( i in options.xhrFields ) {
+ xhr[ i ] = options.xhrFields[ i ];
+ }
+ }
+
+ // Override mime type if needed
+ if ( options.mimeType && xhr.overrideMimeType ) {
+ xhr.overrideMimeType( options.mimeType );
+ }
+
+ // X-Requested-With header
+ // For cross-domain requests, seeing as conditions for a preflight are
+ // akin to a jigsaw puzzle, we simply never set it to be sure.
+ // (it can always be set on a per-request basis or even using ajaxSetup)
+ // For same-domain requests, won't change header if already provided.
+ if ( !options.crossDomain && !headers[ "X-Requested-With" ] ) {
+ headers[ "X-Requested-With" ] = "XMLHttpRequest";
+ }
+
+ // Set headers
+ for ( i in headers ) {
+ xhr.setRequestHeader( i, headers[ i ] );
+ }
+
+ // Callback
+ callback = function( type ) {
+ return function() {
+ if ( callback ) {
+ callback = errorCallback = xhr.onload =
+ xhr.onerror = xhr.onabort = xhr.onreadystatechange = null;
+
+ if ( type === "abort" ) {
+ xhr.abort();
+ } else if ( type === "error" ) {
+
+ // Support: IE <=9 only
+ // On a manual native abort, IE9 throws
+ // errors on any property access that is not readyState
+ if ( typeof xhr.status !== "number" ) {
+ complete( 0, "error" );
+ } else {
+ complete(
+
+ // File: protocol always yields status 0; see #8605, #14207
+ xhr.status,
+ xhr.statusText
+ );
+ }
+ } else {
+ complete(
+ xhrSuccessStatus[ xhr.status ] || xhr.status,
+ xhr.statusText,
+
+ // Support: IE <=9 only
+ // IE9 has no XHR2 but throws on binary (trac-11426)
+ // For XHR2 non-text, let the caller handle it (gh-2498)
+ ( xhr.responseType || "text" ) !== "text" ||
+ typeof xhr.responseText !== "string" ?
+ { binary: xhr.response } :
+ { text: xhr.responseText },
+ xhr.getAllResponseHeaders()
+ );
+ }
+ }
+ };
+ };
+
+ // Listen to events
+ xhr.onload = callback();
+ errorCallback = xhr.onerror = callback( "error" );
+
+ // Support: IE 9 only
+ // Use onreadystatechange to replace onabort
+ // to handle uncaught aborts
+ if ( xhr.onabort !== undefined ) {
+ xhr.onabort = errorCallback;
+ } else {
+ xhr.onreadystatechange = function() {
+
+ // Check readyState before timeout as it changes
+ if ( xhr.readyState === 4 ) {
+
+ // Allow onerror to be called first,
+ // but that will not handle a native abort
+ // Also, save errorCallback to a variable
+ // as xhr.onerror cannot be accessed
+ window.setTimeout( function() {
+ if ( callback ) {
+ errorCallback();
+ }
+ } );
+ }
+ };
+ }
+
+ // Create the abort callback
+ callback = callback( "abort" );
+
+ try {
+
+ // Do send the request (this may raise an exception)
+ xhr.send( options.hasContent && options.data || null );
+ } catch ( e ) {
+
+ // #14683: Only rethrow if this hasn't been notified as an error yet
+ if ( callback ) {
+ throw e;
+ }
+ }
+ },
+
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+} );
+
+
+
+
+// Prevent auto-execution of scripts when no explicit dataType was provided (See gh-2432)
+jQuery.ajaxPrefilter( function( s ) {
+ if ( s.crossDomain ) {
+ s.contents.script = false;
+ }
+} );
+
+// Install script dataType
+jQuery.ajaxSetup( {
+ accepts: {
+ script: "text/javascript, application/javascript, " +
+ "application/ecmascript, application/x-ecmascript"
+ },
+ contents: {
+ script: /\b(?:java|ecma)script\b/
+ },
+ converters: {
+ "text script": function( text ) {
+ jQuery.globalEval( text );
+ return text;
+ }
+ }
+} );
+
+// Handle cache's special case and crossDomain
+jQuery.ajaxPrefilter( "script", function( s ) {
+ if ( s.cache === undefined ) {
+ s.cache = false;
+ }
+ if ( s.crossDomain ) {
+ s.type = "GET";
+ }
+} );
+
+// Bind script tag hack transport
+jQuery.ajaxTransport( "script", function( s ) {
+
+ // This transport only deals with cross domain requests
+ if ( s.crossDomain ) {
+ var script, callback;
+ return {
+ send: function( _, complete ) {
+ script = jQuery( "<script>" ).prop( {
+ charset: s.scriptCharset,
+ src: s.url
+ } ).on(
+ "load error",
+ callback = function( evt ) {
+ script.remove();
+ callback = null;
+ if ( evt ) {
+ complete( evt.type === "error" ? 404 : 200, evt.type );
+ }
+ }
+ );
+
+ // Use native DOM manipulation to avoid our domManip AJAX trickery
+ document.head.appendChild( script[ 0 ] );
+ },
+ abort: function() {
+ if ( callback ) {
+ callback();
+ }
+ }
+ };
+ }
+} );
+
+
+
+
+var oldCallbacks = [],
+ rjsonp = /(=)\?(?=&|$)|\?\?/;
+
+// Default jsonp settings
+jQuery.ajaxSetup( {
+ jsonp: "callback",
+ jsonpCallback: function() {
+ var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) );
+ this[ callback ] = true;
+ return callback;
+ }
+} );
+
+// Detect, normalize options and install callbacks for jsonp requests
+jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
+
+ var callbackName, overwritten, responseContainer,
+ jsonProp = s.jsonp !== false && ( rjsonp.test( s.url ) ?
+ "url" :
+ typeof s.data === "string" &&
+ ( s.contentType || "" )
+ .indexOf( "application/x-www-form-urlencoded" ) === 0 &&
+ rjsonp.test( s.data ) && "data"
+ );
+
+ // Handle iff the expected data type is "jsonp" or we have a parameter to set
+ if ( jsonProp || s.dataTypes[ 0 ] === "jsonp" ) {
+
+ // Get callback name, remembering preexisting value associated with it
+ callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ?
+ s.jsonpCallback() :
+ s.jsonpCallback;
+
+ // Insert callback into url or form data
+ if ( jsonProp ) {
+ s[ jsonProp ] = s[ jsonProp ].replace( rjsonp, "$1" + callbackName );
+ } else if ( s.jsonp !== false ) {
+ s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName;
+ }
+
+ // Use data converter to retrieve json after script execution
+ s.converters[ "script json" ] = function() {
+ if ( !responseContainer ) {
+ jQuery.error( callbackName + " was not called" );
+ }
+ return responseContainer[ 0 ];
+ };
+
+ // Force json dataType
+ s.dataTypes[ 0 ] = "json";
+
+ // Install callback
+ overwritten = window[ callbackName ];
+ window[ callbackName ] = function() {
+ responseContainer = arguments;
+ };
+
+ // Clean-up function (fires after converters)
+ jqXHR.always( function() {
+
+ // If previous value didn't exist - remove it
+ if ( overwritten === undefined ) {
+ jQuery( window ).removeProp( callbackName );
+
+ // Otherwise restore preexisting value
+ } else {
+ window[ callbackName ] = overwritten;
+ }
+
+ // Save back as free
+ if ( s[ callbackName ] ) {
+
+ // Make sure that re-using the options doesn't screw things around
+ s.jsonpCallback = originalSettings.jsonpCallback;
+
+ // Save the callback name for future use
+ oldCallbacks.push( callbackName );
+ }
+
+ // Call if it was a function and we have a response
+ if ( responseContainer && jQuery.isFunction( overwritten ) ) {
+ overwritten( responseContainer[ 0 ] );
+ }
+
+ responseContainer = overwritten = undefined;
+ } );
+
+ // Delegate to script
+ return "script";
+ }
+} );
+
+
+
+
+// Support: Safari 8 only
+// In Safari 8 documents created via document.implementation.createHTMLDocument
+// collapse sibling forms: the second one becomes a child of the first one.
+// Because of that, this security measure has to be disabled in Safari 8.
+// https://bugs.webkit.org/show_bug.cgi?id=137337
+support.createHTMLDocument = ( function() {
+ var body = document.implementation.createHTMLDocument( "" ).body;
+ body.innerHTML = "<form></form><form></form>";
+ return body.childNodes.length === 2;
+} )();
+
+
+// Argument "data" should be string of html
+// context (optional): If specified, the fragment will be created in this context,
+// defaults to document
+// keepScripts (optional): If true, will include scripts passed in the html string
+jQuery.parseHTML = function( data, context, keepScripts ) {
+ if ( typeof data !== "string" ) {
+ return [];
+ }
+ if ( typeof context === "boolean" ) {
+ keepScripts = context;
+ context = false;
+ }
+
+ var base, parsed, scripts;
+
+ if ( !context ) {
+
+ // Stop scripts or inline event handlers from being executed immediately
+ // by using document.implementation
+ if ( support.createHTMLDocument ) {
+ context = document.implementation.createHTMLDocument( "" );
+
+ // Set the base href for the created document
+ // so any parsed elements with URLs
+ // are based on the document's URL (gh-2965)
+ base = context.createElement( "base" );
+ base.href = document.location.href;
+ context.head.appendChild( base );
+ } else {
+ context = document;
+ }
+ }
+
+ parsed = rsingleTag.exec( data );
+ scripts = !keepScripts && [];
+
+ // Single tag
+ if ( parsed ) {
+ return [ context.createElement( parsed[ 1 ] ) ];
+ }
+
+ parsed = buildFragment( [ data ], context, scripts );
+
+ if ( scripts && scripts.length ) {
+ jQuery( scripts ).remove();
+ }
+
+ return jQuery.merge( [], parsed.childNodes );
+};
+
+
+/**
+ * Load a url into a page
+ */
+jQuery.fn.load = function( url, params, callback ) {
+ var selector, type, response,
+ self = this,
+ off = url.indexOf( " " );
+
+ if ( off > -1 ) {
+ selector = stripAndCollapse( url.slice( off ) );
+ url = url.slice( 0, off );
+ }
+
+ // If it's a function
+ if ( jQuery.isFunction( params ) ) {
+
+ // We assume that it's the callback
+ callback = params;
+ params = undefined;
+
+ // Otherwise, build a param string
+ } else if ( params && typeof params === "object" ) {
+ type = "POST";
+ }
+
+ // If we have elements to modify, make the request
+ if ( self.length > 0 ) {
+ jQuery.ajax( {
+ url: url,
+
+ // If "type" variable is undefined, then "GET" method will be used.
+ // Make value of this field explicit since
+ // user can override it through ajaxSetup method
+ type: type || "GET",
+ dataType: "html",
+ data: params
+ } ).done( function( responseText ) {
+
+ // Save response for use in complete callback
+ response = arguments;
+
+ self.html( selector ?
+
+ // If a selector was specified, locate the right elements in a dummy div
+ // Exclude scripts to avoid IE 'Permission Denied' errors
+ jQuery( "<div>" ).append( jQuery.parseHTML( responseText ) ).find( selector ) :
+
+ // Otherwise use the full result
+ responseText );
+
+ // If the request succeeds, this function gets "data", "status", "jqXHR"
+ // but they are ignored because response was set above.
+ // If it fails, this function gets "jqXHR", "status", "error"
+ } ).always( callback && function( jqXHR, status ) {
+ self.each( function() {
+ callback.apply( this, response || [ jqXHR.responseText, status, jqXHR ] );
+ } );
+ } );
+ }
+
+ return this;
+};
+
+
+
+
+// Attach a bunch of functions for handling common AJAX events
+jQuery.each( [
+ "ajaxStart",
+ "ajaxStop",
+ "ajaxComplete",
+ "ajaxError",
+ "ajaxSuccess",
+ "ajaxSend"
+], function( i, type ) {
+ jQuery.fn[ type ] = function( fn ) {
+ return this.on( type, fn );
+ };
+} );
+
+
+
+
+jQuery.expr.pseudos.animated = function( elem ) {
+ return jQuery.grep( jQuery.timers, function( fn ) {
+ return elem === fn.elem;
+ } ).length;
+};
+
+
+
+
+jQuery.offset = {
+ setOffset: function( elem, options, i ) {
+ var curPosition, curLeft, curCSSTop, curTop, curOffset, curCSSLeft, calculatePosition,
+ position = jQuery.css( elem, "position" ),
+ curElem = jQuery( elem ),
+ props = {};
+
+ // Set position first, in-case top/left are set even on static elem
+ if ( position === "static" ) {
+ elem.style.position = "relative";
+ }
+
+ curOffset = curElem.offset();
+ curCSSTop = jQuery.css( elem, "top" );
+ curCSSLeft = jQuery.css( elem, "left" );
+ calculatePosition = ( position === "absolute" || position === "fixed" ) &&
+ ( curCSSTop + curCSSLeft ).indexOf( "auto" ) > -1;
+
+ // Need to be able to calculate position if either
+ // top or left is auto and position is either absolute or fixed
+ if ( calculatePosition ) {
+ curPosition = curElem.position();
+ curTop = curPosition.top;
+ curLeft = curPosition.left;
+
+ } else {
+ curTop = parseFloat( curCSSTop ) || 0;
+ curLeft = parseFloat( curCSSLeft ) || 0;
+ }
+
+ if ( jQuery.isFunction( options ) ) {
+
+ // Use jQuery.extend here to allow modification of coordinates argument (gh-1848)
+ options = options.call( elem, i, jQuery.extend( {}, curOffset ) );
+ }
+
+ if ( options.top != null ) {
+ props.top = ( options.top - curOffset.top ) + curTop;
+ }
+ if ( options.left != null ) {
+ props.left = ( options.left - curOffset.left ) + curLeft;
+ }
+
+ if ( "using" in options ) {
+ options.using.call( elem, props );
+
+ } else {
+ curElem.css( props );
+ }
+ }
+};
+
+jQuery.fn.extend( {
+ offset: function( options ) {
+
+ // Preserve chaining for setter
+ if ( arguments.length ) {
+ return options === undefined ?
+ this :
+ this.each( function( i ) {
+ jQuery.offset.setOffset( this, options, i );
+ } );
+ }
+
+ var doc, docElem, rect, win,
+ elem = this[ 0 ];
+
+ if ( !elem ) {
+ return;
+ }
+
+ // Return zeros for disconnected and hidden (display: none) elements (gh-2310)
+ // Support: IE <=11 only
+ // Running getBoundingClientRect on a
+ // disconnected node in IE throws an error
+ if ( !elem.getClientRects().length ) {
+ return { top: 0, left: 0 };
+ }
+
+ rect = elem.getBoundingClientRect();
+
+ doc = elem.ownerDocument;
+ docElem = doc.documentElement;
+ win = doc.defaultView;
+
+ return {
+ top: rect.top + win.pageYOffset - docElem.clientTop,
+ left: rect.left + win.pageXOffset - docElem.clientLeft
+ };
+ },
+
+ position: function() {
+ if ( !this[ 0 ] ) {
+ return;
+ }
+
+ var offsetParent, offset,
+ elem = this[ 0 ],
+ parentOffset = { top: 0, left: 0 };
+
+ // Fixed elements are offset from window (parentOffset = {top:0, left: 0},
+ // because it is its only offset parent
+ if ( jQuery.css( elem, "position" ) === "fixed" ) {
+
+ // Assume getBoundingClientRect is there when computed position is fixed
+ offset = elem.getBoundingClientRect();
+
+ } else {
+
+ // Get *real* offsetParent
+ offsetParent = this.offsetParent();
+
+ // Get correct offsets
+ offset = this.offset();
+ if ( !nodeName( offsetParent[ 0 ], "html" ) ) {
+ parentOffset = offsetParent.offset();
+ }
+
+ // Add offsetParent borders
+ parentOffset = {
+ top: parentOffset.top + jQuery.css( offsetParent[ 0 ], "borderTopWidth", true ),
+ left: parentOffset.left + jQuery.css( offsetParent[ 0 ], "borderLeftWidth", true )
+ };
+ }
+
+ // Subtract parent offsets and element margins
+ return {
+ top: offset.top - parentOffset.top - jQuery.css( elem, "marginTop", true ),
+ left: offset.left - parentOffset.left - jQuery.css( elem, "marginLeft", true )
+ };
+ },
+
+ // This method will return documentElement in the following cases:
+ // 1) For the element inside the iframe without offsetParent, this method will return
+ // documentElement of the parent window
+ // 2) For the hidden or detached element
+ // 3) For body or html element, i.e. in case of the html node - it will return itself
+ //
+ // but those exceptions were never presented as a real life use-cases
+ // and might be considered as more preferable results.
+ //
+ // This logic, however, is not guaranteed and can change at any point in the future
+ offsetParent: function() {
+ return this.map( function() {
+ var offsetParent = this.offsetParent;
+
+ while ( offsetParent && jQuery.css( offsetParent, "position" ) === "static" ) {
+ offsetParent = offsetParent.offsetParent;
+ }
+
+ return offsetParent || documentElement;
+ } );
+ }
+} );
+
+// Create scrollLeft and scrollTop methods
+jQuery.each( { scrollLeft: "pageXOffset", scrollTop: "pageYOffset" }, function( method, prop ) {
+ var top = "pageYOffset" === prop;
+
+ jQuery.fn[ method ] = function( val ) {
+ return access( this, function( elem, method, val ) {
+
+ // Coalesce documents and windows
+ var win;
+ if ( jQuery.isWindow( elem ) ) {
+ win = elem;
+ } else if ( elem.nodeType === 9 ) {
+ win = elem.defaultView;
+ }
+
+ if ( val === undefined ) {
+ return win ? win[ prop ] : elem[ method ];
+ }
+
+ if ( win ) {
+ win.scrollTo(
+ !top ? val : win.pageXOffset,
+ top ? val : win.pageYOffset
+ );
+
+ } else {
+ elem[ method ] = val;
+ }
+ }, method, val, arguments.length );
+ };
+} );
+
+// Support: Safari <=7 - 9.1, Chrome <=37 - 49
+// Add the top/left cssHooks using jQuery.fn.position
+// Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084
+// Blink bug: https://bugs.chromium.org/p/chromium/issues/detail?id=589347
+// getComputedStyle returns percent when specified for top/left/bottom/right;
+// rather than make the css module depend on the offset module, just check for it here
+jQuery.each( [ "top", "left" ], function( i, prop ) {
+ jQuery.cssHooks[ prop ] = addGetHookIf( support.pixelPosition,
+ function( elem, computed ) {
+ if ( computed ) {
+ computed = curCSS( elem, prop );
+
+ // If curCSS returns percentage, fallback to offset
+ return rnumnonpx.test( computed ) ?
+ jQuery( elem ).position()[ prop ] + "px" :
+ computed;
+ }
+ }
+ );
+} );
+
+
+// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods
+jQuery.each( { Height: "height", Width: "width" }, function( name, type ) {
+ jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name },
+ function( defaultExtra, funcName ) {
+
+ // Margin is only for outerHeight, outerWidth
+ jQuery.fn[ funcName ] = function( margin, value ) {
+ var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ),
+ extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" );
+
+ return access( this, function( elem, type, value ) {
+ var doc;
+
+ if ( jQuery.isWindow( elem ) ) {
+
+ // $( window ).outerWidth/Height return w/h including scrollbars (gh-1729)
+ return funcName.indexOf( "outer" ) === 0 ?
+ elem[ "inner" + name ] :
+ elem.document.documentElement[ "client" + name ];
+ }
+
+ // Get document width or height
+ if ( elem.nodeType === 9 ) {
+ doc = elem.documentElement;
+
+ // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height],
+ // whichever is greatest
+ return Math.max(
+ elem.body[ "scroll" + name ], doc[ "scroll" + name ],
+ elem.body[ "offset" + name ], doc[ "offset" + name ],
+ doc[ "client" + name ]
+ );
+ }
+
+ return value === undefined ?
+
+ // Get width or height on the element, requesting but not forcing parseFloat
+ jQuery.css( elem, type, extra ) :
+
+ // Set width or height on the element
+ jQuery.style( elem, type, value, extra );
+ }, type, chainable ? margin : undefined, chainable );
+ };
+ } );
+} );
+
+
+jQuery.fn.extend( {
+
+ bind: function( types, data, fn ) {
+ return this.on( types, null, data, fn );
+ },
+ unbind: function( types, fn ) {
+ return this.off( types, null, fn );
+ },
+
+ delegate: function( selector, types, data, fn ) {
+ return this.on( types, selector, data, fn );
+ },
+ undelegate: function( selector, types, fn ) {
+
+ // ( namespace ) or ( selector, types [, fn] )
+ return arguments.length === 1 ?
+ this.off( selector, "**" ) :
+ this.off( types, selector || "**", fn );
+ }
+} );
+
+jQuery.holdReady = function( hold ) {
+ if ( hold ) {
+ jQuery.readyWait++;
+ } else {
+ jQuery.ready( true );
+ }
+};
+jQuery.isArray = Array.isArray;
+jQuery.parseJSON = JSON.parse;
+jQuery.nodeName = nodeName;
+
+
+
+
+// Register as a named AMD module, since jQuery can be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Lowercase jquery is used because AMD module names are
+// derived from file names, and jQuery is normally delivered in a lowercase
+// file name. Do this after creating the global so that if an AMD module wants
+// to call noConflict to hide this version of jQuery, it will work.
+
+// Note that for maximum portability, libraries that are not jQuery should
+// declare themselves as anonymous modules, and avoid setting a global if an
+// AMD loader is present. jQuery is a special case. For more information, see
+// https://github.com/jrburke/requirejs/wiki/Updating-existing-libraries#wiki-anon
+
+if ( typeof define === "function" && define.amd ) {
+ define( "jquery", [], function() {
+ return jQuery;
+ } );
+}
+
+
+
+
+var
+
+ // Map over jQuery in case of overwrite
+ _jQuery = window.jQuery,
+
+ // Map over the $ in case of overwrite
+ _$ = window.$;
+
+jQuery.noConflict = function( deep ) {
+ if ( window.$ === jQuery ) {
+ window.$ = _$;
+ }
+
+ if ( deep && window.jQuery === jQuery ) {
+ window.jQuery = _jQuery;
+ }
+
+ return jQuery;
+};
+
+// Expose jQuery and $ identifiers, even in AMD
+// (#7102#comment:10, https://github.com/jquery/jquery/pull/557)
+// and CommonJS for browser emulators (#13566)
+if ( !noGlobal ) {
+ window.jQuery = window.$ = jQuery;
+}
+
+
+
+
+return jQuery;
+} );
diff --git a/www/wiki/resources/lib/json2/json2.js b/www/wiki/resources/lib/json2/json2.js
new file mode 100644
index 00000000..58384577
--- /dev/null
+++ b/www/wiki/resources/lib/json2/json2.js
@@ -0,0 +1,519 @@
+/*
+ json2.js
+ 2015-05-03
+
+ Public Domain.
+
+ NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
+
+ See http://www.JSON.org/js.html
+
+
+ This code should be minified before deployment.
+ See http://javascript.crockford.com/jsmin.html
+
+ USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
+ NOT CONTROL.
+
+
+ This file creates a global JSON object containing two methods: stringify
+ and parse. This file is provides the ES5 JSON capability to ES3 systems.
+ If a project might run on IE8 or earlier, then this file should be included.
+ This file does nothing on ES5 systems.
+
+ JSON.stringify(value, replacer, space)
+ value any JavaScript value, usually an object or array.
+
+ replacer an optional parameter that determines how object
+ values are stringified for objects. It can be a
+ function or an array of strings.
+
+ space an optional parameter that specifies the indentation
+ of nested structures. If it is omitted, the text will
+ be packed without extra whitespace. If it is a number,
+ it will specify the number of spaces to indent at each
+ level. If it is a string (such as '\t' or '&nbsp;'),
+ it contains the characters used to indent at each level.
+
+ This method produces a JSON text from a JavaScript value.
+
+ When an object value is found, if the object contains a toJSON
+ method, its toJSON method will be called and the result will be
+ stringified. A toJSON method does not serialize: it returns the
+ value represented by the name/value pair that should be serialized,
+ or undefined if nothing should be serialized. The toJSON method
+ will be passed the key associated with the value, and this will be
+ bound to the value
+
+ For example, this would serialize Dates as ISO strings.
+
+ Date.prototype.toJSON = function (key) {
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10
+ ? '0' + n
+ : n;
+ }
+
+ return this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z';
+ };
+
+ You can provide an optional replacer method. It will be passed the
+ key and value of each member, with this bound to the containing
+ object. The value that is returned from your method will be
+ serialized. If your method returns undefined, then the member will
+ be excluded from the serialization.
+
+ If the replacer parameter is an array of strings, then it will be
+ used to select the members to be serialized. It filters the results
+ such that only members with keys listed in the replacer array are
+ stringified.
+
+ Values that do not have JSON representations, such as undefined or
+ functions, will not be serialized. Such values in objects will be
+ dropped; in arrays they will be replaced with null. You can use
+ a replacer function to replace those with JSON values.
+ JSON.stringify(undefined) returns undefined.
+
+ The optional space parameter produces a stringification of the
+ value that is filled with line breaks and indentation to make it
+ easier to read.
+
+ If the space parameter is a non-empty string, then that string will
+ be used for indentation. If the space parameter is a number, then
+ the indentation will be that many spaces.
+
+ Example:
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}]);
+ // text is '["e",{"pluribus":"unum"}]'
+
+
+ text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
+ // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
+
+ text = JSON.stringify([new Date()], function (key, value) {
+ return this[key] instanceof Date
+ ? 'Date(' + this[key] + ')'
+ : value;
+ });
+ // text is '["Date(---current time---)"]'
+
+
+ JSON.parse(text, reviver)
+ This method parses a JSON text to produce an object or array.
+ It can throw a SyntaxError exception.
+
+ The optional reviver parameter is a function that can filter and
+ transform the results. It receives each of the keys and values,
+ and its return value is used instead of the original value.
+ If it returns what it received, then the structure is not modified.
+ If it returns undefined then the member is deleted.
+
+ Example:
+
+ // Parse the text. Values that look like ISO date strings will
+ // be converted to Date objects.
+
+ myData = JSON.parse(text, function (key, value) {
+ var a;
+ if (typeof value === 'string') {
+ a =
+/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
+ if (a) {
+ return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+ +a[5], +a[6]));
+ }
+ }
+ return value;
+ });
+
+ myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
+ var d;
+ if (typeof value === 'string' &&
+ value.slice(0, 5) === 'Date(' &&
+ value.slice(-1) === ')') {
+ d = new Date(value.slice(5, -1));
+ if (d) {
+ return d;
+ }
+ }
+ return value;
+ });
+
+
+ This is a reference implementation. You are free to copy, modify, or
+ redistribute.
+*/
+
+/*jslint
+ eval, for, this
+*/
+
+/*property
+ JSON, apply, call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
+ getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
+ lastIndex, length, parse, prototype, push, replace, slice, stringify,
+ test, toJSON, toString, valueOf
+*/
+
+
+// Create a JSON object only if one does not already exist. We create the
+// methods in a closure to avoid creating global variables.
+
+if (typeof JSON !== 'object') {
+ JSON = {};
+}
+
+(function () {
+ 'use strict';
+
+ var rx_one = /^[\],:{}\s]*$/,
+ rx_two = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
+ rx_three = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
+ rx_four = /(?:^|:|,)(?:\s*\[)+/g,
+ rx_escapable = /[\\\"\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
+ rx_dangerous = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
+
+ function f(n) {
+ // Format integers to have at least two digits.
+ return n < 10
+ ? '0' + n
+ : n;
+ }
+
+ function this_value() {
+ return this.valueOf();
+ }
+
+ if (typeof Date.prototype.toJSON !== 'function') {
+
+ Date.prototype.toJSON = function () {
+
+ return isFinite(this.valueOf())
+ ? this.getUTCFullYear() + '-' +
+ f(this.getUTCMonth() + 1) + '-' +
+ f(this.getUTCDate()) + 'T' +
+ f(this.getUTCHours()) + ':' +
+ f(this.getUTCMinutes()) + ':' +
+ f(this.getUTCSeconds()) + 'Z'
+ : null;
+ };
+
+ Boolean.prototype.toJSON = this_value;
+ Number.prototype.toJSON = this_value;
+ String.prototype.toJSON = this_value;
+ }
+
+ var gap,
+ indent,
+ meta,
+ rep;
+
+
+ function quote(string) {
+
+// If the string contains no control characters, no quote characters, and no
+// backslash characters, then we can safely slap some quotes around it.
+// Otherwise we must also replace the offending characters with safe escape
+// sequences.
+
+ rx_escapable.lastIndex = 0;
+ return rx_escapable.test(string)
+ ? '"' + string.replace(rx_escapable, function (a) {
+ var c = meta[a];
+ return typeof c === 'string'
+ ? c
+ : '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ }) + '"'
+ : '"' + string + '"';
+ }
+
+
+ function str(key, holder) {
+
+// Produce a string from holder[key].
+
+ var i, // The loop counter.
+ k, // The member key.
+ v, // The member value.
+ length,
+ mind = gap,
+ partial,
+ value = holder[key];
+
+// If the value has a toJSON method, call it to obtain a replacement value.
+
+ if (value && typeof value === 'object' &&
+ typeof value.toJSON === 'function') {
+ value = value.toJSON(key);
+ }
+
+// If we were called with a replacer function, then call the replacer to
+// obtain a replacement value.
+
+ if (typeof rep === 'function') {
+ value = rep.call(holder, key, value);
+ }
+
+// What happens next depends on the value's type.
+
+ switch (typeof value) {
+ case 'string':
+ return quote(value);
+
+ case 'number':
+
+// JSON numbers must be finite. Encode non-finite numbers as null.
+
+ return isFinite(value)
+ ? String(value)
+ : 'null';
+
+ case 'boolean':
+ case 'null':
+
+// If the value is a boolean or null, convert it to a string. Note:
+// typeof null does not produce 'null'. The case is included here in
+// the remote chance that this gets fixed someday.
+
+ return String(value);
+
+// If the type is 'object', we might be dealing with an object or an array or
+// null.
+
+ case 'object':
+
+// Due to a specification blunder in ECMAScript, typeof null is 'object',
+// so watch out for that case.
+
+ if (!value) {
+ return 'null';
+ }
+
+// Make an array to hold the partial results of stringifying this object value.
+
+ gap += indent;
+ partial = [];
+
+// Is the value an array?
+
+ if (Object.prototype.toString.apply(value) === '[object Array]') {
+
+// The value is an array. Stringify every element. Use null as a placeholder
+// for non-JSON values.
+
+ length = value.length;
+ for (i = 0; i < length; i += 1) {
+ partial[i] = str(i, value) || 'null';
+ }
+
+// Join all of the elements together, separated with commas, and wrap them in
+// brackets.
+
+ v = partial.length === 0
+ ? '[]'
+ : gap
+ ? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
+ : '[' + partial.join(',') + ']';
+ gap = mind;
+ return v;
+ }
+
+// If the replacer is an array, use it to select the members to be stringified.
+
+ if (rep && typeof rep === 'object') {
+ length = rep.length;
+ for (i = 0; i < length; i += 1) {
+ if (typeof rep[i] === 'string') {
+ k = rep[i];
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (
+ gap
+ ? ': '
+ : ':'
+ ) + v);
+ }
+ }
+ }
+ } else {
+
+// Otherwise, iterate through all of the keys in the object.
+
+ for (k in value) {
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
+ v = str(k, value);
+ if (v) {
+ partial.push(quote(k) + (
+ gap
+ ? ': '
+ : ':'
+ ) + v);
+ }
+ }
+ }
+ }
+
+// Join all of the member texts together, separated with commas,
+// and wrap them in braces.
+
+ v = partial.length === 0
+ ? '{}'
+ : gap
+ ? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
+ : '{' + partial.join(',') + '}';
+ gap = mind;
+ return v;
+ }
+ }
+
+// If the JSON object does not yet have a stringify method, give it one.
+
+ if (typeof JSON.stringify !== 'function') {
+ meta = { // table of character substitutions
+ '\b': '\\b',
+ '\t': '\\t',
+ '\n': '\\n',
+ '\f': '\\f',
+ '\r': '\\r',
+ '"': '\\"',
+ '\\': '\\\\'
+ };
+ JSON.stringify = function (value, replacer, space) {
+
+// The stringify method takes a value and an optional replacer, and an optional
+// space parameter, and returns a JSON text. The replacer can be a function
+// that can replace values, or an array of strings that will select the keys.
+// A default replacer method can be provided. Use of the space parameter can
+// produce text that is more easily readable.
+
+ var i;
+ gap = '';
+ indent = '';
+
+// If the space parameter is a number, make an indent string containing that
+// many spaces.
+
+ if (typeof space === 'number') {
+ for (i = 0; i < space; i += 1) {
+ indent += ' ';
+ }
+
+// If the space parameter is a string, it will be used as the indent string.
+
+ } else if (typeof space === 'string') {
+ indent = space;
+ }
+
+// If there is a replacer, it must be a function or an array.
+// Otherwise, throw an error.
+
+ rep = replacer;
+ if (replacer && typeof replacer !== 'function' &&
+ (typeof replacer !== 'object' ||
+ typeof replacer.length !== 'number')) {
+ throw new Error('JSON.stringify');
+ }
+
+// Make a fake root object containing our value under the key of ''.
+// Return the result of stringifying the value.
+
+ return str('', {'': value});
+ };
+ }
+
+
+// If the JSON object does not yet have a parse method, give it one.
+
+ if (typeof JSON.parse !== 'function') {
+ JSON.parse = function (text, reviver) {
+
+// The parse method takes a text and an optional reviver function, and returns
+// a JavaScript value if the text is a valid JSON text.
+
+ var j;
+
+ function walk(holder, key) {
+
+// The walk method is used to recursively walk the resulting structure so
+// that modifications can be made.
+
+ var k, v, value = holder[key];
+ if (value && typeof value === 'object') {
+ for (k in value) {
+ if (Object.prototype.hasOwnProperty.call(value, k)) {
+ v = walk(value, k);
+ if (v !== undefined) {
+ value[k] = v;
+ } else {
+ delete value[k];
+ }
+ }
+ }
+ }
+ return reviver.call(holder, key, value);
+ }
+
+
+// Parsing happens in four stages. In the first stage, we replace certain
+// Unicode characters with escape sequences. JavaScript handles many characters
+// incorrectly, either silently deleting them, or treating them as line endings.
+
+ text = String(text);
+ rx_dangerous.lastIndex = 0;
+ if (rx_dangerous.test(text)) {
+ text = text.replace(rx_dangerous, function (a) {
+ return '\\u' +
+ ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
+ });
+ }
+
+// In the second stage, we run the text against regular expressions that look
+// for non-JSON patterns. We are especially concerned with '()' and 'new'
+// because they can cause invocation, and '=' because it can cause mutation.
+// But just to be safe, we want to reject all unexpected forms.
+
+// We split the second stage into 4 regexp operations in order to work around
+// crippling inefficiencies in IE's and Safari's regexp engines. First we
+// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
+// replace all simple value tokens with ']' characters. Third, we delete all
+// open brackets that follow a colon or comma or that begin the text. Finally,
+// we look to see that the remaining characters are only whitespace or ']' or
+// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
+
+ if (
+ rx_one.test(
+ text
+ .replace(rx_two, '@')
+ .replace(rx_three, ']')
+ .replace(rx_four, '')
+ )
+ ) {
+
+// In the third stage we use the eval function to compile the text into a
+// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
+// in JavaScript: it can begin a block or an object literal. We wrap the text
+// in parens to eliminate the ambiguity.
+
+ j = eval('(' + text + ')');
+
+// In the optional fourth stage, we recursively walk the new structure, passing
+// each name/value pair to a reviver function for possible transformation.
+
+ return typeof reviver === 'function'
+ ? walk({'': j}, '')
+ : j;
+ }
+
+// If the text is not JSON parseable, then a SyntaxError is thrown.
+
+ throw new SyntaxError('JSON.parse');
+ };
+ }
+}());
diff --git a/www/wiki/resources/lib/moment/LICENSE b/www/wiki/resources/lib/moment/LICENSE
new file mode 100644
index 00000000..8618b733
--- /dev/null
+++ b/www/wiki/resources/lib/moment/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) JS Foundation and other contributors
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/www/wiki/resources/lib/moment/README.md b/www/wiki/resources/lib/moment/README.md
new file mode 100644
index 00000000..06783de0
--- /dev/null
+++ b/www/wiki/resources/lib/moment/README.md
@@ -0,0 +1,61 @@
+[![Join the chat at https://gitter.im/moment/moment](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/moment/moment?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+[![NPM version][npm-version-image]][npm-url] [![NPM downloads][npm-downloads-image]][npm-url] [![MIT License][license-image]][license-url] [![Build Status][travis-image]][travis-url]
+[![Coverage Status](https://coveralls.io/repos/moment/moment/badge.svg?branch=develop)](https://coveralls.io/r/moment/moment?branch=develop)
+[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmoment%2Fmoment.svg?type=shield)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmoment%2Fmoment?ref=badge_shield)
+
+A lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates.
+
+**[Documentation](http://momentjs.com/docs/)**
+
+## Port to ECMAScript 6 (version 2.10.0)
+
+Moment 2.10.0 does not bring any new features, but the code is now written in
+ECMAScript 6 modules and placed inside `src/`. Previously `moment.js`, `locale/*.js` and
+`test/moment/*.js`, `test/locale/*.js` contained the source of the project. Now
+the source is in `src/`, temporary build (ECMAScript 5) files are placed under
+`build/umd/` (for running tests during development), and the `moment.js` and
+`locale/*.js` files are updated only on release.
+
+If you want to use a particular revision of the code, make sure to run
+`grunt transpile update-index`, so `moment.js` and `locales/*.js` are synced
+with `src/*`. We might place that in a commit hook in the future.
+
+## Upgrading to 2.0.0
+
+There are a number of small backwards incompatible changes with version 2.0.0. [See the full descriptions here](https://gist.github.com/timrwood/e72f2eef320ed9e37c51#backwards-incompatible-changes)
+
+ * Changed language ordinal method to return the number + ordinal instead of just the ordinal.
+
+ * Changed two digit year parsing cutoff to match strptime.
+
+ * Removed `moment#sod` and `moment#eod` in favor of `moment#startOf` and `moment#endOf`.
+
+ * Removed `moment.humanizeDuration()` in favor of `moment.duration().humanize()`.
+
+ * Removed the lang data objects from the top level namespace.
+
+ * Duplicate `Date` passed to `moment()` instead of referencing it.
+
+## [Changelog](https://github.com/moment/moment/blob/develop/CHANGELOG.md)
+
+## [Contributing](https://github.com/moment/moment/blob/develop/CONTRIBUTING.md)
+
+We're looking for co-maintainers! If you want to become a master of time please
+write to [ichernev](https://github.com/ichernev).
+
+## License
+
+Moment.js is freely distributable under the terms of the [MIT license](https://github.com/moment/moment/blob/develop/LICENSE).
+
+[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmoment%2Fmoment.svg?type=large)](https://app.fossa.io/projects/git%2Bhttps%3A%2F%2Fgithub.com%2Fmoment%2Fmoment?ref=badge_large)
+
+[license-image]: http://img.shields.io/badge/license-MIT-blue.svg?style=flat
+[license-url]: LICENSE
+
+[npm-url]: https://npmjs.org/package/moment
+[npm-version-image]: http://img.shields.io/npm/v/moment.svg?style=flat
+[npm-downloads-image]: http://img.shields.io/npm/dm/moment.svg?style=flat
+
+[travis-url]: http://travis-ci.org/moment/moment
+[travis-image]: http://img.shields.io/travis/moment/moment/develop.svg?style=flat
diff --git a/www/wiki/resources/lib/moment/locale/af.js b/www/wiki/resources/lib/moment/locale/af.js
new file mode 100644
index 00000000..a89257fd
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/af.js
@@ -0,0 +1,73 @@
+//! moment.js locale configuration
+//! locale : Afrikaans [af]
+//! author : Werner Mollentze : https://github.com/wernerm
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var af = moment.defineLocale('af', {
+ months : 'Januarie_Februarie_Maart_April_Mei_Junie_Julie_Augustus_September_Oktober_November_Desember'.split('_'),
+ monthsShort : 'Jan_Feb_Mrt_Apr_Mei_Jun_Jul_Aug_Sep_Okt_Nov_Des'.split('_'),
+ weekdays : 'Sondag_Maandag_Dinsdag_Woensdag_Donderdag_Vrydag_Saterdag'.split('_'),
+ weekdaysShort : 'Son_Maa_Din_Woe_Don_Vry_Sat'.split('_'),
+ weekdaysMin : 'So_Ma_Di_Wo_Do_Vr_Sa'.split('_'),
+ meridiemParse: /vm|nm/i,
+ isPM : function (input) {
+ return /^nm$/i.test(input);
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 12) {
+ return isLower ? 'vm' : 'VM';
+ } else {
+ return isLower ? 'nm' : 'NM';
+ }
+ },
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Vandag om] LT',
+ nextDay : '[Môre om] LT',
+ nextWeek : 'dddd [om] LT',
+ lastDay : '[Gister om] LT',
+ lastWeek : '[Laas] dddd [om] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'oor %s',
+ past : '%s gelede',
+ s : '\'n paar sekondes',
+ m : '\'n minuut',
+ mm : '%d minute',
+ h : '\'n uur',
+ hh : '%d ure',
+ d : '\'n dag',
+ dd : '%d dae',
+ M : '\'n maand',
+ MM : '%d maande',
+ y : '\'n jaar',
+ yy : '%d jaar'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
+ ordinal : function (number) {
+ return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de'); // Thanks to Joris Röling : https://github.com/jjupiter
+ },
+ week : {
+ dow : 1, // Maandag is die eerste dag van die week.
+ doy : 4 // Die week wat die 4de Januarie bevat is die eerste week van die jaar.
+ }
+});
+
+return af;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ar-ma.js b/www/wiki/resources/lib/moment/locale/ar-ma.js
new file mode 100644
index 00000000..cbd810ba
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ar-ma.js
@@ -0,0 +1,60 @@
+//! moment.js locale configuration
+//! locale : Arabic (Morocco) [ar-ma]
+//! author : ElFadili Yassine : https://github.com/ElFadiliY
+//! author : Abdel Said : https://github.com/abdelsaid
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var arMa = moment.defineLocale('ar-ma', {
+ months : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+ monthsShort : 'يناير_فبراير_مارس_أبريل_ماي_يونيو_يوليوز_غشت_شتنبر_أكتوبر_نونبر_دجنبر'.split('_'),
+ weekdays : 'الأحد_الإتنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+ weekdaysShort : 'احد_اتنين_ثلاثاء_اربعاء_خميس_جمعة_سبت'.split('_'),
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[اليوم على الساعة] LT',
+ nextDay: '[غدا على الساعة] LT',
+ nextWeek: 'dddd [على الساعة] LT',
+ lastDay: '[أمس على الساعة] LT',
+ lastWeek: 'dddd [على الساعة] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'في %s',
+ past : 'منذ %s',
+ s : 'ثوان',
+ m : 'دقيقة',
+ mm : '%d دقائق',
+ h : 'ساعة',
+ hh : '%d ساعات',
+ d : 'يوم',
+ dd : '%d أيام',
+ M : 'شهر',
+ MM : '%d أشهر',
+ y : 'سنة',
+ yy : '%d سنوات'
+ },
+ week : {
+ dow : 6, // Saturday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return arMa;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ar-sa.js b/www/wiki/resources/lib/moment/locale/ar-sa.js
new file mode 100644
index 00000000..dccd0d83
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ar-sa.js
@@ -0,0 +1,105 @@
+//! moment.js locale configuration
+//! locale : Arabic (Saudi Arabia) [ar-sa]
+//! author : Suhail Alkowaileet : https://github.com/xsoh
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '١',
+ '2': '٢',
+ '3': '٣',
+ '4': '٤',
+ '5': '٥',
+ '6': '٦',
+ '7': '٧',
+ '8': '٨',
+ '9': '٩',
+ '0': '٠'
+};
+var numberMap = {
+ '١': '1',
+ '٢': '2',
+ '٣': '3',
+ '٤': '4',
+ '٥': '5',
+ '٦': '6',
+ '٧': '7',
+ '٨': '8',
+ '٩': '9',
+ '٠': '0'
+};
+
+var arSa = moment.defineLocale('ar-sa', {
+ months : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+ monthsShort : 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+ weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+ weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /ص|م/,
+ isPM : function (input) {
+ return 'م' === input;
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'ص';
+ } else {
+ return 'م';
+ }
+ },
+ calendar : {
+ sameDay: '[اليوم على الساعة] LT',
+ nextDay: '[غدا على الساعة] LT',
+ nextWeek: 'dddd [على الساعة] LT',
+ lastDay: '[أمس على الساعة] LT',
+ lastWeek: 'dddd [على الساعة] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'في %s',
+ past : 'منذ %s',
+ s : 'ثوان',
+ m : 'دقيقة',
+ mm : '%d دقائق',
+ h : 'ساعة',
+ hh : '%d ساعات',
+ d : 'يوم',
+ dd : '%d أيام',
+ M : 'شهر',
+ MM : '%d أشهر',
+ y : 'سنة',
+ yy : '%d سنوات'
+ },
+ preparse: function (string) {
+ return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
+ return numberMap[match];
+ }).replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ }).replace(/,/g, '،');
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return arSa;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ar-tn.js b/www/wiki/resources/lib/moment/locale/ar-tn.js
new file mode 100644
index 00000000..5f0d38bb
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ar-tn.js
@@ -0,0 +1,59 @@
+//! moment.js locale configuration
+//! locale : Arabic (Tunisia) [ar-tn]
+//! author : Nader Toukabri : https://github.com/naderio
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var arTn = moment.defineLocale('ar-tn', {
+ months: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+ monthsShort: 'جانفي_فيفري_مارس_أفريل_ماي_جوان_جويلية_أوت_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+ weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+ weekdaysShort: 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+ weekdaysMin: 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat: {
+ LT: 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY HH:mm',
+ LLLL: 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar: {
+ sameDay: '[اليوم على الساعة] LT',
+ nextDay: '[غدا على الساعة] LT',
+ nextWeek: 'dddd [على الساعة] LT',
+ lastDay: '[أمس على الساعة] LT',
+ lastWeek: 'dddd [على الساعة] LT',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: 'في %s',
+ past: 'منذ %s',
+ s: 'ثوان',
+ m: 'دقيقة',
+ mm: '%d دقائق',
+ h: 'ساعة',
+ hh: '%d ساعات',
+ d: 'يوم',
+ dd: '%d أيام',
+ M: 'شهر',
+ MM: '%d أشهر',
+ y: 'سنة',
+ yy: '%d سنوات'
+ },
+ week: {
+ dow: 1, // Monday is the first day of the week.
+ doy: 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return arTn;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ar.js b/www/wiki/resources/lib/moment/locale/ar.js
new file mode 100644
index 00000000..ae09617a
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ar.js
@@ -0,0 +1,142 @@
+//! moment.js locale configuration
+//! locale : Arabic [ar]
+//! author : Abdel Said: https://github.com/abdelsaid
+//! author : Ahmed Elkhatib
+//! author : forabi https://github.com/forabi
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '١',
+ '2': '٢',
+ '3': '٣',
+ '4': '٤',
+ '5': '٥',
+ '6': '٦',
+ '7': '٧',
+ '8': '٨',
+ '9': '٩',
+ '0': '٠'
+};
+var numberMap = {
+ '١': '1',
+ '٢': '2',
+ '٣': '3',
+ '٤': '4',
+ '٥': '5',
+ '٦': '6',
+ '٧': '7',
+ '٨': '8',
+ '٩': '9',
+ '٠': '0'
+};
+var pluralForm = function (n) {
+ return n === 0 ? 0 : n === 1 ? 1 : n === 2 ? 2 : n % 100 >= 3 && n % 100 <= 10 ? 3 : n % 100 >= 11 ? 4 : 5;
+};
+var plurals = {
+ s : ['أقل من ثانية', 'ثانية واحدة', ['ثانيتان', 'ثانيتين'], '%d ثوان', '%d ثانية', '%d ثانية'],
+ m : ['أقل من دقيقة', 'دقيقة واحدة', ['دقيقتان', 'دقيقتين'], '%d دقائق', '%d دقيقة', '%d دقيقة'],
+ h : ['أقل من ساعة', 'ساعة واحدة', ['ساعتان', 'ساعتين'], '%d ساعات', '%d ساعة', '%d ساعة'],
+ d : ['أقل من يوم', 'يوم واحد', ['يومان', 'يومين'], '%d أيام', '%d يومًا', '%d يوم'],
+ M : ['أقل من شهر', 'شهر واحد', ['شهران', 'شهرين'], '%d أشهر', '%d شهرا', '%d شهر'],
+ y : ['أقل من عام', 'عام واحد', ['عامان', 'عامين'], '%d أعوام', '%d عامًا', '%d عام']
+};
+var pluralize = function (u) {
+ return function (number, withoutSuffix, string, isFuture) {
+ var f = pluralForm(number),
+ str = plurals[u][pluralForm(number)];
+ if (f === 2) {
+ str = str[withoutSuffix ? 0 : 1];
+ }
+ return str.replace(/%d/i, number);
+ };
+};
+var months = [
+ 'كانون الثاني يناير',
+ 'شباط فبراير',
+ 'آذار مارس',
+ 'نيسان أبريل',
+ 'أيار مايو',
+ 'حزيران يونيو',
+ 'تموز يوليو',
+ 'آب أغسطس',
+ 'أيلول سبتمبر',
+ 'تشرين الأول أكتوبر',
+ 'تشرين الثاني نوفمبر',
+ 'كانون الأول ديسمبر'
+];
+
+var ar = moment.defineLocale('ar', {
+ months : months,
+ monthsShort : months,
+ weekdays : 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
+ weekdaysShort : 'أحد_إثنين_ثلاثاء_أربعاء_خميس_جمعة_سبت'.split('_'),
+ weekdaysMin : 'ح_ن_ث_ر_خ_ج_س'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'D/\u200FM/\u200FYYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /ص|م/,
+ isPM : function (input) {
+ return 'م' === input;
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'ص';
+ } else {
+ return 'م';
+ }
+ },
+ calendar : {
+ sameDay: '[اليوم عند الساعة] LT',
+ nextDay: '[غدًا عند الساعة] LT',
+ nextWeek: 'dddd [عند الساعة] LT',
+ lastDay: '[أمس عند الساعة] LT',
+ lastWeek: 'dddd [عند الساعة] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'بعد %s',
+ past : 'منذ %s',
+ s : pluralize('s'),
+ m : pluralize('m'),
+ mm : pluralize('m'),
+ h : pluralize('h'),
+ hh : pluralize('h'),
+ d : pluralize('d'),
+ dd : pluralize('d'),
+ M : pluralize('M'),
+ MM : pluralize('M'),
+ y : pluralize('y'),
+ yy : pluralize('y')
+ },
+ preparse: function (string) {
+ return string.replace(/[١٢٣٤٥٦٧٨٩٠]/g, function (match) {
+ return numberMap[match];
+ }).replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ }).replace(/,/g, '،');
+ },
+ week : {
+ dow : 6, // Saturday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ar;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/az.js b/www/wiki/resources/lib/moment/locale/az.js
new file mode 100644
index 00000000..56021b44
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/az.js
@@ -0,0 +1,105 @@
+//! moment.js locale configuration
+//! locale : Azerbaijani [az]
+//! author : topchiyev : https://github.com/topchiyev
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var suffixes = {
+ 1: '-inci',
+ 5: '-inci',
+ 8: '-inci',
+ 70: '-inci',
+ 80: '-inci',
+ 2: '-nci',
+ 7: '-nci',
+ 20: '-nci',
+ 50: '-nci',
+ 3: '-üncü',
+ 4: '-üncü',
+ 100: '-üncü',
+ 6: '-ncı',
+ 9: '-uncu',
+ 10: '-uncu',
+ 30: '-uncu',
+ 60: '-ıncı',
+ 90: '-ıncı'
+};
+
+var az = moment.defineLocale('az', {
+ months : 'yanvar_fevral_mart_aprel_may_iyun_iyul_avqust_sentyabr_oktyabr_noyabr_dekabr'.split('_'),
+ monthsShort : 'yan_fev_mar_apr_may_iyn_iyl_avq_sen_okt_noy_dek'.split('_'),
+ weekdays : 'Bazar_Bazar ertəsi_Çərşənbə axşamı_Çərşənbə_Cümə axşamı_Cümə_Şənbə'.split('_'),
+ weekdaysShort : 'Baz_BzE_ÇAx_Çər_CAx_Cüm_Şən'.split('_'),
+ weekdaysMin : 'Bz_BE_ÇA_Çə_CA_Cü_Şə'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[bugün saat] LT',
+ nextDay : '[sabah saat] LT',
+ nextWeek : '[gələn həftə] dddd [saat] LT',
+ lastDay : '[dünən] LT',
+ lastWeek : '[keçən həftə] dddd [saat] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s sonra',
+ past : '%s əvvəl',
+ s : 'birneçə saniyyə',
+ m : 'bir dəqiqə',
+ mm : '%d dəqiqə',
+ h : 'bir saat',
+ hh : '%d saat',
+ d : 'bir gün',
+ dd : '%d gün',
+ M : 'bir ay',
+ MM : '%d ay',
+ y : 'bir il',
+ yy : '%d il'
+ },
+ meridiemParse: /gecə|səhər|gündüz|axşam/,
+ isPM : function (input) {
+ return /^(gündüz|axşam)$/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'gecə';
+ } else if (hour < 12) {
+ return 'səhər';
+ } else if (hour < 17) {
+ return 'gündüz';
+ } else {
+ return 'axşam';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(ıncı|inci|nci|üncü|ncı|uncu)/,
+ ordinal : function (number) {
+ if (number === 0) { // special case for zero
+ return number + '-ıncı';
+ }
+ var a = number % 10,
+ b = number % 100 - a,
+ c = number >= 100 ? 100 : null;
+ return number + (suffixes[a] || suffixes[b] || suffixes[c]);
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return az;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/be.js b/www/wiki/resources/lib/moment/locale/be.js
new file mode 100644
index 00000000..83025fdc
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/be.js
@@ -0,0 +1,134 @@
+//! moment.js locale configuration
+//! locale : Belarusian [be]
+//! author : Dmitry Demidov : https://github.com/demidov91
+//! author: Praleska: http://praleska.pro/
+//! Author : Menelion Elensúle : https://github.com/Oire
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function plural(word, num) {
+ var forms = word.split('_');
+ return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+}
+function relativeTimeWithPlural(number, withoutSuffix, key) {
+ var format = {
+ 'mm': withoutSuffix ? 'хвіліна_хвіліны_хвілін' : 'хвіліну_хвіліны_хвілін',
+ 'hh': withoutSuffix ? 'гадзіна_гадзіны_гадзін' : 'гадзіну_гадзіны_гадзін',
+ 'dd': 'дзень_дні_дзён',
+ 'MM': 'месяц_месяцы_месяцаў',
+ 'yy': 'год_гады_гадоў'
+ };
+ if (key === 'm') {
+ return withoutSuffix ? 'хвіліна' : 'хвіліну';
+ }
+ else if (key === 'h') {
+ return withoutSuffix ? 'гадзіна' : 'гадзіну';
+ }
+ else {
+ return number + ' ' + plural(format[key], +number);
+ }
+}
+
+var be = moment.defineLocale('be', {
+ months : {
+ format: 'студзеня_лютага_сакавіка_красавіка_траўня_чэрвеня_ліпеня_жніўня_верасня_кастрычніка_лістапада_снежня'.split('_'),
+ standalone: 'студзень_люты_сакавік_красавік_травень_чэрвень_ліпень_жнівень_верасень_кастрычнік_лістапад_снежань'.split('_')
+ },
+ monthsShort : 'студ_лют_сак_крас_трав_чэрв_ліп_жнів_вер_каст_ліст_снеж'.split('_'),
+ weekdays : {
+ format: 'нядзелю_панядзелак_аўторак_сераду_чацвер_пятніцу_суботу'.split('_'),
+ standalone: 'нядзеля_панядзелак_аўторак_серада_чацвер_пятніца_субота'.split('_'),
+ isFormat: /\[ ?[Вв] ?(?:мінулую|наступную)? ?\] ?dddd/
+ },
+ weekdaysShort : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
+ weekdaysMin : 'нд_пн_ат_ср_чц_пт_сб'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY г.',
+ LLL : 'D MMMM YYYY г., HH:mm',
+ LLLL : 'dddd, D MMMM YYYY г., HH:mm'
+ },
+ calendar : {
+ sameDay: '[Сёння ў] LT',
+ nextDay: '[Заўтра ў] LT',
+ lastDay: '[Учора ў] LT',
+ nextWeek: function () {
+ return '[У] dddd [ў] LT';
+ },
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ case 5:
+ case 6:
+ return '[У мінулую] dddd [ў] LT';
+ case 1:
+ case 2:
+ case 4:
+ return '[У мінулы] dddd [ў] LT';
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'праз %s',
+ past : '%s таму',
+ s : 'некалькі секунд',
+ m : relativeTimeWithPlural,
+ mm : relativeTimeWithPlural,
+ h : relativeTimeWithPlural,
+ hh : relativeTimeWithPlural,
+ d : 'дзень',
+ dd : relativeTimeWithPlural,
+ M : 'месяц',
+ MM : relativeTimeWithPlural,
+ y : 'год',
+ yy : relativeTimeWithPlural
+ },
+ meridiemParse: /ночы|раніцы|дня|вечара/,
+ isPM : function (input) {
+ return /^(дня|вечара)$/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'ночы';
+ } else if (hour < 12) {
+ return 'раніцы';
+ } else if (hour < 17) {
+ return 'дня';
+ } else {
+ return 'вечара';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(і|ы|га)/,
+ ordinal: function (number, period) {
+ switch (period) {
+ case 'M':
+ case 'd':
+ case 'DDD':
+ case 'w':
+ case 'W':
+ return (number % 10 === 2 || number % 10 === 3) && (number % 100 !== 12 && number % 100 !== 13) ? number + '-і' : number + '-ы';
+ case 'D':
+ return number + '-га';
+ default:
+ return number;
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return be;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/bg.js b/www/wiki/resources/lib/moment/locale/bg.js
new file mode 100644
index 00000000..ee06d197
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/bg.js
@@ -0,0 +1,90 @@
+//! moment.js locale configuration
+//! locale : Bulgarian [bg]
+//! author : Krasen Borisov : https://github.com/kraz
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var bg = moment.defineLocale('bg', {
+ months : 'януари_февруари_март_април_май_юни_юли_август_септември_октомври_ноември_декември'.split('_'),
+ monthsShort : 'янр_фев_мар_апр_май_юни_юли_авг_сеп_окт_ное_дек'.split('_'),
+ weekdays : 'неделя_понеделник_вторник_сряда_четвъртък_петък_събота'.split('_'),
+ weekdaysShort : 'нед_пон_вто_сря_чет_пет_съб'.split('_'),
+ weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'D.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY H:mm',
+ LLLL : 'dddd, D MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[Днес в] LT',
+ nextDay : '[Утре в] LT',
+ nextWeek : 'dddd [в] LT',
+ lastDay : '[Вчера в] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ case 6:
+ return '[В изминалата] dddd [в] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[В изминалия] dddd [в] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'след %s',
+ past : 'преди %s',
+ s : 'няколко секунди',
+ m : 'минута',
+ mm : '%d минути',
+ h : 'час',
+ hh : '%d часа',
+ d : 'ден',
+ dd : '%d дни',
+ M : 'месец',
+ MM : '%d месеца',
+ y : 'година',
+ yy : '%d години'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
+ ordinal : function (number) {
+ var lastDigit = number % 10,
+ last2Digits = number % 100;
+ if (number === 0) {
+ return number + '-ев';
+ } else if (last2Digits === 0) {
+ return number + '-ен';
+ } else if (last2Digits > 10 && last2Digits < 20) {
+ return number + '-ти';
+ } else if (lastDigit === 1) {
+ return number + '-ви';
+ } else if (lastDigit === 2) {
+ return number + '-ри';
+ } else if (lastDigit === 7 || lastDigit === 8) {
+ return number + '-ми';
+ } else {
+ return number + '-ти';
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return bg;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/bm.js b/www/wiki/resources/lib/moment/locale/bm.js
new file mode 100644
index 00000000..1de2b5e9
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/bm.js
@@ -0,0 +1,59 @@
+//! moment.js locale configuration
+//! locale : Bambara [bm]
+//! author : Estelle Comment : https://github.com/estellecomment
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+// Language contact person : Abdoufata Kane : https://github.com/abdoufata
+
+var bm = moment.defineLocale('bm', {
+ months : 'Zanwuyekalo_Fewuruyekalo_Marisikalo_Awirilikalo_Mɛkalo_Zuwɛnkalo_Zuluyekalo_Utikalo_Sɛtanburukalo_ɔkutɔburukalo_Nowanburukalo_Desanburukalo'.split('_'),
+ monthsShort : 'Zan_Few_Mar_Awi_Mɛ_Zuw_Zul_Uti_Sɛt_ɔku_Now_Des'.split('_'),
+ weekdays : 'Kari_Ntɛnɛn_Tarata_Araba_Alamisa_Juma_Sibiri'.split('_'),
+ weekdaysShort : 'Kar_Ntɛ_Tar_Ara_Ala_Jum_Sib'.split('_'),
+ weekdaysMin : 'Ka_Nt_Ta_Ar_Al_Ju_Si'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'MMMM [tile] D [san] YYYY',
+ LLL : 'MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm',
+ LLLL : 'dddd MMMM [tile] D [san] YYYY [lɛrɛ] HH:mm'
+ },
+ calendar : {
+ sameDay : '[Bi lɛrɛ] LT',
+ nextDay : '[Sini lɛrɛ] LT',
+ nextWeek : 'dddd [don lɛrɛ] LT',
+ lastDay : '[Kunu lɛrɛ] LT',
+ lastWeek : 'dddd [tɛmɛnen lɛrɛ] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s kɔnɔ',
+ past : 'a bɛ %s bɔ',
+ s : 'sanga dama dama',
+ m : 'miniti kelen',
+ mm : 'miniti %d',
+ h : 'lɛrɛ kelen',
+ hh : 'lɛrɛ %d',
+ d : 'tile kelen',
+ dd : 'tile %d',
+ M : 'kalo kelen',
+ MM : 'kalo %d',
+ y : 'san kelen',
+ yy : 'san %d'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return bm;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/bn.js b/www/wiki/resources/lib/moment/locale/bn.js
new file mode 100644
index 00000000..b6f942a6
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/bn.js
@@ -0,0 +1,119 @@
+//! moment.js locale configuration
+//! locale : Bengali [bn]
+//! author : Kaushik Gandhi : https://github.com/kaushikgandhi
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '১',
+ '2': '২',
+ '3': '৩',
+ '4': '৪',
+ '5': '৫',
+ '6': '৬',
+ '7': '৭',
+ '8': '৮',
+ '9': '৯',
+ '0': '০'
+};
+var numberMap = {
+ '১': '1',
+ '২': '2',
+ '৩': '3',
+ '৪': '4',
+ '৫': '5',
+ '৬': '6',
+ '৭': '7',
+ '৮': '8',
+ '৯': '9',
+ '০': '0'
+};
+
+var bn = moment.defineLocale('bn', {
+ months : 'জানুয়ারী_ফেব্রুয়ারি_মার্চ_এপ্রিল_মে_জুন_জুলাই_আগস্ট_সেপ্টেম্বর_অক্টোবর_নভেম্বর_ডিসেম্বর'.split('_'),
+ monthsShort : 'জানু_ফেব_মার্চ_এপ্র_মে_জুন_জুল_আগ_সেপ্ট_অক্টো_নভে_ডিসে'.split('_'),
+ weekdays : 'রবিবার_সোমবার_মঙ্গলবার_বুধবার_বৃহস্পতিবার_শুক্রবার_শনিবার'.split('_'),
+ weekdaysShort : 'রবি_সোম_মঙ্গল_বুধ_বৃহস্পতি_শুক্র_শনি'.split('_'),
+ weekdaysMin : 'রবি_সোম_মঙ্গ_বুধ_বৃহঃ_শুক্র_শনি'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm সময়',
+ LTS : 'A h:mm:ss সময়',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm সময়',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm সময়'
+ },
+ calendar : {
+ sameDay : '[আজ] LT',
+ nextDay : '[আগামীকাল] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[গতকাল] LT',
+ lastWeek : '[গত] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s পরে',
+ past : '%s আগে',
+ s : 'কয়েক সেকেন্ড',
+ m : 'এক মিনিট',
+ mm : '%d মিনিট',
+ h : 'এক ঘন্টা',
+ hh : '%d ঘন্টা',
+ d : 'এক দিন',
+ dd : '%d দিন',
+ M : 'এক মাস',
+ MM : '%d মাস',
+ y : 'এক বছর',
+ yy : '%d বছর'
+ },
+ preparse: function (string) {
+ return string.replace(/[১২৩৪৫৬৭৮৯০]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ meridiemParse: /রাত|সকাল|দুপুর|বিকাল|রাত/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if ((meridiem === 'রাত' && hour >= 4) ||
+ (meridiem === 'দুপুর' && hour < 5) ||
+ meridiem === 'বিকাল') {
+ return hour + 12;
+ } else {
+ return hour;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'রাত';
+ } else if (hour < 10) {
+ return 'সকাল';
+ } else if (hour < 17) {
+ return 'দুপুর';
+ } else if (hour < 20) {
+ return 'বিকাল';
+ } else {
+ return 'রাত';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return bn;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/bo.js b/www/wiki/resources/lib/moment/locale/bo.js
new file mode 100644
index 00000000..eb6db476
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/bo.js
@@ -0,0 +1,119 @@
+//! moment.js locale configuration
+//! locale : Tibetan [bo]
+//! author : Thupten N. Chakrishar : https://github.com/vajradog
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '༡',
+ '2': '༢',
+ '3': '༣',
+ '4': '༤',
+ '5': '༥',
+ '6': '༦',
+ '7': '༧',
+ '8': '༨',
+ '9': '༩',
+ '0': '༠'
+};
+var numberMap = {
+ '༡': '1',
+ '༢': '2',
+ '༣': '3',
+ '༤': '4',
+ '༥': '5',
+ '༦': '6',
+ '༧': '7',
+ '༨': '8',
+ '༩': '9',
+ '༠': '0'
+};
+
+var bo = moment.defineLocale('bo', {
+ months : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
+ monthsShort : 'ཟླ་བ་དང་པོ_ཟླ་བ་གཉིས་པ_ཟླ་བ་གསུམ་པ_ཟླ་བ་བཞི་པ_ཟླ་བ་ལྔ་པ_ཟླ་བ་དྲུག་པ_ཟླ་བ་བདུན་པ_ཟླ་བ་བརྒྱད་པ_ཟླ་བ་དགུ་པ_ཟླ་བ་བཅུ་པ_ཟླ་བ་བཅུ་གཅིག་པ_ཟླ་བ་བཅུ་གཉིས་པ'.split('_'),
+ weekdays : 'གཟའ་ཉི་མ་_གཟའ་ཟླ་བ་_གཟའ་མིག་དམར་_གཟའ་ལྷག་པ་_གཟའ་ཕུར་བུ_གཟའ་པ་སངས་_གཟའ་སྤེན་པ་'.split('_'),
+ weekdaysShort : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
+ weekdaysMin : 'ཉི་མ་_ཟླ་བ་_མིག་དམར་_ལྷག་པ་_ཕུར་བུ_པ་སངས་_སྤེན་པ་'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm',
+ LTS : 'A h:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm'
+ },
+ calendar : {
+ sameDay : '[དི་རིང] LT',
+ nextDay : '[སང་ཉིན] LT',
+ nextWeek : '[བདུན་ཕྲག་རྗེས་མ], LT',
+ lastDay : '[ཁ་སང] LT',
+ lastWeek : '[བདུན་ཕྲག་མཐའ་མ] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s ལ་',
+ past : '%s སྔན་ལ',
+ s : 'ལམ་སང',
+ m : 'སྐར་མ་གཅིག',
+ mm : '%d སྐར་མ',
+ h : 'ཆུ་ཚོད་གཅིག',
+ hh : '%d ཆུ་ཚོད',
+ d : 'ཉིན་གཅིག',
+ dd : '%d ཉིན་',
+ M : 'ཟླ་བ་གཅིག',
+ MM : '%d ཟླ་བ',
+ y : 'ལོ་གཅིག',
+ yy : '%d ལོ'
+ },
+ preparse: function (string) {
+ return string.replace(/[༡༢༣༤༥༦༧༨༩༠]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ meridiemParse: /མཚན་མོ|ཞོགས་ཀས|ཉིན་གུང|དགོང་དག|མཚན་མོ/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if ((meridiem === 'མཚན་མོ' && hour >= 4) ||
+ (meridiem === 'ཉིན་གུང' && hour < 5) ||
+ meridiem === 'དགོང་དག') {
+ return hour + 12;
+ } else {
+ return hour;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'མཚན་མོ';
+ } else if (hour < 10) {
+ return 'ཞོགས་ཀས';
+ } else if (hour < 17) {
+ return 'ཉིན་གུང';
+ } else if (hour < 20) {
+ return 'དགོང་དག';
+ } else {
+ return 'མཚན་མོ';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return bo;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/br.js b/www/wiki/resources/lib/moment/locale/br.js
new file mode 100644
index 00000000..72330631
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/br.js
@@ -0,0 +1,108 @@
+//! moment.js locale configuration
+//! locale : Breton [br]
+//! author : Jean-Baptiste Le Duigou : https://github.com/jbleduigou
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function relativeTimeWithMutation(number, withoutSuffix, key) {
+ var format = {
+ 'mm': 'munutenn',
+ 'MM': 'miz',
+ 'dd': 'devezh'
+ };
+ return number + ' ' + mutation(format[key], number);
+}
+function specialMutationForYears(number) {
+ switch (lastNumber(number)) {
+ case 1:
+ case 3:
+ case 4:
+ case 5:
+ case 9:
+ return number + ' bloaz';
+ default:
+ return number + ' vloaz';
+ }
+}
+function lastNumber(number) {
+ if (number > 9) {
+ return lastNumber(number % 10);
+ }
+ return number;
+}
+function mutation(text, number) {
+ if (number === 2) {
+ return softMutation(text);
+ }
+ return text;
+}
+function softMutation(text) {
+ var mutationTable = {
+ 'm': 'v',
+ 'b': 'v',
+ 'd': 'z'
+ };
+ if (mutationTable[text.charAt(0)] === undefined) {
+ return text;
+ }
+ return mutationTable[text.charAt(0)] + text.substring(1);
+}
+
+var br = moment.defineLocale('br', {
+ months : 'Genver_C\'hwevrer_Meurzh_Ebrel_Mae_Mezheven_Gouere_Eost_Gwengolo_Here_Du_Kerzu'.split('_'),
+ monthsShort : 'Gen_C\'hwe_Meu_Ebr_Mae_Eve_Gou_Eos_Gwe_Her_Du_Ker'.split('_'),
+ weekdays : 'Sul_Lun_Meurzh_Merc\'her_Yaou_Gwener_Sadorn'.split('_'),
+ weekdaysShort : 'Sul_Lun_Meu_Mer_Yao_Gwe_Sad'.split('_'),
+ weekdaysMin : 'Su_Lu_Me_Mer_Ya_Gw_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'h[e]mm A',
+ LTS : 'h[e]mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D [a viz] MMMM YYYY',
+ LLL : 'D [a viz] MMMM YYYY h[e]mm A',
+ LLLL : 'dddd, D [a viz] MMMM YYYY h[e]mm A'
+ },
+ calendar : {
+ sameDay : '[Hiziv da] LT',
+ nextDay : '[Warc\'hoazh da] LT',
+ nextWeek : 'dddd [da] LT',
+ lastDay : '[Dec\'h da] LT',
+ lastWeek : 'dddd [paset da] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'a-benn %s',
+ past : '%s \'zo',
+ s : 'un nebeud segondennoù',
+ m : 'ur vunutenn',
+ mm : relativeTimeWithMutation,
+ h : 'un eur',
+ hh : '%d eur',
+ d : 'un devezh',
+ dd : relativeTimeWithMutation,
+ M : 'ur miz',
+ MM : relativeTimeWithMutation,
+ y : 'ur bloaz',
+ yy : specialMutationForYears
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(añ|vet)/,
+ ordinal : function (number) {
+ var output = (number === 1) ? 'añ' : 'vet';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return br;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/bs.js b/www/wiki/resources/lib/moment/locale/bs.js
new file mode 100644
index 00000000..760a7867
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/bs.js
@@ -0,0 +1,143 @@
+//! moment.js locale configuration
+//! locale : Bosnian [bs]
+//! author : Nedim Cholich : https://github.com/frontyard
+//! based on (hr) translation by Bojan Marković
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function translate(number, withoutSuffix, key) {
+ var result = number + ' ';
+ switch (key) {
+ case 'm':
+ return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+ case 'mm':
+ if (number === 1) {
+ result += 'minuta';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'minute';
+ } else {
+ result += 'minuta';
+ }
+ return result;
+ case 'h':
+ return withoutSuffix ? 'jedan sat' : 'jednog sata';
+ case 'hh':
+ if (number === 1) {
+ result += 'sat';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'sata';
+ } else {
+ result += 'sati';
+ }
+ return result;
+ case 'dd':
+ if (number === 1) {
+ result += 'dan';
+ } else {
+ result += 'dana';
+ }
+ return result;
+ case 'MM':
+ if (number === 1) {
+ result += 'mjesec';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'mjeseca';
+ } else {
+ result += 'mjeseci';
+ }
+ return result;
+ case 'yy':
+ if (number === 1) {
+ result += 'godina';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'godine';
+ } else {
+ result += 'godina';
+ }
+ return result;
+ }
+}
+
+var bs = moment.defineLocale('bs', {
+ months : 'januar_februar_mart_april_maj_juni_juli_august_septembar_oktobar_novembar_decembar'.split('_'),
+ monthsShort : 'jan._feb._mar._apr._maj._jun._jul._aug._sep._okt._nov._dec.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
+ weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
+ weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[danas u] LT',
+ nextDay : '[sutra u] LT',
+ nextWeek : function () {
+ switch (this.day()) {
+ case 0:
+ return '[u] [nedjelju] [u] LT';
+ case 3:
+ return '[u] [srijedu] [u] LT';
+ case 6:
+ return '[u] [subotu] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[u] dddd [u] LT';
+ }
+ },
+ lastDay : '[jučer u] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ return '[prošlu] dddd [u] LT';
+ case 6:
+ return '[prošle] [subote] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[prošli] dddd [u] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : 'prije %s',
+ s : 'par sekundi',
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : 'dan',
+ dd : translate,
+ M : 'mjesec',
+ MM : translate,
+ y : 'godinu',
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return bs;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ca.js b/www/wiki/resources/lib/moment/locale/ca.js
new file mode 100644
index 00000000..8064a5d8
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ca.js
@@ -0,0 +1,88 @@
+//! moment.js locale configuration
+//! locale : Catalan [ca]
+//! author : Juan G. Hurtado : https://github.com/juanghurtado
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ca = moment.defineLocale('ca', {
+ months : {
+ standalone: 'gener_febrer_març_abril_maig_juny_juliol_agost_setembre_octubre_novembre_desembre'.split('_'),
+ format: 'de gener_de febrer_de març_d\'abril_de maig_de juny_de juliol_d\'agost_de setembre_d\'octubre_de novembre_de desembre'.split('_'),
+ isFormat: /D[oD]?(\s)+MMMM/
+ },
+ monthsShort : 'gen._febr._març_abr._maig_juny_jul._ag._set._oct._nov._des.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'diumenge_dilluns_dimarts_dimecres_dijous_divendres_dissabte'.split('_'),
+ weekdaysShort : 'dg._dl._dt._dc._dj._dv._ds.'.split('_'),
+ weekdaysMin : 'dg_dl_dt_dc_dj_dv_ds'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM [de] YYYY',
+ ll : 'D MMM YYYY',
+ LLL : 'D MMMM [de] YYYY [a les] H:mm',
+ lll : 'D MMM YYYY, H:mm',
+ LLLL : 'dddd D MMMM [de] YYYY [a les] H:mm',
+ llll : 'ddd D MMM YYYY, H:mm'
+ },
+ calendar : {
+ sameDay : function () {
+ return '[avui a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+ },
+ nextDay : function () {
+ return '[demà a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+ },
+ nextWeek : function () {
+ return 'dddd [a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+ },
+ lastDay : function () {
+ return '[ahir a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+ },
+ lastWeek : function () {
+ return '[el] dddd [passat a ' + ((this.hours() !== 1) ? 'les' : 'la') + '] LT';
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'd\'aquí %s',
+ past : 'fa %s',
+ s : 'uns segons',
+ m : 'un minut',
+ mm : '%d minuts',
+ h : 'una hora',
+ hh : '%d hores',
+ d : 'un dia',
+ dd : '%d dies',
+ M : 'un mes',
+ MM : '%d mesos',
+ y : 'un any',
+ yy : '%d anys'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(r|n|t|è|a)/,
+ ordinal : function (number, period) {
+ var output = (number === 1) ? 'r' :
+ (number === 2) ? 'n' :
+ (number === 3) ? 'r' :
+ (number === 4) ? 't' : 'è';
+ if (period === 'w' || period === 'W') {
+ output = 'a';
+ }
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return ca;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/cs.js b/www/wiki/resources/lib/moment/locale/cs.js
new file mode 100644
index 00000000..952dc49e
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/cs.js
@@ -0,0 +1,172 @@
+//! moment.js locale configuration
+//! locale : Czech [cs]
+//! author : petrbela : https://github.com/petrbela
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = 'leden_únor_březen_duben_květen_červen_červenec_srpen_září_říjen_listopad_prosinec'.split('_');
+var monthsShort = 'led_úno_bře_dub_kvě_čvn_čvc_srp_zář_říj_lis_pro'.split('_');
+function plural(n) {
+ return (n > 1) && (n < 5) && (~~(n / 10) !== 1);
+}
+function translate(number, withoutSuffix, key, isFuture) {
+ var result = number + ' ';
+ switch (key) {
+ case 's': // a few seconds / in a few seconds / a few seconds ago
+ return (withoutSuffix || isFuture) ? 'pár sekund' : 'pár sekundami';
+ case 'm': // a minute / in a minute / a minute ago
+ return withoutSuffix ? 'minuta' : (isFuture ? 'minutu' : 'minutou');
+ case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'minuty' : 'minut');
+ } else {
+ return result + 'minutami';
+ }
+ break;
+ case 'h': // an hour / in an hour / an hour ago
+ return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
+ case 'hh': // 9 hours / in 9 hours / 9 hours ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'hodiny' : 'hodin');
+ } else {
+ return result + 'hodinami';
+ }
+ break;
+ case 'd': // a day / in a day / a day ago
+ return (withoutSuffix || isFuture) ? 'den' : 'dnem';
+ case 'dd': // 9 days / in 9 days / 9 days ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'dny' : 'dní');
+ } else {
+ return result + 'dny';
+ }
+ break;
+ case 'M': // a month / in a month / a month ago
+ return (withoutSuffix || isFuture) ? 'měsíc' : 'měsícem';
+ case 'MM': // 9 months / in 9 months / 9 months ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'měsíce' : 'měsíců');
+ } else {
+ return result + 'měsíci';
+ }
+ break;
+ case 'y': // a year / in a year / a year ago
+ return (withoutSuffix || isFuture) ? 'rok' : 'rokem';
+ case 'yy': // 9 years / in 9 years / 9 years ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'roky' : 'let');
+ } else {
+ return result + 'lety';
+ }
+ break;
+ }
+}
+
+var cs = moment.defineLocale('cs', {
+ months : months,
+ monthsShort : monthsShort,
+ monthsParse : (function (months, monthsShort) {
+ var i, _monthsParse = [];
+ for (i = 0; i < 12; i++) {
+ // use custom parser to solve problem with July (červenec)
+ _monthsParse[i] = new RegExp('^' + months[i] + '$|^' + monthsShort[i] + '$', 'i');
+ }
+ return _monthsParse;
+ }(months, monthsShort)),
+ shortMonthsParse : (function (monthsShort) {
+ var i, _shortMonthsParse = [];
+ for (i = 0; i < 12; i++) {
+ _shortMonthsParse[i] = new RegExp('^' + monthsShort[i] + '$', 'i');
+ }
+ return _shortMonthsParse;
+ }(monthsShort)),
+ longMonthsParse : (function (months) {
+ var i, _longMonthsParse = [];
+ for (i = 0; i < 12; i++) {
+ _longMonthsParse[i] = new RegExp('^' + months[i] + '$', 'i');
+ }
+ return _longMonthsParse;
+ }(months)),
+ weekdays : 'neděle_pondělí_úterý_středa_čtvrtek_pátek_sobota'.split('_'),
+ weekdaysShort : 'ne_po_út_st_čt_pá_so'.split('_'),
+ weekdaysMin : 'ne_po_út_st_čt_pá_so'.split('_'),
+ longDateFormat : {
+ LT: 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd D. MMMM YYYY H:mm',
+ l : 'D. M. YYYY'
+ },
+ calendar : {
+ sameDay: '[dnes v] LT',
+ nextDay: '[zítra v] LT',
+ nextWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[v neděli v] LT';
+ case 1:
+ case 2:
+ return '[v] dddd [v] LT';
+ case 3:
+ return '[ve středu v] LT';
+ case 4:
+ return '[ve čtvrtek v] LT';
+ case 5:
+ return '[v pátek v] LT';
+ case 6:
+ return '[v sobotu v] LT';
+ }
+ },
+ lastDay: '[včera v] LT',
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[minulou neděli v] LT';
+ case 1:
+ case 2:
+ return '[minulé] dddd [v] LT';
+ case 3:
+ return '[minulou středu v] LT';
+ case 4:
+ case 5:
+ return '[minulý] dddd [v] LT';
+ case 6:
+ return '[minulou sobotu v] LT';
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : 'před %s',
+ s : translate,
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : translate,
+ dd : translate,
+ M : translate,
+ MM : translate,
+ y : translate,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return cs;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/cv.js b/www/wiki/resources/lib/moment/locale/cv.js
new file mode 100644
index 00000000..6d207798
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/cv.js
@@ -0,0 +1,63 @@
+//! moment.js locale configuration
+//! locale : Chuvash [cv]
+//! author : Anatoly Mironov : https://github.com/mirontoli
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var cv = moment.defineLocale('cv', {
+ months : 'кӑрлач_нарӑс_пуш_ака_май_ҫӗртме_утӑ_ҫурла_авӑн_юпа_чӳк_раштав'.split('_'),
+ monthsShort : 'кӑр_нар_пуш_ака_май_ҫӗр_утӑ_ҫур_авн_юпа_чӳк_раш'.split('_'),
+ weekdays : 'вырсарникун_тунтикун_ытларикун_юнкун_кӗҫнерникун_эрнекун_шӑматкун'.split('_'),
+ weekdaysShort : 'выр_тун_ытл_юн_кӗҫ_эрн_шӑм'.split('_'),
+ weekdaysMin : 'вр_тн_ыт_юн_кҫ_эр_шм'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD-MM-YYYY',
+ LL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ]',
+ LLL : 'YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm',
+ LLLL : 'dddd, YYYY [ҫулхи] MMMM [уйӑхӗн] D[-мӗшӗ], HH:mm'
+ },
+ calendar : {
+ sameDay: '[Паян] LT [сехетре]',
+ nextDay: '[Ыран] LT [сехетре]',
+ lastDay: '[Ӗнер] LT [сехетре]',
+ nextWeek: '[Ҫитес] dddd LT [сехетре]',
+ lastWeek: '[Иртнӗ] dddd LT [сехетре]',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : function (output) {
+ var affix = /сехет$/i.exec(output) ? 'рен' : /ҫул$/i.exec(output) ? 'тан' : 'ран';
+ return output + affix;
+ },
+ past : '%s каялла',
+ s : 'пӗр-ик ҫеккунт',
+ m : 'пӗр минут',
+ mm : '%d минут',
+ h : 'пӗр сехет',
+ hh : '%d сехет',
+ d : 'пӗр кун',
+ dd : '%d кун',
+ M : 'пӗр уйӑх',
+ MM : '%d уйӑх',
+ y : 'пӗр ҫул',
+ yy : '%d ҫул'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-мӗш/,
+ ordinal : '%d-мӗш',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return cv;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/cy.js b/www/wiki/resources/lib/moment/locale/cy.js
new file mode 100644
index 00000000..c570c227
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/cy.js
@@ -0,0 +1,81 @@
+//! moment.js locale configuration
+//! locale : Welsh [cy]
+//! author : Robert Allen : https://github.com/robgallen
+//! author : https://github.com/ryangreaves
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var cy = moment.defineLocale('cy', {
+ months: 'Ionawr_Chwefror_Mawrth_Ebrill_Mai_Mehefin_Gorffennaf_Awst_Medi_Hydref_Tachwedd_Rhagfyr'.split('_'),
+ monthsShort: 'Ion_Chwe_Maw_Ebr_Mai_Meh_Gor_Aws_Med_Hyd_Tach_Rhag'.split('_'),
+ weekdays: 'Dydd Sul_Dydd Llun_Dydd Mawrth_Dydd Mercher_Dydd Iau_Dydd Gwener_Dydd Sadwrn'.split('_'),
+ weekdaysShort: 'Sul_Llun_Maw_Mer_Iau_Gwe_Sad'.split('_'),
+ weekdaysMin: 'Su_Ll_Ma_Me_Ia_Gw_Sa'.split('_'),
+ weekdaysParseExact : true,
+ // time formats are the same as en-gb
+ longDateFormat: {
+ LT: 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY HH:mm',
+ LLLL: 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar: {
+ sameDay: '[Heddiw am] LT',
+ nextDay: '[Yfory am] LT',
+ nextWeek: 'dddd [am] LT',
+ lastDay: '[Ddoe am] LT',
+ lastWeek: 'dddd [diwethaf am] LT',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: 'mewn %s',
+ past: '%s yn ôl',
+ s: 'ychydig eiliadau',
+ m: 'munud',
+ mm: '%d munud',
+ h: 'awr',
+ hh: '%d awr',
+ d: 'diwrnod',
+ dd: '%d diwrnod',
+ M: 'mis',
+ MM: '%d mis',
+ y: 'blwyddyn',
+ yy: '%d flynedd'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(fed|ain|af|il|ydd|ed|eg)/,
+ // traditional ordinal numbers above 31 are not commonly used in colloquial Welsh
+ ordinal: function (number) {
+ var b = number,
+ output = '',
+ lookup = [
+ '', 'af', 'il', 'ydd', 'ydd', 'ed', 'ed', 'ed', 'fed', 'fed', 'fed', // 1af to 10fed
+ 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'eg', 'fed', 'eg', 'fed' // 11eg to 20fed
+ ];
+ if (b > 20) {
+ if (b === 40 || b === 50 || b === 60 || b === 80 || b === 100) {
+ output = 'fed'; // not 30ain, 70ain or 90ain
+ } else {
+ output = 'ain';
+ }
+ } else if (b > 0) {
+ output = lookup[b];
+ }
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return cy;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/da.js b/www/wiki/resources/lib/moment/locale/da.js
new file mode 100644
index 00000000..42d5f169
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/da.js
@@ -0,0 +1,60 @@
+//! moment.js locale configuration
+//! locale : Danish [da]
+//! author : Ulrik Nielsen : https://github.com/mrbase
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var da = moment.defineLocale('da', {
+ months : 'januar_februar_marts_april_maj_juni_juli_august_september_oktober_november_december'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
+ weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
+ weekdaysShort : 'søn_man_tir_ons_tor_fre_lør'.split('_'),
+ weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY HH:mm',
+ LLLL : 'dddd [d.] D. MMMM YYYY [kl.] HH:mm'
+ },
+ calendar : {
+ sameDay : '[i dag kl.] LT',
+ nextDay : '[i morgen kl.] LT',
+ nextWeek : 'på dddd [kl.] LT',
+ lastDay : '[i går kl.] LT',
+ lastWeek : '[i] dddd[s kl.] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'om %s',
+ past : '%s siden',
+ s : 'få sekunder',
+ m : 'et minut',
+ mm : '%d minutter',
+ h : 'en time',
+ hh : '%d timer',
+ d : 'en dag',
+ dd : '%d dage',
+ M : 'en måned',
+ MM : '%d måneder',
+ y : 'et år',
+ yy : '%d år'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return da;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/de-at.js b/www/wiki/resources/lib/moment/locale/de-at.js
new file mode 100644
index 00000000..8755e421
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/de-at.js
@@ -0,0 +1,79 @@
+//! moment.js locale configuration
+//! locale : German (Austria) [de-at]
+//! author : lluchs : https://github.com/lluchs
+//! author: Menelion Elensúle: https://github.com/Oire
+//! author : Martin Groller : https://github.com/MadMG
+//! author : Mikolaj Dadela : https://github.com/mik01aj
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 'm': ['eine Minute', 'einer Minute'],
+ 'h': ['eine Stunde', 'einer Stunde'],
+ 'd': ['ein Tag', 'einem Tag'],
+ 'dd': [number + ' Tage', number + ' Tagen'],
+ 'M': ['ein Monat', 'einem Monat'],
+ 'MM': [number + ' Monate', number + ' Monaten'],
+ 'y': ['ein Jahr', 'einem Jahr'],
+ 'yy': [number + ' Jahre', number + ' Jahren']
+ };
+ return withoutSuffix ? format[key][0] : format[key][1];
+}
+
+var deAt = moment.defineLocale('de-at', {
+ months : 'Jänner_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+ monthsShort : 'Jän._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
+ weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
+ weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT: 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY HH:mm',
+ LLLL : 'dddd, D. MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[heute um] LT [Uhr]',
+ sameElse: 'L',
+ nextDay: '[morgen um] LT [Uhr]',
+ nextWeek: 'dddd [um] LT [Uhr]',
+ lastDay: '[gestern um] LT [Uhr]',
+ lastWeek: '[letzten] dddd [um] LT [Uhr]'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : 'vor %s',
+ s : 'ein paar Sekunden',
+ m : processRelativeTime,
+ mm : '%d Minuten',
+ h : processRelativeTime,
+ hh : '%d Stunden',
+ d : processRelativeTime,
+ dd : processRelativeTime,
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return deAt;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/de-ch.js b/www/wiki/resources/lib/moment/locale/de-ch.js
new file mode 100644
index 00000000..45de05ee
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/de-ch.js
@@ -0,0 +1,78 @@
+//! moment.js locale configuration
+//! locale : German (Switzerland) [de-ch]
+//! author : sschueller : https://github.com/sschueller
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+// based on: https://www.bk.admin.ch/dokumentation/sprachen/04915/05016/index.html?lang=de#
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 'm': ['eine Minute', 'einer Minute'],
+ 'h': ['eine Stunde', 'einer Stunde'],
+ 'd': ['ein Tag', 'einem Tag'],
+ 'dd': [number + ' Tage', number + ' Tagen'],
+ 'M': ['ein Monat', 'einem Monat'],
+ 'MM': [number + ' Monate', number + ' Monaten'],
+ 'y': ['ein Jahr', 'einem Jahr'],
+ 'yy': [number + ' Jahre', number + ' Jahren']
+ };
+ return withoutSuffix ? format[key][0] : format[key][1];
+}
+
+var deCh = moment.defineLocale('de-ch', {
+ months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+ monthsShort : 'Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
+ weekdaysShort : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+ weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT: 'HH.mm',
+ LTS: 'HH.mm.ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY HH.mm',
+ LLLL : 'dddd, D. MMMM YYYY HH.mm'
+ },
+ calendar : {
+ sameDay: '[heute um] LT [Uhr]',
+ sameElse: 'L',
+ nextDay: '[morgen um] LT [Uhr]',
+ nextWeek: 'dddd [um] LT [Uhr]',
+ lastDay: '[gestern um] LT [Uhr]',
+ lastWeek: '[letzten] dddd [um] LT [Uhr]'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : 'vor %s',
+ s : 'ein paar Sekunden',
+ m : processRelativeTime,
+ mm : '%d Minuten',
+ h : processRelativeTime,
+ hh : '%d Stunden',
+ d : processRelativeTime,
+ dd : processRelativeTime,
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return deCh;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/de.js b/www/wiki/resources/lib/moment/locale/de.js
new file mode 100644
index 00000000..f0978a33
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/de.js
@@ -0,0 +1,78 @@
+//! moment.js locale configuration
+//! locale : German [de]
+//! author : lluchs : https://github.com/lluchs
+//! author: Menelion Elensúle: https://github.com/Oire
+//! author : Mikolaj Dadela : https://github.com/mik01aj
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 'm': ['eine Minute', 'einer Minute'],
+ 'h': ['eine Stunde', 'einer Stunde'],
+ 'd': ['ein Tag', 'einem Tag'],
+ 'dd': [number + ' Tage', number + ' Tagen'],
+ 'M': ['ein Monat', 'einem Monat'],
+ 'MM': [number + ' Monate', number + ' Monaten'],
+ 'y': ['ein Jahr', 'einem Jahr'],
+ 'yy': [number + ' Jahre', number + ' Jahren']
+ };
+ return withoutSuffix ? format[key][0] : format[key][1];
+}
+
+var de = moment.defineLocale('de', {
+ months : 'Januar_Februar_März_April_Mai_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+ monthsShort : 'Jan._Feb._März_Apr._Mai_Juni_Juli_Aug._Sep._Okt._Nov._Dez.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'Sonntag_Montag_Dienstag_Mittwoch_Donnerstag_Freitag_Samstag'.split('_'),
+ weekdaysShort : 'So._Mo._Di._Mi._Do._Fr._Sa.'.split('_'),
+ weekdaysMin : 'So_Mo_Di_Mi_Do_Fr_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT: 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY HH:mm',
+ LLLL : 'dddd, D. MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[heute um] LT [Uhr]',
+ sameElse: 'L',
+ nextDay: '[morgen um] LT [Uhr]',
+ nextWeek: 'dddd [um] LT [Uhr]',
+ lastDay: '[gestern um] LT [Uhr]',
+ lastWeek: '[letzten] dddd [um] LT [Uhr]'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : 'vor %s',
+ s : 'ein paar Sekunden',
+ m : processRelativeTime,
+ mm : '%d Minuten',
+ h : processRelativeTime,
+ hh : '%d Stunden',
+ d : processRelativeTime,
+ dd : processRelativeTime,
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return de;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/dv.js b/www/wiki/resources/lib/moment/locale/dv.js
new file mode 100644
index 00000000..065df78c
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/dv.js
@@ -0,0 +1,100 @@
+//! moment.js locale configuration
+//! locale : Maldivian [dv]
+//! author : Jawish Hameed : https://github.com/jawish
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = [
+ 'ޖެނުއަރީ',
+ 'ފެބްރުއަރީ',
+ 'މާރިޗު',
+ 'އޭޕްރީލު',
+ 'މޭ',
+ 'ޖޫން',
+ 'ޖުލައި',
+ 'އޯގަސްޓު',
+ 'ސެޕްޓެމްބަރު',
+ 'އޮކްޓޯބަރު',
+ 'ނޮވެމްބަރު',
+ 'ޑިސެމްބަރު'
+];
+var weekdays = [
+ 'އާދިއްތަ',
+ 'ހޯމަ',
+ 'އަންގާރަ',
+ 'ބުދަ',
+ 'ބުރާސްފަތި',
+ 'ހުކުރު',
+ 'ހޮނިހިރު'
+];
+
+var dv = moment.defineLocale('dv', {
+ months : months,
+ monthsShort : months,
+ weekdays : weekdays,
+ weekdaysShort : weekdays,
+ weekdaysMin : 'އާދި_ހޯމަ_އަން_ބުދަ_ބުރާ_ހުކު_ހޮނި'.split('_'),
+ longDateFormat : {
+
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'D/M/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /މކ|މފ/,
+ isPM : function (input) {
+ return 'މފ' === input;
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'މކ';
+ } else {
+ return 'މފ';
+ }
+ },
+ calendar : {
+ sameDay : '[މިއަދު] LT',
+ nextDay : '[މާދަމާ] LT',
+ nextWeek : 'dddd LT',
+ lastDay : '[އިއްޔެ] LT',
+ lastWeek : '[ފާއިތުވި] dddd LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'ތެރޭގައި %s',
+ past : 'ކުރިން %s',
+ s : 'ސިކުންތުކޮޅެއް',
+ m : 'މިނިޓެއް',
+ mm : 'މިނިޓު %d',
+ h : 'ގަޑިއިރެއް',
+ hh : 'ގަޑިއިރު %d',
+ d : 'ދުވަހެއް',
+ dd : 'ދުވަސް %d',
+ M : 'މަހެއް',
+ MM : 'މަސް %d',
+ y : 'އަހަރެއް',
+ yy : 'އަހަރު %d'
+ },
+ preparse: function (string) {
+ return string.replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/,/g, '،');
+ },
+ week : {
+ dow : 7, // Sunday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return dv;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/el.js b/www/wiki/resources/lib/moment/locale/el.js
new file mode 100644
index 00000000..af1ab2cb
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/el.js
@@ -0,0 +1,100 @@
+//! moment.js locale configuration
+//! locale : Greek [el]
+//! author : Aggelos Karalias : https://github.com/mehiel
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+function isFunction(input) {
+ return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
+}
+
+
+var el = moment.defineLocale('el', {
+ monthsNominativeEl : 'Ιανουάριος_Φεβρουάριος_Μάρτιος_Απρίλιος_Μάιος_Ιούνιος_Ιούλιος_Αύγουστος_Σεπτέμβριος_Οκτώβριος_Νοέμβριος_Δεκέμβριος'.split('_'),
+ monthsGenitiveEl : 'Ιανουαρίου_Φεβρουαρίου_Μαρτίου_Απριλίου_Μαΐου_Ιουνίου_Ιουλίου_Αυγούστου_Σεπτεμβρίου_Οκτωβρίου_Νοεμβρίου_Δεκεμβρίου'.split('_'),
+ months : function (momentToFormat, format) {
+ if (!momentToFormat) {
+ return this._monthsNominativeEl;
+ } else if (typeof format === 'string' && /D/.test(format.substring(0, format.indexOf('MMMM')))) { // if there is a day number before 'MMMM'
+ return this._monthsGenitiveEl[momentToFormat.month()];
+ } else {
+ return this._monthsNominativeEl[momentToFormat.month()];
+ }
+ },
+ monthsShort : 'Ιαν_Φεβ_Μαρ_Απρ_Μαϊ_Ιουν_Ιουλ_Αυγ_Σεπ_Οκτ_Νοε_Δεκ'.split('_'),
+ weekdays : 'Κυριακή_Δευτέρα_Τρίτη_Τετάρτη_Πέμπτη_Παρασκευή_Σάββατο'.split('_'),
+ weekdaysShort : 'Κυρ_Δευ_Τρι_Τετ_Πεμ_Παρ_Σαβ'.split('_'),
+ weekdaysMin : 'Κυ_Δε_Τρ_Τε_Πε_Πα_Σα'.split('_'),
+ meridiem : function (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'μμ' : 'ΜΜ';
+ } else {
+ return isLower ? 'πμ' : 'ΠΜ';
+ }
+ },
+ isPM : function (input) {
+ return ((input + '').toLowerCase()[0] === 'μ');
+ },
+ meridiemParse : /[ΠΜ]\.?Μ?\.?/i,
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY h:mm A',
+ LLLL : 'dddd, D MMMM YYYY h:mm A'
+ },
+ calendarEl : {
+ sameDay : '[Σήμερα {}] LT',
+ nextDay : '[Αύριο {}] LT',
+ nextWeek : 'dddd [{}] LT',
+ lastDay : '[Χθες {}] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 6:
+ return '[το προηγούμενο] dddd [{}] LT';
+ default:
+ return '[την προηγούμενη] dddd [{}] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ calendar : function (key, mom) {
+ var output = this._calendarEl[key],
+ hours = mom && mom.hours();
+ if (isFunction(output)) {
+ output = output.apply(mom);
+ }
+ return output.replace('{}', (hours % 12 === 1 ? 'στη' : 'στις'));
+ },
+ relativeTime : {
+ future : 'σε %s',
+ past : '%s πριν',
+ s : 'λίγα δευτερόλεπτα',
+ m : 'ένα λεπτό',
+ mm : '%d λεπτά',
+ h : 'μία ώρα',
+ hh : '%d ώρες',
+ d : 'μία μέρα',
+ dd : '%d μέρες',
+ M : 'ένας μήνας',
+ MM : '%d μήνες',
+ y : 'ένας χρόνος',
+ yy : '%d χρόνια'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}η/,
+ ordinal: '%dη',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4st is the first week of the year.
+ }
+});
+
+return el;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/en-au.js b/www/wiki/resources/lib/moment/locale/en-au.js
new file mode 100644
index 00000000..e8a8fdc9
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/en-au.js
@@ -0,0 +1,67 @@
+//! moment.js locale configuration
+//! locale : English (Australia) [en-au]
+//! author : Jared Morse : https://github.com/jarcoal
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var enAu = moment.defineLocale('en-au', {
+ months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+ weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+ weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+ weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY h:mm A',
+ LLLL : 'dddd, D MMMM YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : '%s ago',
+ s : 'a few seconds',
+ m : 'a minute',
+ mm : '%d minutes',
+ h : 'an hour',
+ hh : '%d hours',
+ d : 'a day',
+ dd : '%d days',
+ M : 'a month',
+ MM : '%d months',
+ y : 'a year',
+ yy : '%d years'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return enAu;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/en-ca.js b/www/wiki/resources/lib/moment/locale/en-ca.js
new file mode 100644
index 00000000..3629bf1a
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/en-ca.js
@@ -0,0 +1,63 @@
+//! moment.js locale configuration
+//! locale : English (Canada) [en-ca]
+//! author : Jonathan Abourbih : https://github.com/jonbca
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var enCa = moment.defineLocale('en-ca', {
+ months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+ weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+ weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+ weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'YYYY-MM-DD',
+ LL : 'MMMM D, YYYY',
+ LLL : 'MMMM D, YYYY h:mm A',
+ LLLL : 'dddd, MMMM D, YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : '%s ago',
+ s : 'a few seconds',
+ m : 'a minute',
+ mm : '%d minutes',
+ h : 'an hour',
+ hh : '%d hours',
+ d : 'a day',
+ dd : '%d days',
+ M : 'a month',
+ MM : '%d months',
+ y : 'a year',
+ yy : '%d years'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ }
+});
+
+return enCa;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/en-gb.js b/www/wiki/resources/lib/moment/locale/en-gb.js
new file mode 100644
index 00000000..fe48a78c
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/en-gb.js
@@ -0,0 +1,67 @@
+//! moment.js locale configuration
+//! locale : English (United Kingdom) [en-gb]
+//! author : Chris Gedrim : https://github.com/chrisgedrim
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var enGb = moment.defineLocale('en-gb', {
+ months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
+ weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
+ weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
+ weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'in %s',
+ past : '%s ago',
+ s : 'a few seconds',
+ m : 'a minute',
+ mm : '%d minutes',
+ h : 'an hour',
+ hh : '%d hours',
+ d : 'a day',
+ dd : '%d days',
+ M : 'a month',
+ MM : '%d months',
+ y : 'a year',
+ yy : '%d years'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return enGb;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/eo.js b/www/wiki/resources/lib/moment/locale/eo.js
new file mode 100644
index 00000000..8001c83c
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/eo.js
@@ -0,0 +1,73 @@
+//! moment.js locale configuration
+//! locale : Esperanto [eo]
+//! author : Colin Dean : https://github.com/colindean
+//! author : Mia Nordentoft Imperatori : https://github.com/miestasmia
+//! comment : miestasmia corrected the translation by colindean
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var eo = moment.defineLocale('eo', {
+ months : 'januaro_februaro_marto_aprilo_majo_junio_julio_aŭgusto_septembro_oktobro_novembro_decembro'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aŭg_sep_okt_nov_dec'.split('_'),
+ weekdays : 'dimanĉo_lundo_mardo_merkredo_ĵaŭdo_vendredo_sabato'.split('_'),
+ weekdaysShort : 'dim_lun_mard_merk_ĵaŭ_ven_sab'.split('_'),
+ weekdaysMin : 'di_lu_ma_me_ĵa_ve_sa'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY-MM-DD',
+ LL : 'D[-a de] MMMM, YYYY',
+ LLL : 'D[-a de] MMMM, YYYY HH:mm',
+ LLLL : 'dddd, [la] D[-a de] MMMM, YYYY HH:mm'
+ },
+ meridiemParse: /[ap]\.t\.m/i,
+ isPM: function (input) {
+ return input.charAt(0).toLowerCase() === 'p';
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'p.t.m.' : 'P.T.M.';
+ } else {
+ return isLower ? 'a.t.m.' : 'A.T.M.';
+ }
+ },
+ calendar : {
+ sameDay : '[Hodiaŭ je] LT',
+ nextDay : '[Morgaŭ je] LT',
+ nextWeek : 'dddd [je] LT',
+ lastDay : '[Hieraŭ je] LT',
+ lastWeek : '[pasinta] dddd [je] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'post %s',
+ past : 'antaŭ %s',
+ s : 'sekundoj',
+ m : 'minuto',
+ mm : '%d minutoj',
+ h : 'horo',
+ hh : '%d horoj',
+ d : 'tago',//ne 'diurno', ĉar estas uzita por proksimumo
+ dd : '%d tagoj',
+ M : 'monato',
+ MM : '%d monatoj',
+ y : 'jaro',
+ yy : '%d jaroj'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}a/,
+ ordinal : '%da',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return eo;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/es.js b/www/wiki/resources/lib/moment/locale/es.js
new file mode 100644
index 00000000..9fce89d1
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/es.js
@@ -0,0 +1,92 @@
+//! moment.js locale configuration
+//! locale : Spanish [es]
+//! author : Julio Napurí : https://github.com/julionc
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var monthsShortDot = 'ene._feb._mar._abr._may._jun._jul._ago._sep._oct._nov._dic.'.split('_');
+var monthsShort = 'ene_feb_mar_abr_may_jun_jul_ago_sep_oct_nov_dic'.split('_');
+
+var monthsParse = [/^ene/i, /^feb/i, /^mar/i, /^abr/i, /^may/i, /^jun/i, /^jul/i, /^ago/i, /^sep/i, /^oct/i, /^nov/i, /^dic/i];
+var monthsRegex = /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre|ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i;
+
+var es = moment.defineLocale('es', {
+ months : 'enero_febrero_marzo_abril_mayo_junio_julio_agosto_septiembre_octubre_noviembre_diciembre'.split('_'),
+ monthsShort : function (m, format) {
+ if (!m) {
+ return monthsShortDot;
+ } else if (/-MMM-/.test(format)) {
+ return monthsShort[m.month()];
+ } else {
+ return monthsShortDot[m.month()];
+ }
+ },
+ monthsRegex : monthsRegex,
+ monthsShortRegex : monthsRegex,
+ monthsStrictRegex : /^(enero|febrero|marzo|abril|mayo|junio|julio|agosto|septiembre|octubre|noviembre|diciembre)/i,
+ monthsShortStrictRegex : /^(ene\.?|feb\.?|mar\.?|abr\.?|may\.?|jun\.?|jul\.?|ago\.?|sep\.?|oct\.?|nov\.?|dic\.?)/i,
+ monthsParse : monthsParse,
+ longMonthsParse : monthsParse,
+ shortMonthsParse : monthsParse,
+ weekdays : 'domingo_lunes_martes_miércoles_jueves_viernes_sábado'.split('_'),
+ weekdaysShort : 'dom._lun._mar._mié._jue._vie._sáb.'.split('_'),
+ weekdaysMin : 'do_lu_ma_mi_ju_vi_sá'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D [de] MMMM [de] YYYY',
+ LLL : 'D [de] MMMM [de] YYYY H:mm',
+ LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm'
+ },
+ calendar : {
+ sameDay : function () {
+ return '[hoy a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ nextDay : function () {
+ return '[mañana a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ nextWeek : function () {
+ return 'dddd [a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ lastDay : function () {
+ return '[ayer a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ lastWeek : function () {
+ return '[el] dddd [pasado a la' + ((this.hours() !== 1) ? 's' : '') + '] LT';
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'en %s',
+ past : 'hace %s',
+ s : 'unos segundos',
+ m : 'un minuto',
+ mm : '%d minutos',
+ h : 'una hora',
+ hh : '%d horas',
+ d : 'un día',
+ dd : '%d días',
+ M : 'un mes',
+ MM : '%d meses',
+ y : 'un año',
+ yy : '%d años'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}º/,
+ ordinal : '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return es;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/et.js b/www/wiki/resources/lib/moment/locale/et.js
new file mode 100644
index 00000000..3a759e9e
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/et.js
@@ -0,0 +1,80 @@
+//! moment.js locale configuration
+//! locale : Estonian [et]
+//! author : Henry Kehlmann : https://github.com/madhenry
+//! improvements : Illimar Tambek : https://github.com/ragulka
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 's' : ['mõne sekundi', 'mõni sekund', 'paar sekundit'],
+ 'm' : ['ühe minuti', 'üks minut'],
+ 'mm': [number + ' minuti', number + ' minutit'],
+ 'h' : ['ühe tunni', 'tund aega', 'üks tund'],
+ 'hh': [number + ' tunni', number + ' tundi'],
+ 'd' : ['ühe päeva', 'üks päev'],
+ 'M' : ['kuu aja', 'kuu aega', 'üks kuu'],
+ 'MM': [number + ' kuu', number + ' kuud'],
+ 'y' : ['ühe aasta', 'aasta', 'üks aasta'],
+ 'yy': [number + ' aasta', number + ' aastat']
+ };
+ if (withoutSuffix) {
+ return format[key][2] ? format[key][2] : format[key][1];
+ }
+ return isFuture ? format[key][0] : format[key][1];
+}
+
+var et = moment.defineLocale('et', {
+ months : 'jaanuar_veebruar_märts_aprill_mai_juuni_juuli_august_september_oktoober_november_detsember'.split('_'),
+ monthsShort : 'jaan_veebr_märts_apr_mai_juuni_juuli_aug_sept_okt_nov_dets'.split('_'),
+ weekdays : 'pühapäev_esmaspäev_teisipäev_kolmapäev_neljapäev_reede_laupäev'.split('_'),
+ weekdaysShort : 'P_E_T_K_N_R_L'.split('_'),
+ weekdaysMin : 'P_E_T_K_N_R_L'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[Täna,] LT',
+ nextDay : '[Homme,] LT',
+ nextWeek : '[Järgmine] dddd LT',
+ lastDay : '[Eile,] LT',
+ lastWeek : '[Eelmine] dddd LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s pärast',
+ past : '%s tagasi',
+ s : processRelativeTime,
+ m : processRelativeTime,
+ mm : processRelativeTime,
+ h : processRelativeTime,
+ hh : processRelativeTime,
+ d : processRelativeTime,
+ dd : '%d päeva',
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return et;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/eu.js b/www/wiki/resources/lib/moment/locale/eu.js
new file mode 100644
index 00000000..e2021cfa
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/eu.js
@@ -0,0 +1,66 @@
+//! moment.js locale configuration
+//! locale : Basque [eu]
+//! author : Eneko Illarramendi : https://github.com/eillarra
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var eu = moment.defineLocale('eu', {
+ months : 'urtarrila_otsaila_martxoa_apirila_maiatza_ekaina_uztaila_abuztua_iraila_urria_azaroa_abendua'.split('_'),
+ monthsShort : 'urt._ots._mar._api._mai._eka._uzt._abu._ira._urr._aza._abe.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'igandea_astelehena_asteartea_asteazkena_osteguna_ostirala_larunbata'.split('_'),
+ weekdaysShort : 'ig._al._ar._az._og._ol._lr.'.split('_'),
+ weekdaysMin : 'ig_al_ar_az_og_ol_lr'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY-MM-DD',
+ LL : 'YYYY[ko] MMMM[ren] D[a]',
+ LLL : 'YYYY[ko] MMMM[ren] D[a] HH:mm',
+ LLLL : 'dddd, YYYY[ko] MMMM[ren] D[a] HH:mm',
+ l : 'YYYY-M-D',
+ ll : 'YYYY[ko] MMM D[a]',
+ lll : 'YYYY[ko] MMM D[a] HH:mm',
+ llll : 'ddd, YYYY[ko] MMM D[a] HH:mm'
+ },
+ calendar : {
+ sameDay : '[gaur] LT[etan]',
+ nextDay : '[bihar] LT[etan]',
+ nextWeek : 'dddd LT[etan]',
+ lastDay : '[atzo] LT[etan]',
+ lastWeek : '[aurreko] dddd LT[etan]',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s barru',
+ past : 'duela %s',
+ s : 'segundo batzuk',
+ m : 'minutu bat',
+ mm : '%d minutu',
+ h : 'ordu bat',
+ hh : '%d ordu',
+ d : 'egun bat',
+ dd : '%d egun',
+ M : 'hilabete bat',
+ MM : '%d hilabete',
+ y : 'urte bat',
+ yy : '%d urte'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return eu;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/fa.js b/www/wiki/resources/lib/moment/locale/fa.js
new file mode 100644
index 00000000..e6e5619d
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/fa.js
@@ -0,0 +1,107 @@
+//! moment.js locale configuration
+//! locale : Persian [fa]
+//! author : Ebrahim Byagowi : https://github.com/ebraminio
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '۱',
+ '2': '۲',
+ '3': '۳',
+ '4': '۴',
+ '5': '۵',
+ '6': '۶',
+ '7': '۷',
+ '8': '۸',
+ '9': '۹',
+ '0': '۰'
+};
+var numberMap = {
+ '۱': '1',
+ '۲': '2',
+ '۳': '3',
+ '۴': '4',
+ '۵': '5',
+ '۶': '6',
+ '۷': '7',
+ '۸': '8',
+ '۹': '9',
+ '۰': '0'
+};
+
+var fa = moment.defineLocale('fa', {
+ months : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
+ monthsShort : 'ژانویه_فوریه_مارس_آوریل_مه_ژوئن_ژوئیه_اوت_سپتامبر_اکتبر_نوامبر_دسامبر'.split('_'),
+ weekdays : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
+ weekdaysShort : 'یک\u200cشنبه_دوشنبه_سه\u200cشنبه_چهارشنبه_پنج\u200cشنبه_جمعه_شنبه'.split('_'),
+ weekdaysMin : 'ی_د_س_چ_پ_ج_ش'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /قبل از ظهر|بعد از ظهر/,
+ isPM: function (input) {
+ return /بعد از ظهر/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'قبل از ظهر';
+ } else {
+ return 'بعد از ظهر';
+ }
+ },
+ calendar : {
+ sameDay : '[امروز ساعت] LT',
+ nextDay : '[فردا ساعت] LT',
+ nextWeek : 'dddd [ساعت] LT',
+ lastDay : '[دیروز ساعت] LT',
+ lastWeek : 'dddd [پیش] [ساعت] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'در %s',
+ past : '%s پیش',
+ s : 'چند ثانیه',
+ m : 'یک دقیقه',
+ mm : '%d دقیقه',
+ h : 'یک ساعت',
+ hh : '%d ساعت',
+ d : 'یک روز',
+ dd : '%d روز',
+ M : 'یک ماه',
+ MM : '%d ماه',
+ y : 'یک سال',
+ yy : '%d سال'
+ },
+ preparse: function (string) {
+ return string.replace(/[۰-۹]/g, function (match) {
+ return numberMap[match];
+ }).replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ }).replace(/,/g, '،');
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}م/,
+ ordinal : '%dم',
+ week : {
+ dow : 6, // Saturday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return fa;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/fi.js b/www/wiki/resources/lib/moment/locale/fi.js
new file mode 100644
index 00000000..3eeef5c1
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/fi.js
@@ -0,0 +1,107 @@
+//! moment.js locale configuration
+//! locale : Finnish [fi]
+//! author : Tarmo Aidantausta : https://github.com/bleadof
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var numbersPast = 'nolla yksi kaksi kolme neljä viisi kuusi seitsemän kahdeksan yhdeksän'.split(' ');
+var numbersFuture = [
+ 'nolla', 'yhden', 'kahden', 'kolmen', 'neljän', 'viiden', 'kuuden',
+ numbersPast[7], numbersPast[8], numbersPast[9]
+ ];
+function translate(number, withoutSuffix, key, isFuture) {
+ var result = '';
+ switch (key) {
+ case 's':
+ return isFuture ? 'muutaman sekunnin' : 'muutama sekunti';
+ case 'm':
+ return isFuture ? 'minuutin' : 'minuutti';
+ case 'mm':
+ result = isFuture ? 'minuutin' : 'minuuttia';
+ break;
+ case 'h':
+ return isFuture ? 'tunnin' : 'tunti';
+ case 'hh':
+ result = isFuture ? 'tunnin' : 'tuntia';
+ break;
+ case 'd':
+ return isFuture ? 'päivän' : 'päivä';
+ case 'dd':
+ result = isFuture ? 'päivän' : 'päivää';
+ break;
+ case 'M':
+ return isFuture ? 'kuukauden' : 'kuukausi';
+ case 'MM':
+ result = isFuture ? 'kuukauden' : 'kuukautta';
+ break;
+ case 'y':
+ return isFuture ? 'vuoden' : 'vuosi';
+ case 'yy':
+ result = isFuture ? 'vuoden' : 'vuotta';
+ break;
+ }
+ result = verbalNumber(number, isFuture) + ' ' + result;
+ return result;
+}
+function verbalNumber(number, isFuture) {
+ return number < 10 ? (isFuture ? numbersFuture[number] : numbersPast[number]) : number;
+}
+
+var fi = moment.defineLocale('fi', {
+ months : 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'),
+ monthsShort : 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'),
+ weekdays : 'sunnuntai_maanantai_tiistai_keskiviikko_torstai_perjantai_lauantai'.split('_'),
+ weekdaysShort : 'su_ma_ti_ke_to_pe_la'.split('_'),
+ weekdaysMin : 'su_ma_ti_ke_to_pe_la'.split('_'),
+ longDateFormat : {
+ LT : 'HH.mm',
+ LTS : 'HH.mm.ss',
+ L : 'DD.MM.YYYY',
+ LL : 'Do MMMM[ta] YYYY',
+ LLL : 'Do MMMM[ta] YYYY, [klo] HH.mm',
+ LLLL : 'dddd, Do MMMM[ta] YYYY, [klo] HH.mm',
+ l : 'D.M.YYYY',
+ ll : 'Do MMM YYYY',
+ lll : 'Do MMM YYYY, [klo] HH.mm',
+ llll : 'ddd, Do MMM YYYY, [klo] HH.mm'
+ },
+ calendar : {
+ sameDay : '[tänään] [klo] LT',
+ nextDay : '[huomenna] [klo] LT',
+ nextWeek : 'dddd [klo] LT',
+ lastDay : '[eilen] [klo] LT',
+ lastWeek : '[viime] dddd[na] [klo] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s päästä',
+ past : '%s sitten',
+ s : translate,
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : translate,
+ dd : translate,
+ M : translate,
+ MM : translate,
+ y : translate,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return fi;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/fo.js b/www/wiki/resources/lib/moment/locale/fo.js
new file mode 100644
index 00000000..eec43bc6
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/fo.js
@@ -0,0 +1,60 @@
+//! moment.js locale configuration
+//! locale : Faroese [fo]
+//! author : Ragnar Johannesen : https://github.com/ragnar123
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var fo = moment.defineLocale('fo', {
+ months : 'januar_februar_mars_apríl_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
+ weekdays : 'sunnudagur_mánadagur_týsdagur_mikudagur_hósdagur_fríggjadagur_leygardagur'.split('_'),
+ weekdaysShort : 'sun_mán_týs_mik_hós_frí_ley'.split('_'),
+ weekdaysMin : 'su_má_tý_mi_hó_fr_le'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D. MMMM, YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Í dag kl.] LT',
+ nextDay : '[Í morgin kl.] LT',
+ nextWeek : 'dddd [kl.] LT',
+ lastDay : '[Í gjár kl.] LT',
+ lastWeek : '[síðstu] dddd [kl] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'um %s',
+ past : '%s síðani',
+ s : 'fá sekund',
+ m : 'ein minutt',
+ mm : '%d minuttir',
+ h : 'ein tími',
+ hh : '%d tímar',
+ d : 'ein dagur',
+ dd : '%d dagar',
+ M : 'ein mánaði',
+ MM : '%d mánaðir',
+ y : 'eitt ár',
+ yy : '%d ár'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return fo;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/fr-ca.js b/www/wiki/resources/lib/moment/locale/fr-ca.js
new file mode 100644
index 00000000..49e61d29
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/fr-ca.js
@@ -0,0 +1,74 @@
+//! moment.js locale configuration
+//! locale : French (Canada) [fr-ca]
+//! author : Jonathan Abourbih : https://github.com/jonbca
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var frCa = moment.defineLocale('fr-ca', {
+ months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
+ monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
+ weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
+ weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY-MM-DD',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Aujourd’hui à] LT',
+ nextDay : '[Demain à] LT',
+ nextWeek : 'dddd [à] LT',
+ lastDay : '[Hier à] LT',
+ lastWeek : 'dddd [dernier à] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'dans %s',
+ past : 'il y a %s',
+ s : 'quelques secondes',
+ m : 'une minute',
+ mm : '%d minutes',
+ h : 'une heure',
+ hh : '%d heures',
+ d : 'un jour',
+ dd : '%d jours',
+ M : 'un mois',
+ MM : '%d mois',
+ y : 'un an',
+ yy : '%d ans'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(er|e)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ // Words with masculine grammatical gender: mois, trimestre, jour
+ default:
+ case 'M':
+ case 'Q':
+ case 'D':
+ case 'DDD':
+ case 'd':
+ return number + (number === 1 ? 'er' : 'e');
+
+ // Words with feminine grammatical gender: semaine
+ case 'w':
+ case 'W':
+ return number + (number === 1 ? 're' : 'e');
+ }
+ }
+});
+
+return frCa;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/fr.js b/www/wiki/resources/lib/moment/locale/fr.js
new file mode 100644
index 00000000..7e4cfbce
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/fr.js
@@ -0,0 +1,83 @@
+//! moment.js locale configuration
+//! locale : French [fr]
+//! author : John Fischer : https://github.com/jfroffice
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var fr = moment.defineLocale('fr', {
+ months : 'janvier_février_mars_avril_mai_juin_juillet_août_septembre_octobre_novembre_décembre'.split('_'),
+ monthsShort : 'janv._févr._mars_avr._mai_juin_juil._août_sept._oct._nov._déc.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'dimanche_lundi_mardi_mercredi_jeudi_vendredi_samedi'.split('_'),
+ weekdaysShort : 'dim._lun._mar._mer._jeu._ven._sam.'.split('_'),
+ weekdaysMin : 'Di_Lu_Ma_Me_Je_Ve_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Aujourd’hui à] LT',
+ nextDay : '[Demain à] LT',
+ nextWeek : 'dddd [à] LT',
+ lastDay : '[Hier à] LT',
+ lastWeek : 'dddd [dernier à] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'dans %s',
+ past : 'il y a %s',
+ s : 'quelques secondes',
+ m : 'une minute',
+ mm : '%d minutes',
+ h : 'une heure',
+ hh : '%d heures',
+ d : 'un jour',
+ dd : '%d jours',
+ M : 'un mois',
+ MM : '%d mois',
+ y : 'un an',
+ yy : '%d ans'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(er|)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ // TODO: Return 'e' when day of month > 1. Move this case inside
+ // block for masculine words below.
+ // See https://github.com/moment/moment/issues/3375
+ case 'D':
+ return number + (number === 1 ? 'er' : '');
+
+ // Words with masculine grammatical gender: mois, trimestre, jour
+ default:
+ case 'M':
+ case 'Q':
+ case 'DDD':
+ case 'd':
+ return number + (number === 1 ? 'er' : 'e');
+
+ // Words with feminine grammatical gender: semaine
+ case 'w':
+ case 'W':
+ return number + (number === 1 ? 're' : 'e');
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return fr;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/fy.js b/www/wiki/resources/lib/moment/locale/fy.js
new file mode 100644
index 00000000..2ed7d5b6
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/fy.js
@@ -0,0 +1,75 @@
+//! moment.js locale configuration
+//! locale : Frisian [fy]
+//! author : Robin van der Vliet : https://github.com/robin0van0der0v
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var monthsShortWithDots = 'jan._feb._mrt._apr._mai_jun._jul._aug._sep._okt._nov._des.'.split('_');
+var monthsShortWithoutDots = 'jan_feb_mrt_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_');
+
+var fy = moment.defineLocale('fy', {
+ months : 'jannewaris_febrewaris_maart_april_maaie_juny_july_augustus_septimber_oktober_novimber_desimber'.split('_'),
+ monthsShort : function (m, format) {
+ if (!m) {
+ return monthsShortWithDots;
+ } else if (/-MMM-/.test(format)) {
+ return monthsShortWithoutDots[m.month()];
+ } else {
+ return monthsShortWithDots[m.month()];
+ }
+ },
+ monthsParseExact : true,
+ weekdays : 'snein_moandei_tiisdei_woansdei_tongersdei_freed_sneon'.split('_'),
+ weekdaysShort : 'si._mo._ti._wo._to._fr._so.'.split('_'),
+ weekdaysMin : 'Si_Mo_Ti_Wo_To_Fr_So'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD-MM-YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[hjoed om] LT',
+ nextDay: '[moarn om] LT',
+ nextWeek: 'dddd [om] LT',
+ lastDay: '[juster om] LT',
+ lastWeek: '[ôfrûne] dddd [om] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'oer %s',
+ past : '%s lyn',
+ s : 'in pear sekonden',
+ m : 'ien minút',
+ mm : '%d minuten',
+ h : 'ien oere',
+ hh : '%d oeren',
+ d : 'ien dei',
+ dd : '%d dagen',
+ M : 'ien moanne',
+ MM : '%d moannen',
+ y : 'ien jier',
+ yy : '%d jierren'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
+ ordinal : function (number) {
+ return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return fy;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/gd.js b/www/wiki/resources/lib/moment/locale/gd.js
new file mode 100644
index 00000000..af9eec84
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/gd.js
@@ -0,0 +1,76 @@
+//! moment.js locale configuration
+//! locale : Scottish Gaelic [gd]
+//! author : Jon Ashdown : https://github.com/jonashdown
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = [
+ 'Am Faoilleach', 'An Gearran', 'Am Màrt', 'An Giblean', 'An Cèitean', 'An t-Ògmhios', 'An t-Iuchar', 'An Lùnastal', 'An t-Sultain', 'An Dàmhair', 'An t-Samhain', 'An Dùbhlachd'
+];
+
+var monthsShort = ['Faoi', 'Gear', 'Màrt', 'Gibl', 'Cèit', 'Ògmh', 'Iuch', 'Lùn', 'Sult', 'Dàmh', 'Samh', 'Dùbh'];
+
+var weekdays = ['Didòmhnaich', 'Diluain', 'Dimàirt', 'Diciadain', 'Diardaoin', 'Dihaoine', 'Disathairne'];
+
+var weekdaysShort = ['Did', 'Dil', 'Dim', 'Dic', 'Dia', 'Dih', 'Dis'];
+
+var weekdaysMin = ['Dò', 'Lu', 'Mà', 'Ci', 'Ar', 'Ha', 'Sa'];
+
+var gd = moment.defineLocale('gd', {
+ months : months,
+ monthsShort : monthsShort,
+ monthsParseExact : true,
+ weekdays : weekdays,
+ weekdaysShort : weekdaysShort,
+ weekdaysMin : weekdaysMin,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[An-diugh aig] LT',
+ nextDay : '[A-màireach aig] LT',
+ nextWeek : 'dddd [aig] LT',
+ lastDay : '[An-dè aig] LT',
+ lastWeek : 'dddd [seo chaidh] [aig] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'ann an %s',
+ past : 'bho chionn %s',
+ s : 'beagan diogan',
+ m : 'mionaid',
+ mm : '%d mionaidean',
+ h : 'uair',
+ hh : '%d uairean',
+ d : 'latha',
+ dd : '%d latha',
+ M : 'mìos',
+ MM : '%d mìosan',
+ y : 'bliadhna',
+ yy : '%d bliadhna'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}(d|na|mh)/,
+ ordinal : function (number) {
+ var output = number === 1 ? 'd' : number % 10 === 2 ? 'na' : 'mh';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return gd;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/gl.js b/www/wiki/resources/lib/moment/locale/gl.js
new file mode 100644
index 00000000..e894db73
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/gl.js
@@ -0,0 +1,77 @@
+//! moment.js locale configuration
+//! locale : Galician [gl]
+//! author : Juan G. Hurtado : https://github.com/juanghurtado
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var gl = moment.defineLocale('gl', {
+ months : 'xaneiro_febreiro_marzo_abril_maio_xuño_xullo_agosto_setembro_outubro_novembro_decembro'.split('_'),
+ monthsShort : 'xan._feb._mar._abr._mai._xuñ._xul._ago._set._out._nov._dec.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'domingo_luns_martes_mércores_xoves_venres_sábado'.split('_'),
+ weekdaysShort : 'dom._lun._mar._mér._xov._ven._sáb.'.split('_'),
+ weekdaysMin : 'do_lu_ma_mé_xo_ve_sá'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D [de] MMMM [de] YYYY',
+ LLL : 'D [de] MMMM [de] YYYY H:mm',
+ LLLL : 'dddd, D [de] MMMM [de] YYYY H:mm'
+ },
+ calendar : {
+ sameDay : function () {
+ return '[hoxe ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
+ },
+ nextDay : function () {
+ return '[mañá ' + ((this.hours() !== 1) ? 'ás' : 'á') + '] LT';
+ },
+ nextWeek : function () {
+ return 'dddd [' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
+ },
+ lastDay : function () {
+ return '[onte ' + ((this.hours() !== 1) ? 'á' : 'a') + '] LT';
+ },
+ lastWeek : function () {
+ return '[o] dddd [pasado ' + ((this.hours() !== 1) ? 'ás' : 'a') + '] LT';
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : function (str) {
+ if (str.indexOf('un') === 0) {
+ return 'n' + str;
+ }
+ return 'en ' + str;
+ },
+ past : 'hai %s',
+ s : 'uns segundos',
+ m : 'un minuto',
+ mm : '%d minutos',
+ h : 'unha hora',
+ hh : '%d horas',
+ d : 'un día',
+ dd : '%d días',
+ M : 'un mes',
+ MM : '%d meses',
+ y : 'un ano',
+ yy : '%d anos'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}º/,
+ ordinal : '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return gl;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/gom-latn.js b/www/wiki/resources/lib/moment/locale/gom-latn.js
new file mode 100644
index 00000000..084b4b22
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/gom-latn.js
@@ -0,0 +1,122 @@
+//! moment.js locale configuration
+//! locale : Konkani Latin script [gom-latn]
+//! author : The Discoverer : https://github.com/WikiDiscoverer
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 's': ['thodde secondanim', 'thodde second'],
+ 'm': ['eka mintan', 'ek minute'],
+ 'mm': [number + ' mintanim', number + ' mintam'],
+ 'h': ['eka horan', 'ek hor'],
+ 'hh': [number + ' horanim', number + ' hor'],
+ 'd': ['eka disan', 'ek dis'],
+ 'dd': [number + ' disanim', number + ' dis'],
+ 'M': ['eka mhoinean', 'ek mhoino'],
+ 'MM': [number + ' mhoineanim', number + ' mhoine'],
+ 'y': ['eka vorsan', 'ek voros'],
+ 'yy': [number + ' vorsanim', number + ' vorsam']
+ };
+ return withoutSuffix ? format[key][0] : format[key][1];
+}
+
+var gomLatn = moment.defineLocale('gom-latn', {
+ months : 'Janer_Febrer_Mars_Abril_Mai_Jun_Julai_Agost_Setembr_Otubr_Novembr_Dezembr'.split('_'),
+ monthsShort : 'Jan._Feb._Mars_Abr._Mai_Jun_Jul._Ago._Set._Otu._Nov._Dez.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'Aitar_Somar_Mongllar_Budvar_Brestar_Sukrar_Son\'var'.split('_'),
+ weekdaysShort : 'Ait._Som._Mon._Bud._Bre._Suk._Son.'.split('_'),
+ weekdaysMin : 'Ai_Sm_Mo_Bu_Br_Su_Sn'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'A h:mm [vazta]',
+ LTS : 'A h:mm:ss [vazta]',
+ L : 'DD-MM-YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY A h:mm [vazta]',
+ LLLL : 'dddd, MMMM[achea] Do, YYYY, A h:mm [vazta]',
+ llll: 'ddd, D MMM YYYY, A h:mm [vazta]'
+ },
+ calendar : {
+ sameDay: '[Aiz] LT',
+ nextDay: '[Faleam] LT',
+ nextWeek: '[Ieta to] dddd[,] LT',
+ lastDay: '[Kal] LT',
+ lastWeek: '[Fatlo] dddd[,] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : '%s',
+ past : '%s adim',
+ s : processRelativeTime,
+ m : processRelativeTime,
+ mm : processRelativeTime,
+ h : processRelativeTime,
+ hh : processRelativeTime,
+ d : processRelativeTime,
+ dd : processRelativeTime,
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}(er)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ // the ordinal 'er' only applies to day of the month
+ case 'D':
+ return number + 'er';
+ default:
+ case 'M':
+ case 'Q':
+ case 'DDD':
+ case 'd':
+ case 'w':
+ case 'W':
+ return number;
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ },
+ meridiemParse: /rati|sokalli|donparam|sanje/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'rati') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'sokalli') {
+ return hour;
+ } else if (meridiem === 'donparam') {
+ return hour > 12 ? hour : hour + 12;
+ } else if (meridiem === 'sanje') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'rati';
+ } else if (hour < 12) {
+ return 'sokalli';
+ } else if (hour < 16) {
+ return 'donparam';
+ } else if (hour < 20) {
+ return 'sanje';
+ } else {
+ return 'rati';
+ }
+ }
+});
+
+return gomLatn;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/gu.js b/www/wiki/resources/lib/moment/locale/gu.js
new file mode 100644
index 00000000..1a13fc4e
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/gu.js
@@ -0,0 +1,124 @@
+//! moment.js locale configuration
+//! locale : Gujarati [gu]
+//! author : Kaushik Thanki : https://github.com/Kaushik1987
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '૧',
+ '2': '૨',
+ '3': '૩',
+ '4': '૪',
+ '5': '૫',
+ '6': '૬',
+ '7': '૭',
+ '8': '૮',
+ '9': '૯',
+ '0': '૦'
+ };
+var numberMap = {
+ '૧': '1',
+ '૨': '2',
+ '૩': '3',
+ '૪': '4',
+ '૫': '5',
+ '૬': '6',
+ '૭': '7',
+ '૮': '8',
+ '૯': '9',
+ '૦': '0'
+ };
+
+var gu = moment.defineLocale('gu', {
+ months: 'જાન્યુઆરી_ફેબ્રુઆરી_માર્ચ_એપ્રિલ_મે_જૂન_જુલાઈ_ઑગસ્ટ_સપ્ટેમ્બર_ઑક્ટ્બર_નવેમ્બર_ડિસેમ્બર'.split('_'),
+ monthsShort: 'જાન્યુ._ફેબ્રુ._માર્ચ_એપ્રિ._મે_જૂન_જુલા._ઑગ._સપ્ટે._ઑક્ટ્._નવે._ડિસે.'.split('_'),
+ monthsParseExact: true,
+ weekdays: 'રવિવાર_સોમવાર_મંગળવાર_બુધ્વાર_ગુરુવાર_શુક્રવાર_શનિવાર'.split('_'),
+ weekdaysShort: 'રવિ_સોમ_મંગળ_બુધ્_ગુરુ_શુક્ર_શનિ'.split('_'),
+ weekdaysMin: 'ર_સો_મં_બુ_ગુ_શુ_શ'.split('_'),
+ longDateFormat: {
+ LT: 'A h:mm વાગ્યે',
+ LTS: 'A h:mm:ss વાગ્યે',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY, A h:mm વાગ્યે',
+ LLLL: 'dddd, D MMMM YYYY, A h:mm વાગ્યે'
+ },
+ calendar: {
+ sameDay: '[આજ] LT',
+ nextDay: '[કાલે] LT',
+ nextWeek: 'dddd, LT',
+ lastDay: '[ગઇકાલે] LT',
+ lastWeek: '[પાછલા] dddd, LT',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: '%s મા',
+ past: '%s પેહલા',
+ s: 'અમુક પળો',
+ m: 'એક મિનિટ',
+ mm: '%d મિનિટ',
+ h: 'એક કલાક',
+ hh: '%d કલાક',
+ d: 'એક દિવસ',
+ dd: '%d દિવસ',
+ M: 'એક મહિનો',
+ MM: '%d મહિનો',
+ y: 'એક વર્ષ',
+ yy: '%d વર્ષ'
+ },
+ preparse: function (string) {
+ return string.replace(/[૧૨૩૪૫૬૭૮૯૦]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ // Gujarati notation for meridiems are quite fuzzy in practice. While there exists
+ // a rigid notion of a 'Pahar' it is not used as rigidly in modern Gujarati.
+ meridiemParse: /રાત|બપોર|સવાર|સાંજ/,
+ meridiemHour: function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'રાત') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'સવાર') {
+ return hour;
+ } else if (meridiem === 'બપોર') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'સાંજ') {
+ return hour + 12;
+ }
+ },
+ meridiem: function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'રાત';
+ } else if (hour < 10) {
+ return 'સવાર';
+ } else if (hour < 17) {
+ return 'બપોર';
+ } else if (hour < 20) {
+ return 'સાંજ';
+ } else {
+ return 'રાત';
+ }
+ },
+ week: {
+ dow: 0, // Sunday is the first day of the week.
+ doy: 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return gu;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/he.js b/www/wiki/resources/lib/moment/locale/he.js
new file mode 100644
index 00000000..e8843811
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/he.js
@@ -0,0 +1,99 @@
+//! moment.js locale configuration
+//! locale : Hebrew [he]
+//! author : Tomer Cohen : https://github.com/tomer
+//! author : Moshe Simantov : https://github.com/DevelopmentIL
+//! author : Tal Ater : https://github.com/TalAter
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var he = moment.defineLocale('he', {
+ months : 'ינואר_פברואר_מרץ_אפריל_מאי_יוני_יולי_אוגוסט_ספטמבר_אוקטובר_נובמבר_דצמבר'.split('_'),
+ monthsShort : 'ינו׳_פבר׳_מרץ_אפר׳_מאי_יוני_יולי_אוג׳_ספט׳_אוק׳_נוב׳_דצמ׳'.split('_'),
+ weekdays : 'ראשון_שני_שלישי_רביעי_חמישי_שישי_שבת'.split('_'),
+ weekdaysShort : 'א׳_ב׳_ג׳_ד׳_ה׳_ו׳_ש׳'.split('_'),
+ weekdaysMin : 'א_ב_ג_ד_ה_ו_ש'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D [ב]MMMM YYYY',
+ LLL : 'D [ב]MMMM YYYY HH:mm',
+ LLLL : 'dddd, D [ב]MMMM YYYY HH:mm',
+ l : 'D/M/YYYY',
+ ll : 'D MMM YYYY',
+ lll : 'D MMM YYYY HH:mm',
+ llll : 'ddd, D MMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[היום ב־]LT',
+ nextDay : '[מחר ב־]LT',
+ nextWeek : 'dddd [בשעה] LT',
+ lastDay : '[אתמול ב־]LT',
+ lastWeek : '[ביום] dddd [האחרון בשעה] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'בעוד %s',
+ past : 'לפני %s',
+ s : 'מספר שניות',
+ m : 'דקה',
+ mm : '%d דקות',
+ h : 'שעה',
+ hh : function (number) {
+ if (number === 2) {
+ return 'שעתיים';
+ }
+ return number + ' שעות';
+ },
+ d : 'יום',
+ dd : function (number) {
+ if (number === 2) {
+ return 'יומיים';
+ }
+ return number + ' ימים';
+ },
+ M : 'חודש',
+ MM : function (number) {
+ if (number === 2) {
+ return 'חודשיים';
+ }
+ return number + ' חודשים';
+ },
+ y : 'שנה',
+ yy : function (number) {
+ if (number === 2) {
+ return 'שנתיים';
+ } else if (number % 10 === 0 && number !== 10) {
+ return number + ' שנה';
+ }
+ return number + ' שנים';
+ }
+ },
+ meridiemParse: /אחה"צ|לפנה"צ|אחרי הצהריים|לפני הצהריים|לפנות בוקר|בבוקר|בערב/i,
+ isPM : function (input) {
+ return /^(אחה"צ|אחרי הצהריים|בערב)$/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 5) {
+ return 'לפנות בוקר';
+ } else if (hour < 10) {
+ return 'בבוקר';
+ } else if (hour < 12) {
+ return isLower ? 'לפנה"צ' : 'לפני הצהריים';
+ } else if (hour < 18) {
+ return isLower ? 'אחה"צ' : 'אחרי הצהריים';
+ } else {
+ return 'בערב';
+ }
+ }
+});
+
+return he;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/hi.js b/www/wiki/resources/lib/moment/locale/hi.js
new file mode 100644
index 00000000..58afc6b1
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/hi.js
@@ -0,0 +1,124 @@
+//! moment.js locale configuration
+//! locale : Hindi [hi]
+//! author : Mayank Singhal : https://github.com/mayanksinghal
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '१',
+ '2': '२',
+ '3': '३',
+ '4': '४',
+ '5': '५',
+ '6': '६',
+ '7': '७',
+ '8': '८',
+ '9': '९',
+ '0': '०'
+};
+var numberMap = {
+ '१': '1',
+ '२': '2',
+ '३': '3',
+ '४': '4',
+ '५': '5',
+ '६': '6',
+ '७': '7',
+ '८': '8',
+ '९': '9',
+ '०': '0'
+};
+
+var hi = moment.defineLocale('hi', {
+ months : 'जनवरी_फ़रवरी_मार्च_अप्रैल_मई_जून_जुलाई_अगस्त_सितम्बर_अक्टूबर_नवम्बर_दिसम्बर'.split('_'),
+ monthsShort : 'जन._फ़र._मार्च_अप्रै._मई_जून_जुल._अग._सित._अक्टू._नव._दिस.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'रविवार_सोमवार_मंगलवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
+ weekdaysShort : 'रवि_सोम_मंगल_बुध_गुरू_शुक्र_शनि'.split('_'),
+ weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm बजे',
+ LTS : 'A h:mm:ss बजे',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm बजे',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm बजे'
+ },
+ calendar : {
+ sameDay : '[आज] LT',
+ nextDay : '[कल] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[कल] LT',
+ lastWeek : '[पिछले] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s में',
+ past : '%s पहले',
+ s : 'कुछ ही क्षण',
+ m : 'एक मिनट',
+ mm : '%d मिनट',
+ h : 'एक घंटा',
+ hh : '%d घंटे',
+ d : 'एक दिन',
+ dd : '%d दिन',
+ M : 'एक महीने',
+ MM : '%d महीने',
+ y : 'एक वर्ष',
+ yy : '%d वर्ष'
+ },
+ preparse: function (string) {
+ return string.replace(/[१२३४५६७८९०]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ // Hindi notation for meridiems are quite fuzzy in practice. While there exists
+ // a rigid notion of a 'Pahar' it is not used as rigidly in modern Hindi.
+ meridiemParse: /रात|सुबह|दोपहर|शाम/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'रात') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'सुबह') {
+ return hour;
+ } else if (meridiem === 'दोपहर') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'शाम') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'रात';
+ } else if (hour < 10) {
+ return 'सुबह';
+ } else if (hour < 17) {
+ return 'दोपहर';
+ } else if (hour < 20) {
+ return 'शाम';
+ } else {
+ return 'रात';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return hi;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/hr.js b/www/wiki/resources/lib/moment/locale/hr.js
new file mode 100644
index 00000000..5caeec80
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/hr.js
@@ -0,0 +1,145 @@
+//! moment.js locale configuration
+//! locale : Croatian [hr]
+//! author : Bojan Marković : https://github.com/bmarkovic
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function translate(number, withoutSuffix, key) {
+ var result = number + ' ';
+ switch (key) {
+ case 'm':
+ return withoutSuffix ? 'jedna minuta' : 'jedne minute';
+ case 'mm':
+ if (number === 1) {
+ result += 'minuta';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'minute';
+ } else {
+ result += 'minuta';
+ }
+ return result;
+ case 'h':
+ return withoutSuffix ? 'jedan sat' : 'jednog sata';
+ case 'hh':
+ if (number === 1) {
+ result += 'sat';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'sata';
+ } else {
+ result += 'sati';
+ }
+ return result;
+ case 'dd':
+ if (number === 1) {
+ result += 'dan';
+ } else {
+ result += 'dana';
+ }
+ return result;
+ case 'MM':
+ if (number === 1) {
+ result += 'mjesec';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'mjeseca';
+ } else {
+ result += 'mjeseci';
+ }
+ return result;
+ case 'yy':
+ if (number === 1) {
+ result += 'godina';
+ } else if (number === 2 || number === 3 || number === 4) {
+ result += 'godine';
+ } else {
+ result += 'godina';
+ }
+ return result;
+ }
+}
+
+var hr = moment.defineLocale('hr', {
+ months : {
+ format: 'siječnja_veljače_ožujka_travnja_svibnja_lipnja_srpnja_kolovoza_rujna_listopada_studenoga_prosinca'.split('_'),
+ standalone: 'siječanj_veljača_ožujak_travanj_svibanj_lipanj_srpanj_kolovoz_rujan_listopad_studeni_prosinac'.split('_')
+ },
+ monthsShort : 'sij._velj._ožu._tra._svi._lip._srp._kol._ruj._lis._stu._pro.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'nedjelja_ponedjeljak_utorak_srijeda_četvrtak_petak_subota'.split('_'),
+ weekdaysShort : 'ned._pon._uto._sri._čet._pet._sub.'.split('_'),
+ weekdaysMin : 'ne_po_ut_sr_če_pe_su'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[danas u] LT',
+ nextDay : '[sutra u] LT',
+ nextWeek : function () {
+ switch (this.day()) {
+ case 0:
+ return '[u] [nedjelju] [u] LT';
+ case 3:
+ return '[u] [srijedu] [u] LT';
+ case 6:
+ return '[u] [subotu] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[u] dddd [u] LT';
+ }
+ },
+ lastDay : '[jučer u] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ return '[prošlu] dddd [u] LT';
+ case 6:
+ return '[prošle] [subote] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[prošli] dddd [u] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : 'prije %s',
+ s : 'par sekundi',
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : 'dan',
+ dd : translate,
+ M : 'mjesec',
+ MM : translate,
+ y : 'godinu',
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return hr;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/hu.js b/www/wiki/resources/lib/moment/locale/hu.js
new file mode 100644
index 00000000..8460392b
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/hu.js
@@ -0,0 +1,108 @@
+//! moment.js locale configuration
+//! locale : Hungarian [hu]
+//! author : Adam Brunner : https://github.com/adambrunner
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var weekEndings = 'vasárnap hétfőn kedden szerdán csütörtökön pénteken szombaton'.split(' ');
+function translate(number, withoutSuffix, key, isFuture) {
+ var num = number;
+ switch (key) {
+ case 's':
+ return (isFuture || withoutSuffix) ? 'néhány másodperc' : 'néhány másodperce';
+ case 'm':
+ return 'egy' + (isFuture || withoutSuffix ? ' perc' : ' perce');
+ case 'mm':
+ return num + (isFuture || withoutSuffix ? ' perc' : ' perce');
+ case 'h':
+ return 'egy' + (isFuture || withoutSuffix ? ' óra' : ' órája');
+ case 'hh':
+ return num + (isFuture || withoutSuffix ? ' óra' : ' órája');
+ case 'd':
+ return 'egy' + (isFuture || withoutSuffix ? ' nap' : ' napja');
+ case 'dd':
+ return num + (isFuture || withoutSuffix ? ' nap' : ' napja');
+ case 'M':
+ return 'egy' + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
+ case 'MM':
+ return num + (isFuture || withoutSuffix ? ' hónap' : ' hónapja');
+ case 'y':
+ return 'egy' + (isFuture || withoutSuffix ? ' év' : ' éve');
+ case 'yy':
+ return num + (isFuture || withoutSuffix ? ' év' : ' éve');
+ }
+ return '';
+}
+function week(isFuture) {
+ return (isFuture ? '' : '[múlt] ') + '[' + weekEndings[this.day()] + '] LT[-kor]';
+}
+
+var hu = moment.defineLocale('hu', {
+ months : 'január_február_március_április_május_június_július_augusztus_szeptember_október_november_december'.split('_'),
+ monthsShort : 'jan_feb_márc_ápr_máj_jún_júl_aug_szept_okt_nov_dec'.split('_'),
+ weekdays : 'vasárnap_hétfő_kedd_szerda_csütörtök_péntek_szombat'.split('_'),
+ weekdaysShort : 'vas_hét_kedd_sze_csüt_pén_szo'.split('_'),
+ weekdaysMin : 'v_h_k_sze_cs_p_szo'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'YYYY.MM.DD.',
+ LL : 'YYYY. MMMM D.',
+ LLL : 'YYYY. MMMM D. H:mm',
+ LLLL : 'YYYY. MMMM D., dddd H:mm'
+ },
+ meridiemParse: /de|du/i,
+ isPM: function (input) {
+ return input.charAt(1).toLowerCase() === 'u';
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 12) {
+ return isLower === true ? 'de' : 'DE';
+ } else {
+ return isLower === true ? 'du' : 'DU';
+ }
+ },
+ calendar : {
+ sameDay : '[ma] LT[-kor]',
+ nextDay : '[holnap] LT[-kor]',
+ nextWeek : function () {
+ return week.call(this, true);
+ },
+ lastDay : '[tegnap] LT[-kor]',
+ lastWeek : function () {
+ return week.call(this, false);
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s múlva',
+ past : '%s',
+ s : translate,
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : translate,
+ dd : translate,
+ M : translate,
+ MM : translate,
+ y : translate,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return hu;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/hy-am.js b/www/wiki/resources/lib/moment/locale/hy-am.js
new file mode 100644
index 00000000..0b768458
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/hy-am.js
@@ -0,0 +1,95 @@
+//! moment.js locale configuration
+//! locale : Armenian [hy-am]
+//! author : Armendarabyan : https://github.com/armendarabyan
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var hyAm = moment.defineLocale('hy-am', {
+ months : {
+ format: 'հունվարի_փետրվարի_մարտի_ապրիլի_մայիսի_հունիսի_հուլիսի_օգոստոսի_սեպտեմբերի_հոկտեմբերի_նոյեմբերի_դեկտեմբերի'.split('_'),
+ standalone: 'հունվար_փետրվար_մարտ_ապրիլ_մայիս_հունիս_հուլիս_օգոստոս_սեպտեմբեր_հոկտեմբեր_նոյեմբեր_դեկտեմբեր'.split('_')
+ },
+ monthsShort : 'հնվ_փտր_մրտ_ապր_մյս_հնս_հլս_օգս_սպտ_հկտ_նմբ_դկտ'.split('_'),
+ weekdays : 'կիրակի_երկուշաբթի_երեքշաբթի_չորեքշաբթի_հինգշաբթի_ուրբաթ_շաբաթ'.split('_'),
+ weekdaysShort : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
+ weekdaysMin : 'կրկ_երկ_երք_չրք_հնգ_ուրբ_շբթ'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY թ.',
+ LLL : 'D MMMM YYYY թ., HH:mm',
+ LLLL : 'dddd, D MMMM YYYY թ., HH:mm'
+ },
+ calendar : {
+ sameDay: '[այսօր] LT',
+ nextDay: '[վաղը] LT',
+ lastDay: '[երեկ] LT',
+ nextWeek: function () {
+ return 'dddd [օրը ժամը] LT';
+ },
+ lastWeek: function () {
+ return '[անցած] dddd [օրը ժամը] LT';
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : '%s հետո',
+ past : '%s առաջ',
+ s : 'մի քանի վայրկյան',
+ m : 'րոպե',
+ mm : '%d րոպե',
+ h : 'ժամ',
+ hh : '%d ժամ',
+ d : 'օր',
+ dd : '%d օր',
+ M : 'ամիս',
+ MM : '%d ամիս',
+ y : 'տարի',
+ yy : '%d տարի'
+ },
+ meridiemParse: /գիշերվա|առավոտվա|ցերեկվա|երեկոյան/,
+ isPM: function (input) {
+ return /^(ցերեկվա|երեկոյան)$/.test(input);
+ },
+ meridiem : function (hour) {
+ if (hour < 4) {
+ return 'գիշերվա';
+ } else if (hour < 12) {
+ return 'առավոտվա';
+ } else if (hour < 17) {
+ return 'ցերեկվա';
+ } else {
+ return 'երեկոյան';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}|\d{1,2}-(ին|րդ)/,
+ ordinal: function (number, period) {
+ switch (period) {
+ case 'DDD':
+ case 'w':
+ case 'W':
+ case 'DDDo':
+ if (number === 1) {
+ return number + '-ին';
+ }
+ return number + '-րդ';
+ default:
+ return number;
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return hyAm;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/id.js b/www/wiki/resources/lib/moment/locale/id.js
new file mode 100644
index 00000000..a1cfb183
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/id.js
@@ -0,0 +1,83 @@
+//! moment.js locale configuration
+//! locale : Indonesian [id]
+//! author : Mohammad Satrio Utomo : https://github.com/tyok
+//! reference: http://id.wikisource.org/wiki/Pedoman_Umum_Ejaan_Bahasa_Indonesia_yang_Disempurnakan
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var id = moment.defineLocale('id', {
+ months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_November_Desember'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nov_Des'.split('_'),
+ weekdays : 'Minggu_Senin_Selasa_Rabu_Kamis_Jumat_Sabtu'.split('_'),
+ weekdaysShort : 'Min_Sen_Sel_Rab_Kam_Jum_Sab'.split('_'),
+ weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sb'.split('_'),
+ longDateFormat : {
+ LT : 'HH.mm',
+ LTS : 'HH.mm.ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY [pukul] HH.mm',
+ LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+ },
+ meridiemParse: /pagi|siang|sore|malam/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'pagi') {
+ return hour;
+ } else if (meridiem === 'siang') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === 'sore' || meridiem === 'malam') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 11) {
+ return 'pagi';
+ } else if (hours < 15) {
+ return 'siang';
+ } else if (hours < 19) {
+ return 'sore';
+ } else {
+ return 'malam';
+ }
+ },
+ calendar : {
+ sameDay : '[Hari ini pukul] LT',
+ nextDay : '[Besok pukul] LT',
+ nextWeek : 'dddd [pukul] LT',
+ lastDay : '[Kemarin pukul] LT',
+ lastWeek : 'dddd [lalu pukul] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'dalam %s',
+ past : '%s yang lalu',
+ s : 'beberapa detik',
+ m : 'semenit',
+ mm : '%d menit',
+ h : 'sejam',
+ hh : '%d jam',
+ d : 'sehari',
+ dd : '%d hari',
+ M : 'sebulan',
+ MM : '%d bulan',
+ y : 'setahun',
+ yy : '%d tahun'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return id;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/is.js b/www/wiki/resources/lib/moment/locale/is.js
new file mode 100644
index 00000000..541b270e
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/is.js
@@ -0,0 +1,127 @@
+//! moment.js locale configuration
+//! locale : Icelandic [is]
+//! author : Hinrik Örn Sigurðsson : https://github.com/hinrik
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function plural(n) {
+ if (n % 100 === 11) {
+ return true;
+ } else if (n % 10 === 1) {
+ return false;
+ }
+ return true;
+}
+function translate(number, withoutSuffix, key, isFuture) {
+ var result = number + ' ';
+ switch (key) {
+ case 's':
+ return withoutSuffix || isFuture ? 'nokkrar sekúndur' : 'nokkrum sekúndum';
+ case 'm':
+ return withoutSuffix ? 'mínúta' : 'mínútu';
+ case 'mm':
+ if (plural(number)) {
+ return result + (withoutSuffix || isFuture ? 'mínútur' : 'mínútum');
+ } else if (withoutSuffix) {
+ return result + 'mínúta';
+ }
+ return result + 'mínútu';
+ case 'hh':
+ if (plural(number)) {
+ return result + (withoutSuffix || isFuture ? 'klukkustundir' : 'klukkustundum');
+ }
+ return result + 'klukkustund';
+ case 'd':
+ if (withoutSuffix) {
+ return 'dagur';
+ }
+ return isFuture ? 'dag' : 'degi';
+ case 'dd':
+ if (plural(number)) {
+ if (withoutSuffix) {
+ return result + 'dagar';
+ }
+ return result + (isFuture ? 'daga' : 'dögum');
+ } else if (withoutSuffix) {
+ return result + 'dagur';
+ }
+ return result + (isFuture ? 'dag' : 'degi');
+ case 'M':
+ if (withoutSuffix) {
+ return 'mánuður';
+ }
+ return isFuture ? 'mánuð' : 'mánuði';
+ case 'MM':
+ if (plural(number)) {
+ if (withoutSuffix) {
+ return result + 'mánuðir';
+ }
+ return result + (isFuture ? 'mánuði' : 'mánuðum');
+ } else if (withoutSuffix) {
+ return result + 'mánuður';
+ }
+ return result + (isFuture ? 'mánuð' : 'mánuði');
+ case 'y':
+ return withoutSuffix || isFuture ? 'ár' : 'ári';
+ case 'yy':
+ if (plural(number)) {
+ return result + (withoutSuffix || isFuture ? 'ár' : 'árum');
+ }
+ return result + (withoutSuffix || isFuture ? 'ár' : 'ári');
+ }
+}
+
+var is = moment.defineLocale('is', {
+ months : 'janúar_febrúar_mars_apríl_maí_júní_júlí_ágúst_september_október_nóvember_desember'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_maí_jún_júl_ágú_sep_okt_nóv_des'.split('_'),
+ weekdays : 'sunnudagur_mánudagur_þriðjudagur_miðvikudagur_fimmtudagur_föstudagur_laugardagur'.split('_'),
+ weekdaysShort : 'sun_mán_þri_mið_fim_fös_lau'.split('_'),
+ weekdaysMin : 'Su_Má_Þr_Mi_Fi_Fö_La'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY [kl.] H:mm',
+ LLLL : 'dddd, D. MMMM YYYY [kl.] H:mm'
+ },
+ calendar : {
+ sameDay : '[í dag kl.] LT',
+ nextDay : '[á morgun kl.] LT',
+ nextWeek : 'dddd [kl.] LT',
+ lastDay : '[í gær kl.] LT',
+ lastWeek : '[síðasta] dddd [kl.] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'eftir %s',
+ past : 'fyrir %s síðan',
+ s : translate,
+ m : translate,
+ mm : translate,
+ h : 'klukkustund',
+ hh : translate,
+ d : translate,
+ dd : translate,
+ M : translate,
+ MM : translate,
+ y : translate,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return is;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/it.js b/www/wiki/resources/lib/moment/locale/it.js
new file mode 100644
index 00000000..f3079cb4
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/it.js
@@ -0,0 +1,70 @@
+//! moment.js locale configuration
+//! locale : Italian [it]
+//! author : Lorenzo : https://github.com/aliem
+//! author: Mattia Larentis: https://github.com/nostalgiaz
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var it = moment.defineLocale('it', {
+ months : 'gennaio_febbraio_marzo_aprile_maggio_giugno_luglio_agosto_settembre_ottobre_novembre_dicembre'.split('_'),
+ monthsShort : 'gen_feb_mar_apr_mag_giu_lug_ago_set_ott_nov_dic'.split('_'),
+ weekdays : 'domenica_lunedì_martedì_mercoledì_giovedì_venerdì_sabato'.split('_'),
+ weekdaysShort : 'dom_lun_mar_mer_gio_ven_sab'.split('_'),
+ weekdaysMin : 'do_lu_ma_me_gi_ve_sa'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Oggi alle] LT',
+ nextDay: '[Domani alle] LT',
+ nextWeek: 'dddd [alle] LT',
+ lastDay: '[Ieri alle] LT',
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[la scorsa] dddd [alle] LT';
+ default:
+ return '[lo scorso] dddd [alle] LT';
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : function (s) {
+ return ((/^[0-9].+$/).test(s) ? 'tra' : 'in') + ' ' + s;
+ },
+ past : '%s fa',
+ s : 'alcuni secondi',
+ m : 'un minuto',
+ mm : '%d minuti',
+ h : 'un\'ora',
+ hh : '%d ore',
+ d : 'un giorno',
+ dd : '%d giorni',
+ M : 'un mese',
+ MM : '%d mesi',
+ y : 'un anno',
+ yy : '%d anni'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}º/,
+ ordinal: '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return it;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ja.js b/www/wiki/resources/lib/moment/locale/ja.js
new file mode 100644
index 00000000..b2e65539
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ja.js
@@ -0,0 +1,80 @@
+//! moment.js locale configuration
+//! locale : Japanese [ja]
+//! author : LI Long : https://github.com/baryon
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ja = moment.defineLocale('ja', {
+ months : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+ monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+ weekdays : '日曜日_月曜日_火曜日_水曜日_木曜日_金曜日_土曜日'.split('_'),
+ weekdaysShort : '日_月_火_水_木_金_土'.split('_'),
+ weekdaysMin : '日_月_火_水_木_金_土'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY/MM/DD',
+ LL : 'YYYY年M月D日',
+ LLL : 'YYYY年M月D日 HH:mm',
+ LLLL : 'YYYY年M月D日 HH:mm dddd',
+ l : 'YYYY/MM/DD',
+ ll : 'YYYY年M月D日',
+ lll : 'YYYY年M月D日 HH:mm',
+ llll : 'YYYY年M月D日 HH:mm dddd'
+ },
+ meridiemParse: /午前|午後/i,
+ isPM : function (input) {
+ return input === '午後';
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return '午前';
+ } else {
+ return '午後';
+ }
+ },
+ calendar : {
+ sameDay : '[今日] LT',
+ nextDay : '[明日] LT',
+ nextWeek : '[来週]dddd LT',
+ lastDay : '[昨日] LT',
+ lastWeek : '[前週]dddd LT',
+ sameElse : 'L'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}日/,
+ ordinal : function (number, period) {
+ switch (period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return number + '日';
+ default:
+ return number;
+ }
+ },
+ relativeTime : {
+ future : '%s後',
+ past : '%s前',
+ s : '数秒',
+ m : '1分',
+ mm : '%d分',
+ h : '1時間',
+ hh : '%d時間',
+ d : '1日',
+ dd : '%d日',
+ M : '1ヶ月',
+ MM : '%dヶ月',
+ y : '1年',
+ yy : '%d年'
+ }
+});
+
+return ja;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/jv.js b/www/wiki/resources/lib/moment/locale/jv.js
new file mode 100644
index 00000000..5b939e0f
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/jv.js
@@ -0,0 +1,83 @@
+//! moment.js locale configuration
+//! locale : Javanese [jv]
+//! author : Rony Lantip : https://github.com/lantip
+//! reference: http://jv.wikipedia.org/wiki/Basa_Jawa
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var jv = moment.defineLocale('jv', {
+ months : 'Januari_Februari_Maret_April_Mei_Juni_Juli_Agustus_September_Oktober_Nopember_Desember'.split('_'),
+ monthsShort : 'Jan_Feb_Mar_Apr_Mei_Jun_Jul_Ags_Sep_Okt_Nop_Des'.split('_'),
+ weekdays : 'Minggu_Senen_Seloso_Rebu_Kemis_Jemuwah_Septu'.split('_'),
+ weekdaysShort : 'Min_Sen_Sel_Reb_Kem_Jem_Sep'.split('_'),
+ weekdaysMin : 'Mg_Sn_Sl_Rb_Km_Jm_Sp'.split('_'),
+ longDateFormat : {
+ LT : 'HH.mm',
+ LTS : 'HH.mm.ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY [pukul] HH.mm',
+ LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+ },
+ meridiemParse: /enjing|siyang|sonten|ndalu/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'enjing') {
+ return hour;
+ } else if (meridiem === 'siyang') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === 'sonten' || meridiem === 'ndalu') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 11) {
+ return 'enjing';
+ } else if (hours < 15) {
+ return 'siyang';
+ } else if (hours < 19) {
+ return 'sonten';
+ } else {
+ return 'ndalu';
+ }
+ },
+ calendar : {
+ sameDay : '[Dinten puniko pukul] LT',
+ nextDay : '[Mbenjang pukul] LT',
+ nextWeek : 'dddd [pukul] LT',
+ lastDay : '[Kala wingi pukul] LT',
+ lastWeek : 'dddd [kepengker pukul] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'wonten ing %s',
+ past : '%s ingkang kepengker',
+ s : 'sawetawis detik',
+ m : 'setunggal menit',
+ mm : '%d menit',
+ h : 'setunggal jam',
+ hh : '%d jam',
+ d : 'sedinten',
+ dd : '%d dinten',
+ M : 'sewulan',
+ MM : '%d wulan',
+ y : 'setaun',
+ yy : '%d taun'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return jv;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ka.js b/www/wiki/resources/lib/moment/locale/ka.js
new file mode 100644
index 00000000..2a95638a
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ka.js
@@ -0,0 +1,89 @@
+//! moment.js locale configuration
+//! locale : Georgian [ka]
+//! author : Irakli Janiashvili : https://github.com/irakli-janiashvili
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ka = moment.defineLocale('ka', {
+ months : {
+ standalone: 'იანვარი_თებერვალი_მარტი_აპრილი_მაისი_ივნისი_ივლისი_აგვისტო_სექტემბერი_ოქტომბერი_ნოემბერი_დეკემბერი'.split('_'),
+ format: 'იანვარს_თებერვალს_მარტს_აპრილის_მაისს_ივნისს_ივლისს_აგვისტს_სექტემბერს_ოქტომბერს_ნოემბერს_დეკემბერს'.split('_')
+ },
+ monthsShort : 'იან_თებ_მარ_აპრ_მაი_ივნ_ივლ_აგვ_სექ_ოქტ_ნოე_დეკ'.split('_'),
+ weekdays : {
+ standalone: 'კვირა_ორშაბათი_სამშაბათი_ოთხშაბათი_ხუთშაბათი_პარასკევი_შაბათი'.split('_'),
+ format: 'კვირას_ორშაბათს_სამშაბათს_ოთხშაბათს_ხუთშაბათს_პარასკევს_შაბათს'.split('_'),
+ isFormat: /(წინა|შემდეგ)/
+ },
+ weekdaysShort : 'კვი_ორშ_სამ_ოთხ_ხუთ_პარ_შაბ'.split('_'),
+ weekdaysMin : 'კვ_ორ_სა_ოთ_ხუ_პა_შა'.split('_'),
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY h:mm A',
+ LLLL : 'dddd, D MMMM YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : '[დღეს] LT[-ზე]',
+ nextDay : '[ხვალ] LT[-ზე]',
+ lastDay : '[გუშინ] LT[-ზე]',
+ nextWeek : '[შემდეგ] dddd LT[-ზე]',
+ lastWeek : '[წინა] dddd LT-ზე',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : function (s) {
+ return (/(წამი|წუთი|საათი|წელი)/).test(s) ?
+ s.replace(/ი$/, 'ში') :
+ s + 'ში';
+ },
+ past : function (s) {
+ if ((/(წამი|წუთი|საათი|დღე|თვე)/).test(s)) {
+ return s.replace(/(ი|ე)$/, 'ის უკან');
+ }
+ if ((/წელი/).test(s)) {
+ return s.replace(/წელი$/, 'წლის უკან');
+ }
+ },
+ s : 'რამდენიმე წამი',
+ m : 'წუთი',
+ mm : '%d წუთი',
+ h : 'საათი',
+ hh : '%d საათი',
+ d : 'დღე',
+ dd : '%d დღე',
+ M : 'თვე',
+ MM : '%d თვე',
+ y : 'წელი',
+ yy : '%d წელი'
+ },
+ dayOfMonthOrdinalParse: /0|1-ლი|მე-\d{1,2}|\d{1,2}-ე/,
+ ordinal : function (number) {
+ if (number === 0) {
+ return number;
+ }
+ if (number === 1) {
+ return number + '-ლი';
+ }
+ if ((number < 20) || (number <= 100 && (number % 20 === 0)) || (number % 100 === 0)) {
+ return 'მე-' + number;
+ }
+ return number + '-ე';
+ },
+ week : {
+ dow : 1,
+ doy : 7
+ }
+});
+
+return ka;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/kk.js b/www/wiki/resources/lib/moment/locale/kk.js
new file mode 100644
index 00000000..777a5294
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/kk.js
@@ -0,0 +1,87 @@
+//! moment.js locale configuration
+//! locale : Kazakh [kk]
+//! authors : Nurlan Rakhimzhanov : https://github.com/nurlan
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var suffixes = {
+ 0: '-ші',
+ 1: '-ші',
+ 2: '-ші',
+ 3: '-ші',
+ 4: '-ші',
+ 5: '-ші',
+ 6: '-шы',
+ 7: '-ші',
+ 8: '-ші',
+ 9: '-шы',
+ 10: '-шы',
+ 20: '-шы',
+ 30: '-шы',
+ 40: '-шы',
+ 50: '-ші',
+ 60: '-шы',
+ 70: '-ші',
+ 80: '-ші',
+ 90: '-шы',
+ 100: '-ші'
+};
+
+var kk = moment.defineLocale('kk', {
+ months : 'қаңтар_ақпан_наурыз_сәуір_мамыр_маусым_шілде_тамыз_қыркүйек_қазан_қараша_желтоқсан'.split('_'),
+ monthsShort : 'қаң_ақп_нау_сәу_мам_мау_шіл_там_қыр_қаз_қар_жел'.split('_'),
+ weekdays : 'жексенбі_дүйсенбі_сейсенбі_сәрсенбі_бейсенбі_жұма_сенбі'.split('_'),
+ weekdaysShort : 'жек_дүй_сей_сәр_бей_жұм_сен'.split('_'),
+ weekdaysMin : 'жк_дй_сй_ср_бй_жм_сн'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Бүгін сағат] LT',
+ nextDay : '[Ертең сағат] LT',
+ nextWeek : 'dddd [сағат] LT',
+ lastDay : '[Кеше сағат] LT',
+ lastWeek : '[Өткен аптаның] dddd [сағат] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s ішінде',
+ past : '%s бұрын',
+ s : 'бірнеше секунд',
+ m : 'бір минут',
+ mm : '%d минут',
+ h : 'бір сағат',
+ hh : '%d сағат',
+ d : 'бір күн',
+ dd : '%d күн',
+ M : 'бір ай',
+ MM : '%d ай',
+ y : 'бір жыл',
+ yy : '%d жыл'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(ші|шы)/,
+ ordinal : function (number) {
+ var a = number % 10,
+ b = number >= 100 ? 100 : null;
+ return number + (suffixes[number] || suffixes[a] || suffixes[b]);
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return kk;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/km.js b/www/wiki/resources/lib/moment/locale/km.js
new file mode 100644
index 00000000..71482a7b
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/km.js
@@ -0,0 +1,58 @@
+//! moment.js locale configuration
+//! locale : Cambodian [km]
+//! author : Kruy Vanna : https://github.com/kruyvanna
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var km = moment.defineLocale('km', {
+ months: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
+ monthsShort: 'មករា_កុម្ភៈ_មីនា_មេសា_ឧសភា_មិថុនា_កក្កដា_សីហា_កញ្ញា_តុលា_វិច្ឆិកា_ធ្នូ'.split('_'),
+ weekdays: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+ weekdaysShort: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+ weekdaysMin: 'អាទិត្យ_ច័ន្ទ_អង្គារ_ពុធ_ព្រហស្បតិ៍_សុក្រ_សៅរ៍'.split('_'),
+ longDateFormat: {
+ LT: 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY HH:mm',
+ LLLL: 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar: {
+ sameDay: '[ថ្ងៃនេះ ម៉ោង] LT',
+ nextDay: '[ស្អែក ម៉ោង] LT',
+ nextWeek: 'dddd [ម៉ោង] LT',
+ lastDay: '[ម្សិលមិញ ម៉ោង] LT',
+ lastWeek: 'dddd [សប្តាហ៍មុន] [ម៉ោង] LT',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: '%sទៀត',
+ past: '%sមុន',
+ s: 'ប៉ុន្មានវិនាទី',
+ m: 'មួយនាទី',
+ mm: '%d នាទី',
+ h: 'មួយម៉ោង',
+ hh: '%d ម៉ោង',
+ d: 'មួយថ្ងៃ',
+ dd: '%d ថ្ងៃ',
+ M: 'មួយខែ',
+ MM: '%d ខែ',
+ y: 'មួយឆ្នាំ',
+ yy: '%d ឆ្នាំ'
+ },
+ week: {
+ dow: 1, // Monday is the first day of the week.
+ doy: 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return km;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/kn.js b/www/wiki/resources/lib/moment/locale/kn.js
new file mode 100644
index 00000000..aeacafa6
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/kn.js
@@ -0,0 +1,126 @@
+//! moment.js locale configuration
+//! locale : Kannada [kn]
+//! author : Rajeev Naik : https://github.com/rajeevnaikte
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '೧',
+ '2': '೨',
+ '3': '೩',
+ '4': '೪',
+ '5': '೫',
+ '6': '೬',
+ '7': '೭',
+ '8': '೮',
+ '9': '೯',
+ '0': '೦'
+};
+var numberMap = {
+ '೧': '1',
+ '೨': '2',
+ '೩': '3',
+ '೪': '4',
+ '೫': '5',
+ '೬': '6',
+ '೭': '7',
+ '೮': '8',
+ '೯': '9',
+ '೦': '0'
+};
+
+var kn = moment.defineLocale('kn', {
+ months : 'ಜನವರಿ_ಫೆಬ್ರವರಿ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂಬರ್_ಅಕ್ಟೋಬರ್_ನವೆಂಬರ್_ಡಿಸೆಂಬರ್'.split('_'),
+ monthsShort : 'ಜನ_ಫೆಬ್ರ_ಮಾರ್ಚ್_ಏಪ್ರಿಲ್_ಮೇ_ಜೂನ್_ಜುಲೈ_ಆಗಸ್ಟ್_ಸೆಪ್ಟೆಂಬ_ಅಕ್ಟೋಬ_ನವೆಂಬ_ಡಿಸೆಂಬ'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'ಭಾನುವಾರ_ಸೋಮವಾರ_ಮಂಗಳವಾರ_ಬುಧವಾರ_ಗುರುವಾರ_ಶುಕ್ರವಾರ_ಶನಿವಾರ'.split('_'),
+ weekdaysShort : 'ಭಾನು_ಸೋಮ_ಮಂಗಳ_ಬುಧ_ಗುರು_ಶುಕ್ರ_ಶನಿ'.split('_'),
+ weekdaysMin : 'ಭಾ_ಸೋ_ಮಂ_ಬು_ಗು_ಶು_ಶ'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm',
+ LTS : 'A h:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm'
+ },
+ calendar : {
+ sameDay : '[ಇಂದು] LT',
+ nextDay : '[ನಾಳೆ] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[ನಿನ್ನೆ] LT',
+ lastWeek : '[ಕೊನೆಯ] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s ನಂತರ',
+ past : '%s ಹಿಂದೆ',
+ s : 'ಕೆಲವು ಕ್ಷಣಗಳು',
+ m : 'ಒಂದು ನಿಮಿಷ',
+ mm : '%d ನಿಮಿಷ',
+ h : 'ಒಂದು ಗಂಟೆ',
+ hh : '%d ಗಂಟೆ',
+ d : 'ಒಂದು ದಿನ',
+ dd : '%d ದಿನ',
+ M : 'ಒಂದು ತಿಂಗಳು',
+ MM : '%d ತಿಂಗಳು',
+ y : 'ಒಂದು ವರ್ಷ',
+ yy : '%d ವರ್ಷ'
+ },
+ preparse: function (string) {
+ return string.replace(/[೧೨೩೪೫೬೭೮೯೦]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ meridiemParse: /ರಾತ್ರಿ|ಬೆಳಿಗ್ಗೆ|ಮಧ್ಯಾಹ್ನ|ಸಂಜೆ/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'ರಾತ್ರಿ') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'ಬೆಳಿಗ್ಗೆ') {
+ return hour;
+ } else if (meridiem === 'ಮಧ್ಯಾಹ್ನ') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'ಸಂಜೆ') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'ರಾತ್ರಿ';
+ } else if (hour < 10) {
+ return 'ಬೆಳಿಗ್ಗೆ';
+ } else if (hour < 17) {
+ return 'ಮಧ್ಯಾಹ್ನ';
+ } else if (hour < 20) {
+ return 'ಸಂಜೆ';
+ } else {
+ return 'ರಾತ್ರಿ';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(ನೇ)/,
+ ordinal : function (number) {
+ return number + 'ನೇ';
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return kn;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ko.js b/www/wiki/resources/lib/moment/locale/ko.js
new file mode 100644
index 00000000..8ac7913f
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ko.js
@@ -0,0 +1,83 @@
+//! moment.js locale configuration
+//! locale : Korean [ko]
+//! author : Kyungwook, Park : https://github.com/kyungw00k
+//! author : Jeeeyul Lee <jeeeyul@gmail.com>
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ko = moment.defineLocale('ko', {
+ months : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
+ monthsShort : '1월_2월_3월_4월_5월_6월_7월_8월_9월_10월_11월_12월'.split('_'),
+ weekdays : '일요일_월요일_화요일_수요일_목요일_금요일_토요일'.split('_'),
+ weekdaysShort : '일_월_화_수_목_금_토'.split('_'),
+ weekdaysMin : '일_월_화_수_목_금_토'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm',
+ LTS : 'A h:mm:ss',
+ L : 'YYYY.MM.DD',
+ LL : 'YYYY년 MMMM D일',
+ LLL : 'YYYY년 MMMM D일 A h:mm',
+ LLLL : 'YYYY년 MMMM D일 dddd A h:mm',
+ l : 'YYYY.MM.DD',
+ ll : 'YYYY년 MMMM D일',
+ lll : 'YYYY년 MMMM D일 A h:mm',
+ llll : 'YYYY년 MMMM D일 dddd A h:mm'
+ },
+ calendar : {
+ sameDay : '오늘 LT',
+ nextDay : '내일 LT',
+ nextWeek : 'dddd LT',
+ lastDay : '어제 LT',
+ lastWeek : '지난주 dddd LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s 후',
+ past : '%s 전',
+ s : '몇 초',
+ ss : '%d초',
+ m : '1분',
+ mm : '%d분',
+ h : '한 시간',
+ hh : '%d시간',
+ d : '하루',
+ dd : '%d일',
+ M : '한 달',
+ MM : '%d달',
+ y : '일 년',
+ yy : '%d년'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}(일|월|주)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return number + '일';
+ case 'M':
+ return number + '월';
+ case 'w':
+ case 'W':
+ return number + '주';
+ default:
+ return number;
+ }
+ },
+ meridiemParse : /오전|오후/,
+ isPM : function (token) {
+ return token === '오후';
+ },
+ meridiem : function (hour, minute, isUpper) {
+ return hour < 12 ? '오전' : '오후';
+ }
+});
+
+return ko;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ky.js b/www/wiki/resources/lib/moment/locale/ky.js
new file mode 100644
index 00000000..ae4053a3
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ky.js
@@ -0,0 +1,88 @@
+//! moment.js locale configuration
+//! locale : Kyrgyz [ky]
+//! author : Chyngyz Arystan uulu : https://github.com/chyngyz
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+
+var suffixes = {
+ 0: '-чү',
+ 1: '-чи',
+ 2: '-чи',
+ 3: '-чү',
+ 4: '-чү',
+ 5: '-чи',
+ 6: '-чы',
+ 7: '-чи',
+ 8: '-чи',
+ 9: '-чу',
+ 10: '-чу',
+ 20: '-чы',
+ 30: '-чу',
+ 40: '-чы',
+ 50: '-чү',
+ 60: '-чы',
+ 70: '-чи',
+ 80: '-чи',
+ 90: '-чу',
+ 100: '-чү'
+};
+
+var ky = moment.defineLocale('ky', {
+ months : 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_'),
+ monthsShort : 'янв_фев_март_апр_май_июнь_июль_авг_сен_окт_ноя_дек'.split('_'),
+ weekdays : 'Жекшемби_Дүйшөмбү_Шейшемби_Шаршемби_Бейшемби_Жума_Ишемби'.split('_'),
+ weekdaysShort : 'Жек_Дүй_Шей_Шар_Бей_Жум_Ише'.split('_'),
+ weekdaysMin : 'Жк_Дй_Шй_Шр_Бй_Жм_Иш'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Бүгүн саат] LT',
+ nextDay : '[Эртең саат] LT',
+ nextWeek : 'dddd [саат] LT',
+ lastDay : '[Кече саат] LT',
+ lastWeek : '[Өткен аптанын] dddd [күнү] [саат] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s ичинде',
+ past : '%s мурун',
+ s : 'бирнече секунд',
+ m : 'бир мүнөт',
+ mm : '%d мүнөт',
+ h : 'бир саат',
+ hh : '%d саат',
+ d : 'бир күн',
+ dd : '%d күн',
+ M : 'бир ай',
+ MM : '%d ай',
+ y : 'бир жыл',
+ yy : '%d жыл'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(чи|чы|чү|чу)/,
+ ordinal : function (number) {
+ var a = number % 10,
+ b = number >= 100 ? 100 : null;
+ return number + (suffixes[number] || suffixes[a] || suffixes[b]);
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ky;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/lb.js b/www/wiki/resources/lib/moment/locale/lb.js
new file mode 100644
index 00000000..56c18039
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/lb.js
@@ -0,0 +1,137 @@
+//! moment.js locale configuration
+//! locale : Luxembourgish [lb]
+//! author : mweimerskirch : https://github.com/mweimerskirch
+//! author : David Raison : https://github.com/kwisatz
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var format = {
+ 'm': ['eng Minutt', 'enger Minutt'],
+ 'h': ['eng Stonn', 'enger Stonn'],
+ 'd': ['een Dag', 'engem Dag'],
+ 'M': ['ee Mount', 'engem Mount'],
+ 'y': ['ee Joer', 'engem Joer']
+ };
+ return withoutSuffix ? format[key][0] : format[key][1];
+}
+function processFutureTime(string) {
+ var number = string.substr(0, string.indexOf(' '));
+ if (eifelerRegelAppliesToNumber(number)) {
+ return 'a ' + string;
+ }
+ return 'an ' + string;
+}
+function processPastTime(string) {
+ var number = string.substr(0, string.indexOf(' '));
+ if (eifelerRegelAppliesToNumber(number)) {
+ return 'viru ' + string;
+ }
+ return 'virun ' + string;
+}
+/**
+ * Returns true if the word before the given number loses the '-n' ending.
+ * e.g. 'an 10 Deeg' but 'a 5 Deeg'
+ *
+ * @param number {integer}
+ * @returns {boolean}
+ */
+function eifelerRegelAppliesToNumber(number) {
+ number = parseInt(number, 10);
+ if (isNaN(number)) {
+ return false;
+ }
+ if (number < 0) {
+ // Negative Number --> always true
+ return true;
+ } else if (number < 10) {
+ // Only 1 digit
+ if (4 <= number && number <= 7) {
+ return true;
+ }
+ return false;
+ } else if (number < 100) {
+ // 2 digits
+ var lastDigit = number % 10, firstDigit = number / 10;
+ if (lastDigit === 0) {
+ return eifelerRegelAppliesToNumber(firstDigit);
+ }
+ return eifelerRegelAppliesToNumber(lastDigit);
+ } else if (number < 10000) {
+ // 3 or 4 digits --> recursively check first digit
+ while (number >= 10) {
+ number = number / 10;
+ }
+ return eifelerRegelAppliesToNumber(number);
+ } else {
+ // Anything larger than 4 digits: recursively check first n-3 digits
+ number = number / 1000;
+ return eifelerRegelAppliesToNumber(number);
+ }
+}
+
+var lb = moment.defineLocale('lb', {
+ months: 'Januar_Februar_Mäerz_Abrëll_Mee_Juni_Juli_August_September_Oktober_November_Dezember'.split('_'),
+ monthsShort: 'Jan._Febr._Mrz._Abr._Mee_Jun._Jul._Aug._Sept._Okt._Nov._Dez.'.split('_'),
+ monthsParseExact : true,
+ weekdays: 'Sonndeg_Méindeg_Dënschdeg_Mëttwoch_Donneschdeg_Freideg_Samschdeg'.split('_'),
+ weekdaysShort: 'So._Mé._Dë._Më._Do._Fr._Sa.'.split('_'),
+ weekdaysMin: 'So_Mé_Dë_Më_Do_Fr_Sa'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat: {
+ LT: 'H:mm [Auer]',
+ LTS: 'H:mm:ss [Auer]',
+ L: 'DD.MM.YYYY',
+ LL: 'D. MMMM YYYY',
+ LLL: 'D. MMMM YYYY H:mm [Auer]',
+ LLLL: 'dddd, D. MMMM YYYY H:mm [Auer]'
+ },
+ calendar: {
+ sameDay: '[Haut um] LT',
+ sameElse: 'L',
+ nextDay: '[Muer um] LT',
+ nextWeek: 'dddd [um] LT',
+ lastDay: '[Gëschter um] LT',
+ lastWeek: function () {
+ // Different date string for 'Dënschdeg' (Tuesday) and 'Donneschdeg' (Thursday) due to phonological rule
+ switch (this.day()) {
+ case 2:
+ case 4:
+ return '[Leschten] dddd [um] LT';
+ default:
+ return '[Leschte] dddd [um] LT';
+ }
+ }
+ },
+ relativeTime : {
+ future : processFutureTime,
+ past : processPastTime,
+ s : 'e puer Sekonnen',
+ m : processRelativeTime,
+ mm : '%d Minutten',
+ h : processRelativeTime,
+ hh : '%d Stonnen',
+ d : processRelativeTime,
+ dd : '%d Deeg',
+ M : processRelativeTime,
+ MM : '%d Méint',
+ y : processRelativeTime,
+ yy : '%d Joer'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal: '%d.',
+ week: {
+ dow: 1, // Monday is the first day of the week.
+ doy: 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return lb;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/lo.js b/www/wiki/resources/lib/moment/locale/lo.js
new file mode 100644
index 00000000..8e5cdbdd
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/lo.js
@@ -0,0 +1,70 @@
+//! moment.js locale configuration
+//! locale : Lao [lo]
+//! author : Ryan Hart : https://github.com/ryanhart2
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var lo = moment.defineLocale('lo', {
+ months : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'),
+ monthsShort : 'ມັງກອນ_ກຸມພາ_ມີນາ_ເມສາ_ພຶດສະພາ_ມິຖຸນາ_ກໍລະກົດ_ສິງຫາ_ກັນຍາ_ຕຸລາ_ພະຈິກ_ທັນວາ'.split('_'),
+ weekdays : 'ອາທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
+ weekdaysShort : 'ທິດ_ຈັນ_ອັງຄານ_ພຸດ_ພະຫັດ_ສຸກ_ເສົາ'.split('_'),
+ weekdaysMin : 'ທ_ຈ_ອຄ_ພ_ພຫ_ສກ_ສ'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'ວັນdddd D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /ຕອນເຊົ້າ|ຕອນແລງ/,
+ isPM: function (input) {
+ return input === 'ຕອນແລງ';
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'ຕອນເຊົ້າ';
+ } else {
+ return 'ຕອນແລງ';
+ }
+ },
+ calendar : {
+ sameDay : '[ມື້ນີ້ເວລາ] LT',
+ nextDay : '[ມື້ອື່ນເວລາ] LT',
+ nextWeek : '[ວັນ]dddd[ໜ້າເວລາ] LT',
+ lastDay : '[ມື້ວານນີ້ເວລາ] LT',
+ lastWeek : '[ວັນ]dddd[ແລ້ວນີ້ເວລາ] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'ອີກ %s',
+ past : '%sຜ່ານມາ',
+ s : 'ບໍ່ເທົ່າໃດວິນາທີ',
+ m : '1 ນາທີ',
+ mm : '%d ນາທີ',
+ h : '1 ຊົ່ວໂມງ',
+ hh : '%d ຊົ່ວໂມງ',
+ d : '1 ມື້',
+ dd : '%d ມື້',
+ M : '1 ເດືອນ',
+ MM : '%d ເດືອນ',
+ y : '1 ປີ',
+ yy : '%d ປີ'
+ },
+ dayOfMonthOrdinalParse: /(ທີ່)\d{1,2}/,
+ ordinal : function (number) {
+ return 'ທີ່' + number;
+ }
+});
+
+return lo;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/lt.js b/www/wiki/resources/lib/moment/locale/lt.js
new file mode 100644
index 00000000..d2fb7603
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/lt.js
@@ -0,0 +1,117 @@
+//! moment.js locale configuration
+//! locale : Lithuanian [lt]
+//! author : Mindaugas Mozūras : https://github.com/mmozuras
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var units = {
+ 'm' : 'minutė_minutės_minutę',
+ 'mm': 'minutės_minučių_minutes',
+ 'h' : 'valanda_valandos_valandą',
+ 'hh': 'valandos_valandų_valandas',
+ 'd' : 'diena_dienos_dieną',
+ 'dd': 'dienos_dienų_dienas',
+ 'M' : 'mėnuo_mėnesio_mėnesį',
+ 'MM': 'mėnesiai_mėnesių_mėnesius',
+ 'y' : 'metai_metų_metus',
+ 'yy': 'metai_metų_metus'
+};
+function translateSeconds(number, withoutSuffix, key, isFuture) {
+ if (withoutSuffix) {
+ return 'kelios sekundės';
+ } else {
+ return isFuture ? 'kelių sekundžių' : 'kelias sekundes';
+ }
+}
+function translateSingular(number, withoutSuffix, key, isFuture) {
+ return withoutSuffix ? forms(key)[0] : (isFuture ? forms(key)[1] : forms(key)[2]);
+}
+function special(number) {
+ return number % 10 === 0 || (number > 10 && number < 20);
+}
+function forms(key) {
+ return units[key].split('_');
+}
+function translate(number, withoutSuffix, key, isFuture) {
+ var result = number + ' ';
+ if (number === 1) {
+ return result + translateSingular(number, withoutSuffix, key[0], isFuture);
+ } else if (withoutSuffix) {
+ return result + (special(number) ? forms(key)[1] : forms(key)[0]);
+ } else {
+ if (isFuture) {
+ return result + forms(key)[1];
+ } else {
+ return result + (special(number) ? forms(key)[1] : forms(key)[2]);
+ }
+ }
+}
+var lt = moment.defineLocale('lt', {
+ months : {
+ format: 'sausio_vasario_kovo_balandžio_gegužės_birželio_liepos_rugpjūčio_rugsėjo_spalio_lapkričio_gruodžio'.split('_'),
+ standalone: 'sausis_vasaris_kovas_balandis_gegužė_birželis_liepa_rugpjūtis_rugsėjis_spalis_lapkritis_gruodis'.split('_'),
+ isFormat: /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?|MMMM?(\[[^\[\]]*\]|\s)+D[oD]?/
+ },
+ monthsShort : 'sau_vas_kov_bal_geg_bir_lie_rgp_rgs_spa_lap_grd'.split('_'),
+ weekdays : {
+ format: 'sekmadienį_pirmadienį_antradienį_trečiadienį_ketvirtadienį_penktadienį_šeštadienį'.split('_'),
+ standalone: 'sekmadienis_pirmadienis_antradienis_trečiadienis_ketvirtadienis_penktadienis_šeštadienis'.split('_'),
+ isFormat: /dddd HH:mm/
+ },
+ weekdaysShort : 'Sek_Pir_Ant_Tre_Ket_Pen_Šeš'.split('_'),
+ weekdaysMin : 'S_P_A_T_K_Pn_Š'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY-MM-DD',
+ LL : 'YYYY [m.] MMMM D [d.]',
+ LLL : 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
+ LLLL : 'YYYY [m.] MMMM D [d.], dddd, HH:mm [val.]',
+ l : 'YYYY-MM-DD',
+ ll : 'YYYY [m.] MMMM D [d.]',
+ lll : 'YYYY [m.] MMMM D [d.], HH:mm [val.]',
+ llll : 'YYYY [m.] MMMM D [d.], ddd, HH:mm [val.]'
+ },
+ calendar : {
+ sameDay : '[Šiandien] LT',
+ nextDay : '[Rytoj] LT',
+ nextWeek : 'dddd LT',
+ lastDay : '[Vakar] LT',
+ lastWeek : '[Praėjusį] dddd LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'po %s',
+ past : 'prieš %s',
+ s : translateSeconds,
+ m : translateSingular,
+ mm : translate,
+ h : translateSingular,
+ hh : translate,
+ d : translateSingular,
+ dd : translate,
+ M : translateSingular,
+ MM : translate,
+ y : translateSingular,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-oji/,
+ ordinal : function (number) {
+ return number + '-oji';
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return lt;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/lv.js b/www/wiki/resources/lib/moment/locale/lv.js
new file mode 100644
index 00000000..e2d98879
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/lv.js
@@ -0,0 +1,97 @@
+//! moment.js locale configuration
+//! locale : Latvian [lv]
+//! author : Kristaps Karlsons : https://github.com/skakri
+//! author : Jānis Elmeris : https://github.com/JanisE
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var units = {
+ 'm': 'minūtes_minūtēm_minūte_minūtes'.split('_'),
+ 'mm': 'minūtes_minūtēm_minūte_minūtes'.split('_'),
+ 'h': 'stundas_stundām_stunda_stundas'.split('_'),
+ 'hh': 'stundas_stundām_stunda_stundas'.split('_'),
+ 'd': 'dienas_dienām_diena_dienas'.split('_'),
+ 'dd': 'dienas_dienām_diena_dienas'.split('_'),
+ 'M': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
+ 'MM': 'mēneša_mēnešiem_mēnesis_mēneši'.split('_'),
+ 'y': 'gada_gadiem_gads_gadi'.split('_'),
+ 'yy': 'gada_gadiem_gads_gadi'.split('_')
+};
+/**
+ * @param withoutSuffix boolean true = a length of time; false = before/after a period of time.
+ */
+function format(forms, number, withoutSuffix) {
+ if (withoutSuffix) {
+ // E.g. "21 minūte", "3 minūtes".
+ return number % 10 === 1 && number % 100 !== 11 ? forms[2] : forms[3];
+ } else {
+ // E.g. "21 minūtes" as in "pēc 21 minūtes".
+ // E.g. "3 minūtēm" as in "pēc 3 minūtēm".
+ return number % 10 === 1 && number % 100 !== 11 ? forms[0] : forms[1];
+ }
+}
+function relativeTimeWithPlural(number, withoutSuffix, key) {
+ return number + ' ' + format(units[key], number, withoutSuffix);
+}
+function relativeTimeWithSingular(number, withoutSuffix, key) {
+ return format(units[key], number, withoutSuffix);
+}
+function relativeSeconds(number, withoutSuffix) {
+ return withoutSuffix ? 'dažas sekundes' : 'dažām sekundēm';
+}
+
+var lv = moment.defineLocale('lv', {
+ months : 'janvāris_februāris_marts_aprīlis_maijs_jūnijs_jūlijs_augusts_septembris_oktobris_novembris_decembris'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_mai_jūn_jūl_aug_sep_okt_nov_dec'.split('_'),
+ weekdays : 'svētdiena_pirmdiena_otrdiena_trešdiena_ceturtdiena_piektdiena_sestdiena'.split('_'),
+ weekdaysShort : 'Sv_P_O_T_C_Pk_S'.split('_'),
+ weekdaysMin : 'Sv_P_O_T_C_Pk_S'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY.',
+ LL : 'YYYY. [gada] D. MMMM',
+ LLL : 'YYYY. [gada] D. MMMM, HH:mm',
+ LLLL : 'YYYY. [gada] D. MMMM, dddd, HH:mm'
+ },
+ calendar : {
+ sameDay : '[Šodien pulksten] LT',
+ nextDay : '[Rīt pulksten] LT',
+ nextWeek : 'dddd [pulksten] LT',
+ lastDay : '[Vakar pulksten] LT',
+ lastWeek : '[Pagājušā] dddd [pulksten] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'pēc %s',
+ past : 'pirms %s',
+ s : relativeSeconds,
+ m : relativeTimeWithSingular,
+ mm : relativeTimeWithPlural,
+ h : relativeTimeWithSingular,
+ hh : relativeTimeWithPlural,
+ d : relativeTimeWithSingular,
+ dd : relativeTimeWithPlural,
+ M : relativeTimeWithSingular,
+ MM : relativeTimeWithPlural,
+ y : relativeTimeWithSingular,
+ yy : relativeTimeWithPlural
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return lv;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/mi.js b/www/wiki/resources/lib/moment/locale/mi.js
new file mode 100644
index 00000000..c5cce374
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/mi.js
@@ -0,0 +1,64 @@
+//! moment.js locale configuration
+//! locale : Maori [mi]
+//! author : John Corrigan <robbiecloset@gmail.com> : https://github.com/johnideal
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var mi = moment.defineLocale('mi', {
+ months: 'Kohi-tāte_Hui-tanguru_Poutū-te-rangi_Paenga-whāwhā_Haratua_Pipiri_Hōngoingoi_Here-turi-kōkā_Mahuru_Whiringa-ā-nuku_Whiringa-ā-rangi_Hakihea'.split('_'),
+ monthsShort: 'Kohi_Hui_Pou_Pae_Hara_Pipi_Hōngoi_Here_Mahu_Whi-nu_Whi-ra_Haki'.split('_'),
+ monthsRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
+ monthsStrictRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
+ monthsShortRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,3}/i,
+ monthsShortStrictRegex: /(?:['a-z\u0101\u014D\u016B]+\-?){1,2}/i,
+ weekdays: 'Rātapu_Mane_Tūrei_Wenerei_Tāite_Paraire_Hātarei'.split('_'),
+ weekdaysShort: 'Ta_Ma_Tū_We_Tāi_Pa_Hā'.split('_'),
+ weekdaysMin: 'Ta_Ma_Tū_We_Tāi_Pa_Hā'.split('_'),
+ longDateFormat: {
+ LT: 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY [i] HH:mm',
+ LLLL: 'dddd, D MMMM YYYY [i] HH:mm'
+ },
+ calendar: {
+ sameDay: '[i teie mahana, i] LT',
+ nextDay: '[apopo i] LT',
+ nextWeek: 'dddd [i] LT',
+ lastDay: '[inanahi i] LT',
+ lastWeek: 'dddd [whakamutunga i] LT',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: 'i roto i %s',
+ past: '%s i mua',
+ s: 'te hēkona ruarua',
+ m: 'he meneti',
+ mm: '%d meneti',
+ h: 'te haora',
+ hh: '%d haora',
+ d: 'he ra',
+ dd: '%d ra',
+ M: 'he marama',
+ MM: '%d marama',
+ y: 'he tau',
+ yy: '%d tau'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}º/,
+ ordinal: '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return mi;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/mk.js b/www/wiki/resources/lib/moment/locale/mk.js
new file mode 100644
index 00000000..cdfb1e1c
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/mk.js
@@ -0,0 +1,90 @@
+//! moment.js locale configuration
+//! locale : Macedonian [mk]
+//! author : Borislav Mickov : https://github.com/B0k0
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var mk = moment.defineLocale('mk', {
+ months : 'јануари_февруари_март_април_мај_јуни_јули_август_септември_октомври_ноември_декември'.split('_'),
+ monthsShort : 'јан_фев_мар_апр_мај_јун_јул_авг_сеп_окт_ное_дек'.split('_'),
+ weekdays : 'недела_понеделник_вторник_среда_четврток_петок_сабота'.split('_'),
+ weekdaysShort : 'нед_пон_вто_сре_чет_пет_саб'.split('_'),
+ weekdaysMin : 'нe_пo_вт_ср_че_пе_сa'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'D.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY H:mm',
+ LLLL : 'dddd, D MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[Денес во] LT',
+ nextDay : '[Утре во] LT',
+ nextWeek : '[Во] dddd [во] LT',
+ lastDay : '[Вчера во] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ case 6:
+ return '[Изминатата] dddd [во] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[Изминатиот] dddd [во] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'после %s',
+ past : 'пред %s',
+ s : 'неколку секунди',
+ m : 'минута',
+ mm : '%d минути',
+ h : 'час',
+ hh : '%d часа',
+ d : 'ден',
+ dd : '%d дена',
+ M : 'месец',
+ MM : '%d месеци',
+ y : 'година',
+ yy : '%d години'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(ев|ен|ти|ви|ри|ми)/,
+ ordinal : function (number) {
+ var lastDigit = number % 10,
+ last2Digits = number % 100;
+ if (number === 0) {
+ return number + '-ев';
+ } else if (last2Digits === 0) {
+ return number + '-ен';
+ } else if (last2Digits > 10 && last2Digits < 20) {
+ return number + '-ти';
+ } else if (lastDigit === 1) {
+ return number + '-ви';
+ } else if (lastDigit === 2) {
+ return number + '-ри';
+ } else if (lastDigit === 7 || lastDigit === 8) {
+ return number + '-ми';
+ } else {
+ return number + '-ти';
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return mk;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ml.js b/www/wiki/resources/lib/moment/locale/ml.js
new file mode 100644
index 00000000..e5f52e9c
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ml.js
@@ -0,0 +1,81 @@
+//! moment.js locale configuration
+//! locale : Malayalam [ml]
+//! author : Floyd Pink : https://github.com/floydpink
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ml = moment.defineLocale('ml', {
+ months : 'ജനുവരി_ഫെബ്രുവരി_മാർച്ച്_ഏപ്രിൽ_മേയ്_ജൂൺ_ജൂലൈ_ഓഗസ്റ്റ്_സെപ്റ്റംബർ_ഒക്ടോബർ_നവംബർ_ഡിസംബർ'.split('_'),
+ monthsShort : 'ജനു._ഫെബ്രു._മാർ._ഏപ്രി._മേയ്_ജൂൺ_ജൂലൈ._ഓഗ._സെപ്റ്റ._ഒക്ടോ._നവം._ഡിസം.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'ഞായറാഴ്ച_തിങ്കളാഴ്ച_ചൊവ്വാഴ്ച_ബുധനാഴ്ച_വ്യാഴാഴ്ച_വെള്ളിയാഴ്ച_ശനിയാഴ്ച'.split('_'),
+ weekdaysShort : 'ഞായർ_തിങ്കൾ_ചൊവ്വ_ബുധൻ_വ്യാഴം_വെള്ളി_ശനി'.split('_'),
+ weekdaysMin : 'ഞാ_തി_ചൊ_ബു_വ്യാ_വെ_ശ'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm -നു',
+ LTS : 'A h:mm:ss -നു',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm -നു',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm -നു'
+ },
+ calendar : {
+ sameDay : '[ഇന്ന്] LT',
+ nextDay : '[നാളെ] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[ഇന്നലെ] LT',
+ lastWeek : '[കഴിഞ്ഞ] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s കഴിഞ്ഞ്',
+ past : '%s മുൻപ്',
+ s : 'അൽപ നിമിഷങ്ങൾ',
+ m : 'ഒരു മിനിറ്റ്',
+ mm : '%d മിനിറ്റ്',
+ h : 'ഒരു മണിക്കൂർ',
+ hh : '%d മണിക്കൂർ',
+ d : 'ഒരു ദിവസം',
+ dd : '%d ദിവസം',
+ M : 'ഒരു മാസം',
+ MM : '%d മാസം',
+ y : 'ഒരു വർഷം',
+ yy : '%d വർഷം'
+ },
+ meridiemParse: /രാത്രി|രാവിലെ|ഉച്ച കഴിഞ്ഞ്|വൈകുന്നേരം|രാത്രി/i,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if ((meridiem === 'രാത്രി' && hour >= 4) ||
+ meridiem === 'ഉച്ച കഴിഞ്ഞ്' ||
+ meridiem === 'വൈകുന്നേരം') {
+ return hour + 12;
+ } else {
+ return hour;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'രാത്രി';
+ } else if (hour < 12) {
+ return 'രാവിലെ';
+ } else if (hour < 17) {
+ return 'ഉച്ച കഴിഞ്ഞ്';
+ } else if (hour < 20) {
+ return 'വൈകുന്നേരം';
+ } else {
+ return 'രാത്രി';
+ }
+ }
+});
+
+return ml;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/mr.js b/www/wiki/resources/lib/moment/locale/mr.js
new file mode 100644
index 00000000..abe1024b
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/mr.js
@@ -0,0 +1,159 @@
+//! moment.js locale configuration
+//! locale : Marathi [mr]
+//! author : Harshad Kale : https://github.com/kalehv
+//! author : Vivek Athalye : https://github.com/vnathalye
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '१',
+ '2': '२',
+ '3': '३',
+ '4': '४',
+ '5': '५',
+ '6': '६',
+ '7': '७',
+ '8': '८',
+ '9': '९',
+ '0': '०'
+};
+var numberMap = {
+ '१': '1',
+ '२': '2',
+ '३': '3',
+ '४': '4',
+ '५': '5',
+ '६': '6',
+ '७': '7',
+ '८': '8',
+ '९': '9',
+ '०': '0'
+};
+
+function relativeTimeMr(number, withoutSuffix, string, isFuture)
+{
+ var output = '';
+ if (withoutSuffix) {
+ switch (string) {
+ case 's': output = 'काही सेकंद'; break;
+ case 'm': output = 'एक मिनिट'; break;
+ case 'mm': output = '%d मिनिटे'; break;
+ case 'h': output = 'एक तास'; break;
+ case 'hh': output = '%d तास'; break;
+ case 'd': output = 'एक दिवस'; break;
+ case 'dd': output = '%d दिवस'; break;
+ case 'M': output = 'एक महिना'; break;
+ case 'MM': output = '%d महिने'; break;
+ case 'y': output = 'एक वर्ष'; break;
+ case 'yy': output = '%d वर्षे'; break;
+ }
+ }
+ else {
+ switch (string) {
+ case 's': output = 'काही सेकंदां'; break;
+ case 'm': output = 'एका मिनिटा'; break;
+ case 'mm': output = '%d मिनिटां'; break;
+ case 'h': output = 'एका तासा'; break;
+ case 'hh': output = '%d तासां'; break;
+ case 'd': output = 'एका दिवसा'; break;
+ case 'dd': output = '%d दिवसां'; break;
+ case 'M': output = 'एका महिन्या'; break;
+ case 'MM': output = '%d महिन्यां'; break;
+ case 'y': output = 'एका वर्षा'; break;
+ case 'yy': output = '%d वर्षां'; break;
+ }
+ }
+ return output.replace(/%d/i, number);
+}
+
+var mr = moment.defineLocale('mr', {
+ months : 'जानेवारी_फेब्रुवारी_मार्च_एप्रिल_मे_जून_जुलै_ऑगस्ट_सप्टेंबर_ऑक्टोबर_नोव्हेंबर_डिसेंबर'.split('_'),
+ monthsShort: 'जाने._फेब्रु._मार्च._एप्रि._मे._जून._जुलै._ऑग._सप्टें._ऑक्टो._नोव्हें._डिसें.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'रविवार_सोमवार_मंगळवार_बुधवार_गुरूवार_शुक्रवार_शनिवार'.split('_'),
+ weekdaysShort : 'रवि_सोम_मंगळ_बुध_गुरू_शुक्र_शनि'.split('_'),
+ weekdaysMin : 'र_सो_मं_बु_गु_शु_श'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm वाजता',
+ LTS : 'A h:mm:ss वाजता',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm वाजता',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm वाजता'
+ },
+ calendar : {
+ sameDay : '[आज] LT',
+ nextDay : '[उद्या] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[काल] LT',
+ lastWeek: '[मागील] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future: '%sमध्ये',
+ past: '%sपूर्वी',
+ s: relativeTimeMr,
+ m: relativeTimeMr,
+ mm: relativeTimeMr,
+ h: relativeTimeMr,
+ hh: relativeTimeMr,
+ d: relativeTimeMr,
+ dd: relativeTimeMr,
+ M: relativeTimeMr,
+ MM: relativeTimeMr,
+ y: relativeTimeMr,
+ yy: relativeTimeMr
+ },
+ preparse: function (string) {
+ return string.replace(/[१२३४५६७८९०]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ meridiemParse: /रात्री|सकाळी|दुपारी|सायंकाळी/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'रात्री') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'सकाळी') {
+ return hour;
+ } else if (meridiem === 'दुपारी') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'सायंकाळी') {
+ return hour + 12;
+ }
+ },
+ meridiem: function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'रात्री';
+ } else if (hour < 10) {
+ return 'सकाळी';
+ } else if (hour < 17) {
+ return 'दुपारी';
+ } else if (hour < 20) {
+ return 'सायंकाळी';
+ } else {
+ return 'रात्री';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return mr;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ms-my.js b/www/wiki/resources/lib/moment/locale/ms-my.js
new file mode 100644
index 00000000..0cb403d3
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ms-my.js
@@ -0,0 +1,83 @@
+//! moment.js locale configuration
+//! locale : Malay [ms-my]
+//! note : DEPRECATED, the correct one is [ms]
+//! author : Weldan Jamili : https://github.com/weldan
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var msMy = moment.defineLocale('ms-my', {
+ months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
+ monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
+ weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
+ weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
+ weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
+ longDateFormat : {
+ LT : 'HH.mm',
+ LTS : 'HH.mm.ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY [pukul] HH.mm',
+ LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+ },
+ meridiemParse: /pagi|tengahari|petang|malam/,
+ meridiemHour: function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'pagi') {
+ return hour;
+ } else if (meridiem === 'tengahari') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === 'petang' || meridiem === 'malam') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 11) {
+ return 'pagi';
+ } else if (hours < 15) {
+ return 'tengahari';
+ } else if (hours < 19) {
+ return 'petang';
+ } else {
+ return 'malam';
+ }
+ },
+ calendar : {
+ sameDay : '[Hari ini pukul] LT',
+ nextDay : '[Esok pukul] LT',
+ nextWeek : 'dddd [pukul] LT',
+ lastDay : '[Kelmarin pukul] LT',
+ lastWeek : 'dddd [lepas pukul] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'dalam %s',
+ past : '%s yang lepas',
+ s : 'beberapa saat',
+ m : 'seminit',
+ mm : '%d minit',
+ h : 'sejam',
+ hh : '%d jam',
+ d : 'sehari',
+ dd : '%d hari',
+ M : 'sebulan',
+ MM : '%d bulan',
+ y : 'setahun',
+ yy : '%d tahun'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return msMy;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ms.js b/www/wiki/resources/lib/moment/locale/ms.js
new file mode 100644
index 00000000..4d4afff5
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ms.js
@@ -0,0 +1,82 @@
+//! moment.js locale configuration
+//! locale : Malay [ms]
+//! author : Weldan Jamili : https://github.com/weldan
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ms = moment.defineLocale('ms', {
+ months : 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.split('_'),
+ monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ogs_Sep_Okt_Nov_Dis'.split('_'),
+ weekdays : 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
+ weekdaysShort : 'Ahd_Isn_Sel_Rab_Kha_Jum_Sab'.split('_'),
+ weekdaysMin : 'Ah_Is_Sl_Rb_Km_Jm_Sb'.split('_'),
+ longDateFormat : {
+ LT : 'HH.mm',
+ LTS : 'HH.mm.ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY [pukul] HH.mm',
+ LLLL : 'dddd, D MMMM YYYY [pukul] HH.mm'
+ },
+ meridiemParse: /pagi|tengahari|petang|malam/,
+ meridiemHour: function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'pagi') {
+ return hour;
+ } else if (meridiem === 'tengahari') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === 'petang' || meridiem === 'malam') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 11) {
+ return 'pagi';
+ } else if (hours < 15) {
+ return 'tengahari';
+ } else if (hours < 19) {
+ return 'petang';
+ } else {
+ return 'malam';
+ }
+ },
+ calendar : {
+ sameDay : '[Hari ini pukul] LT',
+ nextDay : '[Esok pukul] LT',
+ nextWeek : 'dddd [pukul] LT',
+ lastDay : '[Kelmarin pukul] LT',
+ lastWeek : 'dddd [lepas pukul] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'dalam %s',
+ past : '%s yang lepas',
+ s : 'beberapa saat',
+ m : 'seminit',
+ mm : '%d minit',
+ h : 'sejam',
+ hh : '%d jam',
+ d : 'sehari',
+ dd : '%d hari',
+ M : 'sebulan',
+ MM : '%d bulan',
+ y : 'setahun',
+ yy : '%d tahun'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ms;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/my.js b/www/wiki/resources/lib/moment/locale/my.js
new file mode 100644
index 00000000..32d67e2b
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/my.js
@@ -0,0 +1,96 @@
+//! moment.js locale configuration
+//! locale : Burmese [my]
+//! author : Squar team, mysquar.com
+//! author : David Rossellat : https://github.com/gholadr
+//! author : Tin Aung Lin : https://github.com/thanyawzinmin
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '၁',
+ '2': '၂',
+ '3': '၃',
+ '4': '၄',
+ '5': '၅',
+ '6': '၆',
+ '7': '၇',
+ '8': '၈',
+ '9': '၉',
+ '0': '၀'
+};
+var numberMap = {
+ '၁': '1',
+ '၂': '2',
+ '၃': '3',
+ '၄': '4',
+ '၅': '5',
+ '၆': '6',
+ '၇': '7',
+ '၈': '8',
+ '၉': '9',
+ '၀': '0'
+};
+
+var my = moment.defineLocale('my', {
+ months: 'ဇန်နဝါရီ_ဖေဖော်ဝါရီ_မတ်_ဧပြီ_မေ_ဇွန်_ဇူလိုင်_သြဂုတ်_စက်တင်ဘာ_အောက်တိုဘာ_နိုဝင်ဘာ_ဒီဇင်ဘာ'.split('_'),
+ monthsShort: 'ဇန်_ဖေ_မတ်_ပြီ_မေ_ဇွန်_လိုင်_သြ_စက်_အောက်_နို_ဒီ'.split('_'),
+ weekdays: 'တနင်္ဂနွေ_တနင်္လာ_အင်္ဂါ_ဗုဒ္ဓဟူး_ကြာသပတေး_သောကြာ_စနေ'.split('_'),
+ weekdaysShort: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
+ weekdaysMin: 'နွေ_လာ_ဂါ_ဟူး_ကြာ_သော_နေ'.split('_'),
+
+ longDateFormat: {
+ LT: 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY HH:mm',
+ LLLL: 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar: {
+ sameDay: '[ယနေ.] LT [မှာ]',
+ nextDay: '[မနက်ဖြန်] LT [မှာ]',
+ nextWeek: 'dddd LT [မှာ]',
+ lastDay: '[မနေ.က] LT [မှာ]',
+ lastWeek: '[ပြီးခဲ့သော] dddd LT [မှာ]',
+ sameElse: 'L'
+ },
+ relativeTime: {
+ future: 'လာမည့် %s မှာ',
+ past: 'လွန်ခဲ့သော %s က',
+ s: 'စက္ကန်.အနည်းငယ်',
+ m: 'တစ်မိနစ်',
+ mm: '%d မိနစ်',
+ h: 'တစ်နာရီ',
+ hh: '%d နာရီ',
+ d: 'တစ်ရက်',
+ dd: '%d ရက်',
+ M: 'တစ်လ',
+ MM: '%d လ',
+ y: 'တစ်နှစ်',
+ yy: '%d နှစ်'
+ },
+ preparse: function (string) {
+ return string.replace(/[၁၂၃၄၅၆၇၈၉၀]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ week: {
+ dow: 1, // Monday is the first day of the week.
+ doy: 4 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return my;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/nb.js b/www/wiki/resources/lib/moment/locale/nb.js
new file mode 100644
index 00000000..2cfe374f
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/nb.js
@@ -0,0 +1,63 @@
+//! moment.js locale configuration
+//! locale : Norwegian Bokmål [nb]
+//! authors : Espen Hovlandsdal : https://github.com/rexxars
+//! Sigurd Gartmann : https://github.com/sigurdga
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var nb = moment.defineLocale('nb', {
+ months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+ monthsShort : 'jan._feb._mars_april_mai_juni_juli_aug._sep._okt._nov._des.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'søndag_mandag_tirsdag_onsdag_torsdag_fredag_lørdag'.split('_'),
+ weekdaysShort : 'sø._ma._ti._on._to._fr._lø.'.split('_'),
+ weekdaysMin : 'sø_ma_ti_on_to_fr_lø'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY [kl.] HH:mm',
+ LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
+ },
+ calendar : {
+ sameDay: '[i dag kl.] LT',
+ nextDay: '[i morgen kl.] LT',
+ nextWeek: 'dddd [kl.] LT',
+ lastDay: '[i går kl.] LT',
+ lastWeek: '[forrige] dddd [kl.] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'om %s',
+ past : '%s siden',
+ s : 'noen sekunder',
+ m : 'ett minutt',
+ mm : '%d minutter',
+ h : 'en time',
+ hh : '%d timer',
+ d : 'en dag',
+ dd : '%d dager',
+ M : 'en måned',
+ MM : '%d måneder',
+ y : 'ett år',
+ yy : '%d år'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return nb;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ne.js b/www/wiki/resources/lib/moment/locale/ne.js
new file mode 100644
index 00000000..a35947a9
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ne.js
@@ -0,0 +1,123 @@
+//! moment.js locale configuration
+//! locale : Nepalese [ne]
+//! author : suvash : https://github.com/suvash
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '१',
+ '2': '२',
+ '3': '३',
+ '4': '४',
+ '5': '५',
+ '6': '६',
+ '7': '७',
+ '8': '८',
+ '9': '९',
+ '0': '०'
+};
+var numberMap = {
+ '१': '1',
+ '२': '2',
+ '३': '3',
+ '४': '4',
+ '५': '5',
+ '६': '6',
+ '७': '7',
+ '८': '8',
+ '९': '9',
+ '०': '0'
+};
+
+var ne = moment.defineLocale('ne', {
+ months : 'जनवरी_फेब्रुवरी_मार्च_अप्रिल_मई_जुन_जुलाई_अगष्ट_सेप्टेम्बर_अक्टोबर_नोभेम्बर_डिसेम्बर'.split('_'),
+ monthsShort : 'जन._फेब्रु._मार्च_अप्रि._मई_जुन_जुलाई._अग._सेप्ट._अक्टो._नोभे._डिसे.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'आइतबार_सोमबार_मङ्गलबार_बुधबार_बिहिबार_शुक्रबार_शनिबार'.split('_'),
+ weekdaysShort : 'आइत._सोम._मङ्गल._बुध._बिहि._शुक्र._शनि.'.split('_'),
+ weekdaysMin : 'आ._सो._मं._बु._बि._शु._श.'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'Aको h:mm बजे',
+ LTS : 'Aको h:mm:ss बजे',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, Aको h:mm बजे',
+ LLLL : 'dddd, D MMMM YYYY, Aको h:mm बजे'
+ },
+ preparse: function (string) {
+ return string.replace(/[१२३४५६७८९०]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ meridiemParse: /राति|बिहान|दिउँसो|साँझ/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'राति') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'बिहान') {
+ return hour;
+ } else if (meridiem === 'दिउँसो') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'साँझ') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 3) {
+ return 'राति';
+ } else if (hour < 12) {
+ return 'बिहान';
+ } else if (hour < 16) {
+ return 'दिउँसो';
+ } else if (hour < 20) {
+ return 'साँझ';
+ } else {
+ return 'राति';
+ }
+ },
+ calendar : {
+ sameDay : '[आज] LT',
+ nextDay : '[भोलि] LT',
+ nextWeek : '[आउँदो] dddd[,] LT',
+ lastDay : '[हिजो] LT',
+ lastWeek : '[गएको] dddd[,] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%sमा',
+ past : '%s अगाडि',
+ s : 'केही क्षण',
+ m : 'एक मिनेट',
+ mm : '%d मिनेट',
+ h : 'एक घण्टा',
+ hh : '%d घण्टा',
+ d : 'एक दिन',
+ dd : '%d दिन',
+ M : 'एक महिना',
+ MM : '%d महिना',
+ y : 'एक बर्ष',
+ yy : '%d बर्ष'
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ne;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/nl.js b/www/wiki/resources/lib/moment/locale/nl.js
new file mode 100644
index 00000000..12c99946
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/nl.js
@@ -0,0 +1,88 @@
+//! moment.js locale configuration
+//! locale : Dutch [nl]
+//! author : Joris Röling : https://github.com/jorisroling
+//! author : Jacob Middag : https://github.com/middagj
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var monthsShortWithDots = 'jan._feb._mrt._apr._mei_jun._jul._aug._sep._okt._nov._dec.'.split('_');
+var monthsShortWithoutDots = 'jan_feb_mrt_apr_mei_jun_jul_aug_sep_okt_nov_dec'.split('_');
+
+var monthsParse = [/^jan/i, /^feb/i, /^maart|mrt.?$/i, /^apr/i, /^mei$/i, /^jun[i.]?$/i, /^jul[i.]?$/i, /^aug/i, /^sep/i, /^okt/i, /^nov/i, /^dec/i];
+var monthsRegex = /^(januari|februari|maart|april|mei|april|ju[nl]i|augustus|september|oktober|november|december|jan\.?|feb\.?|mrt\.?|apr\.?|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i;
+
+var nl = moment.defineLocale('nl', {
+ months : 'januari_februari_maart_april_mei_juni_juli_augustus_september_oktober_november_december'.split('_'),
+ monthsShort : function (m, format) {
+ if (!m) {
+ return monthsShortWithDots;
+ } else if (/-MMM-/.test(format)) {
+ return monthsShortWithoutDots[m.month()];
+ } else {
+ return monthsShortWithDots[m.month()];
+ }
+ },
+
+ monthsRegex: monthsRegex,
+ monthsShortRegex: monthsRegex,
+ monthsStrictRegex: /^(januari|februari|maart|mei|ju[nl]i|april|augustus|september|oktober|november|december)/i,
+ monthsShortStrictRegex: /^(jan\.?|feb\.?|mrt\.?|apr\.?|mei|ju[nl]\.?|aug\.?|sep\.?|okt\.?|nov\.?|dec\.?)/i,
+
+ monthsParse : monthsParse,
+ longMonthsParse : monthsParse,
+ shortMonthsParse : monthsParse,
+
+ weekdays : 'zondag_maandag_dinsdag_woensdag_donderdag_vrijdag_zaterdag'.split('_'),
+ weekdaysShort : 'zo._ma._di._wo._do._vr._za.'.split('_'),
+ weekdaysMin : 'zo_ma_di_wo_do_vr_za'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD-MM-YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[vandaag om] LT',
+ nextDay: '[morgen om] LT',
+ nextWeek: 'dddd [om] LT',
+ lastDay: '[gisteren om] LT',
+ lastWeek: '[afgelopen] dddd [om] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'over %s',
+ past : '%s geleden',
+ s : 'een paar seconden',
+ m : 'één minuut',
+ mm : '%d minuten',
+ h : 'één uur',
+ hh : '%d uur',
+ d : 'één dag',
+ dd : '%d dagen',
+ M : 'één maand',
+ MM : '%d maanden',
+ y : 'één jaar',
+ yy : '%d jaar'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(ste|de)/,
+ ordinal : function (number) {
+ return number + ((number === 1 || number === 8 || number >= 20) ? 'ste' : 'de');
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return nl;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/nn.js b/www/wiki/resources/lib/moment/locale/nn.js
new file mode 100644
index 00000000..90dda8c6
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/nn.js
@@ -0,0 +1,60 @@
+//! moment.js locale configuration
+//! locale : Nynorsk [nn]
+//! author : https://github.com/mechuwind
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var nn = moment.defineLocale('nn', {
+ months : 'januar_februar_mars_april_mai_juni_juli_august_september_oktober_november_desember'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_mai_jun_jul_aug_sep_okt_nov_des'.split('_'),
+ weekdays : 'sundag_måndag_tysdag_onsdag_torsdag_fredag_laurdag'.split('_'),
+ weekdaysShort : 'sun_mån_tys_ons_tor_fre_lau'.split('_'),
+ weekdaysMin : 'su_må_ty_on_to_fr_lø'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY [kl.] H:mm',
+ LLLL : 'dddd D. MMMM YYYY [kl.] HH:mm'
+ },
+ calendar : {
+ sameDay: '[I dag klokka] LT',
+ nextDay: '[I morgon klokka] LT',
+ nextWeek: 'dddd [klokka] LT',
+ lastDay: '[I går klokka] LT',
+ lastWeek: '[Føregåande] dddd [klokka] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'om %s',
+ past : '%s sidan',
+ s : 'nokre sekund',
+ m : 'eit minutt',
+ mm : '%d minutt',
+ h : 'ein time',
+ hh : '%d timar',
+ d : 'ein dag',
+ dd : '%d dagar',
+ M : 'ein månad',
+ MM : '%d månader',
+ y : 'eit år',
+ yy : '%d år'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return nn;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/pa-in.js b/www/wiki/resources/lib/moment/locale/pa-in.js
new file mode 100644
index 00000000..6dec8d17
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/pa-in.js
@@ -0,0 +1,124 @@
+//! moment.js locale configuration
+//! locale : Punjabi (India) [pa-in]
+//! author : Harpreet Singh : https://github.com/harpreetkhalsagtbit
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '੧',
+ '2': '੨',
+ '3': '੩',
+ '4': '੪',
+ '5': '੫',
+ '6': '੬',
+ '7': '੭',
+ '8': '੮',
+ '9': '੯',
+ '0': '੦'
+};
+var numberMap = {
+ '੧': '1',
+ '੨': '2',
+ '੩': '3',
+ '੪': '4',
+ '੫': '5',
+ '੬': '6',
+ '੭': '7',
+ '੮': '8',
+ '੯': '9',
+ '੦': '0'
+};
+
+var paIn = moment.defineLocale('pa-in', {
+ // There are months name as per Nanakshahi Calender but they are not used as rigidly in modern Punjabi.
+ months : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'),
+ monthsShort : 'ਜਨਵਰੀ_ਫ਼ਰਵਰੀ_ਮਾਰਚ_ਅਪ੍ਰੈਲ_ਮਈ_ਜੂਨ_ਜੁਲਾਈ_ਅਗਸਤ_ਸਤੰਬਰ_ਅਕਤੂਬਰ_ਨਵੰਬਰ_ਦਸੰਬਰ'.split('_'),
+ weekdays : 'ਐਤਵਾਰ_ਸੋਮਵਾਰ_ਮੰਗਲਵਾਰ_ਬੁਧਵਾਰ_ਵੀਰਵਾਰ_ਸ਼ੁੱਕਰਵਾਰ_ਸ਼ਨੀਚਰਵਾਰ'.split('_'),
+ weekdaysShort : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
+ weekdaysMin : 'ਐਤ_ਸੋਮ_ਮੰਗਲ_ਬੁਧ_ਵੀਰ_ਸ਼ੁਕਰ_ਸ਼ਨੀ'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm ਵਜੇ',
+ LTS : 'A h:mm:ss ਵਜੇ',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm ਵਜੇ',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm ਵਜੇ'
+ },
+ calendar : {
+ sameDay : '[ਅਜ] LT',
+ nextDay : '[ਕਲ] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[ਕਲ] LT',
+ lastWeek : '[ਪਿਛਲੇ] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s ਵਿੱਚ',
+ past : '%s ਪਿਛਲੇ',
+ s : 'ਕੁਝ ਸਕਿੰਟ',
+ m : 'ਇਕ ਮਿੰਟ',
+ mm : '%d ਮਿੰਟ',
+ h : 'ਇੱਕ ਘੰਟਾ',
+ hh : '%d ਘੰਟੇ',
+ d : 'ਇੱਕ ਦਿਨ',
+ dd : '%d ਦਿਨ',
+ M : 'ਇੱਕ ਮਹੀਨਾ',
+ MM : '%d ਮਹੀਨੇ',
+ y : 'ਇੱਕ ਸਾਲ',
+ yy : '%d ਸਾਲ'
+ },
+ preparse: function (string) {
+ return string.replace(/[੧੨੩੪੫੬੭੮੯੦]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ // Punjabi notation for meridiems are quite fuzzy in practice. While there exists
+ // a rigid notion of a 'Pahar' it is not used as rigidly in modern Punjabi.
+ meridiemParse: /ਰਾਤ|ਸਵੇਰ|ਦੁਪਹਿਰ|ਸ਼ਾਮ/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'ਰਾਤ') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'ਸਵੇਰ') {
+ return hour;
+ } else if (meridiem === 'ਦੁਪਹਿਰ') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'ਸ਼ਾਮ') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'ਰਾਤ';
+ } else if (hour < 10) {
+ return 'ਸਵੇਰ';
+ } else if (hour < 17) {
+ return 'ਦੁਪਹਿਰ';
+ } else if (hour < 20) {
+ return 'ਸ਼ਾਮ';
+ } else {
+ return 'ਰਾਤ';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return paIn;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/pl.js b/www/wiki/resources/lib/moment/locale/pl.js
new file mode 100644
index 00000000..db466b6b
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/pl.js
@@ -0,0 +1,124 @@
+//! moment.js locale configuration
+//! locale : Polish [pl]
+//! author : Rafal Hirsz : https://github.com/evoL
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var monthsNominative = 'styczeń_luty_marzec_kwiecień_maj_czerwiec_lipiec_sierpień_wrzesień_październik_listopad_grudzień'.split('_');
+var monthsSubjective = 'stycznia_lutego_marca_kwietnia_maja_czerwca_lipca_sierpnia_września_października_listopada_grudnia'.split('_');
+function plural(n) {
+ return (n % 10 < 5) && (n % 10 > 1) && ((~~(n / 10) % 10) !== 1);
+}
+function translate(number, withoutSuffix, key) {
+ var result = number + ' ';
+ switch (key) {
+ case 'm':
+ return withoutSuffix ? 'minuta' : 'minutę';
+ case 'mm':
+ return result + (plural(number) ? 'minuty' : 'minut');
+ case 'h':
+ return withoutSuffix ? 'godzina' : 'godzinę';
+ case 'hh':
+ return result + (plural(number) ? 'godziny' : 'godzin');
+ case 'MM':
+ return result + (plural(number) ? 'miesiące' : 'miesięcy');
+ case 'yy':
+ return result + (plural(number) ? 'lata' : 'lat');
+ }
+}
+
+var pl = moment.defineLocale('pl', {
+ months : function (momentToFormat, format) {
+ if (!momentToFormat) {
+ return monthsNominative;
+ } else if (format === '') {
+ // Hack: if format empty we know this is used to generate
+ // RegExp by moment. Give then back both valid forms of months
+ // in RegExp ready format.
+ return '(' + monthsSubjective[momentToFormat.month()] + '|' + monthsNominative[momentToFormat.month()] + ')';
+ } else if (/D MMMM/.test(format)) {
+ return monthsSubjective[momentToFormat.month()];
+ } else {
+ return monthsNominative[momentToFormat.month()];
+ }
+ },
+ monthsShort : 'sty_lut_mar_kwi_maj_cze_lip_sie_wrz_paź_lis_gru'.split('_'),
+ weekdays : 'niedziela_poniedziałek_wtorek_środa_czwartek_piątek_sobota'.split('_'),
+ weekdaysShort : 'ndz_pon_wt_śr_czw_pt_sob'.split('_'),
+ weekdaysMin : 'Nd_Pn_Wt_Śr_Cz_Pt_So'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Dziś o] LT',
+ nextDay: '[Jutro o] LT',
+ nextWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[W niedzielę o] LT';
+
+ case 2:
+ return '[We wtorek o] LT';
+
+ case 3:
+ return '[W środę o] LT';
+
+ case 6:
+ return '[W sobotę o] LT';
+
+ default:
+ return '[W] dddd [o] LT';
+ }
+ },
+ lastDay: '[Wczoraj o] LT',
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[W zeszłą niedzielę o] LT';
+ case 3:
+ return '[W zeszłą środę o] LT';
+ case 6:
+ return '[W zeszłą sobotę o] LT';
+ default:
+ return '[W zeszły] dddd [o] LT';
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : '%s temu',
+ s : 'kilka sekund',
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : '1 dzień',
+ dd : '%d dni',
+ M : 'miesiąc',
+ MM : translate,
+ y : 'rok',
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return pl;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/pt-br.js b/www/wiki/resources/lib/moment/locale/pt-br.js
new file mode 100644
index 00000000..478b2071
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/pt-br.js
@@ -0,0 +1,62 @@
+//! moment.js locale configuration
+//! locale : Portuguese (Brazil) [pt-br]
+//! author : Caio Ribeiro Pereira : https://github.com/caio-ribeiro-pereira
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var ptBr = moment.defineLocale('pt-br', {
+ months : 'janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro'.split('_'),
+ monthsShort : 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_'),
+ weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'),
+ weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
+ weekdaysMin : 'Do_2ª_3ª_4ª_5ª_6ª_Sá'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D [de] MMMM [de] YYYY',
+ LLL : 'D [de] MMMM [de] YYYY [às] HH:mm',
+ LLLL : 'dddd, D [de] MMMM [de] YYYY [às] HH:mm'
+ },
+ calendar : {
+ sameDay: '[Hoje às] LT',
+ nextDay: '[Amanhã às] LT',
+ nextWeek: 'dddd [às] LT',
+ lastDay: '[Ontem às] LT',
+ lastWeek: function () {
+ return (this.day() === 0 || this.day() === 6) ?
+ '[Último] dddd [às] LT' : // Saturday + Sunday
+ '[Última] dddd [às] LT'; // Monday - Friday
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'em %s',
+ past : '%s atrás',
+ s : 'poucos segundos',
+ ss : '%d segundos',
+ m : 'um minuto',
+ mm : '%d minutos',
+ h : 'uma hora',
+ hh : '%d horas',
+ d : 'um dia',
+ dd : '%d dias',
+ M : 'um mês',
+ MM : '%d meses',
+ y : 'um ano',
+ yy : '%d anos'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}º/,
+ ordinal : '%dº'
+});
+
+return ptBr;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/pt.js b/www/wiki/resources/lib/moment/locale/pt.js
new file mode 100644
index 00000000..3d8ee7e2
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/pt.js
@@ -0,0 +1,65 @@
+//! moment.js locale configuration
+//! locale : Portuguese [pt]
+//! author : Jefferson : https://github.com/jalex79
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var pt = moment.defineLocale('pt', {
+ months : 'janeiro_fevereiro_março_abril_maio_junho_julho_agosto_setembro_outubro_novembro_dezembro'.split('_'),
+ monthsShort : 'jan_fev_mar_abr_mai_jun_jul_ago_set_out_nov_dez'.split('_'),
+ weekdays : 'Domingo_Segunda-feira_Terça-feira_Quarta-feira_Quinta-feira_Sexta-feira_Sábado'.split('_'),
+ weekdaysShort : 'Dom_Seg_Ter_Qua_Qui_Sex_Sáb'.split('_'),
+ weekdaysMin : 'Do_2ª_3ª_4ª_5ª_6ª_Sá'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D [de] MMMM [de] YYYY',
+ LLL : 'D [de] MMMM [de] YYYY HH:mm',
+ LLLL : 'dddd, D [de] MMMM [de] YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Hoje às] LT',
+ nextDay: '[Amanhã às] LT',
+ nextWeek: 'dddd [às] LT',
+ lastDay: '[Ontem às] LT',
+ lastWeek: function () {
+ return (this.day() === 0 || this.day() === 6) ?
+ '[Último] dddd [às] LT' : // Saturday + Sunday
+ '[Última] dddd [às] LT'; // Monday - Friday
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'em %s',
+ past : 'há %s',
+ s : 'segundos',
+ m : 'um minuto',
+ mm : '%d minutos',
+ h : 'uma hora',
+ hh : '%d horas',
+ d : 'um dia',
+ dd : '%d dias',
+ M : 'um mês',
+ MM : '%d meses',
+ y : 'um ano',
+ yy : '%d anos'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}º/,
+ ordinal : '%dº',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return pt;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ro.js b/www/wiki/resources/lib/moment/locale/ro.js
new file mode 100644
index 00000000..8a0cd750
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ro.js
@@ -0,0 +1,75 @@
+//! moment.js locale configuration
+//! locale : Romanian [ro]
+//! author : Vlad Gurdiga : https://github.com/gurdiga
+//! author : Valentin Agachi : https://github.com/avaly
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function relativeTimeWithPlural(number, withoutSuffix, key) {
+ var format = {
+ 'mm': 'minute',
+ 'hh': 'ore',
+ 'dd': 'zile',
+ 'MM': 'luni',
+ 'yy': 'ani'
+ },
+ separator = ' ';
+ if (number % 100 >= 20 || (number >= 100 && number % 100 === 0)) {
+ separator = ' de ';
+ }
+ return number + separator + format[key];
+}
+
+var ro = moment.defineLocale('ro', {
+ months : 'ianuarie_februarie_martie_aprilie_mai_iunie_iulie_august_septembrie_octombrie_noiembrie_decembrie'.split('_'),
+ monthsShort : 'ian._febr._mart._apr._mai_iun._iul._aug._sept._oct._nov._dec.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'duminică_luni_marți_miercuri_joi_vineri_sâmbătă'.split('_'),
+ weekdaysShort : 'Dum_Lun_Mar_Mie_Joi_Vin_Sâm'.split('_'),
+ weekdaysMin : 'Du_Lu_Ma_Mi_Jo_Vi_Sâ'.split('_'),
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY H:mm',
+ LLLL : 'dddd, D MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay: '[azi la] LT',
+ nextDay: '[mâine la] LT',
+ nextWeek: 'dddd [la] LT',
+ lastDay: '[ieri la] LT',
+ lastWeek: '[fosta] dddd [la] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'peste %s',
+ past : '%s în urmă',
+ s : 'câteva secunde',
+ m : 'un minut',
+ mm : relativeTimeWithPlural,
+ h : 'o oră',
+ hh : relativeTimeWithPlural,
+ d : 'o zi',
+ dd : relativeTimeWithPlural,
+ M : 'o lună',
+ MM : relativeTimeWithPlural,
+ y : 'un an',
+ yy : relativeTimeWithPlural
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ro;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ru.js b/www/wiki/resources/lib/moment/locale/ru.js
new file mode 100644
index 00000000..356a0fa8
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ru.js
@@ -0,0 +1,183 @@
+//! moment.js locale configuration
+//! locale : Russian [ru]
+//! author : Viktorminator : https://github.com/Viktorminator
+//! Author : Menelion Elensúle : https://github.com/Oire
+//! author : Коренберг Марк : https://github.com/socketpair
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function plural(word, num) {
+ var forms = word.split('_');
+ return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+}
+function relativeTimeWithPlural(number, withoutSuffix, key) {
+ var format = {
+ 'mm': withoutSuffix ? 'минута_минуты_минут' : 'минуту_минуты_минут',
+ 'hh': 'час_часа_часов',
+ 'dd': 'день_дня_дней',
+ 'MM': 'месяц_месяца_месяцев',
+ 'yy': 'год_года_лет'
+ };
+ if (key === 'm') {
+ return withoutSuffix ? 'минута' : 'минуту';
+ }
+ else {
+ return number + ' ' + plural(format[key], +number);
+ }
+}
+var monthsParse = [/^янв/i, /^фев/i, /^мар/i, /^апр/i, /^ма[йя]/i, /^июн/i, /^июл/i, /^авг/i, /^сен/i, /^окт/i, /^ноя/i, /^дек/i];
+
+// http://new.gramota.ru/spravka/rules/139-prop : § 103
+// Сокращения месяцев: http://new.gramota.ru/spravka/buro/search-answer?s=242637
+// CLDR data: http://www.unicode.org/cldr/charts/28/summary/ru.html#1753
+var ru = moment.defineLocale('ru', {
+ months : {
+ format: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split('_'),
+ standalone: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split('_')
+ },
+ monthsShort : {
+ // по CLDR именно "июл." и "июн.", но какой смысл менять букву на точку ?
+ format: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split('_'),
+ standalone: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split('_')
+ },
+ weekdays : {
+ standalone: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
+ format: 'воскресенье_понедельник_вторник_среду_четверг_пятницу_субботу'.split('_'),
+ isFormat: /\[ ?[Вв] ?(?:прошлую|следующую|эту)? ?\] ?dddd/
+ },
+ weekdaysShort : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
+ weekdaysMin : 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
+ monthsParse : monthsParse,
+ longMonthsParse : monthsParse,
+ shortMonthsParse : monthsParse,
+
+ // полные названия с падежами, по три буквы, для некоторых, по 4 буквы, сокращения с точкой и без точки
+ monthsRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,
+
+ // копия предыдущего
+ monthsShortRegex: /^(январ[ья]|янв\.?|феврал[ья]|февр?\.?|марта?|мар\.?|апрел[ья]|апр\.?|ма[йя]|июн[ья]|июн\.?|июл[ья]|июл\.?|августа?|авг\.?|сентябр[ья]|сент?\.?|октябр[ья]|окт\.?|ноябр[ья]|нояб?\.?|декабр[ья]|дек\.?)/i,
+
+ // полные названия с падежами
+ monthsStrictRegex: /^(январ[яь]|феврал[яь]|марта?|апрел[яь]|ма[яй]|июн[яь]|июл[яь]|августа?|сентябр[яь]|октябр[яь]|ноябр[яь]|декабр[яь])/i,
+
+ // Выражение, которое соотвествует только сокращённым формам
+ monthsShortStrictRegex: /^(янв\.|февр?\.|мар[т.]|апр\.|ма[яй]|июн[ья.]|июл[ья.]|авг\.|сент?\.|окт\.|нояб?\.|дек\.)/i,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY г.',
+ LLL : 'D MMMM YYYY г., HH:mm',
+ LLLL : 'dddd, D MMMM YYYY г., HH:mm'
+ },
+ calendar : {
+ sameDay: '[Сегодня в] LT',
+ nextDay: '[Завтра в] LT',
+ lastDay: '[Вчера в] LT',
+ nextWeek: function (now) {
+ if (now.week() !== this.week()) {
+ switch (this.day()) {
+ case 0:
+ return '[В следующее] dddd [в] LT';
+ case 1:
+ case 2:
+ case 4:
+ return '[В следующий] dddd [в] LT';
+ case 3:
+ case 5:
+ case 6:
+ return '[В следующую] dddd [в] LT';
+ }
+ } else {
+ if (this.day() === 2) {
+ return '[Во] dddd [в] LT';
+ } else {
+ return '[В] dddd [в] LT';
+ }
+ }
+ },
+ lastWeek: function (now) {
+ if (now.week() !== this.week()) {
+ switch (this.day()) {
+ case 0:
+ return '[В прошлое] dddd [в] LT';
+ case 1:
+ case 2:
+ case 4:
+ return '[В прошлый] dddd [в] LT';
+ case 3:
+ case 5:
+ case 6:
+ return '[В прошлую] dddd [в] LT';
+ }
+ } else {
+ if (this.day() === 2) {
+ return '[Во] dddd [в] LT';
+ } else {
+ return '[В] dddd [в] LT';
+ }
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'через %s',
+ past : '%s назад',
+ s : 'несколько секунд',
+ m : relativeTimeWithPlural,
+ mm : relativeTimeWithPlural,
+ h : 'час',
+ hh : relativeTimeWithPlural,
+ d : 'день',
+ dd : relativeTimeWithPlural,
+ M : 'месяц',
+ MM : relativeTimeWithPlural,
+ y : 'год',
+ yy : relativeTimeWithPlural
+ },
+ meridiemParse: /ночи|утра|дня|вечера/i,
+ isPM : function (input) {
+ return /^(дня|вечера)$/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'ночи';
+ } else if (hour < 12) {
+ return 'утра';
+ } else if (hour < 17) {
+ return 'дня';
+ } else {
+ return 'вечера';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(й|го|я)/,
+ ordinal: function (number, period) {
+ switch (period) {
+ case 'M':
+ case 'd':
+ case 'DDD':
+ return number + '-й';
+ case 'D':
+ return number + '-го';
+ case 'w':
+ case 'W':
+ return number + '-я';
+ default:
+ return number;
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return ru;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/sd.js b/www/wiki/resources/lib/moment/locale/sd.js
new file mode 100644
index 00000000..0fcf7e10
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/sd.js
@@ -0,0 +1,98 @@
+//! moment.js locale configuration
+//! locale : Sindhi [sd]
+//! author : Narain Sagar : https://github.com/narainsagar
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = [
+ 'جنوري',
+ 'فيبروري',
+ 'مارچ',
+ 'اپريل',
+ 'مئي',
+ 'جون',
+ 'جولاءِ',
+ 'آگسٽ',
+ 'سيپٽمبر',
+ 'آڪٽوبر',
+ 'نومبر',
+ 'ڊسمبر'
+];
+var days = [
+ 'آچر',
+ 'سومر',
+ 'اڱارو',
+ 'اربع',
+ 'خميس',
+ 'جمع',
+ 'ڇنڇر'
+];
+
+var sd = moment.defineLocale('sd', {
+ months : months,
+ monthsShort : months,
+ weekdays : days,
+ weekdaysShort : days,
+ weekdaysMin : days,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd، D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /صبح|شام/,
+ isPM : function (input) {
+ return 'شام' === input;
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'صبح';
+ }
+ return 'شام';
+ },
+ calendar : {
+ sameDay : '[اڄ] LT',
+ nextDay : '[سڀاڻي] LT',
+ nextWeek : 'dddd [اڳين هفتي تي] LT',
+ lastDay : '[ڪالهه] LT',
+ lastWeek : '[گزريل هفتي] dddd [تي] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s پوء',
+ past : '%s اڳ',
+ s : 'چند سيڪنڊ',
+ m : 'هڪ منٽ',
+ mm : '%d منٽ',
+ h : 'هڪ ڪلاڪ',
+ hh : '%d ڪلاڪ',
+ d : 'هڪ ڏينهن',
+ dd : '%d ڏينهن',
+ M : 'هڪ مهينو',
+ MM : '%d مهينا',
+ y : 'هڪ سال',
+ yy : '%d سال'
+ },
+ preparse: function (string) {
+ return string.replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/,/g, '،');
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return sd;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/se.js b/www/wiki/resources/lib/moment/locale/se.js
new file mode 100644
index 00000000..d44d0df2
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/se.js
@@ -0,0 +1,61 @@
+//! moment.js locale configuration
+//! locale : Northern Sami [se]
+//! authors : Bård Rolstad Henriksen : https://github.com/karamell
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+
+var se = moment.defineLocale('se', {
+ months : 'ođđajagemánnu_guovvamánnu_njukčamánnu_cuoŋománnu_miessemánnu_geassemánnu_suoidnemánnu_borgemánnu_čakčamánnu_golggotmánnu_skábmamánnu_juovlamánnu'.split('_'),
+ monthsShort : 'ođđj_guov_njuk_cuo_mies_geas_suoi_borg_čakč_golg_skáb_juov'.split('_'),
+ weekdays : 'sotnabeaivi_vuossárga_maŋŋebárga_gaskavahkku_duorastat_bearjadat_lávvardat'.split('_'),
+ weekdaysShort : 'sotn_vuos_maŋ_gask_duor_bear_láv'.split('_'),
+ weekdaysMin : 's_v_m_g_d_b_L'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'MMMM D. [b.] YYYY',
+ LLL : 'MMMM D. [b.] YYYY [ti.] HH:mm',
+ LLLL : 'dddd, MMMM D. [b.] YYYY [ti.] HH:mm'
+ },
+ calendar : {
+ sameDay: '[otne ti] LT',
+ nextDay: '[ihttin ti] LT',
+ nextWeek: 'dddd [ti] LT',
+ lastDay: '[ikte ti] LT',
+ lastWeek: '[ovddit] dddd [ti] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : '%s geažes',
+ past : 'maŋit %s',
+ s : 'moadde sekunddat',
+ m : 'okta minuhta',
+ mm : '%d minuhtat',
+ h : 'okta diimmu',
+ hh : '%d diimmut',
+ d : 'okta beaivi',
+ dd : '%d beaivvit',
+ M : 'okta mánnu',
+ MM : '%d mánut',
+ y : 'okta jahki',
+ yy : '%d jagit'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return se;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/si.js b/www/wiki/resources/lib/moment/locale/si.js
new file mode 100644
index 00000000..f5c124ee
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/si.js
@@ -0,0 +1,71 @@
+//! moment.js locale configuration
+//! locale : Sinhalese [si]
+//! author : Sampath Sitinamaluwa : https://github.com/sampathsris
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+/*jshint -W100*/
+var si = moment.defineLocale('si', {
+ months : 'ජනවාරි_පෙබරවාරි_මාර්තු_අප්‍රේල්_මැයි_ජූනි_ජූලි_අගෝස්තු_සැප්තැම්බර්_ඔක්තෝබර්_නොවැම්බර්_දෙසැම්බර්'.split('_'),
+ monthsShort : 'ජන_පෙබ_මාර්_අප්_මැයි_ජූනි_ජූලි_අගෝ_සැප්_ඔක්_නොවැ_දෙසැ'.split('_'),
+ weekdays : 'ඉරිදා_සඳුදා_අඟහරුවාදා_බදාදා_බ්‍රහස්පතින්දා_සිකුරාදා_සෙනසුරාදා'.split('_'),
+ weekdaysShort : 'ඉරි_සඳු_අඟ_බදා_බ්‍රහ_සිකු_සෙන'.split('_'),
+ weekdaysMin : 'ඉ_ස_අ_බ_බ්‍ර_සි_සෙ'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'a h:mm',
+ LTS : 'a h:mm:ss',
+ L : 'YYYY/MM/DD',
+ LL : 'YYYY MMMM D',
+ LLL : 'YYYY MMMM D, a h:mm',
+ LLLL : 'YYYY MMMM D [වැනි] dddd, a h:mm:ss'
+ },
+ calendar : {
+ sameDay : '[අද] LT[ට]',
+ nextDay : '[හෙට] LT[ට]',
+ nextWeek : 'dddd LT[ට]',
+ lastDay : '[ඊයේ] LT[ට]',
+ lastWeek : '[පසුගිය] dddd LT[ට]',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%sකින්',
+ past : '%sකට පෙර',
+ s : 'තත්පර කිහිපය',
+ m : 'මිනිත්තුව',
+ mm : 'මිනිත්තු %d',
+ h : 'පැය',
+ hh : 'පැය %d',
+ d : 'දිනය',
+ dd : 'දින %d',
+ M : 'මාසය',
+ MM : 'මාස %d',
+ y : 'වසර',
+ yy : 'වසර %d'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2} වැනි/,
+ ordinal : function (number) {
+ return number + ' වැනි';
+ },
+ meridiemParse : /පෙර වරු|පස් වරු|පෙ.ව|ප.ව./,
+ isPM : function (input) {
+ return input === 'ප.ව.' || input === 'පස් වරු';
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'ප.ව.' : 'පස් වරු';
+ } else {
+ return isLower ? 'පෙ.ව.' : 'පෙර වරු';
+ }
+ }
+});
+
+return si;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/sk.js b/www/wiki/resources/lib/moment/locale/sk.js
new file mode 100644
index 00000000..aa61da62
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/sk.js
@@ -0,0 +1,150 @@
+//! moment.js locale configuration
+//! locale : Slovak [sk]
+//! author : Martin Minka : https://github.com/k2s
+//! based on work of petrbela : https://github.com/petrbela
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = 'január_február_marec_apríl_máj_jún_júl_august_september_október_november_december'.split('_');
+var monthsShort = 'jan_feb_mar_apr_máj_jún_júl_aug_sep_okt_nov_dec'.split('_');
+function plural(n) {
+ return (n > 1) && (n < 5);
+}
+function translate(number, withoutSuffix, key, isFuture) {
+ var result = number + ' ';
+ switch (key) {
+ case 's': // a few seconds / in a few seconds / a few seconds ago
+ return (withoutSuffix || isFuture) ? 'pár sekúnd' : 'pár sekundami';
+ case 'm': // a minute / in a minute / a minute ago
+ return withoutSuffix ? 'minúta' : (isFuture ? 'minútu' : 'minútou');
+ case 'mm': // 9 minutes / in 9 minutes / 9 minutes ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'minúty' : 'minút');
+ } else {
+ return result + 'minútami';
+ }
+ break;
+ case 'h': // an hour / in an hour / an hour ago
+ return withoutSuffix ? 'hodina' : (isFuture ? 'hodinu' : 'hodinou');
+ case 'hh': // 9 hours / in 9 hours / 9 hours ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'hodiny' : 'hodín');
+ } else {
+ return result + 'hodinami';
+ }
+ break;
+ case 'd': // a day / in a day / a day ago
+ return (withoutSuffix || isFuture) ? 'deň' : 'dňom';
+ case 'dd': // 9 days / in 9 days / 9 days ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'dni' : 'dní');
+ } else {
+ return result + 'dňami';
+ }
+ break;
+ case 'M': // a month / in a month / a month ago
+ return (withoutSuffix || isFuture) ? 'mesiac' : 'mesiacom';
+ case 'MM': // 9 months / in 9 months / 9 months ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'mesiace' : 'mesiacov');
+ } else {
+ return result + 'mesiacmi';
+ }
+ break;
+ case 'y': // a year / in a year / a year ago
+ return (withoutSuffix || isFuture) ? 'rok' : 'rokom';
+ case 'yy': // 9 years / in 9 years / 9 years ago
+ if (withoutSuffix || isFuture) {
+ return result + (plural(number) ? 'roky' : 'rokov');
+ } else {
+ return result + 'rokmi';
+ }
+ break;
+ }
+}
+
+var sk = moment.defineLocale('sk', {
+ months : months,
+ monthsShort : monthsShort,
+ weekdays : 'nedeľa_pondelok_utorok_streda_štvrtok_piatok_sobota'.split('_'),
+ weekdaysShort : 'ne_po_ut_st_št_pi_so'.split('_'),
+ weekdaysMin : 'ne_po_ut_st_št_pi_so'.split('_'),
+ longDateFormat : {
+ LT: 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd D. MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay: '[dnes o] LT',
+ nextDay: '[zajtra o] LT',
+ nextWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[v nedeľu o] LT';
+ case 1:
+ case 2:
+ return '[v] dddd [o] LT';
+ case 3:
+ return '[v stredu o] LT';
+ case 4:
+ return '[vo štvrtok o] LT';
+ case 5:
+ return '[v piatok o] LT';
+ case 6:
+ return '[v sobotu o] LT';
+ }
+ },
+ lastDay: '[včera o] LT',
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[minulú nedeľu o] LT';
+ case 1:
+ case 2:
+ return '[minulý] dddd [o] LT';
+ case 3:
+ return '[minulú stredu o] LT';
+ case 4:
+ case 5:
+ return '[minulý] dddd [o] LT';
+ case 6:
+ return '[minulú sobotu o] LT';
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : 'pred %s',
+ s : translate,
+ m : translate,
+ mm : translate,
+ h : translate,
+ hh : translate,
+ d : translate,
+ dd : translate,
+ M : translate,
+ MM : translate,
+ y : translate,
+ yy : translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return sk;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/sl.js b/www/wiki/resources/lib/moment/locale/sl.js
new file mode 100644
index 00000000..e74b3a11
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/sl.js
@@ -0,0 +1,162 @@
+//! moment.js locale configuration
+//! locale : Slovenian [sl]
+//! author : Robert Sedovšek : https://github.com/sedovsek
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function processRelativeTime(number, withoutSuffix, key, isFuture) {
+ var result = number + ' ';
+ switch (key) {
+ case 's':
+ return withoutSuffix || isFuture ? 'nekaj sekund' : 'nekaj sekundami';
+ case 'm':
+ return withoutSuffix ? 'ena minuta' : 'eno minuto';
+ case 'mm':
+ if (number === 1) {
+ result += withoutSuffix ? 'minuta' : 'minuto';
+ } else if (number === 2) {
+ result += withoutSuffix || isFuture ? 'minuti' : 'minutama';
+ } else if (number < 5) {
+ result += withoutSuffix || isFuture ? 'minute' : 'minutami';
+ } else {
+ result += withoutSuffix || isFuture ? 'minut' : 'minutami';
+ }
+ return result;
+ case 'h':
+ return withoutSuffix ? 'ena ura' : 'eno uro';
+ case 'hh':
+ if (number === 1) {
+ result += withoutSuffix ? 'ura' : 'uro';
+ } else if (number === 2) {
+ result += withoutSuffix || isFuture ? 'uri' : 'urama';
+ } else if (number < 5) {
+ result += withoutSuffix || isFuture ? 'ure' : 'urami';
+ } else {
+ result += withoutSuffix || isFuture ? 'ur' : 'urami';
+ }
+ return result;
+ case 'd':
+ return withoutSuffix || isFuture ? 'en dan' : 'enim dnem';
+ case 'dd':
+ if (number === 1) {
+ result += withoutSuffix || isFuture ? 'dan' : 'dnem';
+ } else if (number === 2) {
+ result += withoutSuffix || isFuture ? 'dni' : 'dnevoma';
+ } else {
+ result += withoutSuffix || isFuture ? 'dni' : 'dnevi';
+ }
+ return result;
+ case 'M':
+ return withoutSuffix || isFuture ? 'en mesec' : 'enim mesecem';
+ case 'MM':
+ if (number === 1) {
+ result += withoutSuffix || isFuture ? 'mesec' : 'mesecem';
+ } else if (number === 2) {
+ result += withoutSuffix || isFuture ? 'meseca' : 'mesecema';
+ } else if (number < 5) {
+ result += withoutSuffix || isFuture ? 'mesece' : 'meseci';
+ } else {
+ result += withoutSuffix || isFuture ? 'mesecev' : 'meseci';
+ }
+ return result;
+ case 'y':
+ return withoutSuffix || isFuture ? 'eno leto' : 'enim letom';
+ case 'yy':
+ if (number === 1) {
+ result += withoutSuffix || isFuture ? 'leto' : 'letom';
+ } else if (number === 2) {
+ result += withoutSuffix || isFuture ? 'leti' : 'letoma';
+ } else if (number < 5) {
+ result += withoutSuffix || isFuture ? 'leta' : 'leti';
+ } else {
+ result += withoutSuffix || isFuture ? 'let' : 'leti';
+ }
+ return result;
+ }
+}
+
+var sl = moment.defineLocale('sl', {
+ months : 'januar_februar_marec_april_maj_junij_julij_avgust_september_oktober_november_december'.split('_'),
+ monthsShort : 'jan._feb._mar._apr._maj._jun._jul._avg._sep._okt._nov._dec.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'nedelja_ponedeljek_torek_sreda_četrtek_petek_sobota'.split('_'),
+ weekdaysShort : 'ned._pon._tor._sre._čet._pet._sob.'.split('_'),
+ weekdaysMin : 'ne_po_to_sr_če_pe_so'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D. MMMM YYYY',
+ LLL : 'D. MMMM YYYY H:mm',
+ LLLL : 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar : {
+ sameDay : '[danes ob] LT',
+ nextDay : '[jutri ob] LT',
+
+ nextWeek : function () {
+ switch (this.day()) {
+ case 0:
+ return '[v] [nedeljo] [ob] LT';
+ case 3:
+ return '[v] [sredo] [ob] LT';
+ case 6:
+ return '[v] [soboto] [ob] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[v] dddd [ob] LT';
+ }
+ },
+ lastDay : '[včeraj ob] LT',
+ lastWeek : function () {
+ switch (this.day()) {
+ case 0:
+ return '[prejšnjo] [nedeljo] [ob] LT';
+ case 3:
+ return '[prejšnjo] [sredo] [ob] LT';
+ case 6:
+ return '[prejšnjo] [soboto] [ob] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[prejšnji] dddd [ob] LT';
+ }
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'čez %s',
+ past : 'pred %s',
+ s : processRelativeTime,
+ m : processRelativeTime,
+ mm : processRelativeTime,
+ h : processRelativeTime,
+ hh : processRelativeTime,
+ d : processRelativeTime,
+ dd : processRelativeTime,
+ M : processRelativeTime,
+ MM : processRelativeTime,
+ y : processRelativeTime,
+ yy : processRelativeTime
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return sl;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/sq.js b/www/wiki/resources/lib/moment/locale/sq.js
new file mode 100644
index 00000000..b92dc172
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/sq.js
@@ -0,0 +1,70 @@
+//! moment.js locale configuration
+//! locale : Albanian [sq]
+//! author : Flakërim Ismani : https://github.com/flakerimi
+//! author : Menelion Elensúle : https://github.com/Oire
+//! author : Oerd Cukalla : https://github.com/oerd
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var sq = moment.defineLocale('sq', {
+ months : 'Janar_Shkurt_Mars_Prill_Maj_Qershor_Korrik_Gusht_Shtator_Tetor_Nëntor_Dhjetor'.split('_'),
+ monthsShort : 'Jan_Shk_Mar_Pri_Maj_Qer_Kor_Gus_Sht_Tet_Nën_Dhj'.split('_'),
+ weekdays : 'E Diel_E Hënë_E Martë_E Mërkurë_E Enjte_E Premte_E Shtunë'.split('_'),
+ weekdaysShort : 'Die_Hën_Mar_Mër_Enj_Pre_Sht'.split('_'),
+ weekdaysMin : 'D_H_Ma_Më_E_P_Sh'.split('_'),
+ weekdaysParseExact : true,
+ meridiemParse: /PD|MD/,
+ isPM: function (input) {
+ return input.charAt(0) === 'M';
+ },
+ meridiem : function (hours, minutes, isLower) {
+ return hours < 12 ? 'PD' : 'MD';
+ },
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[Sot në] LT',
+ nextDay : '[Nesër në] LT',
+ nextWeek : 'dddd [në] LT',
+ lastDay : '[Dje në] LT',
+ lastWeek : 'dddd [e kaluar në] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'në %s',
+ past : '%s më parë',
+ s : 'disa sekonda',
+ m : 'një minutë',
+ mm : '%d minuta',
+ h : 'një orë',
+ hh : '%d orë',
+ d : 'një ditë',
+ dd : '%d ditë',
+ M : 'një muaj',
+ MM : '%d muaj',
+ y : 'një vit',
+ yy : '%d vite'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return sq;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/sr-cyrl.js b/www/wiki/resources/lib/moment/locale/sr-cyrl.js
new file mode 100644
index 00000000..3007819b
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/sr-cyrl.js
@@ -0,0 +1,110 @@
+//! moment.js locale configuration
+//! locale : Serbian Cyrillic [sr-cyrl]
+//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var translator = {
+ words: { //Different grammatical cases
+ m: ['један минут', 'једне минуте'],
+ mm: ['минут', 'минуте', 'минута'],
+ h: ['један сат', 'једног сата'],
+ hh: ['сат', 'сата', 'сати'],
+ dd: ['дан', 'дана', 'дана'],
+ MM: ['месец', 'месеца', 'месеци'],
+ yy: ['година', 'године', 'година']
+ },
+ correctGrammaticalCase: function (number, wordKey) {
+ return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
+ },
+ translate: function (number, withoutSuffix, key) {
+ var wordKey = translator.words[key];
+ if (key.length === 1) {
+ return withoutSuffix ? wordKey[0] : wordKey[1];
+ } else {
+ return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
+ }
+ }
+};
+
+var srCyrl = moment.defineLocale('sr-cyrl', {
+ months: 'јануар_фебруар_март_април_мај_јун_јул_август_септембар_октобар_новембар_децембар'.split('_'),
+ monthsShort: 'јан._феб._мар._апр._мај_јун_јул_авг._сеп._окт._нов._дец.'.split('_'),
+ monthsParseExact: true,
+ weekdays: 'недеља_понедељак_уторак_среда_четвртак_петак_субота'.split('_'),
+ weekdaysShort: 'нед._пон._уто._сре._чет._пет._суб.'.split('_'),
+ weekdaysMin: 'не_по_ут_ср_че_пе_су'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat: {
+ LT: 'H:mm',
+ LTS : 'H:mm:ss',
+ L: 'DD.MM.YYYY',
+ LL: 'D. MMMM YYYY',
+ LLL: 'D. MMMM YYYY H:mm',
+ LLLL: 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar: {
+ sameDay: '[данас у] LT',
+ nextDay: '[сутра у] LT',
+ nextWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[у] [недељу] [у] LT';
+ case 3:
+ return '[у] [среду] [у] LT';
+ case 6:
+ return '[у] [суботу] [у] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[у] dddd [у] LT';
+ }
+ },
+ lastDay : '[јуче у] LT',
+ lastWeek : function () {
+ var lastWeekDays = [
+ '[прошле] [недеље] [у] LT',
+ '[прошлог] [понедељка] [у] LT',
+ '[прошлог] [уторка] [у] LT',
+ '[прошле] [среде] [у] LT',
+ '[прошлог] [четвртка] [у] LT',
+ '[прошлог] [петка] [у] LT',
+ '[прошле] [суботе] [у] LT'
+ ];
+ return lastWeekDays[this.day()];
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'за %s',
+ past : 'пре %s',
+ s : 'неколико секунди',
+ m : translator.translate,
+ mm : translator.translate,
+ h : translator.translate,
+ hh : translator.translate,
+ d : 'дан',
+ dd : translator.translate,
+ M : 'месец',
+ MM : translator.translate,
+ y : 'годину',
+ yy : translator.translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return srCyrl;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/sr.js b/www/wiki/resources/lib/moment/locale/sr.js
new file mode 100644
index 00000000..90778a9b
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/sr.js
@@ -0,0 +1,110 @@
+//! moment.js locale configuration
+//! locale : Serbian [sr]
+//! author : Milan Janačković<milanjanackovic@gmail.com> : https://github.com/milan-j
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var translator = {
+ words: { //Different grammatical cases
+ m: ['jedan minut', 'jedne minute'],
+ mm: ['minut', 'minute', 'minuta'],
+ h: ['jedan sat', 'jednog sata'],
+ hh: ['sat', 'sata', 'sati'],
+ dd: ['dan', 'dana', 'dana'],
+ MM: ['mesec', 'meseca', 'meseci'],
+ yy: ['godina', 'godine', 'godina']
+ },
+ correctGrammaticalCase: function (number, wordKey) {
+ return number === 1 ? wordKey[0] : (number >= 2 && number <= 4 ? wordKey[1] : wordKey[2]);
+ },
+ translate: function (number, withoutSuffix, key) {
+ var wordKey = translator.words[key];
+ if (key.length === 1) {
+ return withoutSuffix ? wordKey[0] : wordKey[1];
+ } else {
+ return number + ' ' + translator.correctGrammaticalCase(number, wordKey);
+ }
+ }
+};
+
+var sr = moment.defineLocale('sr', {
+ months: 'januar_februar_mart_april_maj_jun_jul_avgust_septembar_oktobar_novembar_decembar'.split('_'),
+ monthsShort: 'jan._feb._mar._apr._maj_jun_jul_avg._sep._okt._nov._dec.'.split('_'),
+ monthsParseExact: true,
+ weekdays: 'nedelja_ponedeljak_utorak_sreda_četvrtak_petak_subota'.split('_'),
+ weekdaysShort: 'ned._pon._uto._sre._čet._pet._sub.'.split('_'),
+ weekdaysMin: 'ne_po_ut_sr_če_pe_su'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat: {
+ LT: 'H:mm',
+ LTS : 'H:mm:ss',
+ L: 'DD.MM.YYYY',
+ LL: 'D. MMMM YYYY',
+ LLL: 'D. MMMM YYYY H:mm',
+ LLLL: 'dddd, D. MMMM YYYY H:mm'
+ },
+ calendar: {
+ sameDay: '[danas u] LT',
+ nextDay: '[sutra u] LT',
+ nextWeek: function () {
+ switch (this.day()) {
+ case 0:
+ return '[u] [nedelju] [u] LT';
+ case 3:
+ return '[u] [sredu] [u] LT';
+ case 6:
+ return '[u] [subotu] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[u] dddd [u] LT';
+ }
+ },
+ lastDay : '[juče u] LT',
+ lastWeek : function () {
+ var lastWeekDays = [
+ '[prošle] [nedelje] [u] LT',
+ '[prošlog] [ponedeljka] [u] LT',
+ '[prošlog] [utorka] [u] LT',
+ '[prošle] [srede] [u] LT',
+ '[prošlog] [četvrtka] [u] LT',
+ '[prošlog] [petka] [u] LT',
+ '[prošle] [subote] [u] LT'
+ ];
+ return lastWeekDays[this.day()];
+ },
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'za %s',
+ past : 'pre %s',
+ s : 'nekoliko sekundi',
+ m : translator.translate,
+ mm : translator.translate,
+ h : translator.translate,
+ hh : translator.translate,
+ d : 'dan',
+ dd : translator.translate,
+ M : 'mesec',
+ MM : translator.translate,
+ y : 'godinu',
+ yy : translator.translate
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}\./,
+ ordinal : '%d.',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return sr;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ss.js b/www/wiki/resources/lib/moment/locale/ss.js
new file mode 100644
index 00000000..e89e2db2
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ss.js
@@ -0,0 +1,89 @@
+//! moment.js locale configuration
+//! locale : siSwati [ss]
+//! author : Nicolai Davies<mail@nicolai.io> : https://github.com/nicolaidavies
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+
+var ss = moment.defineLocale('ss', {
+ months : "Bhimbidvwane_Indlovana_Indlov'lenkhulu_Mabasa_Inkhwekhweti_Inhlaba_Kholwane_Ingci_Inyoni_Imphala_Lweti_Ingongoni".split('_'),
+ monthsShort : 'Bhi_Ina_Inu_Mab_Ink_Inh_Kho_Igc_Iny_Imp_Lwe_Igo'.split('_'),
+ weekdays : 'Lisontfo_Umsombuluko_Lesibili_Lesitsatfu_Lesine_Lesihlanu_Umgcibelo'.split('_'),
+ weekdaysShort : 'Lis_Umb_Lsb_Les_Lsi_Lsh_Umg'.split('_'),
+ weekdaysMin : 'Li_Us_Lb_Lt_Ls_Lh_Ug'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY h:mm A',
+ LLLL : 'dddd, D MMMM YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : '[Namuhla nga] LT',
+ nextDay : '[Kusasa nga] LT',
+ nextWeek : 'dddd [nga] LT',
+ lastDay : '[Itolo nga] LT',
+ lastWeek : 'dddd [leliphelile] [nga] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'nga %s',
+ past : 'wenteka nga %s',
+ s : 'emizuzwana lomcane',
+ m : 'umzuzu',
+ mm : '%d emizuzu',
+ h : 'lihora',
+ hh : '%d emahora',
+ d : 'lilanga',
+ dd : '%d emalanga',
+ M : 'inyanga',
+ MM : '%d tinyanga',
+ y : 'umnyaka',
+ yy : '%d iminyaka'
+ },
+ meridiemParse: /ekuseni|emini|entsambama|ebusuku/,
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 11) {
+ return 'ekuseni';
+ } else if (hours < 15) {
+ return 'emini';
+ } else if (hours < 19) {
+ return 'entsambama';
+ } else {
+ return 'ebusuku';
+ }
+ },
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'ekuseni') {
+ return hour;
+ } else if (meridiem === 'emini') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === 'entsambama' || meridiem === 'ebusuku') {
+ if (hour === 0) {
+ return 0;
+ }
+ return hour + 12;
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}/,
+ ordinal : '%d',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return ss;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/sv.js b/www/wiki/resources/lib/moment/locale/sv.js
new file mode 100644
index 00000000..1aa76607
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/sv.js
@@ -0,0 +1,69 @@
+//! moment.js locale configuration
+//! locale : Swedish [sv]
+//! author : Jens Alm : https://github.com/ulmus
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var sv = moment.defineLocale('sv', {
+ months : 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'),
+ monthsShort : 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
+ weekdays : 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'),
+ weekdaysShort : 'sön_mån_tis_ons_tor_fre_lör'.split('_'),
+ weekdaysMin : 'sö_må_ti_on_to_fr_lö'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY-MM-DD',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY [kl.] HH:mm',
+ LLLL : 'dddd D MMMM YYYY [kl.] HH:mm',
+ lll : 'D MMM YYYY HH:mm',
+ llll : 'ddd D MMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Idag] LT',
+ nextDay: '[Imorgon] LT',
+ lastDay: '[Igår] LT',
+ nextWeek: '[På] dddd LT',
+ lastWeek: '[I] dddd[s] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'om %s',
+ past : 'för %s sedan',
+ s : 'några sekunder',
+ m : 'en minut',
+ mm : '%d minuter',
+ h : 'en timme',
+ hh : '%d timmar',
+ d : 'en dag',
+ dd : '%d dagar',
+ M : 'en månad',
+ MM : '%d månader',
+ y : 'ett år',
+ yy : '%d år'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(e|a)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'e' :
+ (b === 1) ? 'a' :
+ (b === 2) ? 'a' :
+ (b === 3) ? 'e' : 'e';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return sv;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/sw.js b/www/wiki/resources/lib/moment/locale/sw.js
new file mode 100644
index 00000000..9ed314f5
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/sw.js
@@ -0,0 +1,59 @@
+//! moment.js locale configuration
+//! locale : Swahili [sw]
+//! author : Fahad Kassim : https://github.com/fadsel
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var sw = moment.defineLocale('sw', {
+ months : 'Januari_Februari_Machi_Aprili_Mei_Juni_Julai_Agosti_Septemba_Oktoba_Novemba_Desemba'.split('_'),
+ monthsShort : 'Jan_Feb_Mac_Apr_Mei_Jun_Jul_Ago_Sep_Okt_Nov_Des'.split('_'),
+ weekdays : 'Jumapili_Jumatatu_Jumanne_Jumatano_Alhamisi_Ijumaa_Jumamosi'.split('_'),
+ weekdaysShort : 'Jpl_Jtat_Jnne_Jtan_Alh_Ijm_Jmos'.split('_'),
+ weekdaysMin : 'J2_J3_J4_J5_Al_Ij_J1'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[leo saa] LT',
+ nextDay : '[kesho saa] LT',
+ nextWeek : '[wiki ijayo] dddd [saat] LT',
+ lastDay : '[jana] LT',
+ lastWeek : '[wiki iliyopita] dddd [saat] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s baadaye',
+ past : 'tokea %s',
+ s : 'hivi punde',
+ m : 'dakika moja',
+ mm : 'dakika %d',
+ h : 'saa limoja',
+ hh : 'masaa %d',
+ d : 'siku moja',
+ dd : 'masiku %d',
+ M : 'mwezi mmoja',
+ MM : 'miezi %d',
+ y : 'mwaka mmoja',
+ yy : 'miaka %d'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return sw;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ta.js b/www/wiki/resources/lib/moment/locale/ta.js
new file mode 100644
index 00000000..d9d2555a
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ta.js
@@ -0,0 +1,130 @@
+//! moment.js locale configuration
+//! locale : Tamil [ta]
+//! author : Arjunkumar Krishnamoorthy : https://github.com/tk120404
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var symbolMap = {
+ '1': '௧',
+ '2': '௨',
+ '3': '௩',
+ '4': '௪',
+ '5': '௫',
+ '6': '௬',
+ '7': '௭',
+ '8': '௮',
+ '9': '௯',
+ '0': '௦'
+};
+var numberMap = {
+ '௧': '1',
+ '௨': '2',
+ '௩': '3',
+ '௪': '4',
+ '௫': '5',
+ '௬': '6',
+ '௭': '7',
+ '௮': '8',
+ '௯': '9',
+ '௦': '0'
+};
+
+var ta = moment.defineLocale('ta', {
+ months : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
+ monthsShort : 'ஜனவரி_பிப்ரவரி_மார்ச்_ஏப்ரல்_மே_ஜூன்_ஜூலை_ஆகஸ்ட்_செப்டெம்பர்_அக்டோபர்_நவம்பர்_டிசம்பர்'.split('_'),
+ weekdays : 'ஞாயிற்றுக்கிழமை_திங்கட்கிழமை_செவ்வாய்கிழமை_புதன்கிழமை_வியாழக்கிழமை_வெள்ளிக்கிழமை_சனிக்கிழமை'.split('_'),
+ weekdaysShort : 'ஞாயிறு_திங்கள்_செவ்வாய்_புதன்_வியாழன்_வெள்ளி_சனி'.split('_'),
+ weekdaysMin : 'ஞா_தி_செ_பு_வி_வெ_ச'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, HH:mm',
+ LLLL : 'dddd, D MMMM YYYY, HH:mm'
+ },
+ calendar : {
+ sameDay : '[இன்று] LT',
+ nextDay : '[நாளை] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[நேற்று] LT',
+ lastWeek : '[கடந்த வாரம்] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s இல்',
+ past : '%s முன்',
+ s : 'ஒரு சில விநாடிகள்',
+ m : 'ஒரு நிமிடம்',
+ mm : '%d நிமிடங்கள்',
+ h : 'ஒரு மணி நேரம்',
+ hh : '%d மணி நேரம்',
+ d : 'ஒரு நாள்',
+ dd : '%d நாட்கள்',
+ M : 'ஒரு மாதம்',
+ MM : '%d மாதங்கள்',
+ y : 'ஒரு வருடம்',
+ yy : '%d ஆண்டுகள்'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}வது/,
+ ordinal : function (number) {
+ return number + 'வது';
+ },
+ preparse: function (string) {
+ return string.replace(/[௧௨௩௪௫௬௭௮௯௦]/g, function (match) {
+ return numberMap[match];
+ });
+ },
+ postformat: function (string) {
+ return string.replace(/\d/g, function (match) {
+ return symbolMap[match];
+ });
+ },
+ // refer http://ta.wikipedia.org/s/1er1
+ meridiemParse: /யாமம்|வைகறை|காலை|நண்பகல்|எற்பாடு|மாலை/,
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 2) {
+ return ' யாமம்';
+ } else if (hour < 6) {
+ return ' வைகறை'; // வைகறை
+ } else if (hour < 10) {
+ return ' காலை'; // காலை
+ } else if (hour < 14) {
+ return ' நண்பகல்'; // நண்பகல்
+ } else if (hour < 18) {
+ return ' எற்பாடு'; // எற்பாடு
+ } else if (hour < 22) {
+ return ' மாலை'; // மாலை
+ } else {
+ return ' யாமம்';
+ }
+ },
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'யாமம்') {
+ return hour < 2 ? hour : hour + 12;
+ } else if (meridiem === 'வைகறை' || meridiem === 'காலை') {
+ return hour;
+ } else if (meridiem === 'நண்பகல்') {
+ return hour >= 10 ? hour : hour + 12;
+ } else {
+ return hour + 12;
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return ta;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/te.js b/www/wiki/resources/lib/moment/locale/te.js
new file mode 100644
index 00000000..fe339047
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/te.js
@@ -0,0 +1,89 @@
+//! moment.js locale configuration
+//! locale : Telugu [te]
+//! author : Krishna Chaitanya Thota : https://github.com/kcthota
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var te = moment.defineLocale('te', {
+ months : 'జనవరి_ఫిబ్రవరి_మార్చి_ఏప్రిల్_మే_జూన్_జూలై_ఆగస్టు_సెప్టెంబర్_అక్టోబర్_నవంబర్_డిసెంబర్'.split('_'),
+ monthsShort : 'జన._ఫిబ్ర._మార్చి_ఏప్రి._మే_జూన్_జూలై_ఆగ._సెప్._అక్టో._నవ._డిసె.'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'ఆదివారం_సోమవారం_మంగళవారం_బుధవారం_గురువారం_శుక్రవారం_శనివారం'.split('_'),
+ weekdaysShort : 'ఆది_సోమ_మంగళ_బుధ_గురు_శుక్ర_శని'.split('_'),
+ weekdaysMin : 'ఆ_సో_మం_బు_గు_శు_శ'.split('_'),
+ longDateFormat : {
+ LT : 'A h:mm',
+ LTS : 'A h:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY, A h:mm',
+ LLLL : 'dddd, D MMMM YYYY, A h:mm'
+ },
+ calendar : {
+ sameDay : '[నేడు] LT',
+ nextDay : '[రేపు] LT',
+ nextWeek : 'dddd, LT',
+ lastDay : '[నిన్న] LT',
+ lastWeek : '[గత] dddd, LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s లో',
+ past : '%s క్రితం',
+ s : 'కొన్ని క్షణాలు',
+ m : 'ఒక నిమిషం',
+ mm : '%d నిమిషాలు',
+ h : 'ఒక గంట',
+ hh : '%d గంటలు',
+ d : 'ఒక రోజు',
+ dd : '%d రోజులు',
+ M : 'ఒక నెల',
+ MM : '%d నెలలు',
+ y : 'ఒక సంవత్సరం',
+ yy : '%d సంవత్సరాలు'
+ },
+ dayOfMonthOrdinalParse : /\d{1,2}వ/,
+ ordinal : '%dవ',
+ meridiemParse: /రాత్రి|ఉదయం|మధ్యాహ్నం|సాయంత్రం/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === 'రాత్రి') {
+ return hour < 4 ? hour : hour + 12;
+ } else if (meridiem === 'ఉదయం') {
+ return hour;
+ } else if (meridiem === 'మధ్యాహ్నం') {
+ return hour >= 10 ? hour : hour + 12;
+ } else if (meridiem === 'సాయంత్రం') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'రాత్రి';
+ } else if (hour < 10) {
+ return 'ఉదయం';
+ } else if (hour < 17) {
+ return 'మధ్యాహ్నం';
+ } else if (hour < 20) {
+ return 'సాయంత్రం';
+ } else {
+ return 'రాత్రి';
+ }
+ },
+ week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return te;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/tet.js b/www/wiki/resources/lib/moment/locale/tet.js
new file mode 100644
index 00000000..c9c2928f
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/tet.js
@@ -0,0 +1,68 @@
+//! moment.js locale configuration
+//! locale : Tetun Dili (East Timor) [tet]
+//! author : Joshua Brooks : https://github.com/joshbrooks
+//! author : Onorio De J. Afonso : https://github.com/marobo
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var tet = moment.defineLocale('tet', {
+ months : 'Janeiru_Fevereiru_Marsu_Abril_Maiu_Juniu_Juliu_Augustu_Setembru_Outubru_Novembru_Dezembru'.split('_'),
+ monthsShort : 'Jan_Fev_Mar_Abr_Mai_Jun_Jul_Aug_Set_Out_Nov_Dez'.split('_'),
+ weekdays : 'Domingu_Segunda_Tersa_Kuarta_Kinta_Sexta_Sabadu'.split('_'),
+ weekdaysShort : 'Dom_Seg_Ters_Kua_Kint_Sext_Sab'.split('_'),
+ weekdaysMin : 'Do_Seg_Te_Ku_Ki_Sex_Sa'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Ohin iha] LT',
+ nextDay: '[Aban iha] LT',
+ nextWeek: 'dddd [iha] LT',
+ lastDay: '[Horiseik iha] LT',
+ lastWeek: 'dddd [semana kotuk] [iha] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'iha %s',
+ past : '%s liuba',
+ s : 'minutu balun',
+ m : 'minutu ida',
+ mm : 'minutus %d',
+ h : 'horas ida',
+ hh : 'horas %d',
+ d : 'loron ida',
+ dd : 'loron %d',
+ M : 'fulan ida',
+ MM : 'fulan %d',
+ y : 'tinan ida',
+ yy : 'tinan %d'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(st|nd|rd|th)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return tet;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/th.js b/www/wiki/resources/lib/moment/locale/th.js
new file mode 100644
index 00000000..17ec0f19
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/th.js
@@ -0,0 +1,67 @@
+//! moment.js locale configuration
+//! locale : Thai [th]
+//! author : Kridsada Thanabulpong : https://github.com/sirn
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var th = moment.defineLocale('th', {
+ months : 'มกราคม_กุมภาพันธ์_มีนาคม_เมษายน_พฤษภาคม_มิถุนายน_กรกฎาคม_สิงหาคม_กันยายน_ตุลาคม_พฤศจิกายน_ธันวาคม'.split('_'),
+ monthsShort : 'ม.ค._ก.พ._มี.ค._เม.ย._พ.ค._มิ.ย._ก.ค._ส.ค._ก.ย._ต.ค._พ.ย._ธ.ค.'.split('_'),
+ monthsParseExact: true,
+ weekdays : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัสบดี_ศุกร์_เสาร์'.split('_'),
+ weekdaysShort : 'อาทิตย์_จันทร์_อังคาร_พุธ_พฤหัส_ศุกร์_เสาร์'.split('_'), // yes, three characters difference
+ weekdaysMin : 'อา._จ._อ._พ._พฤ._ศ._ส.'.split('_'),
+ weekdaysParseExact : true,
+ longDateFormat : {
+ LT : 'H:mm',
+ LTS : 'H:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY เวลา H:mm',
+ LLLL : 'วันddddที่ D MMMM YYYY เวลา H:mm'
+ },
+ meridiemParse: /ก่อนเที่ยง|หลังเที่ยง/,
+ isPM: function (input) {
+ return input === 'หลังเที่ยง';
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'ก่อนเที่ยง';
+ } else {
+ return 'หลังเที่ยง';
+ }
+ },
+ calendar : {
+ sameDay : '[วันนี้ เวลา] LT',
+ nextDay : '[พรุ่งนี้ เวลา] LT',
+ nextWeek : 'dddd[หน้า เวลา] LT',
+ lastDay : '[เมื่อวานนี้ เวลา] LT',
+ lastWeek : '[วัน]dddd[ที่แล้ว เวลา] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'อีก %s',
+ past : '%sที่แล้ว',
+ s : 'ไม่กี่วินาที',
+ m : '1 นาที',
+ mm : '%d นาที',
+ h : '1 ชั่วโมง',
+ hh : '%d ชั่วโมง',
+ d : '1 วัน',
+ dd : '%d วัน',
+ M : '1 เดือน',
+ MM : '%d เดือน',
+ y : '1 ปี',
+ yy : '%d ปี'
+ }
+});
+
+return th;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/tl-ph.js b/www/wiki/resources/lib/moment/locale/tl-ph.js
new file mode 100644
index 00000000..f66b0220
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/tl-ph.js
@@ -0,0 +1,62 @@
+//! moment.js locale configuration
+//! locale : Tagalog (Philippines) [tl-ph]
+//! author : Dan Hagman : https://github.com/hagmandan
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var tlPh = moment.defineLocale('tl-ph', {
+ months : 'Enero_Pebrero_Marso_Abril_Mayo_Hunyo_Hulyo_Agosto_Setyembre_Oktubre_Nobyembre_Disyembre'.split('_'),
+ monthsShort : 'Ene_Peb_Mar_Abr_May_Hun_Hul_Ago_Set_Okt_Nob_Dis'.split('_'),
+ weekdays : 'Linggo_Lunes_Martes_Miyerkules_Huwebes_Biyernes_Sabado'.split('_'),
+ weekdaysShort : 'Lin_Lun_Mar_Miy_Huw_Biy_Sab'.split('_'),
+ weekdaysMin : 'Li_Lu_Ma_Mi_Hu_Bi_Sab'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'MM/D/YYYY',
+ LL : 'MMMM D, YYYY',
+ LLL : 'MMMM D, YYYY HH:mm',
+ LLLL : 'dddd, MMMM DD, YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: 'LT [ngayong araw]',
+ nextDay: '[Bukas ng] LT',
+ nextWeek: 'LT [sa susunod na] dddd',
+ lastDay: 'LT [kahapon]',
+ lastWeek: 'LT [noong nakaraang] dddd',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'sa loob ng %s',
+ past : '%s ang nakalipas',
+ s : 'ilang segundo',
+ m : 'isang minuto',
+ mm : '%d minuto',
+ h : 'isang oras',
+ hh : '%d oras',
+ d : 'isang araw',
+ dd : '%d araw',
+ M : 'isang buwan',
+ MM : '%d buwan',
+ y : 'isang taon',
+ yy : '%d taon'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}/,
+ ordinal : function (number) {
+ return number;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return tlPh;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/tr.js b/www/wiki/resources/lib/moment/locale/tr.js
new file mode 100644
index 00000000..911e8d14
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/tr.js
@@ -0,0 +1,90 @@
+//! moment.js locale configuration
+//! locale : Turkish [tr]
+//! authors : Erhan Gundogan : https://github.com/erhangundogan,
+//! Burak Yiğit Kaya: https://github.com/BYK
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var suffixes = {
+ 1: '\'inci',
+ 5: '\'inci',
+ 8: '\'inci',
+ 70: '\'inci',
+ 80: '\'inci',
+ 2: '\'nci',
+ 7: '\'nci',
+ 20: '\'nci',
+ 50: '\'nci',
+ 3: '\'üncü',
+ 4: '\'üncü',
+ 100: '\'üncü',
+ 6: '\'ncı',
+ 9: '\'uncu',
+ 10: '\'uncu',
+ 30: '\'uncu',
+ 60: '\'ıncı',
+ 90: '\'ıncı'
+};
+
+var tr = moment.defineLocale('tr', {
+ months : 'Ocak_Şubat_Mart_Nisan_Mayıs_Haziran_Temmuz_Ağustos_Eylül_Ekim_Kasım_Aralık'.split('_'),
+ monthsShort : 'Oca_Şub_Mar_Nis_May_Haz_Tem_Ağu_Eyl_Eki_Kas_Ara'.split('_'),
+ weekdays : 'Pazar_Pazartesi_Salı_Çarşamba_Perşembe_Cuma_Cumartesi'.split('_'),
+ weekdaysShort : 'Paz_Pts_Sal_Çar_Per_Cum_Cts'.split('_'),
+ weekdaysMin : 'Pz_Pt_Sa_Ça_Pe_Cu_Ct'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd, D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay : '[bugün saat] LT',
+ nextDay : '[yarın saat] LT',
+ nextWeek : '[gelecek] dddd [saat] LT',
+ lastDay : '[dün] LT',
+ lastWeek : '[geçen] dddd [saat] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s sonra',
+ past : '%s önce',
+ s : 'birkaç saniye',
+ m : 'bir dakika',
+ mm : '%d dakika',
+ h : 'bir saat',
+ hh : '%d saat',
+ d : 'bir gün',
+ dd : '%d gün',
+ M : 'bir ay',
+ MM : '%d ay',
+ y : 'bir yıl',
+ yy : '%d yıl'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}'(inci|nci|üncü|ncı|uncu|ıncı)/,
+ ordinal : function (number) {
+ if (number === 0) { // special case for zero
+ return number + '\'ıncı';
+ }
+ var a = number % 10,
+ b = number % 100 - a,
+ c = number >= 100 ? 100 : null;
+ return number + (suffixes[a] || suffixes[b] || suffixes[c]);
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return tr;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/tzm-latn.js b/www/wiki/resources/lib/moment/locale/tzm-latn.js
new file mode 100644
index 00000000..4d742c52
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/tzm-latn.js
@@ -0,0 +1,58 @@
+//! moment.js locale configuration
+//! locale : Central Atlas Tamazight Latin [tzm-latn]
+//! author : Abdel Said : https://github.com/abdelsaid
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var tzmLatn = moment.defineLocale('tzm-latn', {
+ months : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
+ monthsShort : 'innayr_brˤayrˤ_marˤsˤ_ibrir_mayyw_ywnyw_ywlywz_ɣwšt_šwtanbir_ktˤwbrˤ_nwwanbir_dwjnbir'.split('_'),
+ weekdays : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+ weekdaysShort : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+ weekdaysMin : 'asamas_aynas_asinas_akras_akwas_asimwas_asiḍyas'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[asdkh g] LT',
+ nextDay: '[aska g] LT',
+ nextWeek: 'dddd [g] LT',
+ lastDay: '[assant g] LT',
+ lastWeek: 'dddd [g] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'dadkh s yan %s',
+ past : 'yan %s',
+ s : 'imik',
+ m : 'minuḍ',
+ mm : '%d minuḍ',
+ h : 'saɛa',
+ hh : '%d tassaɛin',
+ d : 'ass',
+ dd : '%d ossan',
+ M : 'ayowr',
+ MM : '%d iyyirn',
+ y : 'asgas',
+ yy : '%d isgasn'
+ },
+ week : {
+ dow : 6, // Saturday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return tzmLatn;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/tzm.js b/www/wiki/resources/lib/moment/locale/tzm.js
new file mode 100644
index 00000000..1d1c2600
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/tzm.js
@@ -0,0 +1,58 @@
+//! moment.js locale configuration
+//! locale : Central Atlas Tamazight [tzm]
+//! author : Abdel Said : https://github.com/abdelsaid
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var tzm = moment.defineLocale('tzm', {
+ months : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
+ monthsShort : 'ⵉⵏⵏⴰⵢⵔ_ⴱⵕⴰⵢⵕ_ⵎⴰⵕⵚ_ⵉⴱⵔⵉⵔ_ⵎⴰⵢⵢⵓ_ⵢⵓⵏⵢⵓ_ⵢⵓⵍⵢⵓⵣ_ⵖⵓⵛⵜ_ⵛⵓⵜⴰⵏⴱⵉⵔ_ⴽⵟⵓⴱⵕ_ⵏⵓⵡⴰⵏⴱⵉⵔ_ⴷⵓⵊⵏⴱⵉⵔ'.split('_'),
+ weekdays : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+ weekdaysShort : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+ weekdaysMin : 'ⴰⵙⴰⵎⴰⵙ_ⴰⵢⵏⴰⵙ_ⴰⵙⵉⵏⴰⵙ_ⴰⴽⵔⴰⵙ_ⴰⴽⵡⴰⵙ_ⴰⵙⵉⵎⵡⴰⵙ_ⴰⵙⵉⴹⵢⴰⵙ'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS: 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd D MMMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[ⴰⵙⴷⵅ ⴴ] LT',
+ nextDay: '[ⴰⵙⴽⴰ ⴴ] LT',
+ nextWeek: 'dddd [ⴴ] LT',
+ lastDay: '[ⴰⵚⴰⵏⵜ ⴴ] LT',
+ lastWeek: 'dddd [ⴴ] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'ⴷⴰⴷⵅ ⵙ ⵢⴰⵏ %s',
+ past : 'ⵢⴰⵏ %s',
+ s : 'ⵉⵎⵉⴽ',
+ m : 'ⵎⵉⵏⵓⴺ',
+ mm : '%d ⵎⵉⵏⵓⴺ',
+ h : 'ⵙⴰⵄⴰ',
+ hh : '%d ⵜⴰⵙⵙⴰⵄⵉⵏ',
+ d : 'ⴰⵙⵙ',
+ dd : '%d oⵙⵙⴰⵏ',
+ M : 'ⴰⵢoⵓⵔ',
+ MM : '%d ⵉⵢⵢⵉⵔⵏ',
+ y : 'ⴰⵙⴳⴰⵙ',
+ yy : '%d ⵉⵙⴳⴰⵙⵏ'
+ },
+ week : {
+ dow : 6, // Saturday is the first day of the week.
+ doy : 12 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return tzm;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/uk.js b/www/wiki/resources/lib/moment/locale/uk.js
new file mode 100644
index 00000000..1aff8c14
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/uk.js
@@ -0,0 +1,151 @@
+//! moment.js locale configuration
+//! locale : Ukrainian [uk]
+//! author : zemlanin : https://github.com/zemlanin
+//! Author : Menelion Elensúle : https://github.com/Oire
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+function plural(word, num) {
+ var forms = word.split('_');
+ return num % 10 === 1 && num % 100 !== 11 ? forms[0] : (num % 10 >= 2 && num % 10 <= 4 && (num % 100 < 10 || num % 100 >= 20) ? forms[1] : forms[2]);
+}
+function relativeTimeWithPlural(number, withoutSuffix, key) {
+ var format = {
+ 'mm': withoutSuffix ? 'хвилина_хвилини_хвилин' : 'хвилину_хвилини_хвилин',
+ 'hh': withoutSuffix ? 'година_години_годин' : 'годину_години_годин',
+ 'dd': 'день_дні_днів',
+ 'MM': 'місяць_місяці_місяців',
+ 'yy': 'рік_роки_років'
+ };
+ if (key === 'm') {
+ return withoutSuffix ? 'хвилина' : 'хвилину';
+ }
+ else if (key === 'h') {
+ return withoutSuffix ? 'година' : 'годину';
+ }
+ else {
+ return number + ' ' + plural(format[key], +number);
+ }
+}
+function weekdaysCaseReplace(m, format) {
+ var weekdays = {
+ 'nominative': 'неділя_понеділок_вівторок_середа_четвер_п’ятниця_субота'.split('_'),
+ 'accusative': 'неділю_понеділок_вівторок_середу_четвер_п’ятницю_суботу'.split('_'),
+ 'genitive': 'неділі_понеділка_вівторка_середи_четверга_п’ятниці_суботи'.split('_')
+ };
+
+ if (!m) {
+ return weekdays['nominative'];
+ }
+
+ var nounCase = (/(\[[ВвУу]\]) ?dddd/).test(format) ?
+ 'accusative' :
+ ((/\[?(?:минулої|наступної)? ?\] ?dddd/).test(format) ?
+ 'genitive' :
+ 'nominative');
+ return weekdays[nounCase][m.day()];
+}
+function processHoursFunction(str) {
+ return function () {
+ return str + 'о' + (this.hours() === 11 ? 'б' : '') + '] LT';
+ };
+}
+
+var uk = moment.defineLocale('uk', {
+ months : {
+ 'format': 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split('_'),
+ 'standalone': 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split('_')
+ },
+ monthsShort : 'січ_лют_бер_квіт_трав_черв_лип_серп_вер_жовт_лист_груд'.split('_'),
+ weekdays : weekdaysCaseReplace,
+ weekdaysShort : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+ weekdaysMin : 'нд_пн_вт_ср_чт_пт_сб'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD.MM.YYYY',
+ LL : 'D MMMM YYYY р.',
+ LLL : 'D MMMM YYYY р., HH:mm',
+ LLLL : 'dddd, D MMMM YYYY р., HH:mm'
+ },
+ calendar : {
+ sameDay: processHoursFunction('[Сьогодні '),
+ nextDay: processHoursFunction('[Завтра '),
+ lastDay: processHoursFunction('[Вчора '),
+ nextWeek: processHoursFunction('[У] dddd ['),
+ lastWeek: function () {
+ switch (this.day()) {
+ case 0:
+ case 3:
+ case 5:
+ case 6:
+ return processHoursFunction('[Минулої] dddd [').call(this);
+ case 1:
+ case 2:
+ case 4:
+ return processHoursFunction('[Минулого] dddd [').call(this);
+ }
+ },
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : 'за %s',
+ past : '%s тому',
+ s : 'декілька секунд',
+ m : relativeTimeWithPlural,
+ mm : relativeTimeWithPlural,
+ h : 'годину',
+ hh : relativeTimeWithPlural,
+ d : 'день',
+ dd : relativeTimeWithPlural,
+ M : 'місяць',
+ MM : relativeTimeWithPlural,
+ y : 'рік',
+ yy : relativeTimeWithPlural
+ },
+ // M. E.: those two are virtually unused but a user might want to implement them for his/her website for some reason
+ meridiemParse: /ночі|ранку|дня|вечора/,
+ isPM: function (input) {
+ return /^(дня|вечора)$/.test(input);
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 4) {
+ return 'ночі';
+ } else if (hour < 12) {
+ return 'ранку';
+ } else if (hour < 17) {
+ return 'дня';
+ } else {
+ return 'вечора';
+ }
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}-(й|го)/,
+ ordinal: function (number, period) {
+ switch (period) {
+ case 'M':
+ case 'd':
+ case 'DDD':
+ case 'w':
+ case 'W':
+ return number + '-й';
+ case 'D':
+ return number + '-го';
+ default:
+ return number;
+ }
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return uk;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/ur.js b/www/wiki/resources/lib/moment/locale/ur.js
new file mode 100644
index 00000000..4cf1c07a
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/ur.js
@@ -0,0 +1,99 @@
+//! moment.js locale configuration
+//! locale : Urdu [ur]
+//! author : Sawood Alam : https://github.com/ibnesayeed
+//! author : Zack : https://github.com/ZackVision
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var months = [
+ 'جنوری',
+ 'فروری',
+ 'مارچ',
+ 'اپریل',
+ 'مئی',
+ 'جون',
+ 'جولائی',
+ 'اگست',
+ 'ستمبر',
+ 'اکتوبر',
+ 'نومبر',
+ 'دسمبر'
+];
+var days = [
+ 'اتوار',
+ 'پیر',
+ 'منگل',
+ 'بدھ',
+ 'جمعرات',
+ 'جمعہ',
+ 'ہفتہ'
+];
+
+var ur = moment.defineLocale('ur', {
+ months : months,
+ monthsShort : months,
+ weekdays : days,
+ weekdaysShort : days,
+ weekdaysMin : days,
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'dddd، D MMMM YYYY HH:mm'
+ },
+ meridiemParse: /صبح|شام/,
+ isPM : function (input) {
+ return 'شام' === input;
+ },
+ meridiem : function (hour, minute, isLower) {
+ if (hour < 12) {
+ return 'صبح';
+ }
+ return 'شام';
+ },
+ calendar : {
+ sameDay : '[آج بوقت] LT',
+ nextDay : '[کل بوقت] LT',
+ nextWeek : 'dddd [بوقت] LT',
+ lastDay : '[گذشتہ روز بوقت] LT',
+ lastWeek : '[گذشتہ] dddd [بوقت] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : '%s بعد',
+ past : '%s قبل',
+ s : 'چند سیکنڈ',
+ m : 'ایک منٹ',
+ mm : '%d منٹ',
+ h : 'ایک گھنٹہ',
+ hh : '%d گھنٹے',
+ d : 'ایک دن',
+ dd : '%d دن',
+ M : 'ایک ماہ',
+ MM : '%d ماہ',
+ y : 'ایک سال',
+ yy : '%d سال'
+ },
+ preparse: function (string) {
+ return string.replace(/،/g, ',');
+ },
+ postformat: function (string) {
+ return string.replace(/,/g, '،');
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return ur;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/uz-latn.js b/www/wiki/resources/lib/moment/locale/uz-latn.js
new file mode 100644
index 00000000..21463b76
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/uz-latn.js
@@ -0,0 +1,58 @@
+//! moment.js locale configuration
+//! locale : Uzbek Latin [uz-latn]
+//! author : Rasulbek Mirzayev : github.com/Rasulbeeek
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var uzLatn = moment.defineLocale('uz-latn', {
+ months : 'Yanvar_Fevral_Mart_Aprel_May_Iyun_Iyul_Avgust_Sentabr_Oktabr_Noyabr_Dekabr'.split('_'),
+ monthsShort : 'Yan_Fev_Mar_Apr_May_Iyun_Iyul_Avg_Sen_Okt_Noy_Dek'.split('_'),
+ weekdays : 'Yakshanba_Dushanba_Seshanba_Chorshanba_Payshanba_Juma_Shanba'.split('_'),
+ weekdaysShort : 'Yak_Dush_Sesh_Chor_Pay_Jum_Shan'.split('_'),
+ weekdaysMin : 'Ya_Du_Se_Cho_Pa_Ju_Sha'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'D MMMM YYYY, dddd HH:mm'
+ },
+ calendar : {
+ sameDay : '[Bugun soat] LT [da]',
+ nextDay : '[Ertaga] LT [da]',
+ nextWeek : 'dddd [kuni soat] LT [da]',
+ lastDay : '[Kecha soat] LT [da]',
+ lastWeek : '[O\'tgan] dddd [kuni soat] LT [da]',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'Yaqin %s ichida',
+ past : 'Bir necha %s oldin',
+ s : 'soniya',
+ m : 'bir daqiqa',
+ mm : '%d daqiqa',
+ h : 'bir soat',
+ hh : '%d soat',
+ d : 'bir kun',
+ dd : '%d kun',
+ M : 'bir oy',
+ MM : '%d oy',
+ y : 'bir yil',
+ yy : '%d yil'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 1st is the first week of the year.
+ }
+});
+
+return uzLatn;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/uz.js b/www/wiki/resources/lib/moment/locale/uz.js
new file mode 100644
index 00000000..378461eb
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/uz.js
@@ -0,0 +1,58 @@
+//! moment.js locale configuration
+//! locale : Uzbek [uz]
+//! author : Sardor Muminov : https://github.com/muminoff
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var uz = moment.defineLocale('uz', {
+ months : 'январ_феврал_март_апрел_май_июн_июл_август_сентябр_октябр_ноябр_декабр'.split('_'),
+ monthsShort : 'янв_фев_мар_апр_май_июн_июл_авг_сен_окт_ноя_дек'.split('_'),
+ weekdays : 'Якшанба_Душанба_Сешанба_Чоршанба_Пайшанба_Жума_Шанба'.split('_'),
+ weekdaysShort : 'Якш_Душ_Сеш_Чор_Пай_Жум_Шан'.split('_'),
+ weekdaysMin : 'Як_Ду_Се_Чо_Па_Жу_Ша'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY HH:mm',
+ LLLL : 'D MMMM YYYY, dddd HH:mm'
+ },
+ calendar : {
+ sameDay : '[Бугун соат] LT [да]',
+ nextDay : '[Эртага] LT [да]',
+ nextWeek : 'dddd [куни соат] LT [да]',
+ lastDay : '[Кеча соат] LT [да]',
+ lastWeek : '[Утган] dddd [куни соат] LT [да]',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'Якин %s ичида',
+ past : 'Бир неча %s олдин',
+ s : 'фурсат',
+ m : 'бир дакика',
+ mm : '%d дакика',
+ h : 'бир соат',
+ hh : '%d соат',
+ d : 'бир кун',
+ dd : '%d кун',
+ M : 'бир ой',
+ MM : '%d ой',
+ y : 'бир йил',
+ yy : '%d йил'
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 7 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return uz;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/vi.js b/www/wiki/resources/lib/moment/locale/vi.js
new file mode 100644
index 00000000..1adacc3a
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/vi.js
@@ -0,0 +1,79 @@
+//! moment.js locale configuration
+//! locale : Vietnamese [vi]
+//! author : Bang Nguyen : https://github.com/bangnk
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var vi = moment.defineLocale('vi', {
+ months : 'tháng 1_tháng 2_tháng 3_tháng 4_tháng 5_tháng 6_tháng 7_tháng 8_tháng 9_tháng 10_tháng 11_tháng 12'.split('_'),
+ monthsShort : 'Th01_Th02_Th03_Th04_Th05_Th06_Th07_Th08_Th09_Th10_Th11_Th12'.split('_'),
+ monthsParseExact : true,
+ weekdays : 'chủ nhật_thứ hai_thứ ba_thứ tư_thứ năm_thứ sáu_thứ bảy'.split('_'),
+ weekdaysShort : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
+ weekdaysMin : 'CN_T2_T3_T4_T5_T6_T7'.split('_'),
+ weekdaysParseExact : true,
+ meridiemParse: /sa|ch/i,
+ isPM : function (input) {
+ return /^ch$/i.test(input);
+ },
+ meridiem : function (hours, minutes, isLower) {
+ if (hours < 12) {
+ return isLower ? 'sa' : 'SA';
+ } else {
+ return isLower ? 'ch' : 'CH';
+ }
+ },
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM [năm] YYYY',
+ LLL : 'D MMMM [năm] YYYY HH:mm',
+ LLLL : 'dddd, D MMMM [năm] YYYY HH:mm',
+ l : 'DD/M/YYYY',
+ ll : 'D MMM YYYY',
+ lll : 'D MMM YYYY HH:mm',
+ llll : 'ddd, D MMM YYYY HH:mm'
+ },
+ calendar : {
+ sameDay: '[Hôm nay lúc] LT',
+ nextDay: '[Ngày mai lúc] LT',
+ nextWeek: 'dddd [tuần tới lúc] LT',
+ lastDay: '[Hôm qua lúc] LT',
+ lastWeek: 'dddd [tuần rồi lúc] LT',
+ sameElse: 'L'
+ },
+ relativeTime : {
+ future : '%s tới',
+ past : '%s trước',
+ s : 'vài giây',
+ m : 'một phút',
+ mm : '%d phút',
+ h : 'một giờ',
+ hh : '%d giờ',
+ d : 'một ngày',
+ dd : '%d ngày',
+ M : 'một tháng',
+ MM : '%d tháng',
+ y : 'một năm',
+ yy : '%d năm'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}/,
+ ordinal : function (number) {
+ return number;
+ },
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return vi;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/yo.js b/www/wiki/resources/lib/moment/locale/yo.js
new file mode 100644
index 00000000..ec28a912
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/yo.js
@@ -0,0 +1,60 @@
+//! moment.js locale configuration
+//! locale : Yoruba Nigeria [yo]
+//! author : Atolagbe Abisoye : https://github.com/andela-batolagbe
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var yo = moment.defineLocale('yo', {
+ months : 'Sẹ́rẹ́_Èrèlè_Ẹrẹ̀nà_Ìgbé_Èbibi_Òkùdu_Agẹmo_Ògún_Owewe_Ọ̀wàrà_Bélú_Ọ̀pẹ̀̀'.split('_'),
+ monthsShort : 'Sẹ́r_Èrl_Ẹrn_Ìgb_Èbi_Òkù_Agẹ_Ògú_Owe_Ọ̀wà_Bél_Ọ̀pẹ̀̀'.split('_'),
+ weekdays : 'Àìkú_Ajé_Ìsẹ́gun_Ọjọ́rú_Ọjọ́bọ_Ẹtì_Àbámẹ́ta'.split('_'),
+ weekdaysShort : 'Àìk_Ajé_Ìsẹ́_Ọjr_Ọjb_Ẹtì_Àbá'.split('_'),
+ weekdaysMin : 'Àì_Aj_Ìs_Ọr_Ọb_Ẹt_Àb'.split('_'),
+ longDateFormat : {
+ LT : 'h:mm A',
+ LTS : 'h:mm:ss A',
+ L : 'DD/MM/YYYY',
+ LL : 'D MMMM YYYY',
+ LLL : 'D MMMM YYYY h:mm A',
+ LLLL : 'dddd, D MMMM YYYY h:mm A'
+ },
+ calendar : {
+ sameDay : '[Ònì ni] LT',
+ nextDay : '[Ọ̀la ni] LT',
+ nextWeek : 'dddd [Ọsẹ̀ tón\'bọ] [ni] LT',
+ lastDay : '[Àna ni] LT',
+ lastWeek : 'dddd [Ọsẹ̀ tólọ́] [ni] LT',
+ sameElse : 'L'
+ },
+ relativeTime : {
+ future : 'ní %s',
+ past : '%s kọjá',
+ s : 'ìsẹjú aayá die',
+ m : 'ìsẹjú kan',
+ mm : 'ìsẹjú %d',
+ h : 'wákati kan',
+ hh : 'wákati %d',
+ d : 'ọjọ́ kan',
+ dd : 'ọjọ́ %d',
+ M : 'osù kan',
+ MM : 'osù %d',
+ y : 'ọdún kan',
+ yy : 'ọdún %d'
+ },
+ dayOfMonthOrdinalParse : /ọjọ́\s\d{1,2}/,
+ ordinal : 'ọjọ́ %d',
+ week : {
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return yo;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/zh-cn.js b/www/wiki/resources/lib/moment/locale/zh-cn.js
new file mode 100644
index 00000000..005e941f
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/zh-cn.js
@@ -0,0 +1,111 @@
+//! moment.js locale configuration
+//! locale : Chinese (China) [zh-cn]
+//! author : suupic : https://github.com/suupic
+//! author : Zeno Zeng : https://github.com/zenozeng
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var zhCn = moment.defineLocale('zh-cn', {
+ months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
+ monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+ weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
+ weekdaysShort : '周日_周一_周二_周三_周四_周五_周六'.split('_'),
+ weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY年MMMD日',
+ LL : 'YYYY年MMMD日',
+ LLL : 'YYYY年MMMD日Ah点mm分',
+ LLLL : 'YYYY年MMMD日ddddAh点mm分',
+ l : 'YYYY年MMMD日',
+ ll : 'YYYY年MMMD日',
+ lll : 'YYYY年MMMD日 HH:mm',
+ llll : 'YYYY年MMMD日dddd HH:mm'
+ },
+ meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
+ meridiemHour: function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === '凌晨' || meridiem === '早上' ||
+ meridiem === '上午') {
+ return hour;
+ } else if (meridiem === '下午' || meridiem === '晚上') {
+ return hour + 12;
+ } else {
+ // '中午'
+ return hour >= 11 ? hour : hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ var hm = hour * 100 + minute;
+ if (hm < 600) {
+ return '凌晨';
+ } else if (hm < 900) {
+ return '早上';
+ } else if (hm < 1130) {
+ return '上午';
+ } else if (hm < 1230) {
+ return '中午';
+ } else if (hm < 1800) {
+ return '下午';
+ } else {
+ return '晚上';
+ }
+ },
+ calendar : {
+ sameDay : '[今天]LT',
+ nextDay : '[明天]LT',
+ nextWeek : '[下]ddddLT',
+ lastDay : '[昨天]LT',
+ lastWeek : '[上]ddddLT',
+ sameElse : 'L'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(日|月|周)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ case 'd':
+ case 'D':
+ case 'DDD':
+ return number + '日';
+ case 'M':
+ return number + '月';
+ case 'w':
+ case 'W':
+ return number + '周';
+ default:
+ return number;
+ }
+ },
+ relativeTime : {
+ future : '%s内',
+ past : '%s前',
+ s : '几秒',
+ m : '1 分钟',
+ mm : '%d 分钟',
+ h : '1 小时',
+ hh : '%d 小时',
+ d : '1 天',
+ dd : '%d 天',
+ M : '1 个月',
+ MM : '%d 个月',
+ y : '1 年',
+ yy : '%d 年'
+ },
+ week : {
+ // GB/T 7408-1994《数据元和交换格式·信息交换·日期和时间表示法》与ISO 8601:1988等效
+ dow : 1, // Monday is the first day of the week.
+ doy : 4 // The week that contains Jan 4th is the first week of the year.
+ }
+});
+
+return zhCn;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/zh-hk.js b/www/wiki/resources/lib/moment/locale/zh-hk.js
new file mode 100644
index 00000000..5ded143d
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/zh-hk.js
@@ -0,0 +1,105 @@
+//! moment.js locale configuration
+//! locale : Chinese (Hong Kong) [zh-hk]
+//! author : Ben : https://github.com/ben-lin
+//! author : Chris Lam : https://github.com/hehachris
+//! author : Konstantin : https://github.com/skfd
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var zhHk = moment.defineLocale('zh-hk', {
+ months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
+ monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+ weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
+ weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'),
+ weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY年MMMD日',
+ LL : 'YYYY年MMMD日',
+ LLL : 'YYYY年MMMD日 HH:mm',
+ LLLL : 'YYYY年MMMD日dddd HH:mm',
+ l : 'YYYY年MMMD日',
+ ll : 'YYYY年MMMD日',
+ lll : 'YYYY年MMMD日 HH:mm',
+ llll : 'YYYY年MMMD日dddd HH:mm'
+ },
+ meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') {
+ return hour;
+ } else if (meridiem === '中午') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === '下午' || meridiem === '晚上') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ var hm = hour * 100 + minute;
+ if (hm < 600) {
+ return '凌晨';
+ } else if (hm < 900) {
+ return '早上';
+ } else if (hm < 1130) {
+ return '上午';
+ } else if (hm < 1230) {
+ return '中午';
+ } else if (hm < 1800) {
+ return '下午';
+ } else {
+ return '晚上';
+ }
+ },
+ calendar : {
+ sameDay : '[今天]LT',
+ nextDay : '[明天]LT',
+ nextWeek : '[下]ddddLT',
+ lastDay : '[昨天]LT',
+ lastWeek : '[上]ddddLT',
+ sameElse : 'L'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(日|月|週)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ case 'd' :
+ case 'D' :
+ case 'DDD' :
+ return number + '日';
+ case 'M' :
+ return number + '月';
+ case 'w' :
+ case 'W' :
+ return number + '週';
+ default :
+ return number;
+ }
+ },
+ relativeTime : {
+ future : '%s內',
+ past : '%s前',
+ s : '幾秒',
+ m : '1 分鐘',
+ mm : '%d 分鐘',
+ h : '1 小時',
+ hh : '%d 小時',
+ d : '1 天',
+ dd : '%d 天',
+ M : '1 個月',
+ MM : '%d 個月',
+ y : '1 年',
+ yy : '%d 年'
+ }
+});
+
+return zhHk;
+
+})));
diff --git a/www/wiki/resources/lib/moment/locale/zh-tw.js b/www/wiki/resources/lib/moment/locale/zh-tw.js
new file mode 100644
index 00000000..50a6b6a4
--- /dev/null
+++ b/www/wiki/resources/lib/moment/locale/zh-tw.js
@@ -0,0 +1,104 @@
+//! moment.js locale configuration
+//! locale : Chinese (Taiwan) [zh-tw]
+//! author : Ben : https://github.com/ben-lin
+//! author : Chris Lam : https://github.com/hehachris
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined'
+ && typeof require === 'function' ? factory(require('../moment')) :
+ typeof define === 'function' && define.amd ? define(['../moment'], factory) :
+ factory(global.moment)
+}(this, (function (moment) { 'use strict';
+
+
+var zhTw = moment.defineLocale('zh-tw', {
+ months : '一月_二月_三月_四月_五月_六月_七月_八月_九月_十月_十一月_十二月'.split('_'),
+ monthsShort : '1月_2月_3月_4月_5月_6月_7月_8月_9月_10月_11月_12月'.split('_'),
+ weekdays : '星期日_星期一_星期二_星期三_星期四_星期五_星期六'.split('_'),
+ weekdaysShort : '週日_週一_週二_週三_週四_週五_週六'.split('_'),
+ weekdaysMin : '日_一_二_三_四_五_六'.split('_'),
+ longDateFormat : {
+ LT : 'HH:mm',
+ LTS : 'HH:mm:ss',
+ L : 'YYYY年MMMD日',
+ LL : 'YYYY年MMMD日',
+ LLL : 'YYYY年MMMD日 HH:mm',
+ LLLL : 'YYYY年MMMD日dddd HH:mm',
+ l : 'YYYY年MMMD日',
+ ll : 'YYYY年MMMD日',
+ lll : 'YYYY年MMMD日 HH:mm',
+ llll : 'YYYY年MMMD日dddd HH:mm'
+ },
+ meridiemParse: /凌晨|早上|上午|中午|下午|晚上/,
+ meridiemHour : function (hour, meridiem) {
+ if (hour === 12) {
+ hour = 0;
+ }
+ if (meridiem === '凌晨' || meridiem === '早上' || meridiem === '上午') {
+ return hour;
+ } else if (meridiem === '中午') {
+ return hour >= 11 ? hour : hour + 12;
+ } else if (meridiem === '下午' || meridiem === '晚上') {
+ return hour + 12;
+ }
+ },
+ meridiem : function (hour, minute, isLower) {
+ var hm = hour * 100 + minute;
+ if (hm < 600) {
+ return '凌晨';
+ } else if (hm < 900) {
+ return '早上';
+ } else if (hm < 1130) {
+ return '上午';
+ } else if (hm < 1230) {
+ return '中午';
+ } else if (hm < 1800) {
+ return '下午';
+ } else {
+ return '晚上';
+ }
+ },
+ calendar : {
+ sameDay : '[今天]LT',
+ nextDay : '[明天]LT',
+ nextWeek : '[下]ddddLT',
+ lastDay : '[昨天]LT',
+ lastWeek : '[上]ddddLT',
+ sameElse : 'L'
+ },
+ dayOfMonthOrdinalParse: /\d{1,2}(日|月|週)/,
+ ordinal : function (number, period) {
+ switch (period) {
+ case 'd' :
+ case 'D' :
+ case 'DDD' :
+ return number + '日';
+ case 'M' :
+ return number + '月';
+ case 'w' :
+ case 'W' :
+ return number + '週';
+ default :
+ return number;
+ }
+ },
+ relativeTime : {
+ future : '%s內',
+ past : '%s前',
+ s : '幾秒',
+ m : '1 分鐘',
+ mm : '%d 分鐘',
+ h : '1 小時',
+ hh : '%d 小時',
+ d : '1 天',
+ dd : '%d 天',
+ M : '1 個月',
+ MM : '%d 個月',
+ y : '1 年',
+ yy : '%d 年'
+ }
+});
+
+return zhTw;
+
+})));
diff --git a/www/wiki/resources/lib/moment/moment.js b/www/wiki/resources/lib/moment/moment.js
new file mode 100644
index 00000000..9dd31d13
--- /dev/null
+++ b/www/wiki/resources/lib/moment/moment.js
@@ -0,0 +1,4515 @@
+//! moment.js
+//! version : 2.19.3
+//! authors : Tim Wood, Iskren Chernev, Moment.js contributors
+//! license : MIT
+//! momentjs.com
+
+;(function (global, factory) {
+ typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
+ typeof define === 'function' && define.amd ? define(factory) :
+ global.moment = factory()
+}(this, (function () { 'use strict';
+
+var hookCallback;
+
+function hooks () {
+ return hookCallback.apply(null, arguments);
+}
+
+// This is done to register the method called with moment()
+// without creating circular dependencies.
+function setHookCallback (callback) {
+ hookCallback = callback;
+}
+
+function isArray(input) {
+ return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]';
+}
+
+function isObject(input) {
+ // IE8 will treat undefined and null as object if it wasn't for
+ // input != null
+ return input != null && Object.prototype.toString.call(input) === '[object Object]';
+}
+
+function isObjectEmpty(obj) {
+ if (Object.getOwnPropertyNames) {
+ return (Object.getOwnPropertyNames(obj).length === 0);
+ } else {
+ var k;
+ for (k in obj) {
+ if (obj.hasOwnProperty(k)) {
+ return false;
+ }
+ }
+ return true;
+ }
+}
+
+function isUndefined(input) {
+ return input === void 0;
+}
+
+function isNumber(input) {
+ return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]';
+}
+
+function isDate(input) {
+ return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]';
+}
+
+function map(arr, fn) {
+ var res = [], i;
+ for (i = 0; i < arr.length; ++i) {
+ res.push(fn(arr[i], i));
+ }
+ return res;
+}
+
+function hasOwnProp(a, b) {
+ return Object.prototype.hasOwnProperty.call(a, b);
+}
+
+function extend(a, b) {
+ for (var i in b) {
+ if (hasOwnProp(b, i)) {
+ a[i] = b[i];
+ }
+ }
+
+ if (hasOwnProp(b, 'toString')) {
+ a.toString = b.toString;
+ }
+
+ if (hasOwnProp(b, 'valueOf')) {
+ a.valueOf = b.valueOf;
+ }
+
+ return a;
+}
+
+function createUTC (input, format, locale, strict) {
+ return createLocalOrUTC(input, format, locale, strict, true).utc();
+}
+
+function defaultParsingFlags() {
+ // We need to deep clone this object.
+ return {
+ empty : false,
+ unusedTokens : [],
+ unusedInput : [],
+ overflow : -2,
+ charsLeftOver : 0,
+ nullInput : false,
+ invalidMonth : null,
+ invalidFormat : false,
+ userInvalidated : false,
+ iso : false,
+ parsedDateParts : [],
+ meridiem : null,
+ rfc2822 : false,
+ weekdayMismatch : false
+ };
+}
+
+function getParsingFlags(m) {
+ if (m._pf == null) {
+ m._pf = defaultParsingFlags();
+ }
+ return m._pf;
+}
+
+var some;
+if (Array.prototype.some) {
+ some = Array.prototype.some;
+} else {
+ some = function (fun) {
+ var t = Object(this);
+ var len = t.length >>> 0;
+
+ for (var i = 0; i < len; i++) {
+ if (i in t && fun.call(this, t[i], i, t)) {
+ return true;
+ }
+ }
+
+ return false;
+ };
+}
+
+function isValid(m) {
+ if (m._isValid == null) {
+ var flags = getParsingFlags(m);
+ var parsedParts = some.call(flags.parsedDateParts, function (i) {
+ return i != null;
+ });
+ var isNowValid = !isNaN(m._d.getTime()) &&
+ flags.overflow < 0 &&
+ !flags.empty &&
+ !flags.invalidMonth &&
+ !flags.invalidWeekday &&
+ !flags.weekdayMismatch &&
+ !flags.nullInput &&
+ !flags.invalidFormat &&
+ !flags.userInvalidated &&
+ (!flags.meridiem || (flags.meridiem && parsedParts));
+
+ if (m._strict) {
+ isNowValid = isNowValid &&
+ flags.charsLeftOver === 0 &&
+ flags.unusedTokens.length === 0 &&
+ flags.bigHour === undefined;
+ }
+
+ if (Object.isFrozen == null || !Object.isFrozen(m)) {
+ m._isValid = isNowValid;
+ }
+ else {
+ return isNowValid;
+ }
+ }
+ return m._isValid;
+}
+
+function createInvalid (flags) {
+ var m = createUTC(NaN);
+ if (flags != null) {
+ extend(getParsingFlags(m), flags);
+ }
+ else {
+ getParsingFlags(m).userInvalidated = true;
+ }
+
+ return m;
+}
+
+// Plugins that add properties should also add the key here (null value),
+// so we can properly clone ourselves.
+var momentProperties = hooks.momentProperties = [];
+
+function copyConfig(to, from) {
+ var i, prop, val;
+
+ if (!isUndefined(from._isAMomentObject)) {
+ to._isAMomentObject = from._isAMomentObject;
+ }
+ if (!isUndefined(from._i)) {
+ to._i = from._i;
+ }
+ if (!isUndefined(from._f)) {
+ to._f = from._f;
+ }
+ if (!isUndefined(from._l)) {
+ to._l = from._l;
+ }
+ if (!isUndefined(from._strict)) {
+ to._strict = from._strict;
+ }
+ if (!isUndefined(from._tzm)) {
+ to._tzm = from._tzm;
+ }
+ if (!isUndefined(from._isUTC)) {
+ to._isUTC = from._isUTC;
+ }
+ if (!isUndefined(from._offset)) {
+ to._offset = from._offset;
+ }
+ if (!isUndefined(from._pf)) {
+ to._pf = getParsingFlags(from);
+ }
+ if (!isUndefined(from._locale)) {
+ to._locale = from._locale;
+ }
+
+ if (momentProperties.length > 0) {
+ for (i = 0; i < momentProperties.length; i++) {
+ prop = momentProperties[i];
+ val = from[prop];
+ if (!isUndefined(val)) {
+ to[prop] = val;
+ }
+ }
+ }
+
+ return to;
+}
+
+var updateInProgress = false;
+
+// Moment prototype object
+function Moment(config) {
+ copyConfig(this, config);
+ this._d = new Date(config._d != null ? config._d.getTime() : NaN);
+ if (!this.isValid()) {
+ this._d = new Date(NaN);
+ }
+ // Prevent infinite loop in case updateOffset creates new moment
+ // objects.
+ if (updateInProgress === false) {
+ updateInProgress = true;
+ hooks.updateOffset(this);
+ updateInProgress = false;
+ }
+}
+
+function isMoment (obj) {
+ return obj instanceof Moment || (obj != null && obj._isAMomentObject != null);
+}
+
+function absFloor (number) {
+ if (number < 0) {
+ // -0 -> 0
+ return Math.ceil(number) || 0;
+ } else {
+ return Math.floor(number);
+ }
+}
+
+function toInt(argumentForCoercion) {
+ var coercedNumber = +argumentForCoercion,
+ value = 0;
+
+ if (coercedNumber !== 0 && isFinite(coercedNumber)) {
+ value = absFloor(coercedNumber);
+ }
+
+ return value;
+}
+
+// compare two arrays, return the number of differences
+function compareArrays(array1, array2, dontConvert) {
+ var len = Math.min(array1.length, array2.length),
+ lengthDiff = Math.abs(array1.length - array2.length),
+ diffs = 0,
+ i;
+ for (i = 0; i < len; i++) {
+ if ((dontConvert && array1[i] !== array2[i]) ||
+ (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) {
+ diffs++;
+ }
+ }
+ return diffs + lengthDiff;
+}
+
+function warn(msg) {
+ if (hooks.suppressDeprecationWarnings === false &&
+ (typeof console !== 'undefined') && console.warn) {
+ console.warn('Deprecation warning: ' + msg);
+ }
+}
+
+function deprecate(msg, fn) {
+ var firstTime = true;
+
+ return extend(function () {
+ if (hooks.deprecationHandler != null) {
+ hooks.deprecationHandler(null, msg);
+ }
+ if (firstTime) {
+ var args = [];
+ var arg;
+ for (var i = 0; i < arguments.length; i++) {
+ arg = '';
+ if (typeof arguments[i] === 'object') {
+ arg += '\n[' + i + '] ';
+ for (var key in arguments[0]) {
+ arg += key + ': ' + arguments[0][key] + ', ';
+ }
+ arg = arg.slice(0, -2); // Remove trailing comma and space
+ } else {
+ arg = arguments[i];
+ }
+ args.push(arg);
+ }
+ warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack);
+ firstTime = false;
+ }
+ return fn.apply(this, arguments);
+ }, fn);
+}
+
+var deprecations = {};
+
+function deprecateSimple(name, msg) {
+ if (hooks.deprecationHandler != null) {
+ hooks.deprecationHandler(name, msg);
+ }
+ if (!deprecations[name]) {
+ warn(msg);
+ deprecations[name] = true;
+ }
+}
+
+hooks.suppressDeprecationWarnings = false;
+hooks.deprecationHandler = null;
+
+function isFunction(input) {
+ return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]';
+}
+
+function set (config) {
+ var prop, i;
+ for (i in config) {
+ prop = config[i];
+ if (isFunction(prop)) {
+ this[i] = prop;
+ } else {
+ this['_' + i] = prop;
+ }
+ }
+ this._config = config;
+ // Lenient ordinal parsing accepts just a number in addition to
+ // number + (possibly) stuff coming from _dayOfMonthOrdinalParse.
+ // TODO: Remove "ordinalParse" fallback in next major release.
+ this._dayOfMonthOrdinalParseLenient = new RegExp(
+ (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) +
+ '|' + (/\d{1,2}/).source);
+}
+
+function mergeConfigs(parentConfig, childConfig) {
+ var res = extend({}, parentConfig), prop;
+ for (prop in childConfig) {
+ if (hasOwnProp(childConfig, prop)) {
+ if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) {
+ res[prop] = {};
+ extend(res[prop], parentConfig[prop]);
+ extend(res[prop], childConfig[prop]);
+ } else if (childConfig[prop] != null) {
+ res[prop] = childConfig[prop];
+ } else {
+ delete res[prop];
+ }
+ }
+ }
+ for (prop in parentConfig) {
+ if (hasOwnProp(parentConfig, prop) &&
+ !hasOwnProp(childConfig, prop) &&
+ isObject(parentConfig[prop])) {
+ // make sure changes to properties don't modify parent config
+ res[prop] = extend({}, res[prop]);
+ }
+ }
+ return res;
+}
+
+function Locale(config) {
+ if (config != null) {
+ this.set(config);
+ }
+}
+
+var keys;
+
+if (Object.keys) {
+ keys = Object.keys;
+} else {
+ keys = function (obj) {
+ var i, res = [];
+ for (i in obj) {
+ if (hasOwnProp(obj, i)) {
+ res.push(i);
+ }
+ }
+ return res;
+ };
+}
+
+var defaultCalendar = {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[Last] dddd [at] LT',
+ sameElse : 'L'
+};
+
+function calendar (key, mom, now) {
+ var output = this._calendar[key] || this._calendar['sameElse'];
+ return isFunction(output) ? output.call(mom, now) : output;
+}
+
+var defaultLongDateFormat = {
+ LTS : 'h:mm:ss A',
+ LT : 'h:mm A',
+ L : 'MM/DD/YYYY',
+ LL : 'MMMM D, YYYY',
+ LLL : 'MMMM D, YYYY h:mm A',
+ LLLL : 'dddd, MMMM D, YYYY h:mm A'
+};
+
+function longDateFormat (key) {
+ var format = this._longDateFormat[key],
+ formatUpper = this._longDateFormat[key.toUpperCase()];
+
+ if (format || !formatUpper) {
+ return format;
+ }
+
+ this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) {
+ return val.slice(1);
+ });
+
+ return this._longDateFormat[key];
+}
+
+var defaultInvalidDate = 'Invalid date';
+
+function invalidDate () {
+ return this._invalidDate;
+}
+
+var defaultOrdinal = '%d';
+var defaultDayOfMonthOrdinalParse = /\d{1,2}/;
+
+function ordinal (number) {
+ return this._ordinal.replace('%d', number);
+}
+
+var defaultRelativeTime = {
+ future : 'in %s',
+ past : '%s ago',
+ s : 'a few seconds',
+ ss : '%d seconds',
+ m : 'a minute',
+ mm : '%d minutes',
+ h : 'an hour',
+ hh : '%d hours',
+ d : 'a day',
+ dd : '%d days',
+ M : 'a month',
+ MM : '%d months',
+ y : 'a year',
+ yy : '%d years'
+};
+
+function relativeTime (number, withoutSuffix, string, isFuture) {
+ var output = this._relativeTime[string];
+ return (isFunction(output)) ?
+ output(number, withoutSuffix, string, isFuture) :
+ output.replace(/%d/i, number);
+}
+
+function pastFuture (diff, output) {
+ var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
+ return isFunction(format) ? format(output) : format.replace(/%s/i, output);
+}
+
+var aliases = {};
+
+function addUnitAlias (unit, shorthand) {
+ var lowerCase = unit.toLowerCase();
+ aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit;
+}
+
+function normalizeUnits(units) {
+ return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined;
+}
+
+function normalizeObjectUnits(inputObject) {
+ var normalizedInput = {},
+ normalizedProp,
+ prop;
+
+ for (prop in inputObject) {
+ if (hasOwnProp(inputObject, prop)) {
+ normalizedProp = normalizeUnits(prop);
+ if (normalizedProp) {
+ normalizedInput[normalizedProp] = inputObject[prop];
+ }
+ }
+ }
+
+ return normalizedInput;
+}
+
+var priorities = {};
+
+function addUnitPriority(unit, priority) {
+ priorities[unit] = priority;
+}
+
+function getPrioritizedUnits(unitsObj) {
+ var units = [];
+ for (var u in unitsObj) {
+ units.push({unit: u, priority: priorities[u]});
+ }
+ units.sort(function (a, b) {
+ return a.priority - b.priority;
+ });
+ return units;
+}
+
+function zeroFill(number, targetLength, forceSign) {
+ var absNumber = '' + Math.abs(number),
+ zerosToFill = targetLength - absNumber.length,
+ sign = number >= 0;
+ return (sign ? (forceSign ? '+' : '') : '-') +
+ Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber;
+}
+
+var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g;
+
+var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g;
+
+var formatFunctions = {};
+
+var formatTokenFunctions = {};
+
+// token: 'M'
+// padded: ['MM', 2]
+// ordinal: 'Mo'
+// callback: function () { this.month() + 1 }
+function addFormatToken (token, padded, ordinal, callback) {
+ var func = callback;
+ if (typeof callback === 'string') {
+ func = function () {
+ return this[callback]();
+ };
+ }
+ if (token) {
+ formatTokenFunctions[token] = func;
+ }
+ if (padded) {
+ formatTokenFunctions[padded[0]] = function () {
+ return zeroFill(func.apply(this, arguments), padded[1], padded[2]);
+ };
+ }
+ if (ordinal) {
+ formatTokenFunctions[ordinal] = function () {
+ return this.localeData().ordinal(func.apply(this, arguments), token);
+ };
+ }
+}
+
+function removeFormattingTokens(input) {
+ if (input.match(/\[[\s\S]/)) {
+ return input.replace(/^\[|\]$/g, '');
+ }
+ return input.replace(/\\/g, '');
+}
+
+function makeFormatFunction(format) {
+ var array = format.match(formattingTokens), i, length;
+
+ for (i = 0, length = array.length; i < length; i++) {
+ if (formatTokenFunctions[array[i]]) {
+ array[i] = formatTokenFunctions[array[i]];
+ } else {
+ array[i] = removeFormattingTokens(array[i]);
+ }
+ }
+
+ return function (mom) {
+ var output = '', i;
+ for (i = 0; i < length; i++) {
+ output += isFunction(array[i]) ? array[i].call(mom, format) : array[i];
+ }
+ return output;
+ };
+}
+
+// format date using native date object
+function formatMoment(m, format) {
+ if (!m.isValid()) {
+ return m.localeData().invalidDate();
+ }
+
+ format = expandFormat(format, m.localeData());
+ formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format);
+
+ return formatFunctions[format](m);
+}
+
+function expandFormat(format, locale) {
+ var i = 5;
+
+ function replaceLongDateFormatTokens(input) {
+ return locale.longDateFormat(input) || input;
+ }
+
+ localFormattingTokens.lastIndex = 0;
+ while (i >= 0 && localFormattingTokens.test(format)) {
+ format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
+ localFormattingTokens.lastIndex = 0;
+ i -= 1;
+ }
+
+ return format;
+}
+
+var match1 = /\d/; // 0 - 9
+var match2 = /\d\d/; // 00 - 99
+var match3 = /\d{3}/; // 000 - 999
+var match4 = /\d{4}/; // 0000 - 9999
+var match6 = /[+-]?\d{6}/; // -999999 - 999999
+var match1to2 = /\d\d?/; // 0 - 99
+var match3to4 = /\d\d\d\d?/; // 999 - 9999
+var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999
+var match1to3 = /\d{1,3}/; // 0 - 999
+var match1to4 = /\d{1,4}/; // 0 - 9999
+var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999
+
+var matchUnsigned = /\d+/; // 0 - inf
+var matchSigned = /[+-]?\d+/; // -inf - inf
+
+var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z
+var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z
+
+var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123
+
+// any word (or two) characters or numbers including two/three word month in arabic.
+// includes scottish gaelic two word and hyphenated months
+var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;
+
+
+var regexes = {};
+
+function addRegexToken (token, regex, strictRegex) {
+ regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) {
+ return (isStrict && strictRegex) ? strictRegex : regex;
+ };
+}
+
+function getParseRegexForToken (token, config) {
+ if (!hasOwnProp(regexes, token)) {
+ return new RegExp(unescapeFormat(token));
+ }
+
+ return regexes[token](config._strict, config._locale);
+}
+
+// Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
+function unescapeFormat(s) {
+ return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) {
+ return p1 || p2 || p3 || p4;
+ }));
+}
+
+function regexEscape(s) {
+ return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
+}
+
+var tokens = {};
+
+function addParseToken (token, callback) {
+ var i, func = callback;
+ if (typeof token === 'string') {
+ token = [token];
+ }
+ if (isNumber(callback)) {
+ func = function (input, array) {
+ array[callback] = toInt(input);
+ };
+ }
+ for (i = 0; i < token.length; i++) {
+ tokens[token[i]] = func;
+ }
+}
+
+function addWeekParseToken (token, callback) {
+ addParseToken(token, function (input, array, config, token) {
+ config._w = config._w || {};
+ callback(input, config._w, config, token);
+ });
+}
+
+function addTimeToArrayFromToken(token, input, config) {
+ if (input != null && hasOwnProp(tokens, token)) {
+ tokens[token](input, config._a, config, token);
+ }
+}
+
+var YEAR = 0;
+var MONTH = 1;
+var DATE = 2;
+var HOUR = 3;
+var MINUTE = 4;
+var SECOND = 5;
+var MILLISECOND = 6;
+var WEEK = 7;
+var WEEKDAY = 8;
+
+// FORMATTING
+
+addFormatToken('Y', 0, 0, function () {
+ var y = this.year();
+ return y <= 9999 ? '' + y : '+' + y;
+});
+
+addFormatToken(0, ['YY', 2], 0, function () {
+ return this.year() % 100;
+});
+
+addFormatToken(0, ['YYYY', 4], 0, 'year');
+addFormatToken(0, ['YYYYY', 5], 0, 'year');
+addFormatToken(0, ['YYYYYY', 6, true], 0, 'year');
+
+// ALIASES
+
+addUnitAlias('year', 'y');
+
+// PRIORITIES
+
+addUnitPriority('year', 1);
+
+// PARSING
+
+addRegexToken('Y', matchSigned);
+addRegexToken('YY', match1to2, match2);
+addRegexToken('YYYY', match1to4, match4);
+addRegexToken('YYYYY', match1to6, match6);
+addRegexToken('YYYYYY', match1to6, match6);
+
+addParseToken(['YYYYY', 'YYYYYY'], YEAR);
+addParseToken('YYYY', function (input, array) {
+ array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input);
+});
+addParseToken('YY', function (input, array) {
+ array[YEAR] = hooks.parseTwoDigitYear(input);
+});
+addParseToken('Y', function (input, array) {
+ array[YEAR] = parseInt(input, 10);
+});
+
+// HELPERS
+
+function daysInYear(year) {
+ return isLeapYear(year) ? 366 : 365;
+}
+
+function isLeapYear(year) {
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+}
+
+// HOOKS
+
+hooks.parseTwoDigitYear = function (input) {
+ return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
+};
+
+// MOMENTS
+
+var getSetYear = makeGetSet('FullYear', true);
+
+function getIsLeapYear () {
+ return isLeapYear(this.year());
+}
+
+function makeGetSet (unit, keepTime) {
+ return function (value) {
+ if (value != null) {
+ set$1(this, unit, value);
+ hooks.updateOffset(this, keepTime);
+ return this;
+ } else {
+ return get(this, unit);
+ }
+ };
+}
+
+function get (mom, unit) {
+ return mom.isValid() ?
+ mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN;
+}
+
+function set$1 (mom, unit, value) {
+ if (mom.isValid() && !isNaN(value)) {
+ if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) {
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month()));
+ }
+ else {
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
+ }
+ }
+}
+
+// MOMENTS
+
+function stringGet (units) {
+ units = normalizeUnits(units);
+ if (isFunction(this[units])) {
+ return this[units]();
+ }
+ return this;
+}
+
+
+function stringSet (units, value) {
+ if (typeof units === 'object') {
+ units = normalizeObjectUnits(units);
+ var prioritized = getPrioritizedUnits(units);
+ for (var i = 0; i < prioritized.length; i++) {
+ this[prioritized[i].unit](units[prioritized[i].unit]);
+ }
+ } else {
+ units = normalizeUnits(units);
+ if (isFunction(this[units])) {
+ return this[units](value);
+ }
+ }
+ return this;
+}
+
+function mod(n, x) {
+ return ((n % x) + x) % x;
+}
+
+var indexOf;
+
+if (Array.prototype.indexOf) {
+ indexOf = Array.prototype.indexOf;
+} else {
+ indexOf = function (o) {
+ // I know
+ var i;
+ for (i = 0; i < this.length; ++i) {
+ if (this[i] === o) {
+ return i;
+ }
+ }
+ return -1;
+ };
+}
+
+function daysInMonth(year, month) {
+ if (isNaN(year) || isNaN(month)) {
+ return NaN;
+ }
+ var modMonth = mod(month, 12);
+ year += (month - modMonth) / 12;
+ return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2);
+}
+
+// FORMATTING
+
+addFormatToken('M', ['MM', 2], 'Mo', function () {
+ return this.month() + 1;
+});
+
+addFormatToken('MMM', 0, 0, function (format) {
+ return this.localeData().monthsShort(this, format);
+});
+
+addFormatToken('MMMM', 0, 0, function (format) {
+ return this.localeData().months(this, format);
+});
+
+// ALIASES
+
+addUnitAlias('month', 'M');
+
+// PRIORITY
+
+addUnitPriority('month', 8);
+
+// PARSING
+
+addRegexToken('M', match1to2);
+addRegexToken('MM', match1to2, match2);
+addRegexToken('MMM', function (isStrict, locale) {
+ return locale.monthsShortRegex(isStrict);
+});
+addRegexToken('MMMM', function (isStrict, locale) {
+ return locale.monthsRegex(isStrict);
+});
+
+addParseToken(['M', 'MM'], function (input, array) {
+ array[MONTH] = toInt(input) - 1;
+});
+
+addParseToken(['MMM', 'MMMM'], function (input, array, config, token) {
+ var month = config._locale.monthsParse(input, token, config._strict);
+ // if we didn't find a month name, mark the date as invalid.
+ if (month != null) {
+ array[MONTH] = month;
+ } else {
+ getParsingFlags(config).invalidMonth = input;
+ }
+});
+
+// LOCALES
+
+var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/;
+var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_');
+function localeMonths (m, format) {
+ if (!m) {
+ return isArray(this._months) ? this._months :
+ this._months['standalone'];
+ }
+ return isArray(this._months) ? this._months[m.month()] :
+ this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()];
+}
+
+var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_');
+function localeMonthsShort (m, format) {
+ if (!m) {
+ return isArray(this._monthsShort) ? this._monthsShort :
+ this._monthsShort['standalone'];
+ }
+ return isArray(this._monthsShort) ? this._monthsShort[m.month()] :
+ this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()];
+}
+
+function handleStrictParse(monthName, format, strict) {
+ var i, ii, mom, llc = monthName.toLocaleLowerCase();
+ if (!this._monthsParse) {
+ // this is not used
+ this._monthsParse = [];
+ this._longMonthsParse = [];
+ this._shortMonthsParse = [];
+ for (i = 0; i < 12; ++i) {
+ mom = createUTC([2000, i]);
+ this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase();
+ this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase();
+ }
+ }
+
+ if (strict) {
+ if (format === 'MMM') {
+ ii = indexOf.call(this._shortMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._longMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ } else {
+ if (format === 'MMM') {
+ ii = indexOf.call(this._shortMonthsParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._longMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._longMonthsParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._shortMonthsParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ }
+}
+
+function localeMonthsParse (monthName, format, strict) {
+ var i, mom, regex;
+
+ if (this._monthsParseExact) {
+ return handleStrictParse.call(this, monthName, format, strict);
+ }
+
+ if (!this._monthsParse) {
+ this._monthsParse = [];
+ this._longMonthsParse = [];
+ this._shortMonthsParse = [];
+ }
+
+ // TODO: add sorting
+ // Sorting makes sure if one month (or abbr) is a prefix of another
+ // see sorting in computeMonthsParse
+ for (i = 0; i < 12; i++) {
+ // make the regex if we don't have it already
+ mom = createUTC([2000, i]);
+ if (strict && !this._longMonthsParse[i]) {
+ this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
+ this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
+ }
+ if (!strict && !this._monthsParse[i]) {
+ regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
+ this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
+ }
+ // test the regex
+ if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
+ return i;
+ } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
+ return i;
+ } else if (!strict && this._monthsParse[i].test(monthName)) {
+ return i;
+ }
+ }
+}
+
+// MOMENTS
+
+function setMonth (mom, value) {
+ var dayOfMonth;
+
+ if (!mom.isValid()) {
+ // No op
+ return mom;
+ }
+
+ if (typeof value === 'string') {
+ if (/^\d+$/.test(value)) {
+ value = toInt(value);
+ } else {
+ value = mom.localeData().monthsParse(value);
+ // TODO: Another silent failure?
+ if (!isNumber(value)) {
+ return mom;
+ }
+ }
+ }
+
+ dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value));
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
+ return mom;
+}
+
+function getSetMonth (value) {
+ if (value != null) {
+ setMonth(this, value);
+ hooks.updateOffset(this, true);
+ return this;
+ } else {
+ return get(this, 'Month');
+ }
+}
+
+function getDaysInMonth () {
+ return daysInMonth(this.year(), this.month());
+}
+
+var defaultMonthsShortRegex = matchWord;
+function monthsShortRegex (isStrict) {
+ if (this._monthsParseExact) {
+ if (!hasOwnProp(this, '_monthsRegex')) {
+ computeMonthsParse.call(this);
+ }
+ if (isStrict) {
+ return this._monthsShortStrictRegex;
+ } else {
+ return this._monthsShortRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_monthsShortRegex')) {
+ this._monthsShortRegex = defaultMonthsShortRegex;
+ }
+ return this._monthsShortStrictRegex && isStrict ?
+ this._monthsShortStrictRegex : this._monthsShortRegex;
+ }
+}
+
+var defaultMonthsRegex = matchWord;
+function monthsRegex (isStrict) {
+ if (this._monthsParseExact) {
+ if (!hasOwnProp(this, '_monthsRegex')) {
+ computeMonthsParse.call(this);
+ }
+ if (isStrict) {
+ return this._monthsStrictRegex;
+ } else {
+ return this._monthsRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_monthsRegex')) {
+ this._monthsRegex = defaultMonthsRegex;
+ }
+ return this._monthsStrictRegex && isStrict ?
+ this._monthsStrictRegex : this._monthsRegex;
+ }
+}
+
+function computeMonthsParse () {
+ function cmpLenRev(a, b) {
+ return b.length - a.length;
+ }
+
+ var shortPieces = [], longPieces = [], mixedPieces = [],
+ i, mom;
+ for (i = 0; i < 12; i++) {
+ // make the regex if we don't have it already
+ mom = createUTC([2000, i]);
+ shortPieces.push(this.monthsShort(mom, ''));
+ longPieces.push(this.months(mom, ''));
+ mixedPieces.push(this.months(mom, ''));
+ mixedPieces.push(this.monthsShort(mom, ''));
+ }
+ // Sorting makes sure if one month (or abbr) is a prefix of another it
+ // will match the longer piece.
+ shortPieces.sort(cmpLenRev);
+ longPieces.sort(cmpLenRev);
+ mixedPieces.sort(cmpLenRev);
+ for (i = 0; i < 12; i++) {
+ shortPieces[i] = regexEscape(shortPieces[i]);
+ longPieces[i] = regexEscape(longPieces[i]);
+ }
+ for (i = 0; i < 24; i++) {
+ mixedPieces[i] = regexEscape(mixedPieces[i]);
+ }
+
+ this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
+ this._monthsShortRegex = this._monthsRegex;
+ this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
+ this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
+}
+
+function createDate (y, m, d, h, M, s, ms) {
+ // can't just apply() to create a date:
+ // https://stackoverflow.com/q/181348
+ var date = new Date(y, m, d, h, M, s, ms);
+
+ // the date constructor remaps years 0-99 to 1900-1999
+ if (y < 100 && y >= 0 && isFinite(date.getFullYear())) {
+ date.setFullYear(y);
+ }
+ return date;
+}
+
+function createUTCDate (y) {
+ var date = new Date(Date.UTC.apply(null, arguments));
+
+ // the Date.UTC function remaps years 0-99 to 1900-1999
+ if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) {
+ date.setUTCFullYear(y);
+ }
+ return date;
+}
+
+// start-of-first-week - start-of-year
+function firstWeekOffset(year, dow, doy) {
+ var // first-week day -- which january is always in the first week (4 for iso, 1 for other)
+ fwd = 7 + dow - doy,
+ // first-week day local weekday -- which local weekday is fwd
+ fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7;
+
+ return -fwdlw + fwd - 1;
+}
+
+// https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
+function dayOfYearFromWeeks(year, week, weekday, dow, doy) {
+ var localWeekday = (7 + weekday - dow) % 7,
+ weekOffset = firstWeekOffset(year, dow, doy),
+ dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset,
+ resYear, resDayOfYear;
+
+ if (dayOfYear <= 0) {
+ resYear = year - 1;
+ resDayOfYear = daysInYear(resYear) + dayOfYear;
+ } else if (dayOfYear > daysInYear(year)) {
+ resYear = year + 1;
+ resDayOfYear = dayOfYear - daysInYear(year);
+ } else {
+ resYear = year;
+ resDayOfYear = dayOfYear;
+ }
+
+ return {
+ year: resYear,
+ dayOfYear: resDayOfYear
+ };
+}
+
+function weekOfYear(mom, dow, doy) {
+ var weekOffset = firstWeekOffset(mom.year(), dow, doy),
+ week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1,
+ resWeek, resYear;
+
+ if (week < 1) {
+ resYear = mom.year() - 1;
+ resWeek = week + weeksInYear(resYear, dow, doy);
+ } else if (week > weeksInYear(mom.year(), dow, doy)) {
+ resWeek = week - weeksInYear(mom.year(), dow, doy);
+ resYear = mom.year() + 1;
+ } else {
+ resYear = mom.year();
+ resWeek = week;
+ }
+
+ return {
+ week: resWeek,
+ year: resYear
+ };
+}
+
+function weeksInYear(year, dow, doy) {
+ var weekOffset = firstWeekOffset(year, dow, doy),
+ weekOffsetNext = firstWeekOffset(year + 1, dow, doy);
+ return (daysInYear(year) - weekOffset + weekOffsetNext) / 7;
+}
+
+// FORMATTING
+
+addFormatToken('w', ['ww', 2], 'wo', 'week');
+addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek');
+
+// ALIASES
+
+addUnitAlias('week', 'w');
+addUnitAlias('isoWeek', 'W');
+
+// PRIORITIES
+
+addUnitPriority('week', 5);
+addUnitPriority('isoWeek', 5);
+
+// PARSING
+
+addRegexToken('w', match1to2);
+addRegexToken('ww', match1to2, match2);
+addRegexToken('W', match1to2);
+addRegexToken('WW', match1to2, match2);
+
+addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) {
+ week[token.substr(0, 1)] = toInt(input);
+});
+
+// HELPERS
+
+// LOCALES
+
+function localeWeek (mom) {
+ return weekOfYear(mom, this._week.dow, this._week.doy).week;
+}
+
+var defaultLocaleWeek = {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+};
+
+function localeFirstDayOfWeek () {
+ return this._week.dow;
+}
+
+function localeFirstDayOfYear () {
+ return this._week.doy;
+}
+
+// MOMENTS
+
+function getSetWeek (input) {
+ var week = this.localeData().week(this);
+ return input == null ? week : this.add((input - week) * 7, 'd');
+}
+
+function getSetISOWeek (input) {
+ var week = weekOfYear(this, 1, 4).week;
+ return input == null ? week : this.add((input - week) * 7, 'd');
+}
+
+// FORMATTING
+
+addFormatToken('d', 0, 'do', 'day');
+
+addFormatToken('dd', 0, 0, function (format) {
+ return this.localeData().weekdaysMin(this, format);
+});
+
+addFormatToken('ddd', 0, 0, function (format) {
+ return this.localeData().weekdaysShort(this, format);
+});
+
+addFormatToken('dddd', 0, 0, function (format) {
+ return this.localeData().weekdays(this, format);
+});
+
+addFormatToken('e', 0, 0, 'weekday');
+addFormatToken('E', 0, 0, 'isoWeekday');
+
+// ALIASES
+
+addUnitAlias('day', 'd');
+addUnitAlias('weekday', 'e');
+addUnitAlias('isoWeekday', 'E');
+
+// PRIORITY
+addUnitPriority('day', 11);
+addUnitPriority('weekday', 11);
+addUnitPriority('isoWeekday', 11);
+
+// PARSING
+
+addRegexToken('d', match1to2);
+addRegexToken('e', match1to2);
+addRegexToken('E', match1to2);
+addRegexToken('dd', function (isStrict, locale) {
+ return locale.weekdaysMinRegex(isStrict);
+});
+addRegexToken('ddd', function (isStrict, locale) {
+ return locale.weekdaysShortRegex(isStrict);
+});
+addRegexToken('dddd', function (isStrict, locale) {
+ return locale.weekdaysRegex(isStrict);
+});
+
+addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) {
+ var weekday = config._locale.weekdaysParse(input, token, config._strict);
+ // if we didn't get a weekday name, mark the date as invalid
+ if (weekday != null) {
+ week.d = weekday;
+ } else {
+ getParsingFlags(config).invalidWeekday = input;
+ }
+});
+
+addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) {
+ week[token] = toInt(input);
+});
+
+// HELPERS
+
+function parseWeekday(input, locale) {
+ if (typeof input !== 'string') {
+ return input;
+ }
+
+ if (!isNaN(input)) {
+ return parseInt(input, 10);
+ }
+
+ input = locale.weekdaysParse(input);
+ if (typeof input === 'number') {
+ return input;
+ }
+
+ return null;
+}
+
+function parseIsoWeekday(input, locale) {
+ if (typeof input === 'string') {
+ return locale.weekdaysParse(input) % 7 || 7;
+ }
+ return isNaN(input) ? null : input;
+}
+
+// LOCALES
+
+var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_');
+function localeWeekdays (m, format) {
+ if (!m) {
+ return isArray(this._weekdays) ? this._weekdays :
+ this._weekdays['standalone'];
+ }
+ return isArray(this._weekdays) ? this._weekdays[m.day()] :
+ this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()];
+}
+
+var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_');
+function localeWeekdaysShort (m) {
+ return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort;
+}
+
+var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_');
+function localeWeekdaysMin (m) {
+ return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin;
+}
+
+function handleStrictParse$1(weekdayName, format, strict) {
+ var i, ii, mom, llc = weekdayName.toLocaleLowerCase();
+ if (!this._weekdaysParse) {
+ this._weekdaysParse = [];
+ this._shortWeekdaysParse = [];
+ this._minWeekdaysParse = [];
+
+ for (i = 0; i < 7; ++i) {
+ mom = createUTC([2000, 1]).day(i);
+ this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase();
+ this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase();
+ this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase();
+ }
+ }
+
+ if (strict) {
+ if (format === 'dddd') {
+ ii = indexOf.call(this._weekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else if (format === 'ddd') {
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ } else {
+ if (format === 'dddd') {
+ ii = indexOf.call(this._weekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else if (format === 'ddd') {
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._weekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ } else {
+ ii = indexOf.call(this._minWeekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._weekdaysParse, llc);
+ if (ii !== -1) {
+ return ii;
+ }
+ ii = indexOf.call(this._shortWeekdaysParse, llc);
+ return ii !== -1 ? ii : null;
+ }
+ }
+}
+
+function localeWeekdaysParse (weekdayName, format, strict) {
+ var i, mom, regex;
+
+ if (this._weekdaysParseExact) {
+ return handleStrictParse$1.call(this, weekdayName, format, strict);
+ }
+
+ if (!this._weekdaysParse) {
+ this._weekdaysParse = [];
+ this._minWeekdaysParse = [];
+ this._shortWeekdaysParse = [];
+ this._fullWeekdaysParse = [];
+ }
+
+ for (i = 0; i < 7; i++) {
+ // make the regex if we don't have it already
+
+ mom = createUTC([2000, 1]).day(i);
+ if (strict && !this._fullWeekdaysParse[i]) {
+ this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\.?') + '$', 'i');
+ this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\.?') + '$', 'i');
+ this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\.?') + '$', 'i');
+ }
+ if (!this._weekdaysParse[i]) {
+ regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
+ this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
+ }
+ // test the regex
+ if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) {
+ return i;
+ } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) {
+ return i;
+ } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) {
+ return i;
+ } else if (!strict && this._weekdaysParse[i].test(weekdayName)) {
+ return i;
+ }
+ }
+}
+
+// MOMENTS
+
+function getSetDayOfWeek (input) {
+ if (!this.isValid()) {
+ return input != null ? this : NaN;
+ }
+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
+ if (input != null) {
+ input = parseWeekday(input, this.localeData());
+ return this.add(input - day, 'd');
+ } else {
+ return day;
+ }
+}
+
+function getSetLocaleDayOfWeek (input) {
+ if (!this.isValid()) {
+ return input != null ? this : NaN;
+ }
+ var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
+ return input == null ? weekday : this.add(input - weekday, 'd');
+}
+
+function getSetISODayOfWeek (input) {
+ if (!this.isValid()) {
+ return input != null ? this : NaN;
+ }
+
+ // behaves the same as moment#day except
+ // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
+ // as a setter, sunday should belong to the previous week.
+
+ if (input != null) {
+ var weekday = parseIsoWeekday(input, this.localeData());
+ return this.day(this.day() % 7 ? weekday : weekday - 7);
+ } else {
+ return this.day() || 7;
+ }
+}
+
+var defaultWeekdaysRegex = matchWord;
+function weekdaysRegex (isStrict) {
+ if (this._weekdaysParseExact) {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ computeWeekdaysParse.call(this);
+ }
+ if (isStrict) {
+ return this._weekdaysStrictRegex;
+ } else {
+ return this._weekdaysRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ this._weekdaysRegex = defaultWeekdaysRegex;
+ }
+ return this._weekdaysStrictRegex && isStrict ?
+ this._weekdaysStrictRegex : this._weekdaysRegex;
+ }
+}
+
+var defaultWeekdaysShortRegex = matchWord;
+function weekdaysShortRegex (isStrict) {
+ if (this._weekdaysParseExact) {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ computeWeekdaysParse.call(this);
+ }
+ if (isStrict) {
+ return this._weekdaysShortStrictRegex;
+ } else {
+ return this._weekdaysShortRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_weekdaysShortRegex')) {
+ this._weekdaysShortRegex = defaultWeekdaysShortRegex;
+ }
+ return this._weekdaysShortStrictRegex && isStrict ?
+ this._weekdaysShortStrictRegex : this._weekdaysShortRegex;
+ }
+}
+
+var defaultWeekdaysMinRegex = matchWord;
+function weekdaysMinRegex (isStrict) {
+ if (this._weekdaysParseExact) {
+ if (!hasOwnProp(this, '_weekdaysRegex')) {
+ computeWeekdaysParse.call(this);
+ }
+ if (isStrict) {
+ return this._weekdaysMinStrictRegex;
+ } else {
+ return this._weekdaysMinRegex;
+ }
+ } else {
+ if (!hasOwnProp(this, '_weekdaysMinRegex')) {
+ this._weekdaysMinRegex = defaultWeekdaysMinRegex;
+ }
+ return this._weekdaysMinStrictRegex && isStrict ?
+ this._weekdaysMinStrictRegex : this._weekdaysMinRegex;
+ }
+}
+
+
+function computeWeekdaysParse () {
+ function cmpLenRev(a, b) {
+ return b.length - a.length;
+ }
+
+ var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [],
+ i, mom, minp, shortp, longp;
+ for (i = 0; i < 7; i++) {
+ // make the regex if we don't have it already
+ mom = createUTC([2000, 1]).day(i);
+ minp = this.weekdaysMin(mom, '');
+ shortp = this.weekdaysShort(mom, '');
+ longp = this.weekdays(mom, '');
+ minPieces.push(minp);
+ shortPieces.push(shortp);
+ longPieces.push(longp);
+ mixedPieces.push(minp);
+ mixedPieces.push(shortp);
+ mixedPieces.push(longp);
+ }
+ // Sorting makes sure if one weekday (or abbr) is a prefix of another it
+ // will match the longer piece.
+ minPieces.sort(cmpLenRev);
+ shortPieces.sort(cmpLenRev);
+ longPieces.sort(cmpLenRev);
+ mixedPieces.sort(cmpLenRev);
+ for (i = 0; i < 7; i++) {
+ shortPieces[i] = regexEscape(shortPieces[i]);
+ longPieces[i] = regexEscape(longPieces[i]);
+ mixedPieces[i] = regexEscape(mixedPieces[i]);
+ }
+
+ this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i');
+ this._weekdaysShortRegex = this._weekdaysRegex;
+ this._weekdaysMinRegex = this._weekdaysRegex;
+
+ this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i');
+ this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i');
+ this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i');
+}
+
+// FORMATTING
+
+function hFormat() {
+ return this.hours() % 12 || 12;
+}
+
+function kFormat() {
+ return this.hours() || 24;
+}
+
+addFormatToken('H', ['HH', 2], 0, 'hour');
+addFormatToken('h', ['hh', 2], 0, hFormat);
+addFormatToken('k', ['kk', 2], 0, kFormat);
+
+addFormatToken('hmm', 0, 0, function () {
+ return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2);
+});
+
+addFormatToken('hmmss', 0, 0, function () {
+ return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) +
+ zeroFill(this.seconds(), 2);
+});
+
+addFormatToken('Hmm', 0, 0, function () {
+ return '' + this.hours() + zeroFill(this.minutes(), 2);
+});
+
+addFormatToken('Hmmss', 0, 0, function () {
+ return '' + this.hours() + zeroFill(this.minutes(), 2) +
+ zeroFill(this.seconds(), 2);
+});
+
+function meridiem (token, lowercase) {
+ addFormatToken(token, 0, 0, function () {
+ return this.localeData().meridiem(this.hours(), this.minutes(), lowercase);
+ });
+}
+
+meridiem('a', true);
+meridiem('A', false);
+
+// ALIASES
+
+addUnitAlias('hour', 'h');
+
+// PRIORITY
+addUnitPriority('hour', 13);
+
+// PARSING
+
+function matchMeridiem (isStrict, locale) {
+ return locale._meridiemParse;
+}
+
+addRegexToken('a', matchMeridiem);
+addRegexToken('A', matchMeridiem);
+addRegexToken('H', match1to2);
+addRegexToken('h', match1to2);
+addRegexToken('k', match1to2);
+addRegexToken('HH', match1to2, match2);
+addRegexToken('hh', match1to2, match2);
+addRegexToken('kk', match1to2, match2);
+
+addRegexToken('hmm', match3to4);
+addRegexToken('hmmss', match5to6);
+addRegexToken('Hmm', match3to4);
+addRegexToken('Hmmss', match5to6);
+
+addParseToken(['H', 'HH'], HOUR);
+addParseToken(['k', 'kk'], function (input, array, config) {
+ var kInput = toInt(input);
+ array[HOUR] = kInput === 24 ? 0 : kInput;
+});
+addParseToken(['a', 'A'], function (input, array, config) {
+ config._isPm = config._locale.isPM(input);
+ config._meridiem = input;
+});
+addParseToken(['h', 'hh'], function (input, array, config) {
+ array[HOUR] = toInt(input);
+ getParsingFlags(config).bigHour = true;
+});
+addParseToken('hmm', function (input, array, config) {
+ var pos = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos));
+ array[MINUTE] = toInt(input.substr(pos));
+ getParsingFlags(config).bigHour = true;
+});
+addParseToken('hmmss', function (input, array, config) {
+ var pos1 = input.length - 4;
+ var pos2 = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos1));
+ array[MINUTE] = toInt(input.substr(pos1, 2));
+ array[SECOND] = toInt(input.substr(pos2));
+ getParsingFlags(config).bigHour = true;
+});
+addParseToken('Hmm', function (input, array, config) {
+ var pos = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos));
+ array[MINUTE] = toInt(input.substr(pos));
+});
+addParseToken('Hmmss', function (input, array, config) {
+ var pos1 = input.length - 4;
+ var pos2 = input.length - 2;
+ array[HOUR] = toInt(input.substr(0, pos1));
+ array[MINUTE] = toInt(input.substr(pos1, 2));
+ array[SECOND] = toInt(input.substr(pos2));
+});
+
+// LOCALES
+
+function localeIsPM (input) {
+ // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
+ // Using charAt should be more compatible.
+ return ((input + '').toLowerCase().charAt(0) === 'p');
+}
+
+var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i;
+function localeMeridiem (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'pm' : 'PM';
+ } else {
+ return isLower ? 'am' : 'AM';
+ }
+}
+
+
+// MOMENTS
+
+// Setting the hour should keep the time, because the user explicitly
+// specified which hour he wants. So trying to maintain the same hour (in
+// a new timezone) makes sense. Adding/subtracting hours does not follow
+// this rule.
+var getSetHour = makeGetSet('Hours', true);
+
+// months
+// week
+// weekdays
+// meridiem
+var baseConfig = {
+ calendar: defaultCalendar,
+ longDateFormat: defaultLongDateFormat,
+ invalidDate: defaultInvalidDate,
+ ordinal: defaultOrdinal,
+ dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse,
+ relativeTime: defaultRelativeTime,
+
+ months: defaultLocaleMonths,
+ monthsShort: defaultLocaleMonthsShort,
+
+ week: defaultLocaleWeek,
+
+ weekdays: defaultLocaleWeekdays,
+ weekdaysMin: defaultLocaleWeekdaysMin,
+ weekdaysShort: defaultLocaleWeekdaysShort,
+
+ meridiemParse: defaultLocaleMeridiemParse
+};
+
+// internal storage for locale config files
+var locales = {};
+var localeFamilies = {};
+var globalLocale;
+
+function normalizeLocale(key) {
+ return key ? key.toLowerCase().replace('_', '-') : key;
+}
+
+// pick the locale from the array
+// try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
+// substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
+function chooseLocale(names) {
+ var i = 0, j, next, locale, split;
+
+ while (i < names.length) {
+ split = normalizeLocale(names[i]).split('-');
+ j = split.length;
+ next = normalizeLocale(names[i + 1]);
+ next = next ? next.split('-') : null;
+ while (j > 0) {
+ locale = loadLocale(split.slice(0, j).join('-'));
+ if (locale) {
+ return locale;
+ }
+ if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
+ //the next array item is better than a shallower substring of this one
+ break;
+ }
+ j--;
+ }
+ i++;
+ }
+ return null;
+}
+
+function loadLocale(name) {
+ var oldLocale = null;
+ // TODO: Find a better way to register and load all the locales in Node
+ if (!locales[name] && (typeof module !== 'undefined') &&
+ module && module.exports) {
+ try {
+ oldLocale = globalLocale._abbr;
+ var aliasedRequire = require;
+ aliasedRequire('./locale/' + name);
+ getSetGlobalLocale(oldLocale);
+ } catch (e) {}
+ }
+ return locales[name];
+}
+
+// This function will load locale and then set the global locale. If
+// no arguments are passed in, it will simply return the current global
+// locale key.
+function getSetGlobalLocale (key, values) {
+ var data;
+ if (key) {
+ if (isUndefined(values)) {
+ data = getLocale(key);
+ }
+ else {
+ data = defineLocale(key, values);
+ }
+
+ if (data) {
+ // moment.duration._locale = moment._locale = data;
+ globalLocale = data;
+ }
+ }
+
+ return globalLocale._abbr;
+}
+
+function defineLocale (name, config) {
+ if (config !== null) {
+ var parentConfig = baseConfig;
+ config.abbr = name;
+ if (locales[name] != null) {
+ deprecateSimple('defineLocaleOverride',
+ 'use moment.updateLocale(localeName, config) to change ' +
+ 'an existing locale. moment.defineLocale(localeName, ' +
+ 'config) should only be used for creating a new locale ' +
+ 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.');
+ parentConfig = locales[name]._config;
+ } else if (config.parentLocale != null) {
+ if (locales[config.parentLocale] != null) {
+ parentConfig = locales[config.parentLocale]._config;
+ } else {
+ if (!localeFamilies[config.parentLocale]) {
+ localeFamilies[config.parentLocale] = [];
+ }
+ localeFamilies[config.parentLocale].push({
+ name: name,
+ config: config
+ });
+ return null;
+ }
+ }
+ locales[name] = new Locale(mergeConfigs(parentConfig, config));
+
+ if (localeFamilies[name]) {
+ localeFamilies[name].forEach(function (x) {
+ defineLocale(x.name, x.config);
+ });
+ }
+
+ // backwards compat for now: also set the locale
+ // make sure we set the locale AFTER all child locales have been
+ // created, so we won't end up with the child locale set.
+ getSetGlobalLocale(name);
+
+
+ return locales[name];
+ } else {
+ // useful for testing
+ delete locales[name];
+ return null;
+ }
+}
+
+function updateLocale(name, config) {
+ if (config != null) {
+ var locale, tmpLocale, parentConfig = baseConfig;
+ // MERGE
+ tmpLocale = loadLocale(name);
+ if (tmpLocale != null) {
+ parentConfig = tmpLocale._config;
+ }
+ config = mergeConfigs(parentConfig, config);
+ locale = new Locale(config);
+ locale.parentLocale = locales[name];
+ locales[name] = locale;
+
+ // backwards compat for now: also set the locale
+ getSetGlobalLocale(name);
+ } else {
+ // pass null for config to unupdate, useful for tests
+ if (locales[name] != null) {
+ if (locales[name].parentLocale != null) {
+ locales[name] = locales[name].parentLocale;
+ } else if (locales[name] != null) {
+ delete locales[name];
+ }
+ }
+ }
+ return locales[name];
+}
+
+// returns locale data
+function getLocale (key) {
+ var locale;
+
+ if (key && key._locale && key._locale._abbr) {
+ key = key._locale._abbr;
+ }
+
+ if (!key) {
+ return globalLocale;
+ }
+
+ if (!isArray(key)) {
+ //short-circuit everything else
+ locale = loadLocale(key);
+ if (locale) {
+ return locale;
+ }
+ key = [key];
+ }
+
+ return chooseLocale(key);
+}
+
+function listLocales() {
+ return keys(locales);
+}
+
+function checkOverflow (m) {
+ var overflow;
+ var a = m._a;
+
+ if (a && getParsingFlags(m).overflow === -2) {
+ overflow =
+ a[MONTH] < 0 || a[MONTH] > 11 ? MONTH :
+ a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE :
+ a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR :
+ a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE :
+ a[SECOND] < 0 || a[SECOND] > 59 ? SECOND :
+ a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND :
+ -1;
+
+ if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) {
+ overflow = DATE;
+ }
+ if (getParsingFlags(m)._overflowWeeks && overflow === -1) {
+ overflow = WEEK;
+ }
+ if (getParsingFlags(m)._overflowWeekday && overflow === -1) {
+ overflow = WEEKDAY;
+ }
+
+ getParsingFlags(m).overflow = overflow;
+ }
+
+ return m;
+}
+
+// Pick the first defined of two or three arguments.
+function defaults(a, b, c) {
+ if (a != null) {
+ return a;
+ }
+ if (b != null) {
+ return b;
+ }
+ return c;
+}
+
+function currentDateArray(config) {
+ // hooks is actually the exported moment object
+ var nowValue = new Date(hooks.now());
+ if (config._useUTC) {
+ return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()];
+ }
+ return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()];
+}
+
+// convert an array to a date.
+// the array should mirror the parameters below
+// note: all values past the year are optional and will default to the lowest possible value.
+// [year, month, day , hour, minute, second, millisecond]
+function configFromArray (config) {
+ var i, date, input = [], currentDate, yearToUse;
+
+ if (config._d) {
+ return;
+ }
+
+ currentDate = currentDateArray(config);
+
+ //compute day of the year from weeks and weekdays
+ if (config._w && config._a[DATE] == null && config._a[MONTH] == null) {
+ dayOfYearFromWeekInfo(config);
+ }
+
+ //if the day of the year is set, figure out what it is
+ if (config._dayOfYear != null) {
+ yearToUse = defaults(config._a[YEAR], currentDate[YEAR]);
+
+ if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) {
+ getParsingFlags(config)._overflowDayOfYear = true;
+ }
+
+ date = createUTCDate(yearToUse, 0, config._dayOfYear);
+ config._a[MONTH] = date.getUTCMonth();
+ config._a[DATE] = date.getUTCDate();
+ }
+
+ // Default to current date.
+ // * if no year, month, day of month are given, default to today
+ // * if day of month is given, default month and year
+ // * if month is given, default only year
+ // * if year is given, don't default anything
+ for (i = 0; i < 3 && config._a[i] == null; ++i) {
+ config._a[i] = input[i] = currentDate[i];
+ }
+
+ // Zero out whatever was not defaulted, including time
+ for (; i < 7; i++) {
+ config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
+ }
+
+ // Check for 24:00:00.000
+ if (config._a[HOUR] === 24 &&
+ config._a[MINUTE] === 0 &&
+ config._a[SECOND] === 0 &&
+ config._a[MILLISECOND] === 0) {
+ config._nextDay = true;
+ config._a[HOUR] = 0;
+ }
+
+ config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input);
+ // Apply timezone offset from input. The actual utcOffset can be changed
+ // with parseZone.
+ if (config._tzm != null) {
+ config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
+ }
+
+ if (config._nextDay) {
+ config._a[HOUR] = 24;
+ }
+
+ // check for mismatching day of week
+ if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== config._d.getDay()) {
+ getParsingFlags(config).weekdayMismatch = true;
+ }
+}
+
+function dayOfYearFromWeekInfo(config) {
+ var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow;
+
+ w = config._w;
+ if (w.GG != null || w.W != null || w.E != null) {
+ dow = 1;
+ doy = 4;
+
+ // TODO: We need to take the current isoWeekYear, but that depends on
+ // how we interpret now (local, utc, fixed offset). So create
+ // a now version of current config (take local/utc/offset flags, and
+ // create now).
+ weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year);
+ week = defaults(w.W, 1);
+ weekday = defaults(w.E, 1);
+ if (weekday < 1 || weekday > 7) {
+ weekdayOverflow = true;
+ }
+ } else {
+ dow = config._locale._week.dow;
+ doy = config._locale._week.doy;
+
+ var curWeek = weekOfYear(createLocal(), dow, doy);
+
+ weekYear = defaults(w.gg, config._a[YEAR], curWeek.year);
+
+ // Default to current week.
+ week = defaults(w.w, curWeek.week);
+
+ if (w.d != null) {
+ // weekday -- low day numbers are considered next week
+ weekday = w.d;
+ if (weekday < 0 || weekday > 6) {
+ weekdayOverflow = true;
+ }
+ } else if (w.e != null) {
+ // local weekday -- counting starts from begining of week
+ weekday = w.e + dow;
+ if (w.e < 0 || w.e > 6) {
+ weekdayOverflow = true;
+ }
+ } else {
+ // default to begining of week
+ weekday = dow;
+ }
+ }
+ if (week < 1 || week > weeksInYear(weekYear, dow, doy)) {
+ getParsingFlags(config)._overflowWeeks = true;
+ } else if (weekdayOverflow != null) {
+ getParsingFlags(config)._overflowWeekday = true;
+ } else {
+ temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy);
+ config._a[YEAR] = temp.year;
+ config._dayOfYear = temp.dayOfYear;
+ }
+}
+
+// iso 8601 regex
+// 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000 or +00)
+var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
+var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/;
+
+var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/;
+
+var isoDates = [
+ ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/],
+ ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/],
+ ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/],
+ ['GGGG-[W]WW', /\d{4}-W\d\d/, false],
+ ['YYYY-DDD', /\d{4}-\d{3}/],
+ ['YYYY-MM', /\d{4}-\d\d/, false],
+ ['YYYYYYMMDD', /[+-]\d{10}/],
+ ['YYYYMMDD', /\d{8}/],
+ // YYYYMM is NOT allowed by the standard
+ ['GGGG[W]WWE', /\d{4}W\d{3}/],
+ ['GGGG[W]WW', /\d{4}W\d{2}/, false],
+ ['YYYYDDD', /\d{7}/]
+];
+
+// iso time formats and regexes
+var isoTimes = [
+ ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/],
+ ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/],
+ ['HH:mm:ss', /\d\d:\d\d:\d\d/],
+ ['HH:mm', /\d\d:\d\d/],
+ ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/],
+ ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/],
+ ['HHmmss', /\d\d\d\d\d\d/],
+ ['HHmm', /\d\d\d\d/],
+ ['HH', /\d\d/]
+];
+
+var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i;
+
+// date from iso format
+function configFromISO(config) {
+ var i, l,
+ string = config._i,
+ match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string),
+ allowTime, dateFormat, timeFormat, tzFormat;
+
+ if (match) {
+ getParsingFlags(config).iso = true;
+
+ for (i = 0, l = isoDates.length; i < l; i++) {
+ if (isoDates[i][1].exec(match[1])) {
+ dateFormat = isoDates[i][0];
+ allowTime = isoDates[i][2] !== false;
+ break;
+ }
+ }
+ if (dateFormat == null) {
+ config._isValid = false;
+ return;
+ }
+ if (match[3]) {
+ for (i = 0, l = isoTimes.length; i < l; i++) {
+ if (isoTimes[i][1].exec(match[3])) {
+ // match[2] should be 'T' or space
+ timeFormat = (match[2] || ' ') + isoTimes[i][0];
+ break;
+ }
+ }
+ if (timeFormat == null) {
+ config._isValid = false;
+ return;
+ }
+ }
+ if (!allowTime && timeFormat != null) {
+ config._isValid = false;
+ return;
+ }
+ if (match[4]) {
+ if (tzRegex.exec(match[4])) {
+ tzFormat = 'Z';
+ } else {
+ config._isValid = false;
+ return;
+ }
+ }
+ config._f = dateFormat + (timeFormat || '') + (tzFormat || '');
+ configFromStringAndFormat(config);
+ } else {
+ config._isValid = false;
+ }
+}
+
+// RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3
+var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/;
+
+function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) {
+ var result = [
+ untruncateYear(yearStr),
+ defaultLocaleMonthsShort.indexOf(monthStr),
+ parseInt(dayStr, 10),
+ parseInt(hourStr, 10),
+ parseInt(minuteStr, 10)
+ ];
+
+ if (secondStr) {
+ result.push(parseInt(secondStr, 10));
+ }
+
+ return result;
+}
+
+function untruncateYear(yearStr) {
+ var year = parseInt(yearStr, 10);
+ if (year <= 49) {
+ return 2000 + year;
+ } else if (year <= 999) {
+ return 1900 + year;
+ }
+ return year;
+}
+
+function preprocessRFC2822(s) {
+ // Remove comments and folding whitespace and replace multiple-spaces with a single space
+ return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').trim();
+}
+
+function checkWeekday(weekdayStr, parsedInput, config) {
+ if (weekdayStr) {
+ // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check.
+ var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr),
+ weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay();
+ if (weekdayProvided !== weekdayActual) {
+ getParsingFlags(config).weekdayMismatch = true;
+ config._isValid = false;
+ return false;
+ }
+ }
+ return true;
+}
+
+var obsOffsets = {
+ UT: 0,
+ GMT: 0,
+ EDT: -4 * 60,
+ EST: -5 * 60,
+ CDT: -5 * 60,
+ CST: -6 * 60,
+ MDT: -6 * 60,
+ MST: -7 * 60,
+ PDT: -7 * 60,
+ PST: -8 * 60
+};
+
+function calculateOffset(obsOffset, militaryOffset, numOffset) {
+ if (obsOffset) {
+ return obsOffsets[obsOffset];
+ } else if (militaryOffset) {
+ // the only allowed military tz is Z
+ return 0;
+ } else {
+ var hm = parseInt(numOffset, 10);
+ var m = hm % 100, h = (hm - m) / 100;
+ return h * 60 + m;
+ }
+}
+
+// date and time from ref 2822 format
+function configFromRFC2822(config) {
+ var match = rfc2822.exec(preprocessRFC2822(config._i));
+ if (match) {
+ var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]);
+ if (!checkWeekday(match[1], parsedArray, config)) {
+ return;
+ }
+
+ config._a = parsedArray;
+ config._tzm = calculateOffset(match[8], match[9], match[10]);
+
+ config._d = createUTCDate.apply(null, config._a);
+ config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
+
+ getParsingFlags(config).rfc2822 = true;
+ } else {
+ config._isValid = false;
+ }
+}
+
+// date from iso format or fallback
+function configFromString(config) {
+ var matched = aspNetJsonRegex.exec(config._i);
+
+ if (matched !== null) {
+ config._d = new Date(+matched[1]);
+ return;
+ }
+
+ configFromISO(config);
+ if (config._isValid === false) {
+ delete config._isValid;
+ } else {
+ return;
+ }
+
+ configFromRFC2822(config);
+ if (config._isValid === false) {
+ delete config._isValid;
+ } else {
+ return;
+ }
+
+ // Final attempt, use Input Fallback
+ hooks.createFromInputFallback(config);
+}
+
+hooks.createFromInputFallback = deprecate(
+ 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' +
+ 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' +
+ 'discouraged and will be removed in an upcoming major release. Please refer to ' +
+ 'http://momentjs.com/guides/#/warnings/js-date/ for more info.',
+ function (config) {
+ config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
+ }
+);
+
+// constant that refers to the ISO standard
+hooks.ISO_8601 = function () {};
+
+// constant that refers to the RFC 2822 form
+hooks.RFC_2822 = function () {};
+
+// date from string and format string
+function configFromStringAndFormat(config) {
+ // TODO: Move this to another part of the creation flow to prevent circular deps
+ if (config._f === hooks.ISO_8601) {
+ configFromISO(config);
+ return;
+ }
+ if (config._f === hooks.RFC_2822) {
+ configFromRFC2822(config);
+ return;
+ }
+ config._a = [];
+ getParsingFlags(config).empty = true;
+
+ // This array is used to make a Date, either with `new Date` or `Date.UTC`
+ var string = '' + config._i,
+ i, parsedInput, tokens, token, skipped,
+ stringLength = string.length,
+ totalParsedInputLength = 0;
+
+ tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
+
+ for (i = 0; i < tokens.length; i++) {
+ token = tokens[i];
+ parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0];
+ // console.log('token', token, 'parsedInput', parsedInput,
+ // 'regex', getParseRegexForToken(token, config));
+ if (parsedInput) {
+ skipped = string.substr(0, string.indexOf(parsedInput));
+ if (skipped.length > 0) {
+ getParsingFlags(config).unusedInput.push(skipped);
+ }
+ string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
+ totalParsedInputLength += parsedInput.length;
+ }
+ // don't parse if it's not a known token
+ if (formatTokenFunctions[token]) {
+ if (parsedInput) {
+ getParsingFlags(config).empty = false;
+ }
+ else {
+ getParsingFlags(config).unusedTokens.push(token);
+ }
+ addTimeToArrayFromToken(token, parsedInput, config);
+ }
+ else if (config._strict && !parsedInput) {
+ getParsingFlags(config).unusedTokens.push(token);
+ }
+ }
+
+ // add remaining unparsed input length to the string
+ getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength;
+ if (string.length > 0) {
+ getParsingFlags(config).unusedInput.push(string);
+ }
+
+ // clear _12h flag if hour is <= 12
+ if (config._a[HOUR] <= 12 &&
+ getParsingFlags(config).bigHour === true &&
+ config._a[HOUR] > 0) {
+ getParsingFlags(config).bigHour = undefined;
+ }
+
+ getParsingFlags(config).parsedDateParts = config._a.slice(0);
+ getParsingFlags(config).meridiem = config._meridiem;
+ // handle meridiem
+ config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem);
+
+ configFromArray(config);
+ checkOverflow(config);
+}
+
+
+function meridiemFixWrap (locale, hour, meridiem) {
+ var isPm;
+
+ if (meridiem == null) {
+ // nothing to do
+ return hour;
+ }
+ if (locale.meridiemHour != null) {
+ return locale.meridiemHour(hour, meridiem);
+ } else if (locale.isPM != null) {
+ // Fallback
+ isPm = locale.isPM(meridiem);
+ if (isPm && hour < 12) {
+ hour += 12;
+ }
+ if (!isPm && hour === 12) {
+ hour = 0;
+ }
+ return hour;
+ } else {
+ // this is not supposed to happen
+ return hour;
+ }
+}
+
+// date from string and array of format strings
+function configFromStringAndArray(config) {
+ var tempConfig,
+ bestMoment,
+
+ scoreToBeat,
+ i,
+ currentScore;
+
+ if (config._f.length === 0) {
+ getParsingFlags(config).invalidFormat = true;
+ config._d = new Date(NaN);
+ return;
+ }
+
+ for (i = 0; i < config._f.length; i++) {
+ currentScore = 0;
+ tempConfig = copyConfig({}, config);
+ if (config._useUTC != null) {
+ tempConfig._useUTC = config._useUTC;
+ }
+ tempConfig._f = config._f[i];
+ configFromStringAndFormat(tempConfig);
+
+ if (!isValid(tempConfig)) {
+ continue;
+ }
+
+ // if there is any input that was not parsed add a penalty for that format
+ currentScore += getParsingFlags(tempConfig).charsLeftOver;
+
+ //or tokens
+ currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10;
+
+ getParsingFlags(tempConfig).score = currentScore;
+
+ if (scoreToBeat == null || currentScore < scoreToBeat) {
+ scoreToBeat = currentScore;
+ bestMoment = tempConfig;
+ }
+ }
+
+ extend(config, bestMoment || tempConfig);
+}
+
+function configFromObject(config) {
+ if (config._d) {
+ return;
+ }
+
+ var i = normalizeObjectUnits(config._i);
+ config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) {
+ return obj && parseInt(obj, 10);
+ });
+
+ configFromArray(config);
+}
+
+function createFromConfig (config) {
+ var res = new Moment(checkOverflow(prepareConfig(config)));
+ if (res._nextDay) {
+ // Adding is smart enough around DST
+ res.add(1, 'd');
+ res._nextDay = undefined;
+ }
+
+ return res;
+}
+
+function prepareConfig (config) {
+ var input = config._i,
+ format = config._f;
+
+ config._locale = config._locale || getLocale(config._l);
+
+ if (input === null || (format === undefined && input === '')) {
+ return createInvalid({nullInput: true});
+ }
+
+ if (typeof input === 'string') {
+ config._i = input = config._locale.preparse(input);
+ }
+
+ if (isMoment(input)) {
+ return new Moment(checkOverflow(input));
+ } else if (isDate(input)) {
+ config._d = input;
+ } else if (isArray(format)) {
+ configFromStringAndArray(config);
+ } else if (format) {
+ configFromStringAndFormat(config);
+ } else {
+ configFromInput(config);
+ }
+
+ if (!isValid(config)) {
+ config._d = null;
+ }
+
+ return config;
+}
+
+function configFromInput(config) {
+ var input = config._i;
+ if (isUndefined(input)) {
+ config._d = new Date(hooks.now());
+ } else if (isDate(input)) {
+ config._d = new Date(input.valueOf());
+ } else if (typeof input === 'string') {
+ configFromString(config);
+ } else if (isArray(input)) {
+ config._a = map(input.slice(0), function (obj) {
+ return parseInt(obj, 10);
+ });
+ configFromArray(config);
+ } else if (isObject(input)) {
+ configFromObject(config);
+ } else if (isNumber(input)) {
+ // from milliseconds
+ config._d = new Date(input);
+ } else {
+ hooks.createFromInputFallback(config);
+ }
+}
+
+function createLocalOrUTC (input, format, locale, strict, isUTC) {
+ var c = {};
+
+ if (locale === true || locale === false) {
+ strict = locale;
+ locale = undefined;
+ }
+
+ if ((isObject(input) && isObjectEmpty(input)) ||
+ (isArray(input) && input.length === 0)) {
+ input = undefined;
+ }
+ // object construction must be done this way.
+ // https://github.com/moment/moment/issues/1423
+ c._isAMomentObject = true;
+ c._useUTC = c._isUTC = isUTC;
+ c._l = locale;
+ c._i = input;
+ c._f = format;
+ c._strict = strict;
+
+ return createFromConfig(c);
+}
+
+function createLocal (input, format, locale, strict) {
+ return createLocalOrUTC(input, format, locale, strict, false);
+}
+
+var prototypeMin = deprecate(
+ 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/',
+ function () {
+ var other = createLocal.apply(null, arguments);
+ if (this.isValid() && other.isValid()) {
+ return other < this ? this : other;
+ } else {
+ return createInvalid();
+ }
+ }
+);
+
+var prototypeMax = deprecate(
+ 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/',
+ function () {
+ var other = createLocal.apply(null, arguments);
+ if (this.isValid() && other.isValid()) {
+ return other > this ? this : other;
+ } else {
+ return createInvalid();
+ }
+ }
+);
+
+// Pick a moment m from moments so that m[fn](other) is true for all
+// other. This relies on the function fn to be transitive.
+//
+// moments should either be an array of moment objects or an array, whose
+// first element is an array of moment objects.
+function pickBy(fn, moments) {
+ var res, i;
+ if (moments.length === 1 && isArray(moments[0])) {
+ moments = moments[0];
+ }
+ if (!moments.length) {
+ return createLocal();
+ }
+ res = moments[0];
+ for (i = 1; i < moments.length; ++i) {
+ if (!moments[i].isValid() || moments[i][fn](res)) {
+ res = moments[i];
+ }
+ }
+ return res;
+}
+
+// TODO: Use [].sort instead?
+function min () {
+ var args = [].slice.call(arguments, 0);
+
+ return pickBy('isBefore', args);
+}
+
+function max () {
+ var args = [].slice.call(arguments, 0);
+
+ return pickBy('isAfter', args);
+}
+
+var now = function () {
+ return Date.now ? Date.now() : +(new Date());
+};
+
+var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond'];
+
+function isDurationValid(m) {
+ for (var key in m) {
+ if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) {
+ return false;
+ }
+ }
+
+ var unitHasDecimal = false;
+ for (var i = 0; i < ordering.length; ++i) {
+ if (m[ordering[i]]) {
+ if (unitHasDecimal) {
+ return false; // only allow non-integers for smallest unit
+ }
+ if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) {
+ unitHasDecimal = true;
+ }
+ }
+ }
+
+ return true;
+}
+
+function isValid$1() {
+ return this._isValid;
+}
+
+function createInvalid$1() {
+ return createDuration(NaN);
+}
+
+function Duration (duration) {
+ var normalizedInput = normalizeObjectUnits(duration),
+ years = normalizedInput.year || 0,
+ quarters = normalizedInput.quarter || 0,
+ months = normalizedInput.month || 0,
+ weeks = normalizedInput.week || 0,
+ days = normalizedInput.day || 0,
+ hours = normalizedInput.hour || 0,
+ minutes = normalizedInput.minute || 0,
+ seconds = normalizedInput.second || 0,
+ milliseconds = normalizedInput.millisecond || 0;
+
+ this._isValid = isDurationValid(normalizedInput);
+
+ // representation for dateAddRemove
+ this._milliseconds = +milliseconds +
+ seconds * 1e3 + // 1000
+ minutes * 6e4 + // 1000 * 60
+ hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978
+ // Because of dateAddRemove treats 24 hours as different from a
+ // day when working around DST, we need to store them separately
+ this._days = +days +
+ weeks * 7;
+ // It is impossible to translate months into days without knowing
+ // which months you are are talking about, so we have to store
+ // it separately.
+ this._months = +months +
+ quarters * 3 +
+ years * 12;
+
+ this._data = {};
+
+ this._locale = getLocale();
+
+ this._bubble();
+}
+
+function isDuration (obj) {
+ return obj instanceof Duration;
+}
+
+function absRound (number) {
+ if (number < 0) {
+ return Math.round(-1 * number) * -1;
+ } else {
+ return Math.round(number);
+ }
+}
+
+// FORMATTING
+
+function offset (token, separator) {
+ addFormatToken(token, 0, 0, function () {
+ var offset = this.utcOffset();
+ var sign = '+';
+ if (offset < 0) {
+ offset = -offset;
+ sign = '-';
+ }
+ return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2);
+ });
+}
+
+offset('Z', ':');
+offset('ZZ', '');
+
+// PARSING
+
+addRegexToken('Z', matchShortOffset);
+addRegexToken('ZZ', matchShortOffset);
+addParseToken(['Z', 'ZZ'], function (input, array, config) {
+ config._useUTC = true;
+ config._tzm = offsetFromString(matchShortOffset, input);
+});
+
+// HELPERS
+
+// timezone chunker
+// '+10:00' > ['10', '00']
+// '-1530' > ['-15', '30']
+var chunkOffset = /([\+\-]|\d\d)/gi;
+
+function offsetFromString(matcher, string) {
+ var matches = (string || '').match(matcher);
+
+ if (matches === null) {
+ return null;
+ }
+
+ var chunk = matches[matches.length - 1] || [];
+ var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0];
+ var minutes = +(parts[1] * 60) + toInt(parts[2]);
+
+ return minutes === 0 ?
+ 0 :
+ parts[0] === '+' ? minutes : -minutes;
+}
+
+// Return a moment from input, that is local/utc/zone equivalent to model.
+function cloneWithOffset(input, model) {
+ var res, diff;
+ if (model._isUTC) {
+ res = model.clone();
+ diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf();
+ // Use low-level api, because this fn is low-level api.
+ res._d.setTime(res._d.valueOf() + diff);
+ hooks.updateOffset(res, false);
+ return res;
+ } else {
+ return createLocal(input).local();
+ }
+}
+
+function getDateOffset (m) {
+ // On Firefox.24 Date#getTimezoneOffset returns a floating point.
+ // https://github.com/moment/moment/pull/1871
+ return -Math.round(m._d.getTimezoneOffset() / 15) * 15;
+}
+
+// HOOKS
+
+// This function will be called whenever a moment is mutated.
+// It is intended to keep the offset in sync with the timezone.
+hooks.updateOffset = function () {};
+
+// MOMENTS
+
+// keepLocalTime = true means only change the timezone, without
+// affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
+// 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
+// +0200, so we adjust the time as needed, to be valid.
+//
+// Keeping the time actually adds/subtracts (one hour)
+// from the actual represented time. That is why we call updateOffset
+// a second time. In case it wants us to change the offset again
+// _changeInProgress == true case, then we have to adjust, because
+// there is no such time in the given timezone.
+function getSetOffset (input, keepLocalTime, keepMinutes) {
+ var offset = this._offset || 0,
+ localAdjust;
+ if (!this.isValid()) {
+ return input != null ? this : NaN;
+ }
+ if (input != null) {
+ if (typeof input === 'string') {
+ input = offsetFromString(matchShortOffset, input);
+ if (input === null) {
+ return this;
+ }
+ } else if (Math.abs(input) < 16 && !keepMinutes) {
+ input = input * 60;
+ }
+ if (!this._isUTC && keepLocalTime) {
+ localAdjust = getDateOffset(this);
+ }
+ this._offset = input;
+ this._isUTC = true;
+ if (localAdjust != null) {
+ this.add(localAdjust, 'm');
+ }
+ if (offset !== input) {
+ if (!keepLocalTime || this._changeInProgress) {
+ addSubtract(this, createDuration(input - offset, 'm'), 1, false);
+ } else if (!this._changeInProgress) {
+ this._changeInProgress = true;
+ hooks.updateOffset(this, true);
+ this._changeInProgress = null;
+ }
+ }
+ return this;
+ } else {
+ return this._isUTC ? offset : getDateOffset(this);
+ }
+}
+
+function getSetZone (input, keepLocalTime) {
+ if (input != null) {
+ if (typeof input !== 'string') {
+ input = -input;
+ }
+
+ this.utcOffset(input, keepLocalTime);
+
+ return this;
+ } else {
+ return -this.utcOffset();
+ }
+}
+
+function setOffsetToUTC (keepLocalTime) {
+ return this.utcOffset(0, keepLocalTime);
+}
+
+function setOffsetToLocal (keepLocalTime) {
+ if (this._isUTC) {
+ this.utcOffset(0, keepLocalTime);
+ this._isUTC = false;
+
+ if (keepLocalTime) {
+ this.subtract(getDateOffset(this), 'm');
+ }
+ }
+ return this;
+}
+
+function setOffsetToParsedOffset () {
+ if (this._tzm != null) {
+ this.utcOffset(this._tzm, false, true);
+ } else if (typeof this._i === 'string') {
+ var tZone = offsetFromString(matchOffset, this._i);
+ if (tZone != null) {
+ this.utcOffset(tZone);
+ }
+ else {
+ this.utcOffset(0, true);
+ }
+ }
+ return this;
+}
+
+function hasAlignedHourOffset (input) {
+ if (!this.isValid()) {
+ return false;
+ }
+ input = input ? createLocal(input).utcOffset() : 0;
+
+ return (this.utcOffset() - input) % 60 === 0;
+}
+
+function isDaylightSavingTime () {
+ return (
+ this.utcOffset() > this.clone().month(0).utcOffset() ||
+ this.utcOffset() > this.clone().month(5).utcOffset()
+ );
+}
+
+function isDaylightSavingTimeShifted () {
+ if (!isUndefined(this._isDSTShifted)) {
+ return this._isDSTShifted;
+ }
+
+ var c = {};
+
+ copyConfig(c, this);
+ c = prepareConfig(c);
+
+ if (c._a) {
+ var other = c._isUTC ? createUTC(c._a) : createLocal(c._a);
+ this._isDSTShifted = this.isValid() &&
+ compareArrays(c._a, other.toArray()) > 0;
+ } else {
+ this._isDSTShifted = false;
+ }
+
+ return this._isDSTShifted;
+}
+
+function isLocal () {
+ return this.isValid() ? !this._isUTC : false;
+}
+
+function isUtcOffset () {
+ return this.isValid() ? this._isUTC : false;
+}
+
+function isUtc () {
+ return this.isValid() ? this._isUTC && this._offset === 0 : false;
+}
+
+// ASP.NET json date format regex
+var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/;
+
+// from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
+// somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
+// and further modified to allow for strings containing both week and day
+var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;
+
+function createDuration (input, key) {
+ var duration = input,
+ // matching against regexp is expensive, do it on demand
+ match = null,
+ sign,
+ ret,
+ diffRes;
+
+ if (isDuration(input)) {
+ duration = {
+ ms : input._milliseconds,
+ d : input._days,
+ M : input._months
+ };
+ } else if (isNumber(input)) {
+ duration = {};
+ if (key) {
+ duration[key] = input;
+ } else {
+ duration.milliseconds = input;
+ }
+ } else if (!!(match = aspNetRegex.exec(input))) {
+ sign = (match[1] === '-') ? -1 : 1;
+ duration = {
+ y : 0,
+ d : toInt(match[DATE]) * sign,
+ h : toInt(match[HOUR]) * sign,
+ m : toInt(match[MINUTE]) * sign,
+ s : toInt(match[SECOND]) * sign,
+ ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match
+ };
+ } else if (!!(match = isoRegex.exec(input))) {
+ sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1;
+ duration = {
+ y : parseIso(match[2], sign),
+ M : parseIso(match[3], sign),
+ w : parseIso(match[4], sign),
+ d : parseIso(match[5], sign),
+ h : parseIso(match[6], sign),
+ m : parseIso(match[7], sign),
+ s : parseIso(match[8], sign)
+ };
+ } else if (duration == null) {// checks for null or undefined
+ duration = {};
+ } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) {
+ diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to));
+
+ duration = {};
+ duration.ms = diffRes.milliseconds;
+ duration.M = diffRes.months;
+ }
+
+ ret = new Duration(duration);
+
+ if (isDuration(input) && hasOwnProp(input, '_locale')) {
+ ret._locale = input._locale;
+ }
+
+ return ret;
+}
+
+createDuration.fn = Duration.prototype;
+createDuration.invalid = createInvalid$1;
+
+function parseIso (inp, sign) {
+ // We'd normally use ~~inp for this, but unfortunately it also
+ // converts floats to ints.
+ // inp may be undefined, so careful calling replace on it.
+ var res = inp && parseFloat(inp.replace(',', '.'));
+ // apply sign while we're at it
+ return (isNaN(res) ? 0 : res) * sign;
+}
+
+function positiveMomentsDifference(base, other) {
+ var res = {milliseconds: 0, months: 0};
+
+ res.months = other.month() - base.month() +
+ (other.year() - base.year()) * 12;
+ if (base.clone().add(res.months, 'M').isAfter(other)) {
+ --res.months;
+ }
+
+ res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
+
+ return res;
+}
+
+function momentsDifference(base, other) {
+ var res;
+ if (!(base.isValid() && other.isValid())) {
+ return {milliseconds: 0, months: 0};
+ }
+
+ other = cloneWithOffset(other, base);
+ if (base.isBefore(other)) {
+ res = positiveMomentsDifference(base, other);
+ } else {
+ res = positiveMomentsDifference(other, base);
+ res.milliseconds = -res.milliseconds;
+ res.months = -res.months;
+ }
+
+ return res;
+}
+
+// TODO: remove 'name' arg after deprecation is removed
+function createAdder(direction, name) {
+ return function (val, period) {
+ var dur, tmp;
+ //invert the arguments, but complain about it
+ if (period !== null && !isNaN(+period)) {
+ deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' +
+ 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.');
+ tmp = val; val = period; period = tmp;
+ }
+
+ val = typeof val === 'string' ? +val : val;
+ dur = createDuration(val, period);
+ addSubtract(this, dur, direction);
+ return this;
+ };
+}
+
+function addSubtract (mom, duration, isAdding, updateOffset) {
+ var milliseconds = duration._milliseconds,
+ days = absRound(duration._days),
+ months = absRound(duration._months);
+
+ if (!mom.isValid()) {
+ // No op
+ return;
+ }
+
+ updateOffset = updateOffset == null ? true : updateOffset;
+
+ if (months) {
+ setMonth(mom, get(mom, 'Month') + months * isAdding);
+ }
+ if (days) {
+ set$1(mom, 'Date', get(mom, 'Date') + days * isAdding);
+ }
+ if (milliseconds) {
+ mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding);
+ }
+ if (updateOffset) {
+ hooks.updateOffset(mom, days || months);
+ }
+}
+
+var add = createAdder(1, 'add');
+var subtract = createAdder(-1, 'subtract');
+
+function getCalendarFormat(myMoment, now) {
+ var diff = myMoment.diff(now, 'days', true);
+ return diff < -6 ? 'sameElse' :
+ diff < -1 ? 'lastWeek' :
+ diff < 0 ? 'lastDay' :
+ diff < 1 ? 'sameDay' :
+ diff < 2 ? 'nextDay' :
+ diff < 7 ? 'nextWeek' : 'sameElse';
+}
+
+function calendar$1 (time, formats) {
+ // We want to compare the start of today, vs this.
+ // Getting start-of-today depends on whether we're local/utc/offset or not.
+ var now = time || createLocal(),
+ sod = cloneWithOffset(now, this).startOf('day'),
+ format = hooks.calendarFormat(this, sod) || 'sameElse';
+
+ var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]);
+
+ return this.format(output || this.localeData().calendar(format, this, createLocal(now)));
+}
+
+function clone () {
+ return new Moment(this);
+}
+
+function isAfter (input, units) {
+ var localInput = isMoment(input) ? input : createLocal(input);
+ if (!(this.isValid() && localInput.isValid())) {
+ return false;
+ }
+ units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
+ if (units === 'millisecond') {
+ return this.valueOf() > localInput.valueOf();
+ } else {
+ return localInput.valueOf() < this.clone().startOf(units).valueOf();
+ }
+}
+
+function isBefore (input, units) {
+ var localInput = isMoment(input) ? input : createLocal(input);
+ if (!(this.isValid() && localInput.isValid())) {
+ return false;
+ }
+ units = normalizeUnits(!isUndefined(units) ? units : 'millisecond');
+ if (units === 'millisecond') {
+ return this.valueOf() < localInput.valueOf();
+ } else {
+ return this.clone().endOf(units).valueOf() < localInput.valueOf();
+ }
+}
+
+function isBetween (from, to, units, inclusivity) {
+ inclusivity = inclusivity || '()';
+ return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) &&
+ (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units));
+}
+
+function isSame (input, units) {
+ var localInput = isMoment(input) ? input : createLocal(input),
+ inputMs;
+ if (!(this.isValid() && localInput.isValid())) {
+ return false;
+ }
+ units = normalizeUnits(units || 'millisecond');
+ if (units === 'millisecond') {
+ return this.valueOf() === localInput.valueOf();
+ } else {
+ inputMs = localInput.valueOf();
+ return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf();
+ }
+}
+
+function isSameOrAfter (input, units) {
+ return this.isSame(input, units) || this.isAfter(input,units);
+}
+
+function isSameOrBefore (input, units) {
+ return this.isSame(input, units) || this.isBefore(input,units);
+}
+
+function diff (input, units, asFloat) {
+ var that,
+ zoneDelta,
+ delta, output;
+
+ if (!this.isValid()) {
+ return NaN;
+ }
+
+ that = cloneWithOffset(input, this);
+
+ if (!that.isValid()) {
+ return NaN;
+ }
+
+ zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4;
+
+ units = normalizeUnits(units);
+
+ switch (units) {
+ case 'year': output = monthDiff(this, that) / 12; break;
+ case 'month': output = monthDiff(this, that); break;
+ case 'quarter': output = monthDiff(this, that) / 3; break;
+ case 'second': output = (this - that) / 1e3; break; // 1000
+ case 'minute': output = (this - that) / 6e4; break; // 1000 * 60
+ case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60
+ case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst
+ case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst
+ default: output = this - that;
+ }
+
+ return asFloat ? output : absFloor(output);
+}
+
+function monthDiff (a, b) {
+ // difference in months
+ var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
+ // b is in (anchor - 1 month, anchor + 1 month)
+ anchor = a.clone().add(wholeMonthDiff, 'months'),
+ anchor2, adjust;
+
+ if (b - anchor < 0) {
+ anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
+ // linear across the month
+ adjust = (b - anchor) / (anchor - anchor2);
+ } else {
+ anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
+ // linear across the month
+ adjust = (b - anchor) / (anchor2 - anchor);
+ }
+
+ //check for negative zero, return zero if negative zero
+ return -(wholeMonthDiff + adjust) || 0;
+}
+
+hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ';
+hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]';
+
+function toString () {
+ return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
+}
+
+function toISOString() {
+ if (!this.isValid()) {
+ return null;
+ }
+ var m = this.clone().utc();
+ if (m.year() < 0 || m.year() > 9999) {
+ return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+ }
+ if (isFunction(Date.prototype.toISOString)) {
+ // native implementation is ~50x faster, use it when we can
+ return this.toDate().toISOString();
+ }
+ return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+}
+
+/**
+ * Return a human readable representation of a moment that can
+ * also be evaluated to get a new moment which is the same
+ *
+ * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects
+ */
+function inspect () {
+ if (!this.isValid()) {
+ return 'moment.invalid(/* ' + this._i + ' */)';
+ }
+ var func = 'moment';
+ var zone = '';
+ if (!this.isLocal()) {
+ func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone';
+ zone = 'Z';
+ }
+ var prefix = '[' + func + '("]';
+ var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY';
+ var datetime = '-MM-DD[T]HH:mm:ss.SSS';
+ var suffix = zone + '[")]';
+
+ return this.format(prefix + year + datetime + suffix);
+}
+
+function format (inputString) {
+ if (!inputString) {
+ inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat;
+ }
+ var output = formatMoment(this, inputString);
+ return this.localeData().postformat(output);
+}
+
+function from (time, withoutSuffix) {
+ if (this.isValid() &&
+ ((isMoment(time) && time.isValid()) ||
+ createLocal(time).isValid())) {
+ return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
+ } else {
+ return this.localeData().invalidDate();
+ }
+}
+
+function fromNow (withoutSuffix) {
+ return this.from(createLocal(), withoutSuffix);
+}
+
+function to (time, withoutSuffix) {
+ if (this.isValid() &&
+ ((isMoment(time) && time.isValid()) ||
+ createLocal(time).isValid())) {
+ return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix);
+ } else {
+ return this.localeData().invalidDate();
+ }
+}
+
+function toNow (withoutSuffix) {
+ return this.to(createLocal(), withoutSuffix);
+}
+
+// If passed a locale key, it will set the locale for this
+// instance. Otherwise, it will return the locale configuration
+// variables for this instance.
+function locale (key) {
+ var newLocaleData;
+
+ if (key === undefined) {
+ return this._locale._abbr;
+ } else {
+ newLocaleData = getLocale(key);
+ if (newLocaleData != null) {
+ this._locale = newLocaleData;
+ }
+ return this;
+ }
+}
+
+var lang = deprecate(
+ 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
+ function (key) {
+ if (key === undefined) {
+ return this.localeData();
+ } else {
+ return this.locale(key);
+ }
+ }
+);
+
+function localeData () {
+ return this._locale;
+}
+
+function startOf (units) {
+ units = normalizeUnits(units);
+ // the following switch intentionally omits break keywords
+ // to utilize falling through the cases.
+ switch (units) {
+ case 'year':
+ this.month(0);
+ /* falls through */
+ case 'quarter':
+ case 'month':
+ this.date(1);
+ /* falls through */
+ case 'week':
+ case 'isoWeek':
+ case 'day':
+ case 'date':
+ this.hours(0);
+ /* falls through */
+ case 'hour':
+ this.minutes(0);
+ /* falls through */
+ case 'minute':
+ this.seconds(0);
+ /* falls through */
+ case 'second':
+ this.milliseconds(0);
+ }
+
+ // weeks are a special case
+ if (units === 'week') {
+ this.weekday(0);
+ }
+ if (units === 'isoWeek') {
+ this.isoWeekday(1);
+ }
+
+ // quarters are also special
+ if (units === 'quarter') {
+ this.month(Math.floor(this.month() / 3) * 3);
+ }
+
+ return this;
+}
+
+function endOf (units) {
+ units = normalizeUnits(units);
+ if (units === undefined || units === 'millisecond') {
+ return this;
+ }
+
+ // 'date' is an alias for 'day', so it should be considered as such.
+ if (units === 'date') {
+ units = 'day';
+ }
+
+ return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
+}
+
+function valueOf () {
+ return this._d.valueOf() - ((this._offset || 0) * 60000);
+}
+
+function unix () {
+ return Math.floor(this.valueOf() / 1000);
+}
+
+function toDate () {
+ return new Date(this.valueOf());
+}
+
+function toArray () {
+ var m = this;
+ return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()];
+}
+
+function toObject () {
+ var m = this;
+ return {
+ years: m.year(),
+ months: m.month(),
+ date: m.date(),
+ hours: m.hours(),
+ minutes: m.minutes(),
+ seconds: m.seconds(),
+ milliseconds: m.milliseconds()
+ };
+}
+
+function toJSON () {
+ // new Date(NaN).toJSON() === null
+ return this.isValid() ? this.toISOString() : null;
+}
+
+function isValid$2 () {
+ return isValid(this);
+}
+
+function parsingFlags () {
+ return extend({}, getParsingFlags(this));
+}
+
+function invalidAt () {
+ return getParsingFlags(this).overflow;
+}
+
+function creationData() {
+ return {
+ input: this._i,
+ format: this._f,
+ locale: this._locale,
+ isUTC: this._isUTC,
+ strict: this._strict
+ };
+}
+
+// FORMATTING
+
+addFormatToken(0, ['gg', 2], 0, function () {
+ return this.weekYear() % 100;
+});
+
+addFormatToken(0, ['GG', 2], 0, function () {
+ return this.isoWeekYear() % 100;
+});
+
+function addWeekYearFormatToken (token, getter) {
+ addFormatToken(0, [token, token.length], 0, getter);
+}
+
+addWeekYearFormatToken('gggg', 'weekYear');
+addWeekYearFormatToken('ggggg', 'weekYear');
+addWeekYearFormatToken('GGGG', 'isoWeekYear');
+addWeekYearFormatToken('GGGGG', 'isoWeekYear');
+
+// ALIASES
+
+addUnitAlias('weekYear', 'gg');
+addUnitAlias('isoWeekYear', 'GG');
+
+// PRIORITY
+
+addUnitPriority('weekYear', 1);
+addUnitPriority('isoWeekYear', 1);
+
+
+// PARSING
+
+addRegexToken('G', matchSigned);
+addRegexToken('g', matchSigned);
+addRegexToken('GG', match1to2, match2);
+addRegexToken('gg', match1to2, match2);
+addRegexToken('GGGG', match1to4, match4);
+addRegexToken('gggg', match1to4, match4);
+addRegexToken('GGGGG', match1to6, match6);
+addRegexToken('ggggg', match1to6, match6);
+
+addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) {
+ week[token.substr(0, 2)] = toInt(input);
+});
+
+addWeekParseToken(['gg', 'GG'], function (input, week, config, token) {
+ week[token] = hooks.parseTwoDigitYear(input);
+});
+
+// MOMENTS
+
+function getSetWeekYear (input) {
+ return getSetWeekYearHelper.call(this,
+ input,
+ this.week(),
+ this.weekday(),
+ this.localeData()._week.dow,
+ this.localeData()._week.doy);
+}
+
+function getSetISOWeekYear (input) {
+ return getSetWeekYearHelper.call(this,
+ input, this.isoWeek(), this.isoWeekday(), 1, 4);
+}
+
+function getISOWeeksInYear () {
+ return weeksInYear(this.year(), 1, 4);
+}
+
+function getWeeksInYear () {
+ var weekInfo = this.localeData()._week;
+ return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
+}
+
+function getSetWeekYearHelper(input, week, weekday, dow, doy) {
+ var weeksTarget;
+ if (input == null) {
+ return weekOfYear(this, dow, doy).year;
+ } else {
+ weeksTarget = weeksInYear(input, dow, doy);
+ if (week > weeksTarget) {
+ week = weeksTarget;
+ }
+ return setWeekAll.call(this, input, week, weekday, dow, doy);
+ }
+}
+
+function setWeekAll(weekYear, week, weekday, dow, doy) {
+ var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy),
+ date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear);
+
+ this.year(date.getUTCFullYear());
+ this.month(date.getUTCMonth());
+ this.date(date.getUTCDate());
+ return this;
+}
+
+// FORMATTING
+
+addFormatToken('Q', 0, 'Qo', 'quarter');
+
+// ALIASES
+
+addUnitAlias('quarter', 'Q');
+
+// PRIORITY
+
+addUnitPriority('quarter', 7);
+
+// PARSING
+
+addRegexToken('Q', match1);
+addParseToken('Q', function (input, array) {
+ array[MONTH] = (toInt(input) - 1) * 3;
+});
+
+// MOMENTS
+
+function getSetQuarter (input) {
+ return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
+}
+
+// FORMATTING
+
+addFormatToken('D', ['DD', 2], 'Do', 'date');
+
+// ALIASES
+
+addUnitAlias('date', 'D');
+
+// PRIOROITY
+addUnitPriority('date', 9);
+
+// PARSING
+
+addRegexToken('D', match1to2);
+addRegexToken('DD', match1to2, match2);
+addRegexToken('Do', function (isStrict, locale) {
+ // TODO: Remove "ordinalParse" fallback in next major release.
+ return isStrict ?
+ (locale._dayOfMonthOrdinalParse || locale._ordinalParse) :
+ locale._dayOfMonthOrdinalParseLenient;
+});
+
+addParseToken(['D', 'DD'], DATE);
+addParseToken('Do', function (input, array) {
+ array[DATE] = toInt(input.match(match1to2)[0], 10);
+});
+
+// MOMENTS
+
+var getSetDayOfMonth = makeGetSet('Date', true);
+
+// FORMATTING
+
+addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear');
+
+// ALIASES
+
+addUnitAlias('dayOfYear', 'DDD');
+
+// PRIORITY
+addUnitPriority('dayOfYear', 4);
+
+// PARSING
+
+addRegexToken('DDD', match1to3);
+addRegexToken('DDDD', match3);
+addParseToken(['DDD', 'DDDD'], function (input, array, config) {
+ config._dayOfYear = toInt(input);
+});
+
+// HELPERS
+
+// MOMENTS
+
+function getSetDayOfYear (input) {
+ var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1;
+ return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
+}
+
+// FORMATTING
+
+addFormatToken('m', ['mm', 2], 0, 'minute');
+
+// ALIASES
+
+addUnitAlias('minute', 'm');
+
+// PRIORITY
+
+addUnitPriority('minute', 14);
+
+// PARSING
+
+addRegexToken('m', match1to2);
+addRegexToken('mm', match1to2, match2);
+addParseToken(['m', 'mm'], MINUTE);
+
+// MOMENTS
+
+var getSetMinute = makeGetSet('Minutes', false);
+
+// FORMATTING
+
+addFormatToken('s', ['ss', 2], 0, 'second');
+
+// ALIASES
+
+addUnitAlias('second', 's');
+
+// PRIORITY
+
+addUnitPriority('second', 15);
+
+// PARSING
+
+addRegexToken('s', match1to2);
+addRegexToken('ss', match1to2, match2);
+addParseToken(['s', 'ss'], SECOND);
+
+// MOMENTS
+
+var getSetSecond = makeGetSet('Seconds', false);
+
+// FORMATTING
+
+addFormatToken('S', 0, 0, function () {
+ return ~~(this.millisecond() / 100);
+});
+
+addFormatToken(0, ['SS', 2], 0, function () {
+ return ~~(this.millisecond() / 10);
+});
+
+addFormatToken(0, ['SSS', 3], 0, 'millisecond');
+addFormatToken(0, ['SSSS', 4], 0, function () {
+ return this.millisecond() * 10;
+});
+addFormatToken(0, ['SSSSS', 5], 0, function () {
+ return this.millisecond() * 100;
+});
+addFormatToken(0, ['SSSSSS', 6], 0, function () {
+ return this.millisecond() * 1000;
+});
+addFormatToken(0, ['SSSSSSS', 7], 0, function () {
+ return this.millisecond() * 10000;
+});
+addFormatToken(0, ['SSSSSSSS', 8], 0, function () {
+ return this.millisecond() * 100000;
+});
+addFormatToken(0, ['SSSSSSSSS', 9], 0, function () {
+ return this.millisecond() * 1000000;
+});
+
+
+// ALIASES
+
+addUnitAlias('millisecond', 'ms');
+
+// PRIORITY
+
+addUnitPriority('millisecond', 16);
+
+// PARSING
+
+addRegexToken('S', match1to3, match1);
+addRegexToken('SS', match1to3, match2);
+addRegexToken('SSS', match1to3, match3);
+
+var token;
+for (token = 'SSSS'; token.length <= 9; token += 'S') {
+ addRegexToken(token, matchUnsigned);
+}
+
+function parseMs(input, array) {
+ array[MILLISECOND] = toInt(('0.' + input) * 1000);
+}
+
+for (token = 'S'; token.length <= 9; token += 'S') {
+ addParseToken(token, parseMs);
+}
+// MOMENTS
+
+var getSetMillisecond = makeGetSet('Milliseconds', false);
+
+// FORMATTING
+
+addFormatToken('z', 0, 0, 'zoneAbbr');
+addFormatToken('zz', 0, 0, 'zoneName');
+
+// MOMENTS
+
+function getZoneAbbr () {
+ return this._isUTC ? 'UTC' : '';
+}
+
+function getZoneName () {
+ return this._isUTC ? 'Coordinated Universal Time' : '';
+}
+
+var proto = Moment.prototype;
+
+proto.add = add;
+proto.calendar = calendar$1;
+proto.clone = clone;
+proto.diff = diff;
+proto.endOf = endOf;
+proto.format = format;
+proto.from = from;
+proto.fromNow = fromNow;
+proto.to = to;
+proto.toNow = toNow;
+proto.get = stringGet;
+proto.invalidAt = invalidAt;
+proto.isAfter = isAfter;
+proto.isBefore = isBefore;
+proto.isBetween = isBetween;
+proto.isSame = isSame;
+proto.isSameOrAfter = isSameOrAfter;
+proto.isSameOrBefore = isSameOrBefore;
+proto.isValid = isValid$2;
+proto.lang = lang;
+proto.locale = locale;
+proto.localeData = localeData;
+proto.max = prototypeMax;
+proto.min = prototypeMin;
+proto.parsingFlags = parsingFlags;
+proto.set = stringSet;
+proto.startOf = startOf;
+proto.subtract = subtract;
+proto.toArray = toArray;
+proto.toObject = toObject;
+proto.toDate = toDate;
+proto.toISOString = toISOString;
+proto.inspect = inspect;
+proto.toJSON = toJSON;
+proto.toString = toString;
+proto.unix = unix;
+proto.valueOf = valueOf;
+proto.creationData = creationData;
+
+// Year
+proto.year = getSetYear;
+proto.isLeapYear = getIsLeapYear;
+
+// Week Year
+proto.weekYear = getSetWeekYear;
+proto.isoWeekYear = getSetISOWeekYear;
+
+// Quarter
+proto.quarter = proto.quarters = getSetQuarter;
+
+// Month
+proto.month = getSetMonth;
+proto.daysInMonth = getDaysInMonth;
+
+// Week
+proto.week = proto.weeks = getSetWeek;
+proto.isoWeek = proto.isoWeeks = getSetISOWeek;
+proto.weeksInYear = getWeeksInYear;
+proto.isoWeeksInYear = getISOWeeksInYear;
+
+// Day
+proto.date = getSetDayOfMonth;
+proto.day = proto.days = getSetDayOfWeek;
+proto.weekday = getSetLocaleDayOfWeek;
+proto.isoWeekday = getSetISODayOfWeek;
+proto.dayOfYear = getSetDayOfYear;
+
+// Hour
+proto.hour = proto.hours = getSetHour;
+
+// Minute
+proto.minute = proto.minutes = getSetMinute;
+
+// Second
+proto.second = proto.seconds = getSetSecond;
+
+// Millisecond
+proto.millisecond = proto.milliseconds = getSetMillisecond;
+
+// Offset
+proto.utcOffset = getSetOffset;
+proto.utc = setOffsetToUTC;
+proto.local = setOffsetToLocal;
+proto.parseZone = setOffsetToParsedOffset;
+proto.hasAlignedHourOffset = hasAlignedHourOffset;
+proto.isDST = isDaylightSavingTime;
+proto.isLocal = isLocal;
+proto.isUtcOffset = isUtcOffset;
+proto.isUtc = isUtc;
+proto.isUTC = isUtc;
+
+// Timezone
+proto.zoneAbbr = getZoneAbbr;
+proto.zoneName = getZoneName;
+
+// Deprecations
+proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth);
+proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth);
+proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear);
+proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone);
+proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted);
+
+function createUnix (input) {
+ return createLocal(input * 1000);
+}
+
+function createInZone () {
+ return createLocal.apply(null, arguments).parseZone();
+}
+
+function preParsePostFormat (string) {
+ return string;
+}
+
+var proto$1 = Locale.prototype;
+
+proto$1.calendar = calendar;
+proto$1.longDateFormat = longDateFormat;
+proto$1.invalidDate = invalidDate;
+proto$1.ordinal = ordinal;
+proto$1.preparse = preParsePostFormat;
+proto$1.postformat = preParsePostFormat;
+proto$1.relativeTime = relativeTime;
+proto$1.pastFuture = pastFuture;
+proto$1.set = set;
+
+// Month
+proto$1.months = localeMonths;
+proto$1.monthsShort = localeMonthsShort;
+proto$1.monthsParse = localeMonthsParse;
+proto$1.monthsRegex = monthsRegex;
+proto$1.monthsShortRegex = monthsShortRegex;
+
+// Week
+proto$1.week = localeWeek;
+proto$1.firstDayOfYear = localeFirstDayOfYear;
+proto$1.firstDayOfWeek = localeFirstDayOfWeek;
+
+// Day of Week
+proto$1.weekdays = localeWeekdays;
+proto$1.weekdaysMin = localeWeekdaysMin;
+proto$1.weekdaysShort = localeWeekdaysShort;
+proto$1.weekdaysParse = localeWeekdaysParse;
+
+proto$1.weekdaysRegex = weekdaysRegex;
+proto$1.weekdaysShortRegex = weekdaysShortRegex;
+proto$1.weekdaysMinRegex = weekdaysMinRegex;
+
+// Hours
+proto$1.isPM = localeIsPM;
+proto$1.meridiem = localeMeridiem;
+
+function get$1 (format, index, field, setter) {
+ var locale = getLocale();
+ var utc = createUTC().set(setter, index);
+ return locale[field](utc, format);
+}
+
+function listMonthsImpl (format, index, field) {
+ if (isNumber(format)) {
+ index = format;
+ format = undefined;
+ }
+
+ format = format || '';
+
+ if (index != null) {
+ return get$1(format, index, field, 'month');
+ }
+
+ var i;
+ var out = [];
+ for (i = 0; i < 12; i++) {
+ out[i] = get$1(format, i, field, 'month');
+ }
+ return out;
+}
+
+// ()
+// (5)
+// (fmt, 5)
+// (fmt)
+// (true)
+// (true, 5)
+// (true, fmt, 5)
+// (true, fmt)
+function listWeekdaysImpl (localeSorted, format, index, field) {
+ if (typeof localeSorted === 'boolean') {
+ if (isNumber(format)) {
+ index = format;
+ format = undefined;
+ }
+
+ format = format || '';
+ } else {
+ format = localeSorted;
+ index = format;
+ localeSorted = false;
+
+ if (isNumber(format)) {
+ index = format;
+ format = undefined;
+ }
+
+ format = format || '';
+ }
+
+ var locale = getLocale(),
+ shift = localeSorted ? locale._week.dow : 0;
+
+ if (index != null) {
+ return get$1(format, (index + shift) % 7, field, 'day');
+ }
+
+ var i;
+ var out = [];
+ for (i = 0; i < 7; i++) {
+ out[i] = get$1(format, (i + shift) % 7, field, 'day');
+ }
+ return out;
+}
+
+function listMonths (format, index) {
+ return listMonthsImpl(format, index, 'months');
+}
+
+function listMonthsShort (format, index) {
+ return listMonthsImpl(format, index, 'monthsShort');
+}
+
+function listWeekdays (localeSorted, format, index) {
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdays');
+}
+
+function listWeekdaysShort (localeSorted, format, index) {
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort');
+}
+
+function listWeekdaysMin (localeSorted, format, index) {
+ return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin');
+}
+
+getSetGlobalLocale('en', {
+ dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/,
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (toInt(number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ }
+});
+
+// Side effect imports
+hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale);
+hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale);
+
+var mathAbs = Math.abs;
+
+function abs () {
+ var data = this._data;
+
+ this._milliseconds = mathAbs(this._milliseconds);
+ this._days = mathAbs(this._days);
+ this._months = mathAbs(this._months);
+
+ data.milliseconds = mathAbs(data.milliseconds);
+ data.seconds = mathAbs(data.seconds);
+ data.minutes = mathAbs(data.minutes);
+ data.hours = mathAbs(data.hours);
+ data.months = mathAbs(data.months);
+ data.years = mathAbs(data.years);
+
+ return this;
+}
+
+function addSubtract$1 (duration, input, value, direction) {
+ var other = createDuration(input, value);
+
+ duration._milliseconds += direction * other._milliseconds;
+ duration._days += direction * other._days;
+ duration._months += direction * other._months;
+
+ return duration._bubble();
+}
+
+// supports only 2.0-style add(1, 's') or add(duration)
+function add$1 (input, value) {
+ return addSubtract$1(this, input, value, 1);
+}
+
+// supports only 2.0-style subtract(1, 's') or subtract(duration)
+function subtract$1 (input, value) {
+ return addSubtract$1(this, input, value, -1);
+}
+
+function absCeil (number) {
+ if (number < 0) {
+ return Math.floor(number);
+ } else {
+ return Math.ceil(number);
+ }
+}
+
+function bubble () {
+ var milliseconds = this._milliseconds;
+ var days = this._days;
+ var months = this._months;
+ var data = this._data;
+ var seconds, minutes, hours, years, monthsFromDays;
+
+ // if we have a mix of positive and negative values, bubble down first
+ // check: https://github.com/moment/moment/issues/2166
+ if (!((milliseconds >= 0 && days >= 0 && months >= 0) ||
+ (milliseconds <= 0 && days <= 0 && months <= 0))) {
+ milliseconds += absCeil(monthsToDays(months) + days) * 864e5;
+ days = 0;
+ months = 0;
+ }
+
+ // The following code bubbles up values, see the tests for
+ // examples of what that means.
+ data.milliseconds = milliseconds % 1000;
+
+ seconds = absFloor(milliseconds / 1000);
+ data.seconds = seconds % 60;
+
+ minutes = absFloor(seconds / 60);
+ data.minutes = minutes % 60;
+
+ hours = absFloor(minutes / 60);
+ data.hours = hours % 24;
+
+ days += absFloor(hours / 24);
+
+ // convert days to months
+ monthsFromDays = absFloor(daysToMonths(days));
+ months += monthsFromDays;
+ days -= absCeil(monthsToDays(monthsFromDays));
+
+ // 12 months -> 1 year
+ years = absFloor(months / 12);
+ months %= 12;
+
+ data.days = days;
+ data.months = months;
+ data.years = years;
+
+ return this;
+}
+
+function daysToMonths (days) {
+ // 400 years have 146097 days (taking into account leap year rules)
+ // 400 years have 12 months === 4800
+ return days * 4800 / 146097;
+}
+
+function monthsToDays (months) {
+ // the reverse of daysToMonths
+ return months * 146097 / 4800;
+}
+
+function as (units) {
+ if (!this.isValid()) {
+ return NaN;
+ }
+ var days;
+ var months;
+ var milliseconds = this._milliseconds;
+
+ units = normalizeUnits(units);
+
+ if (units === 'month' || units === 'year') {
+ days = this._days + milliseconds / 864e5;
+ months = this._months + daysToMonths(days);
+ return units === 'month' ? months : months / 12;
+ } else {
+ // handle milliseconds separately because of floating point math errors (issue #1867)
+ days = this._days + Math.round(monthsToDays(this._months));
+ switch (units) {
+ case 'week' : return days / 7 + milliseconds / 6048e5;
+ case 'day' : return days + milliseconds / 864e5;
+ case 'hour' : return days * 24 + milliseconds / 36e5;
+ case 'minute' : return days * 1440 + milliseconds / 6e4;
+ case 'second' : return days * 86400 + milliseconds / 1000;
+ // Math.floor prevents floating point math errors here
+ case 'millisecond': return Math.floor(days * 864e5) + milliseconds;
+ default: throw new Error('Unknown unit ' + units);
+ }
+ }
+}
+
+// TODO: Use this.as('ms')?
+function valueOf$1 () {
+ if (!this.isValid()) {
+ return NaN;
+ }
+ return (
+ this._milliseconds +
+ this._days * 864e5 +
+ (this._months % 12) * 2592e6 +
+ toInt(this._months / 12) * 31536e6
+ );
+}
+
+function makeAs (alias) {
+ return function () {
+ return this.as(alias);
+ };
+}
+
+var asMilliseconds = makeAs('ms');
+var asSeconds = makeAs('s');
+var asMinutes = makeAs('m');
+var asHours = makeAs('h');
+var asDays = makeAs('d');
+var asWeeks = makeAs('w');
+var asMonths = makeAs('M');
+var asYears = makeAs('y');
+
+function clone$1 () {
+ return createDuration(this);
+}
+
+function get$2 (units) {
+ units = normalizeUnits(units);
+ return this.isValid() ? this[units + 's']() : NaN;
+}
+
+function makeGetter(name) {
+ return function () {
+ return this.isValid() ? this._data[name] : NaN;
+ };
+}
+
+var milliseconds = makeGetter('milliseconds');
+var seconds = makeGetter('seconds');
+var minutes = makeGetter('minutes');
+var hours = makeGetter('hours');
+var days = makeGetter('days');
+var months = makeGetter('months');
+var years = makeGetter('years');
+
+function weeks () {
+ return absFloor(this.days() / 7);
+}
+
+var round = Math.round;
+var thresholds = {
+ ss: 44, // a few seconds to seconds
+ s : 45, // seconds to minute
+ m : 45, // minutes to hour
+ h : 22, // hours to day
+ d : 26, // days to month
+ M : 11 // months to year
+};
+
+// helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
+function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
+ return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
+}
+
+function relativeTime$1 (posNegDuration, withoutSuffix, locale) {
+ var duration = createDuration(posNegDuration).abs();
+ var seconds = round(duration.as('s'));
+ var minutes = round(duration.as('m'));
+ var hours = round(duration.as('h'));
+ var days = round(duration.as('d'));
+ var months = round(duration.as('M'));
+ var years = round(duration.as('y'));
+
+ var a = seconds <= thresholds.ss && ['s', seconds] ||
+ seconds < thresholds.s && ['ss', seconds] ||
+ minutes <= 1 && ['m'] ||
+ minutes < thresholds.m && ['mm', minutes] ||
+ hours <= 1 && ['h'] ||
+ hours < thresholds.h && ['hh', hours] ||
+ days <= 1 && ['d'] ||
+ days < thresholds.d && ['dd', days] ||
+ months <= 1 && ['M'] ||
+ months < thresholds.M && ['MM', months] ||
+ years <= 1 && ['y'] || ['yy', years];
+
+ a[2] = withoutSuffix;
+ a[3] = +posNegDuration > 0;
+ a[4] = locale;
+ return substituteTimeAgo.apply(null, a);
+}
+
+// This function allows you to set the rounding function for relative time strings
+function getSetRelativeTimeRounding (roundingFunction) {
+ if (roundingFunction === undefined) {
+ return round;
+ }
+ if (typeof(roundingFunction) === 'function') {
+ round = roundingFunction;
+ return true;
+ }
+ return false;
+}
+
+// This function allows you to set a threshold for relative time strings
+function getSetRelativeTimeThreshold (threshold, limit) {
+ if (thresholds[threshold] === undefined) {
+ return false;
+ }
+ if (limit === undefined) {
+ return thresholds[threshold];
+ }
+ thresholds[threshold] = limit;
+ if (threshold === 's') {
+ thresholds.ss = limit - 1;
+ }
+ return true;
+}
+
+function humanize (withSuffix) {
+ if (!this.isValid()) {
+ return this.localeData().invalidDate();
+ }
+
+ var locale = this.localeData();
+ var output = relativeTime$1(this, !withSuffix, locale);
+
+ if (withSuffix) {
+ output = locale.pastFuture(+this, output);
+ }
+
+ return locale.postformat(output);
+}
+
+var abs$1 = Math.abs;
+
+function sign(x) {
+ return ((x > 0) - (x < 0)) || +x;
+}
+
+function toISOString$1() {
+ // for ISO strings we do not use the normal bubbling rules:
+ // * milliseconds bubble up until they become hours
+ // * days do not bubble at all
+ // * months bubble up until they become years
+ // This is because there is no context-free conversion between hours and days
+ // (think of clock changes)
+ // and also not between days and months (28-31 days per month)
+ if (!this.isValid()) {
+ return this.localeData().invalidDate();
+ }
+
+ var seconds = abs$1(this._milliseconds) / 1000;
+ var days = abs$1(this._days);
+ var months = abs$1(this._months);
+ var minutes, hours, years;
+
+ // 3600 seconds -> 60 minutes -> 1 hour
+ minutes = absFloor(seconds / 60);
+ hours = absFloor(minutes / 60);
+ seconds %= 60;
+ minutes %= 60;
+
+ // 12 months -> 1 year
+ years = absFloor(months / 12);
+ months %= 12;
+
+
+ // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
+ var Y = years;
+ var M = months;
+ var D = days;
+ var h = hours;
+ var m = minutes;
+ var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : '';
+ var total = this.asSeconds();
+
+ if (!total) {
+ // this is the same as C#'s (Noda) and python (isodate)...
+ // but not other JS (goog.date)
+ return 'P0D';
+ }
+
+ var totalSign = total < 0 ? '-' : '';
+ var ymSign = sign(this._months) !== sign(total) ? '-' : '';
+ var daysSign = sign(this._days) !== sign(total) ? '-' : '';
+ var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : '';
+
+ return totalSign + 'P' +
+ (Y ? ymSign + Y + 'Y' : '') +
+ (M ? ymSign + M + 'M' : '') +
+ (D ? daysSign + D + 'D' : '') +
+ ((h || m || s) ? 'T' : '') +
+ (h ? hmsSign + h + 'H' : '') +
+ (m ? hmsSign + m + 'M' : '') +
+ (s ? hmsSign + s + 'S' : '');
+}
+
+var proto$2 = Duration.prototype;
+
+proto$2.isValid = isValid$1;
+proto$2.abs = abs;
+proto$2.add = add$1;
+proto$2.subtract = subtract$1;
+proto$2.as = as;
+proto$2.asMilliseconds = asMilliseconds;
+proto$2.asSeconds = asSeconds;
+proto$2.asMinutes = asMinutes;
+proto$2.asHours = asHours;
+proto$2.asDays = asDays;
+proto$2.asWeeks = asWeeks;
+proto$2.asMonths = asMonths;
+proto$2.asYears = asYears;
+proto$2.valueOf = valueOf$1;
+proto$2._bubble = bubble;
+proto$2.clone = clone$1;
+proto$2.get = get$2;
+proto$2.milliseconds = milliseconds;
+proto$2.seconds = seconds;
+proto$2.minutes = minutes;
+proto$2.hours = hours;
+proto$2.days = days;
+proto$2.weeks = weeks;
+proto$2.months = months;
+proto$2.years = years;
+proto$2.humanize = humanize;
+proto$2.toISOString = toISOString$1;
+proto$2.toString = toISOString$1;
+proto$2.toJSON = toISOString$1;
+proto$2.locale = locale;
+proto$2.localeData = localeData;
+
+// Deprecations
+proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1);
+proto$2.lang = lang;
+
+// Side effect imports
+
+// FORMATTING
+
+addFormatToken('X', 0, 0, 'unix');
+addFormatToken('x', 0, 0, 'valueOf');
+
+// PARSING
+
+addRegexToken('x', matchSigned);
+addRegexToken('X', matchTimestamp);
+addParseToken('X', function (input, array, config) {
+ config._d = new Date(parseFloat(input, 10) * 1000);
+});
+addParseToken('x', function (input, array, config) {
+ config._d = new Date(toInt(input));
+});
+
+// Side effect imports
+
+
+hooks.version = '2.19.3';
+
+setHookCallback(createLocal);
+
+hooks.fn = proto;
+hooks.min = min;
+hooks.max = max;
+hooks.now = now;
+hooks.utc = createUTC;
+hooks.unix = createUnix;
+hooks.months = listMonths;
+hooks.isDate = isDate;
+hooks.locale = getSetGlobalLocale;
+hooks.invalid = createInvalid;
+hooks.duration = createDuration;
+hooks.isMoment = isMoment;
+hooks.weekdays = listWeekdays;
+hooks.parseZone = createInZone;
+hooks.localeData = getLocale;
+hooks.isDuration = isDuration;
+hooks.monthsShort = listMonthsShort;
+hooks.weekdaysMin = listWeekdaysMin;
+hooks.defineLocale = defineLocale;
+hooks.updateLocale = updateLocale;
+hooks.locales = listLocales;
+hooks.weekdaysShort = listWeekdaysShort;
+hooks.normalizeUnits = normalizeUnits;
+hooks.relativeTimeRounding = getSetRelativeTimeRounding;
+hooks.relativeTimeThreshold = getSetRelativeTimeThreshold;
+hooks.calendarFormat = getCalendarFormat;
+hooks.prototype = proto;
+
+return hooks;
+
+})));
diff --git a/www/wiki/resources/lib/mustache/LICENSE b/www/wiki/resources/lib/mustache/LICENSE
new file mode 100644
index 00000000..aa1b8316
--- /dev/null
+++ b/www/wiki/resources/lib/mustache/LICENSE
@@ -0,0 +1,10 @@
+The MIT License
+
+Copyright (c) 2009 Chris Wanstrath (Ruby)
+Copyright (c) 2010-2014 Jan Lehnardt (JavaScript)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/www/wiki/resources/lib/mustache/mustache.js b/www/wiki/resources/lib/mustache/mustache.js
new file mode 100644
index 00000000..dbc98231
--- /dev/null
+++ b/www/wiki/resources/lib/mustache/mustache.js
@@ -0,0 +1,578 @@
+/*!
+ * mustache.js - Logic-less {{mustache}} templates with JavaScript
+ * http://github.com/janl/mustache.js
+ */
+
+/*global define: false*/
+
+(function (global, factory) {
+ if (typeof exports === "object" && exports) {
+ factory(exports); // CommonJS
+ } else if (typeof define === "function" && define.amd) {
+ define(['exports'], factory); // AMD
+ } else {
+ factory(global.Mustache = {}); // <script>
+ }
+}(this, function (mustache) {
+
+ var Object_toString = Object.prototype.toString;
+ var isArray = Array.isArray || function (object) {
+ return Object_toString.call(object) === '[object Array]';
+ };
+
+ function isFunction(object) {
+ return typeof object === 'function';
+ }
+
+ function escapeRegExp(string) {
+ return string.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
+ }
+
+ // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577
+ // See https://github.com/janl/mustache.js/issues/189
+ var RegExp_test = RegExp.prototype.test;
+ function testRegExp(re, string) {
+ return RegExp_test.call(re, string);
+ }
+
+ var nonSpaceRe = /\S/;
+ function isWhitespace(string) {
+ return !testRegExp(nonSpaceRe, string);
+ }
+
+ var entityMap = {
+ "&": "&amp;",
+ "<": "&lt;",
+ ">": "&gt;",
+ '"': '&quot;',
+ "'": '&#39;',
+ "/": '&#x2F;'
+ };
+
+ function escapeHtml(string) {
+ return String(string).replace(/[&<>"'\/]/g, function (s) {
+ return entityMap[s];
+ });
+ }
+
+ var whiteRe = /\s*/;
+ var spaceRe = /\s+/;
+ var equalsRe = /\s*=/;
+ var curlyRe = /\s*\}/;
+ var tagRe = /#|\^|\/|>|\{|&|=|!/;
+
+ /**
+ * Breaks up the given `template` string into a tree of tokens. If the `tags`
+ * argument is given here it must be an array with two string values: the
+ * opening and closing tags used in the template (e.g. [ "<%", "%>" ]). Of
+ * course, the default is to use mustaches (i.e. mustache.tags).
+ *
+ * A token is an array with at least 4 elements. The first element is the
+ * mustache symbol that was used inside the tag, e.g. "#" or "&". If the tag
+ * did not contain a symbol (i.e. {{myValue}}) this element is "name". For
+ * all text that appears outside a symbol this element is "text".
+ *
+ * The second element of a token is its "value". For mustache tags this is
+ * whatever else was inside the tag besides the opening symbol. For text tokens
+ * this is the text itself.
+ *
+ * The third and fourth elements of the token are the start and end indices,
+ * respectively, of the token in the original template.
+ *
+ * Tokens that are the root node of a subtree contain two more elements: 1) an
+ * array of tokens in the subtree and 2) the index in the original template at
+ * which the closing tag for that section begins.
+ */
+ function parseTemplate(template, tags) {
+ if (!template)
+ return [];
+
+ var sections = []; // Stack to hold section tokens
+ var tokens = []; // Buffer to hold the tokens
+ var spaces = []; // Indices of whitespace tokens on the current line
+ var hasTag = false; // Is there a {{tag}} on the current line?
+ var nonSpace = false; // Is there a non-space char on the current line?
+
+ // Strips all whitespace tokens array for the current line
+ // if there was a {{#tag}} on it and otherwise only space.
+ function stripSpace() {
+ if (hasTag && !nonSpace) {
+ while (spaces.length)
+ delete tokens[spaces.pop()];
+ } else {
+ spaces = [];
+ }
+
+ hasTag = false;
+ nonSpace = false;
+ }
+
+ var openingTagRe, closingTagRe, closingCurlyRe;
+ function compileTags(tags) {
+ if (typeof tags === 'string')
+ tags = tags.split(spaceRe, 2);
+
+ if (!isArray(tags) || tags.length !== 2)
+ throw new Error('Invalid tags: ' + tags);
+
+ openingTagRe = new RegExp(escapeRegExp(tags[0]) + '\\s*');
+ closingTagRe = new RegExp('\\s*' + escapeRegExp(tags[1]));
+ closingCurlyRe = new RegExp('\\s*' + escapeRegExp('}' + tags[1]));
+ }
+
+ compileTags(tags || mustache.tags);
+
+ var scanner = new Scanner(template);
+
+ var start, type, value, chr, token, openSection;
+ while (!scanner.eos()) {
+ start = scanner.pos;
+
+ // Match any text between tags.
+ value = scanner.scanUntil(openingTagRe);
+
+ if (value) {
+ for (var i = 0, valueLength = value.length; i < valueLength; ++i) {
+ chr = value.charAt(i);
+
+ if (isWhitespace(chr)) {
+ spaces.push(tokens.length);
+ } else {
+ nonSpace = true;
+ }
+
+ tokens.push([ 'text', chr, start, start + 1 ]);
+ start += 1;
+
+ // Check for whitespace on the current line.
+ if (chr === '\n')
+ stripSpace();
+ }
+ }
+
+ // Match the opening tag.
+ if (!scanner.scan(openingTagRe))
+ break;
+
+ hasTag = true;
+
+ // Get the tag type.
+ type = scanner.scan(tagRe) || 'name';
+ scanner.scan(whiteRe);
+
+ // Get the tag value.
+ if (type === '=') {
+ value = scanner.scanUntil(equalsRe);
+ scanner.scan(equalsRe);
+ scanner.scanUntil(closingTagRe);
+ } else if (type === '{') {
+ value = scanner.scanUntil(closingCurlyRe);
+ scanner.scan(curlyRe);
+ scanner.scanUntil(closingTagRe);
+ type = '&';
+ } else {
+ value = scanner.scanUntil(closingTagRe);
+ }
+
+ // Match the closing tag.
+ if (!scanner.scan(closingTagRe))
+ throw new Error('Unclosed tag at ' + scanner.pos);
+
+ token = [ type, value, start, scanner.pos ];
+ tokens.push(token);
+
+ if (type === '#' || type === '^') {
+ sections.push(token);
+ } else if (type === '/') {
+ // Check section nesting.
+ openSection = sections.pop();
+
+ if (!openSection)
+ throw new Error('Unopened section "' + value + '" at ' + start);
+
+ if (openSection[1] !== value)
+ throw new Error('Unclosed section "' + openSection[1] + '" at ' + start);
+ } else if (type === 'name' || type === '{' || type === '&') {
+ nonSpace = true;
+ } else if (type === '=') {
+ // Set the tags for the next time around.
+ compileTags(value);
+ }
+ }
+
+ // Make sure there are no open sections when we're done.
+ openSection = sections.pop();
+
+ if (openSection)
+ throw new Error('Unclosed section "' + openSection[1] + '" at ' + scanner.pos);
+
+ return nestTokens(squashTokens(tokens));
+ }
+
+ /**
+ * Combines the values of consecutive text tokens in the given `tokens` array
+ * to a single token.
+ */
+ function squashTokens(tokens) {
+ var squashedTokens = [];
+
+ var token, lastToken;
+ for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
+ token = tokens[i];
+
+ if (token) {
+ if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {
+ lastToken[1] += token[1];
+ lastToken[3] = token[3];
+ } else {
+ squashedTokens.push(token);
+ lastToken = token;
+ }
+ }
+ }
+
+ return squashedTokens;
+ }
+
+ /**
+ * Forms the given array of `tokens` into a nested tree structure where
+ * tokens that represent a section have two additional items: 1) an array of
+ * all tokens that appear in that section and 2) the index in the original
+ * template that represents the end of that section.
+ */
+ function nestTokens(tokens) {
+ var nestedTokens = [];
+ var collector = nestedTokens;
+ var sections = [];
+
+ var token, section;
+ for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
+ token = tokens[i];
+
+ switch (token[0]) {
+ case '#':
+ case '^':
+ collector.push(token);
+ sections.push(token);
+ collector = token[4] = [];
+ break;
+ case '/':
+ section = sections.pop();
+ section[5] = token[2];
+ collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;
+ break;
+ default:
+ collector.push(token);
+ }
+ }
+
+ return nestedTokens;
+ }
+
+ /**
+ * A simple string scanner that is used by the template parser to find
+ * tokens in template strings.
+ */
+ function Scanner(string) {
+ this.string = string;
+ this.tail = string;
+ this.pos = 0;
+ }
+
+ /**
+ * Returns `true` if the tail is empty (end of string).
+ */
+ Scanner.prototype.eos = function () {
+ return this.tail === "";
+ };
+
+ /**
+ * Tries to match the given regular expression at the current position.
+ * Returns the matched text if it can match, the empty string otherwise.
+ */
+ Scanner.prototype.scan = function (re) {
+ var match = this.tail.match(re);
+
+ if (!match || match.index !== 0)
+ return '';
+
+ var string = match[0];
+
+ this.tail = this.tail.substring(string.length);
+ this.pos += string.length;
+
+ return string;
+ };
+
+ /**
+ * Skips all text until the given regular expression can be matched. Returns
+ * the skipped string, which is the entire tail if no match can be made.
+ */
+ Scanner.prototype.scanUntil = function (re) {
+ var index = this.tail.search(re), match;
+
+ switch (index) {
+ case -1:
+ match = this.tail;
+ this.tail = "";
+ break;
+ case 0:
+ match = "";
+ break;
+ default:
+ match = this.tail.substring(0, index);
+ this.tail = this.tail.substring(index);
+ }
+
+ this.pos += match.length;
+
+ return match;
+ };
+
+ /**
+ * Represents a rendering context by wrapping a view object and
+ * maintaining a reference to the parent context.
+ */
+ function Context(view, parentContext) {
+ this.view = view == null ? {} : view;
+ this.cache = { '.': this.view };
+ this.parent = parentContext;
+ }
+
+ /**
+ * Creates a new context using the given view with this context
+ * as the parent.
+ */
+ Context.prototype.push = function (view) {
+ return new Context(view, this);
+ };
+
+ /**
+ * Returns the value of the given name in this context, traversing
+ * up the context hierarchy if the value is absent in this context's view.
+ */
+ Context.prototype.lookup = function (name) {
+ var cache = this.cache;
+
+ var value;
+ if (name in cache) {
+ value = cache[name];
+ } else {
+ var context = this, names, index;
+
+ while (context) {
+ if (name.indexOf('.') > 0) {
+ value = context.view;
+ names = name.split('.');
+ index = 0;
+
+ while (value != null && index < names.length)
+ value = value[names[index++]];
+ } else if (typeof context.view == 'object') {
+ value = context.view[name];
+ }
+
+ if (value != null)
+ break;
+
+ context = context.parent;
+ }
+
+ cache[name] = value;
+ }
+
+ if (isFunction(value))
+ value = value.call(this.view);
+
+ return value;
+ };
+
+ /**
+ * A Writer knows how to take a stream of tokens and render them to a
+ * string, given a context. It also maintains a cache of templates to
+ * avoid the need to parse the same template twice.
+ */
+ function Writer() {
+ this.cache = {};
+ }
+
+ /**
+ * Clears all cached templates in this writer.
+ */
+ Writer.prototype.clearCache = function () {
+ this.cache = {};
+ };
+
+ /**
+ * Parses and caches the given `template` and returns the array of tokens
+ * that is generated from the parse.
+ */
+ Writer.prototype.parse = function (template, tags) {
+ var cache = this.cache;
+ var tokens = cache[template];
+
+ if (tokens == null)
+ tokens = cache[template] = parseTemplate(template, tags);
+
+ return tokens;
+ };
+
+ /**
+ * High-level method that is used to render the given `template` with
+ * the given `view`.
+ *
+ * The optional `partials` argument may be an object that contains the
+ * names and templates of partials that are used in the template. It may
+ * also be a function that is used to load partial templates on the fly
+ * that takes a single argument: the name of the partial.
+ */
+ Writer.prototype.render = function (template, view, partials) {
+ var tokens = this.parse(template);
+ var context = (view instanceof Context) ? view : new Context(view);
+ return this.renderTokens(tokens, context, partials, template);
+ };
+
+ /**
+ * Low-level method that renders the given array of `tokens` using
+ * the given `context` and `partials`.
+ *
+ * Note: The `originalTemplate` is only ever used to extract the portion
+ * of the original template that was contained in a higher-order section.
+ * If the template doesn't use higher-order sections, this argument may
+ * be omitted.
+ */
+ Writer.prototype.renderTokens = function (tokens, context, partials, originalTemplate) {
+ var buffer = '';
+
+ // This function is used to render an arbitrary template
+ // in the current context by higher-order sections.
+ var self = this;
+ function subRender(template) {
+ return self.render(template, context, partials);
+ }
+
+ var token, value;
+ for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {
+ token = tokens[i];
+
+ switch (token[0]) {
+ case '#':
+ value = context.lookup(token[1]);
+
+ if (!value)
+ continue;
+
+ if (isArray(value)) {
+ for (var j = 0, valueLength = value.length; j < valueLength; ++j) {
+ buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);
+ }
+ } else if (typeof value === 'object' || typeof value === 'string') {
+ buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);
+ } else if (isFunction(value)) {
+ if (typeof originalTemplate !== 'string')
+ throw new Error('Cannot use higher-order sections without the original template');
+
+ // Extract the portion of the original template that the section contains.
+ value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);
+
+ if (value != null)
+ buffer += value;
+ } else {
+ buffer += this.renderTokens(token[4], context, partials, originalTemplate);
+ }
+
+ break;
+ case '^':
+ value = context.lookup(token[1]);
+
+ // Use JavaScript's definition of falsy. Include empty arrays.
+ // See https://github.com/janl/mustache.js/issues/186
+ if (!value || (isArray(value) && value.length === 0))
+ buffer += this.renderTokens(token[4], context, partials, originalTemplate);
+
+ break;
+ case '>':
+ if (!partials)
+ continue;
+
+ value = isFunction(partials) ? partials(token[1]) : partials[token[1]];
+
+ if (value != null)
+ buffer += this.renderTokens(this.parse(value), context, partials, value);
+
+ break;
+ case '&':
+ value = context.lookup(token[1]);
+
+ if (value != null)
+ buffer += value;
+
+ break;
+ case 'name':
+ value = context.lookup(token[1]);
+
+ if (value != null)
+ buffer += mustache.escape(value);
+
+ break;
+ case 'text':
+ buffer += token[1];
+ break;
+ }
+ }
+
+ return buffer;
+ };
+
+ mustache.name = "mustache.js";
+ mustache.version = "0.8.2";
+ mustache.tags = [ "{{", "}}" ];
+
+ // All high-level mustache.* functions use this writer.
+ var defaultWriter = new Writer();
+
+ /**
+ * Clears all cached templates in the default writer.
+ */
+ mustache.clearCache = function () {
+ return defaultWriter.clearCache();
+ };
+
+ /**
+ * Parses and caches the given template in the default writer and returns the
+ * array of tokens it contains. Doing this ahead of time avoids the need to
+ * parse templates on the fly as they are rendered.
+ */
+ mustache.parse = function (template, tags) {
+ return defaultWriter.parse(template, tags);
+ };
+
+ /**
+ * Renders the `template` with the given `view` and `partials` using the
+ * default writer.
+ */
+ mustache.render = function (template, view, partials) {
+ return defaultWriter.render(template, view, partials);
+ };
+
+ // This is here for backwards compatibility with 0.4.x.
+ mustache.to_html = function (template, view, partials, send) {
+ var result = mustache.render(template, view, partials);
+
+ if (isFunction(send)) {
+ send(result);
+ } else {
+ return result;
+ }
+ };
+
+ // Export the escaping function so that the user may override it.
+ // See https://github.com/janl/mustache.js/issues/244
+ mustache.escape = escapeHtml;
+
+ // Export these mainly for testing, but also for advanced usage.
+ mustache.Scanner = Scanner;
+ mustache.Context = Context;
+ mustache.Writer = Writer;
+
+}));
diff --git a/www/wiki/resources/lib/oojs-router/AUTHORS.txt b/www/wiki/resources/lib/oojs-router/AUTHORS.txt
new file mode 100644
index 00000000..5390c84c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-router/AUTHORS.txt
@@ -0,0 +1 @@
+Jon Robson <jdlrobson@gmail.com>
diff --git a/www/wiki/resources/lib/oojs-router/LICENSE-MIT b/www/wiki/resources/lib/oojs-router/LICENSE-MIT
new file mode 100644
index 00000000..acbe7089
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-router/LICENSE-MIT
@@ -0,0 +1,20 @@
+Copyright 2011-2016 OOjs Team and other contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/www/wiki/resources/lib/oojs-router/oojs-router.js b/www/wiki/resources/lib/oojs-router/oojs-router.js
new file mode 100644
index 00000000..b136923e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-router/oojs-router.js
@@ -0,0 +1,205 @@
+/*!
+ * OOjs Router v0.1.0
+ * https://www.mediawiki.org/wiki/OOjs
+ *
+ * Copyright 2011-2016 OOjs Team and other contributors.
+ * Released under the MIT license
+ * http://oojs-router.mit-license.org
+ *
+ * Date: 2016-05-05T19:27:58Z
+ */
+( function ( $ ) {
+
+'use strict';
+
+/**
+ * Does hash match entry.path? If it does apply the
+ * callback for the Entry object.
+ *
+ * @method
+ * @private
+ * @ignore
+ * @param {string} hash string to match
+ * @param {Object} entry Entry object
+ * @return {boolean} Whether hash matches entry.path
+ */
+function matchRoute( hash, entry ) {
+ var match = hash.match( entry.path );
+ if ( match ) {
+ entry.callback.apply( this, match.slice( 1 ) );
+ return true;
+ }
+ return false;
+}
+
+/**
+ * Provides navigation routing and location information
+ *
+ * @class Router
+ * @mixins OO.EventEmitter
+ */
+function Router() {
+ var self = this;
+ OO.EventEmitter.call( this );
+ // use an object instead of an array for routes so that we don't
+ // duplicate entries that already exist
+ this.routes = {};
+ this.enabled = true;
+ this.oldHash = this.getPath();
+
+ $( window ).on( 'popstate', function () {
+ self.emit( 'popstate' );
+ } );
+
+ $( window ).on( 'hashchange', function () {
+ self.emit( 'hashchange' );
+ } );
+
+ this.on( 'hashchange', function () {
+ // ev.originalEvent.newURL is undefined on Android 2.x
+ var routeEv;
+
+ if ( self.enabled ) {
+ routeEv = $.Event( 'route', {
+ path: self.getPath()
+ } );
+ self.emit( 'route', routeEv );
+
+ if ( !routeEv.isDefaultPrevented() ) {
+ self.checkRoute();
+ } else {
+ // if route was prevented, ignore the next hash change and revert the
+ // hash to its old value
+ self.enabled = false;
+ self.navigate( self.oldHash );
+ }
+ } else {
+ self.enabled = true;
+ }
+
+ self.oldHash = self.getPath();
+ } );
+}
+OO.mixinClass( Router, OO.EventEmitter );
+
+/**
+ * Check the current route and run appropriate callback if it matches.
+ *
+ * @method
+ */
+Router.prototype.checkRoute = function () {
+ var hash = this.getPath();
+
+ $.each( this.routes, function ( id, entry ) {
+ return !matchRoute( hash, entry );
+ } );
+};
+
+/**
+ * Bind a specific callback to a hash-based route, e.g.
+ *
+ * @example
+ * route( 'alert', function () { alert( 'something' ); } );
+ * route( /hi-(.*)/, function ( name ) { alert( 'Hi ' + name ) } );
+ * Note that after defining all available routes it is up to the caller
+ * to check the existing route via the checkRoute method.
+ *
+ * @method
+ * @param {Object} path string or RegExp to match.
+ * @param {Function} callback Callback to be run when hash changes to one
+ * that matches.
+ */
+Router.prototype.route = function ( path, callback ) {
+ var entry = {
+ path: typeof path === 'string' ?
+ new RegExp( '^' + path.replace( /[\\^$*+?.()|[\]{}]/g, '\\$&' ) + '$' )
+ : path,
+ callback: callback
+ };
+ this.routes[ entry.path ] = entry;
+};
+
+/**
+ * Navigate to a specific route.
+ *
+ * @method
+ * @param {string} path string with a route (hash without #).
+ */
+Router.prototype.navigate = function ( path ) {
+ var history = window.history;
+ // Take advantage of `pushState` when available, to clear the hash and
+ // not leave `#` in the history. An entry with `#` in the history has
+ // the side-effect of resetting the scroll position when navigating the
+ // history.
+ if ( path === '' && history && history.pushState ) {
+ // To clear the hash we need to cut the hash from the URL.
+ path = window.location.href.replace( /#.*$/, '' );
+ history.pushState( null, document.title, path );
+ this.checkRoute();
+ } else {
+ window.location.hash = path;
+ }
+};
+
+/**
+ * Triggers back on the window
+ */
+Router.prototype.goBack = function () {
+ window.history.back();
+};
+
+/**
+ * Navigate to the previous route. This is a wrapper for window.history.back
+ *
+ * @method
+ * @return {jQuery.Deferred}
+ */
+Router.prototype.back = function () {
+ var deferredRequest = $.Deferred(),
+ self = this,
+ timeoutID;
+
+ this.once( 'popstate', function () {
+ clearTimeout( timeoutID );
+ deferredRequest.resolve();
+ } );
+
+ this.goBack();
+
+ // If for some reason (old browser, bug in IE/windows 8.1, etc) popstate doesn't fire,
+ // resolve manually. Since we don't know for sure which browsers besides IE10/11 have
+ // this problem, it's better to fall back this way rather than singling out browsers
+ // and resolving the deferred request for them individually.
+ // See https://connect.microsoft.com/IE/feedback/details/793618/history-back-popstate-not-working-as-expected-in-webview-control
+ // Give browser a few ms to update its history.
+ timeoutID = setTimeout( function () {
+ self.off( 'popstate' );
+ deferredRequest.resolve();
+ }, 50 );
+
+ return deferredRequest;
+};
+
+/**
+ * Get current path (hash).
+ *
+ * @method
+ * @return {string} Current path.
+ */
+Router.prototype.getPath = function () {
+ return window.location.hash.slice( 1 );
+};
+
+/**
+ * Determine if current browser supports onhashchange event
+ *
+ * @method
+ * @return {boolean}
+ */
+Router.prototype.isSupported = function () {
+ return 'onhashchange' in window;
+};
+
+module.exports = Router;
+
+}( jQuery ) );
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ace.json b/www/wiki/resources/lib/oojs-ui/i18n/ace.json
new file mode 100644
index 00000000..0fdc1a89
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ace.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Si Gam Acèh"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pinah item u yup",
+ "ooui-outline-control-move-up": "Pinah item u ateuëh",
+ "ooui-toolbar-more": "Lom"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/af.json b/www/wiki/resources/lib/oojs-ui/i18n/af.json
new file mode 100644
index 00000000..ed56521f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/af.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Naudefj",
+ "Fwolff"
+ ]
+ },
+ "ooui-outline-control-move-down": "Skuif item af",
+ "ooui-outline-control-move-up": "Skuif item op",
+ "ooui-outline-control-remove": "Verwyder item",
+ "ooui-toolbar-more": "Meer",
+ "ooui-toolgroup-expand": "Meer",
+ "ooui-toolgroup-collapse": "Minder",
+ "ooui-dialog-message-accept": "Regso",
+ "ooui-dialog-message-reject": "Kanselleer",
+ "ooui-dialog-process-error": "Iets het verkeerd gegaan",
+ "ooui-dialog-process-dismiss": "Sluit",
+ "ooui-dialog-process-retry": "Probeer weer",
+ "ooui-dialog-process-continue": "Gaan voort",
+ "ooui-selectfile-button-select": "Kies 'n lêer",
+ "ooui-selectfile-not-supported": "Lêers kan nie gekies word nie",
+ "ooui-selectfile-placeholder": "Geen lêer is gekies nie",
+ "ooui-selectfile-dragdrop-placeholder": "Laat val die lêer hier"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ais.json b/www/wiki/resources/lib/oojs-ui/i18n/ais.json
new file mode 100644
index 00000000..78c22fed
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ais.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bunukwiki"
+ ]
+ },
+ "ooui-toolbar-more": "yadah",
+ "ooui-toolgroup-expand": "yadah",
+ "ooui-toolgroup-collapse": "ma’ngadis mangalep",
+ "ooui-item-remove": "milimad",
+ "ooui-dialog-message-accept": "malucekay",
+ "ooui-dialog-message-reject": "palawpes",
+ "ooui-dialog-process-dismiss": "edeben",
+ "ooui-dialog-process-continue": "palalid"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/am.json b/www/wiki/resources/lib/oojs-ui/i18n/am.json
new file mode 100644
index 00000000..bfe9d5c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/am.json
@@ -0,0 +1,7 @@
+{
+ "@metadata": {
+ "authors": [
+ "Elfalem"
+ ]
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ar.json b/www/wiki/resources/lib/oojs-ui/i18n/ar.json
new file mode 100644
index 00000000..ad2995a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ar.json
@@ -0,0 +1,36 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ciphers",
+ "Claw eg",
+ "Elfalem",
+ "Jdforrester",
+ "Mido",
+ "OsamaK",
+ "زكريا",
+ "مشعل الحربي",
+ "ترجمان05",
+ "Abanima",
+ "محمد أحمد عبد الفتاح",
+ "Hiba Alshawi",
+ "Meno25"
+ ]
+ },
+ "ooui-outline-control-move-down": "انقل العنصر للأسفل",
+ "ooui-outline-control-move-up": "انقل العنصر للأعلى",
+ "ooui-outline-control-remove": "أزل العنصر",
+ "ooui-toolbar-more": "مزيد",
+ "ooui-toolgroup-expand": "مزيد",
+ "ooui-toolgroup-collapse": "أقل",
+ "ooui-item-remove": "إزالة",
+ "ooui-dialog-message-accept": "موافق",
+ "ooui-dialog-message-reject": "ألغ",
+ "ooui-dialog-process-error": "حدث خطأ",
+ "ooui-dialog-process-dismiss": "أغلق",
+ "ooui-dialog-process-retry": "حاول مرة أخرى",
+ "ooui-dialog-process-continue": "استمر",
+ "ooui-selectfile-button-select": "اختر ملفا",
+ "ooui-selectfile-not-supported": "اختيار الملفات غير مدعوم",
+ "ooui-selectfile-placeholder": "لم يتم اختيار أي ملف",
+ "ooui-selectfile-dragdrop-placeholder": "اترك الملف هنا"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/arc.json b/www/wiki/resources/lib/oojs-ui/i18n/arc.json
new file mode 100644
index 00000000..de5b7aff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/arc.json
@@ -0,0 +1,7 @@
+{
+ "@metadata": {
+ "authors": [
+ "Basharh"
+ ]
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/arq.json b/www/wiki/resources/lib/oojs-ui/i18n/arq.json
new file mode 100644
index 00000000..61eb3844
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/arq.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bachounda"
+ ]
+ },
+ "ooui-outline-control-move-down": "هبط الشيئ للتحت",
+ "ooui-outline-control-move-up": "طلع الشيئ للفوق",
+ "ooui-outline-control-remove": "أمحي العنصر",
+ "ooui-toolbar-more": "زيادة",
+ "ooui-toolgroup-expand": "زيادة",
+ "ooui-toolgroup-collapse": "قليل",
+ "ooui-dialog-message-accept": "مليح",
+ "ooui-dialog-message-reject": "رجَع",
+ "ooui-dialog-process-error": "حاجه ما خدمتش مليح",
+ "ooui-dialog-process-dismiss": "أرفضها",
+ "ooui-dialog-process-retry": "عاود جرب",
+ "ooui-dialog-process-continue": "واصل",
+ "ooui-selectfile-not-supported": "تحديد الفيشيات ما هوش محدد",
+ "ooui-selectfile-placeholder": "ما اختاريتش حتا ملف"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/as.json b/www/wiki/resources/lib/oojs-ui/i18n/as.json
new file mode 100644
index 00000000..54a42441
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/as.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gitartha.bordoloi",
+ "Dibya Dutta",
+ "IKHazarika"
+ ]
+ },
+ "ooui-outline-control-move-down": "সমল তললৈ স্থানান্তৰ কৰক",
+ "ooui-outline-control-move-up": "সমল ওপৰলৈ স্থানান্তৰ কৰক",
+ "ooui-outline-control-remove": "সমল আঁতৰাওক",
+ "ooui-toolbar-more": "অধিক",
+ "ooui-toolgroup-expand": "অধিক",
+ "ooui-toolgroup-collapse": "কম দেখাওক",
+ "ooui-dialog-message-accept": "বাৰু",
+ "ooui-dialog-message-reject": "বাতিল কৰক",
+ "ooui-dialog-process-error": "কিবা ত্ৰুটি হৈছে",
+ "ooui-dialog-process-dismiss": "বাতিল",
+ "ooui-dialog-process-retry": "পুনৰ চেষ্টা কৰক",
+ "ooui-dialog-process-continue": "অব্যাহত ৰাখক",
+ "ooui-selectfile-button-select": "ফাইল নিৰ্বাচন কৰক",
+ "ooui-selectfile-not-supported": "নথি নিৰ্বাচন সমৰ্থন কৰা নাই",
+ "ooui-selectfile-placeholder": "কোনো নথি নিৰ্বাচিত কৰা হোৱা নাই",
+ "ooui-selectfile-dragdrop-placeholder": "ইয়াত ফাইল এৰক"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ast.json b/www/wiki/resources/lib/oojs-ui/i18n/ast.json
new file mode 100644
index 00000000..623892df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ast.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Basharh",
+ "Bishnu Saikia",
+ "Xuacu"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mover abaxo l'elementu",
+ "ooui-outline-control-move-up": "Mover arriba l'elementu",
+ "ooui-outline-control-remove": "Desaniciar elementu",
+ "ooui-toolbar-more": "Más",
+ "ooui-toolgroup-expand": "Más",
+ "ooui-toolgroup-collapse": "Menos",
+ "ooui-item-remove": "Desaniciar",
+ "ooui-dialog-message-accept": "Aceutar",
+ "ooui-dialog-message-reject": "Encaboxar",
+ "ooui-dialog-process-error": "Daqué funcionó mal",
+ "ooui-dialog-process-dismiss": "Descartar",
+ "ooui-dialog-process-retry": "Vuelvi a intentalo",
+ "ooui-dialog-process-continue": "Siguir",
+ "ooui-selectfile-button-select": "Seleicionar un ficheru",
+ "ooui-selectfile-not-supported": "Nun hai encontu pa la seleición de ficheros",
+ "ooui-selectfile-placeholder": "Nun se seleicionó nengún ficheru",
+ "ooui-selectfile-dragdrop-placeholder": "Soltar el ficheru equí"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/awa.json b/www/wiki/resources/lib/oojs-ui/i18n/awa.json
new file mode 100644
index 00000000..f78ed326
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/awa.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "1AnuraagPandey"
+ ]
+ },
+ "ooui-toolbar-more": "अउर"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/az.json b/www/wiki/resources/lib/oojs-ui/i18n/az.json
new file mode 100644
index 00000000..fc12d1b3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/az.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cekli829",
+ "Interfase",
+ "Jduranboger"
+ ]
+ },
+ "ooui-outline-control-move-down": "Bəndi aşağı apar",
+ "ooui-outline-control-move-up": "Bəndi yuxarı apar",
+ "ooui-outline-control-remove": "Bəndi sil",
+ "ooui-toolbar-more": "Daha artıq"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/azb.json b/www/wiki/resources/lib/oojs-ui/i18n/azb.json
new file mode 100644
index 00000000..313122ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/azb.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sadiqr"
+ ]
+ },
+ "ooui-dialog-message-reject": "وازگئچ",
+ "ooui-dialog-process-continue": "داوام ائت",
+ "ooui-selectfile-button-select": "بیر فایل سئچ",
+ "ooui-selectfile-placeholder": "هئچ فایل سئچیلمه‌ییب"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ba.json b/www/wiki/resources/lib/oojs-ui/i18n/ba.json
new file mode 100644
index 00000000..d8c99aaf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ba.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "AiseluRB",
+ "Amire80",
+ "Assele",
+ "Haqmar",
+ "Sagan",
+ "Рустам Нурыев",
+ "Азат Хәлилов"
+ ]
+ },
+ "ooui-outline-control-move-down": "Элементты аҫҡа күсерергә",
+ "ooui-outline-control-move-up": "Элементты өҫкә күсерергә",
+ "ooui-outline-control-remove": "Биттәрҙе юйырға",
+ "ooui-toolbar-more": "Тағы",
+ "ooui-toolgroup-expand": "Күберәк",
+ "ooui-toolgroup-collapse": "Аҙыраҡ",
+ "ooui-dialog-message-accept": "Тамам",
+ "ooui-dialog-message-reject": "Кире алырға",
+ "ooui-dialog-process-error": "Нимәлер килеп сыҡманы.",
+ "ooui-dialog-process-dismiss": "Йәшерергә",
+ "ooui-dialog-process-retry": "Ҡабатлап ҡарарға.",
+ "ooui-dialog-process-continue": "Дауам итергә",
+ "ooui-selectfile-button-select": "Файлды һайлағыҙ",
+ "ooui-selectfile-not-supported": "Файл һайлау хупланмай.",
+ "ooui-selectfile-placeholder": "Файл һайланмаған",
+ "ooui-selectfile-dragdrop-placeholder": "Файлды бында күсерегеҙ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/bcc.json b/www/wiki/resources/lib/oojs-ui/i18n/bcc.json
new file mode 100644
index 00000000..a340a881
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/bcc.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Baloch Afghanistan"
+ ]
+ },
+ "ooui-dialog-message-accept": "اوکی",
+ "ooui-dialog-process-retry": "پدا کوشش کورتین"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/bcl.json b/www/wiki/resources/lib/oojs-ui/i18n/bcl.json
new file mode 100644
index 00000000..bc2251e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/bcl.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Geopoet",
+ "Sky Harbor"
+ ]
+ },
+ "ooui-outline-control-move-down": "Balyuhon an aytem paibaba",
+ "ooui-outline-control-move-up": "Balyuhon an aytem paitaas",
+ "ooui-toolbar-more": "Kadugangan"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/be-tarask.json b/www/wiki/resources/lib/oojs-ui/i18n/be-tarask.json
new file mode 100644
index 00000000..40a6efd0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/be-tarask.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "EugeneZelenko",
+ "Wizardist",
+ "Чаховіч Уладзіслаў",
+ "Zedlik",
+ "Red Winged Duck",
+ "Renessaince"
+ ]
+ },
+ "ooui-outline-control-move-down": "Перасунуць элемэнт ніжэй",
+ "ooui-outline-control-move-up": "Перасунуць элемэнт вышэй",
+ "ooui-outline-control-remove": "Выдаліць пункт",
+ "ooui-toolbar-more": "Болей",
+ "ooui-toolgroup-expand": "Болей",
+ "ooui-toolgroup-collapse": "Меней",
+ "ooui-item-remove": "Выдаліць",
+ "ooui-dialog-message-accept": "Добра",
+ "ooui-dialog-message-reject": "Скасаваць",
+ "ooui-dialog-process-error": "Нешта пайшло ня так",
+ "ooui-dialog-process-dismiss": "Прапусьціць",
+ "ooui-dialog-process-retry": "Паспрабаваць зноў",
+ "ooui-dialog-process-continue": "Працягваць",
+ "ooui-selectfile-button-select": "Абраць файл",
+ "ooui-selectfile-not-supported": "Выбар файлу не падтрымліваецца",
+ "ooui-selectfile-placeholder": "Ніводзін файл не абраны",
+ "ooui-selectfile-dragdrop-placeholder": "Перацягніце файл сюды"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/be.json b/www/wiki/resources/lib/oojs-ui/i18n/be.json
new file mode 100644
index 00000000..7b4e5468
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/be.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Чаховіч Уладзіслаў",
+ "Artificial123",
+ "Goshaproject",
+ "Mechanizatar"
+ ]
+ },
+ "ooui-outline-control-move-down": "Перамясціць элемент ўніз",
+ "ooui-outline-control-move-up": "Перамясціць элемент уверх",
+ "ooui-outline-control-remove": "Выдаліць элемент",
+ "ooui-toolbar-more": "Яшчэ",
+ "ooui-toolgroup-expand": "Яшчэ",
+ "ooui-toolgroup-collapse": "Менш",
+ "ooui-dialog-message-accept": "ОК",
+ "ooui-dialog-message-reject": "Адмяніць",
+ "ooui-dialog-process-error": "Штось пайшло не так…",
+ "ooui-dialog-process-dismiss": "Прапусціць",
+ "ooui-dialog-process-retry": "Паспрабаваць яшчэ раз",
+ "ooui-dialog-process-continue": "Працягнуць",
+ "ooui-selectfile-button-select": "Выбраць файл",
+ "ooui-selectfile-not-supported": "Выбраны файл не падтрымліваецца",
+ "ooui-selectfile-placeholder": "Файл не выбраны"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/bg.json b/www/wiki/resources/lib/oojs-ui/i18n/bg.json
new file mode 100644
index 00000000..5a3a93dc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/bg.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "DCLXVI",
+ "Hristofor.mirchev",
+ "පසිඳු කාවින්ද",
+ "Mitzev",
+ "Aquilax",
+ "Vodnokon4e"
+ ]
+ },
+ "ooui-outline-control-move-down": "Преместване на елемента надолу",
+ "ooui-outline-control-move-up": "Преместване на елемента нагоре",
+ "ooui-outline-control-remove": "Премахване на обекта",
+ "ooui-toolbar-more": "Още",
+ "ooui-toolgroup-expand": "Още",
+ "ooui-toolgroup-collapse": "По-малко",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Отказ",
+ "ooui-dialog-process-error": "Нещо се обърка",
+ "ooui-dialog-process-dismiss": "Затвори",
+ "ooui-dialog-process-retry": "Опитайте отново",
+ "ooui-dialog-process-continue": "Продължаване",
+ "ooui-selectfile-button-select": "Избиране на файл",
+ "ooui-selectfile-not-supported": "Избраният файл не се поддържа",
+ "ooui-selectfile-placeholder": "Не е избран файл",
+ "ooui-selectfile-dragdrop-placeholder": "Пуснете файла тук"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/bho.json b/www/wiki/resources/lib/oojs-ui/i18n/bho.json
new file mode 100644
index 00000000..9697db02
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/bho.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "SatyamMishra"
+ ]
+ },
+ "ooui-outline-control-move-down": "आइटम नीचे घसकाईं",
+ "ooui-outline-control-move-up": "आइटम ऊपर घसकाईं",
+ "ooui-outline-control-remove": "आइटम हटाईं",
+ "ooui-toolbar-more": "अउरी",
+ "ooui-toolgroup-expand": "अउरी",
+ "ooui-toolgroup-collapse": "कम",
+ "ooui-dialog-message-accept": "ओके",
+ "ooui-dialog-message-reject": "कैंसिल",
+ "ooui-dialog-process-error": "कुछ गड़बड़ी हो गइल",
+ "ooui-dialog-process-dismiss": "रद्द",
+ "ooui-dialog-process-retry": "दोबारा कोसिस करीं",
+ "ooui-dialog-process-continue": "जारी राखीं",
+ "ooui-selectfile-button-select": "एगो फाइल चुनीं",
+ "ooui-selectfile-not-supported": "फाइल के चुनाव के सपोर्ट नइखे",
+ "ooui-selectfile-placeholder": "कौनों फाइल नइखे चुनल गइल",
+ "ooui-selectfile-dragdrop-placeholder": "फाइल इहाँ ड्रॉप करीं"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/bn.json b/www/wiki/resources/lib/oojs-ui/i18n/bn.json
new file mode 100644
index 00000000..273b7db1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/bn.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Aftab1995",
+ "Bellayet",
+ "Jayantanth",
+ "Nasir8891",
+ "Runab",
+ "Sayak Sarkar",
+ "Aftabuzzaman",
+ "RYasmeen (WMF)",
+ "NahidSultan"
+ ]
+ },
+ "ooui-outline-control-move-down": "আইটেম নিচে স্থানান্তর",
+ "ooui-outline-control-move-up": "আইটেম উপরে স্থানান্তর",
+ "ooui-outline-control-remove": "আইটেম সরান",
+ "ooui-toolbar-more": "আরও",
+ "ooui-toolgroup-expand": "আরও",
+ "ooui-toolgroup-collapse": "কম দেখাও",
+ "ooui-item-remove": "সরান",
+ "ooui-dialog-message-accept": "ঠিক আছে",
+ "ooui-dialog-message-reject": "বাতিল",
+ "ooui-dialog-process-error": "কিছু একটায় ত্রুটি হয়েছে",
+ "ooui-dialog-process-dismiss": "বাতিল করুন",
+ "ooui-dialog-process-retry": "আবার চেষ্টা করুন",
+ "ooui-dialog-process-continue": "অগ্রসর হোন",
+ "ooui-selectfile-button-select": "একটি ফাইল নির্বাচন করুন",
+ "ooui-selectfile-not-supported": "চিত্র নির্বাচন সমর্থিত নয়",
+ "ooui-selectfile-placeholder": "কোন চিত্র নির্বাচিত হয়নি",
+ "ooui-selectfile-dragdrop-placeholder": "এখানে ফাইল ছাড়ুন"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/bqi.json b/www/wiki/resources/lib/oojs-ui/i18n/bqi.json
new file mode 100644
index 00000000..a0e53b36
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/bqi.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mogoeilor"
+ ]
+ },
+ "ooui-outline-control-move-down": "ڤا دڤۈن بوردن آیتم",
+ "ooui-outline-control-move-up": "ڤارو بردن آیتم",
+ "ooui-outline-control-remove": "ڤورداشتن آیتم",
+ "ooui-toolbar-more": "بیشتر",
+ "ooui-toolgroup-expand": "بیشتر",
+ "ooui-toolgroup-collapse": "کمتر",
+ "ooui-dialog-message-accept": "خۈڤإ",
+ "ooui-dialog-message-reject": "أنجومشيڤ کردن",
+ "ooui-dialog-process-error": "یأ چي ايچو إشتوا إ",
+ "ooui-dialog-process-retry": "ز نۉ تلاش کونين",
+ "ooui-dialog-process-continue": "ديندا گرهڌن",
+ "ooui-selectfile-button-select": "گولإڤورچين کردن جانیا",
+ "ooui-selectfile-not-supported": "گول ڤورچی کردن جانیا کونشتکاری نڤابیڌ",
+ "ooui-selectfile-placeholder": "هيژ جانيایي گولإ ڤورچين نڤابيڌإ",
+ "ooui-selectfile-dragdrop-placeholder": "جانيانأ ڤأنين ايچو"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/br.json b/www/wiki/resources/lib/oojs-ui/i18n/br.json
new file mode 100644
index 00000000..1383d9aa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/br.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Fohanno",
+ "Fulup",
+ "Y-M D",
+ "Maoris",
+ "Gwendal"
+ ]
+ },
+ "ooui-outline-control-move-down": "Lakaat an elfenn da ziskenn",
+ "ooui-outline-control-move-up": "Lakaat an elfenn da bignat",
+ "ooui-outline-control-remove": "Tennañ an elfenn",
+ "ooui-toolbar-more": "Muioc'h",
+ "ooui-toolgroup-expand": "Muioc'h",
+ "ooui-toolgroup-collapse": "Nebeutoc'h",
+ "ooui-item-remove": "Dilemel",
+ "ooui-dialog-message-accept": "Mat eo",
+ "ooui-dialog-message-reject": "Nullañ",
+ "ooui-dialog-process-error": "Un dra bennak a-dreuz a zo bet",
+ "ooui-dialog-process-dismiss": "Disteurel",
+ "ooui-dialog-process-retry": "Klask en-dro",
+ "ooui-dialog-process-continue": "Kenderc'hel",
+ "ooui-selectfile-button-select": "Diuzañ ur restr",
+ "ooui-selectfile-not-supported": "N'eo ket skoret an diuzañ restroù",
+ "ooui-selectfile-placeholder": "N'eus bet diuzet restr ebet",
+ "ooui-selectfile-dragdrop-placeholder": "Lezel ar restr amañ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/bs.json b/www/wiki/resources/lib/oojs-ui/i18n/bs.json
new file mode 100644
index 00000000..fc4c320a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/bs.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "DzWiki",
+ "Semso98",
+ "Srdjan m"
+ ]
+ },
+ "ooui-outline-control-move-down": "Premjesti stavku dolje",
+ "ooui-outline-control-move-up": "Premjesti stavku gore",
+ "ooui-outline-control-remove": "Ukloni stavku",
+ "ooui-toolbar-more": "Više",
+ "ooui-toolgroup-expand": "Više",
+ "ooui-toolgroup-collapse": "Manje",
+ "ooui-dialog-message-accept": "U redu",
+ "ooui-dialog-message-reject": "Otkaži",
+ "ooui-dialog-process-error": "Nešto je pošlo naopako",
+ "ooui-dialog-process-dismiss": "Odbaci",
+ "ooui-dialog-process-retry": "Pokušaj ponovo",
+ "ooui-dialog-process-continue": "Nastavi",
+ "ooui-selectfile-button-select": "Izaberite datoteku",
+ "ooui-selectfile-not-supported": "Izbor datoteke nije podržan",
+ "ooui-selectfile-placeholder": "Nijedna datoteka nije izabrana",
+ "ooui-selectfile-dragdrop-placeholder": "Prevucite datoteku ovdje"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ca.json b/www/wiki/resources/lib/oojs-ui/i18n/ca.json
new file mode 100644
index 00000000..96d782ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ca.json
@@ -0,0 +1,35 @@
+{
+ "@metadata": {
+ "authors": [
+ "Alvaro Vidal-Abarca",
+ "Amire80",
+ "Arnaugir",
+ "Pginer",
+ "QuimGil",
+ "SMP",
+ "Vriullop",
+ "Toniher",
+ "Edustus",
+ "Davidpar",
+ "Maceleiro",
+ "Kippelboy",
+ "Macofe"
+ ]
+ },
+ "ooui-outline-control-move-down": "Baixa l'element",
+ "ooui-outline-control-move-up": "Puja l'element",
+ "ooui-outline-control-remove": "Esborra l'ítem",
+ "ooui-toolbar-more": "Més",
+ "ooui-toolgroup-expand": "Més",
+ "ooui-toolgroup-collapse": "Menys",
+ "ooui-dialog-message-accept": "D'acord",
+ "ooui-dialog-message-reject": "Cancel·la",
+ "ooui-dialog-process-error": "Alguna cosa no ha funcionat",
+ "ooui-dialog-process-dismiss": "Descarta",
+ "ooui-dialog-process-retry": "Torneu-ho a provar",
+ "ooui-dialog-process-continue": "Continua",
+ "ooui-selectfile-button-select": "Seleccioneu un fitxer",
+ "ooui-selectfile-not-supported": "El tipus de fitxer no és compatible",
+ "ooui-selectfile-placeholder": "No s'ha seleccionat cap fitxer",
+ "ooui-selectfile-dragdrop-placeholder": "Deseu els arxius aquí"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/cdo.json b/www/wiki/resources/lib/oojs-ui/i18n/cdo.json
new file mode 100644
index 00000000..cb46b437
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/cdo.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Yejianfei"
+ ]
+ },
+ "ooui-outline-control-move-down": "下移項目",
+ "ooui-outline-control-move-up": "上移項目",
+ "ooui-outline-control-remove": "移除項目",
+ "ooui-toolbar-more": "更価",
+ "ooui-toolgroup-expand": "更価",
+ "ooui-toolgroup-collapse": "更少",
+ "ooui-dialog-message-accept": "確定",
+ "ooui-dialog-message-reject": "取消",
+ "ooui-dialog-process-error": "什乇出毛病了",
+ "ooui-dialog-process-dismiss": "關閉",
+ "ooui-dialog-process-retry": "重試",
+ "ooui-dialog-process-continue": "繼續",
+ "ooui-selectfile-button-select": "選擇蜀萆文件",
+ "ooui-selectfile-not-supported": "𣍐支持選擇其文件",
+ "ooui-selectfile-placeholder": "未選文件",
+ "ooui-selectfile-dragdrop-placeholder": "共文件拖遘嚽塊"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ce.json b/www/wiki/resources/lib/oojs-ui/i18n/ce.json
new file mode 100644
index 00000000..3f8dfb13
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ce.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Умар"
+ ]
+ },
+ "ooui-outline-control-move-down": "Лаха яккха элемент",
+ "ooui-outline-control-move-up": "Лаккха яккха элемент",
+ "ooui-outline-control-remove": "ДӀадаха меттиг",
+ "ooui-toolbar-more": "Кхин",
+ "ooui-toolgroup-expand": "Дукха",
+ "ooui-toolgroup-collapse": "КӀезиг",
+ "ooui-dialog-message-accept": "ХӀаъ",
+ "ooui-dialog-message-reject": "Цаоьшу",
+ "ooui-dialog-process-continue": "Кхин дӀа",
+ "ooui-selectfile-button-select": "Харжа файл",
+ "ooui-selectfile-placeholder": "Файл хаьржина яц"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ckb.json b/www/wiki/resources/lib/oojs-ui/i18n/ckb.json
new file mode 100644
index 00000000..999fae04
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ckb.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Calak",
+ "Muhammed taha",
+ "Serwan",
+ "Pirehelokan",
+ "Sarchia"
+ ]
+ },
+ "ooui-toolbar-more": "زیاتر",
+ "ooui-toolgroup-expand": "زیاتر",
+ "ooui-toolgroup-collapse": "کەمتر",
+ "ooui-dialog-message-accept": "باشە",
+ "ooui-dialog-message-reject": "پاشگەزبوونەوە",
+ "ooui-dialog-process-error": "ھەڵەیەک ڕووی داوە",
+ "ooui-dialog-process-dismiss": "لێگەڕان",
+ "ooui-dialog-process-retry": "دیسان ھەوڵ بدە",
+ "ooui-dialog-process-continue": "درێژە بدە",
+ "ooui-selectfile-button-select": "پەڕگەیەک دەستنیشان بکە",
+ "ooui-selectfile-placeholder": "ھیچ فایلێک ھەڵنەبژێراوە",
+ "ooui-selectfile-dragdrop-placeholder": "پەڕگەکان بخەرە ئێرە"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/co.json b/www/wiki/resources/lib/oojs-ui/i18n/co.json
new file mode 100644
index 00000000..01d181d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/co.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "Paulu"
+ ]
+ },
+ "ooui-outline-control-move-down": "Fà falà l'ogettu",
+ "ooui-outline-control-move-up": "Fà cullà l'ogettu"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/crh-cyrl.json b/www/wiki/resources/lib/oojs-ui/i18n/crh-cyrl.json
new file mode 100644
index 00000000..ccc00269
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/crh-cyrl.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Don Alessandro"
+ ]
+ },
+ "ooui-toolbar-more": "Даа зияде"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/crh-latn.json b/www/wiki/resources/lib/oojs-ui/i18n/crh-latn.json
new file mode 100644
index 00000000..7ad7b0bb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/crh-latn.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Don Alessandro"
+ ]
+ },
+ "ooui-toolbar-more": "Daa ziyade"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/cs.json b/www/wiki/resources/lib/oojs-ui/i18n/cs.json
new file mode 100644
index 00000000..8e3d1af1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/cs.json
@@ -0,0 +1,36 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chmee2",
+ "Jkjk",
+ "Juandev",
+ "Koo6",
+ "Littledogboy",
+ "Michaelbrabec",
+ "Mormegil",
+ "Polda18",
+ "Tchoř",
+ "ශ්වෙත",
+ "Vojtěch Dostál",
+ "Matěj Suchánek",
+ "Martin Urbanec"
+ ]
+ },
+ "ooui-outline-control-move-down": "Přesunout položku dolů",
+ "ooui-outline-control-move-up": "Přesunout položku nahoru",
+ "ooui-outline-control-remove": "Odstranit položku",
+ "ooui-toolbar-more": "Další",
+ "ooui-toolgroup-expand": "Více",
+ "ooui-toolgroup-collapse": "Méně",
+ "ooui-item-remove": "Odebrat",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Storno",
+ "ooui-dialog-process-error": "Něco se pokazilo",
+ "ooui-dialog-process-dismiss": "Zavřít",
+ "ooui-dialog-process-retry": "Zkusit znovu",
+ "ooui-dialog-process-continue": "Pokračovat",
+ "ooui-selectfile-button-select": "Vybrat soubor",
+ "ooui-selectfile-not-supported": "Výběr souboru není podporován",
+ "ooui-selectfile-placeholder": "Nebyl vybrán žádný soubor",
+ "ooui-selectfile-dragdrop-placeholder": "Umístěte soubor sem"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/cu.json b/www/wiki/resources/lib/oojs-ui/i18n/cu.json
new file mode 100644
index 00000000..d627de06
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/cu.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "ОйЛ"
+ ]
+ },
+ "ooui-toolbar-more": "вѧщє",
+ "ooui-toolgroup-expand": "вѧщє",
+ "ooui-dialog-process-error": "нѣчьто ꙁълѣ сѧ авило"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/cy.json b/www/wiki/resources/lib/oojs-ui/i18n/cy.json
new file mode 100644
index 00000000..f3c7e3c4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/cy.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lloffiwr",
+ "Robin Owain",
+ "ОйЛ",
+ "DChan (WMF)",
+ "Jdforrester"
+ ]
+ },
+ "ooui-outline-control-move-down": "Symud yr eitem i lawr",
+ "ooui-outline-control-move-up": "Symud yr eitem i fyny",
+ "ooui-outline-control-remove": "Tynnu'r eitem",
+ "ooui-toolbar-more": "Rhagor",
+ "ooui-toolgroup-expand": "Mwy",
+ "ooui-toolgroup-collapse": "Llai",
+ "ooui-dialog-message-accept": "Iawn",
+ "ooui-dialog-message-reject": "Canslo",
+ "ooui-dialog-process-error": "Aeth rhywbeth o’i le",
+ "ooui-dialog-process-dismiss": "Gadael",
+ "ooui-dialog-process-retry": "Ailgeisio",
+ "ooui-dialog-process-continue": "Parhau",
+ "ooui-selectfile-button-select": "Dewis ffeil",
+ "ooui-selectfile-not-supported": "Nid oes modd dewis ffeil",
+ "ooui-selectfile-placeholder": "Dim ffeil wedi'i dewis",
+ "ooui-selectfile-dragdrop-placeholder": "Gollwng ffeil yma"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/da.json b/www/wiki/resources/lib/oojs-ui/i18n/da.json
new file mode 100644
index 00000000..3a5590ae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/da.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cgtdk",
+ "Christian List",
+ "EileenSanda",
+ "Laketown",
+ "Palnatoke",
+ "Simeondahl",
+ "Tehnix",
+ "Macofe",
+ "Peter Alberti",
+ "Joedalton"
+ ]
+ },
+ "ooui-outline-control-move-down": "Flyt ned",
+ "ooui-outline-control-move-up": "Flyt op",
+ "ooui-toolbar-more": "Mere",
+ "ooui-toolgroup-expand": "Mere",
+ "ooui-toolgroup-collapse": "Færre",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Afbryd",
+ "ooui-dialog-process-error": "Noget gik galt",
+ "ooui-dialog-process-retry": "Prøv igen",
+ "ooui-dialog-process-continue": "Fortsæt",
+ "ooui-selectfile-button-select": "Vælg en fil",
+ "ooui-selectfile-dragdrop-placeholder": "Smid filen her"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/de.json b/www/wiki/resources/lib/oojs-ui/i18n/de.json
new file mode 100644
index 00000000..a9eea8aa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/de.json
@@ -0,0 +1,33 @@
+{
+ "@metadata": {
+ "authors": [
+ "APPER",
+ "G.Hagedorn",
+ "Inkowik",
+ "Jcornelius",
+ "Jdforrester",
+ "Kghbln",
+ "Metalhead64",
+ "Murma174",
+ "Se4598",
+ "Tomabrafix"
+ ]
+ },
+ "ooui-outline-control-move-down": "Element nach unten verschieben",
+ "ooui-outline-control-move-up": "Element nach oben verschieben",
+ "ooui-outline-control-remove": "Element entfernen",
+ "ooui-toolbar-more": "Mehr",
+ "ooui-toolgroup-expand": "Mehr",
+ "ooui-toolgroup-collapse": "Weniger",
+ "ooui-item-remove": "Entfernen",
+ "ooui-dialog-message-accept": "Okay",
+ "ooui-dialog-message-reject": "Abbrechen",
+ "ooui-dialog-process-error": "Etwas ist schief gelaufen",
+ "ooui-dialog-process-dismiss": "Ausblenden",
+ "ooui-dialog-process-retry": "Erneut versuchen",
+ "ooui-dialog-process-continue": "Fortfahren",
+ "ooui-selectfile-button-select": "Eine Datei auswählen",
+ "ooui-selectfile-not-supported": "Die Dateiauswahl wird nicht unterstützt",
+ "ooui-selectfile-placeholder": "Keine Datei ausgewählt",
+ "ooui-selectfile-dragdrop-placeholder": "Dateien hier ablegen"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/diq.json b/www/wiki/resources/lib/oojs-ui/i18n/diq.json
new file mode 100644
index 00000000..bf6b0873
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/diq.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Erdemaslancan",
+ "Gorizon",
+ "Kghbln",
+ "Marmase",
+ "Mirzali",
+ "Se4598",
+ "Kumkumuk"
+ ]
+ },
+ "ooui-outline-control-move-down": "Bendi bere cêr",
+ "ooui-outline-control-move-up": "Bendi bere cor",
+ "ooui-outline-control-remove": "Obcey wedare",
+ "ooui-toolbar-more": "Zewbi",
+ "ooui-toolgroup-expand": "Dehana",
+ "ooui-toolgroup-collapse": "Deha tayn",
+ "ooui-dialog-message-accept": "TEMAM",
+ "ooui-dialog-message-reject": "Bıtexelne",
+ "ooui-dialog-process-error": "Tayê çi ğelet şi...",
+ "ooui-dialog-process-dismiss": "Racın",
+ "ooui-dialog-process-retry": "Fına bıcerbın",
+ "ooui-dialog-process-continue": "Dewam ke",
+ "ooui-selectfile-button-select": "Yu dosya weçinê",
+ "ooui-selectfile-not-supported": "Dosya weçinayış desteg nêvine na",
+ "ooui-selectfile-placeholder": "Dosya nêwçineya",
+ "ooui-selectfile-dragdrop-placeholder": "Dosya tiyara ake"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/dsb.json b/www/wiki/resources/lib/oojs-ui/i18n/dsb.json
new file mode 100644
index 00000000..7ad3f200
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/dsb.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Michawiki"
+ ]
+ },
+ "ooui-outline-control-move-down": "Element dołoj pśesunuś",
+ "ooui-outline-control-move-up": "Element górjej pśesunuś",
+ "ooui-outline-control-remove": "Zapisk wótpóraś",
+ "ooui-toolbar-more": "Wěcej"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/dty.json b/www/wiki/resources/lib/oojs-ui/i18n/dty.json
new file mode 100644
index 00000000..21742b69
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/dty.json
@@ -0,0 +1,18 @@
+{
+ "@metadata": {
+ "authors": [
+ "जनक राज भट्ट"
+ ]
+ },
+ "ooui-outline-control-move-down": "वस्तुलाई तल साददे",
+ "ooui-outline-control-move-up": "वस्तुलाई मथि साददे",
+ "ooui-outline-control-remove": "वस्तुलाई हटुन्या",
+ "ooui-toolbar-more": "झिक्क",
+ "ooui-toolgroup-expand": "झिक्क",
+ "ooui-toolgroup-collapse": "थोका",
+ "ooui-dialog-message-accept": "हुन्छ",
+ "ooui-dialog-message-reject": "रद्द",
+ "ooui-dialog-process-dismiss": "खारेज गद्दे",
+ "ooui-dialog-process-retry": "दोसरया प्रयास गर",
+ "ooui-dialog-process-continue": "जारी राख्या"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/egl.json b/www/wiki/resources/lib/oojs-ui/i18n/egl.json
new file mode 100644
index 00000000..624ecaa3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/egl.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lévi",
+ "Gloria sah"
+ ]
+ },
+ "ooui-outline-control-move-down": "Spôsta in bâs",
+ "ooui-outline-control-move-up": "Spôsta in êlt",
+ "ooui-outline-control-remove": "Armōv l'elemèint",
+ "ooui-toolbar-more": "Êter",
+ "ooui-dialog-message-accept": "'D acòrdi",
+ "ooui-dialog-message-reject": "Scanślèr"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/el.json b/www/wiki/resources/lib/oojs-ui/i18n/el.json
new file mode 100644
index 00000000..98835d53
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/el.json
@@ -0,0 +1,31 @@
+{
+ "@metadata": {
+ "authors": [
+ "Astralnet",
+ "Dipa1965",
+ "Evropi",
+ "FocalPoint",
+ "Geraki",
+ "Glavkos",
+ "Nikosguard",
+ "Tifa93",
+ "Stam.nikos"
+ ]
+ },
+ "ooui-outline-control-move-down": "Μετακίνηση στοιχείου προς τα κάτω",
+ "ooui-outline-control-move-up": "Μετακίνηση στοιχείου προς τα επάνω",
+ "ooui-outline-control-remove": "Αφαίρεση στοιχείου",
+ "ooui-toolbar-more": "Περισσότερα",
+ "ooui-toolgroup-expand": "Περισσότερα",
+ "ooui-toolgroup-collapse": "Λιγότερα",
+ "ooui-dialog-message-accept": "ΟΚ",
+ "ooui-dialog-message-reject": "Ακύρωση",
+ "ooui-dialog-process-error": "Κάτι πήγε στραβά",
+ "ooui-dialog-process-dismiss": "Απόρριψη",
+ "ooui-dialog-process-retry": "Δοκιμάστε ξανά",
+ "ooui-dialog-process-continue": "Συνέχεια",
+ "ooui-selectfile-button-select": "Επιλέξτε ένα αρχείο",
+ "ooui-selectfile-not-supported": "Επιλογή αρχείου δεν υποστηρίζεται",
+ "ooui-selectfile-placeholder": "Κανένα αρχείο δεν είναι επιλεγμένο",
+ "ooui-selectfile-dragdrop-placeholder": "Σύρετε το αρχείο εδώ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/eml.json b/www/wiki/resources/lib/oojs-ui/i18n/eml.json
new file mode 100644
index 00000000..6d9e8bf0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/eml.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gloria sah",
+ "Lévi"
+ ]
+ },
+ "ooui-outline-control-move-down": "Spôsta in bâs",
+ "ooui-outline-control-move-up": "Spôsta in êlta",
+ "ooui-outline-control-remove": "Tór vìa 'l elemèint",
+ "ooui-toolbar-more": "Êter",
+ "ooui-dialog-message-accept": "'D acòrdi",
+ "ooui-dialog-message-reject": "Scanślèr"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/en-ca.json b/www/wiki/resources/lib/oojs-ui/i18n/en-ca.json
new file mode 100644
index 00000000..1a8e31be
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/en-ca.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Skyllful"
+ ]
+ },
+ "ooui-outline-control-move-down": "Move item down",
+ "ooui-outline-control-move-up": "Move item up",
+ "ooui-outline-control-remove": "Remove item",
+ "ooui-toolbar-more": "More",
+ "ooui-toolgroup-expand": "More",
+ "ooui-toolgroup-collapse": "Less",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancel",
+ "ooui-dialog-process-error": "Something went wrong",
+ "ooui-dialog-process-dismiss": "Dismiss",
+ "ooui-dialog-process-retry": "Try again",
+ "ooui-dialog-process-continue": "Continue",
+ "ooui-selectfile-not-supported": "File(s) not supported",
+ "ooui-selectfile-placeholder": "No file selected",
+ "ooui-selectfile-dragdrop-placeholder": "Drop file here (or click to browse your computer)"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/en.json b/www/wiki/resources/lib/oojs-ui/i18n/en.json
new file mode 100644
index 00000000..fd311503
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/en.json
@@ -0,0 +1,36 @@
+{
+ "@metadata": {
+ "authors": [
+ "Trevor Parscal",
+ "Ed Sanders",
+ "James D. Forrester",
+ "Raimond Spekking",
+ "Erik Moeller",
+ "Moriel Schottlender",
+ "Yuki Shira",
+ "Siebrand Mazeland",
+ "Rob Moen",
+ "Timo Tijhof",
+ "Roan Kattouw",
+ "Christian Williams",
+ "Amir E. Aharoni"
+ ]
+ },
+ "ooui-outline-control-move-down": "Move item down",
+ "ooui-outline-control-move-up": "Move item up",
+ "ooui-outline-control-remove": "Remove item",
+ "ooui-toolbar-more": "More",
+ "ooui-toolgroup-expand": "More",
+ "ooui-toolgroup-collapse": "Fewer",
+ "ooui-item-remove": "Remove",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancel",
+ "ooui-dialog-process-error": "Something went wrong",
+ "ooui-dialog-process-dismiss": "Dismiss",
+ "ooui-dialog-process-retry": "Try again",
+ "ooui-dialog-process-continue": "Continue",
+ "ooui-selectfile-button-select": "Select a file",
+ "ooui-selectfile-not-supported": "File selection is not supported",
+ "ooui-selectfile-placeholder": "No file is selected",
+ "ooui-selectfile-dragdrop-placeholder": "Drop file here"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/eo.json b/www/wiki/resources/lib/oojs-ui/i18n/eo.json
new file mode 100644
index 00000000..ff2a2b31
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/eo.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Happy5214",
+ "KuboF",
+ "Shirayuki",
+ "Yekrats",
+ "Kvardek du",
+ "Psychoslave"
+ ]
+ },
+ "ooui-outline-control-move-down": "Movi eron suben",
+ "ooui-outline-control-move-up": "Movi eron supren",
+ "ooui-outline-control-remove": "Forigi eron",
+ "ooui-toolbar-more": "Pli",
+ "ooui-toolgroup-expand": "Pli",
+ "ooui-toolgroup-collapse": "Mapli",
+ "ooui-dialog-message-accept": "Bone",
+ "ooui-dialog-message-reject": "Nuligi",
+ "ooui-dialog-process-error": "Io rompiĝis",
+ "ooui-dialog-process-dismiss": "Elimini",
+ "ooui-dialog-process-retry": "Reprovi",
+ "ooui-dialog-process-continue": "Daŭrigi",
+ "ooui-selectfile-button-select": "Elekti dosieron",
+ "ooui-selectfile-not-supported": "Dosieroselekto ne estas subtenata.",
+ "ooui-selectfile-placeholder": "Vi ne selektis dosieron",
+ "ooui-selectfile-dragdrop-placeholder": "Ĵetu dosieron ĉi tie."
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/es.json b/www/wiki/resources/lib/oojs-ui/i18n/es.json
new file mode 100644
index 00000000..7873c95c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/es.json
@@ -0,0 +1,38 @@
+{
+ "@metadata": {
+ "authors": [
+ "Armando-Martin",
+ "Aruizdr",
+ "Benfutbol10",
+ "DJ Nietzsche",
+ "Erdemaslancan",
+ "Fitoschido",
+ "Imre",
+ "Invadinado",
+ "Jdforrester",
+ "Jduranboger",
+ "PoLuX124",
+ "Ralgis",
+ "Thehelpfulone",
+ "Gloria sah",
+ "Macofe"
+ ]
+ },
+ "ooui-outline-control-move-down": "Bajar elemento",
+ "ooui-outline-control-move-up": "Subir elemento",
+ "ooui-outline-control-remove": "Eliminar elemento",
+ "ooui-toolbar-more": "Más",
+ "ooui-toolgroup-expand": "Más",
+ "ooui-toolgroup-collapse": "Menos",
+ "ooui-item-remove": "Quitar",
+ "ooui-dialog-message-accept": "Aceptar",
+ "ooui-dialog-message-reject": "Cancelar",
+ "ooui-dialog-process-error": "Algo salió mal",
+ "ooui-dialog-process-dismiss": "Descartar",
+ "ooui-dialog-process-retry": "Intentar de nuevo",
+ "ooui-dialog-process-continue": "Continuar",
+ "ooui-selectfile-button-select": "Selecciona un archivo",
+ "ooui-selectfile-not-supported": "No se admite la selección de archivos",
+ "ooui-selectfile-placeholder": "Ningún archivo seleccionado",
+ "ooui-selectfile-dragdrop-placeholder": "Suelta el archivo aquí"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/et.json b/www/wiki/resources/lib/oojs-ui/i18n/et.json
new file mode 100644
index 00000000..326baaff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/et.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Avjoska",
+ "Pikne",
+ "Suwa"
+ ]
+ },
+ "ooui-outline-control-move-down": "Liiguta üksust allapoole",
+ "ooui-outline-control-move-up": "Liiguta üksust ülespoole",
+ "ooui-outline-control-remove": "Eemalda üksus",
+ "ooui-toolbar-more": "Veel",
+ "ooui-toolgroup-expand": "Veel",
+ "ooui-toolgroup-collapse": "Vähem",
+ "ooui-dialog-message-accept": "Sobib",
+ "ooui-dialog-message-reject": "Loobu",
+ "ooui-dialog-process-error": "Midagi läks valesti",
+ "ooui-dialog-process-dismiss": "Sule",
+ "ooui-dialog-process-retry": "Proovi uuesti",
+ "ooui-dialog-process-continue": "Jätka",
+ "ooui-selectfile-button-select": "Vali fail",
+ "ooui-selectfile-not-supported": "Faili valiku tugi puudub",
+ "ooui-selectfile-placeholder": "Faili ei ole valitud",
+ "ooui-selectfile-dragdrop-placeholder": "Lohista fail siia"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/eu.json b/www/wiki/resources/lib/oojs-ui/i18n/eu.json
new file mode 100644
index 00000000..c715ae6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/eu.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "An13sa",
+ "Unai Fdz. de Betoño",
+ "Xabier Armendaritz",
+ "Subi",
+ "Sator",
+ "Mikel Ibaiba"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mugitu itema beherantz",
+ "ooui-outline-control-move-up": "Mugitu itema gorantz",
+ "ooui-outline-control-remove": "Elementua kendu",
+ "ooui-toolbar-more": "Gehiago",
+ "ooui-toolgroup-expand": "Gehiago",
+ "ooui-toolgroup-collapse": "Gutxiago",
+ "ooui-item-remove": "Ezabatu",
+ "ooui-dialog-message-accept": "Ados",
+ "ooui-dialog-message-reject": "Utzi",
+ "ooui-dialog-process-error": "Zerbaitek huts egin du",
+ "ooui-dialog-process-dismiss": "Utzi",
+ "ooui-dialog-process-retry": "Saiatu berriro",
+ "ooui-dialog-process-continue": "Jarraitu",
+ "ooui-selectfile-button-select": "Fitxategi bat aukeratu",
+ "ooui-selectfile-not-supported": "Fitxategi aukeraketa ez da onartzen",
+ "ooui-selectfile-placeholder": "Ez da fitxategirik hautatu",
+ "ooui-selectfile-dragdrop-placeholder": "Fitxategia hemen utzi"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/fa.json b/www/wiki/resources/lib/oojs-ui/i18n/fa.json
new file mode 100644
index 00000000..8aa519b1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/fa.json
@@ -0,0 +1,37 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dalba",
+ "Ebraminio",
+ "Jdforrester",
+ "Ladsgroup",
+ "Mjbmr",
+ "Nojan Madinehi",
+ "Reza1615",
+ "Taha",
+ "درفش کاویانی",
+ "Armin1392",
+ "Alirezaaa",
+ "Leyth",
+ "الناز",
+ "فلورانس"
+ ]
+ },
+ "ooui-outline-control-move-down": "انتقال مورد به پایین",
+ "ooui-outline-control-move-up": "انتقال مورد به بالا",
+ "ooui-outline-control-remove": "حذف مورد",
+ "ooui-toolbar-more": "بیشتر",
+ "ooui-toolgroup-expand": "بیشتر",
+ "ooui-toolgroup-collapse": "کمتر",
+ "ooui-item-remove": "حذف",
+ "ooui-dialog-message-accept": "تأیید",
+ "ooui-dialog-message-reject": "لغو",
+ "ooui-dialog-process-error": "مشکلی وجود دارد",
+ "ooui-dialog-process-dismiss": "رد",
+ "ooui-dialog-process-retry": "دوباره امتحان کنید",
+ "ooui-dialog-process-continue": "ادامه",
+ "ooui-selectfile-button-select": "یک فایل انتخاب کنید",
+ "ooui-selectfile-not-supported": "انتخاب پرونده پشتیبانی نمی‌شود",
+ "ooui-selectfile-placeholder": "هیچ پرونده‌ای انتخاب نشده است",
+ "ooui-selectfile-dragdrop-placeholder": "فایل را اینجا رها کنید"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/fi.json b/www/wiki/resources/lib/oojs-ui/i18n/fi.json
new file mode 100644
index 00000000..0b9e1499
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/fi.json
@@ -0,0 +1,36 @@
+{
+ "@metadata": {
+ "authors": [
+ "Beluga",
+ "Crt",
+ "Harriv",
+ "Linnea",
+ "Nedergard",
+ "Nike",
+ "Olli",
+ "Pxos",
+ "Samoasambia",
+ "Silvonen",
+ "Skalman",
+ "Stryn",
+ "VezonThunder",
+ "Alluk."
+ ]
+ },
+ "ooui-outline-control-move-down": "Siirrä kohdetta alaspäin",
+ "ooui-outline-control-move-up": "Siirrä kohdetta ylöspäin",
+ "ooui-outline-control-remove": "Poista kohde",
+ "ooui-toolbar-more": "Lisää",
+ "ooui-toolgroup-expand": "Näytä lisää",
+ "ooui-toolgroup-collapse": "Näytä vähemmän",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Peru",
+ "ooui-dialog-process-error": "Jokin meni pieleen",
+ "ooui-dialog-process-dismiss": "Hylkää",
+ "ooui-dialog-process-retry": "Yritä uudelleen",
+ "ooui-dialog-process-continue": "Jatka",
+ "ooui-selectfile-button-select": "Valitse tiedosto",
+ "ooui-selectfile-not-supported": "Tiedoston valitsemista ei tueta",
+ "ooui-selectfile-placeholder": "Tiedostoa ei ole valittu",
+ "ooui-selectfile-dragdrop-placeholder": "Pudota tiedosto tähän"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/fo.json b/www/wiki/resources/lib/oojs-ui/i18n/fo.json
new file mode 100644
index 00000000..6230cc9b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/fo.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "EileenSanda"
+ ]
+ },
+ "ooui-outline-control-move-down": "Flyt lutin niður",
+ "ooui-outline-control-move-up": "Flyt lutin upp",
+ "ooui-outline-control-remove": "Tak ein lut burtur",
+ "ooui-toolbar-more": "Meira",
+ "ooui-toolgroup-expand": "Meira",
+ "ooui-toolgroup-collapse": "Færri",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Avbrót",
+ "ooui-dialog-process-error": "Okkurt gekk galið",
+ "ooui-dialog-process-dismiss": "Lat aftur",
+ "ooui-dialog-process-retry": "Royn aftur",
+ "ooui-dialog-process-continue": "Halt fram"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/fr.json b/www/wiki/resources/lib/oojs-ui/i18n/fr.json
new file mode 100644
index 00000000..1c004d45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/fr.json
@@ -0,0 +1,53 @@
+{
+ "@metadata": {
+ "authors": [
+ "Automatik",
+ "Benoit Rochon",
+ "Boniface",
+ "Brunoperel",
+ "Crochet.david",
+ "DavidL",
+ "Dereckson",
+ "Gomoko",
+ "Guillom",
+ "Hello71",
+ "Jean-Frédéric",
+ "Linedwell",
+ "Ltrlg",
+ "Metroitendo",
+ "NemesisIII",
+ "Nicolas NALLET",
+ "Npettiaux",
+ "Rastus Vernon",
+ "Seb35",
+ "Sherbrooke",
+ "Tpt",
+ "Trizek",
+ "Urhixidur",
+ "Verdy p",
+ "Wyz",
+ "SnowedEarth",
+ "Jdforrester",
+ "Wladek92",
+ "Harmonia Amanda",
+ "The RedBurn"
+ ]
+ },
+ "ooui-outline-control-move-down": "Descendre l’élément",
+ "ooui-outline-control-move-up": "Monter l’élément",
+ "ooui-outline-control-remove": "Supprimer l’élément",
+ "ooui-toolbar-more": "Plus",
+ "ooui-toolgroup-expand": "Plus",
+ "ooui-toolgroup-collapse": "Moins",
+ "ooui-item-remove": "Supprimer",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Annuler",
+ "ooui-dialog-process-error": "Quelque chose s'est mal passé",
+ "ooui-dialog-process-dismiss": "Fermer",
+ "ooui-dialog-process-retry": "Réessayer",
+ "ooui-dialog-process-continue": "Continuer",
+ "ooui-selectfile-button-select": "Sélectionner un fichier",
+ "ooui-selectfile-not-supported": "La sélection de fichier n’est pas prise en charge",
+ "ooui-selectfile-placeholder": "Aucun fichier sélectionné",
+ "ooui-selectfile-dragdrop-placeholder": "Déposer le fichier ici"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/frr.json b/www/wiki/resources/lib/oojs-ui/i18n/frr.json
new file mode 100644
index 00000000..54d0fb22
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/frr.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "ChrisPtDe",
+ "Murma174"
+ ]
+ },
+ "ooui-outline-control-move-down": "Element efter onern sküüw",
+ "ooui-outline-control-move-up": "Element efter boowen sküüw",
+ "ooui-outline-control-remove": "Element wechnem",
+ "ooui-toolbar-more": "Muar"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/fur.json b/www/wiki/resources/lib/oojs-ui/i18n/fur.json
new file mode 100644
index 00000000..83c2fd9e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/fur.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Klenje",
+ "Tocaibon"
+ ]
+ },
+ "ooui-outline-control-move-down": "sposte sot",
+ "ooui-outline-control-move-up": "sposte in su",
+ "ooui-toolbar-more": "Altri"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/fy.json b/www/wiki/resources/lib/oojs-ui/i18n/fy.json
new file mode 100644
index 00000000..ddf9ff75
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/fy.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Robin0van0der0vliet"
+ ]
+ },
+ "ooui-toolbar-more": "Mear",
+ "ooui-toolgroup-expand": "Mear",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Annulearje"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/gd.json b/www/wiki/resources/lib/oojs-ui/i18n/gd.json
new file mode 100644
index 00000000..6a83c9c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/gd.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "GunChleoc"
+ ]
+ },
+ "ooui-outline-control-move-down": "Gluais nì sìos",
+ "ooui-outline-control-move-up": "Gluais nì suas",
+ "ooui-outline-control-remove": "Thoir air falbh an nì",
+ "ooui-toolbar-more": "Barrachd",
+ "ooui-dialog-message-accept": "Ceart ma-thà",
+ "ooui-dialog-message-reject": "Sguir dheth"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/gl.json b/www/wiki/resources/lib/oojs-ui/i18n/gl.json
new file mode 100644
index 00000000..2c3cce31
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/gl.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Alison",
+ "Kscanne",
+ "Toliño",
+ "Elisardojm",
+ "Banjo"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mover o elemento abaixo",
+ "ooui-outline-control-move-up": "Mover o elemento arriba",
+ "ooui-outline-control-remove": "Eliminar o elemento",
+ "ooui-toolbar-more": "Máis",
+ "ooui-toolgroup-expand": "Máis",
+ "ooui-toolgroup-collapse": "Menos",
+ "ooui-item-remove": "Eliminar",
+ "ooui-dialog-message-accept": "Aceptar",
+ "ooui-dialog-message-reject": "Cancelar",
+ "ooui-dialog-process-error": "Algo foi mal",
+ "ooui-dialog-process-dismiss": "Agochar",
+ "ooui-dialog-process-retry": "Inténteo de novo",
+ "ooui-dialog-process-continue": "Continuar",
+ "ooui-selectfile-button-select": "Seleccionar un ficheiro",
+ "ooui-selectfile-not-supported": "Non está soportada a selección de ficheiros",
+ "ooui-selectfile-placeholder": "Non se seleccionou ningún ficheiro",
+ "ooui-selectfile-dragdrop-placeholder": "Solte un ficheiro aquí"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/glk.json b/www/wiki/resources/lib/oojs-ui/i18n/glk.json
new file mode 100644
index 00000000..e6020621
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/glk.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "V6rg",
+ "شیخ"
+ ]
+ },
+ "ooui-outline-control-move-down": "مأسمکه جابجا بۊکۊن جير",
+ "ooui-outline-control-move-up": "مأسمکه جابجا بۊکۊن جؤر",
+ "ooui-outline-control-remove": "مأسمکه حذفأکۊن",
+ "ooui-toolbar-more": "ويشتر",
+ "ooui-toolgroup-expand": "ويشتر",
+ "ooui-toolgroup-collapse": "کمتر",
+ "ooui-dialog-message-accept": "خؤ",
+ "ooui-dialog-message-reject": "لغو",
+ "ooui-dialog-process-error": "ىک مؤشکلي هنأ",
+ "ooui-dialog-process-dismiss": "وأبدي",
+ "ooui-dialog-process-retry": "هندئه حقسأى بۊکۊنين",
+ "ooui-dialog-process-continue": "ايدامه",
+ "ooui-selectfile-button-select": "ىکته فاىله دؤجين بۊکۊنين",
+ "ooui-selectfile-not-supported": "نشأنه فاىله دؤجين گۊدن",
+ "ooui-selectfile-placeholder": "هيچ فاىلي دؤجين نۊبؤ",
+ "ooui-selectfile-dragdrop-placeholder": "فاىله ائره رها بکۊنين"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/gom-latn.json b/www/wiki/resources/lib/oojs-ui/i18n/gom-latn.json
new file mode 100644
index 00000000..afd47100
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/gom-latn.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "The Discoverer"
+ ]
+ },
+ "ooui-toolbar-more": "Anik",
+ "ooui-toolgroup-expand": "Anik",
+ "ooui-dialog-message-reject": "Rodd'dd kor",
+ "ooui-dialog-process-retry": "Porot proyotn kor",
+ "ooui-selectfile-button-select": "Ek fayl nivodd",
+ "ooui-selectfile-placeholder": "Khuimchech fayl nivddunk nam",
+ "ooui-selectfile-dragdrop-placeholder": "Fayl hanga udoi"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/gor.json b/www/wiki/resources/lib/oojs-ui/i18n/gor.json
new file mode 100644
index 00000000..ca0f1b42
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/gor.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Marwan Mohamad"
+ ]
+ },
+ "ooui-outline-control-move-down": "Heyiya botu ode tibawa",
+ "ooui-outline-control-move-up": "Heyiya botu ode yitaato",
+ "ooui-outline-control-remove": "Yinggila botu",
+ "ooui-toolbar-more": "Pe'eentapo",
+ "ooui-toolgroup-expand": "Pe'eentapo",
+ "ooui-toolgroup-collapse": "ngoolo botu",
+ "ooui-dialog-message-accept": "Jo",
+ "ooui-dialog-message-reject": "Bataliya",
+ "ooui-dialog-process-error": "Woluwo u yilotalawa",
+ "ooui-dialog-process-dismiss": "He'uti",
+ "ooui-dialog-process-retry": "Yimontali pooli",
+ "ooui-dialog-process-continue": "Turusi",
+ "ooui-selectfile-button-select": "Tulawota berkas tuwawu",
+ "ooui-selectfile-not-supported": "Berkas tilulawoto ja motuhatawa",
+ "ooui-selectfile-placeholder": "Diya'a berkas u letulawoto",
+ "ooui-selectfile-dragdrop-placeholder": "Dutuwa berkas teeya"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/gu.json b/www/wiki/resources/lib/oojs-ui/i18n/gu.json
new file mode 100644
index 00000000..e7dfeb20
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/gu.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ashok modhvadia",
+ "KartikMistry",
+ "The Discoverer",
+ "NehalDaveND",
+ "Dsvyas"
+ ]
+ },
+ "ooui-outline-control-move-down": "વસ્તુ નીચે ખસેડો",
+ "ooui-outline-control-move-up": "વસ્તુ ઉપર ખસેડો",
+ "ooui-outline-control-remove": "વસ્તુ હટાવો",
+ "ooui-toolbar-more": "વધુ",
+ "ooui-toolgroup-expand": "વધુ",
+ "ooui-toolgroup-collapse": "ઓછા",
+ "ooui-dialog-message-accept": "બરાબર",
+ "ooui-dialog-message-reject": "રદ કરો",
+ "ooui-dialog-process-error": "કંઇક ગરબડ થઇ",
+ "ooui-dialog-process-dismiss": "વિસર્જન",
+ "ooui-dialog-process-retry": "ફરી પ્રયત્ન કરો",
+ "ooui-dialog-process-continue": "ચાલુ રાખો",
+ "ooui-selectfile-button-select": "ફાઈલ પસંદ કરો",
+ "ooui-selectfile-not-supported": "ફાઇલ પસંદગીની જોગવાઈ નથી",
+ "ooui-selectfile-placeholder": "કોઇ ફાઇલ પસંદ નથી કરાઈ",
+ "ooui-selectfile-dragdrop-placeholder": "અહીં ફાઇલ મૂકો"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/he.json b/www/wiki/resources/lib/oojs-ui/i18n/he.json
new file mode 100644
index 00000000..0864ed9c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/he.json
@@ -0,0 +1,35 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "ExampleTomer",
+ "Guycn2",
+ "Matanya",
+ "Mooeypoo",
+ "Orsa",
+ "Shimmin Beg",
+ "אור שפירא",
+ "חיים",
+ "ערן",
+ "פוילישער",
+ "קיפודנחש"
+ ]
+ },
+ "ooui-outline-control-move-down": "להזיז את הפריט מטה",
+ "ooui-outline-control-move-up": "להזיז את הפריט מעלה",
+ "ooui-outline-control-remove": "להסיר את הפריט",
+ "ooui-toolbar-more": "עוד",
+ "ooui-toolgroup-expand": "יותר",
+ "ooui-toolgroup-collapse": "פחות",
+ "ooui-item-remove": "הסרה",
+ "ooui-dialog-message-accept": "אישור",
+ "ooui-dialog-message-reject": "ביטול",
+ "ooui-dialog-process-error": "משהו השתבש",
+ "ooui-dialog-process-dismiss": "לוותר",
+ "ooui-dialog-process-retry": "לנסות שוב",
+ "ooui-dialog-process-continue": "המשך",
+ "ooui-selectfile-button-select": "נא לבחור קובץ",
+ "ooui-selectfile-not-supported": "בחירת קבצים אינה נתמכת",
+ "ooui-selectfile-placeholder": "לא נבחר שום קובץ",
+ "ooui-selectfile-dragdrop-placeholder": "נא לשחרר את הקובץ כאן"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/hi.json b/www/wiki/resources/lib/oojs-ui/i18n/hi.json
new file mode 100644
index 00000000..ce007fc1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/hi.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ansumang",
+ "Devayon",
+ "Rajesh",
+ "Siddhartha Ghai",
+ "Goelujjwal",
+ "Ankita-ks",
+ "Param Mudgal",
+ "Sfic"
+ ]
+ },
+ "ooui-outline-control-move-down": "प्रविष्टि नीचे ले जाएँ",
+ "ooui-outline-control-move-up": "प्रविष्टि ऊपर ले जाएँ",
+ "ooui-outline-control-remove": "आइटम हटाएँ",
+ "ooui-toolbar-more": "अधिक",
+ "ooui-toolgroup-expand": "अधिक",
+ "ooui-toolgroup-collapse": "कम",
+ "ooui-dialog-message-accept": "ठीक है",
+ "ooui-dialog-message-reject": "रद्द करें",
+ "ooui-dialog-process-error": "कुछ गलत हुअा है",
+ "ooui-dialog-process-dismiss": "ख़ारिज करें",
+ "ooui-dialog-process-retry": "पुनः प्रयास करें",
+ "ooui-dialog-process-continue": "जारी रखें",
+ "ooui-selectfile-button-select": "फ़ाइल चुनें",
+ "ooui-selectfile-not-supported": "फ़ाइल का चयन समर्थित नहीं है",
+ "ooui-selectfile-placeholder": "कोई फाइल चुनी नही गई हेै",
+ "ooui-selectfile-dragdrop-placeholder": "फ़ाइल यहाँ डालें"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/hif-latn.json b/www/wiki/resources/lib/oojs-ui/i18n/hif-latn.json
new file mode 100644
index 00000000..9e903ca5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/hif-latn.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Thakurji"
+ ]
+ },
+ "ooui-outline-control-move-down": "Item ke niche karo",
+ "ooui-outline-control-move-up": "Item ke uppar karo",
+ "ooui-outline-control-remove": "Item ke hatao",
+ "ooui-toolbar-more": "Aur",
+ "ooui-toolgroup-expand": "Aur",
+ "ooui-toolgroup-collapse": "Kamtii",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancel karo",
+ "ooui-dialog-process-error": "Koi chij wrong hoe gais",
+ "ooui-dialog-process-dismiss": "Dismiss karo",
+ "ooui-dialog-process-retry": "Fir se try karo",
+ "ooui-dialog-process-continue": "Continue",
+ "ooui-selectfile-button-select": "Ek file ke select karo",
+ "ooui-selectfile-not-supported": "File selection ke support nai karaa jaawe hai",
+ "ooui-selectfile-placeholder": "Koi file ke nai select karaa gais hai",
+ "ooui-selectfile-dragdrop-placeholder": "Hian pe file ke girao"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/hr.json b/www/wiki/resources/lib/oojs-ui/i18n/hr.json
new file mode 100644
index 00000000..b07594ca
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/hr.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "MaGa",
+ "Roberta F.",
+ "SpeedyGonsales",
+ "Zeljko.filipin"
+ ]
+ },
+ "ooui-outline-control-move-down": "Premjesti stavku dolje",
+ "ooui-outline-control-move-up": "Premjesti stavku gore",
+ "ooui-outline-control-remove": "Ukloni",
+ "ooui-toolbar-more": "Više",
+ "ooui-toolgroup-expand": "Više",
+ "ooui-toolgroup-collapse": "Manje",
+ "ooui-dialog-message-accept": "U redu",
+ "ooui-dialog-message-reject": "Odustani",
+ "ooui-dialog-process-error": "Nešto je pošlo po zlu",
+ "ooui-dialog-process-dismiss": "Zatvori",
+ "ooui-dialog-process-retry": "Pokušajte ponovo",
+ "ooui-selectfile-button-select": "Odaberi datoteku",
+ "ooui-selectfile-placeholder": "Datoteka nije označena",
+ "ooui-selectfile-dragdrop-placeholder": "Povucite datoteku ovdje"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/hrx.json b/www/wiki/resources/lib/oojs-ui/i18n/hrx.json
new file mode 100644
index 00000000..1534af76
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/hrx.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Midnight Gambler"
+ ]
+ },
+ "ooui-toolbar-more": "Meahr",
+ "ooui-toolgroup-expand": "Meahr",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Abbreche",
+ "ooui-dialog-process-dismiss": "Ausblenne"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/hsb.json b/www/wiki/resources/lib/oojs-ui/i18n/hsb.json
new file mode 100644
index 00000000..00894e4e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/hsb.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "J budissin",
+ "Michawiki"
+ ]
+ },
+ "ooui-outline-control-move-down": "Zapisk dele přesunyć",
+ "ooui-outline-control-move-up": "Zapisk horje přesunyć",
+ "ooui-outline-control-remove": "Zapisk wotstronić",
+ "ooui-toolbar-more": "Wjace",
+ "ooui-toolgroup-expand": "Wjace",
+ "ooui-toolgroup-collapse": "Mjenje",
+ "ooui-dialog-message-accept": "W porjadku",
+ "ooui-dialog-message-reject": "Přetorhnyć",
+ "ooui-dialog-process-error": "Něšto je so nimokuliło",
+ "ooui-dialog-process-dismiss": "Schować",
+ "ooui-dialog-process-retry": "Hišće raz spytać",
+ "ooui-dialog-process-continue": "Dale"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/hu-formal.json b/www/wiki/resources/lib/oojs-ui/i18n/hu-formal.json
new file mode 100644
index 00000000..34aa0ae6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/hu-formal.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Misibacsi"
+ ]
+ },
+ "ooui-outline-control-move-down": "Elem mozgatása lefelé",
+ "ooui-outline-control-move-up": "Elem mozgatása felfelé",
+ "ooui-outline-control-remove": "Elem eltávolítása",
+ "ooui-toolbar-more": "Tovább...",
+ "ooui-toolgroup-expand": "Tovább",
+ "ooui-toolgroup-collapse": "Kevesebb",
+ "ooui-dialog-message-accept": "Rendben",
+ "ooui-dialog-message-reject": "Mégse",
+ "ooui-dialog-process-error": "Valami elromlott.",
+ "ooui-dialog-process-dismiss": "Mégse",
+ "ooui-dialog-process-retry": "Próbálja újra",
+ "ooui-dialog-process-continue": "Folytatás",
+ "ooui-selectfile-not-supported": "A fájl kiválasztása nincs támogatva",
+ "ooui-selectfile-placeholder": "Nincs fájl kiválasztva"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/hu.json b/www/wiki/resources/lib/oojs-ui/i18n/hu.json
new file mode 100644
index 00000000..cf26cc1a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/hu.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dj",
+ "Einstein2",
+ "Misibacsi",
+ "ViDam",
+ "Tacsipacsi",
+ "Csega",
+ "Kishajnalka"
+ ]
+ },
+ "ooui-outline-control-move-down": "Elem mozgatása lefelé",
+ "ooui-outline-control-move-up": "Elem mozgatása felfelé",
+ "ooui-outline-control-remove": "Elem eltávolítása",
+ "ooui-toolbar-more": "Több",
+ "ooui-toolgroup-expand": "Több",
+ "ooui-toolgroup-collapse": "Kevesebb",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Mégse",
+ "ooui-dialog-process-error": "Valami elromlott",
+ "ooui-dialog-process-dismiss": "Elrejt",
+ "ooui-dialog-process-retry": "Próbáld újra",
+ "ooui-dialog-process-continue": "Folytatás",
+ "ooui-selectfile-button-select": "Fájl kiválasztása",
+ "ooui-selectfile-not-supported": "A fájl kiválasztása nincs támogatva",
+ "ooui-selectfile-placeholder": "Nincs fájl kiválasztva",
+ "ooui-selectfile-dragdrop-placeholder": "Dobd ide a fájlt"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/hy.json b/www/wiki/resources/lib/oojs-ui/i18n/hy.json
new file mode 100644
index 00000000..341d0ff1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/hy.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Vacio",
+ "Xelgen",
+ "Դավիթ Սարոյան",
+ "Vahe Gharakhanyan"
+ ]
+ },
+ "ooui-outline-control-move-down": "Իջեցնել ներքև",
+ "ooui-outline-control-move-up": "Բարձրացնել կետը",
+ "ooui-outline-control-remove": "Հեռացնել տարրը",
+ "ooui-toolbar-more": "Ավելին",
+ "ooui-toolgroup-expand": "Ավելին",
+ "ooui-toolgroup-collapse": "Պակաս",
+ "ooui-dialog-message-accept": "Լավ",
+ "ooui-dialog-message-reject": "Չեղարկել",
+ "ooui-dialog-process-error": "Ինչ-որ սխալ է տեղի ունեցել",
+ "ooui-dialog-process-dismiss": "Փակել",
+ "ooui-dialog-process-retry": "Կրկին փորձել",
+ "ooui-dialog-process-continue": "Շարունակել",
+ "ooui-selectfile-button-select": "Ընտրել նիշք",
+ "ooui-selectfile-not-supported": "Ֆայլի ընտրությունը չի պաշտպանվում",
+ "ooui-selectfile-placeholder": "Ֆայլն ընտրված չէ",
+ "ooui-selectfile-dragdrop-placeholder": "Ֆայլը գցել այստե"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ia.json b/www/wiki/resources/lib/oojs-ui/i18n/ia.json
new file mode 100644
index 00000000..ceb27c9f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ia.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "McDutchie"
+ ]
+ },
+ "ooui-outline-control-move-down": "Displaciar elemento in basso",
+ "ooui-outline-control-move-up": "Displaciar elemento in alto",
+ "ooui-outline-control-remove": "Remover elemento",
+ "ooui-toolbar-more": "Plus",
+ "ooui-toolgroup-expand": "Plus",
+ "ooui-toolgroup-collapse": "Minus",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancellar",
+ "ooui-dialog-process-error": "Qualcosa ha vadite mal",
+ "ooui-dialog-process-dismiss": "Clauder",
+ "ooui-dialog-process-retry": "Reprobar",
+ "ooui-dialog-process-continue": "Continuar",
+ "ooui-selectfile-button-select": "Selige un file",
+ "ooui-selectfile-not-supported": "Le selection de files non es supportate",
+ "ooui-selectfile-placeholder": "Nulle file es seligite",
+ "ooui-selectfile-dragdrop-placeholder": "Depone file hic"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/id.json b/www/wiki/resources/lib/oojs-ui/i18n/id.json
new file mode 100644
index 00000000..c53e058c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/id.json
@@ -0,0 +1,32 @@
+{
+ "@metadata": {
+ "authors": [
+ "Farras",
+ "Ilham151096",
+ "Iwan Novirion",
+ "Iyan",
+ "Kenrick95",
+ "McDutchie",
+ "Rv77ax",
+ "William Surya Permana",
+ "Rachmat.Wahidi",
+ "Rachmat04"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pindahkan butir ke bawah",
+ "ooui-outline-control-move-up": "Pindahkan butir ke atas",
+ "ooui-outline-control-remove": "Hapus butir",
+ "ooui-toolbar-more": "Lainnya",
+ "ooui-toolgroup-expand": "Selengkapnya",
+ "ooui-toolgroup-collapse": "Secukupnya",
+ "ooui-dialog-message-accept": "Oke",
+ "ooui-dialog-message-reject": "Batal",
+ "ooui-dialog-process-error": "Ada yang tidak beres",
+ "ooui-dialog-process-dismiss": "Tutup",
+ "ooui-dialog-process-retry": "Coba lagi",
+ "ooui-dialog-process-continue": "Lanjutkan",
+ "ooui-selectfile-button-select": "Pilih berkas",
+ "ooui-selectfile-not-supported": "Peilihan berkas tidak didukung",
+ "ooui-selectfile-placeholder": "Tidak ada berkas yang terpilih",
+ "ooui-selectfile-dragdrop-placeholder": "Letakkan berkas di sini"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ie.json b/www/wiki/resources/lib/oojs-ui/i18n/ie.json
new file mode 100644
index 00000000..241cc331
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ie.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Makuba"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mover element a infra",
+ "ooui-outline-control-move-up": "Mover element a supra",
+ "ooui-toolbar-more": "Plu"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ilo.json b/www/wiki/resources/lib/oojs-ui/i18n/ilo.json
new file mode 100644
index 00000000..287c86d6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ilo.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lam-ang"
+ ]
+ },
+ "ooui-outline-control-move-down": "Ipababa ti banag",
+ "ooui-outline-control-move-up": "Ipangato ti banag",
+ "ooui-outline-control-remove": "Ikkaten ti banag",
+ "ooui-toolbar-more": "Adu pay",
+ "ooui-toolgroup-expand": "Adu pay",
+ "ooui-toolgroup-collapse": "Basbassit",
+ "ooui-dialog-message-accept": "Sige",
+ "ooui-dialog-message-reject": "Ukasen",
+ "ooui-dialog-process-error": "Adda madi a napasamak",
+ "ooui-dialog-process-dismiss": "Pugsayen",
+ "ooui-dialog-process-retry": "Padasen manen",
+ "ooui-dialog-process-continue": "Agtuloy",
+ "ooui-selectfile-not-supported": "Saan a masuportaran ti panagpili ti papeles",
+ "ooui-selectfile-placeholder": "Awan ti napili a papeles"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/inh.json b/www/wiki/resources/lib/oojs-ui/i18n/inh.json
new file mode 100644
index 00000000..a897ed58
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/inh.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Adam-Yourist",
+ "ElizaMag"
+ ]
+ },
+ "ooui-outline-control-move-down": "Элемент Iолохеяккха",
+ "ooui-outline-control-move-up": "Элемент Iолакхеяккха",
+ "ooui-outline-control-remove": "ДIаяккха пункт",
+ "ooui-toolbar-more": "Кхы а",
+ "ooui-toolgroup-expand": "Дукха",
+ "ooui-toolgroup-collapse": "КӀезига",
+ "ooui-dialog-message-accept": "ОК",
+ "ooui-dialog-message-reject": "Эшац",
+ "ooui-dialog-process-error": "Харцахь хилар цхьа хIама",
+ "ooui-dialog-process-dismiss": "ДIакъовла",
+ "ooui-dialog-process-retry": "Кхы цкъа де гIорта",
+ "ooui-dialog-process-continue": "ДIаьхде",
+ "ooui-selectfile-button-select": "Файл хьахаржа",
+ "ooui-selectfile-not-supported": "Файл харжа вIаштаь дац",
+ "ooui-selectfile-placeholder": "Файл хержа яц",
+ "ooui-selectfile-dragdrop-placeholder": "Хьадехьаяккха файл укхаз"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/io.json b/www/wiki/resources/lib/oojs-ui/i18n/io.json
new file mode 100644
index 00000000..7d7b1b83
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/io.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Idojc"
+ ]
+ },
+ "ooui-outline-control-move-down": "Movar elemento adsube",
+ "ooui-outline-control-move-up": "Movar elemento adsupere",
+ "ooui-outline-control-remove": "Forigar elemento",
+ "ooui-toolbar-more": "Plu multa",
+ "ooui-toolgroup-expand": "Plu multa",
+ "ooui-toolgroup-collapse": "Min multa",
+ "ooui-dialog-message-accept": "Aplikar",
+ "ooui-dialog-message-reject": "Anular",
+ "ooui-dialog-process-error": "Ulo faliis",
+ "ooui-dialog-process-dismiss": "Celar",
+ "ooui-dialog-process-retry": "Riprobar",
+ "ooui-dialog-process-continue": "Durar",
+ "ooui-selectfile-button-select": "Selektar dokumento",
+ "ooui-selectfile-not-supported": "Dokumento-selekto ne esas suportata",
+ "ooui-selectfile-placeholder": "Nula dokumento selektesis",
+ "ooui-selectfile-dragdrop-placeholder": "Pozar dokumento hike"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/is.json b/www/wiki/resources/lib/oojs-ui/i18n/is.json
new file mode 100644
index 00000000..574c5927
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/is.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Maxí",
+ "Snævar"
+ ]
+ },
+ "ooui-outline-control-move-down": "Færa atriði niður",
+ "ooui-outline-control-move-up": "Færa atriði upp",
+ "ooui-outline-control-remove": "Fjarlægja atriði",
+ "ooui-toolbar-more": "Fleira",
+ "ooui-toolgroup-expand": "Fleira",
+ "ooui-toolgroup-collapse": "Færra",
+ "ooui-dialog-message-accept": "Í lagi",
+ "ooui-dialog-message-reject": "Hætta við",
+ "ooui-dialog-process-error": "Eitthvað mistókst",
+ "ooui-dialog-process-dismiss": "Loka",
+ "ooui-dialog-process-retry": "Reyna aftur",
+ "ooui-dialog-process-continue": "Halda áfram",
+ "ooui-selectfile-button-select": "Velja skrá",
+ "ooui-selectfile-not-supported": "Skráar val er ekki stutt.",
+ "ooui-selectfile-placeholder": "Engin skrá er valin",
+ "ooui-selectfile-dragdrop-placeholder": "Slepptu skránni hérna"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/it.json b/www/wiki/resources/lib/oojs-ui/i18n/it.json
new file mode 100644
index 00000000..a301b663
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/it.json
@@ -0,0 +1,39 @@
+{
+ "@metadata": {
+ "authors": [
+ "Beta16",
+ "Darth Kule",
+ "Doc.mari",
+ "Eleonora negri",
+ "Elitre",
+ "F. Cosoleto",
+ "FRacco",
+ "Gianfranco",
+ "Minerva Titani",
+ "Raoli",
+ "Una giornata uggiosa '94",
+ "Ontsed",
+ "Alexmar983",
+ "Nemo bis",
+ "Jdforrester",
+ "Fringio"
+ ]
+ },
+ "ooui-outline-control-move-down": "Sposta in basso",
+ "ooui-outline-control-move-up": "Sposta in alto",
+ "ooui-outline-control-remove": "Rimuovi elemento",
+ "ooui-toolbar-more": "Altro",
+ "ooui-toolgroup-expand": "Altro",
+ "ooui-toolgroup-collapse": "Meno",
+ "ooui-item-remove": "Rimuovi",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Annulla",
+ "ooui-dialog-process-error": "Qualcosa è andato storto",
+ "ooui-dialog-process-dismiss": "Nascondi",
+ "ooui-dialog-process-retry": "Riprova",
+ "ooui-dialog-process-continue": "Continua",
+ "ooui-selectfile-button-select": "Seleziona un file",
+ "ooui-selectfile-not-supported": "La selezione del file non è supportata",
+ "ooui-selectfile-placeholder": "Nessun file è selezionato",
+ "ooui-selectfile-dragdrop-placeholder": "Posiziona i file qui"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ja.json b/www/wiki/resources/lib/oojs-ui/i18n/ja.json
new file mode 100644
index 00000000..308cb80c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ja.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Fryed-peach",
+ "Miya",
+ "Penn Station",
+ "Shirayuki",
+ "Takot",
+ "Los688",
+ "Sujiniku",
+ "Translatealcd"
+ ]
+ },
+ "ooui-outline-control-move-down": "項目を下に移動させる",
+ "ooui-outline-control-move-up": "項目を上に移動させる",
+ "ooui-outline-control-remove": "項目を除去",
+ "ooui-toolbar-more": "その他",
+ "ooui-toolgroup-expand": "その他",
+ "ooui-toolgroup-collapse": "折り畳む",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "キャンセル",
+ "ooui-dialog-process-error": "エラーが発生しました…",
+ "ooui-dialog-process-dismiss": "閉じる",
+ "ooui-dialog-process-retry": "もう一度お試しください",
+ "ooui-dialog-process-continue": "続行",
+ "ooui-selectfile-button-select": "ファイルを選択",
+ "ooui-selectfile-not-supported": "ファイルの選択はサポートされていません",
+ "ooui-selectfile-placeholder": "ファイルが選択されていません",
+ "ooui-selectfile-dragdrop-placeholder": "ファイルをここにドロップ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/jv.json b/www/wiki/resources/lib/oojs-ui/i18n/jv.json
new file mode 100644
index 00000000..5ade0156
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/jv.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gleki",
+ "NoiX180",
+ "Pras",
+ "Jadinegara",
+ "Meursault2004"
+ ]
+ },
+ "ooui-outline-control-move-down": "Lih barang mangisor",
+ "ooui-outline-control-move-up": "Lih barang mandhuwur",
+ "ooui-outline-control-remove": "Buwang barang",
+ "ooui-toolbar-more": "Liyané",
+ "ooui-toolgroup-expand": "Liyané",
+ "ooui-toolgroup-collapse": "Sacukupé",
+ "ooui-dialog-message-accept": "Oké",
+ "ooui-dialog-message-reject": "Wurung",
+ "ooui-dialog-process-error": "Ana sing salah",
+ "ooui-dialog-process-dismiss": "Tutup",
+ "ooui-dialog-process-retry": "Jajalen manèh",
+ "ooui-dialog-process-continue": "Bacutaké",
+ "ooui-selectfile-button-select": "Pilih barkas",
+ "ooui-selectfile-not-supported": "Ora bisa milih barkas",
+ "ooui-selectfile-placeholder": "Ora ana barkas sing dipilih",
+ "ooui-selectfile-dragdrop-placeholder": "Dèkèk barkas ing kéné"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ka.json b/www/wiki/resources/lib/oojs-ui/i18n/ka.json
new file mode 100644
index 00000000..31df1692
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ka.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "BRUTE",
+ "David1010",
+ "Gleki",
+ "ITshnik",
+ "MIKHEIL",
+ "NoiX180",
+ "Pras",
+ "Tokoko"
+ ]
+ },
+ "ooui-outline-control-move-down": "ელემენტის ქვემოთ გადატანა",
+ "ooui-outline-control-move-up": "ელემენტის ზემოთ გადატანა",
+ "ooui-outline-control-remove": "წაშლა",
+ "ooui-toolbar-more": "მეტი",
+ "ooui-toolgroup-expand": "მეტი",
+ "ooui-toolgroup-collapse": "რამდენიმე",
+ "ooui-dialog-message-accept": "დიახ",
+ "ooui-dialog-message-reject": "გაუქმება",
+ "ooui-dialog-process-error": "მოხდა რაღაც შეცდომა",
+ "ooui-dialog-process-dismiss": "დამალვა",
+ "ooui-dialog-process-retry": "კიდევ სცადეთ",
+ "ooui-dialog-process-continue": "გაგრძელება",
+ "ooui-selectfile-button-select": "აირჩიეთ ფაილი",
+ "ooui-selectfile-not-supported": "ფაილის არჩევა არ არის მხარდაჭერილი",
+ "ooui-selectfile-placeholder": "ფაილი არ არის არჩეული",
+ "ooui-selectfile-dragdrop-placeholder": "ჩააგდეთ ფაილი აქ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/kab.json b/www/wiki/resources/lib/oojs-ui/i18n/kab.json
new file mode 100644
index 00000000..55016b22
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/kab.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Belkacem77"
+ ]
+ },
+ "ooui-outline-control-move-down": "Awi aferdi d akesser",
+ "ooui-outline-control-move-up": "Awi aferdis d asawen",
+ "ooui-outline-control-remove": "Kkes aferdis",
+ "ooui-toolbar-more": "Ugar",
+ "ooui-toolgroup-expand": "Ugar",
+ "ooui-toolgroup-collapse": "Drus",
+ "ooui-item-remove": "Kkes",
+ "ooui-dialog-message-accept": "IH",
+ "ooui-dialog-message-reject": "Sefsex",
+ "ooui-dialog-process-error": "Yella wayen yeḍran",
+ "ooui-dialog-process-dismiss": "Mdel",
+ "ooui-dialog-process-retry": "Ɛreḍ tikelt-nniden",
+ "ooui-dialog-process-continue": "Kemmel",
+ "ooui-selectfile-button-select": "Fren afaylu",
+ "ooui-selectfile-not-supported": "Afran n ufaylu ur yettusefrak ara",
+ "ooui-selectfile-placeholder": "Ulac afaylu yettwafernen",
+ "ooui-selectfile-dragdrop-placeholder": "Sers afaylu dagi"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/khw.json b/www/wiki/resources/lib/oojs-ui/i18n/khw.json
new file mode 100644
index 00000000..f0ce2073
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/khw.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "Rachitrali"
+ ]
+ },
+ "ooui-toolbar-more": "مزید",
+ "ooui-toolgroup-expand": "مزید",
+ "ooui-toolgroup-collapse": "ای کما",
+ "ooui-dialog-message-accept": "ٹھیک شیر",
+ "ooui-dialog-message-reject": "کھینسل"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/kk-cyrl.json b/www/wiki/resources/lib/oojs-ui/i18n/kk-cyrl.json
new file mode 100644
index 00000000..779ba7b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/kk-cyrl.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arystanbek"
+ ]
+ },
+ "ooui-outline-control-move-down": "Элементті төмен жылжыту",
+ "ooui-outline-control-move-up": "Элементті жоғары жылжыту",
+ "ooui-outline-control-remove": "Элементті алып тастау",
+ "ooui-toolbar-more": "толығырақ",
+ "ooui-toolgroup-expand": "Тағы",
+ "ooui-toolgroup-collapse": "Азырақ",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Қажет емес",
+ "ooui-dialog-process-error": "Бірдеңеден қате кетті",
+ "ooui-dialog-process-dismiss": "Тоқтату",
+ "ooui-dialog-process-retry": "Қайта байқап көріңіз",
+ "ooui-dialog-process-continue": "Жалғастыру",
+ "ooui-selectfile-button-select": "Файлды таңдау",
+ "ooui-selectfile-not-supported": "Файл таңдауды қолдамайды",
+ "ooui-selectfile-placeholder": "Файл таңдалмады",
+ "ooui-selectfile-dragdrop-placeholder": "Файлды мында жылжыту"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/km.json b/www/wiki/resources/lib/oojs-ui/i18n/km.json
new file mode 100644
index 00000000..e64889f4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/km.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sovichet",
+ "គីមស៊្រុន"
+ ]
+ },
+ "ooui-outline-control-move-down": "រុញ​ធាតុទៅ​ក្រោម",
+ "ooui-outline-control-move-up": "រុញធាតុទៅ​លើ",
+ "ooui-outline-control-remove": "ដកធាតុចេញ",
+ "ooui-toolbar-more": "បន្ថែមទៀត",
+ "ooui-toolgroup-expand": "មើលច្រើន",
+ "ooui-toolgroup-collapse": "មើលតិច",
+ "ooui-dialog-message-accept": "យល់ព្រម",
+ "ooui-dialog-message-reject": "បោះបង់",
+ "ooui-dialog-process-error": "មានបញ្ហាអ្វីមួយ",
+ "ooui-dialog-process-dismiss": "បិទ",
+ "ooui-dialog-process-retry": "ព្យាយាមម្ដងទៀត",
+ "ooui-dialog-process-continue": "បន្ត",
+ "ooui-selectfile-button-select": "ជ្រើសរើសឯកសារ",
+ "ooui-selectfile-not-supported": "ការជ្រើសរើសឯកសារមិនអាចប្រើបានទេ",
+ "ooui-selectfile-placeholder": "គ្មានឯកសារណាមួយត្រូវបានជ្រើសរើស",
+ "ooui-selectfile-dragdrop-placeholder": "ទម្លាក់ឯកសារនៅទីនេះ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/kn.json b/www/wiki/resources/lib/oojs-ui/i18n/kn.json
new file mode 100644
index 00000000..741cfb33
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/kn.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Vikassy",
+ "Nayvik",
+ "Omshivaprakash",
+ "Pavanaja",
+ "Yogesh"
+ ]
+ },
+ "ooui-outline-control-move-down": "ವಸ್ತುವನ್ನು ಕೆಳಗೆ ಸರಿಸು",
+ "ooui-outline-control-move-up": "ವಸ್ತುವನ್ನು ಮೇಲೆ ಸರಿಸು",
+ "ooui-outline-control-remove": "ವಸ್ತುವನ್ನು ತೆಗೆ",
+ "ooui-toolbar-more": "ಇನ್ನಷ್ಟು",
+ "ooui-toolgroup-expand": "ಇನ್ನಷ್ಟು",
+ "ooui-toolgroup-collapse": "ಕೆಲವೇ ಕೆಲವು",
+ "ooui-dialog-message-accept": "ಸರಿ",
+ "ooui-dialog-message-reject": "ರದ್ದುಮಾಡು",
+ "ooui-dialog-process-error": "ಏನೋ ಎಡವಟ್ಟಾಗಿದೆ....",
+ "ooui-dialog-process-dismiss": "ತೆಗೆದುಹಾಕು",
+ "ooui-dialog-process-retry": "ಮತ್ತೆ ಪ್ರಯತ್ನಿಸಿ",
+ "ooui-dialog-process-continue": "ಮುಂದುವರೆಸು",
+ "ooui-selectfile-button-select": "ಕಡತವನ್ನು ಆಯ್ಕೆಮಾಡಿ",
+ "ooui-selectfile-placeholder": "ಕಡತವು ಆಯ್ಕೆಯಾಗಿಲ್ಲ",
+ "ooui-selectfile-dragdrop-placeholder": "ಇಲ್ಲಿ ಕಡತವನ್ನು ಬಿಡಿ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ko.json b/www/wiki/resources/lib/oojs-ui/i18n/ko.json
new file mode 100644
index 00000000..dc3c84a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ko.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Freebiekr",
+ "Hym411",
+ "Kwj2772",
+ "LFM",
+ "아라",
+ "고기랑",
+ "Ryuch",
+ "Revi",
+ "Infinity",
+ "Hwangjy9",
+ "Ykhwong"
+ ]
+ },
+ "ooui-outline-control-move-down": "항목을 아래로 이동",
+ "ooui-outline-control-move-up": "항목을 위로 이동",
+ "ooui-outline-control-remove": "항목 제거",
+ "ooui-toolbar-more": "더 보기",
+ "ooui-toolgroup-expand": "더 보기",
+ "ooui-toolgroup-collapse": "덜 보기",
+ "ooui-item-remove": "제거",
+ "ooui-dialog-message-accept": "확인",
+ "ooui-dialog-message-reject": "취소",
+ "ooui-dialog-process-error": "무언가가 잘못되었습니다",
+ "ooui-dialog-process-dismiss": "숨기기",
+ "ooui-dialog-process-retry": "다시 시도하세요",
+ "ooui-dialog-process-continue": "계속",
+ "ooui-selectfile-button-select": "파일을 선택하세요",
+ "ooui-selectfile-not-supported": "파일 선택은 지원하지 않습니다",
+ "ooui-selectfile-placeholder": "선택한 파일 없음",
+ "ooui-selectfile-dragdrop-placeholder": "여기에 파일을 놓으세요"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/krc.json b/www/wiki/resources/lib/oojs-ui/i18n/krc.json
new file mode 100644
index 00000000..6f17b346
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/krc.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Iltever",
+ "Ernác"
+ ]
+ },
+ "ooui-outline-control-move-down": "Элементни тюбюне кёчюр",
+ "ooui-outline-control-move-up": "Элементни башына кёчюр",
+ "ooui-outline-control-remove": "Пунктну кетер",
+ "ooui-toolbar-more": "Энтда",
+ "ooui-toolgroup-expand": "Энтда",
+ "ooui-toolgroup-collapse": "Артха",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Ызына ал",
+ "ooui-dialog-process-error": "Не эсе да табсыз кетди",
+ "ooui-dialog-process-dismiss": "Джаб",
+ "ooui-dialog-process-retry": "Энтда сынаб кёр",
+ "ooui-dialog-process-continue": "Бардыр",
+ "ooui-selectfile-not-supported": "Файл сайлау тутулмайды",
+ "ooui-selectfile-placeholder": "Бир файл да сайланмагъанды"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/krl.json b/www/wiki/resources/lib/oojs-ui/i18n/krl.json
new file mode 100644
index 00000000..6ff25ebe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/krl.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mashoi7"
+ ]
+ },
+ "ooui-toolbar-more": "Enämpi",
+ "ooui-toolgroup-expand": "Enämpi",
+ "ooui-toolgroup-collapse": "Vähempi"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ksh.json b/www/wiki/resources/lib/oojs-ui/i18n/ksh.json
new file mode 100644
index 00000000..f99c29fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ksh.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Purodha"
+ ]
+ },
+ "ooui-outline-control-move-down": "Öm eine Plaz noh onge schiehbe",
+ "ooui-outline-control-move-up": "Öm eine Plaz noh bovve schiehbe",
+ "ooui-outline-control-remove": "Dä Plaz läddesch maache → fott domet!",
+ "ooui-toolbar-more": "Mih",
+ "ooui-toolgroup-expand": "Mih",
+ "ooui-toolgroup-collapse": "Winnijer",
+ "ooui-dialog-message-accept": "Lohß Jonn!",
+ "ooui-dialog-message-reject": "Ophühre",
+ "ooui-dialog-process-error": "Öhnsjädd es scheif jejange",
+ "ooui-dialog-process-dismiss": "Maach fott, ha_sch jelässe",
+ "ooui-dialog-process-retry": "Norr_ens versöhke",
+ "ooui-dialog-process-continue": "Wigger maache",
+ "ooui-selectfile-button-select": "Söhg en Dattei uß",
+ "ooui-selectfile-not-supported": "Mer ogerschtözze et Datteij_Ußwähle nit.",
+ "ooui-selectfile-placeholder": "Kein Dattei es ußjewählt"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ku-latn.json b/www/wiki/resources/lib/oojs-ui/i18n/ku-latn.json
new file mode 100644
index 00000000..99547449
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ku-latn.json
@@ -0,0 +1,17 @@
+{
+ "@metadata": {
+ "authors": [
+ "George Animal",
+ "Bikarhêner"
+ ]
+ },
+ "ooui-toolbar-more": "Bêhtir",
+ "ooui-toolgroup-expand": "Bêhtir",
+ "ooui-toolgroup-collapse": "Kêmtir",
+ "ooui-dialog-message-accept": "Baş e",
+ "ooui-dialog-message-reject": "Betal bike",
+ "ooui-dialog-process-retry": "Dîsa hewl bide",
+ "ooui-dialog-process-continue": "Bidomîne",
+ "ooui-selectfile-button-select": "Dosyeyekê hilbijêre",
+ "ooui-selectfile-placeholder": "Ti dosye nehatiye hilbijartin"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/kw.json b/www/wiki/resources/lib/oojs-ui/i18n/kw.json
new file mode 100644
index 00000000..a6c6d8ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/kw.json
@@ -0,0 +1,9 @@
+{
+ "@metadata": {
+ "authors": [
+ "George Animal",
+ "Nrowe",
+ "Purodha"
+ ]
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ky.json b/www/wiki/resources/lib/oojs-ui/i18n/ky.json
new file mode 100644
index 00000000..e2b8ab7a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ky.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chorobek",
+ "George Animal",
+ "Nrowe",
+ "Tynchtyk Chorotegin",
+ "Викиней"
+ ]
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/la.json b/www/wiki/resources/lib/oojs-ui/i18n/la.json
new file mode 100644
index 00000000..7a9b2d23
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/la.json
@@ -0,0 +1,15 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jdforrester"
+ ]
+ },
+ "ooui-toolbar-more": "Plus",
+ "ooui-toolgroup-expand": "Plus",
+ "ooui-toolgroup-collapse": "Paucior",
+ "ooui-dialog-message-accept": "Assentior",
+ "ooui-dialog-message-reject": "Dimittere",
+ "ooui-dialog-process-dismiss": "Dimittere",
+ "ooui-dialog-process-retry": "Retemptare",
+ "ooui-dialog-process-continue": "Pergere"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/lb.json b/www/wiki/resources/lib/oojs-ui/i18n/lb.json
new file mode 100644
index 00000000..3deee0d6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/lb.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Autokrator",
+ "Chorobek",
+ "Robby",
+ "Soued031",
+ "Tynchtyk Chorotegin",
+ "UV",
+ "Викиней"
+ ]
+ },
+ "ooui-outline-control-move-down": "Element erof réckelen",
+ "ooui-outline-control-move-up": "Element erop réckelen",
+ "ooui-outline-control-remove": "Element ewechhuelen",
+ "ooui-toolbar-more": "Méi",
+ "ooui-toolgroup-expand": "Méi",
+ "ooui-toolgroup-collapse": "Manner",
+ "ooui-item-remove": "Ewechhuelen",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Ofbriechen",
+ "ooui-dialog-process-error": "Et ass eppes schif gaang",
+ "ooui-dialog-process-dismiss": "Verwerfen",
+ "ooui-dialog-process-retry": "Nach eng Kéier probéieren",
+ "ooui-dialog-process-continue": "Virufueren",
+ "ooui-selectfile-button-select": "E Fichier eraussichen",
+ "ooui-selectfile-not-supported": "D'Eraussiche vu Fichiere gëtt net ënnerstëtzt.",
+ "ooui-selectfile-placeholder": "Et ass kee Fichier erausgesicht",
+ "ooui-selectfile-dragdrop-placeholder": "Fichier hei ofleeën"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/li.json b/www/wiki/resources/lib/oojs-ui/i18n/li.json
new file mode 100644
index 00000000..0012c9cd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/li.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Pahles",
+ "Ooswesthoesbes"
+ ]
+ },
+ "ooui-outline-control-move-down": "Item nao ónger verplaatse",
+ "ooui-outline-control-move-up": "Item nao bove verplaetse",
+ "ooui-outline-control-remove": "Item ewegsjaffe",
+ "ooui-toolbar-more": "Mieë",
+ "ooui-toolgroup-expand": "Mieë",
+ "ooui-toolgroup-collapse": "Minder",
+ "ooui-dialog-message-accept": "Ok",
+ "ooui-dialog-message-reject": "Aafbraeke",
+ "ooui-dialog-process-error": "Dao is get misgegange",
+ "ooui-dialog-process-dismiss": "Sjlete",
+ "ooui-dialog-process-retry": "Perbeer obbenuujts",
+ "ooui-dialog-process-continue": "Doorgaon",
+ "ooui-selectfile-button-select": "Kees e bestandj",
+ "ooui-selectfile-not-supported": "Selektie van 'n besjtandj waert neet óngersteund",
+ "ooui-selectfile-placeholder": "Dao is gein besjtandj geselekteerd",
+ "ooui-selectfile-dragdrop-placeholder": "Sleip e bestandj hieroppes"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/lki.json b/www/wiki/resources/lib/oojs-ui/i18n/lki.json
new file mode 100644
index 00000000..ab6db143
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/lki.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Hosseinblue",
+ "Arash71"
+ ]
+ },
+ "ooui-outline-control-move-down": "جاوواز کردن ئإ هووار",
+ "ooui-outline-control-move-up": "جاوواز کردن ئإ بِلِنگ",
+ "ooui-outline-control-remove": "حذف مورد",
+ "ooui-toolbar-more": "ویشتر/فرۀتر",
+ "ooui-toolgroup-expand": "ویشتر/فرۀتر",
+ "ooui-toolgroup-collapse": "کۀمتر",
+ "ooui-dialog-message-accept": "خوو/ باشد",
+ "ooui-dialog-message-reject": "ئآهووسانن/لغو",
+ "ooui-dialog-process-error": "مشکلی هۀس",
+ "ooui-dialog-process-dismiss": "رد کردن",
+ "ooui-dialog-process-retry": "دووآرۀ تلاش کۀ",
+ "ooui-dialog-process-continue": "ادامه-دؤم گرتن",
+ "ooui-selectfile-button-select": "فایلئ انتخاب کۀ",
+ "ooui-selectfile-not-supported": "انتخاب پرونده پشتیبانی نمی‌شود",
+ "ooui-selectfile-placeholder": "هیچ پرونده‌ای انتخاب نشده است",
+ "ooui-selectfile-dragdrop-placeholder": "فایل را اینجا رها کنید"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/lmo.json b/www/wiki/resources/lib/oojs-ui/i18n/lmo.json
new file mode 100644
index 00000000..87309db0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/lmo.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ninonino"
+ ]
+ },
+ "ooui-outline-control-move-down": "Spòsta 'n zó",
+ "ooui-outline-control-move-up": "Spòsta 'n sö",
+ "ooui-toolbar-more": "Amò"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/lt.json b/www/wiki/resources/lib/oojs-ui/i18n/lt.json
new file mode 100644
index 00000000..86c6d648
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/lt.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Audriusa",
+ "Eitvys200",
+ "Mantak111",
+ "Albertas"
+ ]
+ },
+ "ooui-outline-control-move-down": "Perkelti elementą žemyn",
+ "ooui-outline-control-move-up": "Perkelti elementą aukštyn",
+ "ooui-outline-control-remove": "Šalinti įrašą",
+ "ooui-toolbar-more": "Daugiau",
+ "ooui-toolgroup-expand": "Daugiau",
+ "ooui-toolgroup-collapse": "Mažiau",
+ "ooui-dialog-message-accept": "Gerai",
+ "ooui-dialog-message-reject": "Atšaukti",
+ "ooui-dialog-process-error": "Kažkas nutiko ne taip",
+ "ooui-dialog-process-dismiss": "Paslėpti",
+ "ooui-dialog-process-retry": "Bandykite dar kartą",
+ "ooui-dialog-process-continue": "Tęsti",
+ "ooui-selectfile-button-select": "Pasirinkti failą",
+ "ooui-selectfile-not-supported": "Failų pasirinkimas nepalaikomas",
+ "ooui-selectfile-placeholder": "Nėra pasirinktų failų",
+ "ooui-selectfile-dragdrop-placeholder": "Atitempkite failą čia"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/luz.json b/www/wiki/resources/lib/oojs-ui/i18n/luz.json
new file mode 100644
index 00000000..d48a9dfa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/luz.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "علی ساکی لرستانی"
+ ]
+ },
+ "ooui-outline-control-move-down": "انتقال مورد وه دومن",
+ "ooui-outline-control-move-up": "انتقال مورد وه بالا",
+ "ooui-outline-control-remove": "حذف مورد",
+ "ooui-toolbar-more": "هنی",
+ "ooui-toolgroup-expand": "هنی",
+ "ooui-toolgroup-collapse": "کم تر",
+ "ooui-dialog-message-accept": "خووه",
+ "ooui-dialog-message-reject": "لغو",
+ "ooui-dialog-process-error": "یه چیایی اشتباه ویده",
+ "ooui-dialog-process-dismiss": "منفصل کردن",
+ "ooui-dialog-process-retry": "دوباره تلاش کردن",
+ "ooui-dialog-process-continue": "ادامه دائن",
+ "ooui-selectfile-not-supported": "فایل انتخابی پشتیبانی نوابیه",
+ "ooui-selectfile-placeholder": "فایلی انتخاب نوابیه"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/lv.json b/www/wiki/resources/lib/oojs-ui/i18n/lv.json
new file mode 100644
index 00000000..74658ce1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/lv.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Admresdeserv.",
+ "Audriusa",
+ "Eitvys200",
+ "Papuass",
+ "PeterisP"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pārvietot vienumu uz leju",
+ "ooui-outline-control-move-up": "Pārvietot vienumu uz augšu",
+ "ooui-outline-control-remove": "Noņemt vienumu",
+ "ooui-toolbar-more": "Vairāk",
+ "ooui-toolgroup-expand": "Vairāk",
+ "ooui-toolgroup-collapse": "Mazāk",
+ "ooui-dialog-message-accept": "Labi",
+ "ooui-dialog-message-reject": "Atcelt",
+ "ooui-dialog-process-error": "Kaut kas nogāja greizi",
+ "ooui-dialog-process-dismiss": "Paslēpt",
+ "ooui-dialog-process-retry": "Mēģināt vēlreiz",
+ "ooui-dialog-process-continue": "Turpināt",
+ "ooui-selectfile-button-select": "Izvēlies failu",
+ "ooui-selectfile-not-supported": "Failu izvēle nav atbalstīta",
+ "ooui-selectfile-placeholder": "Nav izvēlēts neviens fails",
+ "ooui-selectfile-dragdrop-placeholder": "Nomet failu šeit"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/lzh.json b/www/wiki/resources/lib/oojs-ui/i18n/lzh.json
new file mode 100644
index 00000000..2b3ad53c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/lzh.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Joe young yu"
+ ]
+ },
+ "ooui-dialog-message-accept": "可"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/mg.json b/www/wiki/resources/lib/oojs-ui/i18n/mg.json
new file mode 100644
index 00000000..722b3e29
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/mg.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jagwar"
+ ]
+ },
+ "ooui-outline-control-move-down": "Hampidina ilay zavatra",
+ "ooui-outline-control-move-up": "Hampiakatra ilay zavatra",
+ "ooui-outline-control-remove": "Hanala iay zavatra",
+ "ooui-toolbar-more": "Be kokoa",
+ "ooui-toolgroup-expand": "Be kokoa",
+ "ooui-toolgroup-collapse": "Kely kokoa",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Avela",
+ "ooui-dialog-process-error": "Nisy hadisoana nitranga",
+ "ooui-dialog-process-dismiss": "Esorina",
+ "ooui-dialog-process-retry": "Andramana indray",
+ "ooui-dialog-process-continue": "Tohizana",
+ "ooui-selectfile-button-select": "Misafidia rakitra iray",
+ "ooui-selectfile-not-supported": "Tsy zaka ny fisafidiana rakitra",
+ "ooui-selectfile-placeholder": "Tsy misy rakitra voafidy",
+ "ooui-selectfile-dragdrop-placeholder": "Hametraka rakitra eto"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/min.json b/www/wiki/resources/lib/oojs-ui/i18n/min.json
new file mode 100644
index 00000000..b8790d31
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/min.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "Iwan Novirion",
+ "Jagwar"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pindahan ko ka bawah",
+ "ooui-outline-control-move-up": "Pindahan ko ka ateh",
+ "ooui-outline-control-remove": "Hapuih ko",
+ "ooui-toolbar-more": "Lainnyo",
+ "ooui-dialog-message-accept": "Yo",
+ "ooui-dialog-message-reject": "Batal"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/mk.json b/www/wiki/resources/lib/oojs-ui/i18n/mk.json
new file mode 100644
index 00000000..23d07760
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/mk.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bjankuloski06",
+ "Brest",
+ "Iwan Novirion"
+ ]
+ },
+ "ooui-outline-control-move-down": "Помести надолу",
+ "ooui-outline-control-move-up": "Помести нагоре",
+ "ooui-outline-control-remove": "Отстрани ставка",
+ "ooui-toolbar-more": "Повеќе",
+ "ooui-toolgroup-expand": "Повеќе",
+ "ooui-toolgroup-collapse": "Помалку",
+ "ooui-item-remove": "Отстрани",
+ "ooui-dialog-message-accept": "ОК",
+ "ooui-dialog-message-reject": "Откажи",
+ "ooui-dialog-process-error": "Нешто не е во ред",
+ "ooui-dialog-process-dismiss": "Тргни",
+ "ooui-dialog-process-retry": "Обиди се пак",
+ "ooui-dialog-process-continue": "Продолжи",
+ "ooui-selectfile-button-select": "Одберете податотека",
+ "ooui-selectfile-not-supported": "Изборот на податотеки не е поддржан",
+ "ooui-selectfile-placeholder": "Немате одбрано податотека",
+ "ooui-selectfile-dragdrop-placeholder": "Тука пуштете ја податотеката"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ml.json b/www/wiki/resources/lib/oojs-ui/i18n/ml.json
new file mode 100644
index 00000000..9649b2eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ml.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kavya Manohar",
+ "Praveenp",
+ "Santhosh.thottingal",
+ "Vssun",
+ "Ranjithsiji"
+ ]
+ },
+ "ooui-outline-control-move-down": "ഇനം താഴേയ്ക്ക് മാറ്റുക",
+ "ooui-outline-control-move-up": "ഇനം മുകളിലേയ്ക്ക് മാറ്റുക",
+ "ooui-outline-control-remove": "ഇനം നീക്കംചെയ്യുക",
+ "ooui-toolbar-more": "കൂടുതൽ",
+ "ooui-toolgroup-expand": "കൂടുതൽ",
+ "ooui-toolgroup-collapse": "കുറച്ച്",
+ "ooui-dialog-message-accept": "ശരി",
+ "ooui-dialog-message-reject": "റദ്ദാക്കുക",
+ "ooui-dialog-process-error": "എന്തോ പ്രശ്നമുണ്ടായി",
+ "ooui-dialog-process-dismiss": "ഒഴിവാക്കുക",
+ "ooui-dialog-process-retry": "വീണ്ടും ശ്രമിക്കുക",
+ "ooui-dialog-process-continue": "തുടരുക",
+ "ooui-selectfile-button-select": "പ്രമാണം തിരഞ്ഞെടുക്കുക",
+ "ooui-selectfile-not-supported": "പ്രമാണം തിരഞ്ഞെടുക്കൽ പിന്തുണയ്ക്കുന്നില്ല",
+ "ooui-selectfile-placeholder": "പ്രമാണങ്ങൾ ഒന്നും തിരഞ്ഞെടുത്തിട്ടില്ല",
+ "ooui-selectfile-dragdrop-placeholder": "പ്രമാണം ഇവിടെ ഇടുക"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/mn.json b/www/wiki/resources/lib/oojs-ui/i18n/mn.json
new file mode 100644
index 00000000..500aca78
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/mn.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Munkhzaya.E"
+ ]
+ },
+ "ooui-toolbar-more": "Илүү",
+ "ooui-toolgroup-expand": "Илүү",
+ "ooui-toolgroup-collapse": "Цөөн",
+ "ooui-dialog-message-accept": "За",
+ "ooui-dialog-message-reject": "Цуцлах",
+ "ooui-dialog-process-error": "Ямар нэг алдаа гарсан",
+ "ooui-dialog-process-dismiss": "Нуух",
+ "ooui-dialog-process-retry": "Дахин оролдох",
+ "ooui-dialog-process-continue": "Цааш явах",
+ "ooui-selectfile-button-select": "Файлаа сонгох",
+ "ooui-selectfile-not-supported": "Сонгосол файл нь дэмжигдэхгүй байна",
+ "ooui-selectfile-placeholder": "Файл сонгоогүй байна",
+ "ooui-selectfile-dragdrop-placeholder": "Файлаа энд хадгалах"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/mr.json b/www/wiki/resources/lib/oojs-ui/i18n/mr.json
new file mode 100644
index 00000000..de8d6f1e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/mr.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kaajawa",
+ "Mahitgar",
+ "Praju23",
+ "V.narsikar",
+ "Ydyashad",
+ "संतोष दहिवळ",
+ "NehalDaveND",
+ "Sau6402"
+ ]
+ },
+ "ooui-outline-control-move-down": "घटक (आयटम) खाली सरकवा",
+ "ooui-outline-control-move-up": "घटक (आयटम) वर सरकवा",
+ "ooui-outline-control-remove": "बाब हटवा",
+ "ooui-toolbar-more": "अधिक",
+ "ooui-toolgroup-expand": "अधिक",
+ "ooui-toolgroup-collapse": "कमी",
+ "ooui-dialog-message-accept": "ठिक आहे",
+ "ooui-dialog-message-reject": "रद्द करा",
+ "ooui-dialog-process-error": "काहीतरी गडबड झाली",
+ "ooui-dialog-process-dismiss": "रद्द करा",
+ "ooui-dialog-process-retry": "पुन्हा प्रयत्न करा",
+ "ooui-dialog-process-continue": "चालू ठेवा",
+ "ooui-selectfile-button-select": "संचिका निवडा",
+ "ooui-selectfile-not-supported": "संचिका निवडणे साहाय्यीकृत नाही",
+ "ooui-selectfile-placeholder": "संचिका निवडल्या गेली नाही",
+ "ooui-selectfile-dragdrop-placeholder": "संचिका येथे टाका"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ms.json b/www/wiki/resources/lib/oojs-ui/i18n/ms.json
new file mode 100644
index 00000000..19ce1c2f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ms.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Anakmalaysia",
+ "Aurora",
+ "Pizza1016",
+ "Karmadunya9-"
+ ]
+ },
+ "ooui-outline-control-move-down": "Alihkan perkara ke bawah",
+ "ooui-outline-control-move-up": "Alihkan perkara ke atas",
+ "ooui-outline-control-remove": "Buang perkara",
+ "ooui-toolbar-more": "Selebihnya",
+ "ooui-toolgroup-expand": "Selengkapnya",
+ "ooui-toolgroup-collapse": "Secukupnya",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Batal",
+ "ooui-dialog-process-error": "Ada masalah",
+ "ooui-dialog-process-dismiss": "Singkir",
+ "ooui-dialog-process-retry": "Cuba lagi",
+ "ooui-dialog-process-continue": "Teruskan",
+ "ooui-selectfile-not-supported": "Pilihan fail tidak disokong",
+ "ooui-selectfile-placeholder": "Tiada fail yang dipilih"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/nan.json b/www/wiki/resources/lib/oojs-ui/i18n/nan.json
new file mode 100644
index 00000000..d94118d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/nan.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Luuva"
+ ]
+ },
+ "ooui-outline-control-move-down": "Hāng-bo̍k sóa ē-té",
+ "ooui-outline-control-move-up": "Hāng-bo̍k sóa téng-bīn",
+ "ooui-outline-control-remove": "Sóa cháu hāng-bo̍k",
+ "ooui-toolbar-more": "Khah chē",
+ "ooui-toolgroup-expand": "Khah chē",
+ "ooui-toolgroup-collapse": "Khah kiám",
+ "ooui-dialog-message-accept": "Liáu-kái",
+ "ooui-dialog-message-reject": "Chhú-siau",
+ "ooui-dialog-process-error": "Ū mi̍h bô hó-sè",
+ "ooui-dialog-process-dismiss": "Koaiⁿ tiāu",
+ "ooui-dialog-process-retry": "Koh chhì khòaⁿ-māi",
+ "ooui-dialog-process-continue": "Kè-sio̍k",
+ "ooui-selectfile-button-select": "Soán-tek 1-ê tóng-àn",
+ "ooui-selectfile-not-supported": "Só͘ soán ê tóng-àn bô siū chi-chhî",
+ "ooui-selectfile-placeholder": "Iáu-bē soán tóng-àn",
+ "ooui-selectfile-dragdrop-placeholder": "Kā tóng-àn tàn chia"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/nap.json b/www/wiki/resources/lib/oojs-ui/i18n/nap.json
new file mode 100644
index 00000000..b7e37b49
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/nap.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Chelin",
+ "Chrisportelli",
+ "PiRSquared17",
+ "C.R.",
+ "Candalua"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mòve abbascio",
+ "ooui-outline-control-move-up": "Mòve ncoppa",
+ "ooui-outline-control-remove": "Leva elemento",
+ "ooui-toolbar-more": "Atro",
+ "ooui-toolgroup-expand": "Cchiù",
+ "ooui-toolgroup-collapse": "Meno",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Scancella",
+ "ooui-dialog-process-error": "Cocchosa è ghiuta malamente",
+ "ooui-dialog-process-dismiss": "Passa 'a vacca",
+ "ooui-dialog-process-retry": "Prova n'ata vota",
+ "ooui-dialog-process-continue": "Continua",
+ "ooui-selectfile-button-select": "Sceglie nu file",
+ "ooui-selectfile-not-supported": "Filtro 'e selezione nun suppurtato",
+ "ooui-selectfile-placeholder": "Nun s'è scigliuto nisciuno file",
+ "ooui-selectfile-dragdrop-placeholder": "Lassa 'o file ccà"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/nb.json b/www/wiki/resources/lib/oojs-ui/i18n/nb.json
new file mode 100644
index 00000000..d3fad8dc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/nb.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Danmichaelo",
+ "Event",
+ "Jeblad",
+ "Laaknor",
+ "Njardarlogar",
+ "Jdforrester",
+ "Apple farmer"
+ ]
+ },
+ "ooui-outline-control-move-down": "Flytt ned",
+ "ooui-outline-control-move-up": "Flytt opp",
+ "ooui-outline-control-remove": "Fjern element",
+ "ooui-toolbar-more": "Mer",
+ "ooui-toolgroup-expand": "Mer",
+ "ooui-toolgroup-collapse": "Færre",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Avbryt",
+ "ooui-dialog-process-error": "Noe gikk galt",
+ "ooui-dialog-process-dismiss": "Lukk",
+ "ooui-dialog-process-retry": "Prøv igjen",
+ "ooui-dialog-process-continue": "Fortsett",
+ "ooui-selectfile-button-select": "Velg en fil",
+ "ooui-selectfile-not-supported": "Filvalg er ikke støttet",
+ "ooui-selectfile-placeholder": "Ingen fil er valgt",
+ "ooui-selectfile-dragdrop-placeholder": "Slipp fil her"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/nds-nl.json b/www/wiki/resources/lib/oojs-ui/i18n/nds-nl.json
new file mode 100644
index 00000000..d3db318b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/nds-nl.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "Servien"
+ ]
+ },
+ "ooui-outline-control-move-down": "Onderwarp ummeneer zetten",
+ "ooui-outline-control-move-up": "Onderwarp umhoge zetten",
+ "ooui-outline-control-remove": "Element vortdoon",
+ "ooui-toolbar-more": "Meer",
+ "ooui-toolgroup-expand": "Meer",
+ "ooui-toolgroup-collapse": "Minder",
+ "ooui-dialog-message-accept": "Okee",
+ "ooui-dialog-message-reject": "Aofbreken",
+ "ooui-dialog-process-error": "Der gung iets fout",
+ "ooui-dialog-process-dismiss": "Sluten",
+ "ooui-dialog-process-retry": "Opniej proberen",
+ "ooui-dialog-process-continue": "Deurgaon"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/nds.json b/www/wiki/resources/lib/oojs-ui/i18n/nds.json
new file mode 100644
index 00000000..9dee2f55
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/nds.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Zylbath",
+ "Joachim Mos"
+ ]
+ },
+ "ooui-outline-control-move-down": "Element na ünnen schuven",
+ "ooui-outline-control-move-up": "Element na baven schuven",
+ "ooui-toolbar-more": "Mehr",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Afbreken",
+ "ooui-dialog-process-error": "Do is wat in'e Büx goan",
+ "ooui-dialog-process-continue": "Wiedermaken",
+ "ooui-selectfile-button-select": "En Datei utwählen"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ne.json b/www/wiki/resources/lib/oojs-ui/i18n/ne.json
new file mode 100644
index 00000000..c7d28613
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ne.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "RajeshPandey",
+ "सरोज कुमार ढकाल",
+ "Ganesh Paudel",
+ "Nirajan pant"
+ ]
+ },
+ "ooui-outline-control-move-down": "वस्तुलाई तल सार्ने",
+ "ooui-outline-control-move-up": "वस्तुलाई माथि सार्ने",
+ "ooui-outline-control-remove": "वस्तुलाई हटाउने",
+ "ooui-toolbar-more": "थप",
+ "ooui-toolgroup-expand": "थप",
+ "ooui-toolgroup-collapse": "कम",
+ "ooui-item-remove": "हटाउनुहोस्",
+ "ooui-dialog-message-accept": "हुन्छ",
+ "ooui-dialog-message-reject": "रद्द गर्ने",
+ "ooui-dialog-process-dismiss": "खारेज गर्ने",
+ "ooui-dialog-process-retry": "पुन प्रयास गर्नुहोस",
+ "ooui-dialog-process-continue": "जारी राख्ने"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/nl.json b/www/wiki/resources/lib/oojs-ui/i18n/nl.json
new file mode 100644
index 00000000..694eb3c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/nl.json
@@ -0,0 +1,41 @@
+{
+ "@metadata": {
+ "authors": [
+ "Bluyten",
+ "Breghtje",
+ "Catrope",
+ "Flightmare",
+ "Hansmuller",
+ "Jdforrester",
+ "Keegan",
+ "Konovalov",
+ "RajeshPandey",
+ "Romaine",
+ "SPQRobin",
+ "Saruman",
+ "Siebrand",
+ "Southparkfan",
+ "सरोज कुमार ढकाल",
+ "Sjoerddebruin",
+ "Gloria sah",
+ "Mainframe98"
+ ]
+ },
+ "ooui-outline-control-move-down": "Item omlaag verplaatsen",
+ "ooui-outline-control-move-up": "Item omhoog verplaatsen",
+ "ooui-outline-control-remove": "Item verwijderen",
+ "ooui-toolbar-more": "Meer",
+ "ooui-toolgroup-expand": "Meer",
+ "ooui-toolgroup-collapse": "Minder",
+ "ooui-item-remove": "Verwijderen",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Annuleren",
+ "ooui-dialog-process-error": "Er is iets misgegaan",
+ "ooui-dialog-process-dismiss": "Sluiten",
+ "ooui-dialog-process-retry": "Opnieuw proberen",
+ "ooui-dialog-process-continue": "Doorgaan",
+ "ooui-selectfile-button-select": "Selecteer een bestand",
+ "ooui-selectfile-not-supported": "Selectie van een bestand wordt niet ondersteund",
+ "ooui-selectfile-placeholder": "Er is geen bestand geselecteerd",
+ "ooui-selectfile-dragdrop-placeholder": "Sleep hier een bestand heen"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/nn.json b/www/wiki/resources/lib/oojs-ui/i18n/nn.json
new file mode 100644
index 00000000..a32e7a41
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/nn.json
@@ -0,0 +1,20 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jeblad",
+ "Njardarlogar"
+ ]
+ },
+ "ooui-outline-control-move-down": "Flytt element ned",
+ "ooui-outline-control-move-up": "Flytt element opp",
+ "ooui-toolbar-more": "Meir",
+ "ooui-toolgroup-expand": "Meir",
+ "ooui-toolgroup-collapse": "Færre",
+ "ooui-dialog-message-reject": "Bryt av",
+ "ooui-dialog-process-error": "Noko gjekk gale",
+ "ooui-dialog-process-dismiss": "Lat att",
+ "ooui-dialog-process-continue": "Hald fram",
+ "ooui-selectfile-button-select": "Vel ei fil",
+ "ooui-selectfile-placeholder": "Inga fil er vald",
+ "ooui-selectfile-dragdrop-placeholder": "Slepp fil her"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/oc.json b/www/wiki/resources/lib/oojs-ui/i18n/oc.json
new file mode 100644
index 00000000..24a5966f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/oc.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cedric31",
+ "Gloria sah"
+ ]
+ },
+ "ooui-outline-control-move-down": "Far davalar l’element",
+ "ooui-outline-control-move-up": "Far montar l’element",
+ "ooui-outline-control-remove": "Suprimir l’element",
+ "ooui-toolbar-more": "Mai",
+ "ooui-toolgroup-expand": "Mai",
+ "ooui-toolgroup-collapse": "Mens",
+ "ooui-dialog-message-accept": "D'acòrdi",
+ "ooui-dialog-message-reject": "Anullar",
+ "ooui-dialog-process-error": "Quicòm a trucat",
+ "ooui-dialog-process-dismiss": "Regetar",
+ "ooui-dialog-process-retry": "Ensajatz tornamai",
+ "ooui-dialog-process-continue": "Contunhar",
+ "ooui-selectfile-button-select": "Seleccionar un fichièr",
+ "ooui-selectfile-not-supported": "Lo tipe de fichièr es pas compatible",
+ "ooui-selectfile-placeholder": "Cap de fichièr pas seleccionat",
+ "ooui-selectfile-dragdrop-placeholder": "Depausar lo fichièr aicí"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/olo.json b/www/wiki/resources/lib/oojs-ui/i18n/olo.json
new file mode 100644
index 00000000..1dc994eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/olo.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mashoi7"
+ ]
+ },
+ "ooui-outline-control-move-down": "Siirrä kohteh alah",
+ "ooui-outline-control-move-up": "Siirrä kohteh yläh",
+ "ooui-outline-control-remove": "Ota kohteh iäre",
+ "ooui-toolbar-more": "Enämbi",
+ "ooui-toolgroup-expand": "Enämbi",
+ "ooui-toolgroup-collapse": "Vähembi",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Hylgiä",
+ "ooui-dialog-process-error": "Mitah haireh rodih",
+ "ooui-dialog-process-dismiss": "Hylgiä",
+ "ooui-dialog-process-retry": "Opi vie",
+ "ooui-dialog-process-continue": "Jatka",
+ "ooui-selectfile-button-select": "Valliče failu",
+ "ooui-selectfile-not-supported": "Failan valličendua ei tuveta",
+ "ooui-selectfile-placeholder": "Failua ei ole vallittu",
+ "ooui-selectfile-dragdrop-placeholder": "Kirvota failu täh"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/om.json b/www/wiki/resources/lib/oojs-ui/i18n/om.json
new file mode 100644
index 00000000..31344be7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/om.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cedric31",
+ "Tumsaa"
+ ]
+ },
+ "ooui-outline-control-move-down": "Gad buusi",
+ "ooui-outline-control-move-up": "Ol baasi",
+ "ooui-outline-control-remove": "Balleessi",
+ "ooui-toolbar-more": "Dabalata",
+ "ooui-toolgroup-expand": "Dabalata",
+ "ooui-toolgroup-collapse": "Xiqqaa",
+ "ooui-dialog-message-accept": "Tole",
+ "ooui-dialog-message-reject": "Dhiisi",
+ "ooui-dialog-process-error": "Dogoggorri wayii ummameera",
+ "ooui-dialog-process-dismiss": "Didi",
+ "ooui-dialog-process-retry": "Itti deebi'ii yaali",
+ "ooui-dialog-process-continue": "Itti fufi",
+ "ooui-selectfile-button-select": "Faayilii filadhu",
+ "ooui-selectfile-not-supported": "Faayilii filachuun hin danda'amu.",
+ "ooui-selectfile-placeholder": "Faayiliin wayiiyyuu hin filatamne",
+ "ooui-selectfile-dragdrop-placeholder": "Faayilii as kaa'i"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/or.json b/www/wiki/resources/lib/oojs-ui/i18n/or.json
new file mode 100644
index 00000000..7d96dcb7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/or.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Odisha1",
+ "Psubhashish",
+ "ଶିତିକଣ୍ଠ ଦାଶ",
+ "Jnanaranjan Sahu"
+ ]
+ },
+ "ooui-outline-control-move-down": "ବସ୍ତୁଟିକୁ ତଳକୁ ଘୁଞ୍ଚାନ୍ତୁ",
+ "ooui-outline-control-move-up": "ବସ୍ତୁଟିକୁ ଉପରକୁ ଘୁଞ୍ଚାନ୍ତୁ",
+ "ooui-outline-control-remove": "ବସ୍ତୁଟିକୁ ଲିଭାନ୍ତୁ",
+ "ooui-toolbar-more": "ଅଧିକ",
+ "ooui-toolgroup-expand": "ଅଧିକ",
+ "ooui-toolgroup-collapse": "ଅଳ୍ପ",
+ "ooui-dialog-message-accept": "ହେଉ",
+ "ooui-dialog-message-reject": "ନାକଚ",
+ "ooui-dialog-process-error": "ଅସୁବିଧାଟିଏ ଘଟିଲା",
+ "ooui-dialog-process-dismiss": "ଖାରଜ",
+ "ooui-dialog-process-retry": "ଆଉ ଥରେ ଚେଷ୍ଟା କରନ୍ତୁ",
+ "ooui-dialog-process-continue": "ଚାଲୁରଖିବେ",
+ "ooui-selectfile-not-supported": "ଫାଇଲ ବାଛିବା ସୁବିଧା ନାହିଁ",
+ "ooui-selectfile-placeholder": "କୌଣସି ଫାଇଲ ବଛାଯାଇନାହିଁ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/pa.json b/www/wiki/resources/lib/oojs-ui/i18n/pa.json
new file mode 100644
index 00000000..a69d76f9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/pa.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amikeco",
+ "Babanwalia",
+ "Bouron",
+ "Nasir8891",
+ "Satdeep gill"
+ ]
+ },
+ "ooui-outline-control-move-down": "ਨੀਚੇ ਲੈਕੇ ਜਾਓ",
+ "ooui-outline-control-move-up": "ਉੱਤੇ ਲੈਕੇ ਜਾਓ",
+ "ooui-outline-control-remove": "ਆਈਟਮ ਹਟਾਓ",
+ "ooui-toolbar-more": "ਹੋਰ",
+ "ooui-toolgroup-expand": "ਹੋਰ",
+ "ooui-toolgroup-collapse": "ਥੋੜ੍ਹੇ",
+ "ooui-dialog-message-accept": "ਠੀਕ ਹੈ",
+ "ooui-dialog-message-reject": "ਰੱਦ ਕਰੋ",
+ "ooui-dialog-process-error": "ਕੁਝ ਗਲਤ ਹੋ ਗਿਆ",
+ "ooui-dialog-process-dismiss": "ਰੱਦ ਕਰੋ",
+ "ooui-dialog-process-retry": "ਦੁਬਾਰਾ ਕੋਸ਼ਿਸ਼ ਕਰੋ",
+ "ooui-dialog-process-continue": "ਜਾਰੀ ਰੱਖੋ",
+ "ooui-selectfile-button-select": "ਫ਼ਾਈਲ ਚੁਣੋ",
+ "ooui-selectfile-not-supported": "ਚੁਣੀ ਗਈ ਫ਼ਾਈਲ ਖੋਲੀ ਨਹੀਂ ਜਾ ਸਕਦੀ",
+ "ooui-selectfile-placeholder": "ਕੋਈ ਫ਼ਾਈਲ ਚੁਣੀ ਨਹੀਂ ਗਈ",
+ "ooui-selectfile-dragdrop-placeholder": "ਫ਼ਾਈਲ ਇੱਥੇ ਸਿੱਟੋ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/pfl.json b/www/wiki/resources/lib/oojs-ui/i18n/pfl.json
new file mode 100644
index 00000000..02d08426
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/pfl.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Manuae"
+ ]
+ },
+ "ooui-outline-control-move-down": "Bweeschs nunna",
+ "ooui-outline-control-move-up": "Bweeschs nuff",
+ "ooui-outline-control-remove": "Leschs",
+ "ooui-toolbar-more": "Mea",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Abbresche"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/pl.json b/www/wiki/resources/lib/oojs-ui/i18n/pl.json
new file mode 100644
index 00000000..eaf0b1a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/pl.json
@@ -0,0 +1,40 @@
+{
+ "@metadata": {
+ "authors": [
+ "Babanwalia",
+ "Chrumps",
+ "Matma Rex",
+ "Mikołka",
+ "Nasir8891",
+ "Odie2",
+ "Rzuwig",
+ "Tar Lócesilion",
+ "Ty221",
+ "WTM",
+ "Woytecr",
+ "Wpedzich",
+ "Jacenty359",
+ "Matik7",
+ "Gloria sah",
+ "Andrzej aa",
+ "The Polish"
+ ]
+ },
+ "ooui-outline-control-move-down": "Przesuń w dół",
+ "ooui-outline-control-move-up": "Przesuń w górę",
+ "ooui-outline-control-remove": "Usuń element",
+ "ooui-toolbar-more": "Więcej",
+ "ooui-toolgroup-expand": "Więcej",
+ "ooui-toolgroup-collapse": "Mniej",
+ "ooui-item-remove": "Usuń",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Anuluj",
+ "ooui-dialog-process-error": "Coś poszło nie tak",
+ "ooui-dialog-process-dismiss": "Powrót",
+ "ooui-dialog-process-retry": "Spróbuj ponownie",
+ "ooui-dialog-process-continue": "Kontynuuj",
+ "ooui-selectfile-button-select": "Wybierz plik",
+ "ooui-selectfile-not-supported": "Wybór pliku nie jest obsługiwany",
+ "ooui-selectfile-placeholder": "Nie wybrano pliku",
+ "ooui-selectfile-dragdrop-placeholder": "Upuść plik tutaj"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/pms.json b/www/wiki/resources/lib/oojs-ui/i18n/pms.json
new file mode 100644
index 00000000..c8b5bc7e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/pms.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Borichèt",
+ "Dragonòt",
+ "පසිඳු කාවින්ද"
+ ]
+ },
+ "ooui-outline-control-move-down": "Fé calé giù l'element",
+ "ooui-outline-control-move-up": "Fé monté l'element",
+ "ooui-outline-control-remove": "Gavé j'element",
+ "ooui-toolbar-more": "Ëd pi",
+ "ooui-toolgroup-expand": "Pi",
+ "ooui-toolgroup-collapse": "Men",
+ "ooui-dialog-message-accept": "Va bin",
+ "ooui-dialog-message-reject": "Scancelé",
+ "ooui-dialog-process-error": "Quaicòs a l'é andà mal",
+ "ooui-dialog-process-dismiss": "Stërmé",
+ "ooui-dialog-process-retry": "Preuva torna",
+ "ooui-dialog-process-continue": "Continua",
+ "ooui-selectfile-not-supported": "La selession d'archivi a l'é nen mantnùa",
+ "ooui-selectfile-placeholder": "Gnun archivi selessionà"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/pnb.json b/www/wiki/resources/lib/oojs-ui/i18n/pnb.json
new file mode 100644
index 00000000..386871c1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/pnb.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Saanvel",
+ "Abbas dhothar"
+ ]
+ },
+ "ooui-outline-control-move-down": "شیہ تھلے کرو",
+ "ooui-outline-control-move-up": "شیہ اتے کرو",
+ "ooui-outline-control-remove": "شیہ مٹاؤ",
+ "ooui-toolbar-more": "ہور",
+ "ooui-toolgroup-expand": "ہور",
+ "ooui-toolgroup-collapse": "گھٹ",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "مکاؤ",
+ "ooui-dialog-process-error": "کوئی رپھڑ پے گیا اے۔",
+ "ooui-dialog-process-dismiss": "مکاؤ",
+ "ooui-dialog-process-retry": "فیر کرو",
+ "ooui-dialog-process-continue": "چلاؤ",
+ "ooui-selectfile-button-select": "فائل چنو",
+ "ooui-selectfile-placeholder": "کوئی فائل نئی چنی ہوئی",
+ "ooui-selectfile-dragdrop-placeholder": "فائل ایتھے پاؤ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ps.json b/www/wiki/resources/lib/oojs-ui/i18n/ps.json
new file mode 100644
index 00000000..579740fb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ps.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ahmed-Najib-Biabani-Ibrahimkhel"
+ ]
+ },
+ "ooui-outline-control-move-down": "توکی ښکته راوړل",
+ "ooui-outline-control-move-up": "توکی پورته راوړل",
+ "ooui-outline-control-remove": "توکی غورځول",
+ "ooui-toolbar-more": "نور",
+ "ooui-toolgroup-expand": "نور",
+ "ooui-toolgroup-collapse": "لږ تر لږ",
+ "ooui-dialog-message-accept": "ښه",
+ "ooui-dialog-message-reject": "ناگارل",
+ "ooui-dialog-process-error": "يوه ستونزه رامنځ ته شوه",
+ "ooui-dialog-process-dismiss": "تړل",
+ "ooui-dialog-process-retry": "بيا هڅه",
+ "ooui-dialog-process-continue": "پرله پورې",
+ "ooui-selectfile-button-select": "يوه دوتنه وټاکئ",
+ "ooui-selectfile-not-supported": "د دوتنې د ټاکنې ملاتړ نه دی شوی",
+ "ooui-selectfile-placeholder": "کومه دوتنه نه ده ټاکل شوې",
+ "ooui-selectfile-dragdrop-placeholder": "دوتنه مو دلته خوشې کړئ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/pt-br.json b/www/wiki/resources/lib/oojs-ui/i18n/pt-br.json
new file mode 100644
index 00000000..41ce674e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/pt-br.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cainamarques",
+ "Dianakc",
+ "Fúlvio",
+ "Helder.wiki",
+ "HenriqueCrang",
+ "Jaideraf",
+ "Luckas",
+ "OTAVIO1981",
+ 555,
+ "TheEduGobi",
+ "TheGabrielZaum",
+ "Felipe L. Ewald"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mover item para baixo",
+ "ooui-outline-control-move-up": "Mover item para cima",
+ "ooui-outline-control-remove": "Remover item",
+ "ooui-toolbar-more": "Mais",
+ "ooui-toolgroup-expand": "Mais",
+ "ooui-toolgroup-collapse": "Menos",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancelar",
+ "ooui-dialog-process-error": "Algo deu errado",
+ "ooui-dialog-process-dismiss": "Dispensar",
+ "ooui-dialog-process-retry": "Tente novamente",
+ "ooui-dialog-process-continue": "Continuar",
+ "ooui-selectfile-button-select": "Selecionar um arquivo",
+ "ooui-selectfile-not-supported": "O selecionamento de arquivos não é suportado",
+ "ooui-selectfile-placeholder": "Nenhum arquivo selecionado",
+ "ooui-selectfile-dragdrop-placeholder": "Arraste o arquivo para cá"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/pt.json b/www/wiki/resources/lib/oojs-ui/i18n/pt.json
new file mode 100644
index 00000000..246d9c2c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/pt.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cainamarques",
+ "Fúlvio",
+ "GoEThe",
+ "Hamilton Abreu",
+ "Helder.wiki",
+ "Jaideraf",
+ "Jdforrester",
+ "Luckas",
+ "Vitorvicentevalente",
+ "SandroHc",
+ "Jkb8"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mover item para baixo",
+ "ooui-outline-control-move-up": "Mover item para cima",
+ "ooui-outline-control-remove": "Remover elemento",
+ "ooui-toolbar-more": "Mais",
+ "ooui-toolgroup-expand": "Mais",
+ "ooui-toolgroup-collapse": "Menos",
+ "ooui-item-remove": "Remover",
+ "ooui-dialog-message-accept": "Aceitar",
+ "ooui-dialog-message-reject": "Cancelar",
+ "ooui-dialog-process-error": "Algo correu mal",
+ "ooui-dialog-process-dismiss": "Ignorar",
+ "ooui-dialog-process-retry": "Tentar novamente",
+ "ooui-dialog-process-continue": "Continuar",
+ "ooui-selectfile-button-select": "Selecionar ficheiro",
+ "ooui-selectfile-not-supported": "A seleção de ficheiros não é suportada",
+ "ooui-selectfile-placeholder": "Nenhum ficheiro selecionado",
+ "ooui-selectfile-dragdrop-placeholder": "Soltar ficheiro aqui"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/qqq.json b/www/wiki/resources/lib/oojs-ui/i18n/qqq.json
new file mode 100644
index 00000000..8ca3afc7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/qqq.json
@@ -0,0 +1,41 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "Beta16",
+ "Erik Moeller",
+ "Jdforrester",
+ "Lloffiwr",
+ "Mooeypoo",
+ "Mormegil",
+ "Nike",
+ "PoLuX124",
+ "Purodha",
+ "Raymond",
+ "Sagan",
+ "Sayak Sarkar",
+ "Shirayuki",
+ "Siebrand",
+ "Trevor Parscal",
+ "Liuxinyu970226",
+ "Robby"
+ ]
+ },
+ "ooui-outline-control-move-down": "Tool tip for a button that moves items in a list down one place",
+ "ooui-outline-control-move-up": "Tool tip for a button that moves items in a list up one place",
+ "ooui-outline-control-remove": "Tool tip for a button that removes items from a list.\n{{Identical|Remove item}}",
+ "ooui-toolbar-more": "Label for the toolbar group that contains a list of all other available tools.\n{{Identical|More}}",
+ "ooui-toolgroup-expand": "Label for the fake tool that expands the full list of tools in a toolbar group.\n\nSee also:\n* {{msg-mw|Ooui-toolgroup-collapse}}\n{{Identical|More}}",
+ "ooui-toolgroup-collapse": "Label for the fake tool that collapses the full list of tools in a toolbar group.\n\nSee also:\n* {{msg-mw|Ooui-toolgroup-expand}}\n{{Identical|Fewer}}",
+ "ooui-item-remove": "Text for the action of removing an item\n{{Identical|Remove}}",
+ "ooui-dialog-message-accept": "Default label for the accept button of a message dialog\n{{Identical|OK}}",
+ "ooui-dialog-message-reject": "Default label for the reject button of a message dialog\n{{Identical|Cancel}}",
+ "ooui-dialog-process-error": "Title for process dialog error description",
+ "ooui-dialog-process-dismiss": "Label for process dialog dismiss error button, visible when describing errors\n{{Identical|Dismiss}}",
+ "ooui-dialog-process-retry": "Label for process dialog retry action button, visible when describing recoverable errors\n{{Identical|Try again}}",
+ "ooui-dialog-process-continue": "Label for process dialog retry action button, visible when describing only warnings\n{{Identical|Continue}}",
+ "ooui-selectfile-button-select": "Label for the file selection widget's select file button",
+ "ooui-selectfile-not-supported": "Label for the file selection widget if file selection is not supported",
+ "ooui-selectfile-placeholder": "Label for the file selection widget when no file is currently selected",
+ "ooui-selectfile-dragdrop-placeholder": "Label for the file selection widget's drop target"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/qu.json b/www/wiki/resources/lib/oojs-ui/i18n/qu.json
new file mode 100644
index 00000000..cb0b2c33
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/qu.json
@@ -0,0 +1,12 @@
+{
+ "@metadata": {
+ "authors": [
+ "AlimanRuna",
+ "Jduranboger"
+ ]
+ },
+ "ooui-outline-control-move-down": "Qallawata uraykuchiy",
+ "ooui-outline-control-move-up": "Qallawata huqariy",
+ "ooui-outline-control-remove": "P'anqa sutikunata qichuy",
+ "ooui-toolbar-more": "Aswan"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ro.json b/www/wiki/resources/lib/oojs-ui/i18n/ro.json
new file mode 100644
index 00000000..69daa180
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ro.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "AlimanRuna",
+ "Firilacroco",
+ "Minisarm",
+ "Stelistcristi",
+ "Gloria sah"
+ ]
+ },
+ "ooui-outline-control-move-down": "Mută elementul mai jos",
+ "ooui-outline-control-move-up": "Mută elementul mai sus",
+ "ooui-outline-control-remove": "Elimină elementul",
+ "ooui-toolbar-more": "Mai mult",
+ "ooui-toolgroup-expand": "Mai multe",
+ "ooui-toolgroup-collapse": "Mai puține",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Revocare",
+ "ooui-dialog-process-error": "Ceva nu a funcționat",
+ "ooui-dialog-process-dismiss": "Renunțare",
+ "ooui-dialog-process-retry": "Reîncearcă",
+ "ooui-dialog-process-continue": "Continuă",
+ "ooui-selectfile-button-select": "Alege un fișier",
+ "ooui-selectfile-not-supported": "Selecția de fișiere nu este acceptată",
+ "ooui-selectfile-placeholder": "Niciun fișier selectat",
+ "ooui-selectfile-dragdrop-placeholder": "Trageți fișierul aici"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/roa-tara.json b/www/wiki/resources/lib/oojs-ui/i18n/roa-tara.json
new file mode 100644
index 00000000..73a5a6c1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/roa-tara.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Joetaras"
+ ]
+ },
+ "ooui-outline-control-move-down": "Spuèste 'a vôsce sotte",
+ "ooui-outline-control-move-up": "Spuèste 'a vôsce sus",
+ "ooui-outline-control-remove": "Live 'a vôsce",
+ "ooui-toolbar-more": "De cchiù",
+ "ooui-toolgroup-expand": "De cchiù",
+ "ooui-toolgroup-collapse": "De mene",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Annulle",
+ "ooui-dialog-process-error": "Quacche cose ha sciute stuèrte",
+ "ooui-dialog-process-dismiss": "Scitte",
+ "ooui-dialog-process-retry": "Pruève arrete",
+ "ooui-dialog-process-continue": "Condinue",
+ "ooui-selectfile-button-select": "Scacchie 'nu file",
+ "ooui-selectfile-not-supported": "'U scacchiamende d'u file non g'è supportate",
+ "ooui-selectfile-placeholder": "Nisciune file scacchiate",
+ "ooui-selectfile-dragdrop-placeholder": "Scitte 'u file aqquà"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ru.json b/www/wiki/resources/lib/oojs-ui/i18n/ru.json
new file mode 100644
index 00000000..6b22fd88
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ru.json
@@ -0,0 +1,41 @@
+{
+ "@metadata": {
+ "authors": [
+ "Amire80",
+ "DR",
+ "Eugrus",
+ "Iluvatar",
+ "KPu3uC B Poccuu",
+ "Kalan",
+ "MaxBioHazard",
+ "NBS",
+ "Niklem",
+ "Okras",
+ "Ole Yves",
+ "Putnik",
+ "Sunpriat",
+ "Yury Katkov",
+ "Умар",
+ "Камалист",
+ "Meshkov.a",
+ "Mailman"
+ ]
+ },
+ "ooui-outline-control-move-down": "Переместить элемент вниз",
+ "ooui-outline-control-move-up": "Переместить элемент вверх",
+ "ooui-outline-control-remove": "Удалить пункт",
+ "ooui-toolbar-more": "Ещё",
+ "ooui-toolgroup-expand": "Больше",
+ "ooui-toolgroup-collapse": "Меньше",
+ "ooui-item-remove": "Удалить",
+ "ooui-dialog-message-accept": "ОК",
+ "ooui-dialog-message-reject": "Отмена",
+ "ooui-dialog-process-error": "Что-то пошло не так",
+ "ooui-dialog-process-dismiss": "Закрыть",
+ "ooui-dialog-process-retry": "Попробовать ещё раз",
+ "ooui-dialog-process-continue": "Продолжить",
+ "ooui-selectfile-button-select": "Выберите файл",
+ "ooui-selectfile-not-supported": "Выбор файла не поддерживается",
+ "ooui-selectfile-placeholder": "Не выбран файл",
+ "ooui-selectfile-dragdrop-placeholder": "Перетащите файл сюда"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sa.json b/www/wiki/resources/lib/oojs-ui/i18n/sa.json
new file mode 100644
index 00000000..49f038c7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sa.json
@@ -0,0 +1,14 @@
+{
+ "@metadata": {
+ "authors": [
+ "NehalDaveND"
+ ]
+ },
+ "ooui-outline-control-remove": "वस्तु निष्कास्यताम्",
+ "ooui-toolbar-more": "अधिकम्",
+ "ooui-toolgroup-expand": "अधिकम्",
+ "ooui-dialog-message-accept": "अस्तु",
+ "ooui-dialog-message-reject": "निरस्यताम्",
+ "ooui-dialog-process-retry": "पुनः चेष्ट्यताम्",
+ "ooui-dialog-process-continue": "निरन्तरम्"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sah.json b/www/wiki/resources/lib/oojs-ui/i18n/sah.json
new file mode 100644
index 00000000..1e4bb555
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sah.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gazeb",
+ "HalanTul"
+ ]
+ },
+ "ooui-outline-control-move-down": "Аллара түһэрэн биэр",
+ "ooui-outline-control-move-up": "Үөһэ таһааран биэр",
+ "ooui-outline-control-remove": "Сот",
+ "ooui-toolbar-more": "Эбии",
+ "ooui-toolgroup-expand": "Эбии",
+ "ooui-toolgroup-collapse": "Кыччат",
+ "ooui-dialog-message-accept": "Сөп",
+ "ooui-dialog-message-reject": "Салҕаама",
+ "ooui-dialog-process-error": "Туга эрэ сатаммата",
+ "ooui-dialog-process-dismiss": "Сап",
+ "ooui-dialog-process-retry": "Хатылаан көр",
+ "ooui-dialog-process-continue": "Салгыы",
+ "ooui-selectfile-button-select": "Билэни тал",
+ "ooui-selectfile-not-supported": "Билэни талыы өйөммөт",
+ "ooui-selectfile-placeholder": "Биир да билэ талыллыбатах",
+ "ooui-selectfile-dragdrop-placeholder": "Билэни манна сыҕарыт"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/scn.json b/www/wiki/resources/lib/oojs-ui/i18n/scn.json
new file mode 100644
index 00000000..22a212f9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/scn.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "Gazeb",
+ "Gmelfi",
+ "HalanTul",
+ "Gloria sah"
+ ]
+ },
+ "ooui-outline-control-move-down": "Sposta di sutta",
+ "ooui-outline-control-move-up": "Sposta di supra",
+ "ooui-toolbar-more": "Àutri cosi"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sco.json b/www/wiki/resources/lib/oojs-ui/i18n/sco.json
new file mode 100644
index 00000000..794d71f7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sco.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "John Reid",
+ "Foxj"
+ ]
+ },
+ "ooui-outline-control-move-down": "Muiv eetem doon",
+ "ooui-outline-control-move-up": "Muiv eetem up",
+ "ooui-outline-control-remove": "Remuiv eetem",
+ "ooui-toolbar-more": "Mair",
+ "ooui-toolgroup-expand": "Mair",
+ "ooui-toolgroup-collapse": "Less",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Cancel",
+ "ooui-dialog-process-error": "Sommit went wrang",
+ "ooui-dialog-process-dismiss": "Close",
+ "ooui-dialog-process-retry": "Hae aniter gae",
+ "ooui-dialog-process-continue": "Conteena",
+ "ooui-selectfile-not-supported": "Cannae pick ony files",
+ "ooui-selectfile-placeholder": "Nae file selectit"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sd.json b/www/wiki/resources/lib/oojs-ui/i18n/sd.json
new file mode 100644
index 00000000..dc14339c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sd.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mehtab ahmed"
+ ]
+ },
+ "ooui-outline-control-move-down": "شيءِ کي هيٺ چوريو",
+ "ooui-outline-control-move-up": "شيءِ کي مٿي چوريو",
+ "ooui-outline-control-remove": "شيءِ هٽايو",
+ "ooui-toolbar-more": "وڌيڪ",
+ "ooui-toolgroup-expand": "وڌيڪ",
+ "ooui-toolgroup-collapse": "گھٽ تر",
+ "ooui-dialog-message-accept": "ٺيڪ",
+ "ooui-dialog-message-reject": "رد",
+ "ooui-dialog-process-error": "ڪا غلطي ٿي",
+ "ooui-dialog-process-dismiss": "برخاست ڪريو",
+ "ooui-dialog-process-retry": "ٻيهر ڪوشش ڪريو",
+ "ooui-dialog-process-continue": "جاري رکو",
+ "ooui-selectfile-button-select": "ڪو فائيل چونڊِو",
+ "ooui-selectfile-not-supported": "فائيل جي چونڊ سپورٽ نٿي ڪئي وڃي",
+ "ooui-selectfile-placeholder": "ڪوبه فائيل چونڊيو نه ويو آهي",
+ "ooui-selectfile-dragdrop-placeholder": "فائيل کي هتي ڪيرايو"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sh.json b/www/wiki/resources/lib/oojs-ui/i18n/sh.json
new file mode 100644
index 00000000..532ba3f7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sh.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "OC Ripper",
+ "Sf"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pomakni stavku dolje",
+ "ooui-outline-control-move-up": "Premjesti stavku gore",
+ "ooui-outline-control-remove": "Ukloni stavku",
+ "ooui-toolbar-more": "Više",
+ "ooui-toolgroup-expand": "Više",
+ "ooui-toolgroup-collapse": "Manje",
+ "ooui-dialog-message-accept": "U redu",
+ "ooui-dialog-message-reject": "Otkaži",
+ "ooui-dialog-process-error": "Nešto je pošlo naopako",
+ "ooui-dialog-process-dismiss": "Odbaci",
+ "ooui-dialog-process-retry": "Pokušajte ponovo",
+ "ooui-dialog-process-continue": "Nastavi",
+ "ooui-selectfile-button-select": "Izaberi datoteku",
+ "ooui-selectfile-not-supported": "Izbor datoteke nije podržan",
+ "ooui-selectfile-placeholder": "Nijedna datoteka nije odabrana",
+ "ooui-selectfile-dragdrop-placeholder": "Prevuci datoteku ovdje"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/shn.json b/www/wiki/resources/lib/oojs-ui/i18n/shn.json
new file mode 100644
index 00000000..a93e616a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/shn.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Saimawnkham"
+ ]
+ },
+ "ooui-outline-control-move-down": "ၶၢႆႉလူင်းၽၢႆႇတႂ်ႈ",
+ "ooui-outline-control-move-up": "ၶၢႆႉၶိုၼ်ႈၽၢႆႇၼိူဝ်",
+ "ooui-outline-control-remove": "ထွၼ်ပႅတ်ႈ ဢၼ်ၶဝ်ႈပႃး",
+ "ooui-toolbar-more": "ၼမ်ႉလိူဝ်",
+ "ooui-toolgroup-expand": "ၼမ်လိူဝ်",
+ "ooui-toolgroup-collapse": "ဢေႇလိူဝ်",
+ "ooui-dialog-message-accept": "ဢူဝ်ႇၶေႇ",
+ "ooui-dialog-message-reject": "ဢမ်ႇႁဵတ်း",
+ "ooui-dialog-process-error": "သေဢၼ်ဢၼ်ၽိတ်းပိူင်ႈဝႆႉ",
+ "ooui-dialog-process-dismiss": "လူတ်းၵၢၼ်",
+ "ooui-dialog-process-retry": "ၶတ်းၸႂ်ထႅင်ႈ",
+ "ooui-dialog-process-continue": "သိုပ်ႇၼႃႈ",
+ "ooui-selectfile-button-select": "လိူၵ်ႈၾၢႆႇ",
+ "ooui-selectfile-not-supported": "လွင်ႈလိူၵ်ႈၽၢႆႇၼႆႉ ဢမ်ႇၵမ်ႉထႅမ်ဝႆႉပၼ်",
+ "ooui-selectfile-placeholder": "ဢမ်ႇလႆႈလိူၵ်ႈ ၾၢႆႇသင်ဝႆႉ",
+ "ooui-selectfile-dragdrop-placeholder": "ဢဝ်ၾၢႆႇ သႂ်ႇတီႈၼႆႉ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/si.json b/www/wiki/resources/lib/oojs-ui/i18n/si.json
new file mode 100644
index 00000000..5988773b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/si.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Singhalawap",
+ "පසිඳු කාවින්ද",
+ "ශ්වෙත"
+ ]
+ },
+ "ooui-outline-control-move-down": "අයිතමය පහලටදමන්න",
+ "ooui-outline-control-move-up": "අයිතමය ඉහලටදමන්න"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sk.json b/www/wiki/resources/lib/oojs-ui/i18n/sk.json
new file mode 100644
index 00000000..fa658889
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sk.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Mimarik",
+ "Teslaton",
+ "Kusavica"
+ ]
+ },
+ "ooui-outline-control-move-down": "Posunúť položku nadol",
+ "ooui-outline-control-move-up": "Posunúť položku nahor",
+ "ooui-outline-control-remove": "Odstrániť položku",
+ "ooui-toolbar-more": "Viac",
+ "ooui-toolgroup-expand": "Viac",
+ "ooui-toolgroup-collapse": "Menej",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Zrušiť",
+ "ooui-dialog-process-error": "Niečo sa pokazilo",
+ "ooui-dialog-process-dismiss": "Zrušiť",
+ "ooui-dialog-process-retry": "Skúsiť znova",
+ "ooui-dialog-process-continue": "Pokračovať",
+ "ooui-selectfile-placeholder": "Nie je vybraný žiadny súbor"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/skr-arab.json b/www/wiki/resources/lib/oojs-ui/i18n/skr-arab.json
new file mode 100644
index 00000000..6be23541
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/skr-arab.json
@@ -0,0 +1,18 @@
+{
+ "@metadata": {
+ "authors": [
+ "Saraiki"
+ ]
+ },
+ "ooui-toolbar-more": "ٻئے",
+ "ooui-toolgroup-expand": "ٻئے",
+ "ooui-toolgroup-collapse": "گھٹ",
+ "ooui-dialog-message-accept": "ٹھیک ہے",
+ "ooui-dialog-message-reject": "منسوخ",
+ "ooui-dialog-process-error": "کجھ خراب تھی ڳئے",
+ "ooui-dialog-process-dismiss": "مکاؤ",
+ "ooui-dialog-process-retry": "ولدا کوشش کرو",
+ "ooui-dialog-process-continue": "جاری رکھو",
+ "ooui-selectfile-button-select": "فائل چݨو",
+ "ooui-selectfile-placeholder": "کوئی فائل کائنی چُݨی"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sl.json b/www/wiki/resources/lib/oojs-ui/i18n/sl.json
new file mode 100644
index 00000000..1b481a3d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sl.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Dbc334",
+ "Eleassar",
+ "Pinky sl",
+ "Yerpo"
+ ]
+ },
+ "ooui-outline-control-move-down": "Prestavi predmet nižje",
+ "ooui-outline-control-move-up": "Prestavi predmet višje",
+ "ooui-outline-control-remove": "Odstrani vnos",
+ "ooui-toolbar-more": "Več",
+ "ooui-toolgroup-expand": "Več",
+ "ooui-toolgroup-collapse": "Manj",
+ "ooui-dialog-message-accept": "V redu",
+ "ooui-dialog-message-reject": "Prekliči",
+ "ooui-dialog-process-error": "Nekaj je šlo narobe",
+ "ooui-dialog-process-dismiss": "Skrij",
+ "ooui-dialog-process-retry": "Poskusi znova",
+ "ooui-dialog-process-continue": "Nadaljuj",
+ "ooui-selectfile-button-select": "Izberite datoteko",
+ "ooui-selectfile-not-supported": "Izbira datoteke ni podprta",
+ "ooui-selectfile-placeholder": "Nobena datoteka ni izbrana",
+ "ooui-selectfile-dragdrop-placeholder": "Tukaj spustite datoteko"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sq.json b/www/wiki/resources/lib/oojs-ui/i18n/sq.json
new file mode 100644
index 00000000..679f1a6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sq.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Euriditi",
+ "Kushtrim",
+ "Elioqoshi",
+ "GretaDoci",
+ "Gertakapllani",
+ "Techlik",
+ "Liridon"
+ ]
+ },
+ "ooui-outline-control-move-down": "Zhvendose artikullin më poshtë",
+ "ooui-outline-control-move-up": "Zhvendose artikullin më lart",
+ "ooui-outline-control-remove": "Hiq artikullin",
+ "ooui-toolbar-more": "Më tepër...",
+ "ooui-toolgroup-expand": "Më tepër...",
+ "ooui-toolgroup-collapse": "Më pak",
+ "ooui-dialog-message-accept": "Në rregull",
+ "ooui-dialog-message-reject": "Anullo",
+ "ooui-dialog-process-error": "Diçka shkoi keq",
+ "ooui-dialog-process-dismiss": "Largoje",
+ "ooui-dialog-process-retry": "Provo përsëri",
+ "ooui-dialog-process-continue": "Vazhdo",
+ "ooui-selectfile-button-select": "Përzgjidhni një skedë",
+ "ooui-selectfile-not-supported": "Skedari i përzgjedhur nuk përkrahet",
+ "ooui-selectfile-placeholder": "Nuk është zgjedhur asnjë skedar",
+ "ooui-selectfile-dragdrop-placeholder": "Vendose skedën këtu"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sr-ec.json b/www/wiki/resources/lib/oojs-ui/i18n/sr-ec.json
new file mode 100644
index 00000000..6d675da9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sr-ec.json
@@ -0,0 +1,29 @@
+{
+ "@metadata": {
+ "authors": [
+ "Milicevic01",
+ "Nikola Smolenski",
+ "Милан Јелисавчић",
+ "Zoranzoki21",
+ "Obsuser",
+ "Prevodim"
+ ]
+ },
+ "ooui-outline-control-move-down": "Премести ставку надоле",
+ "ooui-outline-control-move-up": "Премести ставку нагоре",
+ "ooui-outline-control-remove": "Уклони ставку",
+ "ooui-toolbar-more": "Више",
+ "ooui-toolgroup-expand": "Више",
+ "ooui-toolgroup-collapse": "Мање",
+ "ooui-item-remove": "Уклони",
+ "ooui-dialog-message-accept": "У реду",
+ "ooui-dialog-message-reject": "Откажи",
+ "ooui-dialog-process-error": "Нешто је пошло наопако",
+ "ooui-dialog-process-dismiss": "Одбаци",
+ "ooui-dialog-process-retry": "Покушај поново",
+ "ooui-dialog-process-continue": "Настави",
+ "ooui-selectfile-button-select": "Изабери датотеку",
+ "ooui-selectfile-not-supported": "Избор датотеке није подржан",
+ "ooui-selectfile-placeholder": "Није изабрана ниједна датотека",
+ "ooui-selectfile-dragdrop-placeholder": "Додајте датотеку овде"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sr-el.json b/www/wiki/resources/lib/oojs-ui/i18n/sr-el.json
new file mode 100644
index 00000000..bdf6a64a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sr-el.json
@@ -0,0 +1,21 @@
+{
+ "@metadata": {
+ "authors": [
+ "Milicevic01"
+ ]
+ },
+ "ooui-outline-control-move-down": "Premesti stavku na dole",
+ "ooui-outline-control-move-up": "Premesti stavku na gore",
+ "ooui-outline-control-remove": "Ukloni stavku",
+ "ooui-toolbar-more": "Više",
+ "ooui-toolgroup-expand": "Više",
+ "ooui-toolgroup-collapse": "Manje",
+ "ooui-dialog-message-accept": "U redu",
+ "ooui-dialog-message-reject": "Otkaži",
+ "ooui-dialog-process-error": "Nešto je pošlo naopako",
+ "ooui-dialog-process-dismiss": "Odbaci",
+ "ooui-dialog-process-retry": "Pokušaj ponovo",
+ "ooui-dialog-process-continue": "Nastavi",
+ "ooui-selectfile-button-select": "Izaberi datoteku",
+ "ooui-selectfile-placeholder": "Nije izabrana nijedna datoteka"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/su.json b/www/wiki/resources/lib/oojs-ui/i18n/su.json
new file mode 100644
index 00000000..2824d5bd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/su.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Kandar",
+ "Uchup19"
+ ]
+ },
+ "ooui-outline-control-move-down": "Pindahkeun ka handap",
+ "ooui-outline-control-move-up": "Pindahkeun ka luhur",
+ "ooui-outline-control-remove": "Hapus",
+ "ooui-toolbar-more": "Lobaan",
+ "ooui-toolgroup-expand": "Lobaan",
+ "ooui-toolgroup-collapse": "Saeutikan",
+ "ooui-item-remove": "Pupus",
+ "ooui-dialog-message-accept": "Heug",
+ "ooui-dialog-message-reject": "Bolay",
+ "ooui-dialog-process-error": "Aya nu teu bener",
+ "ooui-dialog-process-dismiss": "Tutup",
+ "ooui-dialog-process-retry": "Cobaan deui",
+ "ooui-dialog-process-continue": "Teruskeun",
+ "ooui-selectfile-button-select": "Pilih berkas",
+ "ooui-selectfile-not-supported": "Pamilihan berkas teu dirojong",
+ "ooui-selectfile-placeholder": "Taya berkas anu dipilih",
+ "ooui-selectfile-dragdrop-placeholder": "Leupaskeun berkas di dieu"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sv.json b/www/wiki/resources/lib/oojs-ui/i18n/sv.json
new file mode 100644
index 00000000..3ffbc489
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sv.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ainali",
+ "Haxpett",
+ "Jopparn",
+ "Knuckles",
+ "Magol",
+ "Milicevic01",
+ "Per",
+ "Sendelbach",
+ "Skalman",
+ "WikiPhoenix",
+ "Lokal Profil",
+ "Warrakkk"
+ ]
+ },
+ "ooui-outline-control-move-down": "Flytta ned objekt",
+ "ooui-outline-control-move-up": "Flytta upp objekt",
+ "ooui-outline-control-remove": "Ta bort objekt",
+ "ooui-toolbar-more": "Mer",
+ "ooui-toolgroup-expand": "Fler",
+ "ooui-toolgroup-collapse": "Färre",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Avbryt",
+ "ooui-dialog-process-error": "Något gick fel",
+ "ooui-dialog-process-dismiss": "Stäng",
+ "ooui-dialog-process-retry": "Försök igen",
+ "ooui-dialog-process-continue": "Fortsätt",
+ "ooui-selectfile-button-select": "Välj en fil",
+ "ooui-selectfile-not-supported": "Filval stöds inte",
+ "ooui-selectfile-placeholder": "Ingen fil är vald",
+ "ooui-selectfile-dragdrop-placeholder": "Släpp filen här"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/sw.json b/www/wiki/resources/lib/oojs-ui/i18n/sw.json
new file mode 100644
index 00000000..598acbcd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/sw.json
@@ -0,0 +1,16 @@
+{
+ "@metadata": {
+ "authors": [
+ "Lloffiwr",
+ "Muddyb Blast Producer",
+ "Muddyb"
+ ]
+ },
+ "ooui-outline-control-move-down": "Sogeza kipengee chini",
+ "ooui-outline-control-move-up": "Sogeza kipengee juu",
+ "ooui-outline-control-remove": "Toa kitu",
+ "ooui-toolbar-more": "Zaidi",
+ "ooui-dialog-message-accept": "Sawa",
+ "ooui-dialog-message-reject": "Batilisha",
+ "ooui-dialog-process-retry": "Jaribu tena"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ta.json b/www/wiki/resources/lib/oojs-ui/i18n/ta.json
new file mode 100644
index 00000000..6e7b2494
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ta.json
@@ -0,0 +1,26 @@
+{
+ "@metadata": {
+ "authors": [
+ "Jayarathina",
+ "Sank",
+ "Shanmugamp7",
+ "மதனாஹரன்",
+ "ElangoRamanujam",
+ "Info-farmer"
+ ]
+ },
+ "ooui-outline-control-move-down": "உருப்படியை கீழிடு",
+ "ooui-outline-control-move-up": "உருப்படியை மேலிடு",
+ "ooui-outline-control-remove": "உருப்படியை நீக்கு",
+ "ooui-toolbar-more": "மேலும்",
+ "ooui-toolgroup-expand": "மேலும்",
+ "ooui-toolgroup-collapse": "குறைவாக",
+ "ooui-dialog-message-accept": "சரி",
+ "ooui-dialog-message-reject": "கைவிடுக",
+ "ooui-dialog-process-error": "ஏதோ தவறாகியுள்ளது",
+ "ooui-dialog-process-dismiss": "அகற்று",
+ "ooui-dialog-process-retry": "மீண்டும் முயல்க",
+ "ooui-dialog-process-continue": "தொடரவும்",
+ "ooui-selectfile-not-supported": "கோப்புத்தேர்வு ஆதரவாக இல்லை",
+ "ooui-selectfile-placeholder": "எக்கோப்பும் தெரிவாகவில்லை"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/te.json b/www/wiki/resources/lib/oojs-ui/i18n/te.json
new file mode 100644
index 00000000..e4b50d84
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/te.json
@@ -0,0 +1,30 @@
+{
+ "@metadata": {
+ "authors": [
+ "Arjunaraoc",
+ "Jayarathina",
+ "Sank",
+ "Shanmugamp7",
+ "Veeven",
+ "Visdaviva",
+ "மதனாஹரன்",
+ "రహ్మానుద్దీన్"
+ ]
+ },
+ "ooui-outline-control-move-down": "అంశాన్ని కిందికి కదుపు",
+ "ooui-outline-control-move-up": "అంశాన్ని పైకి కదుపు",
+ "ooui-outline-control-remove": "అంశాన్ని తీసివేయి",
+ "ooui-toolbar-more": "మరిన్ని",
+ "ooui-toolgroup-expand": "మరిన్ని",
+ "ooui-toolgroup-collapse": "కొన్ని",
+ "ooui-dialog-message-accept": "సరే",
+ "ooui-dialog-message-reject": "రద్దుచేయి",
+ "ooui-dialog-process-error": "ఏదో పొరపాటు జరిగింది",
+ "ooui-dialog-process-dismiss": "రద్దుచేయి",
+ "ooui-dialog-process-retry": "మళ్ళీ ప్రయత్నించు",
+ "ooui-dialog-process-continue": "కొనసాగించు",
+ "ooui-selectfile-button-select": "దస్త్రాన్ని ఎంచుకో",
+ "ooui-selectfile-not-supported": "దస్త్రపు ఎంపిక అందుబాటులో లేదు",
+ "ooui-selectfile-placeholder": "ఏ దస్త్రము ఎంపిక చేయలేదు",
+ "ooui-selectfile-dragdrop-placeholder": "దస్త్రాన్ని ఇక్కడ పడేయండి"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/tg-cyrl.json b/www/wiki/resources/lib/oojs-ui/i18n/tg-cyrl.json
new file mode 100644
index 00000000..1429bedd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/tg-cyrl.json
@@ -0,0 +1,11 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ibrahim"
+ ]
+ },
+ "ooui-outline-control-move-down": "Ҳаракати мавод ба поён",
+ "ooui-outline-control-move-up": "Ҳаракати мавод ба боло",
+ "ooui-outline-control-remove": "Ҳазви мавод",
+ "ooui-toolbar-more": "Бештар"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/th.json b/www/wiki/resources/lib/oojs-ui/i18n/th.json
new file mode 100644
index 00000000..94527935
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/th.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Supasate",
+ "Taweetham"
+ ]
+ },
+ "ooui-outline-control-move-down": "เลื่อนรายการลง",
+ "ooui-outline-control-move-up": "ย้ายรายการขึ้น"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/tl.json b/www/wiki/resources/lib/oojs-ui/i18n/tl.json
new file mode 100644
index 00000000..c0dbd5fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/tl.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "AnakngAraw",
+ "Sky Harbor",
+ "Jewel457"
+ ]
+ },
+ "ooui-outline-control-move-down": "Ilipat ang aytem pababa",
+ "ooui-outline-control-move-up": "Ilipat ang aytem pataas",
+ "ooui-outline-control-remove": "Tanggalin ang aytem",
+ "ooui-toolbar-more": "Marami pa",
+ "ooui-toolgroup-expand": "Maraming iba pa",
+ "ooui-toolgroup-collapse": "Kakaunti",
+ "ooui-dialog-message-accept": "Sige",
+ "ooui-dialog-message-reject": "Huwag ituloy",
+ "ooui-dialog-process-error": "May pagkakamali",
+ "ooui-dialog-process-dismiss": "Isa-isantabi",
+ "ooui-dialog-process-retry": "Subuking muli",
+ "ooui-dialog-process-continue": "Magpatuloy",
+ "ooui-selectfile-not-supported": "Ang pagpili ng file ay hindi kinakatigan",
+ "ooui-selectfile-placeholder": "Walang piniling file"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/tr.json b/www/wiki/resources/lib/oojs-ui/i18n/tr.json
new file mode 100644
index 00000000..9b88695a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/tr.json
@@ -0,0 +1,34 @@
+{
+ "@metadata": {
+ "authors": [
+ "Emperyan",
+ "Incelemeelemani",
+ "LuCKY",
+ "Maidis",
+ "Rapsar",
+ "Talha Samil Cakir",
+ "TurkishStyles",
+ "Sayginer",
+ "Meelo",
+ "McAang",
+ "Uğurkent",
+ "1917 Ekim Devrimi"
+ ]
+ },
+ "ooui-outline-control-move-down": "Ögeyi aşağı taşı",
+ "ooui-outline-control-move-up": "Ögeyi yukarı taşı",
+ "ooui-outline-control-remove": "Ögeyi kaldır",
+ "ooui-toolbar-more": "Dahası",
+ "ooui-toolgroup-expand": "Dahası",
+ "ooui-toolgroup-collapse": "Daha az",
+ "ooui-dialog-message-accept": "Tamam",
+ "ooui-dialog-message-reject": "İptal",
+ "ooui-dialog-process-error": "Bir şeyler yanlış gitti",
+ "ooui-dialog-process-dismiss": "Kapat",
+ "ooui-dialog-process-retry": "Tekrar dene",
+ "ooui-dialog-process-continue": "Devam et",
+ "ooui-selectfile-button-select": "Dosya seç",
+ "ooui-selectfile-not-supported": "Dosya seçimi desteklenmiyor",
+ "ooui-selectfile-placeholder": "Herhangi bir dosya seçilmedi",
+ "ooui-selectfile-dragdrop-placeholder": "Dosyayı buraya aç"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/tt-cyrl.json b/www/wiki/resources/lib/oojs-ui/i18n/tt-cyrl.json
new file mode 100644
index 00000000..335e509e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/tt-cyrl.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Ajdar",
+ "Ильнар"
+ ]
+ },
+ "ooui-outline-control-move-down": "Элементны аска күчерү",
+ "ooui-outline-control-move-up": "Элементны өскә күчерү",
+ "ooui-outline-control-remove": "Пунктны бетерү",
+ "ooui-toolbar-more": "Тагын",
+ "ooui-toolgroup-expand": "Күбрәк",
+ "ooui-toolgroup-collapse": "Азрак",
+ "ooui-dialog-message-accept": "ОК",
+ "ooui-dialog-message-reject": "Баш тарту",
+ "ooui-dialog-process-error": "Нәрсәдер килеп чыкмады",
+ "ooui-dialog-process-dismiss": "Ябу",
+ "ooui-dialog-process-retry": "Кабатлау",
+ "ooui-dialog-process-continue": "Дәвам итү",
+ "ooui-selectfile-button-select": "Файлны сайлагыз",
+ "ooui-selectfile-not-supported": "Файл сайлау хупланмый",
+ "ooui-selectfile-placeholder": "Файл сайланмаган",
+ "ooui-selectfile-dragdrop-placeholder": "Файлны монда куегыз"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ug-arab.json b/www/wiki/resources/lib/oojs-ui/i18n/ug-arab.json
new file mode 100644
index 00000000..00d19619
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ug-arab.json
@@ -0,0 +1,25 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sahran",
+ "Tel'et",
+ "Tifinaghes"
+ ]
+ },
+ "ooui-outline-control-move-down": "تۆۋەنگە يۆتكە",
+ "ooui-outline-control-move-up": "يۇقۇرىغا يۆتكە",
+ "ooui-outline-control-remove": "ئۆچۈر",
+ "ooui-toolbar-more": "تېخىمۇ كۆپ",
+ "ooui-toolgroup-expand": "تېخىمۇ كۆپ",
+ "ooui-toolgroup-collapse": "ئاز",
+ "ooui-dialog-message-accept": "تامام",
+ "ooui-dialog-message-reject": "ۋاز كەچ",
+ "ooui-dialog-process-error": "نامەلۇم خاتالىق كۆرۈلدى",
+ "ooui-dialog-process-dismiss": "چىقىرىۋەت",
+ "ooui-dialog-process-retry": "قايتا سىنا",
+ "ooui-dialog-process-continue": "داۋاملاشتۇر",
+ "ooui-selectfile-button-select": "بىر ھۆججەت تاللا",
+ "ooui-selectfile-not-supported": "تاللانغان ھۆججەتتە مەسىلە بار",
+ "ooui-selectfile-placeholder": "ھۆججەت تاللانمىدى",
+ "ooui-selectfile-dragdrop-placeholder": "ھۆججەتنى بۇ يەرگە تاشلاڭ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/uk.json b/www/wiki/resources/lib/oojs-ui/i18n/uk.json
new file mode 100644
index 00000000..a38afbfd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/uk.json
@@ -0,0 +1,39 @@
+{
+ "@metadata": {
+ "authors": [
+ "AS",
+ "Aced",
+ "Ahonc",
+ "Andriykopanytsia",
+ "Base",
+ "Perohanych",
+ "RLuts",
+ "Sahran",
+ "Sergento",
+ "Steve.rusyn",
+ "SteveR",
+ "Tel'et",
+ "Tifinaghes",
+ "Ата",
+ "Piramidion",
+ "A1",
+ "Dars"
+ ]
+ },
+ "ooui-outline-control-move-down": "Перемістити елемент униз",
+ "ooui-outline-control-move-up": "Перемістити елемент вгору",
+ "ooui-outline-control-remove": "Видалити елемент",
+ "ooui-toolbar-more": "Більше",
+ "ooui-toolgroup-expand": "Більше",
+ "ooui-toolgroup-collapse": "Менше",
+ "ooui-dialog-message-accept": "Готово",
+ "ooui-dialog-message-reject": "Скасувати",
+ "ooui-dialog-process-error": "Щось пішло не так",
+ "ooui-dialog-process-dismiss": "Приховати",
+ "ooui-dialog-process-retry": "Спробуйте ще раз",
+ "ooui-dialog-process-continue": "Продовжити",
+ "ooui-selectfile-button-select": "Оберіть файл",
+ "ooui-selectfile-not-supported": "Вибір файлу не підтримується",
+ "ooui-selectfile-placeholder": "Жодного файлу не вибрано",
+ "ooui-selectfile-dragdrop-placeholder": "Помістіть файл сюди"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/ur.json b/www/wiki/resources/lib/oojs-ui/i18n/ur.json
new file mode 100644
index 00000000..62a17655
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/ur.json
@@ -0,0 +1,23 @@
+{
+ "@metadata": {
+ "authors": [
+ "Muhammad Shuaib"
+ ]
+ },
+ "ooui-outline-control-move-down": "آئیٹم نیچے کھسکائیں",
+ "ooui-outline-control-move-up": "آئیٹم اوپر بڑھائیں",
+ "ooui-outline-control-remove": "آئیٹم حذف کریں",
+ "ooui-toolbar-more": "مزید",
+ "ooui-toolgroup-expand": "مزید",
+ "ooui-toolgroup-collapse": "کم کریں",
+ "ooui-dialog-message-accept": "ٹھیک",
+ "ooui-dialog-message-reject": "منسوخ کریں",
+ "ooui-dialog-process-error": "کچھ غلط ہو گیا ہے",
+ "ooui-dialog-process-dismiss": "ختم کریں",
+ "ooui-dialog-process-retry": "دوبارہ کوشش کریں",
+ "ooui-dialog-process-continue": "جاری رکھیں",
+ "ooui-selectfile-button-select": "فائل منتخب کریں",
+ "ooui-selectfile-not-supported": "فائل کا انتخاب معاونت شدہ نہیں",
+ "ooui-selectfile-placeholder": "کوئی فائل منتخب نہیں",
+ "ooui-selectfile-dragdrop-placeholder": "فائل یہاں چھوڑیں"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/uz.json b/www/wiki/resources/lib/oojs-ui/i18n/uz.json
new file mode 100644
index 00000000..7c6263e4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/uz.json
@@ -0,0 +1,13 @@
+{
+ "@metadata": {
+ "authors": [
+ "CoderSI",
+ "Noor2020",
+ "Sociologist",
+ "පසිඳු කාවින්ද"
+ ]
+ },
+ "ooui-outline-control-move-down": "Elementni pastga koʻchirish",
+ "ooui-outline-control-move-up": "Elementni yuqoriga koʻchirish",
+ "ooui-toolbar-more": "Yana"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/vec.json b/www/wiki/resources/lib/oojs-ui/i18n/vec.json
new file mode 100644
index 00000000..ddd27c5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/vec.json
@@ -0,0 +1,22 @@
+{
+ "@metadata": {
+ "authors": [
+ "Candalua",
+ "GatoSelvadego",
+ "Gloria sah"
+ ]
+ },
+ "ooui-outline-control-move-down": "Sposta in baso",
+ "ooui-outline-control-move-up": "Sposta in sima",
+ "ooui-toolbar-more": "Altro",
+ "ooui-toolgroup-expand": "Piassè",
+ "ooui-toolgroup-collapse": "Manco",
+ "ooui-dialog-message-accept": "Va ben",
+ "ooui-dialog-message-reject": "Fa gnente",
+ "ooui-dialog-process-error": "Xe 'ndà storto calcossa",
+ "ooui-dialog-process-dismiss": "Scondi",
+ "ooui-dialog-process-retry": "Proa da novo",
+ "ooui-dialog-process-continue": "Và vanti",
+ "ooui-selectfile-button-select": "Siegli un file",
+ "ooui-selectfile-dragdrop-placeholder": "Mola zo el file chì rento"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/vep.json b/www/wiki/resources/lib/oojs-ui/i18n/vep.json
new file mode 100644
index 00000000..b6ad0929
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/vep.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Sebranik"
+ ]
+ },
+ "ooui-toolgroup-expand": "Enamba"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/vi.json b/www/wiki/resources/lib/oojs-ui/i18n/vi.json
new file mode 100644
index 00000000..b2714034
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/vi.json
@@ -0,0 +1,28 @@
+{
+ "@metadata": {
+ "authors": [
+ "Cheers!",
+ "Jdforrester",
+ "Minh Nguyen",
+ "Max20091",
+ "Anh88"
+ ]
+ },
+ "ooui-outline-control-move-down": "Chuyển mục xuống",
+ "ooui-outline-control-move-up": "Chuyển mục lên",
+ "ooui-outline-control-remove": "Xóa mục",
+ "ooui-toolbar-more": "Thêm",
+ "ooui-toolgroup-expand": "Mở rộng",
+ "ooui-toolgroup-collapse": "Rút gọn",
+ "ooui-item-remove": "Loại bỏ",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Hủy bỏ",
+ "ooui-dialog-process-error": "Có thứ gì đó bị lỗi",
+ "ooui-dialog-process-dismiss": "Bỏ qua",
+ "ooui-dialog-process-retry": "Thử lại",
+ "ooui-dialog-process-continue": "Tiếp tục",
+ "ooui-selectfile-button-select": "Chọn tập tin",
+ "ooui-selectfile-not-supported": "Không hỗ trợ việc chọn tập tin",
+ "ooui-selectfile-placeholder": "Không có tập tin nào được chọn",
+ "ooui-selectfile-dragdrop-placeholder": "Thả tập tin vào đây"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/vo.json b/www/wiki/resources/lib/oojs-ui/i18n/vo.json
new file mode 100644
index 00000000..3510ca93
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/vo.json
@@ -0,0 +1,8 @@
+{
+ "@metadata": {
+ "authors": [
+ "Malafaya"
+ ]
+ },
+ "ooui-toolbar-more": "Pluikos"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/war.json b/www/wiki/resources/lib/oojs-ui/i18n/war.json
new file mode 100644
index 00000000..b0ea30ca
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/war.json
@@ -0,0 +1,19 @@
+{
+ "@metadata": {
+ "authors": [
+ "JinJian"
+ ]
+ },
+ "ooui-outline-control-move-down": "Ibalhin paubos",
+ "ooui-outline-control-move-up": "Ibalhin paigbaw",
+ "ooui-outline-control-remove": "Tanggala",
+ "ooui-toolbar-more": "Damo pa",
+ "ooui-toolgroup-expand": "Damo pa",
+ "ooui-toolgroup-collapse": "Guruguti",
+ "ooui-dialog-message-accept": "OK",
+ "ooui-dialog-message-reject": "Igpabaliwaray",
+ "ooui-dialog-process-error": "Mayda sayop nga nahitabo",
+ "ooui-dialog-process-retry": "Utroha",
+ "ooui-dialog-process-continue": "Padayon",
+ "ooui-selectfile-button-select": "Pagpili hin file"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/wuu.json b/www/wiki/resources/lib/oojs-ui/i18n/wuu.json
new file mode 100644
index 00000000..64816249
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/wuu.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Malafaya",
+ "十弌",
+ "飞舞回堂前"
+ ]
+ },
+ "ooui-toolbar-more": "更多"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/xmf.json b/www/wiki/resources/lib/oojs-ui/i18n/xmf.json
new file mode 100644
index 00000000..4109c36e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/xmf.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "David1010",
+ "Silovan"
+ ]
+ },
+ "ooui-outline-control-move-down": "ელემენტის ქვემოთ გადატანა",
+ "ooui-outline-control-move-up": "ელემენტის ზემოთ გადატანა",
+ "ooui-outline-control-remove": "ელემენტის წაშლა",
+ "ooui-toolbar-more": "უმოსი",
+ "ooui-toolgroup-expand": "უმოსი",
+ "ooui-toolgroup-collapse": "რამდენიმე",
+ "ooui-dialog-message-accept": "ჯგირი",
+ "ooui-dialog-message-reject": "გოუქვაფა",
+ "ooui-dialog-process-error": "მოხდა რაღაც შეცდომა",
+ "ooui-dialog-process-dismiss": "დამალვა",
+ "ooui-dialog-process-retry": "კიდევ სცადეთ",
+ "ooui-dialog-process-continue": "გაგრძელება",
+ "ooui-selectfile-button-select": "გეგშაგორით ფაილი",
+ "ooui-selectfile-not-supported": "ფაილიშ აშაგორუა ვა რე ხენწყილი",
+ "ooui-selectfile-placeholder": "ფაილი ვა რე გიშაგორილი",
+ "ooui-selectfile-dragdrop-placeholder": "ქინაჸათით ფაილი ათაქ"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/yi.json b/www/wiki/resources/lib/oojs-ui/i18n/yi.json
new file mode 100644
index 00000000..84048e7c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/yi.json
@@ -0,0 +1,24 @@
+{
+ "@metadata": {
+ "authors": [
+ "Malafaya",
+ "פוילישער",
+ "十弌"
+ ]
+ },
+ "ooui-outline-control-move-down": "רוקן עלעמענט אראפ",
+ "ooui-outline-control-move-up": "רוקן עלעמענט ארויף",
+ "ooui-outline-control-remove": "אַראָפנעמען איינס",
+ "ooui-toolbar-more": "נאך",
+ "ooui-toolgroup-expand": "נאך",
+ "ooui-toolgroup-collapse": "ווייניגער",
+ "ooui-dialog-message-accept": "יאָ",
+ "ooui-dialog-message-reject": "אַנולירן",
+ "ooui-dialog-process-error": "עפעס איז דורכגעפאלן",
+ "ooui-dialog-process-dismiss": "צומאַכן",
+ "ooui-dialog-process-retry": "פרובירט נאכאמאל",
+ "ooui-dialog-process-continue": "פֿארזעצן",
+ "ooui-selectfile-button-select": "קלויבט א טעקע",
+ "ooui-selectfile-not-supported": "טעקע אויסווייל נישט געשטיצט",
+ "ooui-selectfile-placeholder": "קיין טעקע נישט אויסגעוויילט"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/yo.json b/www/wiki/resources/lib/oojs-ui/i18n/yo.json
new file mode 100644
index 00000000..d979fc13
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/yo.json
@@ -0,0 +1,10 @@
+{
+ "@metadata": {
+ "authors": [
+ "Demmy"
+ ]
+ },
+ "ooui-outline-control-move-down": "Sún onítòún sí sàlẹ̀",
+ "ooui-outline-control-move-up": "Sún onítòún s'ókè",
+ "ooui-toolbar-more": "Míràn"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/yue.json b/www/wiki/resources/lib/oojs-ui/i18n/yue.json
new file mode 100644
index 00000000..6a9e902b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/yue.json
@@ -0,0 +1,27 @@
+{
+ "@metadata": {
+ "authors": [
+ "Deryck Chan",
+ "William915",
+ "Shinjiman",
+ "Ktchankt",
+ "Hello903hello"
+ ]
+ },
+ "ooui-outline-control-move-down": "向下搬",
+ "ooui-outline-control-move-up": "向上搬",
+ "ooui-outline-control-remove": "拎走",
+ "ooui-toolbar-more": "更多",
+ "ooui-toolgroup-expand": "更多",
+ "ooui-toolgroup-collapse": "少啲",
+ "ooui-dialog-message-accept": "好",
+ "ooui-dialog-message-reject": "取消",
+ "ooui-dialog-process-error": "唔對路",
+ "ooui-dialog-process-dismiss": "閂咗佢",
+ "ooui-dialog-process-retry": "再試過",
+ "ooui-dialog-process-continue": "繼續",
+ "ooui-selectfile-button-select": "揀檔案",
+ "ooui-selectfile-not-supported": "未有文件選擇功能",
+ "ooui-selectfile-placeholder": "無揀到文件",
+ "ooui-selectfile-dragdrop-placeholder": "放檔案響度"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/zh-hans.json b/www/wiki/resources/lib/oojs-ui/i18n/zh-hans.json
new file mode 100644
index 00000000..a3e637d6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/zh-hans.json
@@ -0,0 +1,41 @@
+{
+ "@metadata": {
+ "authors": [
+ "Anakmalaysia",
+ "Bencmq",
+ "Demmy",
+ "Hydra",
+ "Hzy980512",
+ "Liangent",
+ "Liuxinyu970226",
+ "Qiyue2001",
+ "Shirayuki",
+ "Shizhao",
+ "TianyinLee",
+ "Xiaomingyan",
+ "Yfdyh000",
+ "Zhangjintao",
+ "乌拉跨氪",
+ "Great Brightstar",
+ "Nbdd0121",
+ "Yejianfei"
+ ]
+ },
+ "ooui-outline-control-move-down": "向下移动一项",
+ "ooui-outline-control-move-up": "向上移动一项",
+ "ooui-outline-control-remove": "移除项目",
+ "ooui-toolbar-more": "更多",
+ "ooui-toolgroup-expand": "更多",
+ "ooui-toolgroup-collapse": "更少",
+ "ooui-item-remove": "移除",
+ "ooui-dialog-message-accept": "确定",
+ "ooui-dialog-message-reject": "取消",
+ "ooui-dialog-process-error": "发生了一些错误",
+ "ooui-dialog-process-dismiss": "关闭",
+ "ooui-dialog-process-retry": "重试",
+ "ooui-dialog-process-continue": "继续",
+ "ooui-selectfile-button-select": "选择一个文件",
+ "ooui-selectfile-not-supported": "不支持文件选择器",
+ "ooui-selectfile-placeholder": "没有选定文件",
+ "ooui-selectfile-dragdrop-placeholder": "将文件拖动至此"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/i18n/zh-hant.json b/www/wiki/resources/lib/oojs-ui/i18n/zh-hant.json
new file mode 100644
index 00000000..027b7bee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/i18n/zh-hant.json
@@ -0,0 +1,37 @@
+{
+ "@metadata": {
+ "authors": [
+ "Anakmalaysia",
+ "Ch.Andrew",
+ "Hydra",
+ "Justincheng12345",
+ "Liflon",
+ "Liuxinyu970226",
+ "Qiyue2001",
+ "Radish10cm",
+ "Shirayuki",
+ "Simon Shek",
+ "Spring Roll Conan",
+ "Waihorace",
+ "Cwlin0416",
+ "LNDDYL",
+ "Shangkuanlc"
+ ]
+ },
+ "ooui-outline-control-move-down": "項目下移",
+ "ooui-outline-control-move-up": "項目上移",
+ "ooui-outline-control-remove": "移除項目",
+ "ooui-toolbar-more": "更多",
+ "ooui-toolgroup-expand": "更多",
+ "ooui-toolgroup-collapse": "更少",
+ "ooui-dialog-message-accept": "確定",
+ "ooui-dialog-message-reject": "取消",
+ "ooui-dialog-process-error": "發生不明錯誤",
+ "ooui-dialog-process-dismiss": "關閉",
+ "ooui-dialog-process-retry": "再試一次",
+ "ooui-dialog-process-continue": "繼續",
+ "ooui-selectfile-button-select": "選擇一個檔案",
+ "ooui-selectfile-not-supported": "無法支援所選擇的檔案",
+ "ooui-selectfile-placeholder": "尚未選擇檔案",
+ "ooui-selectfile-dragdrop-placeholder": "拖曳檔案到此處"
+}
diff --git a/www/wiki/resources/lib/oojs-ui/images/grab.cur b/www/wiki/resources/lib/oojs-ui/images/grab.cur
new file mode 100644
index 00000000..fba3ddc8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/images/grab.cur
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/images/grabbing.cur b/www/wiki/resources/lib/oojs-ui/images/grabbing.cur
new file mode 100644
index 00000000..41aaa62a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/images/grabbing.cur
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-apex.js b/www/wiki/resources/lib/oojs-ui/oojs-ui-apex.js
new file mode 100644
index 00000000..81a62eff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-apex.js
@@ -0,0 +1,45 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:23:58Z
+ */
+( function ( OO ) {
+
+'use strict';
+
+/**
+ * @class
+ * @extends OO.ui.Theme
+ *
+ * @constructor
+ */
+OO.ui.ApexTheme = function OoUiApexTheme() {
+ // Parent constructor
+ OO.ui.ApexTheme.parent.call( this );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ApexTheme, OO.ui.Theme );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ApexTheme.prototype.getDialogTransitionDuration = function () {
+ return 250;
+};
+
+/* Instantiation */
+
+OO.ui.theme = new OO.ui.ApexTheme();
+
+}( OO ) );
+
+//# sourceMappingURL=oojs-ui-apex.js.map \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-apex.js.map b/www/wiki/resources/lib/oojs-ui/oojs-ui-apex.js.map
new file mode 100644
index 00000000..f5093434
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-apex.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/intro.js.txt","../src/themes/apex/ApexTheme.js","../src/outro.js.txt"],"names":[],"mappings":";;;;;;;;;;AAAA,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACnB;AACA,CAAC,GAAG,CAAC,MAAM,EAAE;;ACFb,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK;AACvB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAC;AAC5C,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACrC,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE;AAChD;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrE,CAAC,MAAM,CAAC,GAAG,CAAC;AACZ,EAAE;AACF;AACA,EAAE,CAAC,aAAa,CAAC,EAAE;AACnB;AACA,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,GAAG;;AC1BpC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE","file":"oojs-ui-apex.js","sourcesContent":["( function ( OO ) {\n\n'use strict';\n","/**\n * @class\n * @extends OO.ui.Theme\n *\n * @constructor\n */\nOO.ui.ApexTheme = function OoUiApexTheme() {\n\t// Parent constructor\n\tOO.ui.ApexTheme.parent.call( this );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ApexTheme, OO.ui.Theme );\n\n/* Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.ApexTheme.prototype.getDialogTransitionDuration = function () {\n\treturn 250;\n};\n\n/* Instantiation */\n\nOO.ui.theme = new OO.ui.ApexTheme();\n","}( OO ) );\n"]} \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-core-apex.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-core-apex.css
new file mode 100644
index 00000000..c6cc9682
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-core-apex.css
@@ -0,0 +1,1481 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:24:03Z
+ */
+.oo-ui-element-hidden {
+ display: none !important;
+}
+.oo-ui-buttonElement {
+ display: inline-block;
+ line-height: normal;
+ vertical-align: middle;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+ cursor: pointer;
+ display: inline-block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ vertical-align: middle;
+ font-family: inherit;
+ font-size: inherit;
+ white-space: nowrap;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button::-moz-focus-inner {
+ border-color: transparent;
+ padding: 0;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ display: none;
+}
+.oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ cursor: default;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
+.oo-ui-buttonElement-frameless.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-buttonElement-frameless {
+ position: relative;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
+ vertical-align: top;
+ text-align: center;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+ color: #333;
+ position: relative;
+ border-radius: 4px;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button:focus {
+ outline: 0;
+}
+.oo-ui-buttonElement > input.oo-ui-buttonElement-button,
+.oo-ui-buttonElement.oo-ui-labelElement .oo-ui-labelElement-label {
+ line-height: 1.875em;
+}
+.oo-ui-buttonElement.oo-ui-iconElement .oo-ui-iconElement-icon {
+ height: 100%;
+ margin-left: 0;
+}
+.oo-ui-buttonElement.oo-ui-iconElement .oo-ui-indicatorElement-indicator {
+ margin-left: 0.46875em;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ margin: 0.46875em;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:hover > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:focus > .oo-ui-iconElement-icon {
+ opacity: 1;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label,
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:focus > .oo-ui-labelElement-label {
+ color: #000;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #333;
+}
+.oo-ui-buttonElement-frameless.oo-ui-labelElement:first-child,
+.oo-ui-buttonElement-frameless.oo-ui-iconElement:first-child {
+ margin-left: -0.3125em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-labelElement > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-frameless.oo-ui-iconElement > .oo-ui-buttonElement-button {
+ padding: 0.3125em 0.3125em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-labelElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-frameless.oo-ui-iconElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button {
+ padding: 0.3125em 0.3125em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #333;
+ margin-left: 0.25em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-indicatorElement > .oo-ui-buttonElement-button {
+ padding: 0;
+}
+.oo-ui-buttonElement-frameless > input.oo-ui-buttonElement-button {
+ padding-left: 0.25em;
+ color: #333;
+}
+.oo-ui-buttonElement-frameless > input.oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-frameless > input.oo-ui-buttonElement-button:focus {
+ color: #000;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-iconElement > .oo-ui-buttonElement-button:focus,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-labelElement > .oo-ui-buttonElement-button:focus {
+ border-color: #ace;
+ box-shadow: 0 0 2px 2px #ace;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-iconElement > .oo-ui-buttonElement-button:focus:active,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-labelElement > .oo-ui-buttonElement-button:focus:active {
+ border-color: #fff;
+ border-color: transparent;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-indicatorElement:not( .oo-ui-iconElement ):not( .oo-ui-labelElement ) > .oo-ui-buttonElement-button {
+ border-radius: 4px;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-indicatorElement:not( .oo-ui-iconElement ):not( .oo-ui-labelElement ) > .oo-ui-buttonElement-button:focus {
+ box-shadow: 0 0 2px 2px #ace;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-indicatorElement:not( .oo-ui-iconElement ):not( .oo-ui-labelElement ) > .oo-ui-buttonElement-button:focus:active {
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #087ecc;
+}
+.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #76ab36;
+}
+.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #d45353;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #ccc;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
+ padding: 0.234375em 0.78125em;
+ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+ border: 1px #c9c9c9 solid;
+ -webkit-transition: border-color 100ms ease;
+ -moz-transition: border-color 100ms ease;
+ transition: border-color 100ms ease;
+ background-color: #eeeeee;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #fff), color-stop(100%, #ddd));
+ background-image: -webkit-linear-gradient(top, #fff 0, #ddd 100%);
+ background-image: -moz-linear-gradient(top, #fff 0, #ddd 100%);
+ background-image: linear-gradient(to bottom, #fff 0, #ddd 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffffff', endColorstr='#ffdddddd' )";
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button:hover {
+ border-color: #aaa;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button:focus {
+ border-color: #ace;
+ box-shadow: 0 0 2px 2px #ace;
+}
+.oo-ui-buttonElement-framed > input.oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ line-height: 1.875em;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+ color: #000;
+ border-color: #c9c9c9;
+ background-color: #eeeeee;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #ddd), color-stop(100%, #fff));
+ background-image: -webkit-linear-gradient(top, #ddd 0, #fff 100%);
+ background-image: -moz-linear-gradient(top, #ddd 0, #fff 100%);
+ background-image: linear-gradient(to bottom, #ddd 0, #fff 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffdddddd', endColorstr='#ffffffff' )";
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active:focus,
+.oo-ui-buttonElement-framed.oo-ui-buttonElement-active > .oo-ui-buttonElement-button:focus,
+.oo-ui-buttonElement-framed.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button:focus {
+ border-color: #ace;
+ box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07), 0 0 2px 2px #ace;
+}
+.oo-ui-buttonElement-framed.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ margin-left: -0.5em;
+ margin-right: -0.5em;
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ margin-right: 0.3em;
+}
+.oo-ui-buttonElement-framed.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ margin-left: -0.005em;
+ margin-right: -0.005em;
+}
+.oo-ui-buttonElement-framed.oo-ui-indicatorElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement-framed.oo-ui-indicatorElement.oo-ui-iconElement:not( .oo-ui-labelElement ) > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ margin-left: 0.46875em;
+ margin-right: -0.275em;
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button {
+ border: 1px solid #a6cee1;
+ background-color: #cde7f4;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #eaf4fa), color-stop(100%, #b0d9ee));
+ background-image: -webkit-linear-gradient(top, #eaf4fa 0, #b0d9ee 100%);
+ background-image: -moz-linear-gradient(top, #eaf4fa 0, #b0d9ee 100%);
+ background-image: linear-gradient(to bottom, #eaf4fa 0, #b0d9ee 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffeaf4fa', endColorstr='#ffb0d9ee' )";
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover {
+ border-color: #9dc2d4;
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-progressive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-progressive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ border: 1px solid #a6cee1;
+ background-color: #cde7f4;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #b0d9ee), color-stop(100%, #eaf4fa));
+ background-image: -webkit-linear-gradient(top, #b0d9ee 0, #eaf4fa 100%);
+ background-image: -moz-linear-gradient(top, #b0d9ee 0, #eaf4fa 100%);
+ background-image: linear-gradient(to bottom, #b0d9ee 0, #eaf4fa 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffb0d9ee', endColorstr='#ffeaf4fa' )";
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
+ border: 1px solid #b8d892;
+ background-color: #daf0bd;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #f0fbe1), color-stop(100%, #c3e59a));
+ background-image: -webkit-linear-gradient(top, #f0fbe1 0, #c3e59a 100%);
+ background-image: -moz-linear-gradient(top, #f0fbe1 0, #c3e59a 100%);
+ background-image: linear-gradient(to bottom, #f0fbe1 0, #c3e59a 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#fff0fbe1', endColorstr='#ffc3e59a' )";
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover {
+ border-color: #adcb89;
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ border: 1px solid #b8d892;
+ background-color: #daf0bd;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #c3e59a), color-stop(100%, #f0fbe1));
+ background-image: -webkit-linear-gradient(top, #c3e59a 0, #f0fbe1 100%);
+ background-image: -moz-linear-gradient(top, #c3e59a 0, #f0fbe1 100%);
+ background-image: linear-gradient(to bottom, #c3e59a 0, #f0fbe1 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffc3e59a', endColorstr='#fff0fbe1' )";
+}
+.oo-ui-buttonElement-framed.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
+ color: #d45353;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ opacity: 0.5;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
+ box-shadow: none;
+ color: #333;
+ background: #eee;
+ border-color: #ccc;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button:focus {
+ border-color: #ccc;
+ box-shadow: none;
+}
+.oo-ui-clippableElement-clippable {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ min-height: 3.125em;
+}
+.oo-ui-floatableElement {
+ position: absolute;
+}
+.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-iconElement.oo-ui-iconElement-icon {
+ background-size: contain;
+ background-position: center center;
+ background-repeat: no-repeat;
+ min-width: 24px;
+ width: 1.875em;
+ min-height: 24px;
+ height: 1.875em;
+}
+.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-iconElement.oo-ui-iconElement-icon {
+ opacity: 0.8;
+}
+.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator,
+.oo-ui-indicatorElement.oo-ui-indicatorElement-indicator {
+ background-size: contain;
+ background-position: center center;
+ background-repeat: no-repeat;
+ min-width: 12px;
+ width: 0.9375em;
+ min-height: 12px;
+ height: 0.9375em;
+}
+.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator,
+.oo-ui-indicatorElement.oo-ui-indicatorElement-indicator {
+ opacity: 0.8;
+}
+.oo-ui-labelElement .oo-ui-labelElement-label-highlight {
+ font-weight: bold;
+}
+.oo-ui-pendingElement-pending {
+ background-image: /* @embed */ url(themes/apex/images/textures/pending.gif);
+}
+.oo-ui-fieldLayout {
+ display: block;
+ margin-top: 1em;
+}
+.oo-ui-fieldLayout:before,
+.oo-ui-fieldLayout:after {
+ content: ' ';
+ display: table;
+}
+.oo-ui-fieldLayout:after {
+ clear: both;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-help,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-help,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ display: block;
+ float: left;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
+ text-align: right;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body {
+ display: table;
+ width: 100%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ display: table-cell;
+ vertical-align: middle;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ width: 1px;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ display: block;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help {
+ float: right;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help > .oo-ui-popupWidget > .oo-ui-popupWidget-popup {
+ z-index: 1;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-help,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-help {
+ margin-right: 0;
+ margin-left: -1.875em;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ width: 60%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
+ margin-right: 5%;
+ width: 35%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header > .oo-ui-labelElement-label {
+ display: block;
+ padding-top: 0.5em;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline {
+ margin-top: 1.25em;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body {
+ max-width: 50em;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
+ padding: 0.25em 0 0.25em 0.5em;
+}
+.oo-ui-fieldLayout:first-child {
+ margin-top: 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
+ max-width: 50em;
+ padding: 0.5em 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top .oo-ui-fieldLayout-help,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline .oo-ui-fieldLayout-help {
+ margin-top: -0.3em;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget {
+ margin-right: 0;
+ margin-top: 0.25em;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-fieldLayout-disabled > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header > .oo-ui-labelElement-label {
+ color: #ccc;
+}
+.oo-ui-fieldLayout-messages {
+ list-style: none none;
+ margin: 0;
+ padding: 0;
+ margin-top: 0.25em;
+ margin-left: 0.25em;
+}
+.oo-ui-fieldLayout-messages > li {
+ margin: 0;
+ padding: 0;
+}
+.oo-ui-fieldLayout-messages .oo-ui-iconWidget {
+ display: none;
+}
+.oo-ui-fieldLayout-messages .oo-ui-fieldLayout-messages-error {
+ color: #d45353;
+}
+.oo-ui-fieldLayout-messages .oo-ui-labelWidget {
+ padding: 0.1em 0;
+ line-height: 1.5em;
+ vertical-align: middle;
+}
+.oo-ui-actionFieldLayout-input,
+.oo-ui-actionFieldLayout-button {
+ display: table-cell;
+ vertical-align: middle;
+}
+.oo-ui-actionFieldLayout-input {
+ padding-right: 1em;
+}
+.oo-ui-actionFieldLayout-button {
+ width: 1%;
+ white-space: nowrap;
+}
+.oo-ui-actionFieldLayout.oo-ui-fieldLayout-align-top {
+ max-width: 50em;
+}
+.oo-ui-fieldsetLayout {
+ position: relative;
+ min-width: 0;
+ margin: 0;
+ border: 0;
+ padding: 0.01px 0 0 0;
+}
+body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
+ display: table-cell;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-fieldsetLayout-header > .oo-ui-iconElement-icon {
+ display: block;
+ position: absolute;
+}
+.oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-fieldsetLayout-header {
+ color: inherit;
+ display: inline-table;
+ box-sizing: border-box;
+ padding: 0;
+ white-space: normal;
+ float: left;
+ width: 100%;
+}
+.oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-fieldsetLayout-header > .oo-ui-labelElement-label:empty {
+ display: none;
+}
+.oo-ui-fieldsetLayout-group {
+ clear: both;
+}
+.oo-ui-fieldsetLayout .oo-ui-fieldsetLayout-help {
+ float: right;
+}
+.oo-ui-fieldsetLayout .oo-ui-fieldsetLayout-help > .oo-ui-popupWidget > .oo-ui-popupWidget-popup {
+ z-index: 1;
+}
+.oo-ui-fieldsetLayout .oo-ui-fieldsetLayout-header {
+ max-width: 50em;
+}
+.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout,
+.oo-ui-fieldsetLayout + .oo-ui-formLayout {
+ margin-top: 2em;
+}
+.oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-fieldsetLayout-header > .oo-ui-labelElement-label {
+ display: inline-block;
+ font-size: 1.15em;
+ margin-bottom: 0.5em;
+ padding: 0.25em 0;
+ font-weight: bold;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-fieldsetLayout-header > .oo-ui-labelElement-label {
+ padding-left: 2em;
+ line-height: 1.8em;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-fieldsetLayout-header > .oo-ui-iconElement-icon {
+ left: 0;
+ top: 0.25em;
+}
+.oo-ui-fieldsetLayout > .oo-ui-fieldsetLayout-header > .oo-ui-popupButtonWidget {
+ margin-right: 0;
+}
+.oo-ui-fieldsetLayout > .oo-ui-fieldsetLayout-header > .oo-ui-popupButtonWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-formLayout + .oo-ui-fieldsetLayout,
+.oo-ui-formLayout + .oo-ui-formLayout {
+ margin-top: 2em;
+}
+.oo-ui-panelLayout {
+ position: relative;
+}
+.oo-ui-panelLayout-scrollable {
+ overflow: auto;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
+}
+.oo-ui-panelLayout-expanded {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-panelLayout-padded {
+ padding: 1.25em;
+}
+.oo-ui-panelLayout-framed {
+ border: 1px solid #ccc;
+ border-radius: 0.5em;
+ box-shadow: 0 0.25em 1em rgba(0, 0, 0, 0.25);
+}
+.oo-ui-panelLayout-padded.oo-ui-panelLayout-framed {
+ margin: 1em 0;
+}
+.oo-ui-horizontalLayout > .oo-ui-widget {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout {
+ display: inline-block;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout,
+.oo-ui-horizontalLayout > .oo-ui-widget {
+ margin-right: 0.5em;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout:last-child,
+.oo-ui-horizontalLayout > .oo-ui-widget:last-child {
+ margin-right: 0;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout {
+ margin-top: 0;
+}
+.oo-ui-optionWidget {
+ position: relative;
+ display: block;
+ padding: 0.25em 0.5em;
+ border: 0;
+}
+.oo-ui-optionWidget.oo-ui-widget-enabled {
+ cursor: pointer;
+}
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+ cursor: default;
+}
+.oo-ui-optionWidget.oo-ui-labelElement > .oo-ui-labelElement-label {
+ display: block;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.oo-ui-optionWidget-highlighted {
+ background-color: #e1f3ff;
+}
+.oo-ui-optionWidget .oo-ui-labelElement-label {
+ line-height: 1.5em;
+}
+.oo-ui-selectWidget-depressed .oo-ui-optionWidget-selected {
+ background-color: #a7dcff;
+}
+.oo-ui-selectWidget-pressed .oo-ui-optionWidget-pressed,
+.oo-ui-selectWidget-pressed .oo-ui-optionWidget-pressed.oo-ui-optionWidget-highlighted,
+.oo-ui-selectWidget-pressed .oo-ui-optionWidget-pressed.oo-ui-optionWidget-highlighted.oo-ui-optionWidget-selected {
+ background-color: #a7dcff;
+}
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+ color: #ccc;
+}
+.oo-ui-decoratedOptionWidget {
+ padding: 0.5em 2em 0.5em 3em;
+}
+.oo-ui-decoratedOptionWidget > .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget > .oo-ui-indicatorElement-indicator {
+ position: absolute;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ top: 0;
+ height: 100%;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+ left: 0.5em;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ right: 0.5em;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-widget-disabled .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-radioOptionWidget {
+ padding: 0;
+ background-color: transparent;
+}
+.oo-ui-radioOptionWidget .oo-ui-radioInputWidget,
+.oo-ui-radioOptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-radioOptionWidget.oo-ui-optionWidget-selected,
+.oo-ui-radioOptionWidget.oo-ui-optionWidget-pressed,
+.oo-ui-radioOptionWidget.oo-ui-optionWidget-highlighted {
+ background-color: transparent;
+}
+.oo-ui-radioOptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ padding-left: 0.5em;
+}
+.oo-ui-radioOptionWidget .oo-ui-radioInputWidget {
+ margin-right: 0;
+}
+.oo-ui-labelWidget {
+ display: inline-block;
+ padding: 0.5em 0;
+}
+.oo-ui-iconWidget {
+ display: inline-block;
+ vertical-align: middle;
+ line-height: 2.5em;
+}
+.oo-ui-iconWidget.oo-ui-widget-disabled {
+ opacity: 0.2;
+}
+.oo-ui-indicatorWidget {
+ display: inline-block;
+ vertical-align: middle;
+ line-height: 2.5em;
+ margin: 0.46875em;
+}
+.oo-ui-indicatorWidget.oo-ui-widget-disabled {
+ opacity: 0.2;
+}
+.oo-ui-buttonWidget {
+ margin-right: 0.5em;
+}
+.oo-ui-buttonWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonGroupWidget {
+ display: inline-block;
+ white-space: nowrap;
+ border-radius: 4px;
+ margin-right: 0.5em;
+ z-index: 0;
+ position: relative;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonWidget.oo-ui-buttonElement-active .oo-ui-buttonElement-button {
+ cursor: default;
+}
+.oo-ui-buttonGroupWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement {
+ margin-right: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+ border-radius: 0;
+ margin-left: -1px;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:first-child .oo-ui-buttonElement-button {
+ border-bottom-left-radius: 4px;
+ border-top-left-radius: 4px;
+ margin-left: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:last-child .oo-ui-buttonElement-button {
+ border-bottom-right-radius: 4px;
+ border-top-right-radius: 4px;
+}
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active {
+ z-index: 1;
+}
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+ z-index: 2;
+}
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ z-index: 3;
+}
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ z-index: -1;
+}
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-toggleWidget-on + .oo-ui-toggleWidget-on > .oo-ui-buttonElement-button,
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-toggleWidget-on + .oo-ui-toggleWidget-on > .oo-ui-buttonElement-button:active {
+ z-index: 3;
+}
+.oo-ui-popupWidget {
+ position: absolute;
+}
+.oo-ui-popupWidget-popup {
+ position: relative;
+ overflow: hidden;
+ z-index: 1;
+}
+.oo-ui-popupWidget-anchor {
+ display: none;
+ z-index: 1;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor {
+ display: block;
+ position: absolute;
+ background-repeat: no-repeat;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:before,
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:after {
+ content: '';
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-style: solid;
+ border-color: transparent;
+}
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor {
+ left: 0;
+}
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor:before,
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor:after {
+ border-top: 0;
+}
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor {
+ left: 0;
+}
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor:before,
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor:after {
+ border-bottom: 0;
+}
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor {
+ top: 0;
+}
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor:before,
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor:after {
+ border-left: 0;
+}
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor {
+ top: 0;
+}
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor:before,
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor:after {
+ border-right: 0;
+}
+.oo-ui-popupWidget-head {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-popupWidget-head > .oo-ui-buttonWidget {
+ position: absolute;
+}
+.oo-ui-popupWidget-head > .oo-ui-labelElement-label {
+ float: left;
+ cursor: default;
+}
+.oo-ui-popupWidget-body {
+ clear: both;
+}
+.oo-ui-popupWidget-body.oo-ui-clippableElement-clippable {
+ min-height: 1em;
+}
+.oo-ui-popupWidget-popup {
+ background-color: #fff;
+ border: 1px solid #ccc;
+ border-radius: 0.25em;
+ box-shadow: 0 0.15em 0.5em 0 rgba(0, 0, 0, 0.2);
+}
+.oo-ui-popupWidget-anchored-top {
+ margin-top: 6px;
+}
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor {
+ top: -6px;
+}
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor:before {
+ bottom: -7px;
+ left: -6px;
+ border-bottom-color: #aaa;
+ border-width: 7px;
+}
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor:after {
+ bottom: -7px;
+ left: -5px;
+ border-bottom-color: #fff;
+ border-width: 6px;
+}
+.oo-ui-popupWidget-anchored-bottom {
+ margin-bottom: 6px;
+}
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor {
+ bottom: -6px;
+}
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor:before {
+ top: -7px;
+ left: -6px;
+ border-top-color: #aaa;
+ border-width: 7px;
+}
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor:after {
+ top: -7px;
+ left: -5px;
+ border-top-color: #fff;
+ border-width: 6px;
+}
+.oo-ui-popupWidget-anchored-start {
+ margin-left: 6px;
+}
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor {
+ left: -6px;
+}
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor:before {
+ right: -7px;
+ top: -6px;
+ border-right-color: #aaa;
+ border-width: 7px;
+}
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor:after {
+ right: -7px;
+ top: -5px;
+ border-right-color: #fff;
+ border-width: 6px;
+}
+.oo-ui-popupWidget-anchored-end {
+ margin-right: 6px;
+}
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor {
+ right: -6px;
+}
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor:before {
+ left: -7px;
+ top: -6px;
+ border-left-color: #aaa;
+ border-width: 7px;
+}
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor:after {
+ left: -7px;
+ top: -5px;
+ border-left-color: #fff;
+ border-width: 6px;
+}
+.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
+ -webkit-transition: width 100ms ease, height 100ms ease, left 100ms ease;
+ -moz-transition: width 100ms ease, height 100ms ease, left 100ms ease;
+ transition: width 100ms ease, height 100ms ease, left 100ms ease;
+}
+.oo-ui-popupWidget-head {
+ height: 2.5em;
+}
+.oo-ui-popupWidget-head > .oo-ui-buttonWidget {
+ top: 0.25em;
+ right: 0.25em;
+}
+.oo-ui-popupWidget-head > .oo-ui-labelElement-label {
+ margin: 0.75em 2.125em 0.75em 1em;
+}
+.oo-ui-popupWidget-body {
+ line-height: 1.4;
+}
+.oo-ui-popupWidget-body-padded {
+ margin: 0.75em 1em;
+}
+.oo-ui-popupButtonWidget {
+ position: relative;
+}
+.oo-ui-popupButtonWidget .oo-ui-popupWidget {
+ cursor: auto;
+}
+.oo-ui-inputWidget {
+ margin-right: 0.5em;
+}
+.oo-ui-inputWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonInputWidget > button,
+.oo-ui-buttonInputWidget > input {
+ background-color: transparent;
+ margin: 0;
+ border: 0;
+ padding: 0;
+}
+.oo-ui-checkboxMultiselectInputWidget .oo-ui-fieldLayout {
+ margin-bottom: 0;
+}
+.oo-ui-dropdownInputWidget {
+ position: relative;
+ vertical-align: middle;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ max-width: 50em;
+}
+.oo-ui-dropdownInputWidget .oo-ui-dropdownWidget,
+.oo-ui-dropdownInputWidget select {
+ display: block;
+}
+.oo-ui-dropdownInputWidget select {
+ background-position: -9999em 0;
+ background-repeat: no-repeat;
+ width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-enabled select {
+ cursor: pointer;
+}
+.oo-ui-dropdownInputWidget select {
+ background-color: #fff;
+ height: 2.5em;
+ padding: 0.5em;
+ font-size: inherit;
+ font-family: inherit;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ border-radius: 0.25em;
+}
+.oo-ui-dropdownInputWidget option {
+ font-size: inherit;
+ font-family: inherit;
+ height: 1.5em;
+ padding: 0.5em 1em;
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-enabled select:hover {
+ border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-enabled select:focus {
+ outline: 0;
+ border-color: #ace;
+ box-shadow: 0 0 2px 2px #ace;
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-disabled select {
+ color: #ccc;
+ border-color: #ddd;
+ background-color: #f3f3f3;
+}
+.oo-ui-radioSelectInputWidget .oo-ui-fieldLayout {
+ margin-bottom: 0;
+}
+.oo-ui-textInputWidget {
+ position: relative;
+ vertical-align: middle;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ max-width: 50em;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+ display: block;
+ width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-textInputWidget textarea {
+ overflow: auto;
+ resize: none;
+}
+.oo-ui-textInputWidget [type='number'] {
+ -moz-appearance: textfield;
+}
+.oo-ui-textInputWidget [type='number']::-webkit-outer-spin-button,
+.oo-ui-textInputWidget [type='number']::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+.oo-ui-textInputWidget [type='search'] {
+ -webkit-appearance: none;
+}
+.oo-ui-textInputWidget [type='search']::-ms-clear {
+ display: none;
+}
+.oo-ui-textInputWidget [type='search']::-webkit-search-decoration,
+.oo-ui-textInputWidget [type='search']::-webkit-search-cancel-button {
+ display: none;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget > .oo-ui-labelElement-label {
+ display: none;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-indicatorElement > .oo-ui-indicatorElement-indicator {
+ display: block;
+ position: absolute;
+ top: 0;
+ height: 100%;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator {
+ cursor: text;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-textInputWidget-type-search > .oo-ui-indicatorElement-indicator {
+ cursor: pointer;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled input,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea,
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-labelElement-label {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-textInputWidget.oo-ui-labelElement > .oo-ui-labelElement-label {
+ display: block;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget-labelPosition-before > .oo-ui-labelElement-label {
+ left: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget-labelPosition-after > .oo-ui-labelElement-label {
+ right: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-labelElement-label {
+ position: absolute;
+ top: 0;
+}
+.oo-ui-textInputWidget-php > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget-php > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget-php > .oo-ui-labelElement-label {
+ pointer-events: none;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+ padding: 0.546875em 0.5em 0.625em 0.5em;
+ font-size: inherit;
+ font-family: inherit;
+ background-color: #fff;
+ color: #000;
+ border: 1px solid #ccc;
+ box-shadow: 0 0 0 #fff, inset 0 0.1em 0.2em #ddd;
+ border-radius: 0.25em;
+ -webkit-transition: border-color 250ms ease, box-shadow 250ms ease;
+ -moz-transition: border-color 250ms ease, box-shadow 250ms ease;
+ transition: border-color 250ms ease, box-shadow 250ms ease;
+}
+.oo-ui-textInputWidget input.oo-ui-pendingElement-pending,
+.oo-ui-textInputWidget textarea.oo-ui-pendingElement-pending {
+ background-color: transparent;
+}
+.oo-ui-textInputWidget input::-webkit-input-placeholder,
+.oo-ui-textInputWidget textarea::-webkit-input-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-textInputWidget input:-ms-input-placeholder,
+.oo-ui-textInputWidget textarea:-ms-input-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-textInputWidget input::-moz-placeholder,
+.oo-ui-textInputWidget textarea::-moz-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-textInputWidget input:-moz-placeholder,
+.oo-ui-textInputWidget textarea:-moz-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-textInputWidget input::placeholder,
+.oo-ui-textInputWidget textarea::placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-textInputWidget input {
+ line-height: 1.172em;
+}
+.oo-ui-textInputWidget textarea {
+ line-height: 1.275;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input:focus,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea:focus {
+ outline: 0;
+ border-color: #ace;
+ box-shadow: 0 0 2px 2px #ace;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input[readonly],
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea[readonly] {
+ color: #767676;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid input,
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid textarea {
+ background-color: #fdd;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled input,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea {
+ color: #ccc;
+ text-shadow: 0 1px 1px #fff;
+ border-color: #ddd;
+ background-color: #f3f3f3;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-labelElement-label {
+ color: #ddd;
+ text-shadow: 0 1px 1px #fff;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement input,
+.oo-ui-textInputWidget.oo-ui-iconElement textarea {
+ padding-left: 2.475em;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+ max-height: 2.5em;
+ margin-left: 0.3em;
+}
+.oo-ui-textInputWidget.oo-ui-indicatorElement input,
+.oo-ui-textInputWidget.oo-ui-indicatorElement textarea {
+ padding-right: 2.4875em;
+}
+.oo-ui-textInputWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ max-height: 2.5em;
+ margin-right: 0.775em;
+}
+.oo-ui-textInputWidget > .oo-ui-labelElement-label {
+ top: 1px;
+ padding: 0.546875em 0.4em 0.625em 0.4em;
+ line-height: 1.172em;
+ color: #767676;
+}
+.oo-ui-textInputWidget-labelPosition-after.oo-ui-indicatorElement > .oo-ui-labelElement-label {
+ margin-right: 2.0875em;
+}
+.oo-ui-textInputWidget-labelPosition-before.oo-ui-iconElement > .oo-ui-labelElement-label {
+ margin-left: 2.075em;
+}
+.oo-ui-menuSelectWidget {
+ position: absolute;
+ width: 100%;
+ z-index: 4;
+ background-color: #fff;
+ margin-top: -1px;
+ border: 1px solid #ccc;
+ border-radius: 0 0 0.25em 0.25em;
+ box-shadow: 0 0.15em 1em 0 rgba(0, 0, 0, 0.2);
+}
+.oo-ui-menuSelectWidget.oo-ui-clippableElement-clippable {
+ min-height: 2.6em;
+}
+.oo-ui-menuSelectWidget-invisible {
+ display: none;
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-selected {
+ background-color: transparent;
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-selected > .oo-ui-iconElement-icon {
+ background-image: url('themes/apex/images/icons/check.png');
+ background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url('themes/apex/images/icons/check.svg');
+ background-image: linear-gradient(transparent, transparent), /* @embed */ url('themes/apex/images/icons/check.svg');
+ background-image: -o-linear-gradient(transparent, transparent), url('themes/apex/images/icons/check.png');
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: contain;
+ display: block;
+ left: 0.5em;
+ top: 0;
+ min-width: 24px;
+ width: 1.875em;
+ min-height: 24px;
+ height: 100%;
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-highlighted,
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-highlighted.oo-ui-optionWidget-selected {
+ background-color: #e1f3ff;
+}
+.oo-ui-menuSectionOptionWidget {
+ padding: 0.33em 0.75em;
+ color: #767676;
+}
+.oo-ui-menuSectionOptionWidget.oo-ui-widget-enabled {
+ cursor: default;
+}
+.oo-ui-dropdownWidget {
+ display: inline-block;
+ position: relative;
+ width: 100%;
+ max-width: 50em;
+ background-color: #fff;
+ margin-right: 0.5em;
+}
+.oo-ui-dropdownWidget-handle {
+ position: relative;
+ width: 100%;
+ display: block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ cursor: default;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon,
+.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator {
+ position: absolute;
+ top: 0;
+ height: 100%;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle {
+ cursor: pointer;
+}
+.oo-ui-dropdownWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-dropdownWidget-handle {
+ height: 2.5em;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ border-radius: 0.25em;
+}
+.oo-ui-dropdownWidget-handle:hover {
+ border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-dropdownWidget-handle:focus {
+ outline: 0;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon {
+ left: 0.25em;
+ margin: 0 0.3em;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-labelElement-label {
+ line-height: 2.5em;
+ margin: 0 0.5em;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator {
+ right: 0;
+ margin: 0 0.775em;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle:focus {
+ border-color: #ace;
+ box-shadow: 0 0 2px 2px #ace;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle {
+ color: #ccc;
+ text-shadow: 0 1px 1px #fff;
+ border-color: #ddd;
+ background-color: #f3f3f3;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-dropdownWidget.oo-ui-iconElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label {
+ margin-left: 3em;
+}
+.oo-ui-dropdownWidget.oo-ui-indicatorElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label {
+ margin-right: 2em;
+}
+.oo-ui-comboBoxInputWidget {
+ display: inline-block;
+ position: relative;
+ width: 100%;
+ max-width: 50em;
+ margin-right: 0.5em;
+}
+.oo-ui-comboBoxInputWidget-field {
+ display: table;
+ width: 100%;
+ table-layout: fixed;
+}
+.oo-ui-comboBoxInputWidget .oo-ui-inputWidget-input {
+ display: table-cell;
+ vertical-align: middle;
+ position: relative;
+ overflow: hidden;
+}
+.oo-ui-comboBoxInputWidget-dropdownButton {
+ display: table-cell;
+}
+.oo-ui-comboBoxInputWidget-dropdownButton > .oo-ui-buttonElement-button {
+ display: block;
+ overflow: hidden;
+}
+.oo-ui-comboBoxInputWidget.oo-ui-comboBoxInputWidget-empty .oo-ui-comboBoxInputWidget-dropdownButton {
+ display: none;
+}
+.oo-ui-comboBoxInputWidget-php ::-webkit-calendar-picker-indicator {
+ opacity: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: 2.5em;
+ height: 2.5em;
+ padding: 0;
+}
+.oo-ui-comboBoxInputWidget-php > .oo-ui-indicatorWidget {
+ display: block;
+ position: absolute;
+ top: 0;
+ height: 100%;
+ pointer-events: none;
+}
+.oo-ui-comboBoxInputWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-comboBoxInputWidget-dropdownButton {
+ position: absolute;
+ top: 0;
+ right: 0;
+ visibility: hidden;
+}
+.oo-ui-comboBoxInputWidget-dropdownButton .oo-ui-buttonElement-button {
+ padding: 0;
+}
+.oo-ui-comboBoxInputWidget-dropdownButton .oo-ui-buttonElement-button .oo-ui-indicatorElement-indicator.oo-ui-indicator-down {
+ visibility: visible;
+ margin: 0.775em;
+}
+.oo-ui-comboBoxInputWidget-php .oo-ui-indicatorWidget {
+ right: 0;
+ max-height: 2.5em;
+ margin: 0;
+ margin-right: 0.775em;
+}
+.oo-ui-comboBoxInputWidget.oo-ui-widget-disabled .oo-ui-textInputWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ cursor: default;
+ opacity: 0.2;
+}
+.oo-ui-multioptionWidget {
+ position: relative;
+ display: block;
+}
+.oo-ui-multioptionWidget.oo-ui-widget-enabled {
+ cursor: pointer;
+}
+.oo-ui-multioptionWidget.oo-ui-widget-disabled {
+ cursor: default;
+}
+.oo-ui-multioptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: block;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.oo-ui-multioptionWidget .oo-ui-labelElement-label {
+ line-height: 1.5em;
+}
+.oo-ui-multioptionWidget.oo-ui-widget-disabled {
+ color: #ccc;
+}
+.oo-ui-checkboxMultioptionWidget {
+ padding: 0;
+}
+.oo-ui-checkboxMultioptionWidget .oo-ui-checkboxInputWidget,
+.oo-ui-checkboxMultioptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-checkboxMultioptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ padding-left: 0.5em;
+}
+.oo-ui-checkboxMultioptionWidget .oo-ui-checkboxInputWidget {
+ margin-right: 0;
+}
+.oo-ui-progressBarWidget {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ max-width: 50em;
+ background-color: #fff;
+ border: 1px solid #ccc;
+ border-radius: 0.25em;
+ overflow: hidden;
+}
+.oo-ui-progressBarWidget-bar {
+ height: 1em;
+ border-right: 1px solid #ccc;
+ -webkit-transition: width 250ms ease;
+ -moz-transition: width 250ms ease;
+ transition: width 250ms ease;
+ background-color: #cde7f4;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #eaf4fa), color-stop(100%, #b0d9ee));
+ background-image: -webkit-linear-gradient(top, #eaf4fa 0, #b0d9ee 100%);
+ background-image: -moz-linear-gradient(top, #eaf4fa 0, #b0d9ee 100%);
+ background-image: linear-gradient(to bottom, #eaf4fa 0, #b0d9ee 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffeaf4fa', endColorstr='#ffb0d9ee' )";
+}
+.oo-ui-progressBarWidget-indeterminate .oo-ui-progressBarWidget-bar {
+ -webkit-animation: oo-ui-progressBarWidget-slide 2s infinite linear;
+ -moz-animation: oo-ui-progressBarWidget-slide 2s infinite linear;
+ animation: oo-ui-progressBarWidget-slide 2s infinite linear;
+ width: 40%;
+ -webkit-transform: translate(-25%);
+ -moz-transform: translate(-25%);
+ -ms-transform: translate(-25%);
+ transform: translate(-25%);
+ border-left: 1px solid #a6cee1;
+}
+.oo-ui-progressBarWidget.oo-ui-widget-disabled {
+ opacity: 0.6;
+}
+@-webkit-keyframes oo-ui-progressBarWidget-slide {
+ from {
+ -webkit-transform: translate(-100%);
+ -moz-transform: translate(-100%);
+ -ms-transform: translate(-100%);
+ transform: translate(-100%);
+ }
+ to {
+ -webkit-transform: translate(350%);
+ -moz-transform: translate(350%);
+ -ms-transform: translate(350%);
+ transform: translate(350%);
+ }
+}
+@-moz-keyframes oo-ui-progressBarWidget-slide {
+ from {
+ -webkit-transform: translate(-100%);
+ -moz-transform: translate(-100%);
+ -ms-transform: translate(-100%);
+ transform: translate(-100%);
+ }
+ to {
+ -webkit-transform: translate(350%);
+ -moz-transform: translate(350%);
+ -ms-transform: translate(350%);
+ transform: translate(350%);
+ }
+}
+@keyframes oo-ui-progressBarWidget-slide {
+ from {
+ -webkit-transform: translate(-100%);
+ -moz-transform: translate(-100%);
+ -ms-transform: translate(-100%);
+ transform: translate(-100%);
+ }
+ to {
+ -webkit-transform: translate(350%);
+ -moz-transform: translate(350%);
+ -ms-transform: translate(350%);
+ transform: translate(350%);
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-core-mediawiki.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-core-mediawiki.css
new file mode 100644
index 00000000..268a6802
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-core-mediawiki.css
@@ -0,0 +1,1350 @@
+/*!
+ * OOjs UI v0.17.1
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2016 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2016-05-03T22:58:06Z
+ */
+.oo-ui-element-hidden {
+ display: none !important;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+ cursor: pointer;
+ display: inline-block;
+ vertical-align: middle;
+ font: inherit;
+ white-space: nowrap;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ display: none;
+}
+.oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ cursor: default;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-buttonElement-frameless {
+ display: inline-block;
+ position: relative;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
+ vertical-align: top;
+ text-align: center;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ cursor: default;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+ font-weight: bold;
+ text-decoration: none;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button:focus {
+ outline: 0;
+}
+.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ margin-left: 0;
+}
+.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ margin-left: 0.46875em;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button:focus {
+ box-shadow: inset 0 0 0 1px #347bff, 0 0 0 1px #347bff;
+}
+.oo-ui-buttonElement-frameless > .oo-ui-buttonElement-button .oo-ui-indicatorElement-indicator {
+ margin-right: 0;
+}
+.oo-ui-buttonElement-frameless.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ margin-left: 0.25em;
+ margin-right: 0.25em;
+}
+.oo-ui-buttonElement-frameless > input.oo-ui-buttonElement-button {
+ padding-left: 0.25em;
+ padding-right: 0.25em;
+ color: #333333;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled > input.oo-ui-buttonElement-button,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #555555;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > input.oo-ui-buttonElement-button,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #444444;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #347bff;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label {
+ color: #2962cc;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active > .oo-ui-labelElement-label,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #1f4999;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #347bff;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label {
+ color: #2962cc;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active > .oo-ui-labelElement-label,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #1f4999;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #d11d13;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover > .oo-ui-labelElement-label {
+ color: #8c130d;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active > .oo-ui-labelElement-label,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ color: #73100a;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ color: #cccccc;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button:focus {
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-labelElement > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button {
+ padding-left: 2.4em;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
+ padding: 0.5em 1em;
+ min-height: 1.2em;
+ min-width: 1em;
+ border-radius: 2px;
+ position: relative;
+ -webkit-transition: background 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+ -moz-transition: background 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+ transition: background 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+}
+.oo-ui-buttonElement-framed > input.oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ line-height: 1.2em;
+}
+.oo-ui-buttonElement-framed.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ position: absolute;
+ top: 0.2em;
+ left: 0.5625em;
+}
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ margin-left: 0.3em;
+}
+.oo-ui-buttonElement-framed.oo-ui-indicatorElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement-framed.oo-ui-indicatorElement.oo-ui-iconElement:not( .oo-ui-labelElement ) > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ margin-left: 0.46875em;
+ margin-right: -0.275em;
+}
+.oo-ui-buttonElement-framed.oo-ui-indicatorElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ position: relative;
+ left: 0.2em;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ background-color: #dddddd;
+ color: #ffffff;
+ border: 1px solid #dddddd;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button {
+ color: #555555;
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover {
+ background-color: #ebebeb;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+ border-color: #347bff;
+ box-shadow: inset 0 0 0 1px #347bff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ background-color: #d9d9d9;
+ border-color: #d9d9d9;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ background-color: #999999;
+ color: #ffffff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button {
+ color: #347bff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover {
+ background-color: #ebf2ff;
+ border-color: #859dcc;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ color: #1f4999;
+ border-color: #1f4999;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ background-color: #999999;
+ color: #ffffff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+ border-color: #347bff;
+ box-shadow: inset 0 0 0 1px #347bff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
+ color: #347bff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover {
+ background-color: #ebf2ff;
+ border-color: #859dcc;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ color: #1f4999;
+ border-color: #1f4999;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ background-color: #999999;
+ color: #ffffff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+ border-color: #347bff;
+ box-shadow: inset 0 0 0 1px #347bff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
+ color: #d11d13;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover {
+ background-color: #fbe8e7;
+ border-color: #b77c79;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ color: #73100a;
+ border-color: #73100a;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ background-color: #999999;
+ color: #ffffff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+ border-color: #d11d13;
+ box-shadow: inset 0 0 0 1px #d11d13;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button {
+ color: #ffffff;
+ background-color: #347bff;
+ border-color: #347bff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover {
+ background-color: #2962cc;
+ border-color: #2962cc;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ color: #ffffff;
+ background-color: #1f4999;
+ border-color: #1f4999;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ background-color: #999999;
+ color: #ffffff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+ border-color: #347bff;
+ box-shadow: inset 0 0 0 1px #ffffff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
+ color: #ffffff;
+ background-color: #347bff;
+ border-color: #347bff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover {
+ background-color: #2962cc;
+ border-color: #2962cc;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ color: #ffffff;
+ background-color: #1f4999;
+ border-color: #1f4999;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ background-color: #999999;
+ color: #ffffff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+ border-color: #347bff;
+ box-shadow: inset 0 0 0 1px #ffffff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
+ color: #ffffff;
+ background-color: #d11d13;
+ border-color: #d11d13;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover {
+ background-color: #8c130d;
+ border-color: #8c130d;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ color: #ffffff;
+ background-color: #73100a;
+ border-color: #73100a;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ background-color: #999999;
+ color: #ffffff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+ border-color: #d11d13;
+ box-shadow: inset 0 0 0 1px #ffffff;
+}
+.oo-ui-clippableElement-clippable {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-floatableElement-hidden {
+ display: none;
+}
+.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-iconElement.oo-ui-iconElement-icon {
+ background-size: contain;
+ background-position: center center;
+ background-repeat: no-repeat;
+ min-width: 24px;
+ width: 1.875em;
+ min-height: 24px;
+ height: 1.875em;
+}
+.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator,
+.oo-ui-indicatorElement.oo-ui-indicatorElement-indicator {
+ background-size: contain;
+ background-position: center center;
+ background-repeat: no-repeat;
+ min-width: 12px;
+ width: 0.9375em;
+ min-height: 12px;
+ height: 0.9375em;
+}
+.oo-ui-labelElement .oo-ui-labelElement-label-highlight {
+ font-weight: bold;
+}
+.oo-ui-pendingElement-pending {
+ background-image: /* @embed */ url(themes/mediawiki/images/textures/pending.gif);
+}
+.oo-ui-fieldLayout {
+ display: block;
+ margin-bottom: 1em;
+}
+.oo-ui-fieldLayout:before,
+.oo-ui-fieldLayout:after {
+ content: " ";
+ display: table;
+}
+.oo-ui-fieldLayout:after {
+ clear: both;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ display: block;
+ float: left;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
+ text-align: right;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body {
+ display: table;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ display: table-cell;
+ vertical-align: middle;
+}
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
+ display: inline-block;
+}
+.oo-ui-fieldLayout > .oo-ui-fieldLayout-help {
+ float: right;
+}
+.oo-ui-fieldLayout > .oo-ui-fieldLayout-help > .oo-ui-popupWidget > .oo-ui-popupWidget-popup {
+ z-index: 1;
+}
+.oo-ui-fieldLayout > .oo-ui-fieldLayout-help .oo-ui-fieldLayout-help-content {
+ padding: 0.5em 0.75em;
+ line-height: 1.5em;
+}
+.oo-ui-fieldLayout:last-child {
+ margin-bottom: 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
+ padding-top: 0.5em;
+ margin-right: 5%;
+ width: 35%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ width: 60%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline {
+ margin-bottom: 1.25em;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
+ padding: 0.25em 0.25em 0.25em 1em;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
+ padding-top: 0.25em;
+ padding-bottom: 0.5em;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget {
+ margin-right: 0;
+}
+.oo-ui-fieldLayout > .oo-ui-popupButtonWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-fieldLayout-disabled > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
+ color: #cccccc;
+}
+.oo-ui-fieldLayout-messages {
+ list-style: none none;
+ margin: 0.25em 0 0 0.25em;
+ padding: 0;
+}
+.oo-ui-fieldLayout-messages > li {
+ margin: 0;
+ padding: 0;
+ display: table;
+}
+.oo-ui-fieldLayout-messages .oo-ui-iconWidget {
+ display: table-cell;
+ border-right: 0.5em solid transparent;
+}
+.oo-ui-fieldLayout-messages .oo-ui-labelWidget {
+ display: table-cell;
+ padding: 0;
+ line-height: 1.875em;
+ vertical-align: middle;
+}
+.oo-ui-actionFieldLayout {
+ max-width: 50em;
+}
+.oo-ui-actionFieldLayout-input,
+.oo-ui-actionFieldLayout-button {
+ display: table-cell;
+ vertical-align: middle;
+}
+.oo-ui-actionFieldLayout-input {
+ padding-right: 1em;
+}
+.oo-ui-actionFieldLayout-button {
+ width: 1%;
+ white-space: nowrap;
+}
+.oo-ui-fieldsetLayout {
+ position: relative;
+ margin: 0;
+ padding: 0;
+ border: 0;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-iconElement-icon {
+ display: block;
+ position: absolute;
+}
+.oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-labelElement-label {
+ display: inline-block;
+}
+.oo-ui-fieldsetLayout > .oo-ui-fieldsetLayout-help {
+ float: right;
+}
+.oo-ui-fieldsetLayout > .oo-ui-fieldsetLayout-help > .oo-ui-popupWidget > .oo-ui-popupWidget-popup {
+ z-index: 1;
+}
+.oo-ui-fieldsetLayout > .oo-ui-fieldsetLayout-help .oo-ui-fieldsetLayout-help-content {
+ padding: 0.5em 0.75em;
+ line-height: 1.5em;
+}
+.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout,
+.oo-ui-fieldsetLayout + .oo-ui-formLayout {
+ margin-top: 2em;
+}
+.oo-ui-fieldsetLayout > .oo-ui-labelElement-label {
+ font-size: 1.1em;
+ margin-bottom: 0.5em;
+ padding: 0.25em 0;
+ font-weight: bold;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-labelElement-label {
+ padding-left: 2em;
+ line-height: 1.8em;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-iconElement-icon {
+ left: 0;
+ top: 0.25em;
+}
+.oo-ui-fieldsetLayout > .oo-ui-popupButtonWidget {
+ margin-right: 0;
+}
+.oo-ui-fieldsetLayout > .oo-ui-popupButtonWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-formLayout + .oo-ui-fieldsetLayout,
+.oo-ui-formLayout + .oo-ui-formLayout {
+ margin-top: 2em;
+}
+.oo-ui-panelLayout {
+ position: relative;
+}
+.oo-ui-panelLayout-scrollable {
+ overflow-y: auto;
+}
+.oo-ui-panelLayout-expanded {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-panelLayout-padded {
+ padding: 1.25em;
+}
+.oo-ui-panelLayout-framed {
+ border: 1px solid #aaaaaa;
+ border-radius: 2px;
+ box-shadow: 0 0.15em 0 0 rgba(0, 0, 0, 0.15);
+}
+.oo-ui-panelLayout-padded.oo-ui-panelLayout-framed {
+ margin: 1em 0;
+}
+.oo-ui-horizontalLayout > .oo-ui-widget {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout {
+ display: inline-block;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout,
+.oo-ui-horizontalLayout > .oo-ui-widget {
+ margin-right: 0.5em;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout:last-child,
+.oo-ui-horizontalLayout > .oo-ui-widget:last-child {
+ margin-right: 0;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout {
+ margin-bottom: 0;
+}
+.oo-ui-optionWidget {
+ position: relative;
+ display: block;
+ padding: 0.25em 0.5em;
+ border: 0;
+}
+.oo-ui-optionWidget.oo-ui-widget-enabled {
+ cursor: pointer;
+}
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+ cursor: default;
+}
+.oo-ui-optionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: block;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.oo-ui-optionWidget-highlighted {
+ background-color: #eeeeee;
+}
+.oo-ui-optionWidget .oo-ui-labelElement-label {
+ line-height: 1.5em;
+}
+.oo-ui-selectWidget-depressed .oo-ui-optionWidget-selected,
+.oo-ui-selectWidget-pressed .oo-ui-optionWidget-pressed,
+.oo-ui-selectWidget-pressed .oo-ui-optionWidget-pressed.oo-ui-optionWidget-highlighted,
+.oo-ui-selectWidget-pressed .oo-ui-optionWidget-pressed.oo-ui-optionWidget-highlighted.oo-ui-optionWidget-selected {
+ background-color: #d0d0d0;
+}
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+ color: #cccccc;
+}
+.oo-ui-decoratedOptionWidget {
+ padding: 0.5em 2em 0.5em 3em;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget .oo-ui-indicatorElement-indicator {
+ position: absolute;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ top: 0;
+ height: 100%;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+ left: 0.5em;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ right: 0.5em;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-widget-disabled .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-radioSelectWidget:focus {
+ outline: 0;
+}
+.oo-ui-radioSelectWidget:focus .oo-ui-radioOptionWidget.oo-ui-optionWidget-selected .oo-ui-radioInputWidget [type="radio"] + span {
+ border-width: 2px;
+}
+.oo-ui-radioOptionWidget {
+ cursor: default;
+ padding: 0.25em 0;
+ background-color: transparent;
+}
+.oo-ui-radioOptionWidget .oo-ui-radioInputWidget,
+.oo-ui-radioOptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-radioOptionWidget.oo-ui-optionWidget-selected,
+.oo-ui-radioOptionWidget.oo-ui-optionWidget-pressed,
+.oo-ui-radioOptionWidget.oo-ui-optionWidget-highlighted {
+ background-color: transparent;
+}
+.oo-ui-radioOptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ padding: 0.25em 0.25em 0.25em 1em;
+}
+.oo-ui-radioOptionWidget .oo-ui-radioInputWidget {
+ margin-right: 0;
+}
+.oo-ui-labelWidget {
+ display: inline-block;
+}
+.oo-ui-iconWidget {
+ display: inline-block;
+ vertical-align: middle;
+ line-height: 2.5em;
+}
+.oo-ui-iconWidget.oo-ui-widget-disabled {
+ opacity: 0.2;
+}
+.oo-ui-indicatorWidget {
+ display: inline-block;
+ vertical-align: middle;
+ line-height: 2.5em;
+ margin: 0.46875em;
+}
+.oo-ui-indicatorWidget.oo-ui-widget-disabled {
+ opacity: 0.2;
+}
+.oo-ui-buttonWidget {
+ display: inline-block;
+ vertical-align: middle;
+ margin-right: 0.5em;
+}
+.oo-ui-buttonWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonGroupWidget {
+ display: inline-block;
+ white-space: nowrap;
+ border-radius: 2px;
+ margin-right: 0.5em;
+}
+.oo-ui-buttonGroupWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement {
+ margin-right: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+ border-radius: 0;
+ margin-left: -1px;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed .oo-ui-buttonElement-button:focus {
+ z-index: 2;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:first-child .oo-ui-buttonElement-button {
+ border-bottom-left-radius: 2px;
+ border-top-left-radius: 2px;
+ margin-left: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:last-child .oo-ui-buttonElement-button {
+ border-bottom-right-radius: 2px;
+ border-top-right-radius: 2px;
+}
+.oo-ui-popupWidget {
+ position: absolute;
+ /* @noflip */
+ left: 0;
+}
+.oo-ui-popupWidget-popup {
+ position: relative;
+ overflow: hidden;
+ z-index: 1;
+}
+.oo-ui-popupWidget-anchor {
+ display: none;
+ z-index: 1;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor {
+ display: block;
+ position: absolute;
+ top: 0;
+ /* @noflip */
+ left: 0;
+ background-repeat: no-repeat;
+}
+.oo-ui-popupWidget-head {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-popupWidget-head > .oo-ui-buttonWidget {
+ float: right;
+}
+.oo-ui-popupWidget-head > .oo-ui-labelElement-label {
+ float: left;
+ cursor: default;
+}
+.oo-ui-popupWidget-body {
+ clear: both;
+ overflow: hidden;
+}
+.oo-ui-popupWidget-popup {
+ background-color: #ffffff;
+ border: 1px solid #aaaaaa;
+ border-radius: 2px;
+ box-shadow: 0 0.15em 0 0 rgba(0, 0, 0, 0.15);
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-popup {
+ margin-top: 9px;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:before,
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:after {
+ content: "";
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-style: solid;
+ border-color: transparent;
+ border-top: 0;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:before {
+ bottom: -10px;
+ left: -9px;
+ border-bottom-color: #888888;
+ border-width: 10px;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:after {
+ bottom: -10px;
+ left: -8px;
+ border-bottom-color: #ffffff;
+ border-width: 9px;
+}
+.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
+ -webkit-transition: width 100ms, height 100ms, left 100ms;
+ -moz-transition: width 100ms, height 100ms, left 100ms;
+ transition: width 100ms, height 100ms, left 100ms;
+}
+.oo-ui-popupWidget-head {
+ height: 2.5em;
+}
+.oo-ui-popupWidget-head > .oo-ui-buttonWidget {
+ margin: 0.25em;
+}
+.oo-ui-popupWidget-head > .oo-ui-labelElement-label {
+ margin: 0.75em 1em;
+}
+.oo-ui-popupWidget-body-padded {
+ padding: 0 1em;
+}
+.oo-ui-popupButtonWidget {
+ position: relative;
+}
+.oo-ui-popupButtonWidget .oo-ui-popupWidget {
+ position: absolute;
+ cursor: auto;
+}
+.oo-ui-popupButtonWidget.oo-ui-buttonElement-frameless > .oo-ui-popupWidget {
+ /* @noflip */
+ left: 0.9375em;
+}
+.oo-ui-popupButtonWidget.oo-ui-buttonElement-framed > .oo-ui-popupWidget {
+ /* @noflip */
+ left: 1.5em;
+}
+.oo-ui-inputWidget {
+ margin-right: 0.5em;
+}
+.oo-ui-inputWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonInputWidget {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-buttonInputWidget > button,
+.oo-ui-buttonInputWidget > input {
+ border: 0;
+ padding: 0;
+ background-color: transparent;
+}
+.oo-ui-checkboxInputWidget {
+ position: relative;
+ line-height: 1.6em;
+ white-space: nowrap;
+}
+.oo-ui-checkboxInputWidget * {
+ font: inherit;
+ vertical-align: middle;
+}
+.oo-ui-checkboxInputWidget [type="checkbox"] {
+ opacity: 0;
+ z-index: 1;
+ position: relative;
+ cursor: pointer;
+ margin: 0;
+ width: 1.6em;
+ height: 1.6em;
+ max-width: none;
+}
+.oo-ui-checkboxInputWidget [type="checkbox"] + span {
+ -webkit-transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ -moz-transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ position: absolute;
+ left: 0;
+ width: 1.6em;
+ height: 1.6em;
+ background-color: #ffffff;
+ background-image: url("themes/mediawiki/images/icons/check-constructive-deprecated.png");
+ background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check-constructive-deprecated.svg");
+ background-image: linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check-constructive-deprecated.svg");
+ background-image: -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/check-constructive-deprecated.png");
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-origin: border-box;
+ background-size: 0 0;
+ border: 1px solid #777777;
+ border-radius: 2px;
+}
+.oo-ui-checkboxInputWidget [type="checkbox"]:checked + span {
+ background-size: 100% 100%;
+}
+.oo-ui-checkboxInputWidget [type="checkbox"]:active + span {
+ background-color: #cccccc;
+ border-color: #cccccc;
+}
+.oo-ui-checkboxInputWidget [type="checkbox"]:focus + span {
+ border-width: 2px;
+}
+.oo-ui-checkboxInputWidget [type="checkbox"]:focus:hover + span,
+.oo-ui-checkboxInputWidget [type="checkbox"]:hover + span {
+ border-bottom-width: 3px;
+}
+.oo-ui-checkboxInputWidget [type="checkbox"]:disabled {
+ cursor: default;
+}
+.oo-ui-checkboxInputWidget [type="checkbox"]:disabled + span {
+ background-color: #dddddd;
+ border-color: #dddddd;
+}
+.oo-ui-checkboxInputWidget [type="checkbox"]:disabled:checked + span {
+ background-image: url("themes/mediawiki/images/icons/check-invert.png");
+ background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check-invert.svg");
+ background-image: linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check-invert.svg");
+ background-image: -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/check-invert.png");
+}
+.oo-ui-dropdownInputWidget {
+ position: relative;
+ vertical-align: middle;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ max-width: 50em;
+}
+.oo-ui-dropdownInputWidget .oo-ui-dropdownWidget,
+.oo-ui-dropdownInputWidget select {
+ display: block;
+}
+.oo-ui-dropdownInputWidget select {
+ width: 100%;
+ cursor: pointer;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-dropdownInputWidget select {
+ background-color: #ffffff;
+ height: 2.275em;
+ font-size: inherit;
+ font-family: inherit;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ border: 1px solid #cccccc;
+ border-radius: 2px;
+ padding-left: 1em;
+ vertical-align: middle;
+}
+.oo-ui-dropdownInputWidget option {
+ font-size: inherit;
+ font-family: inherit;
+ height: 1.5em;
+ padding: 0.5em 1em;
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-enabled select:hover,
+.oo-ui-dropdownInputWidget.oo-ui-widget-enabled select:focus {
+ border-color: #aaaaaa;
+ outline: 0;
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-disabled select {
+ color: #cccccc;
+ border-color: #dddddd;
+ background-color: #f3f3f3;
+}
+.oo-ui-radioInputWidget {
+ position: relative;
+ line-height: 1.6em;
+ white-space: nowrap;
+}
+.oo-ui-radioInputWidget * {
+ font: inherit;
+ vertical-align: middle;
+}
+.oo-ui-radioInputWidget [type="radio"] {
+ opacity: 0;
+ z-index: 1;
+ position: relative;
+ cursor: pointer;
+ margin: 0;
+ width: 1.6em;
+ height: 1.6em;
+ max-width: none;
+}
+.oo-ui-radioInputWidget [type="radio"] + span {
+ -webkit-transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ -moz-transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ transition: background-size 200ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ position: absolute;
+ left: 0;
+ width: 1.6em;
+ height: 1.6em;
+ background-color: #ffffff;
+ background-image: url("themes/mediawiki/images/icons/circle-constructive-deprecated.png");
+ background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/circle-constructive-deprecated.svg");
+ background-image: linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/circle-constructive-deprecated.svg");
+ background-image: -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/circle-constructive-deprecated.png");
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-origin: border-box;
+ background-size: 0 0;
+ border: 1px solid #777777;
+ border-radius: 100%;
+}
+.oo-ui-radioInputWidget [type="radio"]:checked + span {
+ background-size: 100% 100%;
+}
+.oo-ui-radioInputWidget [type="radio"]:active + span {
+ background-color: #cccccc;
+ border-color: #cccccc;
+}
+.oo-ui-radioInputWidget [type="radio"]:focus + span {
+ border-width: 2px;
+}
+.oo-ui-radioInputWidget [type="radio"]:focus:hover + span,
+.oo-ui-radioInputWidget [type="radio"]:hover + span {
+ border-bottom-width: 3px;
+}
+.oo-ui-radioInputWidget [type="radio"]:disabled {
+ cursor: default;
+}
+.oo-ui-radioInputWidget [type="radio"]:disabled + span {
+ background-color: #dddddd;
+ border-color: #dddddd;
+}
+.oo-ui-radioInputWidget [type="radio"]:disabled:checked + span {
+ background-image: url("themes/mediawiki/images/icons/circle-invert.png");
+ background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/circle-invert.svg");
+ background-image: linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/circle-invert.svg");
+ background-image: -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/circle-invert.png");
+}
+.oo-ui-radioSelectInputWidget .oo-ui-fieldLayout {
+ margin-bottom: 0;
+}
+.oo-ui-radioSelectInputWidget .oo-ui-fieldLayout .oo-ui-fieldLayout-body {
+ padding: 0.25em 0;
+}
+.oo-ui-radioSelectInputWidget .oo-ui-fieldLayout .oo-ui-fieldLayout-body .oo-ui-labelElement-label {
+ line-height: 1.5em;
+}
+.oo-ui-textInputWidget {
+ position: relative;
+ vertical-align: middle;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ max-width: 50em;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+ display: block;
+ width: 100%;
+ resize: none;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-textInputWidget textarea {
+ overflow: auto;
+}
+.oo-ui-textInputWidget [type="search"] {
+ -webkit-appearance: textfield;
+}
+.oo-ui-textInputWidget [type="search"]::-ms-clear {
+ display: none;
+}
+.oo-ui-textInputWidget [type="search"]::-webkit-search-decoration,
+.oo-ui-textInputWidget [type="search"]::-webkit-search-cancel-button,
+.oo-ui-textInputWidget [type="search"]::-webkit-search-results-button,
+.oo-ui-textInputWidget [type="search"]::-webkit-search-results-decoration {
+ display: none;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget > .oo-ui-labelElement-label {
+ display: none;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-indicatorElement > .oo-ui-indicatorElement-indicator {
+ display: block;
+ position: absolute;
+ top: 0;
+ height: 100%;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator {
+ cursor: text;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-textInputWidget-type-search > .oo-ui-indicatorElement-indicator {
+ cursor: pointer;
+}
+.oo-ui-textInputWidget.oo-ui-labelElement > .oo-ui-labelElement-label {
+ display: block;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget-labelPosition-before > .oo-ui-labelElement-label {
+ left: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget-labelPosition-after > .oo-ui-labelElement-label {
+ right: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-labelElement-label {
+ position: absolute;
+ top: 0;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+ padding: 0.5em;
+ line-height: 1.275em;
+ margin: 0;
+ font-size: inherit;
+ font-family: inherit;
+ background-color: #ffffff;
+ color: #000000;
+ border: 1px solid #cccccc;
+ border-radius: 2px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-textInputWidget .oo-ui-pendingElement-pending {
+ background-color: transparent;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea {
+ box-shadow: inset 0 0 0 0.1em #ffffff;
+ -webkit-transition: border 200ms cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 200ms cubic-bezier(0.39, 0.575, 0.565, 1);
+ -moz-transition: border 200ms cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 200ms cubic-bezier(0.39, 0.575, 0.565, 1);
+ transition: border 200ms cubic-bezier(0.39, 0.575, 0.565, 1), box-shadow 200ms cubic-bezier(0.39, 0.575, 0.565, 1);
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input:focus,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea:focus {
+ outline: 0;
+ border-color: #347bff;
+ box-shadow: inset 0 0 0 0.1em #347bff;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input[readonly],
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea[readonly] {
+ color: #777777;
+ text-shadow: 0 1px 1px #ffffff;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input[readonly]:focus,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea[readonly]:focus {
+ border-color: #cccccc;
+ box-shadow: inset 0 0 0 0.1em #cccccc;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid input,
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid textarea {
+ border-color: #ff0000;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid input:focus,
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid textarea:focus {
+ border-color: #ff0000;
+ box-shadow: inset 0 0 0 0.1em #ff0000;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled input,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea {
+ color: #cccccc;
+ text-shadow: 0 1px 1px #ffffff;
+ border-color: #dddddd;
+ background-color: #f3f3f3;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-labelElement-label {
+ color: #cccccc;
+ text-shadow: 0 1px 1px #ffffff;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement input,
+.oo-ui-textInputWidget.oo-ui-iconElement textarea {
+ padding-left: 2.875em;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+ left: 0;
+ height: 100%;
+ max-height: 2.375em;
+ margin-left: 0.5em;
+ background-position: right center;
+}
+.oo-ui-textInputWidget.oo-ui-indicatorElement input,
+.oo-ui-textInputWidget.oo-ui-indicatorElement textarea {
+ padding-right: 2.4875em;
+}
+.oo-ui-textInputWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ height: 100%;
+ max-height: 2.375em;
+ margin: 0 0.775em;
+}
+.oo-ui-textInputWidget > .oo-ui-labelElement-label {
+ padding: 0.4em;
+ line-height: 1.5em;
+ color: #888888;
+}
+.oo-ui-textInputWidget-labelPosition-after.oo-ui-indicatorElement > .oo-ui-labelElement-label {
+ margin-right: 2.0875em;
+}
+.oo-ui-textInputWidget-labelPosition-before.oo-ui-iconElement > .oo-ui-labelElement-label {
+ margin-left: 2.475em;
+}
+.oo-ui-menuSelectWidget {
+ position: absolute;
+ background-color: #ffffff;
+ margin-top: -1px;
+ border: 1px solid #aaaaaa;
+ border-radius: 0 0 2px 2px;
+ box-shadow: 0 0.15em 0 0 rgba(0, 0, 0, 0.15);
+}
+.oo-ui-menuSelectWidget input {
+ position: absolute;
+ width: 0;
+ height: 0;
+ overflow: hidden;
+ opacity: 0;
+}
+.oo-ui-menuOptionWidget {
+ position: relative;
+ padding: 0.5em 1em;
+}
+.oo-ui-menuOptionWidget .oo-ui-iconElement-icon {
+ display: none;
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-selected {
+ background-color: transparent;
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-selected .oo-ui-iconElement-icon {
+ display: block;
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-selected {
+ background-color: #d8e6fe;
+ color: rgba(0, 0, 0, 0.8);
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-selected .oo-ui-iconElement-icon {
+ display: none;
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-highlighted {
+ background-color: #eeeeee;
+ color: #000000;
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-selected.oo-ui-menuOptionWidget.oo-ui-optionWidget-highlighted {
+ background-color: #d8e6fe;
+}
+.oo-ui-menuSectionOptionWidget {
+ cursor: default;
+ padding: 0.33em 0.75em;
+ color: #888888;
+}
+.oo-ui-dropdownWidget {
+ display: inline-block;
+ position: relative;
+ width: 100%;
+ max-width: 50em;
+ background-color: #ffffff;
+ margin-right: 0.5em;
+}
+.oo-ui-dropdownWidget-handle {
+ width: 100%;
+ display: block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon {
+ position: absolute;
+}
+.oo-ui-dropdownWidget > .oo-ui-menuSelectWidget {
+ z-index: 1;
+ width: 100%;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle {
+ cursor: pointer;
+}
+.oo-ui-dropdownWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-dropdownWidget-handle {
+ padding: 0.5em 0;
+ height: 2.275em;
+ line-height: 1.275;
+ border: 1px solid #cccccc;
+ border-radius: 2px;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator {
+ right: 0;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon {
+ left: 0.25em;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-labelElement-label {
+ margin: 0 1em;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator {
+ top: 0;
+ margin: 0.775em;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon {
+ top: 0;
+ margin: 0.3em;
+}
+.oo-ui-dropdownWidget:hover .oo-ui-dropdownWidget-handle {
+ border-color: #aaaaaa;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle {
+ color: #cccccc;
+ text-shadow: 0 1px 1px #ffffff;
+ border-color: #dddddd;
+ background-color: #f3f3f3;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle:focus {
+ outline: 0;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-dropdownWidget.oo-ui-iconElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label {
+ margin-left: 3em;
+}
+.oo-ui-dropdownWidget.oo-ui-indicatorElement .oo-ui-dropdownWidget-handle .oo-ui-labelElement-label {
+ margin-right: 2em;
+}
+.oo-ui-comboBoxInputWidget {
+ display: inline-block;
+ position: relative;
+ width: 100%;
+ max-width: 50em;
+ margin-right: 0.5em;
+}
+.oo-ui-comboBoxInputWidget > .oo-ui-menuSelectWidget {
+ z-index: 1;
+ width: 100%;
+}
+.oo-ui-comboBoxInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator {
+ cursor: pointer;
+}
+.oo-ui-comboBoxInputWidget-php input::-webkit-calendar-picker-indicator {
+ opacity: 0 !important;
+ position: absolute;
+ right: 0;
+ top: 0;
+ height: 2.5em;
+ width: 2.5em;
+ padding: 0;
+}
+.oo-ui-comboBoxInputWidget-php > .oo-ui-indicatorElement-indicator {
+ pointer-events: none;
+}
+.oo-ui-comboBoxInputWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-comboBoxInputWidget input,
+.oo-ui-comboBoxInputWidget textarea {
+ height: 2.35em;
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-core-wikimediaui.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-core-wikimediaui.css
new file mode 100644
index 00000000..1b94cbd5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-core-wikimediaui.css
@@ -0,0 +1,1987 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:24:03Z
+ */
+/**
+ * WikimediaUI Base v0.9.2
+ * Wikimedia Foundation user interface base variables
+ */
+/* Colors */
+/* Positioning */
+/* Box Model properties */
+/* Max Widths */
+/* Typography incl. print properties */
+/* Other Properties */
+/* Animation & Transition */
+.oo-ui-element-hidden {
+ display: none !important;
+}
+.oo-ui-buttonElement {
+ display: inline-block;
+ line-height: normal;
+ vertical-align: middle;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+ cursor: pointer;
+ display: inline-block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ vertical-align: middle;
+ font-family: inherit;
+ font-size: inherit;
+ white-space: nowrap;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button::-moz-focus-inner {
+ border-color: transparent;
+ padding: 0;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ display: none;
+}
+.oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ cursor: default;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
+.oo-ui-buttonElement-frameless.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-buttonElement-frameless {
+ position: relative;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
+ vertical-align: top;
+ text-align: center;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+ position: relative;
+ border-radius: 2px;
+ padding-top: 2.34375em;
+ font-weight: bold;
+ text-decoration: none;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button:focus {
+ outline: 0;
+}
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ position: absolute;
+ top: 0;
+ height: 100%;
+}
+.oo-ui-buttonElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ display: block;
+}
+.oo-ui-buttonElement > input.oo-ui-buttonElement-button {
+ -webkit-appearance: none;
+}
+.oo-ui-buttonElement.oo-ui-labelElement > .oo-ui-buttonElement-button {
+ line-height: 1;
+}
+.oo-ui-buttonElement.oo-ui-labelElement > input.oo-ui-buttonElement-button,
+.oo-ui-buttonElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ line-height: 1.172em;
+}
+.oo-ui-buttonElement.oo-ui-labelElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button {
+ padding-right: 2.5em;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ display: block;
+}
+.oo-ui-buttonElement.oo-ui-indicatorElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator,
+.oo-ui-buttonElement.oo-ui-indicatorElement.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ right: 0.9375em;
+}
+.oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button {
+ -webkit-transition: background-color 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+ -moz-transition: background-color 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+ transition: background-color 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+}
+.oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ opacity: 0.87;
+ -webkit-transition: opacity 100ms;
+ -moz-transition: opacity 100ms;
+ transition: opacity 100ms;
+}
+.oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon.oo-ui-image-invert,
+.oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator.oo-ui-image-invert {
+ opacity: 1;
+}
+.oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover > .oo-ui-indicatorElement-indicator {
+ opacity: 0.73;
+}
+.oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover > .oo-ui-iconElement-icon.oo-ui-image-invert,
+.oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover > .oo-ui-indicatorElement-indicator.oo-ui-image-invert {
+ opacity: 1;
+}
+.oo-ui-buttonElement.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ opacity: 1;
+}
+.oo-ui-buttonElement-frameless.oo-ui-iconElement:first-child {
+ margin-left: -0.234375em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-iconElement > .oo-ui-buttonElement-button {
+ min-width: 1.875em;
+ min-height: 1.875em;
+ border-color: #fff;
+ border-color: transparent;
+ border-style: solid;
+ border-width: 1px;
+ padding-top: 2.34375em;
+ padding-left: 2.34375em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ left: 0.234375em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-labelElement:first-child {
+ margin-left: -0.3125em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-labelElement.oo-ui-iconElement:first-child {
+ margin-left: -0.234375em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-labelElement > .oo-ui-buttonElement-button {
+ border-color: #fff;
+ border-color: transparent;
+ border-style: solid;
+ border-width: 1px;
+ padding: 0.625em 0.3125em 0.546875em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-labelElement.oo-ui-iconElement > .oo-ui-buttonElement-button {
+ padding-left: 2.34375em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-indicatorElement > .oo-ui-buttonElement-button {
+ min-width: 12px;
+ min-height: 12px;
+ padding-top: 0;
+}
+.oo-ui-buttonElement-frameless.oo-ui-indicatorElement.oo-ui-iconElement > .oo-ui-buttonElement-button {
+ padding-left: 4.21875em;
+ padding-top: 2.34375em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-indicatorElement.oo-ui-labelElement > .oo-ui-buttonElement-button {
+ padding-left: 0.3125em;
+ padding-top: 0.625em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-indicatorElement.oo-ui-iconElement.oo-ui-labelElement > .oo-ui-buttonElement-button {
+ padding-left: 2.34375em;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled > .oo-ui-buttonElement-button {
+ color: #222;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover {
+ color: #444;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-iconElement > .oo-ui-buttonElement-button:focus,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-labelElement > .oo-ui-buttonElement-button:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-iconElement > .oo-ui-buttonElement-button:focus:active,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-labelElement > .oo-ui-buttonElement-button:focus:active {
+ border-color: #fff;
+ border-color: transparent;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-indicatorElement:not( .oo-ui-iconElement ):not( .oo-ui-labelElement ) > .oo-ui-buttonElement-button {
+ border-radius: 1px;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-indicatorElement:not( .oo-ui-iconElement ):not( .oo-ui-labelElement ) > .oo-ui-buttonElement-button:focus {
+ box-shadow: 0 0 0 2px #36c;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-indicatorElement:not( .oo-ui-iconElement ):not( .oo-ui-labelElement ) > .oo-ui-buttonElement-button:focus:active {
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > input.oo-ui-buttonElement-button,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active {
+ color: #000;
+ border-color: #fff;
+ border-color: transparent;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button {
+ color: #36c;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover {
+ color: #447ff5;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:active:focus,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ color: #2a4b8d;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
+ color: #36c;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover {
+ color: #447ff5;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:active:focus,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ color: #2a4b8d;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
+ color: #d33;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover {
+ color: #ff4242;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:active:focus,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ color: #b32424;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled[class*='oo-ui-flaggedElement'] > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled[class*='oo-ui-flaggedElement'] > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ opacity: 1;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled[class*='oo-ui-flaggedElement'] > .oo-ui-buttonElement-button:hover > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement-frameless.oo-ui-widget-enabled[class*='oo-ui-flaggedElement'] > .oo-ui-buttonElement-button:hover > .oo-ui-indicatorElement-indicator {
+ opacity: 0.73;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ color: #72777d;
+}
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement-frameless.oo-ui-widget-disabled > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ opacity: 0.51;
+}
+.oo-ui-buttonElement-framed > .oo-ui-buttonElement-button {
+ border-style: solid;
+ border-width: 1px;
+ border-radius: 2px;
+ padding-left: 0.9375em;
+ padding-right: 0.9375em;
+}
+.oo-ui-buttonElement-framed.oo-ui-iconElement > .oo-ui-buttonElement-button {
+ padding-top: 2.34375em;
+ padding-bottom: 0;
+ padding-left: 2.03125em;
+}
+.oo-ui-buttonElement-framed.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ left: 0.546875em;
+}
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-labelElement > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button {
+ padding-left: 2.5em;
+}
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement-framed.oo-ui-iconElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ left: 0.46875em;
+}
+.oo-ui-buttonElement-framed.oo-ui-indicatorElement > .oo-ui-buttonElement-button {
+ padding-top: 2.34375em;
+ padding-right: 2.03125em;
+ padding-bottom: 0;
+}
+.oo-ui-buttonElement-framed.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ right: 1.015625em;
+}
+.oo-ui-buttonElement-framed.oo-ui-indicatorElement.oo-ui-labelElement > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-indicatorElement.oo-ui-iconElement > .oo-ui-buttonElement-button {
+ padding-right: 2.5em;
+}
+.oo-ui-buttonElement-framed.oo-ui-labelElement > .oo-ui-buttonElement-button {
+ padding-top: 0.625em;
+ padding-bottom: 0.546875em;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ background-color: #c8ccd1;
+ color: #fff;
+ border-color: #c8ccd1;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button {
+ background-color: #f8f9fa;
+ color: #222;
+ border-color: #a2a9b1;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover {
+ background-color: #fff;
+ color: #444;
+ border-color: #a2a9b1;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button {
+ background-color: #c8ccd1;
+ color: #000;
+ border-color: #72777d;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ background-color: #2a4b8d;
+ color: #fff;
+ border-color: #2a4b8d;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-buttonElement-active > .oo-ui-buttonElement-button:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c, inset 0 0 0 2px #fff;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button {
+ color: #36c;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover {
+ background-color: #fff;
+ border-color: #447ff5;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:active:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive.oo-ui-popupToolGroup-active > .oo-ui-buttonElement-button {
+ background-color: #eff3fa;
+ color: #2a4b8d;
+ border-color: #2a4b8d;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c;
+ outline: 0;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
+ color: #36c;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover {
+ background-color: #fff;
+ border-color: #447ff5;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:active:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive.oo-ui-popupToolGroup-active > .oo-ui-buttonElement-button {
+ background-color: #eff3fa;
+ color: #2a4b8d;
+ border-color: #2a4b8d;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c;
+ outline: 0;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
+ color: #d73333;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover {
+ background-color: #fff;
+ border-color: #ff4242;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:active:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive.oo-ui-popupToolGroup-active > .oo-ui-buttonElement-button {
+ background-color: #ffffff;
+ color: #b32424;
+ border-color: #b32424;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
+ border-color: #d33;
+ box-shadow: inset 0 0 0 1px #d33;
+ outline: 0;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button {
+ color: #fff;
+ background-color: #36c;
+ border-color: #36c;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:hover {
+ background-color: #447ff5;
+ border-color: #447ff5;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:active:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive.oo-ui-popupToolGroup-active > .oo-ui-buttonElement-button {
+ color: #fff;
+ background-color: #2a4b8d;
+ border-color: #2a4b8d;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-progressive > .oo-ui-buttonElement-button:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c, inset 0 0 0 2px #fff;
+ outline: 0;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button {
+ color: #fff;
+ background-color: #36c;
+ border-color: #36c;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:hover {
+ background-color: #447ff5;
+ border-color: #447ff5;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:active:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive.oo-ui-popupToolGroup-active > .oo-ui-buttonElement-button {
+ color: #fff;
+ background-color: #2a4b8d;
+ border-color: #2a4b8d;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-constructive > .oo-ui-buttonElement-button:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c, inset 0 0 0 2px #fff;
+ outline: 0;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button {
+ color: #fff;
+ background-color: #d33;
+ border-color: #d33;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:hover {
+ background-color: #ff4242;
+ border-color: #ff4242;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:active,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:active:focus,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-pressed > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-active > .oo-ui-buttonElement-button,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive.oo-ui-popupToolGroup-active > .oo-ui-buttonElement-button {
+ color: #fff;
+ background-color: #b32424;
+ border-color: #b32424;
+ box-shadow: none;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary.oo-ui-flaggedElement-destructive > .oo-ui-buttonElement-button:focus {
+ border-color: #d33;
+ box-shadow: inset 0 0 0 1px #d33, inset 0 0 0 2px #fff;
+ outline: 0;
+}
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-buttonElement-framed.oo-ui-widget-enabled.oo-ui-flaggedElement-primary > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ opacity: 1;
+}
+.oo-ui-clippableElement-clippable {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ min-height: 3.125em;
+}
+.oo-ui-floatableElement {
+ position: absolute;
+}
+.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-iconElement.oo-ui-iconElement-icon {
+ background-size: contain;
+ background-position: center center;
+ background-repeat: no-repeat;
+ min-width: 24px;
+ width: 1.875em;
+ min-height: 24px;
+ height: 1.875em;
+}
+.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator,
+.oo-ui-indicatorElement.oo-ui-indicatorElement-indicator {
+ background-size: contain;
+ background-position: center center;
+ background-repeat: no-repeat;
+ min-width: 12px;
+ width: 0.9375em;
+ min-height: 12px;
+ height: 0.9375em;
+}
+.oo-ui-labelElement .oo-ui-labelElement-label-highlight {
+ font-weight: bold;
+}
+.oo-ui-pendingElement-pending {
+ background-image: /* @embed */ url(themes/wikimediaui/images/textures/pending.gif);
+}
+.oo-ui-fieldLayout {
+ display: block;
+ margin-top: 1.640625em;
+}
+.oo-ui-fieldLayout:before,
+.oo-ui-fieldLayout:after {
+ content: ' ';
+ display: table;
+}
+.oo-ui-fieldLayout:after {
+ clear: both;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-help,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-help,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ display: block;
+ float: left;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
+ text-align: right;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body {
+ display: table;
+ width: 100%;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ display: table-cell;
+ vertical-align: middle;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ width: 1px;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ display: block;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help {
+ float: right;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help > .oo-ui-popupWidget > .oo-ui-popupWidget-popup {
+ z-index: 1;
+}
+.oo-ui-fieldLayout.oo-ui-labelElement,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline {
+ margin-top: 1.171875em;
+}
+.oo-ui-fieldLayout:first-child,
+.oo-ui-fieldLayout.oo-ui-labelElement:first-child,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline:first-child {
+ margin-top: 0;
+}
+.oo-ui-fieldLayout.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
+ padding-bottom: 0.3125em;
+}
+.oo-ui-fieldLayout.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header > .oo-ui-labelElement-label {
+ line-height: 1.4;
+}
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-top > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header,
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body {
+ max-width: 50em;
+}
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header,
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
+ width: 35%;
+ margin-right: 5%;
+}
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header > .oo-ui-labelElement-label,
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header > .oo-ui-labelElement-label {
+ display: block;
+ padding-top: 0.3125em;
+}
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-help,
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-help {
+ margin-right: 0;
+ margin-left: -1.875em;
+}
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field,
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-right > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ width: 60%;
+}
+.oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-inline > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
+ padding: 0.3125em 0 0.3125em 0.46875em;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help {
+ margin-right: 0;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help:last-child {
+ margin-right: 0;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help .oo-ui-buttonElement-button {
+ padding-top: 1.71875em;
+ padding-left: 1.71875em;
+}
+.oo-ui-fieldLayout .oo-ui-fieldLayout-help .oo-ui-buttonElement-button .oo-ui-iconElement-icon {
+ left: 0;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top .oo-ui-fieldLayout-help,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline .oo-ui-fieldLayout-help {
+ margin-top: -0.46875em;
+}
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-top .oo-ui-fieldLayout-help:last-child,
+.oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline .oo-ui-fieldLayout-help:last-child {
+ margin-right: -0.3125em;
+}
+.oo-ui-fieldLayout-messages {
+ list-style: none none;
+ margin: 0.25em 0 0 0.25em;
+ padding: 0;
+}
+.oo-ui-fieldLayout-messages > li {
+ margin: 0;
+ padding: 0;
+ display: table;
+}
+.oo-ui-fieldLayout-messages .oo-ui-iconWidget {
+ display: table-cell;
+}
+.oo-ui-fieldLayout-messages .oo-ui-labelWidget {
+ display: table-cell;
+ padding: 0.1em 0 0.1em 0.3125em;
+ line-height: 1.4;
+ vertical-align: middle;
+}
+.oo-ui-fieldLayout-disabled > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header > .oo-ui-labelElement-label {
+ color: #72777d;
+}
+.oo-ui-actionFieldLayout-input,
+.oo-ui-actionFieldLayout-button {
+ display: table-cell;
+ vertical-align: middle;
+}
+.oo-ui-actionFieldLayout-input {
+ padding-right: 1em;
+}
+.oo-ui-actionFieldLayout-button {
+ width: 1%;
+ white-space: nowrap;
+}
+.oo-ui-actionFieldLayout.oo-ui-fieldLayout-align-top {
+ max-width: 50em;
+}
+.oo-ui-actionFieldLayout .oo-ui-actionFieldLayout-button .oo-ui-buttonElement-frameless {
+ margin-left: 0.3125em;
+}
+.oo-ui-fieldsetLayout {
+ position: relative;
+ min-width: 0;
+ margin: 0;
+ border: 0;
+ padding: 0.01px 0 0 0;
+}
+body:not( :-moz-handler-blocked ) .oo-ui-fieldsetLayout {
+ display: table-cell;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-fieldsetLayout-header > .oo-ui-iconElement-icon {
+ display: block;
+ position: absolute;
+}
+.oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-fieldsetLayout-header {
+ color: inherit;
+ display: inline-table;
+ box-sizing: border-box;
+ padding: 0;
+ white-space: normal;
+ float: left;
+ width: 100%;
+}
+.oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-fieldsetLayout-header > .oo-ui-labelElement-label:empty {
+ display: none;
+}
+.oo-ui-fieldsetLayout-group {
+ clear: both;
+}
+.oo-ui-fieldsetLayout .oo-ui-fieldsetLayout-help {
+ float: right;
+}
+.oo-ui-fieldsetLayout .oo-ui-fieldsetLayout-help > .oo-ui-popupWidget > .oo-ui-popupWidget-popup {
+ z-index: 1;
+}
+.oo-ui-fieldsetLayout .oo-ui-fieldsetLayout-header {
+ max-width: 50em;
+}
+.oo-ui-fieldsetLayout + .oo-ui-fieldsetLayout,
+.oo-ui-fieldsetLayout + .oo-ui-formLayout {
+ margin-top: 2em;
+}
+.oo-ui-fieldsetLayout.oo-ui-labelElement > .oo-ui-fieldsetLayout-header > .oo-ui-labelElement-label {
+ display: inline-block;
+ margin-bottom: 0.54347826em;
+ font-size: 1.15em;
+ font-weight: bold;
+ line-height: 1.4;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-fieldsetLayout-header > .oo-ui-labelElement-label {
+ padding-left: 1.76630435em;
+ line-height: 1.63043478em;
+}
+.oo-ui-fieldsetLayout.oo-ui-iconElement > .oo-ui-fieldsetLayout-header > .oo-ui-iconElement-icon {
+ top: 0;
+ left: 0;
+}
+.oo-ui-fieldsetLayout .oo-ui-fieldsetLayout-help {
+ margin-right: 0;
+ margin-top: -0.234375em;
+ margin-right: -0.3125em;
+}
+.oo-ui-fieldsetLayout .oo-ui-fieldsetLayout-help:last-child {
+ margin-right: 0;
+}
+.oo-ui-fieldsetLayout .oo-ui-fieldsetLayout-help:last-child {
+ margin-right: -0.3125em;
+}
+.oo-ui-fieldsetLayout .oo-ui-fieldsetLayout-help .oo-ui-buttonElement-button {
+ padding-top: 1.71875em;
+ padding-left: 1.71875em;
+}
+.oo-ui-fieldsetLayout .oo-ui-fieldsetLayout-help .oo-ui-buttonElement-button .oo-ui-iconElement-icon {
+ left: 0;
+}
+.oo-ui-formLayout + .oo-ui-fieldsetLayout,
+.oo-ui-formLayout + .oo-ui-formLayout {
+ margin-top: 2em;
+}
+.oo-ui-panelLayout {
+ position: relative;
+}
+.oo-ui-panelLayout-scrollable {
+ overflow: auto;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
+}
+.oo-ui-panelLayout-expanded {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-panelLayout-padded {
+ padding: 1.25em;
+}
+.oo-ui-panelLayout-padded.oo-ui-formLayout > .oo-ui-fieldsetLayout .oo-ui-labelElement-label,
+.oo-ui-panelLayout-padded.oo-ui-formLayout > .oo-ui-fieldsetLayout .oo-ui-iconElement-icon {
+ margin-top: -0.25em;
+}
+.oo-ui-panelLayout-framed {
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+}
+.oo-ui-panelLayout-padded.oo-ui-panelLayout-framed {
+ margin: 1em 0;
+}
+.oo-ui-horizontalLayout > .oo-ui-widget {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout {
+ display: inline-block;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout,
+.oo-ui-horizontalLayout > .oo-ui-widget {
+ margin-right: 0.5em;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout:last-child,
+.oo-ui-horizontalLayout > .oo-ui-widget:last-child {
+ margin-right: 0;
+}
+.oo-ui-horizontalLayout > .oo-ui-layout {
+ margin-top: 0;
+}
+.oo-ui-optionWidget {
+ position: relative;
+ display: block;
+}
+.oo-ui-optionWidget.oo-ui-widget-enabled {
+ cursor: pointer;
+}
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+ cursor: default;
+}
+.oo-ui-optionWidget.oo-ui-labelElement > .oo-ui-labelElement-label {
+ display: block;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.oo-ui-optionWidget .oo-ui-labelElement-label {
+ line-height: 1.6;
+}
+.oo-ui-optionWidget-selected .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ opacity: 1;
+}
+.oo-ui-optionWidget.oo-ui-widget-disabled {
+ color: #72777d;
+}
+.oo-ui-decoratedOptionWidget {
+ padding: 0.703125em 0.9375em 0.625em;
+ line-height: 1;
+}
+.oo-ui-decoratedOptionWidget > .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget > .oo-ui-indicatorElement-indicator {
+ position: absolute;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ top: 0;
+ height: 100%;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-iconElement {
+ padding-left: 2.96875em;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+ left: 0.9375em;
+}
+.oo-ui-decoratedOptionWidget .oo-ui-labelElement-label {
+ line-height: 1.172em;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-indicatorElement {
+ padding-right: 2.5em;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ right: 0.9375em;
+}
+.oo-ui-decoratedOptionWidget.oo-ui-widget-disabled .oo-ui-iconElement-icon,
+.oo-ui-decoratedOptionWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+ opacity: 0.51;
+}
+.oo-ui-radioSelectWidget:focus {
+ outline: 0;
+}
+.oo-ui-radioSelectWidget:focus [type='radio']:checked + span:before {
+ border-color: #fff;
+}
+.oo-ui-radioOptionWidget {
+ padding: 0.3125em 0;
+}
+.oo-ui-radioOptionWidget .oo-ui-radioInputWidget,
+.oo-ui-radioOptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-radioOptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ padding-left: 0.46875em;
+}
+.oo-ui-radioOptionWidget .oo-ui-radioInputWidget {
+ margin-right: 0;
+}
+.oo-ui-labelWidget {
+ display: inline-block;
+}
+.oo-ui-iconWidget {
+ display: inline-block;
+ vertical-align: middle;
+ line-height: 2.5;
+}
+.oo-ui-iconWidget.oo-ui-widget-disabled {
+ opacity: 0.51;
+}
+.oo-ui-indicatorWidget {
+ display: inline-block;
+ vertical-align: middle;
+ line-height: 2.5;
+ margin: 0.46875em;
+}
+.oo-ui-indicatorWidget.oo-ui-widget-disabled {
+ opacity: 0.51;
+}
+.oo-ui-buttonWidget {
+ margin-right: 0.5em;
+}
+.oo-ui-buttonWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonGroupWidget {
+ display: inline-block;
+ white-space: nowrap;
+ border-radius: 2px;
+ margin-right: 0.5em;
+ z-index: 0;
+ position: relative;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonWidget.oo-ui-buttonElement-active .oo-ui-buttonElement-button {
+ cursor: default;
+}
+.oo-ui-buttonGroupWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement {
+ margin-right: 0;
+ z-index: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+ margin-left: -1px;
+ border-radius: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:first-child .oo-ui-buttonElement-button {
+ margin-left: 0;
+ border-bottom-left-radius: 2px;
+ border-top-left-radius: 2px;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed:last-child .oo-ui-buttonElement-button {
+ border-bottom-right-radius: 2px;
+ border-top-right-radius: 2px;
+}
+.oo-ui-buttonGroupWidget .oo-ui-buttonElement-framed.oo-ui-widget-disabled + .oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ border-left-color: #fff;
+}
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active {
+ z-index: 1;
+}
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:focus {
+ z-index: 2;
+}
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ z-index: 3;
+}
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ z-index: -1;
+}
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-toggleWidget-on + .oo-ui-toggleWidget-on > .oo-ui-buttonElement-button,
+.oo-ui-buttonGroupWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-toggleWidget-on + .oo-ui-toggleWidget-on > .oo-ui-buttonElement-button:active {
+ border-left-color: #a2a9b1;
+ z-index: 3;
+}
+.oo-ui-popupWidget {
+ position: absolute;
+}
+.oo-ui-popupWidget-popup {
+ position: relative;
+ overflow: hidden;
+ z-index: 1;
+}
+.oo-ui-popupWidget-anchor {
+ display: none;
+ z-index: 1;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor {
+ display: block;
+ position: absolute;
+ background-repeat: no-repeat;
+}
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:before,
+.oo-ui-popupWidget-anchored .oo-ui-popupWidget-anchor:after {
+ content: '';
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-style: solid;
+ border-color: transparent;
+}
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor {
+ left: 0;
+}
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor:before,
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor:after {
+ border-top: 0;
+}
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor {
+ left: 0;
+}
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor:before,
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor:after {
+ border-bottom: 0;
+}
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor {
+ top: 0;
+}
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor:before,
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor:after {
+ border-left: 0;
+}
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor {
+ top: 0;
+}
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor:before,
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor:after {
+ border-right: 0;
+}
+.oo-ui-popupWidget-head {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-popupWidget-head > .oo-ui-buttonWidget {
+ position: absolute;
+}
+.oo-ui-popupWidget-head > .oo-ui-labelElement-label {
+ float: left;
+ cursor: default;
+}
+.oo-ui-popupWidget-body {
+ clear: both;
+}
+.oo-ui-popupWidget-body.oo-ui-clippableElement-clippable {
+ min-height: 1em;
+}
+.oo-ui-popupWidget-popup {
+ background-color: #fff;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.25);
+}
+.oo-ui-popupWidget-anchored-top {
+ margin-top: 9px;
+}
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor {
+ top: -9px;
+}
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor:before {
+ bottom: -10px;
+ left: -9px;
+ border-bottom-color: #a2a9b1;
+ border-width: 10px;
+}
+.oo-ui-popupWidget-anchored-top .oo-ui-popupWidget-anchor:after {
+ bottom: -10px;
+ left: -8px;
+ border-bottom-color: #fff;
+ border-width: 9px;
+}
+.oo-ui-popupWidget-anchored-bottom {
+ margin-bottom: 9px;
+}
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor {
+ bottom: -9px;
+}
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor:before {
+ top: -10px;
+ left: -9px;
+ border-top-color: #a2a9b1;
+ border-width: 10px;
+}
+.oo-ui-popupWidget-anchored-bottom .oo-ui-popupWidget-anchor:after {
+ top: -10px;
+ left: -8px;
+ border-top-color: #fff;
+ border-width: 9px;
+}
+.oo-ui-popupWidget-anchored-start {
+ margin-left: 9px;
+}
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor {
+ left: -9px;
+}
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor:before {
+ right: -10px;
+ top: -9px;
+ border-right-color: #a2a9b1;
+ border-width: 10px;
+}
+.oo-ui-popupWidget-anchored-start .oo-ui-popupWidget-anchor:after {
+ right: -10px;
+ top: -8px;
+ border-right-color: #fff;
+ border-width: 9px;
+}
+.oo-ui-popupWidget-anchored-end {
+ margin-right: 9px;
+}
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor {
+ right: -9px;
+}
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor:before {
+ left: -10px;
+ top: -9px;
+ border-left-color: #a2a9b1;
+ border-width: 10px;
+}
+.oo-ui-popupWidget-anchored-end .oo-ui-popupWidget-anchor:after {
+ left: -10px;
+ top: -8px;
+ border-left-color: #fff;
+ border-width: 9px;
+}
+.oo-ui-popupWidget-transitioning .oo-ui-popupWidget-popup {
+ -webkit-transition: width 100ms, height 100ms, left 100ms;
+ -moz-transition: width 100ms, height 100ms, left 100ms;
+ transition: width 100ms, height 100ms, left 100ms;
+}
+.oo-ui-popupWidget-head > .oo-ui-labelElement-label {
+ margin: 0.703125em 2.5em 0.625em 0.9375em;
+ line-height: 1.172em;
+}
+.oo-ui-popupWidget-head > .oo-ui-buttonWidget {
+ right: 0;
+}
+.oo-ui-popupWidget-body {
+ line-height: 1.4;
+}
+.oo-ui-popupWidget-body-padded {
+ margin: 0.703125em 0.9375em 0.625em;
+}
+.oo-ui-popupWidget-body-padded :first-child {
+ margin-top: 0;
+}
+.oo-ui-popupWidget-footer {
+ margin: 0.703125em 0.9375em 0.625em;
+}
+.oo-ui-popupButtonWidget {
+ position: relative;
+}
+.oo-ui-popupButtonWidget .oo-ui-popupWidget {
+ cursor: auto;
+}
+.oo-ui-inputWidget {
+ margin-right: 0.5em;
+}
+.oo-ui-inputWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonInputWidget > button,
+.oo-ui-buttonInputWidget > input {
+ background-color: transparent;
+ margin: 0;
+ border: 0;
+ padding: 0;
+}
+.oo-ui-checkboxInputWidget {
+ position: relative;
+ line-height: 1.5625em;
+ white-space: nowrap;
+ display: inline-block;
+}
+.oo-ui-checkboxInputWidget * {
+ font: inherit;
+ vertical-align: middle;
+}
+.oo-ui-checkboxInputWidget [type='checkbox'] {
+ position: relative;
+ max-width: none;
+ width: 1.5625em;
+ height: 1.5625em;
+ margin: 0;
+ opacity: 0;
+ z-index: 1;
+}
+.oo-ui-checkboxInputWidget [type='checkbox'] + span {
+ background-color: #fff;
+ background-origin: border-box;
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: 0 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ position: absolute;
+ left: 0;
+ width: 1.5625em;
+ height: 1.5625em;
+ border: 1px solid #72777d;
+ border-radius: 2px;
+}
+.oo-ui-checkboxInputWidget [type='checkbox']:checked + span {
+ background-image: url('themes/wikimediaui/images/icons/check-invert.png');
+ background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url('themes/wikimediaui/images/icons/check-invert.svg');
+ background-image: linear-gradient(transparent, transparent), /* @embed */ url('themes/wikimediaui/images/icons/check-invert.svg');
+ background-image: -o-linear-gradient(transparent, transparent), url('themes/wikimediaui/images/icons/check-invert.png');
+ background-size: 90% 90%;
+}
+.oo-ui-checkboxInputWidget [type='checkbox']:disabled + span {
+ background-color: #c8ccd1;
+ border-color: #c8ccd1;
+}
+.oo-ui-checkboxInputWidget.oo-ui-widget-enabled [type='checkbox'] {
+ cursor: pointer;
+}
+.oo-ui-checkboxInputWidget.oo-ui-widget-enabled [type='checkbox'] + span {
+ cursor: pointer;
+ -webkit-transition: background-color 100ms, background-size 100ms, border-color 100ms, box-shadow 100ms;
+ -moz-transition: background-color 100ms, background-size 100ms, border-color 100ms, box-shadow 100ms;
+ transition: background-color 100ms, background-size 100ms, border-color 100ms, box-shadow 100ms;
+}
+.oo-ui-checkboxInputWidget.oo-ui-widget-enabled [type='checkbox']:focus + span {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c;
+}
+.oo-ui-checkboxInputWidget.oo-ui-widget-enabled [type='checkbox']:hover + span {
+ border-color: #36c;
+}
+.oo-ui-checkboxInputWidget.oo-ui-widget-enabled [type='checkbox']:active + span {
+ background-color: #2a4b8d;
+ border-color: #2a4b8d;
+ box-shadow: inset 0 0 0 1px #2a4b8d;
+}
+.oo-ui-checkboxInputWidget.oo-ui-widget-enabled [type='checkbox']:checked + span {
+ background-color: #36c;
+ border-color: #36c;
+}
+.oo-ui-checkboxInputWidget.oo-ui-widget-enabled [type='checkbox']:checked:focus + span {
+ background-color: #36c;
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c, inset 0 0 0 2px #fff;
+}
+.oo-ui-checkboxInputWidget.oo-ui-widget-enabled [type='checkbox']:checked:hover + span {
+ background-color: #447ff5;
+ border-color: #447ff5;
+}
+.oo-ui-checkboxInputWidget.oo-ui-widget-enabled [type='checkbox']:checked:active + span {
+ background-color: #2a4b8d;
+ border-color: #2a4b8d;
+ box-shadow: inset 0 0 0 1px #2a4b8d;
+}
+.oo-ui-checkboxMultiselectInputWidget .oo-ui-fieldLayout {
+ margin-top: 0;
+}
+.oo-ui-checkboxMultiselectInputWidget .oo-ui-fieldLayout .oo-ui-fieldLayout-body {
+ padding: 0.3125em 0;
+}
+.oo-ui-checkboxMultiselectInputWidget .oo-ui-fieldLayout .oo-ui-fieldLayout-body .oo-ui-labelElement-label {
+ line-height: 1.5;
+}
+.oo-ui-dropdownInputWidget {
+ position: relative;
+ vertical-align: middle;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ max-width: 50em;
+}
+.oo-ui-dropdownInputWidget .oo-ui-dropdownWidget,
+.oo-ui-dropdownInputWidget select {
+ display: block;
+}
+.oo-ui-dropdownInputWidget select {
+ background-position: -9999em 0;
+ background-repeat: no-repeat;
+ width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-enabled select {
+ cursor: pointer;
+}
+.oo-ui-dropdownInputWidget-php {
+ border-right: 1px solid #a2a9b1;
+ border-radius: 2px;
+ overflow-x: hidden;
+}
+.oo-ui-dropdownInputWidget select {
+ -webkit-appearance: none;
+ -moz-appearance: none;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ padding: 0.625em 0.9375em 0.546875em;
+ font-size: inherit;
+ font-family: inherit;
+ vertical-align: middle;
+}
+.oo-ui-dropdownInputWidget select::-ms-expand {
+ display: none;
+}
+.oo-ui-dropdownInputWidget select:not( [no-ie] ) {
+ background-position: right 1.75em center;
+ width: calc( 100% + 1em );
+ height: 2.5em;
+ padding: 0 0 0 0.9375em;
+}
+.oo-ui-dropdownInputWidget option {
+ font-size: inherit;
+ font-family: inherit;
+ height: 1.5em;
+ padding: 0.625em 0.9375em;
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-enabled select {
+ background-color: #f8f9fa;
+ color: #222;
+ -webkit-transition: background-color 100ms, border-color 100ms, box-shadow 100ms;
+ -moz-transition: background-color 100ms, border-color 100ms, box-shadow 100ms;
+ transition: background-color 100ms, border-color 100ms, box-shadow 100ms;
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-enabled select:hover {
+ background-color: #fff;
+ color: #444;
+ border-color: #a2a9b1;
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-enabled select:active {
+ color: #000;
+ border-color: #72777d;
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-enabled select:focus {
+ border-color: #36c;
+ outline: 0;
+ box-shadow: inset 0 0 0 1px #36c;
+}
+.oo-ui-dropdownInputWidget.oo-ui-widget-disabled select {
+ background-color: #eaecf0;
+ color: #72777d;
+ border-color: #c8ccd1;
+}
+.oo-ui-radioInputWidget {
+ position: relative;
+ line-height: 1.5625em;
+ white-space: nowrap;
+ display: inline-block;
+}
+.oo-ui-radioInputWidget * {
+ font: inherit;
+ vertical-align: middle;
+}
+.oo-ui-radioInputWidget [type='radio'] {
+ position: relative;
+ max-width: none;
+ width: 1.5625em;
+ height: 1.5625em;
+ margin: 0;
+ opacity: 0;
+ z-index: 1;
+}
+.oo-ui-radioInputWidget [type='radio'] + span {
+ background-color: #fff;
+ position: absolute;
+ left: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 1.5625em;
+ height: 1.5625em;
+ border: 1px solid #72777d;
+ border-radius: 100%;
+}
+.oo-ui-radioInputWidget [type='radio'] + span:before {
+ content: ' ';
+ position: absolute;
+ top: -4px;
+ left: -4px;
+ right: -4px;
+ bottom: -4px;
+ border: 1px solid transparent;
+ border-radius: 100%;
+}
+.oo-ui-radioInputWidget [type='radio']:checked + span,
+.oo-ui-radioInputWidget [type='radio']:checked:hover + span,
+.oo-ui-radioInputWidget [type='radio']:checked:focus:hover + span {
+ border-width: 0.46875em;
+}
+.oo-ui-radioInputWidget [type='radio']:disabled + span {
+ background-color: #c8ccd1;
+ border-color: #c8ccd1;
+}
+.oo-ui-radioInputWidget [type='radio']:disabled:checked + span {
+ background-color: #fff;
+}
+.oo-ui-radioInputWidget.oo-ui-widget-enabled [type='radio'] {
+ cursor: pointer;
+}
+.oo-ui-radioInputWidget.oo-ui-widget-enabled [type='radio'] + span {
+ cursor: pointer;
+ -webkit-transition: background-color 100ms, border-color 100ms, border-width 100ms;
+ -moz-transition: background-color 100ms, border-color 100ms, border-width 100ms;
+ transition: background-color 100ms, border-color 100ms, border-width 100ms;
+}
+.oo-ui-radioInputWidget.oo-ui-widget-enabled [type='radio']:hover + span {
+ border-color: #36c;
+}
+.oo-ui-radioInputWidget.oo-ui-widget-enabled [type='radio']:active + span {
+ background-color: #2a4b8d;
+ border-color: #2a4b8d;
+}
+.oo-ui-radioInputWidget.oo-ui-widget-enabled [type='radio']:checked + span {
+ border-color: #36c;
+}
+.oo-ui-radioInputWidget.oo-ui-widget-enabled [type='radio']:checked:focus + span:before {
+ border-color: #fff;
+}
+.oo-ui-radioInputWidget.oo-ui-widget-enabled [type='radio']:checked:hover + span {
+ border-color: #447ff5;
+}
+.oo-ui-radioInputWidget.oo-ui-widget-enabled [type='radio']:checked:active + span {
+ border-color: #2a4b8d;
+ box-shadow: inset 0 0 0 1px #2a4b8d;
+}
+.oo-ui-radioInputWidget.oo-ui-widget-enabled [type='radio']:checked:active + span:before {
+ border-color: #2a4b8d;
+}
+.oo-ui-radioSelectInputWidget .oo-ui-fieldLayout {
+ margin-top: 0;
+}
+.oo-ui-radioSelectInputWidget .oo-ui-fieldLayout .oo-ui-fieldLayout-body {
+ padding: 0.3125em 0;
+}
+.oo-ui-radioSelectInputWidget .oo-ui-fieldLayout .oo-ui-fieldLayout-body .oo-ui-labelElement-label {
+ line-height: 1.5;
+}
+.oo-ui-textInputWidget {
+ position: relative;
+ vertical-align: middle;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%;
+ max-width: 50em;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+ display: block;
+ width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-textInputWidget textarea {
+ overflow: auto;
+ resize: none;
+}
+.oo-ui-textInputWidget [type='number'] {
+ -moz-appearance: textfield;
+}
+.oo-ui-textInputWidget [type='number']::-webkit-outer-spin-button,
+.oo-ui-textInputWidget [type='number']::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+.oo-ui-textInputWidget [type='search'] {
+ -webkit-appearance: none;
+}
+.oo-ui-textInputWidget [type='search']::-ms-clear {
+ display: none;
+}
+.oo-ui-textInputWidget [type='search']::-webkit-search-decoration,
+.oo-ui-textInputWidget [type='search']::-webkit-search-cancel-button {
+ display: none;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget > .oo-ui-labelElement-label {
+ display: none;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-indicatorElement > .oo-ui-indicatorElement-indicator {
+ display: block;
+ position: absolute;
+ top: 0;
+ height: 100%;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator {
+ cursor: text;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-textInputWidget-type-search > .oo-ui-indicatorElement-indicator {
+ cursor: pointer;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled input,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea,
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-labelElement-label {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-textInputWidget.oo-ui-labelElement > .oo-ui-labelElement-label {
+ display: block;
+}
+.oo-ui-textInputWidget > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget-labelPosition-before > .oo-ui-labelElement-label {
+ left: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget-labelPosition-after > .oo-ui-labelElement-label {
+ right: 0;
+}
+.oo-ui-textInputWidget > .oo-ui-labelElement-label {
+ position: absolute;
+ top: 0;
+}
+.oo-ui-textInputWidget-php > .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget-php > .oo-ui-indicatorElement-indicator,
+.oo-ui-textInputWidget-php > .oo-ui-labelElement-label {
+ pointer-events: none;
+}
+.oo-ui-textInputWidget input,
+.oo-ui-textInputWidget textarea {
+ -webkit-appearance: none;
+ margin: 0;
+ font-size: inherit;
+ font-family: inherit;
+ background-color: #fff;
+ color: #000;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ padding: 0.625em 0.625em 0.546875em;
+}
+.oo-ui-textInputWidget input {
+ line-height: 1.172em;
+}
+.oo-ui-textInputWidget textarea {
+ line-height: 1.275;
+}
+.oo-ui-textInputWidget .oo-ui-pendingElement-pending {
+ background-color: transparent;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea {
+ box-shadow: inset 0 0 0 1px transparent;
+ -webkit-transition: border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), box-shadow 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+ -moz-transition: border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), box-shadow 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+ transition: border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), box-shadow 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input:hover,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea:hover {
+ border-color: #72777d;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input:focus,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea:focus {
+ outline: 0;
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input[readonly],
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea[readonly] {
+ background-color: #f8f9fa;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input[readonly]:hover,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea[readonly]:hover {
+ border-color: #c8ccd1;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input[readonly]:focus,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea[readonly]:focus {
+ border-color: #36c;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input::-webkit-input-placeholder,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea::-webkit-input-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input:-ms-input-placeholder,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea:-ms-input-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input::-moz-placeholder,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea::-moz-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input:-moz-placeholder,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea:-moz-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled input::placeholder,
+.oo-ui-textInputWidget.oo-ui-widget-enabled textarea::placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+@media screen and (min-width: 0) {
+ .oo-ui-textInputWidget.oo-ui-widget-enabled textarea:focus {
+ outline: 1px solid #36c;
+ outline-offset: -2px;
+ }
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid input,
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid textarea {
+ border-color: #d33;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid input:hover,
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid textarea:hover {
+ border-color: #d33;
+}
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid input:focus,
+.oo-ui-textInputWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid textarea:focus {
+ border-color: #d33;
+ box-shadow: inset 0 0 0 1px #d33;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled input,
+.oo-ui-textInputWidget.oo-ui-widget-disabled textarea {
+ background-color: #eaecf0;
+ -webkit-text-fill-color: #72777d;
+ color: #72777d;
+ text-shadow: 0 1px 1px #fff;
+ border-color: #c8ccd1;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-iconElement-icon,
+.oo-ui-textInputWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+ opacity: 0.51;
+}
+.oo-ui-textInputWidget.oo-ui-widget-disabled > .oo-ui-labelElement-label {
+ color: #72777d;
+ text-shadow: 0 1px 1px #fff;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement input,
+.oo-ui-textInputWidget.oo-ui-iconElement textarea {
+ padding-left: 2.5em;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+ left: 0.46875em;
+}
+.oo-ui-textInputWidget.oo-ui-iconElement textarea + .oo-ui-iconElement-icon {
+ max-height: 2.5em;
+}
+.oo-ui-textInputWidget > .oo-ui-labelElement-label {
+ color: #72777d;
+ margin-top: 1px;
+ padding: 0.625em 0.9375em 0.546875em 0.625em;
+ line-height: 1.172em;
+}
+.oo-ui-textInputWidget.oo-ui-indicatorElement input,
+.oo-ui-textInputWidget.oo-ui-indicatorElement textarea {
+ padding-right: 2.1875em;
+}
+.oo-ui-textInputWidget.oo-ui-indicatorElement.oo-ui-textInputWidget-labelPosition-after > .oo-ui-labelElement-label {
+ padding-right: 0;
+}
+.oo-ui-textInputWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ max-height: 2.5em;
+ margin-right: 0.9375em;
+}
+.oo-ui-textInputWidget-labelPosition-after.oo-ui-indicatorElement > .oo-ui-labelElement-label {
+ margin-right: 2.5em;
+}
+.oo-ui-textInputWidget-labelPosition-before.oo-ui-iconElement > .oo-ui-labelElement-label {
+ padding-left: 2.5em;
+}
+.oo-ui-menuSelectWidget {
+ position: absolute;
+ width: 100%;
+ z-index: 4;
+ background-color: #fff;
+ margin-top: -1px;
+ border: 1px solid #a2a9b1;
+ border-radius: 0 0 2px 2px;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.25);
+}
+.oo-ui-menuSelectWidget.oo-ui-clippableElement-clippable {
+ min-height: 2.6em;
+}
+.oo-ui-menuSelectWidget-invisible {
+ display: none;
+}
+.oo-ui-menuOptionWidget {
+ -webkit-transition: background-color 100ms, color 100ms;
+ -moz-transition: background-color 100ms, color 100ms;
+ transition: background-color 100ms, color 100ms;
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-highlighted {
+ background-color: #eaecf0;
+ color: #000;
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-selected {
+ background-color: #eaf3ff;
+ color: #36c;
+}
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-selected.oo-ui-menuOptionWidget.oo-ui-optionWidget-highlighted,
+.oo-ui-menuOptionWidget.oo-ui-optionWidget-pressed.oo-ui-menuOptionWidget.oo-ui-optionWidget-highlighted {
+ background-color: rgba(41, 98, 204, 0.1);
+ color: #36c;
+}
+.oo-ui-menuSectionOptionWidget {
+ color: #72777d;
+ padding: 0.703125em 0.9375em 0.3125em;
+ font-weight: bold;
+}
+.oo-ui-menuSectionOptionWidget.oo-ui-widget-enabled {
+ cursor: default;
+}
+.oo-ui-dropdownWidget {
+ display: inline-block;
+ position: relative;
+ width: 100%;
+ max-width: 50em;
+ margin-right: 0.5em;
+}
+.oo-ui-dropdownWidget-handle {
+ position: relative;
+ width: 100%;
+ display: block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ cursor: default;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon,
+.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator {
+ position: absolute;
+ top: 0;
+ height: 100%;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle {
+ cursor: pointer;
+}
+.oo-ui-dropdownWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-dropdownWidget-handle {
+ min-height: 2.5em;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ padding: 0.625em 0.9375em 0.546875em;
+ line-height: 1;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon {
+ left: 0.46875em;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator {
+ right: 0.9375em;
+}
+.oo-ui-dropdownWidget-handle .oo-ui-labelElement-label {
+ line-height: 1.172em;
+}
+.oo-ui-dropdownWidget.oo-ui-iconElement .oo-ui-dropdownWidget-handle {
+ padding-left: 2.5em;
+}
+.oo-ui-dropdownWidget.oo-ui-indicatorElement .oo-ui-dropdownWidget-handle {
+ padding-right: 1.875em;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle {
+ background-color: #f8f9fa;
+ color: #222;
+ -webkit-transition: background-color 100ms, border-color 100ms, box-shadow 100ms;
+ -moz-transition: background-color 100ms, border-color 100ms, box-shadow 100ms;
+ transition: background-color 100ms, border-color 100ms, box-shadow 100ms;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle:hover {
+ background-color: #fff;
+ color: #444;
+ border-color: #a2a9b1;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle:hover .oo-ui-iconElement-icon,
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle:hover .oo-ui-indicatorElement-indicator {
+ opacity: 0.73;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle:active {
+ color: #000;
+ border-color: #72777d;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle:focus {
+ border-color: #36c;
+ outline: 0;
+ box-shadow: inset 0 0 0 1px #36c;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon,
+.oo-ui-dropdownWidget.oo-ui-widget-enabled .oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator {
+ opacity: 0.87;
+ -webkit-transition: opacity 100ms;
+ -moz-transition: opacity 100ms;
+ transition: opacity 100ms;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled.oo-ui-dropdownWidget-open .oo-ui-dropdownWidget-handle {
+ background-color: #fff;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-enabled.oo-ui-dropdownWidget-open .oo-ui-dropdownWidget-handle .oo-ui-iconElement-icon,
+.oo-ui-dropdownWidget.oo-ui-widget-enabled.oo-ui-dropdownWidget-open .oo-ui-dropdownWidget-handle .oo-ui-indicatorElement-indicator {
+ opacity: 1;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle {
+ color: #72777d;
+ text-shadow: 0 1px 1px #fff;
+ border-color: #c8ccd1;
+ background-color: #eaecf0;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-dropdownWidget-handle:focus {
+ outline: 0;
+}
+.oo-ui-dropdownWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+ opacity: 0.15;
+}
+.oo-ui-comboBoxInputWidget {
+ display: inline-block;
+ position: relative;
+}
+.oo-ui-comboBoxInputWidget-field {
+ display: table;
+ width: 100%;
+ table-layout: fixed;
+}
+.oo-ui-comboBoxInputWidget .oo-ui-inputWidget-input {
+ display: table-cell;
+ vertical-align: middle;
+ position: relative;
+ overflow: hidden;
+}
+.oo-ui-comboBoxInputWidget-dropdownButton {
+ display: table-cell;
+}
+.oo-ui-comboBoxInputWidget-dropdownButton > .oo-ui-buttonElement-button {
+ display: block;
+ overflow: hidden;
+}
+.oo-ui-comboBoxInputWidget.oo-ui-comboBoxInputWidget-empty .oo-ui-comboBoxInputWidget-dropdownButton {
+ display: none;
+}
+.oo-ui-comboBoxInputWidget-php ::-webkit-calendar-picker-indicator {
+ opacity: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ width: 2.5em;
+ height: 2.5em;
+ padding: 0;
+}
+.oo-ui-comboBoxInputWidget-php > .oo-ui-indicatorWidget {
+ display: block;
+ position: absolute;
+ top: 0;
+ height: 100%;
+ pointer-events: none;
+}
+.oo-ui-comboBoxInputWidget input {
+ height: 2.5em;
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ border-right-width: 0;
+}
+.oo-ui-comboBoxInputWidget.oo-ui-comboBoxInputWidget-empty input,
+.oo-ui-comboBoxInputWidget-php input {
+ border-top-right-radius: 2px;
+ border-bottom-right-radius: 2px;
+ border-right-width: 1px;
+}
+.oo-ui-comboBoxInputWidget-dropdownButton.oo-ui-indicatorElement {
+ width: 2.5em;
+}
+.oo-ui-comboBoxInputWidget-dropdownButton.oo-ui-indicatorElement .oo-ui-buttonElement-button {
+ min-width: 2.5em;
+ min-height: 2.5em;
+ padding-left: 0;
+}
+.oo-ui-comboBoxInputWidget-dropdownButton.oo-ui-indicatorElement .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ right: 0.703125em;
+}
+.oo-ui-comboBoxInputWidget-dropdownButton.oo-ui-indicatorElement .oo-ui-buttonElement-button,
+.oo-ui-comboBoxInputWidget-dropdownButton.oo-ui-indicatorElement .oo-ui-buttonElement-button:focus {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.oo-ui-comboBoxInputWidget-php .oo-ui-indicatorWidget {
+ right: 0.9375em;
+ margin: 0;
+}
+.oo-ui-comboBoxInputWidget.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator {
+ opacity: 1;
+}
+.oo-ui-multioptionWidget {
+ position: relative;
+ display: block;
+}
+.oo-ui-multioptionWidget.oo-ui-widget-enabled {
+ cursor: pointer;
+}
+.oo-ui-multioptionWidget.oo-ui-widget-disabled {
+ cursor: default;
+}
+.oo-ui-multioptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: block;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.oo-ui-multioptionWidget.oo-ui-widget-disabled {
+ color: #72777d;
+}
+.oo-ui-checkboxMultioptionWidget {
+ padding: 0.3125em 0;
+}
+.oo-ui-checkboxMultioptionWidget .oo-ui-checkboxInputWidget,
+.oo-ui-checkboxMultioptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-checkboxMultioptionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ padding-left: 0.46875em;
+}
+.oo-ui-checkboxMultioptionWidget .oo-ui-checkboxInputWidget {
+ margin-right: 0;
+}
+.oo-ui-progressBarWidget {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ max-width: 50em;
+ background-color: #fff;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ overflow: hidden;
+}
+.oo-ui-progressBarWidget-bar {
+ height: 1em;
+ -webkit-transition: width 200ms;
+ -moz-transition: width 200ms;
+ transition: width 200ms;
+}
+.oo-ui-progressBarWidget-indeterminate .oo-ui-progressBarWidget-bar {
+ -webkit-animation: oo-ui-progressBarWidget-slide 2s infinite linear;
+ -moz-animation: oo-ui-progressBarWidget-slide 2s infinite linear;
+ animation: oo-ui-progressBarWidget-slide 2s infinite linear;
+ width: 40%;
+ -webkit-transform: translate(-25%);
+ -moz-transform: translate(-25%);
+ -ms-transform: translate(-25%);
+ transform: translate(-25%);
+ border-left-width: 1px;
+}
+.oo-ui-progressBarWidget.oo-ui-widget-enabled .oo-ui-progressBarWidget-bar {
+ background-color: #36c;
+}
+.oo-ui-progressBarWidget.oo-ui-widget-disabled .oo-ui-progressBarWidget-bar {
+ background-color: #c8ccd1;
+}
+@-webkit-keyframes oo-ui-progressBarWidget-slide {
+ from {
+ -webkit-transform: translate(-100%);
+ -moz-transform: translate(-100%);
+ -ms-transform: translate(-100%);
+ transform: translate(-100%);
+ }
+ to {
+ -webkit-transform: translate(350%);
+ -moz-transform: translate(350%);
+ -ms-transform: translate(350%);
+ transform: translate(350%);
+ }
+}
+@-moz-keyframes oo-ui-progressBarWidget-slide {
+ from {
+ -webkit-transform: translate(-100%);
+ -moz-transform: translate(-100%);
+ -ms-transform: translate(-100%);
+ transform: translate(-100%);
+ }
+ to {
+ -webkit-transform: translate(350%);
+ -moz-transform: translate(350%);
+ -ms-transform: translate(350%);
+ transform: translate(350%);
+ }
+}
+@keyframes oo-ui-progressBarWidget-slide {
+ from {
+ -webkit-transform: translate(-100%);
+ -moz-transform: translate(-100%);
+ -ms-transform: translate(-100%);
+ transform: translate(-100%);
+ }
+ to {
+ -webkit-transform: translate(350%);
+ -moz-transform: translate(350%);
+ -ms-transform: translate(350%);
+ transform: translate(350%);
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-core.js b/www/wiki/resources/lib/oojs-ui/oojs-ui-core.js
new file mode 100644
index 00000000..c92ab4dd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-core.js
@@ -0,0 +1,11511 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:23:58Z
+ */
+( function ( OO ) {
+
+'use strict';
+
+/**
+ * Namespace for all classes, static methods and static properties.
+ *
+ * @class
+ * @singleton
+ */
+OO.ui = {};
+
+OO.ui.bind = $.proxy;
+
+/**
+ * @property {Object}
+ */
+OO.ui.Keys = {
+ UNDEFINED: 0,
+ BACKSPACE: 8,
+ DELETE: 46,
+ LEFT: 37,
+ RIGHT: 39,
+ UP: 38,
+ DOWN: 40,
+ ENTER: 13,
+ END: 35,
+ HOME: 36,
+ TAB: 9,
+ PAGEUP: 33,
+ PAGEDOWN: 34,
+ ESCAPE: 27,
+ SHIFT: 16,
+ SPACE: 32
+};
+
+/**
+ * Constants for MouseEvent.which
+ *
+ * @property {Object}
+ */
+OO.ui.MouseButtons = {
+ LEFT: 1,
+ MIDDLE: 2,
+ RIGHT: 3
+};
+
+/**
+ * @property {number}
+ * @private
+ */
+OO.ui.elementId = 0;
+
+/**
+ * Generate a unique ID for element
+ *
+ * @return {string} ID
+ */
+OO.ui.generateElementId = function () {
+ OO.ui.elementId++;
+ return 'oojsui-' + OO.ui.elementId;
+};
+
+/**
+ * Check if an element is focusable.
+ * Inspired by :focusable in jQueryUI v1.11.4 - 2015-04-14
+ *
+ * @param {jQuery} $element Element to test
+ * @return {boolean} Element is focusable
+ */
+OO.ui.isFocusableElement = function ( $element ) {
+ var nodeName,
+ element = $element[ 0 ];
+
+ // Anything disabled is not focusable
+ if ( element.disabled ) {
+ return false;
+ }
+
+ // Check if the element is visible
+ if ( !(
+ // This is quicker than calling $element.is( ':visible' )
+ $.expr.pseudos.visible( element ) &&
+ // Check that all parents are visible
+ !$element.parents().addBack().filter( function () {
+ return $.css( this, 'visibility' ) === 'hidden';
+ } ).length
+ ) ) {
+ return false;
+ }
+
+ // Check if the element is ContentEditable, which is the string 'true'
+ if ( element.contentEditable === 'true' ) {
+ return true;
+ }
+
+ // Anything with a non-negative numeric tabIndex is focusable.
+ // Use .prop to avoid browser bugs
+ if ( $element.prop( 'tabIndex' ) >= 0 ) {
+ return true;
+ }
+
+ // Some element types are naturally focusable
+ // (indexOf is much faster than regex in Chrome and about the
+ // same in FF: https://jsperf.com/regex-vs-indexof-array2)
+ nodeName = element.nodeName.toLowerCase();
+ if ( [ 'input', 'select', 'textarea', 'button', 'object' ].indexOf( nodeName ) !== -1 ) {
+ return true;
+ }
+
+ // Links and areas are focusable if they have an href
+ if ( ( nodeName === 'a' || nodeName === 'area' ) && $element.attr( 'href' ) !== undefined ) {
+ return true;
+ }
+
+ return false;
+};
+
+/**
+ * Find a focusable child
+ *
+ * @param {jQuery} $container Container to search in
+ * @param {boolean} [backwards] Search backwards
+ * @return {jQuery} Focusable child, or an empty jQuery object if none found
+ */
+OO.ui.findFocusable = function ( $container, backwards ) {
+ var $focusable = $( [] ),
+ // $focusableCandidates is a superset of things that
+ // could get matched by isFocusableElement
+ $focusableCandidates = $container
+ .find( 'input, select, textarea, button, object, a, area, [contenteditable], [tabindex]' );
+
+ if ( backwards ) {
+ $focusableCandidates = Array.prototype.reverse.call( $focusableCandidates );
+ }
+
+ $focusableCandidates.each( function () {
+ var $this = $( this );
+ if ( OO.ui.isFocusableElement( $this ) ) {
+ $focusable = $this;
+ return false;
+ }
+ } );
+ return $focusable;
+};
+
+/**
+ * Get the user's language and any fallback languages.
+ *
+ * These language codes are used to localize user interface elements in the user's language.
+ *
+ * In environments that provide a localization system, this function should be overridden to
+ * return the user's language(s). The default implementation returns English (en) only.
+ *
+ * @return {string[]} Language codes, in descending order of priority
+ */
+OO.ui.getUserLanguages = function () {
+ return [ 'en' ];
+};
+
+/**
+ * Get a value in an object keyed by language code.
+ *
+ * @param {Object.<string,Mixed>} obj Object keyed by language code
+ * @param {string|null} [lang] Language code, if omitted or null defaults to any user language
+ * @param {string} [fallback] Fallback code, used if no matching language can be found
+ * @return {Mixed} Local value
+ */
+OO.ui.getLocalValue = function ( obj, lang, fallback ) {
+ var i, len, langs;
+
+ // Requested language
+ if ( obj[ lang ] ) {
+ return obj[ lang ];
+ }
+ // Known user language
+ langs = OO.ui.getUserLanguages();
+ for ( i = 0, len = langs.length; i < len; i++ ) {
+ lang = langs[ i ];
+ if ( obj[ lang ] ) {
+ return obj[ lang ];
+ }
+ }
+ // Fallback language
+ if ( obj[ fallback ] ) {
+ return obj[ fallback ];
+ }
+ // First existing language
+ for ( lang in obj ) {
+ return obj[ lang ];
+ }
+
+ return undefined;
+};
+
+/**
+ * Check if a node is contained within another node
+ *
+ * Similar to jQuery#contains except a list of containers can be supplied
+ * and a boolean argument allows you to include the container in the match list
+ *
+ * @param {HTMLElement|HTMLElement[]} containers Container node(s) to search in
+ * @param {HTMLElement} contained Node to find
+ * @param {boolean} [matchContainers] Include the container(s) in the list of nodes to match, otherwise only match descendants
+ * @return {boolean} The node is in the list of target nodes
+ */
+OO.ui.contains = function ( containers, contained, matchContainers ) {
+ var i;
+ if ( !Array.isArray( containers ) ) {
+ containers = [ containers ];
+ }
+ for ( i = containers.length - 1; i >= 0; i-- ) {
+ if ( ( matchContainers && contained === containers[ i ] ) || $.contains( containers[ i ], contained ) ) {
+ return true;
+ }
+ }
+ return false;
+};
+
+/**
+ * Return a function, that, as long as it continues to be invoked, will not
+ * be triggered. The function will be called after it stops being called for
+ * N milliseconds. If `immediate` is passed, trigger the function on the
+ * leading edge, instead of the trailing.
+ *
+ * Ported from: http://underscorejs.org/underscore.js
+ *
+ * @param {Function} func Function to debounce
+ * @param {number} [wait=0] Wait period in milliseconds
+ * @param {boolean} [immediate] Trigger on leading edge
+ * @return {Function} Debounced function
+ */
+OO.ui.debounce = function ( func, wait, immediate ) {
+ var timeout;
+ return function () {
+ var context = this,
+ args = arguments,
+ later = function () {
+ timeout = null;
+ if ( !immediate ) {
+ func.apply( context, args );
+ }
+ };
+ if ( immediate && !timeout ) {
+ func.apply( context, args );
+ }
+ if ( !timeout || wait ) {
+ clearTimeout( timeout );
+ timeout = setTimeout( later, wait );
+ }
+ };
+};
+
+/**
+ * Puts a console warning with provided message.
+ *
+ * @param {string} message Message
+ */
+OO.ui.warnDeprecation = function ( message ) {
+ if ( OO.getProp( window, 'console', 'warn' ) !== undefined ) {
+ // eslint-disable-next-line no-console
+ console.warn( message );
+ }
+};
+
+/**
+ * Returns a function, that, when invoked, will only be triggered at most once
+ * during a given window of time. If called again during that window, it will
+ * wait until the window ends and then trigger itself again.
+ *
+ * As it's not knowable to the caller whether the function will actually run
+ * when the wrapper is called, return values from the function are entirely
+ * discarded.
+ *
+ * @param {Function} func Function to throttle
+ * @param {number} wait Throttle window length, in milliseconds
+ * @return {Function} Throttled function
+ */
+OO.ui.throttle = function ( func, wait ) {
+ var context, args, timeout,
+ previous = 0,
+ run = function () {
+ timeout = null;
+ previous = OO.ui.now();
+ func.apply( context, args );
+ };
+ return function () {
+ // Check how long it's been since the last time the function was
+ // called, and whether it's more or less than the requested throttle
+ // period. If it's less, run the function immediately. If it's more,
+ // set a timeout for the remaining time -- but don't replace an
+ // existing timeout, since that'd indefinitely prolong the wait.
+ var remaining = wait - ( OO.ui.now() - previous );
+ context = this;
+ args = arguments;
+ if ( remaining <= 0 ) {
+ // Note: unless wait was ridiculously large, this means we'll
+ // automatically run the first time the function was called in a
+ // given period. (If you provide a wait period larger than the
+ // current Unix timestamp, you *deserve* unexpected behavior.)
+ clearTimeout( timeout );
+ run();
+ } else if ( !timeout ) {
+ timeout = setTimeout( run, remaining );
+ }
+ };
+};
+
+/**
+ * A (possibly faster) way to get the current timestamp as an integer
+ *
+ * @return {number} Current timestamp, in milliseconds since the Unix epoch
+ */
+OO.ui.now = Date.now || function () {
+ return new Date().getTime();
+};
+
+/**
+ * Reconstitute a JavaScript object corresponding to a widget created by
+ * the PHP implementation.
+ *
+ * This is an alias for `OO.ui.Element.static.infuse()`.
+ *
+ * @param {string|HTMLElement|jQuery} idOrNode
+ * A DOM id (if a string) or node for the widget to infuse.
+ * @return {OO.ui.Element}
+ * The `OO.ui.Element` corresponding to this (infusable) document node.
+ */
+OO.ui.infuse = function ( idOrNode ) {
+ return OO.ui.Element.static.infuse( idOrNode );
+};
+
+( function () {
+ /**
+ * Message store for the default implementation of OO.ui.msg
+ *
+ * Environments that provide a localization system should not use this, but should override
+ * OO.ui.msg altogether.
+ *
+ * @private
+ */
+ var messages = {
+ // Tool tip for a button that moves items in a list down one place
+ 'ooui-outline-control-move-down': 'Move item down',
+ // Tool tip for a button that moves items in a list up one place
+ 'ooui-outline-control-move-up': 'Move item up',
+ // Tool tip for a button that removes items from a list
+ 'ooui-outline-control-remove': 'Remove item',
+ // Label for the toolbar group that contains a list of all other available tools
+ 'ooui-toolbar-more': 'More',
+ // Label for the fake tool that expands the full list of tools in a toolbar group
+ 'ooui-toolgroup-expand': 'More',
+ // Label for the fake tool that collapses the full list of tools in a toolbar group
+ 'ooui-toolgroup-collapse': 'Fewer',
+ // Default label for the tooltip for the button that removes a tag item
+ 'ooui-item-remove': 'Remove',
+ // Default label for the accept button of a confirmation dialog
+ 'ooui-dialog-message-accept': 'OK',
+ // Default label for the reject button of a confirmation dialog
+ 'ooui-dialog-message-reject': 'Cancel',
+ // Title for process dialog error description
+ 'ooui-dialog-process-error': 'Something went wrong',
+ // Label for process dialog dismiss error button, visible when describing errors
+ 'ooui-dialog-process-dismiss': 'Dismiss',
+ // Label for process dialog retry action button, visible when describing only recoverable errors
+ 'ooui-dialog-process-retry': 'Try again',
+ // Label for process dialog retry action button, visible when describing only warnings
+ 'ooui-dialog-process-continue': 'Continue',
+ // Label for the file selection widget's select file button
+ 'ooui-selectfile-button-select': 'Select a file',
+ // Label for the file selection widget if file selection is not supported
+ 'ooui-selectfile-not-supported': 'File selection is not supported',
+ // Label for the file selection widget when no file is currently selected
+ 'ooui-selectfile-placeholder': 'No file is selected',
+ // Label for the file selection widget's drop target
+ 'ooui-selectfile-dragdrop-placeholder': 'Drop file here'
+ };
+
+ /**
+ * Get a localized message.
+ *
+ * After the message key, message parameters may optionally be passed. In the default implementation,
+ * any occurrences of $1 are replaced with the first parameter, $2 with the second parameter, etc.
+ * Alternative implementations of OO.ui.msg may use any substitution system they like, as long as
+ * they support unnamed, ordered message parameters.
+ *
+ * In environments that provide a localization system, this function should be overridden to
+ * return the message translated in the user's language. The default implementation always returns
+ * English messages. An example of doing this with [jQuery.i18n](https://github.com/wikimedia/jquery.i18n)
+ * follows.
+ *
+ * @example
+ * var i, iLen, button,
+ * messagePath = 'oojs-ui/dist/i18n/',
+ * languages = [ $.i18n().locale, 'ur', 'en' ],
+ * languageMap = {};
+ *
+ * for ( i = 0, iLen = languages.length; i < iLen; i++ ) {
+ * languageMap[ languages[ i ] ] = messagePath + languages[ i ].toLowerCase() + '.json';
+ * }
+ *
+ * $.i18n().load( languageMap ).done( function() {
+ * // Replace the built-in `msg` only once we've loaded the internationalization.
+ * // OOjs UI uses `OO.ui.deferMsg` for all initially-loaded messages. So long as
+ * // you put off creating any widgets until this promise is complete, no English
+ * // will be displayed.
+ * OO.ui.msg = $.i18n;
+ *
+ * // A button displaying "OK" in the default locale
+ * button = new OO.ui.ButtonWidget( {
+ * label: OO.ui.msg( 'ooui-dialog-message-accept' ),
+ * icon: 'check'
+ * } );
+ * $( 'body' ).append( button.$element );
+ *
+ * // A button displaying "OK" in Urdu
+ * $.i18n().locale = 'ur';
+ * button = new OO.ui.ButtonWidget( {
+ * label: OO.ui.msg( 'ooui-dialog-message-accept' ),
+ * icon: 'check'
+ * } );
+ * $( 'body' ).append( button.$element );
+ * } );
+ *
+ * @param {string} key Message key
+ * @param {...Mixed} [params] Message parameters
+ * @return {string} Translated message with parameters substituted
+ */
+ OO.ui.msg = function ( key ) {
+ var message = messages[ key ],
+ params = Array.prototype.slice.call( arguments, 1 );
+ if ( typeof message === 'string' ) {
+ // Perform $1 substitution
+ message = message.replace( /\$(\d+)/g, function ( unused, n ) {
+ var i = parseInt( n, 10 );
+ return params[ i - 1 ] !== undefined ? params[ i - 1 ] : '$' + n;
+ } );
+ } else {
+ // Return placeholder if message not found
+ message = '[' + key + ']';
+ }
+ return message;
+ };
+}() );
+
+/**
+ * Package a message and arguments for deferred resolution.
+ *
+ * Use this when you are statically specifying a message and the message may not yet be present.
+ *
+ * @param {string} key Message key
+ * @param {...Mixed} [params] Message parameters
+ * @return {Function} Function that returns the resolved message when executed
+ */
+OO.ui.deferMsg = function () {
+ var args = arguments;
+ return function () {
+ return OO.ui.msg.apply( OO.ui, args );
+ };
+};
+
+/**
+ * Resolve a message.
+ *
+ * If the message is a function it will be executed, otherwise it will pass through directly.
+ *
+ * @param {Function|string} msg Deferred message, or message text
+ * @return {string} Resolved message
+ */
+OO.ui.resolveMsg = function ( msg ) {
+ if ( $.isFunction( msg ) ) {
+ return msg();
+ }
+ return msg;
+};
+
+/**
+ * @param {string} url
+ * @return {boolean}
+ */
+OO.ui.isSafeUrl = function ( url ) {
+ // Keep this function in sync with php/Tag.php
+ var i, protocolWhitelist;
+
+ function stringStartsWith( haystack, needle ) {
+ return haystack.substr( 0, needle.length ) === needle;
+ }
+
+ protocolWhitelist = [
+ 'bitcoin', 'ftp', 'ftps', 'geo', 'git', 'gopher', 'http', 'https', 'irc', 'ircs',
+ 'magnet', 'mailto', 'mms', 'news', 'nntp', 'redis', 'sftp', 'sip', 'sips', 'sms', 'ssh',
+ 'svn', 'tel', 'telnet', 'urn', 'worldwind', 'xmpp'
+ ];
+
+ if ( url === '' ) {
+ return true;
+ }
+
+ for ( i = 0; i < protocolWhitelist.length; i++ ) {
+ if ( stringStartsWith( url, protocolWhitelist[ i ] + ':' ) ) {
+ return true;
+ }
+ }
+
+ // This matches '//' too
+ if ( stringStartsWith( url, '/' ) || stringStartsWith( url, './' ) ) {
+ return true;
+ }
+ if ( stringStartsWith( url, '?' ) || stringStartsWith( url, '#' ) ) {
+ return true;
+ }
+
+ return false;
+};
+
+/**
+ * Check if the user has a 'mobile' device.
+ *
+ * For our purposes this means the user is primarily using an
+ * on-screen keyboard, touch input instead of a mouse and may
+ * have a physically small display.
+ *
+ * It is left up to implementors to decide how to compute this
+ * so the default implementation always returns false.
+ *
+ * @return {boolean} Use is on a mobile device
+ */
+OO.ui.isMobile = function () {
+ return false;
+};
+
+/*!
+ * Mixin namespace.
+ */
+
+/**
+ * Namespace for OOjs UI mixins.
+ *
+ * Mixins are named according to the type of object they are intended to
+ * be mixed in to. For example, OO.ui.mixin.GroupElement is intended to be
+ * mixed in to an instance of OO.ui.Element, and OO.ui.mixin.GroupWidget
+ * is intended to be mixed in to an instance of OO.ui.Widget.
+ *
+ * @class
+ * @singleton
+ */
+OO.ui.mixin = {};
+
+/**
+ * Each Element represents a rendering in the DOM—a button or an icon, for example, or anything
+ * that is visible to a user. Unlike {@link OO.ui.Widget widgets}, plain elements usually do not have events
+ * connected to them and can't be interacted with.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string[]} [classes] The names of the CSS classes to apply to the element. CSS styles are added
+ * to the top level (e.g., the outermost div) of the element. See the [OOjs UI documentation on MediaWiki][2]
+ * for an example.
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches#cssExample
+ * @cfg {string} [id] The HTML id attribute used in the rendered tag.
+ * @cfg {string} [text] Text to insert
+ * @cfg {Array} [content] An array of content elements to append (after #text).
+ * Strings will be html-escaped; use an OO.ui.HtmlSnippet to append raw HTML.
+ * Instances of OO.ui.Element will have their $element appended.
+ * @cfg {jQuery} [$content] Content elements to append (after #text).
+ * @cfg {jQuery} [$element] Wrapper element. Defaults to a new element with #getTagName.
+ * @cfg {Mixed} [data] Custom data of any type or combination of types (e.g., string, number, array, object).
+ * Data can also be specified with the #setData method.
+ */
+OO.ui.Element = function OoUiElement( config ) {
+ this.initialConfig = config;
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.$ = $;
+ this.elementId = null;
+ this.visible = true;
+ this.data = config.data;
+ this.$element = config.$element ||
+ $( document.createElement( this.getTagName() ) );
+ this.elementGroup = null;
+
+ // Initialization
+ if ( Array.isArray( config.classes ) ) {
+ this.$element.addClass( config.classes.join( ' ' ) );
+ }
+ if ( config.id ) {
+ this.setElementId( config.id );
+ }
+ if ( config.text ) {
+ this.$element.text( config.text );
+ }
+ if ( config.content ) {
+ // The `content` property treats plain strings as text; use an
+ // HtmlSnippet to append HTML content. `OO.ui.Element`s get their
+ // appropriate $element appended.
+ this.$element.append( config.content.map( function ( v ) {
+ if ( typeof v === 'string' ) {
+ // Escape string so it is properly represented in HTML.
+ return document.createTextNode( v );
+ } else if ( v instanceof OO.ui.HtmlSnippet ) {
+ // Bypass escaping.
+ return v.toString();
+ } else if ( v instanceof OO.ui.Element ) {
+ return v.$element;
+ }
+ return v;
+ } ) );
+ }
+ if ( config.$content ) {
+ // The `$content` property treats plain strings as HTML.
+ this.$element.append( config.$content );
+ }
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.Element );
+
+/* Static Properties */
+
+/**
+ * The name of the HTML tag used by the element.
+ *
+ * The static value may be ignored if the #getTagName method is overridden.
+ *
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.Element.static.tagName = 'div';
+
+/* Static Methods */
+
+/**
+ * Reconstitute a JavaScript object corresponding to a widget created
+ * by the PHP implementation.
+ *
+ * @param {string|HTMLElement|jQuery} idOrNode
+ * A DOM id (if a string) or node for the widget to infuse.
+ * @return {OO.ui.Element}
+ * The `OO.ui.Element` corresponding to this (infusable) document node.
+ * For `Tag` objects emitted on the HTML side (used occasionally for content)
+ * the value returned is a newly-created Element wrapping around the existing
+ * DOM node.
+ */
+OO.ui.Element.static.infuse = function ( idOrNode ) {
+ var obj = OO.ui.Element.static.unsafeInfuse( idOrNode, false );
+ // Verify that the type matches up.
+ // FIXME: uncomment after T89721 is fixed, see T90929.
+ /*
+ if ( !( obj instanceof this['class'] ) ) {
+ throw new Error( 'Infusion type mismatch!' );
+ }
+ */
+ return obj;
+};
+
+/**
+ * Implementation helper for `infuse`; skips the type check and has an
+ * extra property so that only the top-level invocation touches the DOM.
+ *
+ * @private
+ * @param {string|HTMLElement|jQuery} idOrNode
+ * @param {jQuery.Promise|boolean} domPromise A promise that will be resolved
+ * when the top-level widget of this infusion is inserted into DOM,
+ * replacing the original node; or false for top-level invocation.
+ * @return {OO.ui.Element}
+ */
+OO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) {
+ // look for a cached result of a previous infusion.
+ var id, $elem, error, data, cls, parts, parent, obj, top, state, infusedChildren;
+ if ( typeof idOrNode === 'string' ) {
+ id = idOrNode;
+ $elem = $( document.getElementById( id ) );
+ } else {
+ $elem = $( idOrNode );
+ id = $elem.attr( 'id' );
+ }
+ if ( !$elem.length ) {
+ if ( typeof idOrNode === 'string' ) {
+ error = 'Widget not found: ' + idOrNode;
+ } else if ( idOrNode && idOrNode.selector ) {
+ error = 'Widget not found: ' + idOrNode.selector;
+ } else {
+ error = 'Widget not found';
+ }
+ throw new Error( error );
+ }
+ if ( $elem[ 0 ].oouiInfused ) {
+ $elem = $elem[ 0 ].oouiInfused;
+ }
+ data = $elem.data( 'ooui-infused' );
+ if ( data ) {
+ // cached!
+ if ( data === true ) {
+ throw new Error( 'Circular dependency! ' + id );
+ }
+ if ( domPromise ) {
+ // pick up dynamic state, like focus, value of form inputs, scroll position, etc.
+ state = data.constructor.static.gatherPreInfuseState( $elem, data );
+ // restore dynamic state after the new element is re-inserted into DOM under infused parent
+ domPromise.done( data.restorePreInfuseState.bind( data, state ) );
+ infusedChildren = $elem.data( 'ooui-infused-children' );
+ if ( infusedChildren && infusedChildren.length ) {
+ infusedChildren.forEach( function ( data ) {
+ var state = data.constructor.static.gatherPreInfuseState( $elem, data );
+ domPromise.done( data.restorePreInfuseState.bind( data, state ) );
+ } );
+ }
+ }
+ return data;
+ }
+ data = $elem.attr( 'data-ooui' );
+ if ( !data ) {
+ throw new Error( 'No infusion data found: ' + id );
+ }
+ try {
+ data = JSON.parse( data );
+ } catch ( _ ) {
+ data = null;
+ }
+ if ( !( data && data._ ) ) {
+ throw new Error( 'No valid infusion data found: ' + id );
+ }
+ if ( data._ === 'Tag' ) {
+ // Special case: this is a raw Tag; wrap existing node, don't rebuild.
+ return new OO.ui.Element( { $element: $elem } );
+ }
+ parts = data._.split( '.' );
+ cls = OO.getProp.apply( OO, [ window ].concat( parts ) );
+ if ( cls === undefined ) {
+ throw new Error( 'Unknown widget type: id: ' + id + ', class: ' + data._ );
+ }
+
+ // Verify that we're creating an OO.ui.Element instance
+ parent = cls.parent;
+
+ while ( parent !== undefined ) {
+ if ( parent === OO.ui.Element ) {
+ // Safe
+ break;
+ }
+
+ parent = parent.parent;
+ }
+
+ if ( parent !== OO.ui.Element ) {
+ throw new Error( 'Unknown widget type: id: ' + id + ', class: ' + data._ );
+ }
+
+ if ( domPromise === false ) {
+ top = $.Deferred();
+ domPromise = top.promise();
+ }
+ $elem.data( 'ooui-infused', true ); // prevent loops
+ data.id = id; // implicit
+ infusedChildren = [];
+ data = OO.copy( data, null, function deserialize( value ) {
+ var infused;
+ if ( OO.isPlainObject( value ) ) {
+ if ( value.tag ) {
+ infused = OO.ui.Element.static.unsafeInfuse( value.tag, domPromise );
+ infusedChildren.push( infused );
+ // Flatten the structure
+ infusedChildren.push.apply( infusedChildren, infused.$element.data( 'ooui-infused-children' ) || [] );
+ infused.$element.removeData( 'ooui-infused-children' );
+ return infused;
+ }
+ if ( value.html !== undefined ) {
+ return new OO.ui.HtmlSnippet( value.html );
+ }
+ }
+ } );
+ // allow widgets to reuse parts of the DOM
+ data = cls.static.reusePreInfuseDOM( $elem[ 0 ], data );
+ // pick up dynamic state, like focus, value of form inputs, scroll position, etc.
+ state = cls.static.gatherPreInfuseState( $elem[ 0 ], data );
+ // rebuild widget
+ // eslint-disable-next-line new-cap
+ obj = new cls( data );
+ // now replace old DOM with this new DOM.
+ if ( top ) {
+ // An efficient constructor might be able to reuse the entire DOM tree of the original element,
+ // so only mutate the DOM if we need to.
+ if ( $elem[ 0 ] !== obj.$element[ 0 ] ) {
+ $elem.replaceWith( obj.$element );
+ // This element is now gone from the DOM, but if anyone is holding a reference to it,
+ // let's allow them to OO.ui.infuse() it and do what they expect, see T105828.
+ // Do not use jQuery.data(), as using it on detached nodes leaks memory in 1.x line by design.
+ $elem[ 0 ].oouiInfused = obj.$element;
+ }
+ top.resolve();
+ }
+ obj.$element.data( 'ooui-infused', obj );
+ obj.$element.data( 'ooui-infused-children', infusedChildren );
+ // set the 'data-ooui' attribute so we can identify infused widgets
+ obj.$element.attr( 'data-ooui', '' );
+ // restore dynamic state after the new element is inserted into DOM
+ domPromise.done( obj.restorePreInfuseState.bind( obj, state ) );
+ return obj;
+};
+
+/**
+ * Pick out parts of `node`'s DOM to be reused when infusing a widget.
+ *
+ * This method **must not** make any changes to the DOM, only find interesting pieces and add them
+ * to `config` (which should then be returned). Actual DOM juggling should then be done by the
+ * constructor, which will be given the enhanced config.
+ *
+ * @protected
+ * @param {HTMLElement} node
+ * @param {Object} config
+ * @return {Object}
+ */
+OO.ui.Element.static.reusePreInfuseDOM = function ( node, config ) {
+ return config;
+};
+
+/**
+ * Gather the dynamic state (focus, value of form inputs, scroll position, etc.) of an HTML DOM node
+ * (and its children) that represent an Element of the same class and the given configuration,
+ * generated by the PHP implementation.
+ *
+ * This method is called just before `node` is detached from the DOM. The return value of this
+ * function will be passed to #restorePreInfuseState after the newly created widget's #$element
+ * is inserted into DOM to replace `node`.
+ *
+ * @protected
+ * @param {HTMLElement} node
+ * @param {Object} config
+ * @return {Object}
+ */
+OO.ui.Element.static.gatherPreInfuseState = function () {
+ return {};
+};
+
+/**
+ * Get a jQuery function within a specific document.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} context Context to bind the function to
+ * @param {jQuery} [$iframe] HTML iframe element that contains the document, omit if document is
+ * not in an iframe
+ * @return {Function} Bound jQuery function
+ */
+OO.ui.Element.static.getJQuery = function ( context, $iframe ) {
+ function wrapper( selector ) {
+ return $( selector, wrapper.context );
+ }
+
+ wrapper.context = this.getDocument( context );
+
+ if ( $iframe ) {
+ wrapper.$iframe = $iframe;
+ }
+
+ return wrapper;
+};
+
+/**
+ * Get the document of an element.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Object to get the document for
+ * @return {HTMLDocument|null} Document object
+ */
+OO.ui.Element.static.getDocument = function ( obj ) {
+ // jQuery - selections created "offscreen" won't have a context, so .context isn't reliable
+ return ( obj[ 0 ] && obj[ 0 ].ownerDocument ) ||
+ // Empty jQuery selections might have a context
+ obj.context ||
+ // HTMLElement
+ obj.ownerDocument ||
+ // Window
+ obj.document ||
+ // HTMLDocument
+ ( obj.nodeType === Node.DOCUMENT_NODE && obj ) ||
+ null;
+};
+
+/**
+ * Get the window of an element or document.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the window for
+ * @return {Window} Window object
+ */
+OO.ui.Element.static.getWindow = function ( obj ) {
+ var doc = this.getDocument( obj );
+ return doc.defaultView;
+};
+
+/**
+ * Get the direction of an element or document.
+ *
+ * @static
+ * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the direction for
+ * @return {string} Text direction, either 'ltr' or 'rtl'
+ */
+OO.ui.Element.static.getDir = function ( obj ) {
+ var isDoc, isWin;
+
+ if ( obj instanceof jQuery ) {
+ obj = obj[ 0 ];
+ }
+ isDoc = obj.nodeType === Node.DOCUMENT_NODE;
+ isWin = obj.document !== undefined;
+ if ( isDoc || isWin ) {
+ if ( isWin ) {
+ obj = obj.document;
+ }
+ obj = obj.body;
+ }
+ return $( obj ).css( 'direction' );
+};
+
+/**
+ * Get the offset between two frames.
+ *
+ * TODO: Make this function not use recursion.
+ *
+ * @static
+ * @param {Window} from Window of the child frame
+ * @param {Window} [to=window] Window of the parent frame
+ * @param {Object} [offset] Offset to start with, used internally
+ * @return {Object} Offset object, containing left and top properties
+ */
+OO.ui.Element.static.getFrameOffset = function ( from, to, offset ) {
+ var i, len, frames, frame, rect;
+
+ if ( !to ) {
+ to = window;
+ }
+ if ( !offset ) {
+ offset = { top: 0, left: 0 };
+ }
+ if ( from.parent === from ) {
+ return offset;
+ }
+
+ // Get iframe element
+ frames = from.parent.document.getElementsByTagName( 'iframe' );
+ for ( i = 0, len = frames.length; i < len; i++ ) {
+ if ( frames[ i ].contentWindow === from ) {
+ frame = frames[ i ];
+ break;
+ }
+ }
+
+ // Recursively accumulate offset values
+ if ( frame ) {
+ rect = frame.getBoundingClientRect();
+ offset.left += rect.left;
+ offset.top += rect.top;
+ if ( from !== to ) {
+ this.getFrameOffset( from.parent, offset );
+ }
+ }
+ return offset;
+};
+
+/**
+ * Get the offset between two elements.
+ *
+ * The two elements may be in a different frame, but in that case the frame $element is in must
+ * be contained in the frame $anchor is in.
+ *
+ * @static
+ * @param {jQuery} $element Element whose position to get
+ * @param {jQuery} $anchor Element to get $element's position relative to
+ * @return {Object} Translated position coordinates, containing top and left properties
+ */
+OO.ui.Element.static.getRelativePosition = function ( $element, $anchor ) {
+ var iframe, iframePos,
+ pos = $element.offset(),
+ anchorPos = $anchor.offset(),
+ elementDocument = this.getDocument( $element ),
+ anchorDocument = this.getDocument( $anchor );
+
+ // If $element isn't in the same document as $anchor, traverse up
+ while ( elementDocument !== anchorDocument ) {
+ iframe = elementDocument.defaultView.frameElement;
+ if ( !iframe ) {
+ throw new Error( '$element frame is not contained in $anchor frame' );
+ }
+ iframePos = $( iframe ).offset();
+ pos.left += iframePos.left;
+ pos.top += iframePos.top;
+ elementDocument = iframe.ownerDocument;
+ }
+ pos.left -= anchorPos.left;
+ pos.top -= anchorPos.top;
+ return pos;
+};
+
+/**
+ * Get element border sizes.
+ *
+ * @static
+ * @param {HTMLElement} el Element to measure
+ * @return {Object} Dimensions object with `top`, `left`, `bottom` and `right` properties
+ */
+OO.ui.Element.static.getBorders = function ( el ) {
+ var doc = el.ownerDocument,
+ win = doc.defaultView,
+ style = win.getComputedStyle( el, null ),
+ $el = $( el ),
+ top = parseFloat( style ? style.borderTopWidth : $el.css( 'borderTopWidth' ) ) || 0,
+ left = parseFloat( style ? style.borderLeftWidth : $el.css( 'borderLeftWidth' ) ) || 0,
+ bottom = parseFloat( style ? style.borderBottomWidth : $el.css( 'borderBottomWidth' ) ) || 0,
+ right = parseFloat( style ? style.borderRightWidth : $el.css( 'borderRightWidth' ) ) || 0;
+
+ return {
+ top: top,
+ left: left,
+ bottom: bottom,
+ right: right
+ };
+};
+
+/**
+ * Get dimensions of an element or window.
+ *
+ * @static
+ * @param {HTMLElement|Window} el Element to measure
+ * @return {Object} Dimensions object with `borders`, `scroll`, `scrollbar` and `rect` properties
+ */
+OO.ui.Element.static.getDimensions = function ( el ) {
+ var $el, $win,
+ doc = el.ownerDocument || el.document,
+ win = doc.defaultView;
+
+ if ( win === el || el === doc.documentElement ) {
+ $win = $( win );
+ return {
+ borders: { top: 0, left: 0, bottom: 0, right: 0 },
+ scroll: {
+ top: $win.scrollTop(),
+ left: $win.scrollLeft()
+ },
+ scrollbar: { right: 0, bottom: 0 },
+ rect: {
+ top: 0,
+ left: 0,
+ bottom: $win.innerHeight(),
+ right: $win.innerWidth()
+ }
+ };
+ } else {
+ $el = $( el );
+ return {
+ borders: this.getBorders( el ),
+ scroll: {
+ top: $el.scrollTop(),
+ left: $el.scrollLeft()
+ },
+ scrollbar: {
+ right: $el.innerWidth() - el.clientWidth,
+ bottom: $el.innerHeight() - el.clientHeight
+ },
+ rect: el.getBoundingClientRect()
+ };
+ }
+};
+
+/**
+ * Get the number of pixels that an element's content is scrolled to the left.
+ *
+ * Adapted from <https://github.com/othree/jquery.rtl-scroll-type>.
+ * Original code copyright 2012 Wei-Ko Kao, licensed under the MIT License.
+ *
+ * This function smooths out browser inconsistencies (nicely described in the README at
+ * <https://github.com/othree/jquery.rtl-scroll-type>) and produces a result consistent
+ * with Firefox's 'scrollLeft', which seems the sanest.
+ *
+ * @static
+ * @method
+ * @param {HTMLElement|Window} el Element to measure
+ * @return {number} Scroll position from the left.
+ * If the element's direction is LTR, this is a positive number between `0` (initial scroll position)
+ * and `el.scrollWidth - el.clientWidth` (furthest possible scroll position).
+ * If the element's direction is RTL, this is a negative number between `0` (initial scroll position)
+ * and `-el.scrollWidth + el.clientWidth` (furthest possible scroll position).
+ */
+OO.ui.Element.static.getScrollLeft = ( function () {
+ var rtlScrollType = null;
+
+ function test() {
+ var $definer = $( '<div dir="rtl" style="font-size: 14px; width: 1px; height: 1px; position: absolute; top: -1000px; overflow: scroll">A</div>' ),
+ definer = $definer[ 0 ];
+
+ $definer.appendTo( 'body' );
+ if ( definer.scrollLeft > 0 ) {
+ // Safari, Chrome
+ rtlScrollType = 'default';
+ } else {
+ definer.scrollLeft = 1;
+ if ( definer.scrollLeft === 0 ) {
+ // Firefox, old Opera
+ rtlScrollType = 'negative';
+ } else {
+ // Internet Explorer, Edge
+ rtlScrollType = 'reverse';
+ }
+ }
+ $definer.remove();
+ }
+
+ return function getScrollLeft( el ) {
+ var isRoot = el.window === el ||
+ el === el.ownerDocument.body ||
+ el === el.ownerDocument.documentElement,
+ scrollLeft = isRoot ? $( window ).scrollLeft() : el.scrollLeft,
+ // All browsers use the correct scroll type ('negative') on the root, so don't
+ // do any fixups when looking at the root element
+ direction = isRoot ? 'ltr' : $( el ).css( 'direction' );
+
+ if ( direction === 'rtl' ) {
+ if ( rtlScrollType === null ) {
+ test();
+ }
+ if ( rtlScrollType === 'reverse' ) {
+ scrollLeft = -scrollLeft;
+ } else if ( rtlScrollType === 'default' ) {
+ scrollLeft = scrollLeft - el.scrollWidth + el.clientWidth;
+ }
+ }
+
+ return scrollLeft;
+ };
+}() );
+
+/**
+ * Get the root scrollable element of given element's document.
+ *
+ * On Blink-based browsers (Chrome etc.), `document.documentElement` can't be used to get or set
+ * the scrollTop property; instead we have to use `document.body`. Changing and testing the value
+ * lets us use 'body' or 'documentElement' based on what is working.
+ *
+ * https://code.google.com/p/chromium/issues/detail?id=303131
+ *
+ * @static
+ * @param {HTMLElement} el Element to find root scrollable parent for
+ * @return {HTMLElement} Scrollable parent, `document.body` or `document.documentElement`
+ * depending on browser
+ */
+OO.ui.Element.static.getRootScrollableElement = function ( el ) {
+ var scrollTop, body;
+
+ if ( OO.ui.scrollableElement === undefined ) {
+ body = el.ownerDocument.body;
+ scrollTop = body.scrollTop;
+ body.scrollTop = 1;
+
+ // In some browsers (observed in Chrome 56 on Linux Mint 18.1),
+ // body.scrollTop doesn't become exactly 1, but a fractional value like 0.76
+ if ( Math.round( body.scrollTop ) === 1 ) {
+ body.scrollTop = scrollTop;
+ OO.ui.scrollableElement = 'body';
+ } else {
+ OO.ui.scrollableElement = 'documentElement';
+ }
+ }
+
+ return el.ownerDocument[ OO.ui.scrollableElement ];
+};
+
+/**
+ * Get closest scrollable container.
+ *
+ * Traverses up until either a scrollable element or the root is reached, in which case the root
+ * scrollable element will be returned (see #getRootScrollableElement).
+ *
+ * @static
+ * @param {HTMLElement} el Element to find scrollable container for
+ * @param {string} [dimension] Dimension of scrolling to look for; `x`, `y` or omit for either
+ * @return {HTMLElement} Closest scrollable container
+ */
+OO.ui.Element.static.getClosestScrollableContainer = function ( el, dimension ) {
+ var i, val,
+ // Browsers do not correctly return the computed value of 'overflow' when 'overflow-x' and
+ // 'overflow-y' have different values, so we need to check the separate properties.
+ props = [ 'overflow-x', 'overflow-y' ],
+ $parent = $( el ).parent();
+
+ if ( dimension === 'x' || dimension === 'y' ) {
+ props = [ 'overflow-' + dimension ];
+ }
+
+ // Special case for the document root (which doesn't really have any scrollable container, since
+ // it is the ultimate scrollable container, but this is probably saner than null or exception)
+ if ( $( el ).is( 'html, body' ) ) {
+ return this.getRootScrollableElement( el );
+ }
+
+ while ( $parent.length ) {
+ if ( $parent[ 0 ] === this.getRootScrollableElement( el ) ) {
+ return $parent[ 0 ];
+ }
+ i = props.length;
+ while ( i-- ) {
+ val = $parent.css( props[ i ] );
+ // We assume that elements with 'overflow' (in any direction) set to 'hidden' will never be
+ // scrolled in that direction, but they can actually be scrolled programatically. The user can
+ // unintentionally perform a scroll in such case even if the application doesn't scroll
+ // programatically, e.g. when jumping to an anchor, or when using built-in find functionality.
+ // This could cause funny issues...
+ if ( val === 'auto' || val === 'scroll' ) {
+ return $parent[ 0 ];
+ }
+ }
+ $parent = $parent.parent();
+ }
+ // The element is unattached... return something mostly sane
+ return this.getRootScrollableElement( el );
+};
+
+/**
+ * Scroll element into view.
+ *
+ * @static
+ * @param {HTMLElement} el Element to scroll into view
+ * @param {Object} [config] Configuration options
+ * @param {string} [config.duration='fast'] jQuery animation duration value
+ * @param {string} [config.direction] Scroll in only one direction, e.g. 'x' or 'y', omit
+ * to scroll in both directions
+ * @return {jQuery.Promise} Promise which resolves when the scroll is complete
+ */
+OO.ui.Element.static.scrollIntoView = function ( el, config ) {
+ var position, animations, container, $container, elementDimensions, containerDimensions, $window,
+ deferred = $.Deferred();
+
+ // Configuration initialization
+ config = config || {};
+
+ animations = {};
+ container = this.getClosestScrollableContainer( el, config.direction );
+ $container = $( container );
+ elementDimensions = this.getDimensions( el );
+ containerDimensions = this.getDimensions( container );
+ $window = $( this.getWindow( el ) );
+
+ // Compute the element's position relative to the container
+ if ( $container.is( 'html, body' ) ) {
+ // If the scrollable container is the root, this is easy
+ position = {
+ top: elementDimensions.rect.top,
+ bottom: $window.innerHeight() - elementDimensions.rect.bottom,
+ left: elementDimensions.rect.left,
+ right: $window.innerWidth() - elementDimensions.rect.right
+ };
+ } else {
+ // Otherwise, we have to subtract el's coordinates from container's coordinates
+ position = {
+ top: elementDimensions.rect.top - ( containerDimensions.rect.top + containerDimensions.borders.top ),
+ bottom: containerDimensions.rect.bottom - containerDimensions.borders.bottom - containerDimensions.scrollbar.bottom - elementDimensions.rect.bottom,
+ left: elementDimensions.rect.left - ( containerDimensions.rect.left + containerDimensions.borders.left ),
+ right: containerDimensions.rect.right - containerDimensions.borders.right - containerDimensions.scrollbar.right - elementDimensions.rect.right
+ };
+ }
+
+ if ( !config.direction || config.direction === 'y' ) {
+ if ( position.top < 0 ) {
+ animations.scrollTop = containerDimensions.scroll.top + position.top;
+ } else if ( position.top > 0 && position.bottom < 0 ) {
+ animations.scrollTop = containerDimensions.scroll.top + Math.min( position.top, -position.bottom );
+ }
+ }
+ if ( !config.direction || config.direction === 'x' ) {
+ if ( position.left < 0 ) {
+ animations.scrollLeft = containerDimensions.scroll.left + position.left;
+ } else if ( position.left > 0 && position.right < 0 ) {
+ animations.scrollLeft = containerDimensions.scroll.left + Math.min( position.left, -position.right );
+ }
+ }
+ if ( !$.isEmptyObject( animations ) ) {
+ $container.stop( true ).animate( animations, config.duration === undefined ? 'fast' : config.duration );
+ $container.queue( function ( next ) {
+ deferred.resolve();
+ next();
+ } );
+ } else {
+ deferred.resolve();
+ }
+ return deferred.promise();
+};
+
+/**
+ * Force the browser to reconsider whether it really needs to render scrollbars inside the element
+ * and reserve space for them, because it probably doesn't.
+ *
+ * Workaround primarily for <https://code.google.com/p/chromium/issues/detail?id=387290>, but also
+ * similar bugs in other browsers. "Just" forcing a reflow is not sufficient in all cases, we need
+ * to first actually detach (or hide, but detaching is simpler) all children, *then* force a reflow,
+ * and then reattach (or show) them back.
+ *
+ * @static
+ * @param {HTMLElement} el Element to reconsider the scrollbars on
+ */
+OO.ui.Element.static.reconsiderScrollbars = function ( el ) {
+ var i, len, scrollLeft, scrollTop, nodes = [];
+ // Save scroll position
+ scrollLeft = el.scrollLeft;
+ scrollTop = el.scrollTop;
+ // Detach all children
+ while ( el.firstChild ) {
+ nodes.push( el.firstChild );
+ el.removeChild( el.firstChild );
+ }
+ // Force reflow
+ void el.offsetHeight;
+ // Reattach all children
+ for ( i = 0, len = nodes.length; i < len; i++ ) {
+ el.appendChild( nodes[ i ] );
+ }
+ // Restore scroll position (no-op if scrollbars disappeared)
+ el.scrollLeft = scrollLeft;
+ el.scrollTop = scrollTop;
+};
+
+/* Methods */
+
+/**
+ * Toggle visibility of an element.
+ *
+ * @param {boolean} [show] Make element visible, omit to toggle visibility
+ * @fires visible
+ * @chainable
+ */
+OO.ui.Element.prototype.toggle = function ( show ) {
+ show = show === undefined ? !this.visible : !!show;
+
+ if ( show !== this.isVisible() ) {
+ this.visible = show;
+ this.$element.toggleClass( 'oo-ui-element-hidden', !this.visible );
+ this.emit( 'toggle', show );
+ }
+
+ return this;
+};
+
+/**
+ * Check if element is visible.
+ *
+ * @return {boolean} element is visible
+ */
+OO.ui.Element.prototype.isVisible = function () {
+ return this.visible;
+};
+
+/**
+ * Get element data.
+ *
+ * @return {Mixed} Element data
+ */
+OO.ui.Element.prototype.getData = function () {
+ return this.data;
+};
+
+/**
+ * Set element data.
+ *
+ * @param {Mixed} data Element data
+ * @chainable
+ */
+OO.ui.Element.prototype.setData = function ( data ) {
+ this.data = data;
+ return this;
+};
+
+/**
+ * Set the element has an 'id' attribute.
+ *
+ * @param {string} id
+ * @chainable
+ */
+OO.ui.Element.prototype.setElementId = function ( id ) {
+ this.elementId = id;
+ this.$element.attr( 'id', id );
+ return this;
+};
+
+/**
+ * Ensure that the element has an 'id' attribute, setting it to an unique value if it's missing,
+ * and return its value.
+ *
+ * @return {string}
+ */
+OO.ui.Element.prototype.getElementId = function () {
+ if ( this.elementId === null ) {
+ this.setElementId( OO.ui.generateElementId() );
+ }
+ return this.elementId;
+};
+
+/**
+ * Check if element supports one or more methods.
+ *
+ * @param {string|string[]} methods Method or list of methods to check
+ * @return {boolean} All methods are supported
+ */
+OO.ui.Element.prototype.supports = function ( methods ) {
+ var i, len,
+ support = 0;
+
+ methods = Array.isArray( methods ) ? methods : [ methods ];
+ for ( i = 0, len = methods.length; i < len; i++ ) {
+ if ( $.isFunction( this[ methods[ i ] ] ) ) {
+ support++;
+ }
+ }
+
+ return methods.length === support;
+};
+
+/**
+ * Update the theme-provided classes.
+ *
+ * @localdoc This is called in element mixins and widget classes any time state changes.
+ * Updating is debounced, minimizing overhead of changing multiple attributes and
+ * guaranteeing that theme updates do not occur within an element's constructor
+ */
+OO.ui.Element.prototype.updateThemeClasses = function () {
+ OO.ui.theme.queueUpdateElementClasses( this );
+};
+
+/**
+ * Get the HTML tag name.
+ *
+ * Override this method to base the result on instance information.
+ *
+ * @return {string} HTML tag name
+ */
+OO.ui.Element.prototype.getTagName = function () {
+ return this.constructor.static.tagName;
+};
+
+/**
+ * Check if the element is attached to the DOM
+ *
+ * @return {boolean} The element is attached to the DOM
+ */
+OO.ui.Element.prototype.isElementAttached = function () {
+ return $.contains( this.getElementDocument(), this.$element[ 0 ] );
+};
+
+/**
+ * Get the DOM document.
+ *
+ * @return {HTMLDocument} Document object
+ */
+OO.ui.Element.prototype.getElementDocument = function () {
+ // Don't cache this in other ways either because subclasses could can change this.$element
+ return OO.ui.Element.static.getDocument( this.$element );
+};
+
+/**
+ * Get the DOM window.
+ *
+ * @return {Window} Window object
+ */
+OO.ui.Element.prototype.getElementWindow = function () {
+ return OO.ui.Element.static.getWindow( this.$element );
+};
+
+/**
+ * Get closest scrollable container.
+ *
+ * @return {HTMLElement} Closest scrollable container
+ */
+OO.ui.Element.prototype.getClosestScrollableElementContainer = function () {
+ return OO.ui.Element.static.getClosestScrollableContainer( this.$element[ 0 ] );
+};
+
+/**
+ * Get group element is in.
+ *
+ * @return {OO.ui.mixin.GroupElement|null} Group element, null if none
+ */
+OO.ui.Element.prototype.getElementGroup = function () {
+ return this.elementGroup;
+};
+
+/**
+ * Set group element is in.
+ *
+ * @param {OO.ui.mixin.GroupElement|null} group Group element, null if none
+ * @chainable
+ */
+OO.ui.Element.prototype.setElementGroup = function ( group ) {
+ this.elementGroup = group;
+ return this;
+};
+
+/**
+ * Scroll element into view.
+ *
+ * @param {Object} [config] Configuration options
+ * @return {jQuery.Promise} Promise which resolves when the scroll is complete
+ */
+OO.ui.Element.prototype.scrollElementIntoView = function ( config ) {
+ if (
+ !this.isElementAttached() ||
+ !this.isVisible() ||
+ ( this.getElementGroup() && !this.getElementGroup().isVisible() )
+ ) {
+ return $.Deferred().resolve();
+ }
+ return OO.ui.Element.static.scrollIntoView( this.$element[ 0 ], config );
+};
+
+/**
+ * Restore the pre-infusion dynamic state for this widget.
+ *
+ * This method is called after #$element has been inserted into DOM. The parameter is the return
+ * value of #gatherPreInfuseState.
+ *
+ * @protected
+ * @param {Object} state
+ */
+OO.ui.Element.prototype.restorePreInfuseState = function () {
+};
+
+/**
+ * Wraps an HTML snippet for use with configuration values which default
+ * to strings. This bypasses the default html-escaping done to string
+ * values.
+ *
+ * @class
+ *
+ * @constructor
+ * @param {string} [content] HTML content
+ */
+OO.ui.HtmlSnippet = function OoUiHtmlSnippet( content ) {
+ // Properties
+ this.content = content;
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.HtmlSnippet );
+
+/* Methods */
+
+/**
+ * Render into HTML.
+ *
+ * @return {string} Unchanged HTML snippet.
+ */
+OO.ui.HtmlSnippet.prototype.toString = function () {
+ return this.content;
+};
+
+/**
+ * Layouts are containers for elements and are used to arrange other widgets of arbitrary type in a way
+ * that is centrally controlled and can be updated dynamically. Layouts can be, and usually are, combined.
+ * See {@link OO.ui.FieldsetLayout FieldsetLayout}, {@link OO.ui.FieldLayout FieldLayout}, {@link OO.ui.FormLayout FormLayout},
+ * {@link OO.ui.PanelLayout PanelLayout}, {@link OO.ui.StackLayout StackLayout}, {@link OO.ui.PageLayout PageLayout},
+ * {@link OO.ui.HorizontalLayout HorizontalLayout}, and {@link OO.ui.BookletLayout BookletLayout} for more information and examples.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.Layout = function OoUiLayout( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.Layout.parent.call( this, config );
+
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-layout' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Layout, OO.ui.Element );
+OO.mixinClass( OO.ui.Layout, OO.EventEmitter );
+
+/**
+ * Widgets are compositions of one or more OOjs UI elements that users can both view
+ * and interact with. All widgets can be configured and modified via a standard API,
+ * and their state can change dynamically according to a model.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [disabled=false] Disable the widget. Disabled widgets cannot be used and their
+ * appearance reflects this state.
+ */
+OO.ui.Widget = function OoUiWidget( config ) {
+ // Initialize config
+ config = $.extend( { disabled: false }, config );
+
+ // Parent constructor
+ OO.ui.Widget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+
+ // Properties
+ this.disabled = null;
+ this.wasDisabled = null;
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-widget' );
+ this.setDisabled( !!config.disabled );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Widget, OO.ui.Element );
+OO.mixinClass( OO.ui.Widget, OO.EventEmitter );
+
+/* Events */
+
+/**
+ * @event disable
+ *
+ * A 'disable' event is emitted when the disabled state of the widget changes
+ * (i.e. on disable **and** enable).
+ *
+ * @param {boolean} disabled Widget is disabled
+ */
+
+/**
+ * @event toggle
+ *
+ * A 'toggle' event is emitted when the visibility of the widget changes.
+ *
+ * @param {boolean} visible Widget is visible
+ */
+
+/* Methods */
+
+/**
+ * Check if the widget is disabled.
+ *
+ * @return {boolean} Widget is disabled
+ */
+OO.ui.Widget.prototype.isDisabled = function () {
+ return this.disabled;
+};
+
+/**
+ * Set the 'disabled' state of the widget.
+ *
+ * When a widget is disabled, it cannot be used and its appearance is updated to reflect this state.
+ *
+ * @param {boolean} disabled Disable widget
+ * @chainable
+ */
+OO.ui.Widget.prototype.setDisabled = function ( disabled ) {
+ var isDisabled;
+
+ this.disabled = !!disabled;
+ isDisabled = this.isDisabled();
+ if ( isDisabled !== this.wasDisabled ) {
+ this.$element.toggleClass( 'oo-ui-widget-disabled', isDisabled );
+ this.$element.toggleClass( 'oo-ui-widget-enabled', !isDisabled );
+ this.$element.attr( 'aria-disabled', isDisabled.toString() );
+ this.emit( 'disable', isDisabled );
+ this.updateThemeClasses();
+ }
+ this.wasDisabled = isDisabled;
+
+ return this;
+};
+
+/**
+ * Update the disabled state, in case of changes in parent widget.
+ *
+ * @chainable
+ */
+OO.ui.Widget.prototype.updateDisabled = function () {
+ this.setDisabled( this.disabled );
+ return this;
+};
+
+/**
+ * Get an ID of a labelable node which is part of this widget, if any, to be used for `<label for>`
+ * value.
+ *
+ * If this function returns null, the widget should have a meaningful #simulateLabelClick method
+ * instead.
+ *
+ * @return {string|null} The ID of the labelable element
+ */
+OO.ui.Widget.prototype.getInputId = function () {
+ return null;
+};
+
+/**
+ * Simulate the behavior of clicking on a label (a HTML `<label>` element) bound to this input.
+ * HTML only allows `<label>` to act on specific "labelable" elements; complex widgets might need to
+ * override this method to provide intuitive, accessible behavior.
+ *
+ * By default, this does nothing. OO.ui.mixin.TabIndexedElement overrides it for focusable widgets.
+ * Individual widgets may override it too.
+ *
+ * This method is called by OO.ui.LabelWidget and OO.ui.FieldLayout. It should not be called
+ * directly.
+ */
+OO.ui.Widget.prototype.simulateLabelClick = function () {
+};
+
+/**
+ * Theme logic.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ */
+OO.ui.Theme = function OoUiTheme() {
+ this.elementClassesQueue = [];
+ this.debouncedUpdateQueuedElementClasses = OO.ui.debounce( this.updateQueuedElementClasses );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.Theme );
+
+/* Methods */
+
+/**
+ * Get a list of classes to be applied to a widget.
+ *
+ * The 'on' and 'off' lists combined MUST contain keys for all classes the theme adds or removes,
+ * otherwise state transitions will not work properly.
+ *
+ * @param {OO.ui.Element} element Element for which to get classes
+ * @return {Object.<string,string[]>} Categorized class names with `on` and `off` lists
+ */
+OO.ui.Theme.prototype.getElementClasses = function () {
+ return { on: [], off: [] };
+};
+
+/**
+ * Update CSS classes provided by the theme.
+ *
+ * For elements with theme logic hooks, this should be called any time there's a state change.
+ *
+ * @param {OO.ui.Element} element Element for which to update classes
+ */
+OO.ui.Theme.prototype.updateElementClasses = function ( element ) {
+ var $elements = $( [] ),
+ classes = this.getElementClasses( element );
+
+ if ( element.$icon ) {
+ $elements = $elements.add( element.$icon );
+ }
+ if ( element.$indicator ) {
+ $elements = $elements.add( element.$indicator );
+ }
+
+ $elements
+ .removeClass( classes.off.join( ' ' ) )
+ .addClass( classes.on.join( ' ' ) );
+};
+
+/**
+ * @private
+ */
+OO.ui.Theme.prototype.updateQueuedElementClasses = function () {
+ var i;
+ for ( i = 0; i < this.elementClassesQueue.length; i++ ) {
+ this.updateElementClasses( this.elementClassesQueue[ i ] );
+ }
+ // Clear the queue
+ this.elementClassesQueue = [];
+};
+
+/**
+ * Queue #updateElementClasses to be called for this element.
+ *
+ * @localdoc QUnit tests override this method to directly call #queueUpdateElementClasses,
+ * to make them synchronous.
+ *
+ * @param {OO.ui.Element} element Element for which to update classes
+ */
+OO.ui.Theme.prototype.queueUpdateElementClasses = function ( element ) {
+ // Keep items in the queue unique. Use lastIndexOf to start checking from the end because that's
+ // the most common case (this method is often called repeatedly for the same element).
+ if ( this.elementClassesQueue.lastIndexOf( element ) !== -1 ) {
+ return;
+ }
+ this.elementClassesQueue.push( element );
+ this.debouncedUpdateQueuedElementClasses();
+};
+
+/**
+ * Get the transition duration in milliseconds for dialogs opening/closing
+ *
+ * The dialog should be fully rendered this many milliseconds after the
+ * ready process has executed.
+ *
+ * @return {number} Transition duration in milliseconds
+ */
+OO.ui.Theme.prototype.getDialogTransitionDuration = function () {
+ return 0;
+};
+
+/**
+ * The TabIndexedElement class is an attribute mixin used to add additional functionality to an
+ * element created by another class. The mixin provides a ‘tabIndex’ property, which specifies the
+ * order in which users will navigate through the focusable elements via the "tab" key.
+ *
+ * @example
+ * // TabIndexedElement is mixed into the ButtonWidget class
+ * // to provide a tabIndex property.
+ * var button1 = new OO.ui.ButtonWidget( {
+ * label: 'fourth',
+ * tabIndex: 4
+ * } );
+ * var button2 = new OO.ui.ButtonWidget( {
+ * label: 'second',
+ * tabIndex: 2
+ * } );
+ * var button3 = new OO.ui.ButtonWidget( {
+ * label: 'third',
+ * tabIndex: 3
+ * } );
+ * var button4 = new OO.ui.ButtonWidget( {
+ * label: 'first',
+ * tabIndex: 1
+ * } );
+ * $( 'body' ).append( button1.$element, button2.$element, button3.$element, button4.$element );
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$tabIndexed] The element that should use the tabindex functionality. By default,
+ * the functionality is applied to the element created by the class ($element). If a different element is specified, the tabindex
+ * functionality will be applied to it instead.
+ * @cfg {string|number|null} [tabIndex=0] Number that specifies the element’s position in the tab-navigation
+ * order (e.g., 1 for the first focusable element). Use 0 to use the default navigation order; use -1
+ * to remove the element from the tab-navigation flow.
+ */
+OO.ui.mixin.TabIndexedElement = function OoUiMixinTabIndexedElement( config ) {
+ // Configuration initialization
+ config = $.extend( { tabIndex: 0 }, config );
+
+ // Properties
+ this.$tabIndexed = null;
+ this.tabIndex = null;
+
+ // Events
+ this.connect( this, { disable: 'onTabIndexedElementDisable' } );
+
+ // Initialization
+ this.setTabIndex( config.tabIndex );
+ this.setTabIndexedElement( config.$tabIndexed || this.$element );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.mixin.TabIndexedElement );
+
+/* Methods */
+
+/**
+ * Set the element that should use the tabindex functionality.
+ *
+ * This method is used to retarget a tabindex mixin so that its functionality applies
+ * to the specified element. If an element is currently using the functionality, the mixin’s
+ * effect on that element is removed before the new element is set up.
+ *
+ * @param {jQuery} $tabIndexed Element that should use the tabindex functionality
+ * @chainable
+ */
+OO.ui.mixin.TabIndexedElement.prototype.setTabIndexedElement = function ( $tabIndexed ) {
+ var tabIndex = this.tabIndex;
+ // Remove attributes from old $tabIndexed
+ this.setTabIndex( null );
+ // Force update of new $tabIndexed
+ this.$tabIndexed = $tabIndexed;
+ this.tabIndex = tabIndex;
+ return this.updateTabIndex();
+};
+
+/**
+ * Set the value of the tabindex.
+ *
+ * @param {string|number|null} tabIndex Tabindex value, or `null` for no tabindex
+ * @chainable
+ */
+OO.ui.mixin.TabIndexedElement.prototype.setTabIndex = function ( tabIndex ) {
+ tabIndex = /^-?\d+$/.test( tabIndex ) ? Number( tabIndex ) : null;
+
+ if ( this.tabIndex !== tabIndex ) {
+ this.tabIndex = tabIndex;
+ this.updateTabIndex();
+ }
+
+ return this;
+};
+
+/**
+ * Update the `tabindex` attribute, in case of changes to tab index or
+ * disabled state.
+ *
+ * @private
+ * @chainable
+ */
+OO.ui.mixin.TabIndexedElement.prototype.updateTabIndex = function () {
+ if ( this.$tabIndexed ) {
+ if ( this.tabIndex !== null ) {
+ // Do not index over disabled elements
+ this.$tabIndexed.attr( {
+ tabindex: this.isDisabled() ? -1 : this.tabIndex,
+ // Support: ChromeVox and NVDA
+ // These do not seem to inherit aria-disabled from parent elements
+ 'aria-disabled': this.isDisabled().toString()
+ } );
+ } else {
+ this.$tabIndexed.removeAttr( 'tabindex aria-disabled' );
+ }
+ }
+ return this;
+};
+
+/**
+ * Handle disable events.
+ *
+ * @private
+ * @param {boolean} disabled Element is disabled
+ */
+OO.ui.mixin.TabIndexedElement.prototype.onTabIndexedElementDisable = function () {
+ this.updateTabIndex();
+};
+
+/**
+ * Get the value of the tabindex.
+ *
+ * @return {number|null} Tabindex value
+ */
+OO.ui.mixin.TabIndexedElement.prototype.getTabIndex = function () {
+ return this.tabIndex;
+};
+
+/**
+ * Get an ID of a focusable element of this widget, if any, to be used for `<label for>` value.
+ *
+ * If the element already has an ID then that is returned, otherwise unique ID is
+ * generated, set on the element, and returned.
+ *
+ * @return {string|null} The ID of the focusable element
+ */
+OO.ui.mixin.TabIndexedElement.prototype.getInputId = function () {
+ var id;
+
+ if ( !this.$tabIndexed ) {
+ return null;
+ }
+ if ( !this.isLabelableNode( this.$tabIndexed ) ) {
+ return null;
+ }
+
+ id = this.$tabIndexed.attr( 'id' );
+ if ( id === undefined ) {
+ id = OO.ui.generateElementId();
+ this.$tabIndexed.attr( 'id', id );
+ }
+
+ return id;
+};
+
+/**
+ * Whether the node is 'labelable' according to the HTML spec
+ * (i.e., whether it can be interacted with through a `<label for="…">`).
+ * See: <https://html.spec.whatwg.org/multipage/forms.html#category-label>.
+ *
+ * @private
+ * @param {jQuery} $node
+ * @return {boolean}
+ */
+OO.ui.mixin.TabIndexedElement.prototype.isLabelableNode = function ( $node ) {
+ var
+ labelableTags = [ 'button', 'meter', 'output', 'progress', 'select', 'textarea' ],
+ tagName = $node.prop( 'tagName' ).toLowerCase();
+
+ if ( tagName === 'input' && $node.attr( 'type' ) !== 'hidden' ) {
+ return true;
+ }
+ if ( labelableTags.indexOf( tagName ) !== -1 ) {
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Focus this element.
+ *
+ * @chainable
+ */
+OO.ui.mixin.TabIndexedElement.prototype.focus = function () {
+ if ( !this.isDisabled() ) {
+ this.$tabIndexed.focus();
+ }
+ return this;
+};
+
+/**
+ * Blur this element.
+ *
+ * @chainable
+ */
+OO.ui.mixin.TabIndexedElement.prototype.blur = function () {
+ this.$tabIndexed.blur();
+ return this;
+};
+
+/**
+ * @inheritdoc OO.ui.Widget
+ */
+OO.ui.mixin.TabIndexedElement.prototype.simulateLabelClick = function () {
+ this.focus();
+};
+
+/**
+ * ButtonElement is often mixed into other classes to generate a button, which is a clickable
+ * interface element that can be configured with access keys for accessibility.
+ * See the [OOjs UI documentation on MediaWiki] [1] for examples.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches#Buttons
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$button] The button element created by the class.
+ * If this configuration is omitted, the button element will use a generated `<a>`.
+ * @cfg {boolean} [framed=true] Render the button with a frame
+ */
+OO.ui.mixin.ButtonElement = function OoUiMixinButtonElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.$button = null;
+ this.framed = null;
+ this.active = config.active !== undefined && config.active;
+ this.onMouseUpHandler = this.onMouseUp.bind( this );
+ this.onMouseDownHandler = this.onMouseDown.bind( this );
+ this.onKeyDownHandler = this.onKeyDown.bind( this );
+ this.onKeyUpHandler = this.onKeyUp.bind( this );
+ this.onClickHandler = this.onClick.bind( this );
+ this.onKeyPressHandler = this.onKeyPress.bind( this );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-buttonElement' );
+ this.toggleFramed( config.framed === undefined || config.framed );
+ this.setButtonElement( config.$button || $( '<a>' ) );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.mixin.ButtonElement );
+
+/* Static Properties */
+
+/**
+ * Cancel mouse down events.
+ *
+ * This property is usually set to `true` to prevent the focus from changing when the button is clicked.
+ * Classes such as {@link OO.ui.mixin.DraggableElement DraggableElement} and {@link OO.ui.ButtonOptionWidget ButtonOptionWidget}
+ * use a value of `false` so that dragging behavior is possible and mousedown events can be handled by a
+ * parent widget.
+ *
+ * @static
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.mixin.ButtonElement.static.cancelButtonMouseDownEvents = true;
+
+/* Events */
+
+/**
+ * A 'click' event is emitted when the button element is clicked.
+ *
+ * @event click
+ */
+
+/* Methods */
+
+/**
+ * Set the button element.
+ *
+ * This method is used to retarget a button mixin so that its functionality applies to
+ * the specified button element instead of the one created by the class. If a button element
+ * is already set, the method will remove the mixin’s effect on that element.
+ *
+ * @param {jQuery} $button Element to use as button
+ */
+OO.ui.mixin.ButtonElement.prototype.setButtonElement = function ( $button ) {
+ if ( this.$button ) {
+ this.$button
+ .removeClass( 'oo-ui-buttonElement-button' )
+ .removeAttr( 'role accesskey' )
+ .off( {
+ mousedown: this.onMouseDownHandler,
+ keydown: this.onKeyDownHandler,
+ click: this.onClickHandler,
+ keypress: this.onKeyPressHandler
+ } );
+ }
+
+ this.$button = $button
+ .addClass( 'oo-ui-buttonElement-button' )
+ .on( {
+ mousedown: this.onMouseDownHandler,
+ keydown: this.onKeyDownHandler,
+ click: this.onClickHandler,
+ keypress: this.onKeyPressHandler
+ } );
+
+ // Add `role="button"` on `<a>` elements, where it's needed
+ // `toUppercase()` is added for XHTML documents
+ if ( this.$button.prop( 'tagName' ).toUpperCase() === 'A' ) {
+ this.$button.attr( 'role', 'button' );
+ }
+};
+
+/**
+ * Handles mouse down events.
+ *
+ * @protected
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.mixin.ButtonElement.prototype.onMouseDown = function ( e ) {
+ if ( this.isDisabled() || e.which !== OO.ui.MouseButtons.LEFT ) {
+ return;
+ }
+ this.$element.addClass( 'oo-ui-buttonElement-pressed' );
+ // Run the mouseup handler no matter where the mouse is when the button is let go, so we can
+ // reliably remove the pressed class
+ this.getElementDocument().addEventListener( 'mouseup', this.onMouseUpHandler, true );
+ // Prevent change of focus unless specifically configured otherwise
+ if ( this.constructor.static.cancelButtonMouseDownEvents ) {
+ return false;
+ }
+};
+
+/**
+ * Handles mouse up events.
+ *
+ * @protected
+ * @param {MouseEvent} e Mouse up event
+ */
+OO.ui.mixin.ButtonElement.prototype.onMouseUp = function ( e ) {
+ if ( this.isDisabled() || e.which !== OO.ui.MouseButtons.LEFT ) {
+ return;
+ }
+ this.$element.removeClass( 'oo-ui-buttonElement-pressed' );
+ // Stop listening for mouseup, since we only needed this once
+ this.getElementDocument().removeEventListener( 'mouseup', this.onMouseUpHandler, true );
+};
+
+/**
+ * Handles mouse click events.
+ *
+ * @protected
+ * @param {jQuery.Event} e Mouse click event
+ * @fires click
+ */
+OO.ui.mixin.ButtonElement.prototype.onClick = function ( e ) {
+ if ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {
+ if ( this.emit( 'click' ) ) {
+ return false;
+ }
+ }
+};
+
+/**
+ * Handles key down events.
+ *
+ * @protected
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.mixin.ButtonElement.prototype.onKeyDown = function ( e ) {
+ if ( this.isDisabled() || ( e.which !== OO.ui.Keys.SPACE && e.which !== OO.ui.Keys.ENTER ) ) {
+ return;
+ }
+ this.$element.addClass( 'oo-ui-buttonElement-pressed' );
+ // Run the keyup handler no matter where the key is when the button is let go, so we can
+ // reliably remove the pressed class
+ this.getElementDocument().addEventListener( 'keyup', this.onKeyUpHandler, true );
+};
+
+/**
+ * Handles key up events.
+ *
+ * @protected
+ * @param {KeyboardEvent} e Key up event
+ */
+OO.ui.mixin.ButtonElement.prototype.onKeyUp = function ( e ) {
+ if ( this.isDisabled() || ( e.which !== OO.ui.Keys.SPACE && e.which !== OO.ui.Keys.ENTER ) ) {
+ return;
+ }
+ this.$element.removeClass( 'oo-ui-buttonElement-pressed' );
+ // Stop listening for keyup, since we only needed this once
+ this.getElementDocument().removeEventListener( 'keyup', this.onKeyUpHandler, true );
+};
+
+/**
+ * Handles key press events.
+ *
+ * @protected
+ * @param {jQuery.Event} e Key press event
+ * @fires click
+ */
+OO.ui.mixin.ButtonElement.prototype.onKeyPress = function ( e ) {
+ if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) {
+ if ( this.emit( 'click' ) ) {
+ return false;
+ }
+ }
+};
+
+/**
+ * Check if button has a frame.
+ *
+ * @return {boolean} Button is framed
+ */
+OO.ui.mixin.ButtonElement.prototype.isFramed = function () {
+ return this.framed;
+};
+
+/**
+ * Render the button with or without a frame. Omit the `framed` parameter to toggle the button frame on and off.
+ *
+ * @param {boolean} [framed] Make button framed, omit to toggle
+ * @chainable
+ */
+OO.ui.mixin.ButtonElement.prototype.toggleFramed = function ( framed ) {
+ framed = framed === undefined ? !this.framed : !!framed;
+ if ( framed !== this.framed ) {
+ this.framed = framed;
+ this.$element
+ .toggleClass( 'oo-ui-buttonElement-frameless', !framed )
+ .toggleClass( 'oo-ui-buttonElement-framed', framed );
+ this.updateThemeClasses();
+ }
+
+ return this;
+};
+
+/**
+ * Set the button's active state.
+ *
+ * The active state can be set on:
+ *
+ * - {@link OO.ui.ButtonOptionWidget ButtonOptionWidget} when it is selected
+ * - {@link OO.ui.ToggleButtonWidget ToggleButtonWidget} when it is toggle on
+ * - {@link OO.ui.ButtonWidget ButtonWidget} when clicking the button would only refresh the page
+ *
+ * @protected
+ * @param {boolean} value Make button active
+ * @chainable
+ */
+OO.ui.mixin.ButtonElement.prototype.setActive = function ( value ) {
+ this.active = !!value;
+ this.$element.toggleClass( 'oo-ui-buttonElement-active', this.active );
+ this.updateThemeClasses();
+ return this;
+};
+
+/**
+ * Check if the button is active
+ *
+ * @protected
+ * @return {boolean} The button is active
+ */
+OO.ui.mixin.ButtonElement.prototype.isActive = function () {
+ return this.active;
+};
+
+/**
+ * Any OOjs UI widget that contains other widgets (such as {@link OO.ui.ButtonWidget buttons} or
+ * {@link OO.ui.OptionWidget options}) mixes in GroupElement. Adding, removing, and clearing
+ * items from the group is done through the interface the class provides.
+ * For more information, please see the [OOjs UI documentation on MediaWiki] [1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Elements/Groups
+ *
+ * @abstract
+ * @mixins OO.EmitterList
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$group] The container element created by the class. If this configuration
+ * is omitted, the group element will use a generated `<div>`.
+ */
+OO.ui.mixin.GroupElement = function OoUiMixinGroupElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Mixin constructors
+ OO.EmitterList.call( this, config );
+
+ // Properties
+ this.$group = null;
+
+ // Initialization
+ this.setGroupElement( config.$group || $( '<div>' ) );
+};
+
+/* Setup */
+
+OO.mixinClass( OO.ui.mixin.GroupElement, OO.EmitterList );
+
+/* Events */
+
+/**
+ * @event change
+ *
+ * A change event is emitted when the set of selected items changes.
+ *
+ * @param {OO.ui.Element[]} items Items currently in the group
+ */
+
+/* Methods */
+
+/**
+ * Set the group element.
+ *
+ * If an element is already set, items will be moved to the new element.
+ *
+ * @param {jQuery} $group Element to use as group
+ */
+OO.ui.mixin.GroupElement.prototype.setGroupElement = function ( $group ) {
+ var i, len;
+
+ this.$group = $group;
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ this.$group.append( this.items[ i ].$element );
+ }
+};
+
+/**
+ * Get an item by its data.
+ *
+ * Only the first item with matching data will be returned. To return all matching items,
+ * use the #getItemsFromData method.
+ *
+ * @param {Object} data Item data to search for
+ * @return {OO.ui.Element|null} Item with equivalent data, `null` if none exists
+ */
+OO.ui.mixin.GroupElement.prototype.getItemFromData = function ( data ) {
+ var i, len, item,
+ hash = OO.getHash( data );
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ item = this.items[ i ];
+ if ( hash === OO.getHash( item.getData() ) ) {
+ return item;
+ }
+ }
+
+ return null;
+};
+
+/**
+ * Get items by their data.
+ *
+ * All items with matching data will be returned. To return only the first match, use the #getItemFromData method instead.
+ *
+ * @param {Object} data Item data to search for
+ * @return {OO.ui.Element[]} Items with equivalent data
+ */
+OO.ui.mixin.GroupElement.prototype.getItemsFromData = function ( data ) {
+ var i, len, item,
+ hash = OO.getHash( data ),
+ items = [];
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ item = this.items[ i ];
+ if ( hash === OO.getHash( item.getData() ) ) {
+ items.push( item );
+ }
+ }
+
+ return items;
+};
+
+/**
+ * Add items to the group.
+ *
+ * Items will be added to the end of the group array unless the optional `index` parameter specifies
+ * a different insertion point. Adding an existing item will move it to the end of the array or the point specified by the `index`.
+ *
+ * @param {OO.ui.Element[]} items An array of items to add to the group
+ * @param {number} [index] Index of the insertion point
+ * @chainable
+ */
+OO.ui.mixin.GroupElement.prototype.addItems = function ( items, index ) {
+ // Mixin method
+ OO.EmitterList.prototype.addItems.call( this, items, index );
+
+ this.emit( 'change', this.getItems() );
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.mixin.GroupElement.prototype.moveItem = function ( items, newIndex ) {
+ // insertItemElements expects this.items to not have been modified yet, so call before the mixin
+ this.insertItemElements( items, newIndex );
+
+ // Mixin method
+ newIndex = OO.EmitterList.prototype.moveItem.call( this, items, newIndex );
+
+ return newIndex;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.mixin.GroupElement.prototype.insertItem = function ( item, index ) {
+ item.setElementGroup( this );
+ this.insertItemElements( item, index );
+
+ // Mixin method
+ index = OO.EmitterList.prototype.insertItem.call( this, item, index );
+
+ return index;
+};
+
+/**
+ * Insert elements into the group
+ *
+ * @private
+ * @param {OO.ui.Element} itemWidget Item to insert
+ * @param {number} index Insertion index
+ */
+OO.ui.mixin.GroupElement.prototype.insertItemElements = function ( itemWidget, index ) {
+ if ( index === undefined || index < 0 || index >= this.items.length ) {
+ this.$group.append( itemWidget.$element );
+ } else if ( index === 0 ) {
+ this.$group.prepend( itemWidget.$element );
+ } else {
+ this.items[ index ].$element.before( itemWidget.$element );
+ }
+};
+
+/**
+ * Remove the specified items from a group.
+ *
+ * Removed items are detached (not removed) from the DOM so that they may be reused.
+ * To remove all items from a group, you may wish to use the #clearItems method instead.
+ *
+ * @param {OO.ui.Element[]} items An array of items to remove
+ * @chainable
+ */
+OO.ui.mixin.GroupElement.prototype.removeItems = function ( items ) {
+ var i, len, item, index;
+
+ // Remove specific items elements
+ for ( i = 0, len = items.length; i < len; i++ ) {
+ item = items[ i ];
+ index = this.items.indexOf( item );
+ if ( index !== -1 ) {
+ item.setElementGroup( null );
+ item.$element.detach();
+ }
+ }
+
+ // Mixin method
+ OO.EmitterList.prototype.removeItems.call( this, items );
+
+ this.emit( 'change', this.getItems() );
+ return this;
+};
+
+/**
+ * Clear all items from the group.
+ *
+ * Cleared items are detached from the DOM, not removed, so that they may be reused.
+ * To remove only a subset of items from a group, use the #removeItems method.
+ *
+ * @chainable
+ */
+OO.ui.mixin.GroupElement.prototype.clearItems = function () {
+ var i, len;
+
+ // Remove all item elements
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ this.items[ i ].setElementGroup( null );
+ this.items[ i ].$element.detach();
+ }
+
+ // Mixin method
+ OO.EmitterList.prototype.clearItems.call( this );
+
+ this.emit( 'change', this.getItems() );
+ return this;
+};
+
+/**
+ * IconElement is often mixed into other classes to generate an icon.
+ * Icons are graphics, about the size of normal text. They are used to aid the user
+ * in locating a control or to convey information in a space-efficient way. See the
+ * [OOjs UI documentation on MediaWiki] [1] for a list of icons
+ * included in the library.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Icons
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$icon] The icon element created by the class. If this configuration is omitted,
+ * the icon element will use a generated `<span>`. To use a different HTML tag, or to specify that
+ * the icon element be set to an existing icon instead of the one generated by this class, set a
+ * value using a jQuery selection. For example:
+ *
+ * // Use a <div> tag instead of a <span>
+ * $icon: $("<div>")
+ * // Use an existing icon element instead of the one generated by the class
+ * $icon: this.$element
+ * // Use an icon element from a child widget
+ * $icon: this.childwidget.$element
+ * @cfg {Object|string} [icon=''] The symbolic name of the icon (e.g., ‘remove’ or ‘menu’), or a map of
+ * symbolic names. A map is used for i18n purposes and contains a `default` icon
+ * name and additional names keyed by language code. The `default` name is used when no icon is keyed
+ * by the user's language.
+ *
+ * Example of an i18n map:
+ *
+ * { default: 'bold-a', en: 'bold-b', de: 'bold-f' }
+ * See the [OOjs UI documentation on MediaWiki] [2] for a list of icons included in the library.
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Icons
+ * @cfg {string|Function} [iconTitle] A text string used as the icon title, or a function that returns title
+ * text. The icon title is displayed when users move the mouse over the icon.
+ */
+OO.ui.mixin.IconElement = function OoUiMixinIconElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.$icon = null;
+ this.icon = null;
+ this.iconTitle = null;
+
+ // Initialization
+ this.setIcon( config.icon || this.constructor.static.icon );
+ this.setIconTitle( config.iconTitle || this.constructor.static.iconTitle );
+ this.setIconElement( config.$icon || $( '<span>' ) );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.mixin.IconElement );
+
+/* Static Properties */
+
+/**
+ * The symbolic name of the icon (e.g., ‘remove’ or ‘menu’), or a map of symbolic names. A map is used
+ * for i18n purposes and contains a `default` icon name and additional names keyed by
+ * language code. The `default` name is used when no icon is keyed by the user's language.
+ *
+ * Example of an i18n map:
+ *
+ * { default: 'bold-a', en: 'bold-b', de: 'bold-f' }
+ *
+ * Note: the static property will be overridden if the #icon configuration is used.
+ *
+ * @static
+ * @inheritable
+ * @property {Object|string}
+ */
+OO.ui.mixin.IconElement.static.icon = null;
+
+/**
+ * The icon title, displayed when users move the mouse over the icon. The value can be text, a
+ * function that returns title text, or `null` for no title.
+ *
+ * The static property will be overridden if the #iconTitle configuration is used.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null}
+ */
+OO.ui.mixin.IconElement.static.iconTitle = null;
+
+/* Methods */
+
+/**
+ * Set the icon element. This method is used to retarget an icon mixin so that its functionality
+ * applies to the specified icon element instead of the one created by the class. If an icon
+ * element is already set, the mixin’s effect on that element is removed. Generated CSS classes
+ * and mixin methods will no longer affect the element.
+ *
+ * @param {jQuery} $icon Element to use as icon
+ */
+OO.ui.mixin.IconElement.prototype.setIconElement = function ( $icon ) {
+ if ( this.$icon ) {
+ this.$icon
+ .removeClass( 'oo-ui-iconElement-icon oo-ui-icon-' + this.icon )
+ .removeAttr( 'title' );
+ }
+
+ this.$icon = $icon
+ .addClass( 'oo-ui-iconElement-icon' )
+ .toggleClass( 'oo-ui-icon-' + this.icon, !!this.icon );
+ if ( this.iconTitle !== null ) {
+ this.$icon.attr( 'title', this.iconTitle );
+ }
+
+ this.updateThemeClasses();
+};
+
+/**
+ * Set icon by symbolic name (e.g., ‘remove’ or ‘menu’). Use `null` to remove an icon.
+ * The icon parameter can also be set to a map of icon names. See the #icon config setting
+ * for an example.
+ *
+ * @param {Object|string|null} icon A symbolic icon name, a {@link #icon map of icon names} keyed
+ * by language code, or `null` to remove the icon.
+ * @chainable
+ */
+OO.ui.mixin.IconElement.prototype.setIcon = function ( icon ) {
+ icon = OO.isPlainObject( icon ) ? OO.ui.getLocalValue( icon, null, 'default' ) : icon;
+ icon = typeof icon === 'string' && icon.trim().length ? icon.trim() : null;
+
+ if ( this.icon !== icon ) {
+ if ( this.$icon ) {
+ if ( this.icon !== null ) {
+ this.$icon.removeClass( 'oo-ui-icon-' + this.icon );
+ }
+ if ( icon !== null ) {
+ this.$icon.addClass( 'oo-ui-icon-' + icon );
+ }
+ }
+ this.icon = icon;
+ }
+
+ this.$element.toggleClass( 'oo-ui-iconElement', !!this.icon );
+ this.updateThemeClasses();
+
+ return this;
+};
+
+/**
+ * Set the icon title. Use `null` to remove the title.
+ *
+ * @param {string|Function|null} iconTitle A text string used as the icon title,
+ * a function that returns title text, or `null` for no title.
+ * @chainable
+ */
+OO.ui.mixin.IconElement.prototype.setIconTitle = function ( iconTitle ) {
+ iconTitle =
+ ( typeof iconTitle === 'function' || ( typeof iconTitle === 'string' && iconTitle.length ) ) ?
+ OO.ui.resolveMsg( iconTitle ) : null;
+
+ if ( this.iconTitle !== iconTitle ) {
+ this.iconTitle = iconTitle;
+ if ( this.$icon ) {
+ if ( this.iconTitle !== null ) {
+ this.$icon.attr( 'title', iconTitle );
+ } else {
+ this.$icon.removeAttr( 'title' );
+ }
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Get the symbolic name of the icon.
+ *
+ * @return {string} Icon name
+ */
+OO.ui.mixin.IconElement.prototype.getIcon = function () {
+ return this.icon;
+};
+
+/**
+ * Get the icon title. The title text is displayed when a user moves the mouse over the icon.
+ *
+ * @return {string} Icon title text
+ */
+OO.ui.mixin.IconElement.prototype.getIconTitle = function () {
+ return this.iconTitle;
+};
+
+/**
+ * IndicatorElement is often mixed into other classes to generate an indicator.
+ * Indicators are small graphics that are generally used in two ways:
+ *
+ * - To draw attention to the status of an item. For example, an indicator might be
+ * used to show that an item in a list has errors that need to be resolved.
+ * - To clarify the function of a control that acts in an exceptional way (a button
+ * that opens a menu instead of performing an action directly, for example).
+ *
+ * For a list of indicators included in the library, please see the
+ * [OOjs UI documentation on MediaWiki] [1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Indicators
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$indicator] The indicator element created by the class. If this
+ * configuration is omitted, the indicator element will use a generated `<span>`.
+ * @cfg {string} [indicator] Symbolic name of the indicator (e.g., ‘alert’ or ‘down’).
+ * See the [OOjs UI documentation on MediaWiki][2] for a list of indicators included
+ * in the library.
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Indicators
+ * @cfg {string|Function} [indicatorTitle] A text string used as the indicator title,
+ * or a function that returns title text. The indicator title is displayed when users move
+ * the mouse over the indicator.
+ */
+OO.ui.mixin.IndicatorElement = function OoUiMixinIndicatorElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.$indicator = null;
+ this.indicator = null;
+ this.indicatorTitle = null;
+
+ // Initialization
+ this.setIndicator( config.indicator || this.constructor.static.indicator );
+ this.setIndicatorTitle( config.indicatorTitle || this.constructor.static.indicatorTitle );
+ this.setIndicatorElement( config.$indicator || $( '<span>' ) );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.mixin.IndicatorElement );
+
+/* Static Properties */
+
+/**
+ * Symbolic name of the indicator (e.g., ‘alert’ or ‘down’).
+ * The static property will be overridden if the #indicator configuration is used.
+ *
+ * @static
+ * @inheritable
+ * @property {string|null}
+ */
+OO.ui.mixin.IndicatorElement.static.indicator = null;
+
+/**
+ * A text string used as the indicator title, a function that returns title text, or `null`
+ * for no title. The static property will be overridden if the #indicatorTitle configuration is used.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null}
+ */
+OO.ui.mixin.IndicatorElement.static.indicatorTitle = null;
+
+/* Methods */
+
+/**
+ * Set the indicator element.
+ *
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $indicator Element to use as indicator
+ */
+OO.ui.mixin.IndicatorElement.prototype.setIndicatorElement = function ( $indicator ) {
+ if ( this.$indicator ) {
+ this.$indicator
+ .removeClass( 'oo-ui-indicatorElement-indicator oo-ui-indicator-' + this.indicator )
+ .removeAttr( 'title' );
+ }
+
+ this.$indicator = $indicator
+ .addClass( 'oo-ui-indicatorElement-indicator' )
+ .toggleClass( 'oo-ui-indicator-' + this.indicator, !!this.indicator );
+ if ( this.indicatorTitle !== null ) {
+ this.$indicator.attr( 'title', this.indicatorTitle );
+ }
+
+ this.updateThemeClasses();
+};
+
+/**
+ * Set the indicator by its symbolic name: ‘alert’, ‘down’, ‘next’, ‘previous’, ‘required’, ‘up’. Use `null` to remove the indicator.
+ *
+ * @param {string|null} indicator Symbolic name of indicator, or `null` for no indicator
+ * @chainable
+ */
+OO.ui.mixin.IndicatorElement.prototype.setIndicator = function ( indicator ) {
+ indicator = typeof indicator === 'string' && indicator.length ? indicator.trim() : null;
+
+ if ( this.indicator !== indicator ) {
+ if ( this.$indicator ) {
+ if ( this.indicator !== null ) {
+ this.$indicator.removeClass( 'oo-ui-indicator-' + this.indicator );
+ }
+ if ( indicator !== null ) {
+ this.$indicator.addClass( 'oo-ui-indicator-' + indicator );
+ }
+ }
+ this.indicator = indicator;
+ }
+
+ this.$element.toggleClass( 'oo-ui-indicatorElement', !!this.indicator );
+ this.updateThemeClasses();
+
+ return this;
+};
+
+/**
+ * Set the indicator title.
+ *
+ * The title is displayed when a user moves the mouse over the indicator.
+ *
+ * @param {string|Function|null} indicatorTitle Indicator title text, a function that returns text, or
+ * `null` for no indicator title
+ * @chainable
+ */
+OO.ui.mixin.IndicatorElement.prototype.setIndicatorTitle = function ( indicatorTitle ) {
+ indicatorTitle =
+ ( typeof indicatorTitle === 'function' || ( typeof indicatorTitle === 'string' && indicatorTitle.length ) ) ?
+ OO.ui.resolveMsg( indicatorTitle ) : null;
+
+ if ( this.indicatorTitle !== indicatorTitle ) {
+ this.indicatorTitle = indicatorTitle;
+ if ( this.$indicator ) {
+ if ( this.indicatorTitle !== null ) {
+ this.$indicator.attr( 'title', indicatorTitle );
+ } else {
+ this.$indicator.removeAttr( 'title' );
+ }
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Get the symbolic name of the indicator (e.g., ‘alert’ or ‘down’).
+ *
+ * @return {string} Symbolic name of indicator
+ */
+OO.ui.mixin.IndicatorElement.prototype.getIndicator = function () {
+ return this.indicator;
+};
+
+/**
+ * Get the indicator title.
+ *
+ * The title is displayed when a user moves the mouse over the indicator.
+ *
+ * @return {string} Indicator title text
+ */
+OO.ui.mixin.IndicatorElement.prototype.getIndicatorTitle = function () {
+ return this.indicatorTitle;
+};
+
+/**
+ * LabelElement is often mixed into other classes to generate a label, which
+ * helps identify the function of an interface element.
+ * See the [OOjs UI documentation on MediaWiki] [1] for more information.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Labels
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$label] The label element created by the class. If this
+ * configuration is omitted, the label element will use a generated `<span>`.
+ * @cfg {jQuery|string|Function|OO.ui.HtmlSnippet} [label] The label text. The label can be specified
+ * as a plaintext string, a jQuery selection of elements, or a function that will produce a string
+ * in the future. See the [OOjs UI documentation on MediaWiki] [2] for examples.
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Labels
+ */
+OO.ui.mixin.LabelElement = function OoUiMixinLabelElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.$label = null;
+ this.label = null;
+
+ // Initialization
+ this.setLabel( config.label || this.constructor.static.label );
+ this.setLabelElement( config.$label || $( '<span>' ) );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.mixin.LabelElement );
+
+/* Events */
+
+/**
+ * @event labelChange
+ * @param {string} value
+ */
+
+/* Static Properties */
+
+/**
+ * The label text. The label can be specified as a plaintext string, a function that will
+ * produce a string in the future, or `null` for no label. The static value will
+ * be overridden if a label is specified with the #label config option.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null}
+ */
+OO.ui.mixin.LabelElement.static.label = null;
+
+/* Static methods */
+
+/**
+ * Highlight the first occurrence of the query in the given text
+ *
+ * @param {string} text Text
+ * @param {string} query Query to find
+ * @return {jQuery} Text with the first match of the query
+ * sub-string wrapped in highlighted span
+ */
+OO.ui.mixin.LabelElement.static.highlightQuery = function ( text, query ) {
+ var $result = $( '<span>' ),
+ offset = text.toLowerCase().indexOf( query.toLowerCase() );
+
+ if ( !query.length || offset === -1 ) {
+ return $result.text( text );
+ }
+ $result.append(
+ document.createTextNode( text.slice( 0, offset ) ),
+ $( '<span>' )
+ .addClass( 'oo-ui-labelElement-label-highlight' )
+ .text( text.slice( offset, offset + query.length ) ),
+ document.createTextNode( text.slice( offset + query.length ) )
+ );
+ return $result.contents();
+};
+
+/* Methods */
+
+/**
+ * Set the label element.
+ *
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $label Element to use as label
+ */
+OO.ui.mixin.LabelElement.prototype.setLabelElement = function ( $label ) {
+ if ( this.$label ) {
+ this.$label.removeClass( 'oo-ui-labelElement-label' ).empty();
+ }
+
+ this.$label = $label.addClass( 'oo-ui-labelElement-label' );
+ this.setLabelContent( this.label );
+};
+
+/**
+ * Set the label.
+ *
+ * An empty string will result in the label being hidden. A string containing only whitespace will
+ * be converted to a single `&nbsp;`.
+ *
+ * @param {jQuery|string|OO.ui.HtmlSnippet|Function|null} label Label nodes; text; a function that returns nodes or
+ * text; or null for no label
+ * @chainable
+ */
+OO.ui.mixin.LabelElement.prototype.setLabel = function ( label ) {
+ label = typeof label === 'function' ? OO.ui.resolveMsg( label ) : label;
+ label = ( ( typeof label === 'string' || label instanceof jQuery ) && label.length ) || ( label instanceof OO.ui.HtmlSnippet && label.toString().length ) ? label : null;
+
+ if ( this.label !== label ) {
+ if ( this.$label ) {
+ this.setLabelContent( label );
+ }
+ this.label = label;
+ this.emit( 'labelChange' );
+ }
+
+ this.$element.toggleClass( 'oo-ui-labelElement', !!this.label );
+
+ return this;
+};
+
+/**
+ * Set the label as plain text with a highlighted query
+ *
+ * @param {string} text Text label to set
+ * @param {string} query Substring of text to highlight
+ * @chainable
+ */
+OO.ui.mixin.LabelElement.prototype.setHighlightedQuery = function ( text, query ) {
+ return this.setLabel( this.constructor.static.highlightQuery( text, query ) );
+};
+
+/**
+ * Get the label.
+ *
+ * @return {jQuery|string|Function|null} Label nodes; text; a function that returns nodes or
+ * text; or null for no label
+ */
+OO.ui.mixin.LabelElement.prototype.getLabel = function () {
+ return this.label;
+};
+
+/**
+ * Set the content of the label.
+ *
+ * Do not call this method until after the label element has been set by #setLabelElement.
+ *
+ * @private
+ * @param {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or
+ * text; or null for no label
+ */
+OO.ui.mixin.LabelElement.prototype.setLabelContent = function ( label ) {
+ if ( typeof label === 'string' ) {
+ if ( label.match( /^\s*$/ ) ) {
+ // Convert whitespace only string to a single non-breaking space
+ this.$label.html( '&nbsp;' );
+ } else {
+ this.$label.text( label );
+ }
+ } else if ( label instanceof OO.ui.HtmlSnippet ) {
+ this.$label.html( label.toString() );
+ } else if ( label instanceof jQuery ) {
+ this.$label.empty().append( label );
+ } else {
+ this.$label.empty();
+ }
+};
+
+/**
+ * The FlaggedElement class is an attribute mixin, meaning that it is used to add
+ * additional functionality to an element created by another class. The class provides
+ * a ‘flags’ property assigned the name (or an array of names) of styling flags,
+ * which are used to customize the look and feel of a widget to better describe its
+ * importance and functionality.
+ *
+ * The library currently contains the following styling flags for general use:
+ *
+ * - **progressive**: Progressive styling is applied to convey that the widget will move the user forward in a process.
+ * - **destructive**: Destructive styling is applied to convey that the widget will remove something.
+ * - **constructive**: Constructive styling is applied to convey that the widget will create something.
+ *
+ * The flags affect the appearance of the buttons:
+ *
+ * @example
+ * // FlaggedElement is mixed into ButtonWidget to provide styling flags
+ * var button1 = new OO.ui.ButtonWidget( {
+ * label: 'Constructive',
+ * flags: 'constructive'
+ * } );
+ * var button2 = new OO.ui.ButtonWidget( {
+ * label: 'Destructive',
+ * flags: 'destructive'
+ * } );
+ * var button3 = new OO.ui.ButtonWidget( {
+ * label: 'Progressive',
+ * flags: 'progressive'
+ * } );
+ * $( 'body' ).append( button1.$element, button2.$element, button3.$element );
+ *
+ * {@link OO.ui.ActionWidget ActionWidgets}, which are a special kind of button that execute an action, use these flags: **primary** and **safe**.
+ * Please see the [OOjs UI documentation on MediaWiki] [1] for more information.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Elements/Flagged
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string|string[]} [flags] The name or names of the flags (e.g., 'constructive' or 'primary') to apply.
+ * Please see the [OOjs UI documentation on MediaWiki] [2] for more information about available flags.
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Elements/Flagged
+ * @cfg {jQuery} [$flagged] The flagged element. By default,
+ * the flagged functionality is applied to the element created by the class ($element).
+ * If a different element is specified, the flagged functionality will be applied to it instead.
+ */
+OO.ui.mixin.FlaggedElement = function OoUiMixinFlaggedElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.flags = {};
+ this.$flagged = null;
+
+ // Initialization
+ this.setFlags( config.flags );
+ this.setFlaggedElement( config.$flagged || this.$element );
+};
+
+/* Events */
+
+/**
+ * @event flag
+ * A flag event is emitted when the #clearFlags or #setFlags methods are used. The `changes`
+ * parameter contains the name of each modified flag and indicates whether it was
+ * added or removed.
+ *
+ * @param {Object.<string,boolean>} changes Object keyed by flag name. A Boolean `true` indicates
+ * that the flag was added, `false` that the flag was removed.
+ */
+
+/* Methods */
+
+/**
+ * Set the flagged element.
+ *
+ * This method is used to retarget a flagged mixin so that its functionality applies to the specified element.
+ * If an element is already set, the method will remove the mixin’s effect on that element.
+ *
+ * @param {jQuery} $flagged Element that should be flagged
+ */
+OO.ui.mixin.FlaggedElement.prototype.setFlaggedElement = function ( $flagged ) {
+ var classNames = Object.keys( this.flags ).map( function ( flag ) {
+ return 'oo-ui-flaggedElement-' + flag;
+ } ).join( ' ' );
+
+ if ( this.$flagged ) {
+ this.$flagged.removeClass( classNames );
+ }
+
+ this.$flagged = $flagged.addClass( classNames );
+};
+
+/**
+ * Check if the specified flag is set.
+ *
+ * @param {string} flag Name of flag
+ * @return {boolean} The flag is set
+ */
+OO.ui.mixin.FlaggedElement.prototype.hasFlag = function ( flag ) {
+ // This may be called before the constructor, thus before this.flags is set
+ return this.flags && ( flag in this.flags );
+};
+
+/**
+ * Get the names of all flags set.
+ *
+ * @return {string[]} Flag names
+ */
+OO.ui.mixin.FlaggedElement.prototype.getFlags = function () {
+ // This may be called before the constructor, thus before this.flags is set
+ return Object.keys( this.flags || {} );
+};
+
+/**
+ * Clear all flags.
+ *
+ * @chainable
+ * @fires flag
+ */
+OO.ui.mixin.FlaggedElement.prototype.clearFlags = function () {
+ var flag, className,
+ changes = {},
+ remove = [],
+ classPrefix = 'oo-ui-flaggedElement-';
+
+ for ( flag in this.flags ) {
+ className = classPrefix + flag;
+ changes[ flag ] = false;
+ delete this.flags[ flag ];
+ remove.push( className );
+ }
+
+ if ( this.$flagged ) {
+ this.$flagged.removeClass( remove.join( ' ' ) );
+ }
+
+ this.updateThemeClasses();
+ this.emit( 'flag', changes );
+
+ return this;
+};
+
+/**
+ * Add one or more flags.
+ *
+ * @param {string|string[]|Object.<string, boolean>} flags A flag name, an array of flag names,
+ * or an object keyed by flag name with a boolean value that indicates whether the flag should
+ * be added (`true`) or removed (`false`).
+ * @chainable
+ * @fires flag
+ */
+OO.ui.mixin.FlaggedElement.prototype.setFlags = function ( flags ) {
+ var i, len, flag, className,
+ changes = {},
+ add = [],
+ remove = [],
+ classPrefix = 'oo-ui-flaggedElement-';
+
+ if ( typeof flags === 'string' ) {
+ className = classPrefix + flags;
+ // Set
+ if ( !this.flags[ flags ] ) {
+ this.flags[ flags ] = true;
+ add.push( className );
+ }
+ } else if ( Array.isArray( flags ) ) {
+ for ( i = 0, len = flags.length; i < len; i++ ) {
+ flag = flags[ i ];
+ className = classPrefix + flag;
+ // Set
+ if ( !this.flags[ flag ] ) {
+ changes[ flag ] = true;
+ this.flags[ flag ] = true;
+ add.push( className );
+ }
+ }
+ } else if ( OO.isPlainObject( flags ) ) {
+ for ( flag in flags ) {
+ className = classPrefix + flag;
+ if ( flags[ flag ] ) {
+ // Set
+ if ( !this.flags[ flag ] ) {
+ changes[ flag ] = true;
+ this.flags[ flag ] = true;
+ add.push( className );
+ }
+ } else {
+ // Remove
+ if ( this.flags[ flag ] ) {
+ changes[ flag ] = false;
+ delete this.flags[ flag ];
+ remove.push( className );
+ }
+ }
+ }
+ }
+
+ if ( this.$flagged ) {
+ this.$flagged
+ .addClass( add.join( ' ' ) )
+ .removeClass( remove.join( ' ' ) );
+ }
+
+ this.updateThemeClasses();
+ this.emit( 'flag', changes );
+
+ return this;
+};
+
+/**
+ * TitledElement is mixed into other classes to provide a `title` attribute.
+ * Titles are rendered by the browser and are made visible when the user moves
+ * the mouse over the element. Titles are not visible on touch devices.
+ *
+ * @example
+ * // TitledElement provides a 'title' attribute to the
+ * // ButtonWidget class
+ * var button = new OO.ui.ButtonWidget( {
+ * label: 'Button with Title',
+ * title: 'I am a button'
+ * } );
+ * $( 'body' ).append( button.$element );
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$titled] The element to which the `title` attribute is applied.
+ * If this config is omitted, the title functionality is applied to $element, the
+ * element created by the class.
+ * @cfg {string|Function} [title] The title text or a function that returns text. If
+ * this config is omitted, the value of the {@link #static-title static title} property is used.
+ */
+OO.ui.mixin.TitledElement = function OoUiMixinTitledElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.$titled = null;
+ this.title = null;
+
+ // Initialization
+ this.setTitle( config.title !== undefined ? config.title : this.constructor.static.title );
+ this.setTitledElement( config.$titled || this.$element );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.mixin.TitledElement );
+
+/* Static Properties */
+
+/**
+ * The title text, a function that returns text, or `null` for no title. The value of the static property
+ * is overridden if the #title config option is used.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null}
+ */
+OO.ui.mixin.TitledElement.static.title = null;
+
+/* Methods */
+
+/**
+ * Set the titled element.
+ *
+ * This method is used to retarget a titledElement mixin so that its functionality applies to the specified element.
+ * If an element is already set, the mixin’s effect on that element is removed before the new element is set up.
+ *
+ * @param {jQuery} $titled Element that should use the 'titled' functionality
+ */
+OO.ui.mixin.TitledElement.prototype.setTitledElement = function ( $titled ) {
+ if ( this.$titled ) {
+ this.$titled.removeAttr( 'title' );
+ }
+
+ this.$titled = $titled;
+ if ( this.title ) {
+ this.updateTitle();
+ }
+};
+
+/**
+ * Set title.
+ *
+ * @param {string|Function|null} title Title text, a function that returns text, or `null` for no title
+ * @chainable
+ */
+OO.ui.mixin.TitledElement.prototype.setTitle = function ( title ) {
+ title = typeof title === 'function' ? OO.ui.resolveMsg( title ) : title;
+ title = ( typeof title === 'string' && title.length ) ? title : null;
+
+ if ( this.title !== title ) {
+ this.title = title;
+ this.updateTitle();
+ }
+
+ return this;
+};
+
+/**
+ * Update the title attribute, in case of changes to title or accessKey.
+ *
+ * @protected
+ * @chainable
+ */
+OO.ui.mixin.TitledElement.prototype.updateTitle = function () {
+ var title = this.getTitle();
+ if ( this.$titled ) {
+ if ( title !== null ) {
+ // Only if this is an AccessKeyedElement
+ if ( this.formatTitleWithAccessKey ) {
+ title = this.formatTitleWithAccessKey( title );
+ }
+ this.$titled.attr( 'title', title );
+ } else {
+ this.$titled.removeAttr( 'title' );
+ }
+ }
+ return this;
+};
+
+/**
+ * Get title.
+ *
+ * @return {string} Title string
+ */
+OO.ui.mixin.TitledElement.prototype.getTitle = function () {
+ return this.title;
+};
+
+/**
+ * AccessKeyedElement is mixed into other classes to provide an `accesskey` attribute.
+ * Accesskeys allow an user to go to a specific element by using
+ * a shortcut combination of a browser specific keys + the key
+ * set to the field.
+ *
+ * @example
+ * // AccessKeyedElement provides an 'accesskey' attribute to the
+ * // ButtonWidget class
+ * var button = new OO.ui.ButtonWidget( {
+ * label: 'Button with Accesskey',
+ * accessKey: 'k'
+ * } );
+ * $( 'body' ).append( button.$element );
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$accessKeyed] The element to which the `accesskey` attribute is applied.
+ * If this config is omitted, the accesskey functionality is applied to $element, the
+ * element created by the class.
+ * @cfg {string|Function} [accessKey] The key or a function that returns the key. If
+ * this config is omitted, no accesskey will be added.
+ */
+OO.ui.mixin.AccessKeyedElement = function OoUiMixinAccessKeyedElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.$accessKeyed = null;
+ this.accessKey = null;
+
+ // Initialization
+ this.setAccessKey( config.accessKey || null );
+ this.setAccessKeyedElement( config.$accessKeyed || this.$element );
+
+ // If this is also a TitledElement and it initialized before we did, we may have
+ // to update the title with the access key
+ if ( this.updateTitle ) {
+ this.updateTitle();
+ }
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.mixin.AccessKeyedElement );
+
+/* Static Properties */
+
+/**
+ * The access key, a function that returns a key, or `null` for no accesskey.
+ *
+ * @static
+ * @inheritable
+ * @property {string|Function|null}
+ */
+OO.ui.mixin.AccessKeyedElement.static.accessKey = null;
+
+/* Methods */
+
+/**
+ * Set the accesskeyed element.
+ *
+ * This method is used to retarget a AccessKeyedElement mixin so that its functionality applies to the specified element.
+ * If an element is already set, the mixin's effect on that element is removed before the new element is set up.
+ *
+ * @param {jQuery} $accessKeyed Element that should use the 'accesskeyes' functionality
+ */
+OO.ui.mixin.AccessKeyedElement.prototype.setAccessKeyedElement = function ( $accessKeyed ) {
+ if ( this.$accessKeyed ) {
+ this.$accessKeyed.removeAttr( 'accesskey' );
+ }
+
+ this.$accessKeyed = $accessKeyed;
+ if ( this.accessKey ) {
+ this.$accessKeyed.attr( 'accesskey', this.accessKey );
+ }
+};
+
+/**
+ * Set accesskey.
+ *
+ * @param {string|Function|null} accessKey Key, a function that returns a key, or `null` for no accesskey
+ * @chainable
+ */
+OO.ui.mixin.AccessKeyedElement.prototype.setAccessKey = function ( accessKey ) {
+ accessKey = typeof accessKey === 'string' ? OO.ui.resolveMsg( accessKey ) : null;
+
+ if ( this.accessKey !== accessKey ) {
+ if ( this.$accessKeyed ) {
+ if ( accessKey !== null ) {
+ this.$accessKeyed.attr( 'accesskey', accessKey );
+ } else {
+ this.$accessKeyed.removeAttr( 'accesskey' );
+ }
+ }
+ this.accessKey = accessKey;
+
+ // Only if this is a TitledElement
+ if ( this.updateTitle ) {
+ this.updateTitle();
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Get accesskey.
+ *
+ * @return {string} accessKey string
+ */
+OO.ui.mixin.AccessKeyedElement.prototype.getAccessKey = function () {
+ return this.accessKey;
+};
+
+/**
+ * Add information about the access key to the element's tooltip label.
+ * (This is only public for hacky usage in FieldLayout.)
+ *
+ * @param {string} title Tooltip label for `title` attribute
+ * @return {string}
+ */
+OO.ui.mixin.AccessKeyedElement.prototype.formatTitleWithAccessKey = function ( title ) {
+ var accessKey;
+
+ if ( !this.$accessKeyed ) {
+ // Not initialized yet; the constructor will call updateTitle() which will rerun this function
+ return title;
+ }
+ // Use jquery.accessKeyLabel if available to show modifiers, otherwise just display the single key
+ if ( $.fn.updateTooltipAccessKeys && $.fn.updateTooltipAccessKeys.getAccessKeyLabel ) {
+ accessKey = $.fn.updateTooltipAccessKeys.getAccessKeyLabel( this.$accessKeyed[ 0 ] );
+ } else {
+ accessKey = this.getAccessKey();
+ }
+ if ( accessKey ) {
+ title += ' [' + accessKey + ']';
+ }
+ return title;
+};
+
+/**
+ * ButtonWidget is a generic widget for buttons. A wide variety of looks,
+ * feels, and functionality can be customized via the class’s configuration options
+ * and methods. Please see the [OOjs UI documentation on MediaWiki] [1] for more information
+ * and examples.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches
+ *
+ * @example
+ * // A button widget
+ * var button = new OO.ui.ButtonWidget( {
+ * label: 'Button with Icon',
+ * icon: 'trash',
+ * iconTitle: 'Remove'
+ * } );
+ * $( 'body' ).append( button.$element );
+ *
+ * NOTE: HTML form buttons should use the OO.ui.ButtonInputWidget class.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.ButtonElement
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.TitledElement
+ * @mixins OO.ui.mixin.FlaggedElement
+ * @mixins OO.ui.mixin.TabIndexedElement
+ * @mixins OO.ui.mixin.AccessKeyedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [active=false] Whether button should be shown as active
+ * @cfg {string} [href] Hyperlink to visit when the button is clicked.
+ * @cfg {string} [target] The frame or window in which to open the hyperlink.
+ * @cfg {boolean} [noFollow] Search engine traversal hint (default: true)
+ */
+OO.ui.ButtonWidget = function OoUiButtonWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.ButtonWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.ButtonElement.call( this, config );
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.IndicatorElement.call( this, config );
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$button } ) );
+ OO.ui.mixin.FlaggedElement.call( this, config );
+ OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$button } ) );
+ OO.ui.mixin.AccessKeyedElement.call( this, $.extend( {}, config, { $accessKeyed: this.$button } ) );
+
+ // Properties
+ this.href = null;
+ this.target = null;
+ this.noFollow = false;
+
+ // Events
+ this.connect( this, { disable: 'onDisable' } );
+
+ // Initialization
+ this.$button.append( this.$icon, this.$label, this.$indicator );
+ this.$element
+ .addClass( 'oo-ui-buttonWidget' )
+ .append( this.$button );
+ this.setActive( config.active );
+ this.setHref( config.href );
+ this.setTarget( config.target );
+ this.setNoFollow( config.noFollow );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ButtonWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.ButtonElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.IndicatorElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.TitledElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.FlaggedElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.TabIndexedElement );
+OO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.AccessKeyedElement );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.ButtonWidget.static.cancelButtonMouseDownEvents = false;
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.ButtonWidget.static.tagName = 'span';
+
+/* Methods */
+
+/**
+ * Get hyperlink location.
+ *
+ * @return {string} Hyperlink location
+ */
+OO.ui.ButtonWidget.prototype.getHref = function () {
+ return this.href;
+};
+
+/**
+ * Get hyperlink target.
+ *
+ * @return {string} Hyperlink target
+ */
+OO.ui.ButtonWidget.prototype.getTarget = function () {
+ return this.target;
+};
+
+/**
+ * Get search engine traversal hint.
+ *
+ * @return {boolean} Whether search engines should avoid traversing this hyperlink
+ */
+OO.ui.ButtonWidget.prototype.getNoFollow = function () {
+ return this.noFollow;
+};
+
+/**
+ * Set hyperlink location.
+ *
+ * @param {string|null} href Hyperlink location, null to remove
+ */
+OO.ui.ButtonWidget.prototype.setHref = function ( href ) {
+ href = typeof href === 'string' ? href : null;
+ if ( href !== null && !OO.ui.isSafeUrl( href ) ) {
+ href = './' + href;
+ }
+
+ if ( href !== this.href ) {
+ this.href = href;
+ this.updateHref();
+ }
+
+ return this;
+};
+
+/**
+ * Update the `href` attribute, in case of changes to href or
+ * disabled state.
+ *
+ * @private
+ * @chainable
+ */
+OO.ui.ButtonWidget.prototype.updateHref = function () {
+ if ( this.href !== null && !this.isDisabled() ) {
+ this.$button.attr( 'href', this.href );
+ } else {
+ this.$button.removeAttr( 'href' );
+ }
+
+ return this;
+};
+
+/**
+ * Handle disable events.
+ *
+ * @private
+ * @param {boolean} disabled Element is disabled
+ */
+OO.ui.ButtonWidget.prototype.onDisable = function () {
+ this.updateHref();
+};
+
+/**
+ * Set hyperlink target.
+ *
+ * @param {string|null} target Hyperlink target, null to remove
+ */
+OO.ui.ButtonWidget.prototype.setTarget = function ( target ) {
+ target = typeof target === 'string' ? target : null;
+
+ if ( target !== this.target ) {
+ this.target = target;
+ if ( target !== null ) {
+ this.$button.attr( 'target', target );
+ } else {
+ this.$button.removeAttr( 'target' );
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Set search engine traversal hint.
+ *
+ * @param {boolean} noFollow True if search engines should avoid traversing this hyperlink
+ */
+OO.ui.ButtonWidget.prototype.setNoFollow = function ( noFollow ) {
+ noFollow = typeof noFollow === 'boolean' ? noFollow : true;
+
+ if ( noFollow !== this.noFollow ) {
+ this.noFollow = noFollow;
+ if ( noFollow ) {
+ this.$button.attr( 'rel', 'nofollow' );
+ } else {
+ this.$button.removeAttr( 'rel' );
+ }
+ }
+
+ return this;
+};
+
+// Override method visibility hints from ButtonElement
+/**
+ * @method setActive
+ * @inheritdoc
+ */
+/**
+ * @method isActive
+ * @inheritdoc
+ */
+
+/**
+ * A ButtonGroupWidget groups related buttons and is used together with OO.ui.ButtonWidget and
+ * its subclasses. Each button in a group is addressed by a unique reference. Buttons can be added,
+ * removed, and cleared from the group.
+ *
+ * @example
+ * // Example: A ButtonGroupWidget with two buttons
+ * var button1 = new OO.ui.PopupButtonWidget( {
+ * label: 'Select a category',
+ * icon: 'menu',
+ * popup: {
+ * $content: $( '<p>List of categories...</p>' ),
+ * padded: true,
+ * align: 'left'
+ * }
+ * } );
+ * var button2 = new OO.ui.ButtonWidget( {
+ * label: 'Add item'
+ * });
+ * var buttonGroup = new OO.ui.ButtonGroupWidget( {
+ * items: [button1, button2]
+ * } );
+ * $( 'body' ).append( buttonGroup.$element );
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.ButtonWidget[]} [items] Buttons to add
+ */
+OO.ui.ButtonGroupWidget = function OoUiButtonGroupWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.ButtonGroupWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.GroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-buttonGroupWidget' );
+ if ( Array.isArray( config.items ) ) {
+ this.addItems( config.items );
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ButtonGroupWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.ButtonGroupWidget, OO.ui.mixin.GroupElement );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.ButtonGroupWidget.static.tagName = 'span';
+
+/* Methods */
+
+/**
+ * Focus the widget
+ *
+ * @chainable
+ */
+OO.ui.ButtonGroupWidget.prototype.focus = function () {
+ if ( !this.isDisabled() ) {
+ if ( this.items[ 0 ] ) {
+ this.items[ 0 ].focus();
+ }
+ }
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ButtonGroupWidget.prototype.simulateLabelClick = function () {
+ this.focus();
+};
+
+/**
+ * IconWidget is a generic widget for {@link OO.ui.mixin.IconElement icons}. In general, IconWidgets should be used with OO.ui.LabelWidget,
+ * which creates a label that identifies the icon’s function. See the [OOjs UI documentation on MediaWiki] [1]
+ * for a list of icons included in the library.
+ *
+ * @example
+ * // An icon widget with a label
+ * var myIcon = new OO.ui.IconWidget( {
+ * icon: 'help',
+ * iconTitle: 'Help'
+ * } );
+ * // Create a label.
+ * var iconLabel = new OO.ui.LabelWidget( {
+ * label: 'Help'
+ * } );
+ * $( 'body' ).append( myIcon.$element, iconLabel.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Icons
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.TitledElement
+ * @mixins OO.ui.mixin.FlaggedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.IconWidget = function OoUiIconWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.IconWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, $.extend( {}, config, { $icon: this.$element } ) );
+ OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) );
+ OO.ui.mixin.FlaggedElement.call( this, $.extend( {}, config, { $flagged: this.$element } ) );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-iconWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.IconWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.IconWidget, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.IconWidget, OO.ui.mixin.TitledElement );
+OO.mixinClass( OO.ui.IconWidget, OO.ui.mixin.FlaggedElement );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.IconWidget.static.tagName = 'span';
+
+/**
+ * IndicatorWidgets create indicators, which are small graphics that are generally used to draw
+ * attention to the status of an item or to clarify the function of a control. For a list of
+ * indicators included in the library, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * @example
+ * // Example of an indicator widget
+ * var indicator1 = new OO.ui.IndicatorWidget( {
+ * indicator: 'alert'
+ * } );
+ *
+ * // Create a fieldset layout to add a label
+ * var fieldset = new OO.ui.FieldsetLayout();
+ * fieldset.addItems( [
+ * new OO.ui.FieldLayout( indicator1, { label: 'An alert indicator:' } )
+ * ] );
+ * $( 'body' ).append( fieldset.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Indicators
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.TitledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.IndicatorWidget = function OoUiIndicatorWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.IndicatorWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.IndicatorElement.call( this, $.extend( {}, config, { $indicator: this.$element } ) );
+ OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-indicatorWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.IndicatorWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.mixin.IndicatorElement );
+OO.mixinClass( OO.ui.IndicatorWidget, OO.ui.mixin.TitledElement );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.IndicatorWidget.static.tagName = 'span';
+
+/**
+ * LabelWidgets help identify the function of interface elements. Each LabelWidget can
+ * be configured with a `label` option that is set to a string, a label node, or a function:
+ *
+ * - String: a plaintext string
+ * - jQuery selection: a jQuery selection, used for anything other than a plaintext label, e.g., a
+ * label that includes a link or special styling, such as a gray color or additional graphical elements.
+ * - Function: a function that will produce a string in the future. Functions are used
+ * in cases where the value of the label is not currently defined.
+ *
+ * In addition, the LabelWidget can be associated with an {@link OO.ui.InputWidget input widget}, which
+ * will come into focus when the label is clicked.
+ *
+ * @example
+ * // Examples of LabelWidgets
+ * var label1 = new OO.ui.LabelWidget( {
+ * label: 'plaintext label'
+ * } );
+ * var label2 = new OO.ui.LabelWidget( {
+ * label: $( '<a href="default.html">jQuery label</a>' )
+ * } );
+ * // Create a fieldset layout with fields for each example
+ * var fieldset = new OO.ui.FieldsetLayout();
+ * fieldset.addItems( [
+ * new OO.ui.FieldLayout( label1 ),
+ * new OO.ui.FieldLayout( label2 )
+ * ] );
+ * $( 'body' ).append( fieldset.$element );
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.TitledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.InputWidget} [input] {@link OO.ui.InputWidget Input widget} that uses the label.
+ * Clicking the label will focus the specified input field.
+ */
+OO.ui.LabelWidget = function OoUiLabelWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.LabelWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.LabelElement.call( this, $.extend( {}, config, { $label: this.$element } ) );
+ OO.ui.mixin.TitledElement.call( this, config );
+
+ // Properties
+ this.input = config.input;
+
+ // Initialization
+ if ( this.input ) {
+ if ( this.input.getInputId() ) {
+ this.$element.attr( 'for', this.input.getInputId() );
+ } else {
+ this.$label.on( 'click', function () {
+ this.input.simulateLabelClick();
+ return false;
+ }.bind( this ) );
+ }
+ }
+ this.$element.addClass( 'oo-ui-labelWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.LabelWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.LabelWidget, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.LabelWidget, OO.ui.mixin.TitledElement );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.LabelWidget.static.tagName = 'label';
+
+/**
+ * PendingElement is a mixin that is used to create elements that notify users that something is happening
+ * and that they should wait before proceeding. The pending state is visually represented with a pending
+ * texture that appears in the head of a pending {@link OO.ui.ProcessDialog process dialog} or in the input
+ * field of a {@link OO.ui.TextInputWidget text input widget}.
+ *
+ * Currently, {@link OO.ui.ActionWidget Action widgets}, which mix in this class, can also be marked as pending, but only when
+ * used in {@link OO.ui.MessageDialog message dialogs}. The behavior is not currently supported for action widgets used
+ * in process dialogs.
+ *
+ * @example
+ * function MessageDialog( config ) {
+ * MessageDialog.parent.call( this, config );
+ * }
+ * OO.inheritClass( MessageDialog, OO.ui.MessageDialog );
+ *
+ * MessageDialog.static.name = 'myMessageDialog';
+ * MessageDialog.static.actions = [
+ * { action: 'save', label: 'Done', flags: 'primary' },
+ * { label: 'Cancel', flags: 'safe' }
+ * ];
+ *
+ * MessageDialog.prototype.initialize = function () {
+ * MessageDialog.parent.prototype.initialize.apply( this, arguments );
+ * this.content = new OO.ui.PanelLayout( { $: this.$, padded: true } );
+ * this.content.$element.append( '<p>Click the \'Done\' action widget to see its pending state. Note that action widgets can be marked pending in message dialogs but not process dialogs.</p>' );
+ * this.$body.append( this.content.$element );
+ * };
+ * MessageDialog.prototype.getBodyHeight = function () {
+ * return 100;
+ * }
+ * MessageDialog.prototype.getActionProcess = function ( action ) {
+ * var dialog = this;
+ * if ( action === 'save' ) {
+ * dialog.getActions().get({actions: 'save'})[0].pushPending();
+ * return new OO.ui.Process()
+ * .next( 1000 )
+ * .next( function () {
+ * dialog.getActions().get({actions: 'save'})[0].popPending();
+ * } );
+ * }
+ * return MessageDialog.parent.prototype.getActionProcess.call( this, action );
+ * };
+ *
+ * var windowManager = new OO.ui.WindowManager();
+ * $( 'body' ).append( windowManager.$element );
+ *
+ * var dialog = new MessageDialog();
+ * windowManager.addWindows( [ dialog ] );
+ * windowManager.openWindow( dialog );
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$pending] Element to mark as pending, defaults to this.$element
+ */
+OO.ui.mixin.PendingElement = function OoUiMixinPendingElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.pending = 0;
+ this.$pending = null;
+
+ // Initialisation
+ this.setPendingElement( config.$pending || this.$element );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.mixin.PendingElement );
+
+/* Methods */
+
+/**
+ * Set the pending element (and clean up any existing one).
+ *
+ * @param {jQuery} $pending The element to set to pending.
+ */
+OO.ui.mixin.PendingElement.prototype.setPendingElement = function ( $pending ) {
+ if ( this.$pending ) {
+ this.$pending.removeClass( 'oo-ui-pendingElement-pending' );
+ }
+
+ this.$pending = $pending;
+ if ( this.pending > 0 ) {
+ this.$pending.addClass( 'oo-ui-pendingElement-pending' );
+ }
+};
+
+/**
+ * Check if an element is pending.
+ *
+ * @return {boolean} Element is pending
+ */
+OO.ui.mixin.PendingElement.prototype.isPending = function () {
+ return !!this.pending;
+};
+
+/**
+ * Increase the pending counter. The pending state will remain active until the counter is zero
+ * (i.e., the number of calls to #pushPending and #popPending is the same).
+ *
+ * @chainable
+ */
+OO.ui.mixin.PendingElement.prototype.pushPending = function () {
+ if ( this.pending === 0 ) {
+ this.$pending.addClass( 'oo-ui-pendingElement-pending' );
+ this.updateThemeClasses();
+ }
+ this.pending++;
+
+ return this;
+};
+
+/**
+ * Decrease the pending counter. The pending state will remain active until the counter is zero
+ * (i.e., the number of calls to #pushPending and #popPending is the same).
+ *
+ * @chainable
+ */
+OO.ui.mixin.PendingElement.prototype.popPending = function () {
+ if ( this.pending === 1 ) {
+ this.$pending.removeClass( 'oo-ui-pendingElement-pending' );
+ this.updateThemeClasses();
+ }
+ this.pending = Math.max( 0, this.pending - 1 );
+
+ return this;
+};
+
+/**
+ * Element that will stick adjacent to a specified container, even when it is inserted elsewhere
+ * in the document (for example, in an OO.ui.Window's $overlay).
+ *
+ * The elements's position is automatically calculated and maintained when window is resized or the
+ * page is scrolled. If you reposition the container manually, you have to call #position to make
+ * sure the element is still placed correctly.
+ *
+ * As positioning is only possible when both the element and the container are attached to the DOM
+ * and visible, it's only done after you call #togglePositioning. You might want to do this inside
+ * the #toggle method to display a floating popup, for example.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$floatable] Node to position, assigned to #$floatable, omit to use #$element
+ * @cfg {jQuery} [$floatableContainer] Node to position adjacent to
+ * @cfg {string} [verticalPosition='below'] Where to position $floatable vertically:
+ * 'below': Directly below $floatableContainer, aligning f's top edge with fC's bottom edge
+ * 'above': Directly above $floatableContainer, aligning f's bottom edge with fC's top edge
+ * 'top': Align the top edge with $floatableContainer's top edge
+ * 'bottom': Align the bottom edge with $floatableContainer's bottom edge
+ * 'center': Vertically align the center with $floatableContainer's center
+ * @cfg {string} [horizontalPosition='start'] Where to position $floatable horizontally:
+ * 'before': Directly before $floatableContainer, aligning f's end edge with fC's start edge
+ * 'after': Directly after $floatableContainer, algining f's start edge with fC's end edge
+ * 'start': Align the start (left in LTR, right in RTL) edge with $floatableContainer's start edge
+ * 'end': Align the end (right in LTR, left in RTL) edge with $floatableContainer's end edge
+ * 'center': Horizontally align the center with $floatableContainer's center
+ * @cfg {boolean} [hideWhenOutOfView=true] Whether to hide the floatable element if the container
+ * is out of view
+ */
+OO.ui.mixin.FloatableElement = function OoUiMixinFloatableElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.$floatable = null;
+ this.$floatableContainer = null;
+ this.$floatableWindow = null;
+ this.$floatableClosestScrollable = null;
+ this.onFloatableScrollHandler = this.position.bind( this );
+ this.onFloatableWindowResizeHandler = this.position.bind( this );
+
+ // Initialization
+ this.setFloatableContainer( config.$floatableContainer );
+ this.setFloatableElement( config.$floatable || this.$element );
+ this.setVerticalPosition( config.verticalPosition || 'below' );
+ this.setHorizontalPosition( config.horizontalPosition || 'start' );
+ this.hideWhenOutOfView = config.hideWhenOutOfView === undefined ? true : !!config.hideWhenOutOfView;
+};
+
+/* Methods */
+
+/**
+ * Set floatable element.
+ *
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $floatable Element to make floatable
+ */
+OO.ui.mixin.FloatableElement.prototype.setFloatableElement = function ( $floatable ) {
+ if ( this.$floatable ) {
+ this.$floatable.removeClass( 'oo-ui-floatableElement-floatable' );
+ this.$floatable.css( { left: '', top: '' } );
+ }
+
+ this.$floatable = $floatable.addClass( 'oo-ui-floatableElement-floatable' );
+ this.position();
+};
+
+/**
+ * Set floatable container.
+ *
+ * The element will be positioned relative to the specified container.
+ *
+ * @param {jQuery|null} $floatableContainer Container to keep visible, or null to unset
+ */
+OO.ui.mixin.FloatableElement.prototype.setFloatableContainer = function ( $floatableContainer ) {
+ this.$floatableContainer = $floatableContainer;
+ if ( this.$floatable ) {
+ this.position();
+ }
+};
+
+/**
+ * Change how the element is positioned vertically.
+ *
+ * @param {string} position 'below', 'above', 'top', 'bottom' or 'center'
+ */
+OO.ui.mixin.FloatableElement.prototype.setVerticalPosition = function ( position ) {
+ if ( [ 'below', 'above', 'top', 'bottom', 'center' ].indexOf( position ) === -1 ) {
+ throw new Error( 'Invalid value for vertical position: ' + position );
+ }
+ if ( this.verticalPosition !== position ) {
+ this.verticalPosition = position;
+ if ( this.$floatable ) {
+ this.position();
+ }
+ }
+};
+
+/**
+ * Change how the element is positioned horizontally.
+ *
+ * @param {string} position 'before', 'after', 'start', 'end' or 'center'
+ */
+OO.ui.mixin.FloatableElement.prototype.setHorizontalPosition = function ( position ) {
+ if ( [ 'before', 'after', 'start', 'end', 'center' ].indexOf( position ) === -1 ) {
+ throw new Error( 'Invalid value for horizontal position: ' + position );
+ }
+ if ( this.horizontalPosition !== position ) {
+ this.horizontalPosition = position;
+ if ( this.$floatable ) {
+ this.position();
+ }
+ }
+};
+
+/**
+ * Toggle positioning.
+ *
+ * Do not turn positioning on until after the element is attached to the DOM and visible.
+ *
+ * @param {boolean} [positioning] Enable positioning, omit to toggle
+ * @chainable
+ */
+OO.ui.mixin.FloatableElement.prototype.togglePositioning = function ( positioning ) {
+ var closestScrollableOfContainer;
+
+ if ( !this.$floatable || !this.$floatableContainer ) {
+ return this;
+ }
+
+ positioning = positioning === undefined ? !this.positioning : !!positioning;
+
+ if ( positioning && !this.warnedUnattached && !this.isElementAttached() ) {
+ OO.ui.warnDeprecation( 'FloatableElement#togglePositioning: Before calling this method, the element must be attached to the DOM.' );
+ this.warnedUnattached = true;
+ }
+
+ if ( this.positioning !== positioning ) {
+ this.positioning = positioning;
+
+ this.needsCustomPosition =
+ this.verticalPostion !== 'below' ||
+ this.horizontalPosition !== 'start' ||
+ !OO.ui.contains( this.$floatableContainer[ 0 ], this.$floatable[ 0 ] );
+
+ closestScrollableOfContainer = OO.ui.Element.static.getClosestScrollableContainer( this.$floatableContainer[ 0 ] );
+ // If the scrollable is the root, we have to listen to scroll events
+ // on the window because of browser inconsistencies.
+ if ( $( closestScrollableOfContainer ).is( 'html, body' ) ) {
+ closestScrollableOfContainer = OO.ui.Element.static.getWindow( closestScrollableOfContainer );
+ }
+
+ if ( positioning ) {
+ this.$floatableWindow = $( this.getElementWindow() );
+ this.$floatableWindow.on( 'resize', this.onFloatableWindowResizeHandler );
+
+ this.$floatableClosestScrollable = $( closestScrollableOfContainer );
+ this.$floatableClosestScrollable.on( 'scroll', this.onFloatableScrollHandler );
+
+ // Initial position after visible
+ this.position();
+ } else {
+ if ( this.$floatableWindow ) {
+ this.$floatableWindow.off( 'resize', this.onFloatableWindowResizeHandler );
+ this.$floatableWindow = null;
+ }
+
+ if ( this.$floatableClosestScrollable ) {
+ this.$floatableClosestScrollable.off( 'scroll', this.onFloatableScrollHandler );
+ this.$floatableClosestScrollable = null;
+ }
+
+ this.$floatable.css( { left: '', right: '', top: '' } );
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Check whether the bottom edge of the given element is within the viewport of the given container.
+ *
+ * @private
+ * @param {jQuery} $element
+ * @param {jQuery} $container
+ * @return {boolean}
+ */
+OO.ui.mixin.FloatableElement.prototype.isElementInViewport = function ( $element, $container ) {
+ var elemRect, contRect, topEdgeInBounds, bottomEdgeInBounds, leftEdgeInBounds, rightEdgeInBounds,
+ startEdgeInBounds, endEdgeInBounds,
+ direction = $element.css( 'direction' );
+
+ elemRect = $element[ 0 ].getBoundingClientRect();
+ if ( $container[ 0 ] === window ) {
+ contRect = {
+ top: 0,
+ left: 0,
+ right: document.documentElement.clientWidth,
+ bottom: document.documentElement.clientHeight
+ };
+ } else {
+ contRect = $container[ 0 ].getBoundingClientRect();
+ }
+
+ topEdgeInBounds = elemRect.top >= contRect.top && elemRect.top <= contRect.bottom;
+ bottomEdgeInBounds = elemRect.bottom >= contRect.top && elemRect.bottom <= contRect.bottom;
+ leftEdgeInBounds = elemRect.left >= contRect.left && elemRect.left <= contRect.right;
+ rightEdgeInBounds = elemRect.right >= contRect.left && elemRect.right <= contRect.right;
+ if ( direction === 'rtl' ) {
+ startEdgeInBounds = rightEdgeInBounds;
+ endEdgeInBounds = leftEdgeInBounds;
+ } else {
+ startEdgeInBounds = leftEdgeInBounds;
+ endEdgeInBounds = rightEdgeInBounds;
+ }
+
+ if ( this.verticalPosition === 'below' && !bottomEdgeInBounds ) {
+ return false;
+ }
+ if ( this.verticalPosition === 'above' && !topEdgeInBounds ) {
+ return false;
+ }
+ if ( this.horizontalPosition === 'before' && !startEdgeInBounds ) {
+ return false;
+ }
+ if ( this.horizontalPosition === 'after' && !endEdgeInBounds ) {
+ return false;
+ }
+
+ // The other positioning values are all about being inside the container,
+ // so in those cases all we care about is that any part of the container is visible.
+ return elemRect.top <= contRect.bottom && elemRect.bottom >= contRect.top &&
+ elemRect.left <= contRect.right && elemRect.right >= contRect.left;
+};
+
+/**
+ * Position the floatable below its container.
+ *
+ * This should only be done when both of them are attached to the DOM and visible.
+ *
+ * @chainable
+ */
+OO.ui.mixin.FloatableElement.prototype.position = function () {
+ if ( !this.positioning ) {
+ return this;
+ }
+
+ if ( !(
+ // To continue, some things need to be true:
+ // The element must actually be in the DOM
+ this.isElementAttached() && (
+ // The closest scrollable is the current window
+ this.$floatableClosestScrollable[ 0 ] === this.getElementWindow() ||
+ // OR is an element in the element's DOM
+ $.contains( this.getElementDocument(), this.$floatableClosestScrollable[ 0 ] )
+ )
+ ) ) {
+ // Abort early if important parts of the widget are no longer attached to the DOM
+ return this;
+ }
+
+ if ( this.hideWhenOutOfView && !this.isElementInViewport( this.$floatableContainer, this.$floatableClosestScrollable ) ) {
+ this.$floatable.addClass( 'oo-ui-element-hidden' );
+ return this;
+ } else {
+ this.$floatable.removeClass( 'oo-ui-element-hidden' );
+ }
+
+ if ( !this.needsCustomPosition ) {
+ return this;
+ }
+
+ this.$floatable.css( this.computePosition() );
+
+ // We updated the position, so re-evaluate the clipping state.
+ // (ClippableElement does not listen to 'scroll' events on $floatableContainer's parent, and so
+ // will not notice the need to update itself.)
+ // TODO: This is terrible, we shouldn't need to know about ClippableElement at all here. Why does
+ // it not listen to the right events in the right places?
+ if ( this.clip ) {
+ this.clip();
+ }
+
+ return this;
+};
+
+/**
+ * Compute how #$floatable should be positioned based on the position of #$floatableContainer
+ * and the positioning settings. This is a helper for #position that shouldn't be called directly,
+ * but may be overridden by subclasses if they want to change or add to the positioning logic.
+ *
+ * @return {Object} New position to apply with .css(). Keys are 'top', 'left', 'bottom' and 'right'.
+ */
+OO.ui.mixin.FloatableElement.prototype.computePosition = function () {
+ var isBody, scrollableX, scrollableY, containerPos,
+ horizScrollbarHeight, vertScrollbarWidth, scrollTop, scrollLeft,
+ newPos = { top: '', left: '', bottom: '', right: '' },
+ direction = this.$floatableContainer.css( 'direction' ),
+ $offsetParent = this.$floatable.offsetParent();
+
+ if ( $offsetParent.is( 'html' ) ) {
+ // The innerHeight/Width and clientHeight/Width calculations don't work well on the
+ // <html> element, but they do work on the <body>
+ $offsetParent = $( $offsetParent[ 0 ].ownerDocument.body );
+ }
+ isBody = $offsetParent.is( 'body' );
+ scrollableX = $offsetParent.css( 'overflow-x' ) === 'scroll' || $offsetParent.css( 'overflow-x' ) === 'auto';
+ scrollableY = $offsetParent.css( 'overflow-y' ) === 'scroll' || $offsetParent.css( 'overflow-y' ) === 'auto';
+
+ vertScrollbarWidth = $offsetParent.innerWidth() - $offsetParent.prop( 'clientWidth' );
+ horizScrollbarHeight = $offsetParent.innerHeight() - $offsetParent.prop( 'clientHeight' );
+ // We don't need to compute and add scrollTop and scrollLeft if the scrollable container is the body,
+ // or if it isn't scrollable
+ scrollTop = scrollableY && !isBody ? $offsetParent.scrollTop() : 0;
+ scrollLeft = scrollableX && !isBody ? OO.ui.Element.static.getScrollLeft( $offsetParent[ 0 ] ) : 0;
+
+ // Avoid passing the <body> to getRelativePosition(), because it won't return what we expect
+ // if the <body> has a margin
+ containerPos = isBody ?
+ this.$floatableContainer.offset() :
+ OO.ui.Element.static.getRelativePosition( this.$floatableContainer, $offsetParent );
+ containerPos.bottom = containerPos.top + this.$floatableContainer.outerHeight();
+ containerPos.right = containerPos.left + this.$floatableContainer.outerWidth();
+ containerPos.start = direction === 'rtl' ? containerPos.right : containerPos.left;
+ containerPos.end = direction === 'rtl' ? containerPos.left : containerPos.right;
+
+ if ( this.verticalPosition === 'below' ) {
+ newPos.top = containerPos.bottom;
+ } else if ( this.verticalPosition === 'above' ) {
+ newPos.bottom = $offsetParent.outerHeight() - containerPos.top;
+ } else if ( this.verticalPosition === 'top' ) {
+ newPos.top = containerPos.top;
+ } else if ( this.verticalPosition === 'bottom' ) {
+ newPos.bottom = $offsetParent.outerHeight() - containerPos.bottom;
+ } else if ( this.verticalPosition === 'center' ) {
+ newPos.top = containerPos.top +
+ ( this.$floatableContainer.height() - this.$floatable.height() ) / 2;
+ }
+
+ if ( this.horizontalPosition === 'before' ) {
+ newPos.end = containerPos.start;
+ } else if ( this.horizontalPosition === 'after' ) {
+ newPos.start = containerPos.end;
+ } else if ( this.horizontalPosition === 'start' ) {
+ newPos.start = containerPos.start;
+ } else if ( this.horizontalPosition === 'end' ) {
+ newPos.end = containerPos.end;
+ } else if ( this.horizontalPosition === 'center' ) {
+ newPos.left = containerPos.left +
+ ( this.$floatableContainer.width() - this.$floatable.width() ) / 2;
+ }
+
+ if ( newPos.start !== undefined ) {
+ if ( direction === 'rtl' ) {
+ newPos.right = ( isBody ? $( $offsetParent[ 0 ].ownerDocument.documentElement ) : $offsetParent ).outerWidth() - newPos.start;
+ } else {
+ newPos.left = newPos.start;
+ }
+ delete newPos.start;
+ }
+ if ( newPos.end !== undefined ) {
+ if ( direction === 'rtl' ) {
+ newPos.left = newPos.end;
+ } else {
+ newPos.right = ( isBody ? $( $offsetParent[ 0 ].ownerDocument.documentElement ) : $offsetParent ).outerWidth() - newPos.end;
+ }
+ delete newPos.end;
+ }
+
+ // Account for scroll position
+ if ( newPos.top !== '' ) {
+ newPos.top += scrollTop;
+ }
+ if ( newPos.bottom !== '' ) {
+ newPos.bottom -= scrollTop;
+ }
+ if ( newPos.left !== '' ) {
+ newPos.left += scrollLeft;
+ }
+ if ( newPos.right !== '' ) {
+ newPos.right -= scrollLeft;
+ }
+
+ // Account for scrollbar gutter
+ if ( newPos.bottom !== '' ) {
+ newPos.bottom -= horizScrollbarHeight;
+ }
+ if ( direction === 'rtl' ) {
+ if ( newPos.left !== '' ) {
+ newPos.left -= vertScrollbarWidth;
+ }
+ } else {
+ if ( newPos.right !== '' ) {
+ newPos.right -= vertScrollbarWidth;
+ }
+ }
+
+ return newPos;
+};
+
+/**
+ * Element that can be automatically clipped to visible boundaries.
+ *
+ * Whenever the element's natural height changes, you have to call
+ * {@link OO.ui.mixin.ClippableElement#clip} to make sure it's still
+ * clipping correctly.
+ *
+ * The dimensions of #$clippableContainer will be compared to the boundaries of the
+ * nearest scrollable container. If #$clippableContainer is too tall and/or too wide,
+ * then #$clippable will be given a fixed reduced height and/or width and will be made
+ * scrollable. By default, #$clippable and #$clippableContainer are the same element,
+ * but you can build a static footer by setting #$clippableContainer to an element that contains
+ * #$clippable and the footer.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$clippable] Node to clip, assigned to #$clippable, omit to use #$element
+ * @cfg {jQuery} [$clippableContainer] Node to keep visible, assigned to #$clippableContainer,
+ * omit to use #$clippable
+ */
+OO.ui.mixin.ClippableElement = function OoUiMixinClippableElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.$clippable = null;
+ this.$clippableContainer = null;
+ this.clipping = false;
+ this.clippedHorizontally = false;
+ this.clippedVertically = false;
+ this.$clippableScrollableContainer = null;
+ this.$clippableScroller = null;
+ this.$clippableWindow = null;
+ this.idealWidth = null;
+ this.idealHeight = null;
+ this.onClippableScrollHandler = this.clip.bind( this );
+ this.onClippableWindowResizeHandler = this.clip.bind( this );
+
+ // Initialization
+ if ( config.$clippableContainer ) {
+ this.setClippableContainer( config.$clippableContainer );
+ }
+ this.setClippableElement( config.$clippable || this.$element );
+};
+
+/* Methods */
+
+/**
+ * Set clippable element.
+ *
+ * If an element is already set, it will be cleaned up before setting up the new element.
+ *
+ * @param {jQuery} $clippable Element to make clippable
+ */
+OO.ui.mixin.ClippableElement.prototype.setClippableElement = function ( $clippable ) {
+ if ( this.$clippable ) {
+ this.$clippable.removeClass( 'oo-ui-clippableElement-clippable' );
+ this.$clippable.css( { width: '', height: '', overflowX: '', overflowY: '' } );
+ OO.ui.Element.static.reconsiderScrollbars( this.$clippable[ 0 ] );
+ }
+
+ this.$clippable = $clippable.addClass( 'oo-ui-clippableElement-clippable' );
+ this.clip();
+};
+
+/**
+ * Set clippable container.
+ *
+ * This is the container that will be measured when deciding whether to clip. When clipping,
+ * #$clippable will be resized in order to keep the clippable container fully visible.
+ *
+ * If the clippable container is unset, #$clippable will be used.
+ *
+ * @param {jQuery|null} $clippableContainer Container to keep visible, or null to unset
+ */
+OO.ui.mixin.ClippableElement.prototype.setClippableContainer = function ( $clippableContainer ) {
+ this.$clippableContainer = $clippableContainer;
+ if ( this.$clippable ) {
+ this.clip();
+ }
+};
+
+/**
+ * Toggle clipping.
+ *
+ * Do not turn clipping on until after the element is attached to the DOM and visible.
+ *
+ * @param {boolean} [clipping] Enable clipping, omit to toggle
+ * @chainable
+ */
+OO.ui.mixin.ClippableElement.prototype.toggleClipping = function ( clipping ) {
+ clipping = clipping === undefined ? !this.clipping : !!clipping;
+
+ if ( clipping && !this.warnedUnattached && !this.isElementAttached() ) {
+ OO.ui.warnDeprecation( 'ClippableElement#toggleClipping: Before calling this method, the element must be attached to the DOM.' );
+ this.warnedUnattached = true;
+ }
+
+ if ( this.clipping !== clipping ) {
+ this.clipping = clipping;
+ if ( clipping ) {
+ this.$clippableScrollableContainer = $( this.getClosestScrollableElementContainer() );
+ // If the clippable container is the root, we have to listen to scroll events and check
+ // jQuery.scrollTop on the window because of browser inconsistencies
+ this.$clippableScroller = this.$clippableScrollableContainer.is( 'html, body' ) ?
+ $( OO.ui.Element.static.getWindow( this.$clippableScrollableContainer ) ) :
+ this.$clippableScrollableContainer;
+ this.$clippableScroller.on( 'scroll', this.onClippableScrollHandler );
+ this.$clippableWindow = $( this.getElementWindow() )
+ .on( 'resize', this.onClippableWindowResizeHandler );
+ // Initial clip after visible
+ this.clip();
+ } else {
+ this.$clippable.css( {
+ width: '',
+ height: '',
+ maxWidth: '',
+ maxHeight: '',
+ overflowX: '',
+ overflowY: ''
+ } );
+ OO.ui.Element.static.reconsiderScrollbars( this.$clippable[ 0 ] );
+
+ this.$clippableScrollableContainer = null;
+ this.$clippableScroller.off( 'scroll', this.onClippableScrollHandler );
+ this.$clippableScroller = null;
+ this.$clippableWindow.off( 'resize', this.onClippableWindowResizeHandler );
+ this.$clippableWindow = null;
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Check if the element will be clipped to fit the visible area of the nearest scrollable container.
+ *
+ * @return {boolean} Element will be clipped to the visible area
+ */
+OO.ui.mixin.ClippableElement.prototype.isClipping = function () {
+ return this.clipping;
+};
+
+/**
+ * Check if the bottom or right of the element is being clipped by the nearest scrollable container.
+ *
+ * @return {boolean} Part of the element is being clipped
+ */
+OO.ui.mixin.ClippableElement.prototype.isClipped = function () {
+ return this.clippedHorizontally || this.clippedVertically;
+};
+
+/**
+ * Check if the right of the element is being clipped by the nearest scrollable container.
+ *
+ * @return {boolean} Part of the element is being clipped
+ */
+OO.ui.mixin.ClippableElement.prototype.isClippedHorizontally = function () {
+ return this.clippedHorizontally;
+};
+
+/**
+ * Check if the bottom of the element is being clipped by the nearest scrollable container.
+ *
+ * @return {boolean} Part of the element is being clipped
+ */
+OO.ui.mixin.ClippableElement.prototype.isClippedVertically = function () {
+ return this.clippedVertically;
+};
+
+/**
+ * Set the ideal size. These are the dimensions #$clippable will have when it's not being clipped.
+ *
+ * @param {number|string} [width] Width as a number of pixels or CSS string with unit suffix
+ * @param {number|string} [height] Height as a number of pixels or CSS string with unit suffix
+ */
+OO.ui.mixin.ClippableElement.prototype.setIdealSize = function ( width, height ) {
+ this.idealWidth = width;
+ this.idealHeight = height;
+
+ if ( !this.clipping ) {
+ // Update dimensions
+ this.$clippable.css( { width: width, height: height } );
+ }
+ // While clipping, idealWidth and idealHeight are not considered
+};
+
+/**
+ * Clip element to visible boundaries and allow scrolling when needed. You should call this method
+ * when the element's natural height changes.
+ *
+ * Element will be clipped the bottom or right of the element is within 10px of the edge of, or
+ * overlapped by, the visible area of the nearest scrollable container.
+ *
+ * Because calling clip() when the natural height changes isn't always possible, we also set
+ * max-height when the element isn't being clipped. This means that if the element tries to grow
+ * beyond the edge, something reasonable will happen before clip() is called.
+ *
+ * @chainable
+ */
+OO.ui.mixin.ClippableElement.prototype.clip = function () {
+ var $container, extraHeight, extraWidth, ccOffset,
+ $scrollableContainer, scOffset, scHeight, scWidth,
+ ccWidth, scrollerIsWindow, scrollTop, scrollLeft,
+ desiredWidth, desiredHeight, allotedWidth, allotedHeight,
+ naturalWidth, naturalHeight, clipWidth, clipHeight,
+ buffer = 7; // Chosen by fair dice roll
+
+ if ( !this.clipping ) {
+ // this.$clippableScrollableContainer and this.$clippableWindow are null, so the below will fail
+ return this;
+ }
+
+ $container = this.$clippableContainer || this.$clippable;
+ extraHeight = $container.outerHeight() - this.$clippable.outerHeight();
+ extraWidth = $container.outerWidth() - this.$clippable.outerWidth();
+ ccOffset = $container.offset();
+ if ( this.$clippableScrollableContainer.is( 'html, body' ) ) {
+ $scrollableContainer = this.$clippableWindow;
+ scOffset = { top: 0, left: 0 };
+ } else {
+ $scrollableContainer = this.$clippableScrollableContainer;
+ scOffset = $scrollableContainer.offset();
+ }
+ scHeight = $scrollableContainer.innerHeight() - buffer;
+ scWidth = $scrollableContainer.innerWidth() - buffer;
+ ccWidth = $container.outerWidth() + buffer;
+ scrollerIsWindow = this.$clippableScroller[ 0 ] === this.$clippableWindow[ 0 ];
+ scrollTop = scrollerIsWindow ? this.$clippableScroller.scrollTop() : 0;
+ scrollLeft = scrollerIsWindow ? this.$clippableScroller.scrollLeft() : 0;
+ desiredWidth = ccOffset.left < 0 ?
+ ccWidth + ccOffset.left :
+ ( scOffset.left + scrollLeft + scWidth ) - ccOffset.left;
+ desiredHeight = ( scOffset.top + scrollTop + scHeight ) - ccOffset.top;
+ // It should never be desirable to exceed the dimensions of the browser viewport... right?
+ desiredWidth = Math.min( desiredWidth, document.documentElement.clientWidth );
+ desiredHeight = Math.min( desiredHeight, document.documentElement.clientHeight );
+ allotedWidth = Math.ceil( desiredWidth - extraWidth );
+ allotedHeight = Math.ceil( desiredHeight - extraHeight );
+ naturalWidth = this.$clippable.prop( 'scrollWidth' );
+ naturalHeight = this.$clippable.prop( 'scrollHeight' );
+ clipWidth = allotedWidth < naturalWidth;
+ clipHeight = allotedHeight < naturalHeight;
+
+ if ( clipWidth ) {
+ // The order matters here. If overflow is not set first, Chrome displays bogus scrollbars. See T157672.
+ // Forcing a reflow is a smaller workaround than calling reconsiderScrollbars() for this case.
+ this.$clippable.css( 'overflowX', 'scroll' );
+ void this.$clippable[ 0 ].offsetHeight; // Force reflow
+ this.$clippable.css( {
+ width: Math.max( 0, allotedWidth ),
+ maxWidth: ''
+ } );
+ } else {
+ this.$clippable.css( {
+ overflowX: '',
+ width: this.idealWidth || '',
+ maxWidth: Math.max( 0, allotedWidth )
+ } );
+ }
+ if ( clipHeight ) {
+ // The order matters here. If overflow is not set first, Chrome displays bogus scrollbars. See T157672.
+ // Forcing a reflow is a smaller workaround than calling reconsiderScrollbars() for this case.
+ this.$clippable.css( 'overflowY', 'scroll' );
+ void this.$clippable[ 0 ].offsetHeight; // Force reflow
+ this.$clippable.css( {
+ height: Math.max( 0, allotedHeight ),
+ maxHeight: ''
+ } );
+ } else {
+ this.$clippable.css( {
+ overflowY: '',
+ height: this.idealHeight || '',
+ maxHeight: Math.max( 0, allotedHeight )
+ } );
+ }
+
+ // If we stopped clipping in at least one of the dimensions
+ if ( ( this.clippedHorizontally && !clipWidth ) || ( this.clippedVertically && !clipHeight ) ) {
+ OO.ui.Element.static.reconsiderScrollbars( this.$clippable[ 0 ] );
+ }
+
+ this.clippedHorizontally = clipWidth;
+ this.clippedVertically = clipHeight;
+
+ return this;
+};
+
+/**
+ * PopupWidget is a container for content. The popup is overlaid and positioned absolutely.
+ * By default, each popup has an anchor that points toward its origin.
+ * Please see the [OOjs UI documentation on Mediawiki] [1] for more information and examples.
+ *
+ * Unlike most widgets, PopupWidget is initially hidden and must be shown by calling #toggle.
+ *
+ * @example
+ * // A popup widget.
+ * var popup = new OO.ui.PopupWidget( {
+ * $content: $( '<p>Hi there!</p>' ),
+ * padded: true,
+ * width: 300
+ * } );
+ *
+ * $( 'body' ).append( popup.$element );
+ * // To display the popup, toggle the visibility to 'true'.
+ * popup.toggle( true );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Popups
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.ClippableElement
+ * @mixins OO.ui.mixin.FloatableElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [width=320] Width of popup in pixels
+ * @cfg {number} [height] Height of popup in pixels. Omit to use the automatic height.
+ * @cfg {boolean} [anchor=true] Show anchor pointing to origin of popup
+ * @cfg {string} [position='below'] Where to position the popup relative to $floatableContainer
+ * 'above': Put popup above $floatableContainer; anchor points down to the horizontal center
+ * of $floatableContainer
+ * 'below': Put popup below $floatableContainer; anchor points up to the horizontal center
+ * of $floatableContainer
+ * 'before': Put popup to the left (LTR) / right (RTL) of $floatableContainer; anchor points
+ * endwards (right/left) to the vertical center of $floatableContainer
+ * 'after': Put popup to the right (LTR) / left (RTL) of $floatableContainer; anchor points
+ * startwards (left/right) to the vertical center of $floatableContainer
+ * @cfg {string} [align='center'] How to align the popup to $floatableContainer
+ * 'forwards': If position is above/below, move the popup as far endwards (right in LTR, left in RTL)
+ * as possible while still keeping the anchor within the popup;
+ * if position is before/after, move the popup as far downwards as possible.
+ * 'backwards': If position is above/below, move the popup as far startwards (left in LTR, right in RTL)
+ * as possible while still keeping the anchor within the popup;
+ * if position in before/after, move the popup as far upwards as possible.
+ * 'center': Horizontally (if position is above/below) or vertically (before/after) align the center
+ * of the popup with the center of $floatableContainer.
+ * 'force-left': Alias for 'forwards' in LTR and 'backwards' in RTL
+ * 'force-right': Alias for 'backwards' in RTL and 'forwards' in LTR
+ * @cfg {jQuery} [$container] Constrain the popup to the boundaries of the specified container.
+ * See the [OOjs UI docs on MediaWiki][3] for an example.
+ * [3]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Popups#containerExample
+ * @cfg {number} [containerPadding=10] Padding between the popup and its container, specified as a number of pixels.
+ * @cfg {jQuery} [$content] Content to append to the popup's body
+ * @cfg {jQuery} [$footer] Content to append to the popup's footer
+ * @cfg {boolean} [autoClose=false] Automatically close the popup when it loses focus.
+ * @cfg {jQuery} [$autoCloseIgnore] Elements that will not close the popup when clicked.
+ * This config option is only relevant if #autoClose is set to `true`. See the [OOjs UI docs on MediaWiki][2]
+ * for an example.
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Popups#autocloseExample
+ * @cfg {boolean} [head=false] Show a popup header that contains a #label (if specified) and close
+ * button.
+ * @cfg {boolean} [padded=false] Add padding to the popup's body
+ */
+OO.ui.PopupWidget = function OoUiPopupWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.PopupWidget.parent.call( this, config );
+
+ // Properties (must be set before ClippableElement constructor call)
+ this.$body = $( '<div>' );
+ this.$popup = $( '<div>' );
+
+ // Mixin constructors
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.ClippableElement.call( this, $.extend( {}, config, {
+ $clippable: this.$body,
+ $clippableContainer: this.$popup
+ } ) );
+ OO.ui.mixin.FloatableElement.call( this, config );
+
+ // Properties
+ this.$anchor = $( '<div>' );
+ // If undefined, will be computed lazily in computePosition()
+ this.$container = config.$container;
+ this.containerPadding = config.containerPadding !== undefined ? config.containerPadding : 10;
+ this.autoClose = !!config.autoClose;
+ this.$autoCloseIgnore = config.$autoCloseIgnore;
+ this.transitionTimeout = null;
+ this.anchored = false;
+ this.width = config.width !== undefined ? config.width : 320;
+ this.height = config.height !== undefined ? config.height : null;
+ this.onMouseDownHandler = this.onMouseDown.bind( this );
+ this.onDocumentKeyDownHandler = this.onDocumentKeyDown.bind( this );
+
+ // Initialization
+ this.toggleAnchor( config.anchor === undefined || config.anchor );
+ this.setAlignment( config.align || 'center' );
+ this.setPosition( config.position || 'below' );
+ this.$body.addClass( 'oo-ui-popupWidget-body' );
+ this.$anchor.addClass( 'oo-ui-popupWidget-anchor' );
+ this.$popup
+ .addClass( 'oo-ui-popupWidget-popup' )
+ .append( this.$body );
+ this.$element
+ .addClass( 'oo-ui-popupWidget' )
+ .append( this.$popup, this.$anchor );
+ // Move content, which was added to #$element by OO.ui.Widget, to the body
+ // FIXME This is gross, we should use '$body' or something for the config
+ if ( config.$content instanceof jQuery ) {
+ this.$body.append( config.$content );
+ }
+
+ if ( config.padded ) {
+ this.$body.addClass( 'oo-ui-popupWidget-body-padded' );
+ }
+
+ if ( config.head ) {
+ this.closeButton = new OO.ui.ButtonWidget( { framed: false, icon: 'close' } );
+ this.closeButton.connect( this, { click: 'onCloseButtonClick' } );
+ this.$head = $( '<div>' )
+ .addClass( 'oo-ui-popupWidget-head' )
+ .append( this.$label, this.closeButton.$element );
+ this.$popup.prepend( this.$head );
+ }
+
+ if ( config.$footer ) {
+ this.$footer = $( '<div>' )
+ .addClass( 'oo-ui-popupWidget-footer' )
+ .append( config.$footer );
+ this.$popup.append( this.$footer );
+ }
+
+ // Initially hidden - using #toggle may cause errors if subclasses override toggle with methods
+ // that reference properties not initialized at that time of parent class construction
+ // TODO: Find a better way to handle post-constructor setup
+ this.visible = false;
+ this.$element.addClass( 'oo-ui-element-hidden' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PopupWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.PopupWidget, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.PopupWidget, OO.ui.mixin.ClippableElement );
+OO.mixinClass( OO.ui.PopupWidget, OO.ui.mixin.FloatableElement );
+
+/* Events */
+
+/**
+ * @event ready
+ *
+ * The popup is ready: it is visible and has been positioned and clipped.
+ */
+
+/* Methods */
+
+/**
+ * Handles mouse down events.
+ *
+ * @private
+ * @param {MouseEvent} e Mouse down event
+ */
+OO.ui.PopupWidget.prototype.onMouseDown = function ( e ) {
+ if (
+ this.isVisible() &&
+ !OO.ui.contains( this.$element.add( this.$autoCloseIgnore ).get(), e.target, true )
+ ) {
+ this.toggle( false );
+ }
+};
+
+/**
+ * Bind mouse down listener.
+ *
+ * @private
+ */
+OO.ui.PopupWidget.prototype.bindMouseDownListener = function () {
+ // Capture clicks outside popup
+ this.getElementWindow().addEventListener( 'mousedown', this.onMouseDownHandler, true );
+};
+
+/**
+ * Handles close button click events.
+ *
+ * @private
+ */
+OO.ui.PopupWidget.prototype.onCloseButtonClick = function () {
+ if ( this.isVisible() ) {
+ this.toggle( false );
+ }
+};
+
+/**
+ * Unbind mouse down listener.
+ *
+ * @private
+ */
+OO.ui.PopupWidget.prototype.unbindMouseDownListener = function () {
+ this.getElementWindow().removeEventListener( 'mousedown', this.onMouseDownHandler, true );
+};
+
+/**
+ * Handles key down events.
+ *
+ * @private
+ * @param {KeyboardEvent} e Key down event
+ */
+OO.ui.PopupWidget.prototype.onDocumentKeyDown = function ( e ) {
+ if (
+ e.which === OO.ui.Keys.ESCAPE &&
+ this.isVisible()
+ ) {
+ this.toggle( false );
+ e.preventDefault();
+ e.stopPropagation();
+ }
+};
+
+/**
+ * Bind key down listener.
+ *
+ * @private
+ */
+OO.ui.PopupWidget.prototype.bindKeyDownListener = function () {
+ this.getElementWindow().addEventListener( 'keydown', this.onDocumentKeyDownHandler, true );
+};
+
+/**
+ * Unbind key down listener.
+ *
+ * @private
+ */
+OO.ui.PopupWidget.prototype.unbindKeyDownListener = function () {
+ this.getElementWindow().removeEventListener( 'keydown', this.onDocumentKeyDownHandler, true );
+};
+
+/**
+ * Show, hide, or toggle the visibility of the anchor.
+ *
+ * @param {boolean} [show] Show anchor, omit to toggle
+ */
+OO.ui.PopupWidget.prototype.toggleAnchor = function ( show ) {
+ show = show === undefined ? !this.anchored : !!show;
+
+ if ( this.anchored !== show ) {
+ if ( show ) {
+ this.$element.addClass( 'oo-ui-popupWidget-anchored' );
+ this.$element.addClass( 'oo-ui-popupWidget-anchored-' + this.anchorEdge );
+ } else {
+ this.$element.removeClass( 'oo-ui-popupWidget-anchored' );
+ this.$element.removeClass( 'oo-ui-popupWidget-anchored-' + this.anchorEdge );
+ }
+ this.anchored = show;
+ }
+};
+/**
+ * Change which edge the anchor appears on.
+ *
+ * @param {string} edge 'top', 'bottom', 'start' or 'end'
+ */
+OO.ui.PopupWidget.prototype.setAnchorEdge = function ( edge ) {
+ if ( [ 'top', 'bottom', 'start', 'end' ].indexOf( edge ) === -1 ) {
+ throw new Error( 'Invalid value for edge: ' + edge );
+ }
+ if ( this.anchorEdge !== null ) {
+ this.$element.removeClass( 'oo-ui-popupWidget-anchored-' + this.anchorEdge );
+ }
+ this.anchorEdge = edge;
+ if ( this.anchored ) {
+ this.$element.addClass( 'oo-ui-popupWidget-anchored-' + edge );
+ }
+};
+
+/**
+ * Check if the anchor is visible.
+ *
+ * @return {boolean} Anchor is visible
+ */
+OO.ui.PopupWidget.prototype.hasAnchor = function () {
+ return this.anchored;
+};
+
+/**
+ * Toggle visibility of the popup. The popup is initially hidden and must be shown by calling
+ * `.toggle( true )` after its #$element is attached to the DOM.
+ *
+ * Do not show the popup while it is not attached to the DOM. The calculations required to display
+ * it in the right place and with the right dimensions only work correctly while it is attached.
+ * Side-effects may include broken interface and exceptions being thrown. This wasn't always
+ * strictly enforced, so currently it only generates a warning in the browser console.
+ *
+ * @fires ready
+ * @inheritdoc
+ */
+OO.ui.PopupWidget.prototype.toggle = function ( show ) {
+ var change;
+ show = show === undefined ? !this.isVisible() : !!show;
+
+ change = show !== this.isVisible();
+
+ if ( show && !this.warnedUnattached && !this.isElementAttached() ) {
+ OO.ui.warnDeprecation( 'PopupWidget#toggle: Before calling this method, the popup must be attached to the DOM.' );
+ this.warnedUnattached = true;
+ }
+ if ( show && !this.$floatableContainer && this.isElementAttached() ) {
+ // Fall back to the parent node if the floatableContainer is not set
+ this.setFloatableContainer( this.$element.parent() );
+ }
+
+ // Parent method
+ OO.ui.PopupWidget.parent.prototype.toggle.call( this, show );
+
+ if ( change ) {
+ this.togglePositioning( show && !!this.$floatableContainer );
+
+ if ( show ) {
+ if ( this.autoClose ) {
+ this.bindMouseDownListener();
+ this.bindKeyDownListener();
+ }
+ this.updateDimensions();
+ this.toggleClipping( true );
+ this.emit( 'ready' );
+ } else {
+ this.toggleClipping( false );
+ if ( this.autoClose ) {
+ this.unbindMouseDownListener();
+ this.unbindKeyDownListener();
+ }
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Set the size of the popup.
+ *
+ * Changing the size may also change the popup's position depending on the alignment.
+ *
+ * @param {number} width Width in pixels
+ * @param {number} height Height in pixels
+ * @param {boolean} [transition=false] Use a smooth transition
+ * @chainable
+ */
+OO.ui.PopupWidget.prototype.setSize = function ( width, height, transition ) {
+ this.width = width;
+ this.height = height !== undefined ? height : null;
+ if ( this.isVisible() ) {
+ this.updateDimensions( transition );
+ }
+};
+
+/**
+ * Update the size and position.
+ *
+ * Only use this to keep the popup properly anchored. Use #setSize to change the size, and this will
+ * be called automatically.
+ *
+ * @param {boolean} [transition=false] Use a smooth transition
+ * @chainable
+ */
+OO.ui.PopupWidget.prototype.updateDimensions = function ( transition ) {
+ var widget = this;
+
+ // Prevent transition from being interrupted
+ clearTimeout( this.transitionTimeout );
+ if ( transition ) {
+ // Enable transition
+ this.$element.addClass( 'oo-ui-popupWidget-transitioning' );
+ }
+
+ this.position();
+
+ if ( transition ) {
+ // Prevent transitioning after transition is complete
+ this.transitionTimeout = setTimeout( function () {
+ widget.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
+ }, 200 );
+ } else {
+ // Prevent transitioning immediately
+ this.$element.removeClass( 'oo-ui-popupWidget-transitioning' );
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.PopupWidget.prototype.computePosition = function () {
+ var direction, align, vertical, start, end, near, far, sizeProp, popupSize, anchorSize, anchorPos,
+ anchorOffset, anchorMargin, parentPosition, positionProp, positionAdjustment, floatablePos,
+ offsetParentPos, containerPos,
+ popupPos = {},
+ anchorCss = { left: '', right: '', top: '', bottom: '' },
+ alignMap = {
+ ltr: {
+ 'force-left': 'backwards',
+ 'force-right': 'forwards'
+ },
+ rtl: {
+ 'force-left': 'forwards',
+ 'force-right': 'backwards'
+ }
+ },
+ anchorEdgeMap = {
+ above: 'bottom',
+ below: 'top',
+ before: 'end',
+ after: 'start'
+ },
+ hPosMap = {
+ forwards: 'start',
+ center: 'center',
+ backwards: this.anchored ? 'before' : 'end'
+ },
+ vPosMap = {
+ forwards: 'top',
+ center: 'center',
+ backwards: 'bottom'
+ };
+
+ if ( !this.$container ) {
+ // Lazy-initialize $container if not specified in constructor
+ this.$container = $( this.getClosestScrollableElementContainer() );
+ }
+ direction = this.$container.css( 'direction' );
+
+ // Set height and width before we do anything else, since it might cause our measurements
+ // to change (e.g. due to scrollbars appearing or disappearing), and it also affects centering
+ this.$popup.css( {
+ width: this.width,
+ height: this.height !== null ? this.height : 'auto'
+ } );
+
+ align = alignMap[ direction ][ this.align ] || this.align;
+ // If the popup is positioned before or after, then the anchor positioning is vertical, otherwise horizontal
+ vertical = this.popupPosition === 'before' || this.popupPosition === 'after';
+ start = vertical ? 'top' : ( direction === 'rtl' ? 'right' : 'left' );
+ end = vertical ? 'bottom' : ( direction === 'rtl' ? 'left' : 'right' );
+ near = vertical ? 'top' : 'left';
+ far = vertical ? 'bottom' : 'right';
+ sizeProp = vertical ? 'Height' : 'Width';
+ popupSize = vertical ? ( this.height || this.$popup.height() ) : this.width;
+
+ this.setAnchorEdge( anchorEdgeMap[ this.popupPosition ] );
+ this.horizontalPosition = vertical ? this.popupPosition : hPosMap[ align ];
+ this.verticalPosition = vertical ? vPosMap[ align ] : this.popupPosition;
+
+ // Parent method
+ parentPosition = OO.ui.mixin.FloatableElement.prototype.computePosition.call( this );
+ // Find out which property FloatableElement used for positioning, and adjust that value
+ positionProp = vertical ?
+ ( parentPosition.top !== '' ? 'top' : 'bottom' ) :
+ ( parentPosition.left !== '' ? 'left' : 'right' );
+
+ // Figure out where the near and far edges of the popup and $floatableContainer are
+ floatablePos = this.$floatableContainer.offset();
+ floatablePos[ far ] = floatablePos[ near ] + this.$floatableContainer[ 'outer' + sizeProp ]();
+ // Measure where the offsetParent is and compute our position based on that and parentPosition
+ offsetParentPos = this.$element.offsetParent().offset();
+
+ if ( positionProp === near ) {
+ popupPos[ near ] = offsetParentPos[ near ] + parentPosition[ near ];
+ popupPos[ far ] = popupPos[ near ] + popupSize;
+ } else {
+ popupPos[ far ] = offsetParentPos[ near ] +
+ this.$element.offsetParent()[ 'inner' + sizeProp ]() - parentPosition[ far ];
+ popupPos[ near ] = popupPos[ far ] - popupSize;
+ }
+
+ if ( this.anchored ) {
+ // Position the anchor (which is positioned relative to the popup) to point to $floatableContainer
+ anchorPos = ( floatablePos[ start ] + floatablePos[ end ] ) / 2;
+ anchorOffset = ( start === far ? -1 : 1 ) * ( anchorPos - popupPos[ start ] );
+
+ // If the anchor is less than 2*anchorSize from either edge, move the popup to make more space
+ // this.$anchor.width()/height() returns 0 because of the CSS trickery we use, so use scrollWidth/Height
+ anchorSize = this.$anchor[ 0 ][ 'scroll' + sizeProp ];
+ anchorMargin = parseFloat( this.$anchor.css( 'margin-' + start ) );
+ if ( anchorOffset + anchorMargin < 2 * anchorSize ) {
+ // Not enough space for the anchor on the start side; pull the popup startwards
+ positionAdjustment = ( positionProp === start ? -1 : 1 ) *
+ ( 2 * anchorSize - ( anchorOffset + anchorMargin ) );
+ } else if ( anchorOffset + anchorMargin > popupSize - 2 * anchorSize ) {
+ // Not enough space for the anchor on the end side; pull the popup endwards
+ positionAdjustment = ( positionProp === end ? -1 : 1 ) *
+ ( anchorOffset + anchorMargin - ( popupSize - 2 * anchorSize ) );
+ } else {
+ positionAdjustment = 0;
+ }
+ } else {
+ positionAdjustment = 0;
+ }
+
+ // Check if the popup will go beyond the edge of this.$container
+ containerPos = this.$container.offset();
+ containerPos[ far ] = containerPos[ near ] + this.$container[ 'inner' + sizeProp ]();
+ // Take into account how much the popup will move because of the adjustments we're going to make
+ popupPos[ near ] += ( positionProp === near ? 1 : -1 ) * positionAdjustment;
+ popupPos[ far ] += ( positionProp === near ? 1 : -1 ) * positionAdjustment;
+ if ( containerPos[ near ] + this.containerPadding > popupPos[ near ] ) {
+ // Popup goes beyond the near (left/top) edge, move it to the right/bottom
+ positionAdjustment += ( positionProp === near ? 1 : -1 ) *
+ ( containerPos[ near ] + this.containerPadding - popupPos[ near ] );
+ } else if ( containerPos[ far ] - this.containerPadding < popupPos[ far ] ) {
+ // Popup goes beyond the far (right/bottom) edge, move it to the left/top
+ positionAdjustment += ( positionProp === far ? 1 : -1 ) *
+ ( popupPos[ far ] - ( containerPos[ far ] - this.containerPadding ) );
+ }
+
+ if ( this.anchored ) {
+ // Adjust anchorOffset for positionAdjustment
+ anchorOffset += ( positionProp === start ? -1 : 1 ) * positionAdjustment;
+
+ // Position the anchor
+ anchorCss[ start ] = anchorOffset;
+ this.$anchor.css( anchorCss );
+ }
+
+ // Move the popup if needed
+ parentPosition[ positionProp ] += positionAdjustment;
+
+ return parentPosition;
+};
+
+/**
+ * Set popup alignment
+ *
+ * @param {string} [align=center] Alignment of the popup, `center`, `force-left`, `force-right`,
+ * `backwards` or `forwards`.
+ */
+OO.ui.PopupWidget.prototype.setAlignment = function ( align ) {
+ // Validate alignment
+ if ( [ 'force-left', 'force-right', 'backwards', 'forwards', 'center' ].indexOf( align ) > -1 ) {
+ this.align = align;
+ } else {
+ this.align = 'center';
+ }
+ this.position();
+};
+
+/**
+ * Get popup alignment
+ *
+ * @return {string} Alignment of the popup, `center`, `force-left`, `force-right`,
+ * `backwards` or `forwards`.
+ */
+OO.ui.PopupWidget.prototype.getAlignment = function () {
+ return this.align;
+};
+
+/**
+ * Change the positioning of the popup.
+ *
+ * @param {string} position 'above', 'below', 'before' or 'after'
+ */
+OO.ui.PopupWidget.prototype.setPosition = function ( position ) {
+ if ( [ 'above', 'below', 'before', 'after' ].indexOf( position ) === -1 ) {
+ position = 'below';
+ }
+ this.popupPosition = position;
+ this.position();
+};
+
+/**
+ * Get popup positioning.
+ *
+ * @return {string} 'above', 'below', 'before' or 'after'
+ */
+OO.ui.PopupWidget.prototype.getPosition = function () {
+ return this.popupPosition;
+};
+
+/**
+ * Get an ID of the body element, this can be used as the
+ * `aria-describedby` attribute for an input field.
+ *
+ * @return {string} The ID of the body element
+ */
+OO.ui.PopupWidget.prototype.getBodyId = function () {
+ var id = this.$body.attr( 'id' );
+ if ( id === undefined ) {
+ id = OO.ui.generateElementId();
+ this.$body.attr( 'id', id );
+ }
+ return id;
+};
+
+/**
+ * PopupElement is mixed into other classes to generate a {@link OO.ui.PopupWidget popup widget}.
+ * A popup is a container for content. It is overlaid and positioned absolutely. By default, each
+ * popup has an anchor, which is an arrow-like protrusion that points toward the popup’s origin.
+ * See {@link OO.ui.PopupWidget PopupWidget} for an example.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} [popup] Configuration to pass to popup
+ * @cfg {boolean} [popup.autoClose=true] Popup auto-closes when it loses focus
+ */
+OO.ui.mixin.PopupElement = function OoUiMixinPopupElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.popup = new OO.ui.PopupWidget( $.extend(
+ {
+ autoClose: true,
+ $floatableContainer: this.$element
+ },
+ config.popup,
+ {
+ $autoCloseIgnore: this.$element.add( config.popup && config.popup.$autoCloseIgnore )
+ }
+ ) );
+};
+
+/* Methods */
+
+/**
+ * Get popup.
+ *
+ * @return {OO.ui.PopupWidget} Popup widget
+ */
+OO.ui.mixin.PopupElement.prototype.getPopup = function () {
+ return this.popup;
+};
+
+/**
+ * PopupButtonWidgets toggle the visibility of a contained {@link OO.ui.PopupWidget PopupWidget},
+ * which is used to display additional information or options.
+ *
+ * @example
+ * // Example of a popup button.
+ * var popupButton = new OO.ui.PopupButtonWidget( {
+ * label: 'Popup button with options',
+ * icon: 'menu',
+ * popup: {
+ * $content: $( '<p>Additional options here.</p>' ),
+ * padded: true,
+ * align: 'force-left'
+ * }
+ * } );
+ * // Append the button to the DOM.
+ * $( 'body' ).append( popupButton.$element );
+ *
+ * @class
+ * @extends OO.ui.ButtonWidget
+ * @mixins OO.ui.mixin.PopupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$overlay] Render the popup into a separate layer. This configuration is useful in cases where
+ * the expanded popup is larger than its containing `<div>`. The specified overlay layer is usually on top of the
+ * containing `<div>` and has a larger area. By default, the popup uses relative positioning.
+ * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.
+ */
+OO.ui.PopupButtonWidget = function OoUiPopupButtonWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.PopupButtonWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.PopupElement.call( this, config );
+
+ // Properties
+ this.$overlay = config.$overlay || this.$element;
+
+ // Events
+ this.connect( this, { click: 'onAction' } );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-popupButtonWidget' )
+ .attr( 'aria-haspopup', 'true' );
+ this.popup.$element
+ .addClass( 'oo-ui-popupButtonWidget-popup' )
+ .toggleClass( 'oo-ui-popupButtonWidget-framed-popup', this.isFramed() )
+ .toggleClass( 'oo-ui-popupButtonWidget-frameless-popup', !this.isFramed() );
+ this.$overlay.append( this.popup.$element );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PopupButtonWidget, OO.ui.ButtonWidget );
+OO.mixinClass( OO.ui.PopupButtonWidget, OO.ui.mixin.PopupElement );
+
+/* Methods */
+
+/**
+ * Handle the button action being triggered.
+ *
+ * @private
+ */
+OO.ui.PopupButtonWidget.prototype.onAction = function () {
+ this.popup.toggle();
+};
+
+/**
+ * Mixin for OO.ui.Widget subclasses to provide OO.ui.mixin.GroupElement.
+ *
+ * Use together with OO.ui.mixin.ItemWidget to make disabled state inheritable.
+ *
+ * @private
+ * @abstract
+ * @class
+ * @mixins OO.ui.mixin.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.mixin.GroupWidget = function OoUiMixinGroupWidget( config ) {
+ // Mixin constructors
+ OO.ui.mixin.GroupElement.call( this, config );
+};
+
+/* Setup */
+
+OO.mixinClass( OO.ui.mixin.GroupWidget, OO.ui.mixin.GroupElement );
+
+/* Methods */
+
+/**
+ * Set the disabled state of the widget.
+ *
+ * This will also update the disabled state of child widgets.
+ *
+ * @param {boolean} disabled Disable widget
+ * @chainable
+ */
+OO.ui.mixin.GroupWidget.prototype.setDisabled = function ( disabled ) {
+ var i, len;
+
+ // Parent method
+ // Note: Calling #setDisabled this way assumes this is mixed into an OO.ui.Widget
+ OO.ui.Widget.prototype.setDisabled.call( this, disabled );
+
+ // During construction, #setDisabled is called before the OO.ui.mixin.GroupElement constructor
+ if ( this.items ) {
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ this.items[ i ].updateDisabled();
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Mixin for widgets used as items in widgets that mix in OO.ui.mixin.GroupWidget.
+ *
+ * Item widgets have a reference to a OO.ui.mixin.GroupWidget while they are attached to the group. This
+ * allows bidirectional communication.
+ *
+ * Use together with OO.ui.mixin.GroupWidget to make disabled state inheritable.
+ *
+ * @private
+ * @abstract
+ * @class
+ *
+ * @constructor
+ */
+OO.ui.mixin.ItemWidget = function OoUiMixinItemWidget() {
+ //
+};
+
+/* Methods */
+
+/**
+ * Check if widget is disabled.
+ *
+ * Checks parent if present, making disabled state inheritable.
+ *
+ * @return {boolean} Widget is disabled
+ */
+OO.ui.mixin.ItemWidget.prototype.isDisabled = function () {
+ return this.disabled ||
+ ( this.elementGroup instanceof OO.ui.Widget && this.elementGroup.isDisabled() );
+};
+
+/**
+ * Set group element is in.
+ *
+ * @param {OO.ui.mixin.GroupElement|null} group Group element, null if none
+ * @chainable
+ */
+OO.ui.mixin.ItemWidget.prototype.setElementGroup = function ( group ) {
+ // Parent method
+ // Note: Calling #setElementGroup this way assumes this is mixed into an OO.ui.Element
+ OO.ui.Element.prototype.setElementGroup.call( this, group );
+
+ // Initialize item disabled states
+ this.updateDisabled();
+
+ return this;
+};
+
+/**
+ * OptionWidgets are special elements that can be selected and configured with data. The
+ * data is often unique for each option, but it does not have to be. OptionWidgets are used
+ * with OO.ui.SelectWidget to create a selection of mutually exclusive options. For more information
+ * and examples, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.ItemWidget
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.FlaggedElement
+ * @mixins OO.ui.mixin.AccessKeyedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.OptionWidget = function OoUiOptionWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.OptionWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.ItemWidget.call( this );
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.FlaggedElement.call( this, config );
+ OO.ui.mixin.AccessKeyedElement.call( this, config );
+
+ // Properties
+ this.selected = false;
+ this.highlighted = false;
+ this.pressed = false;
+
+ // Initialization
+ this.$element
+ .data( 'oo-ui-optionWidget', this )
+ // Allow programmatic focussing (and by accesskey), but not tabbing
+ .attr( 'tabindex', '-1' )
+ .attr( 'role', 'option' )
+ .attr( 'aria-selected', 'false' )
+ .addClass( 'oo-ui-optionWidget' )
+ .append( this.$label );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.OptionWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.mixin.ItemWidget );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.mixin.FlaggedElement );
+OO.mixinClass( OO.ui.OptionWidget, OO.ui.mixin.AccessKeyedElement );
+
+/* Static Properties */
+
+/**
+ * Whether this option can be selected. See #setSelected.
+ *
+ * @static
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.OptionWidget.static.selectable = true;
+
+/**
+ * Whether this option can be highlighted. See #setHighlighted.
+ *
+ * @static
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.OptionWidget.static.highlightable = true;
+
+/**
+ * Whether this option can be pressed. See #setPressed.
+ *
+ * @static
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.OptionWidget.static.pressable = true;
+
+/**
+ * Whether this option will be scrolled into view when it is selected.
+ *
+ * @static
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.OptionWidget.static.scrollIntoViewOnSelect = false;
+
+/* Methods */
+
+/**
+ * Check if the option can be selected.
+ *
+ * @return {boolean} Item is selectable
+ */
+OO.ui.OptionWidget.prototype.isSelectable = function () {
+ return this.constructor.static.selectable && !this.isDisabled() && this.isVisible();
+};
+
+/**
+ * Check if the option can be highlighted. A highlight indicates that the option
+ * may be selected when a user presses enter or clicks. Disabled items cannot
+ * be highlighted.
+ *
+ * @return {boolean} Item is highlightable
+ */
+OO.ui.OptionWidget.prototype.isHighlightable = function () {
+ return this.constructor.static.highlightable && !this.isDisabled() && this.isVisible();
+};
+
+/**
+ * Check if the option can be pressed. The pressed state occurs when a user mouses
+ * down on an item, but has not yet let go of the mouse.
+ *
+ * @return {boolean} Item is pressable
+ */
+OO.ui.OptionWidget.prototype.isPressable = function () {
+ return this.constructor.static.pressable && !this.isDisabled() && this.isVisible();
+};
+
+/**
+ * Check if the option is selected.
+ *
+ * @return {boolean} Item is selected
+ */
+OO.ui.OptionWidget.prototype.isSelected = function () {
+ return this.selected;
+};
+
+/**
+ * Check if the option is highlighted. A highlight indicates that the
+ * item may be selected when a user presses enter or clicks.
+ *
+ * @return {boolean} Item is highlighted
+ */
+OO.ui.OptionWidget.prototype.isHighlighted = function () {
+ return this.highlighted;
+};
+
+/**
+ * Check if the option is pressed. The pressed state occurs when a user mouses
+ * down on an item, but has not yet let go of the mouse. The item may appear
+ * selected, but it will not be selected until the user releases the mouse.
+ *
+ * @return {boolean} Item is pressed
+ */
+OO.ui.OptionWidget.prototype.isPressed = function () {
+ return this.pressed;
+};
+
+/**
+ * Set the option’s selected state. In general, all modifications to the selection
+ * should be handled by the SelectWidget’s {@link OO.ui.SelectWidget#selectItem selectItem( [item] )}
+ * method instead of this method.
+ *
+ * @param {boolean} [state=false] Select option
+ * @chainable
+ */
+OO.ui.OptionWidget.prototype.setSelected = function ( state ) {
+ if ( this.constructor.static.selectable ) {
+ this.selected = !!state;
+ this.$element
+ .toggleClass( 'oo-ui-optionWidget-selected', state )
+ .attr( 'aria-selected', state.toString() );
+ if ( state && this.constructor.static.scrollIntoViewOnSelect ) {
+ this.scrollElementIntoView();
+ }
+ this.updateThemeClasses();
+ }
+ return this;
+};
+
+/**
+ * Set the option’s highlighted state. In general, all programmatic
+ * modifications to the highlight should be handled by the
+ * SelectWidget’s {@link OO.ui.SelectWidget#highlightItem highlightItem( [item] )}
+ * method instead of this method.
+ *
+ * @param {boolean} [state=false] Highlight option
+ * @chainable
+ */
+OO.ui.OptionWidget.prototype.setHighlighted = function ( state ) {
+ if ( this.constructor.static.highlightable ) {
+ this.highlighted = !!state;
+ this.$element.toggleClass( 'oo-ui-optionWidget-highlighted', state );
+ this.updateThemeClasses();
+ }
+ return this;
+};
+
+/**
+ * Set the option’s pressed state. In general, all
+ * programmatic modifications to the pressed state should be handled by the
+ * SelectWidget’s {@link OO.ui.SelectWidget#pressItem pressItem( [item] )}
+ * method instead of this method.
+ *
+ * @param {boolean} [state=false] Press option
+ * @chainable
+ */
+OO.ui.OptionWidget.prototype.setPressed = function ( state ) {
+ if ( this.constructor.static.pressable ) {
+ this.pressed = !!state;
+ this.$element.toggleClass( 'oo-ui-optionWidget-pressed', state );
+ this.updateThemeClasses();
+ }
+ return this;
+};
+
+/**
+ * Get text to match search strings against.
+ *
+ * The default implementation returns the label text, but subclasses
+ * can override this to provide more complex behavior.
+ *
+ * @return {string|boolean} String to match search string against
+ */
+OO.ui.OptionWidget.prototype.getMatchText = function () {
+ var label = this.getLabel();
+ return typeof label === 'string' ? label : this.$label.text();
+};
+
+/**
+ * A SelectWidget is of a generic selection of options. The OOjs UI library contains several types of
+ * select widgets, including {@link OO.ui.ButtonSelectWidget button selects},
+ * {@link OO.ui.RadioSelectWidget radio selects}, and {@link OO.ui.MenuSelectWidget
+ * menu selects}.
+ *
+ * This class should be used together with OO.ui.OptionWidget or OO.ui.DecoratedOptionWidget. For more
+ * information, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * @example
+ * // Example of a select widget with three options
+ * var select = new OO.ui.SelectWidget( {
+ * items: [
+ * new OO.ui.OptionWidget( {
+ * data: 'a',
+ * label: 'Option One',
+ * } ),
+ * new OO.ui.OptionWidget( {
+ * data: 'b',
+ * label: 'Option Two',
+ * } ),
+ * new OO.ui.OptionWidget( {
+ * data: 'c',
+ * label: 'Option Three',
+ * } )
+ * ]
+ * } );
+ * $( 'body' ).append( select.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.GroupWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.OptionWidget[]} [items] An array of options to add to the select.
+ * Options are created with {@link OO.ui.OptionWidget OptionWidget} classes. See
+ * the [OOjs UI documentation on MediaWiki] [2] for examples.
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
+ */
+OO.ui.SelectWidget = function OoUiSelectWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.SelectWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.GroupWidget.call( this, $.extend( {}, config, { $group: this.$element } ) );
+
+ // Properties
+ this.pressed = false;
+ this.selecting = null;
+ this.onMouseUpHandler = this.onMouseUp.bind( this );
+ this.onMouseMoveHandler = this.onMouseMove.bind( this );
+ this.onKeyDownHandler = this.onKeyDown.bind( this );
+ this.onKeyPressHandler = this.onKeyPress.bind( this );
+ this.keyPressBuffer = '';
+ this.keyPressBufferTimer = null;
+ this.blockMouseOverEvents = 0;
+
+ // Events
+ this.connect( this, {
+ toggle: 'onToggle'
+ } );
+ this.$element.on( {
+ focusin: this.onFocus.bind( this ),
+ mousedown: this.onMouseDown.bind( this ),
+ mouseover: this.onMouseOver.bind( this ),
+ mouseleave: this.onMouseLeave.bind( this )
+ } );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-selectWidget oo-ui-selectWidget-depressed' )
+ .attr( 'role', 'listbox' );
+ this.setFocusOwner( this.$element );
+ if ( Array.isArray( config.items ) ) {
+ this.addItems( config.items );
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.SelectWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.SelectWidget, OO.ui.mixin.GroupWidget );
+
+/* Events */
+
+/**
+ * @event highlight
+ *
+ * A `highlight` event is emitted when the highlight is changed with the #highlightItem method.
+ *
+ * @param {OO.ui.OptionWidget|null} item Highlighted item
+ */
+
+/**
+ * @event press
+ *
+ * A `press` event is emitted when the #pressItem method is used to programmatically modify the
+ * pressed state of an option.
+ *
+ * @param {OO.ui.OptionWidget|null} item Pressed item
+ */
+
+/**
+ * @event select
+ *
+ * A `select` event is emitted when the selection is modified programmatically with the #selectItem method.
+ *
+ * @param {OO.ui.OptionWidget|null} item Selected item
+ */
+
+/**
+ * @event choose
+ * A `choose` event is emitted when an item is chosen with the #chooseItem method.
+ * @param {OO.ui.OptionWidget} item Chosen item
+ */
+
+/**
+ * @event add
+ *
+ * An `add` event is emitted when options are added to the select with the #addItems method.
+ *
+ * @param {OO.ui.OptionWidget[]} items Added items
+ * @param {number} index Index of insertion point
+ */
+
+/**
+ * @event remove
+ *
+ * A `remove` event is emitted when options are removed from the select with the #clearItems
+ * or #removeItems methods.
+ *
+ * @param {OO.ui.OptionWidget[]} items Removed items
+ */
+
+/* Methods */
+
+/**
+ * Handle focus events
+ *
+ * @private
+ * @param {jQuery.Event} event
+ */
+OO.ui.SelectWidget.prototype.onFocus = function ( event ) {
+ var item;
+ if ( event.target === this.$element[ 0 ] ) {
+ // This widget was focussed, e.g. by the user tabbing to it.
+ // The styles for focus state depend on one of the items being selected.
+ if ( !this.getSelectedItem() ) {
+ item = this.getFirstSelectableItem();
+ }
+ } else {
+ // One of the options got focussed (and the event bubbled up here).
+ // They can't be tabbed to, but they can be activated using accesskeys.
+ item = this.findTargetItem( event );
+ }
+
+ if ( item ) {
+ if ( item.constructor.static.highlightable ) {
+ this.highlightItem( item );
+ } else {
+ this.selectItem( item );
+ }
+ }
+
+ if ( event.target !== this.$element[ 0 ] ) {
+ this.$focusOwner.focus();
+ }
+};
+
+/**
+ * Handle mouse down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.SelectWidget.prototype.onMouseDown = function ( e ) {
+ var item;
+
+ if ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {
+ this.togglePressed( true );
+ item = this.findTargetItem( e );
+ if ( item && item.isSelectable() ) {
+ this.pressItem( item );
+ this.selecting = item;
+ this.getElementDocument().addEventListener( 'mouseup', this.onMouseUpHandler, true );
+ this.getElementDocument().addEventListener( 'mousemove', this.onMouseMoveHandler, true );
+ }
+ }
+ return false;
+};
+
+/**
+ * Handle mouse up events.
+ *
+ * @private
+ * @param {MouseEvent} e Mouse up event
+ */
+OO.ui.SelectWidget.prototype.onMouseUp = function ( e ) {
+ var item;
+
+ this.togglePressed( false );
+ if ( !this.selecting ) {
+ item = this.findTargetItem( e );
+ if ( item && item.isSelectable() ) {
+ this.selecting = item;
+ }
+ }
+ if ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT && this.selecting ) {
+ this.pressItem( null );
+ this.chooseItem( this.selecting );
+ this.selecting = null;
+ }
+
+ this.getElementDocument().removeEventListener( 'mouseup', this.onMouseUpHandler, true );
+ this.getElementDocument().removeEventListener( 'mousemove', this.onMouseMoveHandler, true );
+
+ return false;
+};
+
+/**
+ * Handle mouse move events.
+ *
+ * @private
+ * @param {MouseEvent} e Mouse move event
+ */
+OO.ui.SelectWidget.prototype.onMouseMove = function ( e ) {
+ var item;
+
+ if ( !this.isDisabled() && this.pressed ) {
+ item = this.findTargetItem( e );
+ if ( item && item !== this.selecting && item.isSelectable() ) {
+ this.pressItem( item );
+ this.selecting = item;
+ }
+ }
+};
+
+/**
+ * Handle mouse over events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse over event
+ */
+OO.ui.SelectWidget.prototype.onMouseOver = function ( e ) {
+ var item;
+ if ( this.blockMouseOverEvents ) {
+ return;
+ }
+ if ( !this.isDisabled() ) {
+ item = this.findTargetItem( e );
+ this.highlightItem( item && item.isHighlightable() ? item : null );
+ }
+ return false;
+};
+
+/**
+ * Handle mouse leave events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse over event
+ */
+OO.ui.SelectWidget.prototype.onMouseLeave = function () {
+ if ( !this.isDisabled() ) {
+ this.highlightItem( null );
+ }
+ return false;
+};
+
+/**
+ * Handle key down events.
+ *
+ * @protected
+ * @param {KeyboardEvent} e Key down event
+ */
+OO.ui.SelectWidget.prototype.onKeyDown = function ( e ) {
+ var nextItem,
+ handled = false,
+ currentItem = this.getHighlightedItem() || this.getSelectedItem();
+
+ if ( !this.isDisabled() && this.isVisible() ) {
+ switch ( e.keyCode ) {
+ case OO.ui.Keys.ENTER:
+ if ( currentItem && currentItem.constructor.static.highlightable ) {
+ // Was only highlighted, now let's select it. No-op if already selected.
+ this.chooseItem( currentItem );
+ handled = true;
+ }
+ break;
+ case OO.ui.Keys.UP:
+ case OO.ui.Keys.LEFT:
+ this.clearKeyPressBuffer();
+ nextItem = this.getRelativeSelectableItem( currentItem, -1 );
+ handled = true;
+ break;
+ case OO.ui.Keys.DOWN:
+ case OO.ui.Keys.RIGHT:
+ this.clearKeyPressBuffer();
+ nextItem = this.getRelativeSelectableItem( currentItem, 1 );
+ handled = true;
+ break;
+ case OO.ui.Keys.ESCAPE:
+ case OO.ui.Keys.TAB:
+ if ( currentItem && currentItem.constructor.static.highlightable ) {
+ currentItem.setHighlighted( false );
+ }
+ this.unbindKeyDownListener();
+ this.unbindKeyPressListener();
+ // Don't prevent tabbing away / defocusing
+ handled = false;
+ break;
+ }
+
+ if ( nextItem ) {
+ if ( nextItem.constructor.static.highlightable ) {
+ this.highlightItem( nextItem );
+ } else {
+ this.chooseItem( nextItem );
+ }
+ this.scrollItemIntoView( nextItem );
+ }
+
+ if ( handled ) {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }
+};
+
+/**
+ * Bind key down listener.
+ *
+ * @protected
+ */
+OO.ui.SelectWidget.prototype.bindKeyDownListener = function () {
+ this.getElementWindow().addEventListener( 'keydown', this.onKeyDownHandler, true );
+};
+
+/**
+ * Unbind key down listener.
+ *
+ * @protected
+ */
+OO.ui.SelectWidget.prototype.unbindKeyDownListener = function () {
+ this.getElementWindow().removeEventListener( 'keydown', this.onKeyDownHandler, true );
+};
+
+/**
+ * Scroll item into view, preventing spurious mouse highlight actions from happening.
+ *
+ * @param {OO.ui.OptionWidget} item Item to scroll into view
+ */
+OO.ui.SelectWidget.prototype.scrollItemIntoView = function ( item ) {
+ var widget = this;
+ // Chromium's Blink engine will generate spurious 'mouseover' events during programmatic scrolling
+ // and around 100-150 ms after it is finished.
+ this.blockMouseOverEvents++;
+ item.scrollElementIntoView().done( function () {
+ setTimeout( function () {
+ widget.blockMouseOverEvents--;
+ }, 200 );
+ } );
+};
+
+/**
+ * Clear the key-press buffer
+ *
+ * @protected
+ */
+OO.ui.SelectWidget.prototype.clearKeyPressBuffer = function () {
+ if ( this.keyPressBufferTimer ) {
+ clearTimeout( this.keyPressBufferTimer );
+ this.keyPressBufferTimer = null;
+ }
+ this.keyPressBuffer = '';
+};
+
+/**
+ * Handle key press events.
+ *
+ * @protected
+ * @param {KeyboardEvent} e Key press event
+ */
+OO.ui.SelectWidget.prototype.onKeyPress = function ( e ) {
+ var c, filter, item;
+
+ if ( !e.charCode ) {
+ if ( e.keyCode === OO.ui.Keys.BACKSPACE && this.keyPressBuffer !== '' ) {
+ this.keyPressBuffer = this.keyPressBuffer.substr( 0, this.keyPressBuffer.length - 1 );
+ return false;
+ }
+ return;
+ }
+ if ( String.fromCodePoint ) {
+ c = String.fromCodePoint( e.charCode );
+ } else {
+ c = String.fromCharCode( e.charCode );
+ }
+
+ if ( this.keyPressBufferTimer ) {
+ clearTimeout( this.keyPressBufferTimer );
+ }
+ this.keyPressBufferTimer = setTimeout( this.clearKeyPressBuffer.bind( this ), 1500 );
+
+ item = this.getHighlightedItem() || this.getSelectedItem();
+
+ if ( this.keyPressBuffer === c ) {
+ // Common (if weird) special case: typing "xxxx" will cycle through all
+ // the items beginning with "x".
+ if ( item ) {
+ item = this.getRelativeSelectableItem( item, 1 );
+ }
+ } else {
+ this.keyPressBuffer += c;
+ }
+
+ filter = this.getItemMatcher( this.keyPressBuffer, false );
+ if ( !item || !filter( item ) ) {
+ item = this.getRelativeSelectableItem( item, 1, filter );
+ }
+ if ( item ) {
+ if ( this.isVisible() && item.constructor.static.highlightable ) {
+ this.highlightItem( item );
+ } else {
+ this.chooseItem( item );
+ }
+ this.scrollItemIntoView( item );
+ }
+
+ e.preventDefault();
+ e.stopPropagation();
+};
+
+/**
+ * Get a matcher for the specific string
+ *
+ * @protected
+ * @param {string} s String to match against items
+ * @param {boolean} [exact=false] Only accept exact matches
+ * @return {Function} function ( OO.ui.OptionWidget ) => boolean
+ */
+OO.ui.SelectWidget.prototype.getItemMatcher = function ( s, exact ) {
+ var re;
+
+ if ( s.normalize ) {
+ s = s.normalize();
+ }
+ s = exact ? s.trim() : s.replace( /^\s+/, '' );
+ re = '^\\s*' + s.replace( /([\\{}()|.?*+\-^$[\]])/g, '\\$1' ).replace( /\s+/g, '\\s+' );
+ if ( exact ) {
+ re += '\\s*$';
+ }
+ re = new RegExp( re, 'i' );
+ return function ( item ) {
+ var matchText = item.getMatchText();
+ if ( matchText.normalize ) {
+ matchText = matchText.normalize();
+ }
+ return re.test( matchText );
+ };
+};
+
+/**
+ * Bind key press listener.
+ *
+ * @protected
+ */
+OO.ui.SelectWidget.prototype.bindKeyPressListener = function () {
+ this.getElementWindow().addEventListener( 'keypress', this.onKeyPressHandler, true );
+};
+
+/**
+ * Unbind key down listener.
+ *
+ * If you override this, be sure to call this.clearKeyPressBuffer() from your
+ * implementation.
+ *
+ * @protected
+ */
+OO.ui.SelectWidget.prototype.unbindKeyPressListener = function () {
+ this.getElementWindow().removeEventListener( 'keypress', this.onKeyPressHandler, true );
+ this.clearKeyPressBuffer();
+};
+
+/**
+ * Visibility change handler
+ *
+ * @protected
+ * @param {boolean} visible
+ */
+OO.ui.SelectWidget.prototype.onToggle = function ( visible ) {
+ if ( !visible ) {
+ this.clearKeyPressBuffer();
+ }
+};
+
+/**
+ * Get the closest item to a jQuery.Event.
+ *
+ * @private
+ * @param {jQuery.Event} e
+ * @return {OO.ui.OptionWidget|null} Outline item widget, `null` if none was found
+ */
+OO.ui.SelectWidget.prototype.findTargetItem = function ( e ) {
+ var $option = $( e.target ).closest( '.oo-ui-optionWidget' );
+ if ( !$option.closest( '.oo-ui-selectWidget' ).is( this.$element ) ) {
+ return null;
+ }
+ return $option.data( 'oo-ui-optionWidget' ) || null;
+};
+
+/**
+ * Get selected item.
+ *
+ * @return {OO.ui.OptionWidget|null} Selected item, `null` if no item is selected
+ */
+OO.ui.SelectWidget.prototype.getSelectedItem = function () {
+ var i, len;
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ if ( this.items[ i ].isSelected() ) {
+ return this.items[ i ];
+ }
+ }
+ return null;
+};
+
+/**
+ * Get highlighted item.
+ *
+ * @return {OO.ui.OptionWidget|null} Highlighted item, `null` if no item is highlighted
+ */
+OO.ui.SelectWidget.prototype.getHighlightedItem = function () {
+ var i, len;
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ if ( this.items[ i ].isHighlighted() ) {
+ return this.items[ i ];
+ }
+ }
+ return null;
+};
+
+/**
+ * Toggle pressed state.
+ *
+ * Press is a state that occurs when a user mouses down on an item, but
+ * has not yet let go of the mouse. The item may appear selected, but it will not be selected
+ * until the user releases the mouse.
+ *
+ * @param {boolean} pressed An option is being pressed
+ */
+OO.ui.SelectWidget.prototype.togglePressed = function ( pressed ) {
+ if ( pressed === undefined ) {
+ pressed = !this.pressed;
+ }
+ if ( pressed !== this.pressed ) {
+ this.$element
+ .toggleClass( 'oo-ui-selectWidget-pressed', pressed )
+ .toggleClass( 'oo-ui-selectWidget-depressed', !pressed );
+ this.pressed = pressed;
+ }
+};
+
+/**
+ * Highlight an option. If the `item` param is omitted, no options will be highlighted
+ * and any existing highlight will be removed. The highlight is mutually exclusive.
+ *
+ * @param {OO.ui.OptionWidget} [item] Item to highlight, omit for no highlight
+ * @fires highlight
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.highlightItem = function ( item ) {
+ var i, len, highlighted,
+ changed = false;
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ highlighted = this.items[ i ] === item;
+ if ( this.items[ i ].isHighlighted() !== highlighted ) {
+ this.items[ i ].setHighlighted( highlighted );
+ changed = true;
+ }
+ }
+ if ( changed ) {
+ if ( item ) {
+ this.$focusOwner.attr( 'aria-activedescendant', item.getElementId() );
+ } else {
+ this.$focusOwner.removeAttr( 'aria-activedescendant' );
+ }
+ this.emit( 'highlight', item );
+ }
+
+ return this;
+};
+
+/**
+ * Fetch an item by its label.
+ *
+ * @param {string} label Label of the item to select.
+ * @param {boolean} [prefix=false] Allow a prefix match, if only a single item matches
+ * @return {OO.ui.Element|null} Item with equivalent label, `null` if none exists
+ */
+OO.ui.SelectWidget.prototype.getItemFromLabel = function ( label, prefix ) {
+ var i, item, found,
+ len = this.items.length,
+ filter = this.getItemMatcher( label, true );
+
+ for ( i = 0; i < len; i++ ) {
+ item = this.items[ i ];
+ if ( item instanceof OO.ui.OptionWidget && item.isSelectable() && filter( item ) ) {
+ return item;
+ }
+ }
+
+ if ( prefix ) {
+ found = null;
+ filter = this.getItemMatcher( label, false );
+ for ( i = 0; i < len; i++ ) {
+ item = this.items[ i ];
+ if ( item instanceof OO.ui.OptionWidget && item.isSelectable() && filter( item ) ) {
+ if ( found ) {
+ return null;
+ }
+ found = item;
+ }
+ }
+ if ( found ) {
+ return found;
+ }
+ }
+
+ return null;
+};
+
+/**
+ * Programmatically select an option by its label. If the item does not exist,
+ * all options will be deselected.
+ *
+ * @param {string} [label] Label of the item to select.
+ * @param {boolean} [prefix=false] Allow a prefix match, if only a single item matches
+ * @fires select
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.selectItemByLabel = function ( label, prefix ) {
+ var itemFromLabel = this.getItemFromLabel( label, !!prefix );
+ if ( label === undefined || !itemFromLabel ) {
+ return this.selectItem();
+ }
+ return this.selectItem( itemFromLabel );
+};
+
+/**
+ * Programmatically select an option by its data. If the `data` parameter is omitted,
+ * or if the item does not exist, all options will be deselected.
+ *
+ * @param {Object|string} [data] Value of the item to select, omit to deselect all
+ * @fires select
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.selectItemByData = function ( data ) {
+ var itemFromData = this.getItemFromData( data );
+ if ( data === undefined || !itemFromData ) {
+ return this.selectItem();
+ }
+ return this.selectItem( itemFromData );
+};
+
+/**
+ * Programmatically select an option by its reference. If the `item` parameter is omitted,
+ * all options will be deselected.
+ *
+ * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all
+ * @fires select
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.selectItem = function ( item ) {
+ var i, len, selected,
+ changed = false;
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ selected = this.items[ i ] === item;
+ if ( this.items[ i ].isSelected() !== selected ) {
+ this.items[ i ].setSelected( selected );
+ changed = true;
+ }
+ }
+ if ( changed ) {
+ if ( item && !item.constructor.static.highlightable ) {
+ if ( item ) {
+ this.$focusOwner.attr( 'aria-activedescendant', item.getElementId() );
+ } else {
+ this.$focusOwner.removeAttr( 'aria-activedescendant' );
+ }
+ }
+ this.emit( 'select', item );
+ }
+
+ return this;
+};
+
+/**
+ * Press an item.
+ *
+ * Press is a state that occurs when a user mouses down on an item, but has not
+ * yet let go of the mouse. The item may appear selected, but it will not be selected until the user
+ * releases the mouse.
+ *
+ * @param {OO.ui.OptionWidget} [item] Item to press, omit to depress all
+ * @fires press
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.pressItem = function ( item ) {
+ var i, len, pressed,
+ changed = false;
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ pressed = this.items[ i ] === item;
+ if ( this.items[ i ].isPressed() !== pressed ) {
+ this.items[ i ].setPressed( pressed );
+ changed = true;
+ }
+ }
+ if ( changed ) {
+ this.emit( 'press', item );
+ }
+
+ return this;
+};
+
+/**
+ * Choose an item.
+ *
+ * Note that ‘choose’ should never be modified programmatically. A user can choose
+ * an option with the keyboard or mouse and it becomes selected. To select an item programmatically,
+ * use the #selectItem method.
+ *
+ * This method is identical to #selectItem, but may vary in subclasses that take additional action
+ * when users choose an item with the keyboard or mouse.
+ *
+ * @param {OO.ui.OptionWidget} item Item to choose
+ * @fires choose
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.chooseItem = function ( item ) {
+ if ( item ) {
+ this.selectItem( item );
+ this.emit( 'choose', item );
+ }
+
+ return this;
+};
+
+/**
+ * Get an option by its position relative to the specified item (or to the start of the option array,
+ * if item is `null`). The direction in which to search through the option array is specified with a
+ * number: -1 for reverse (the default) or 1 for forward. The method will return an option, or
+ * `null` if there are no options in the array.
+ *
+ * @param {OO.ui.OptionWidget|null} item Item to describe the start position, or `null` to start at the beginning of the array.
+ * @param {number} direction Direction to move in: -1 to move backward, 1 to move forward
+ * @param {Function} [filter] Only consider items for which this function returns
+ * true. Function takes an OO.ui.OptionWidget and returns a boolean.
+ * @return {OO.ui.OptionWidget|null} Item at position, `null` if there are no items in the select
+ */
+OO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direction, filter ) {
+ var currentIndex, nextIndex, i,
+ increase = direction > 0 ? 1 : -1,
+ len = this.items.length;
+
+ if ( item instanceof OO.ui.OptionWidget ) {
+ currentIndex = this.items.indexOf( item );
+ nextIndex = ( currentIndex + increase + len ) % len;
+ } else {
+ // If no item is selected and moving forward, start at the beginning.
+ // If moving backward, start at the end.
+ nextIndex = direction > 0 ? 0 : len - 1;
+ }
+
+ for ( i = 0; i < len; i++ ) {
+ item = this.items[ nextIndex ];
+ if (
+ item instanceof OO.ui.OptionWidget && item.isSelectable() &&
+ ( !filter || filter( item ) )
+ ) {
+ return item;
+ }
+ nextIndex = ( nextIndex + increase + len ) % len;
+ }
+ return null;
+};
+
+/**
+ * Get the next selectable item or `null` if there are no selectable items.
+ * Disabled options and menu-section markers and breaks are not selectable.
+ *
+ * @return {OO.ui.OptionWidget|null} Item, `null` if there aren't any selectable items
+ */
+OO.ui.SelectWidget.prototype.getFirstSelectableItem = function () {
+ return this.getRelativeSelectableItem( null, 1 );
+};
+
+/**
+ * Add an array of options to the select. Optionally, an index number can be used to
+ * specify an insertion point.
+ *
+ * @param {OO.ui.OptionWidget[]} items Items to add
+ * @param {number} [index] Index to insert items after
+ * @fires add
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.addItems = function ( items, index ) {
+ // Mixin method
+ OO.ui.mixin.GroupWidget.prototype.addItems.call( this, items, index );
+
+ // Always provide an index, even if it was omitted
+ this.emit( 'add', items, index === undefined ? this.items.length - items.length - 1 : index );
+
+ return this;
+};
+
+/**
+ * Remove the specified array of options from the select. Options will be detached
+ * from the DOM, not removed, so they can be reused later. To remove all options from
+ * the select, you may wish to use the #clearItems method instead.
+ *
+ * @param {OO.ui.OptionWidget[]} items Items to remove
+ * @fires remove
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.removeItems = function ( items ) {
+ var i, len, item;
+
+ // Deselect items being removed
+ for ( i = 0, len = items.length; i < len; i++ ) {
+ item = items[ i ];
+ if ( item.isSelected() ) {
+ this.selectItem( null );
+ }
+ }
+
+ // Mixin method
+ OO.ui.mixin.GroupWidget.prototype.removeItems.call( this, items );
+
+ this.emit( 'remove', items );
+
+ return this;
+};
+
+/**
+ * Clear all options from the select. Options will be detached from the DOM, not removed,
+ * so that they can be reused later. To remove a subset of options from the select, use
+ * the #removeItems method.
+ *
+ * @fires remove
+ * @chainable
+ */
+OO.ui.SelectWidget.prototype.clearItems = function () {
+ var items = this.items.slice();
+
+ // Mixin method
+ OO.ui.mixin.GroupWidget.prototype.clearItems.call( this );
+
+ // Clear selection
+ this.selectItem( null );
+
+ this.emit( 'remove', items );
+
+ return this;
+};
+
+/**
+ * Set the DOM element which has focus while the user is interacting with this SelectWidget.
+ *
+ * Currently this is just used to set `aria-activedescendant` on it.
+ *
+ * @protected
+ * @param {jQuery} $focusOwner
+ */
+OO.ui.SelectWidget.prototype.setFocusOwner = function ( $focusOwner ) {
+ this.$focusOwner = $focusOwner;
+};
+
+/**
+ * DecoratedOptionWidgets are {@link OO.ui.OptionWidget options} that can be configured
+ * with an {@link OO.ui.mixin.IconElement icon} and/or {@link OO.ui.mixin.IndicatorElement indicator}.
+ * This class is used with OO.ui.SelectWidget to create a selection of mutually exclusive
+ * options. For more information about options and selects, please see the
+ * [OOjs UI documentation on MediaWiki][1].
+ *
+ * @example
+ * // Decorated options in a select widget
+ * var select = new OO.ui.SelectWidget( {
+ * items: [
+ * new OO.ui.DecoratedOptionWidget( {
+ * data: 'a',
+ * label: 'Option with icon',
+ * icon: 'help'
+ * } ),
+ * new OO.ui.DecoratedOptionWidget( {
+ * data: 'b',
+ * label: 'Option with indicator',
+ * indicator: 'next'
+ * } )
+ * ]
+ * } );
+ * $( 'body' ).append( select.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.DecoratedOptionWidget = function OoUiDecoratedOptionWidget( config ) {
+ // Parent constructor
+ OO.ui.DecoratedOptionWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.IndicatorElement.call( this, config );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-decoratedOptionWidget' )
+ .prepend( this.$icon )
+ .append( this.$indicator );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.DecoratedOptionWidget, OO.ui.OptionWidget );
+OO.mixinClass( OO.ui.DecoratedOptionWidget, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.DecoratedOptionWidget, OO.ui.mixin.IndicatorElement );
+
+/**
+ * MenuOptionWidget is an option widget that looks like a menu item. The class is used with
+ * OO.ui.MenuSelectWidget to create a menu of mutually exclusive options. Please see
+ * the [OOjs UI documentation on MediaWiki] [1] for more information.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options
+ *
+ * @class
+ * @extends OO.ui.DecoratedOptionWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.MenuOptionWidget = function OoUiMenuOptionWidget( config ) {
+ // Parent constructor
+ OO.ui.MenuOptionWidget.parent.call( this, config );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-menuOptionWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MenuOptionWidget, OO.ui.DecoratedOptionWidget );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.MenuOptionWidget.static.scrollIntoViewOnSelect = true;
+
+/**
+ * MenuSectionOptionWidgets are used inside {@link OO.ui.MenuSelectWidget menu select widgets} to group one or more related
+ * {@link OO.ui.MenuOptionWidget menu options}. MenuSectionOptionWidgets cannot be highlighted or selected.
+ *
+ * @example
+ * var myDropdown = new OO.ui.DropdownWidget( {
+ * menu: {
+ * items: [
+ * new OO.ui.MenuSectionOptionWidget( {
+ * label: 'Dogs'
+ * } ),
+ * new OO.ui.MenuOptionWidget( {
+ * data: 'corgi',
+ * label: 'Welsh Corgi'
+ * } ),
+ * new OO.ui.MenuOptionWidget( {
+ * data: 'poodle',
+ * label: 'Standard Poodle'
+ * } ),
+ * new OO.ui.MenuSectionOptionWidget( {
+ * label: 'Cats'
+ * } ),
+ * new OO.ui.MenuOptionWidget( {
+ * data: 'lion',
+ * label: 'Lion'
+ * } )
+ * ]
+ * }
+ * } );
+ * $( 'body' ).append( myDropdown.$element );
+ *
+ * @class
+ * @extends OO.ui.DecoratedOptionWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.MenuSectionOptionWidget = function OoUiMenuSectionOptionWidget( config ) {
+ // Parent constructor
+ OO.ui.MenuSectionOptionWidget.parent.call( this, config );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-menuSectionOptionWidget' )
+ .removeAttr( 'role aria-selected' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MenuSectionOptionWidget, OO.ui.DecoratedOptionWidget );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.MenuSectionOptionWidget.static.selectable = false;
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.MenuSectionOptionWidget.static.highlightable = false;
+
+/**
+ * MenuSelectWidget is a {@link OO.ui.SelectWidget select widget} that contains options and
+ * is used together with OO.ui.MenuOptionWidget. It is designed be used as part of another widget.
+ * See {@link OO.ui.DropdownWidget DropdownWidget}, {@link OO.ui.ComboBoxInputWidget ComboBoxInputWidget},
+ * and {@link OO.ui.mixin.LookupElement LookupElement} for examples of widgets that contain menus.
+ * MenuSelectWidgets themselves are not instantiated directly, rather subclassed
+ * and customized to be opened, closed, and displayed as needed.
+ *
+ * By default, menus are clipped to the visible viewport and are not visible when a user presses the
+ * mouse outside the menu.
+ *
+ * Menus also have support for keyboard interaction:
+ *
+ * - Enter/Return key: choose and select a menu option
+ * - Up-arrow key: highlight the previous menu option
+ * - Down-arrow key: highlight the next menu option
+ * - Esc key: hide the menu
+ *
+ * Unlike most widgets, MenuSelectWidget is initially hidden and must be shown by calling #toggle.
+ *
+ * Please see the [OOjs UI documentation on MediaWiki][1] for more information.
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ * @mixins OO.ui.mixin.ClippableElement
+ * @mixins OO.ui.mixin.FloatableElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.TextInputWidget} [input] Text input used to implement option highlighting for menu items that match
+ * the text the user types. This config is used by {@link OO.ui.ComboBoxInputWidget ComboBoxInputWidget}
+ * and {@link OO.ui.mixin.LookupElement LookupElement}
+ * @cfg {jQuery} [$input] Text input used to implement option highlighting for menu items that match
+ * the text the user types. This config is used by {@link OO.ui.CapsuleMultiselectWidget CapsuleMultiselectWidget}
+ * @cfg {OO.ui.Widget} [widget] Widget associated with the menu's active state. If the user clicks the mouse
+ * anywhere on the page outside of this widget, the menu is hidden. For example, if there is a button
+ * that toggles the menu's visibility on click, the menu will be hidden then re-shown when the user clicks
+ * that button, unless the button (or its parent widget) is passed in here.
+ * @cfg {boolean} [autoHide=true] Hide the menu when the mouse is pressed outside the menu.
+ * @cfg {jQuery} [$autoCloseIgnore] If these elements are clicked, don't auto-hide the menu.
+ * @cfg {boolean} [hideOnChoose=true] Hide the menu when the user chooses an option.
+ * @cfg {boolean} [filterFromInput=false] Filter the displayed options from the input
+ * @cfg {boolean} [highlightOnFilter] Highlight the first result when filtering
+ * @cfg {number} [width] Width of the menu
+ */
+OO.ui.MenuSelectWidget = function OoUiMenuSelectWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.MenuSelectWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.ClippableElement.call( this, $.extend( {}, config, { $clippable: this.$group } ) );
+ OO.ui.mixin.FloatableElement.call( this, config );
+
+ // Properties
+ this.autoHide = config.autoHide === undefined || !!config.autoHide;
+ this.hideOnChoose = config.hideOnChoose === undefined || !!config.hideOnChoose;
+ this.filterFromInput = !!config.filterFromInput;
+ this.$input = config.$input ? config.$input : config.input ? config.input.$input : null;
+ this.$widget = config.widget ? config.widget.$element : null;
+ this.$autoCloseIgnore = config.$autoCloseIgnore || $( [] );
+ this.onDocumentMouseDownHandler = this.onDocumentMouseDown.bind( this );
+ this.onInputEditHandler = OO.ui.debounce( this.updateItemVisibility.bind( this ), 100 );
+ this.highlightOnFilter = !!config.highlightOnFilter;
+ this.width = config.width;
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-menuSelectWidget' );
+ if ( config.widget ) {
+ this.setFocusOwner( config.widget.$tabIndexed );
+ }
+
+ // Initially hidden - using #toggle may cause errors if subclasses override toggle with methods
+ // that reference properties not initialized at that time of parent class construction
+ // TODO: Find a better way to handle post-constructor setup
+ this.visible = false;
+ this.$element.addClass( 'oo-ui-element-hidden' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MenuSelectWidget, OO.ui.SelectWidget );
+OO.mixinClass( OO.ui.MenuSelectWidget, OO.ui.mixin.ClippableElement );
+OO.mixinClass( OO.ui.MenuSelectWidget, OO.ui.mixin.FloatableElement );
+
+/* Events */
+
+/**
+ * @event ready
+ *
+ * The menu is ready: it is visible and has been positioned and clipped.
+ */
+
+/* Methods */
+
+/**
+ * Handles document mouse down events.
+ *
+ * @protected
+ * @param {MouseEvent} e Mouse down event
+ */
+OO.ui.MenuSelectWidget.prototype.onDocumentMouseDown = function ( e ) {
+ if (
+ this.isVisible() &&
+ !OO.ui.contains(
+ this.$element.add( this.$widget ).add( this.$autoCloseIgnore ).get(),
+ e.target,
+ true
+ )
+ ) {
+ this.toggle( false );
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MenuSelectWidget.prototype.onKeyDown = function ( e ) {
+ var currentItem = this.getHighlightedItem() || this.getSelectedItem();
+
+ if ( !this.isDisabled() && this.isVisible() ) {
+ switch ( e.keyCode ) {
+ case OO.ui.Keys.LEFT:
+ case OO.ui.Keys.RIGHT:
+ // Do nothing if a text field is associated, arrow keys will be handled natively
+ if ( !this.$input ) {
+ OO.ui.MenuSelectWidget.parent.prototype.onKeyDown.call( this, e );
+ }
+ break;
+ case OO.ui.Keys.ESCAPE:
+ case OO.ui.Keys.TAB:
+ if ( currentItem ) {
+ currentItem.setHighlighted( false );
+ }
+ this.toggle( false );
+ // Don't prevent tabbing away, prevent defocusing
+ if ( e.keyCode === OO.ui.Keys.ESCAPE ) {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ break;
+ default:
+ OO.ui.MenuSelectWidget.parent.prototype.onKeyDown.call( this, e );
+ return;
+ }
+ }
+};
+
+/**
+ * Update menu item visibility and clipping after input changes (if filterFromInput is enabled)
+ * or after items were added/removed (always).
+ *
+ * @protected
+ */
+OO.ui.MenuSelectWidget.prototype.updateItemVisibility = function () {
+ var i, item, visible, section, sectionEmpty, filter, exactFilter,
+ firstItemFound = false,
+ anyVisible = false,
+ len = this.items.length,
+ showAll = !this.isVisible(),
+ exactMatch = false;
+
+ if ( this.$input && this.filterFromInput ) {
+ filter = showAll ? null : this.getItemMatcher( this.$input.val() );
+ exactFilter = this.getItemMatcher( this.$input.val(), true );
+
+ // Hide non-matching options, and also hide section headers if all options
+ // in their section are hidden.
+ for ( i = 0; i < len; i++ ) {
+ item = this.items[ i ];
+ if ( item instanceof OO.ui.MenuSectionOptionWidget ) {
+ if ( section ) {
+ // If the previous section was empty, hide its header
+ section.toggle( showAll || !sectionEmpty );
+ }
+ section = item;
+ sectionEmpty = true;
+ } else if ( item instanceof OO.ui.OptionWidget ) {
+ visible = showAll || filter( item );
+ exactMatch = exactMatch || exactFilter( item );
+ anyVisible = anyVisible || visible;
+ sectionEmpty = sectionEmpty && !visible;
+ item.toggle( visible );
+ if ( this.highlightOnFilter && visible && !firstItemFound ) {
+ // Highlight the first item in the list
+ this.highlightItem( item );
+ firstItemFound = true;
+ }
+ }
+ }
+ // Process the final section
+ if ( section ) {
+ section.toggle( showAll || !sectionEmpty );
+ }
+
+ if ( anyVisible && this.items.length && !exactMatch ) {
+ this.scrollItemIntoView( this.items[ 0 ] );
+ }
+
+ this.$element.toggleClass( 'oo-ui-menuSelectWidget-invisible', !anyVisible );
+ }
+
+ // Reevaluate clipping
+ this.clip();
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MenuSelectWidget.prototype.bindKeyDownListener = function () {
+ if ( this.$input ) {
+ this.$input.on( 'keydown', this.onKeyDownHandler );
+ } else {
+ OO.ui.MenuSelectWidget.parent.prototype.bindKeyDownListener.call( this );
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MenuSelectWidget.prototype.unbindKeyDownListener = function () {
+ if ( this.$input ) {
+ this.$input.off( 'keydown', this.onKeyDownHandler );
+ } else {
+ OO.ui.MenuSelectWidget.parent.prototype.unbindKeyDownListener.call( this );
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MenuSelectWidget.prototype.bindKeyPressListener = function () {
+ if ( this.$input ) {
+ if ( this.filterFromInput ) {
+ this.$input.on( 'keydown mouseup cut paste change input select', this.onInputEditHandler );
+ this.updateItemVisibility();
+ }
+ } else {
+ OO.ui.MenuSelectWidget.parent.prototype.bindKeyPressListener.call( this );
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MenuSelectWidget.prototype.unbindKeyPressListener = function () {
+ if ( this.$input ) {
+ if ( this.filterFromInput ) {
+ this.$input.off( 'keydown mouseup cut paste change input select', this.onInputEditHandler );
+ this.updateItemVisibility();
+ }
+ } else {
+ OO.ui.MenuSelectWidget.parent.prototype.unbindKeyPressListener.call( this );
+ }
+};
+
+/**
+ * Choose an item.
+ *
+ * When a user chooses an item, the menu is closed, unless the hideOnChoose config option is set to false.
+ *
+ * Note that ‘choose’ should never be modified programmatically. A user can choose an option with the keyboard
+ * or mouse and it becomes selected. To select an item programmatically, use the #selectItem method.
+ *
+ * @param {OO.ui.OptionWidget} item Item to choose
+ * @chainable
+ */
+OO.ui.MenuSelectWidget.prototype.chooseItem = function ( item ) {
+ OO.ui.MenuSelectWidget.parent.prototype.chooseItem.call( this, item );
+ if ( this.hideOnChoose ) {
+ this.toggle( false );
+ }
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MenuSelectWidget.prototype.addItems = function ( items, index ) {
+ // Parent method
+ OO.ui.MenuSelectWidget.parent.prototype.addItems.call( this, items, index );
+
+ this.updateItemVisibility();
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MenuSelectWidget.prototype.removeItems = function ( items ) {
+ // Parent method
+ OO.ui.MenuSelectWidget.parent.prototype.removeItems.call( this, items );
+
+ this.updateItemVisibility();
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MenuSelectWidget.prototype.clearItems = function () {
+ // Parent method
+ OO.ui.MenuSelectWidget.parent.prototype.clearItems.call( this );
+
+ this.updateItemVisibility();
+
+ return this;
+};
+
+/**
+ * Toggle visibility of the menu. The menu is initially hidden and must be shown by calling
+ * `.toggle( true )` after its #$element is attached to the DOM.
+ *
+ * Do not show the menu while it is not attached to the DOM. The calculations required to display
+ * it in the right place and with the right dimensions only work correctly while it is attached.
+ * Side-effects may include broken interface and exceptions being thrown. This wasn't always
+ * strictly enforced, so currently it only generates a warning in the browser console.
+ *
+ * @fires ready
+ * @inheritdoc
+ */
+OO.ui.MenuSelectWidget.prototype.toggle = function ( visible ) {
+ var change;
+
+ visible = ( visible === undefined ? !this.visible : !!visible ) && !!this.items.length;
+ change = visible !== this.isVisible();
+
+ if ( visible && !this.warnedUnattached && !this.isElementAttached() ) {
+ OO.ui.warnDeprecation( 'MenuSelectWidget#toggle: Before calling this method, the menu must be attached to the DOM.' );
+ this.warnedUnattached = true;
+ }
+
+ if ( change && visible && ( this.width || this.$floatableContainer ) ) {
+ this.setIdealSize( this.width || this.$floatableContainer.width() );
+ }
+
+ // Parent method
+ OO.ui.MenuSelectWidget.parent.prototype.toggle.call( this, visible );
+
+ if ( change ) {
+ if ( visible ) {
+ this.bindKeyDownListener();
+ this.bindKeyPressListener();
+
+ this.togglePositioning( !!this.$floatableContainer );
+ this.toggleClipping( true );
+
+ this.$focusOwner.attr( 'aria-expanded', 'true' );
+
+ if ( this.getSelectedItem() ) {
+ this.$focusOwner.attr( 'aria-activedescendant', this.getSelectedItem().getElementId() );
+ this.getSelectedItem().scrollElementIntoView( { duration: 0 } );
+ }
+
+ // Auto-hide
+ if ( this.autoHide ) {
+ this.getElementDocument().addEventListener( 'mousedown', this.onDocumentMouseDownHandler, true );
+ }
+
+ this.emit( 'ready' );
+ } else {
+ this.$focusOwner.removeAttr( 'aria-activedescendant' );
+ this.unbindKeyDownListener();
+ this.unbindKeyPressListener();
+ this.$focusOwner.attr( 'aria-expanded', 'false' );
+ this.getElementDocument().removeEventListener( 'mousedown', this.onDocumentMouseDownHandler, true );
+ this.togglePositioning( false );
+ this.toggleClipping( false );
+ }
+ }
+
+ return this;
+};
+
+/**
+ * DropdownWidgets are not menus themselves, rather they contain a menu of options created with
+ * OO.ui.MenuOptionWidget. The DropdownWidget takes care of opening and displaying the menu so that
+ * users can interact with it.
+ *
+ * If you want to use this within an HTML form, such as a OO.ui.FormLayout, use
+ * OO.ui.DropdownInputWidget instead.
+ *
+ * @example
+ * // Example: A DropdownWidget with a menu that contains three options
+ * var dropDown = new OO.ui.DropdownWidget( {
+ * label: 'Dropdown menu: Select a menu option',
+ * menu: {
+ * items: [
+ * new OO.ui.MenuOptionWidget( {
+ * data: 'a',
+ * label: 'First'
+ * } ),
+ * new OO.ui.MenuOptionWidget( {
+ * data: 'b',
+ * label: 'Second'
+ * } ),
+ * new OO.ui.MenuOptionWidget( {
+ * data: 'c',
+ * label: 'Third'
+ * } )
+ * ]
+ * }
+ * } );
+ *
+ * $( 'body' ).append( dropDown.$element );
+ *
+ * dropDown.getMenu().selectItemByData( 'b' );
+ *
+ * dropDown.getMenu().getSelectedItem().getData(); // returns 'b'
+ *
+ * For more information, please see the [OOjs UI documentation on MediaWiki] [1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.TitledElement
+ * @mixins OO.ui.mixin.TabIndexedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} [menu] Configuration options to pass to {@link OO.ui.MenuSelectWidget menu select widget}
+ * @cfg {jQuery} [$overlay] Render the menu into a separate layer. This configuration is useful in cases where
+ * the expanded menu is larger than its containing `<div>`. The specified overlay layer is usually on top of the
+ * containing `<div>` and has a larger area. By default, the menu uses relative positioning.
+ * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.
+ */
+OO.ui.DropdownWidget = function OoUiDropdownWidget( config ) {
+ // Configuration initialization
+ config = $.extend( { indicator: 'down' }, config );
+
+ // Parent constructor
+ OO.ui.DropdownWidget.parent.call( this, config );
+
+ // Properties (must be set before TabIndexedElement constructor call)
+ this.$handle = this.$( '<span>' );
+ this.$overlay = config.$overlay || this.$element;
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.IndicatorElement.call( this, config );
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$label } ) );
+ OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$handle } ) );
+
+ // Properties
+ this.menu = new OO.ui.MenuSelectWidget( $.extend( {
+ widget: this,
+ $floatableContainer: this.$element
+ }, config.menu ) );
+
+ // Events
+ this.$handle.on( {
+ click: this.onClick.bind( this ),
+ keydown: this.onKeyDown.bind( this ),
+ // Hack? Handle type-to-search when menu is not expanded and not handling its own events
+ keypress: this.menu.onKeyPressHandler,
+ blur: this.menu.clearKeyPressBuffer.bind( this.menu )
+ } );
+ this.menu.connect( this, {
+ select: 'onMenuSelect',
+ toggle: 'onMenuToggle'
+ } );
+
+ // Initialization
+ this.$handle
+ .addClass( 'oo-ui-dropdownWidget-handle' )
+ .attr( {
+ role: 'combobox',
+ 'aria-owns': this.menu.getElementId(),
+ 'aria-autocomplete': 'list'
+ } )
+ .append( this.$icon, this.$label, this.$indicator );
+ this.$element
+ .addClass( 'oo-ui-dropdownWidget' )
+ .append( this.$handle );
+ this.$overlay.append( this.menu.$element );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.DropdownWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.DropdownWidget, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.DropdownWidget, OO.ui.mixin.IndicatorElement );
+OO.mixinClass( OO.ui.DropdownWidget, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.DropdownWidget, OO.ui.mixin.TitledElement );
+OO.mixinClass( OO.ui.DropdownWidget, OO.ui.mixin.TabIndexedElement );
+
+/* Methods */
+
+/**
+ * Get the menu.
+ *
+ * @return {OO.ui.MenuSelectWidget} Menu of widget
+ */
+OO.ui.DropdownWidget.prototype.getMenu = function () {
+ return this.menu;
+};
+
+/**
+ * Handles menu select events.
+ *
+ * @private
+ * @param {OO.ui.MenuOptionWidget} item Selected menu item
+ */
+OO.ui.DropdownWidget.prototype.onMenuSelect = function ( item ) {
+ var selectedLabel;
+
+ if ( !item ) {
+ this.setLabel( null );
+ return;
+ }
+
+ selectedLabel = item.getLabel();
+
+ // If the label is a DOM element, clone it, because setLabel will append() it
+ if ( selectedLabel instanceof jQuery ) {
+ selectedLabel = selectedLabel.clone();
+ }
+
+ this.setLabel( selectedLabel );
+};
+
+/**
+ * Handle menu toggle events.
+ *
+ * @private
+ * @param {boolean} isVisible Menu toggle event
+ */
+OO.ui.DropdownWidget.prototype.onMenuToggle = function ( isVisible ) {
+ this.$element.toggleClass( 'oo-ui-dropdownWidget-open', isVisible );
+ this.$handle.attr(
+ 'aria-expanded',
+ this.$element.hasClass( 'oo-ui-dropdownWidget-open' ).toString()
+ );
+};
+
+/**
+ * Handle mouse click events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse click event
+ */
+OO.ui.DropdownWidget.prototype.onClick = function ( e ) {
+ if ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {
+ this.menu.toggle();
+ }
+ return false;
+};
+
+/**
+ * Handle key down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.DropdownWidget.prototype.onKeyDown = function ( e ) {
+ if (
+ !this.isDisabled() &&
+ (
+ e.which === OO.ui.Keys.ENTER ||
+ (
+ !this.menu.isVisible() &&
+ (
+ e.which === OO.ui.Keys.SPACE ||
+ e.which === OO.ui.Keys.UP ||
+ e.which === OO.ui.Keys.DOWN
+ )
+ )
+ )
+ ) {
+ this.menu.toggle();
+ return false;
+ }
+};
+
+/**
+ * RadioOptionWidget is an option widget that looks like a radio button.
+ * The class is used with OO.ui.RadioSelectWidget to create a selection of radio options.
+ * Please see the [OOjs UI documentation on MediaWiki] [1] for more information.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Button_selects_and_option
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.RadioOptionWidget = function OoUiRadioOptionWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties (must be done before parent constructor which calls #setDisabled)
+ this.radio = new OO.ui.RadioInputWidget( { value: config.data, tabIndex: -1 } );
+
+ // Parent constructor
+ OO.ui.RadioOptionWidget.parent.call( this, config );
+
+ // Initialization
+ // Remove implicit role, we're handling it ourselves
+ this.radio.$input.attr( 'role', 'presentation' );
+ this.$element
+ .addClass( 'oo-ui-radioOptionWidget' )
+ .attr( 'role', 'radio' )
+ .attr( 'aria-checked', 'false' )
+ .removeAttr( 'aria-selected' )
+ .prepend( this.radio.$element );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.RadioOptionWidget, OO.ui.OptionWidget );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.RadioOptionWidget.static.highlightable = false;
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.RadioOptionWidget.static.scrollIntoViewOnSelect = true;
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.RadioOptionWidget.static.pressable = false;
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.RadioOptionWidget.static.tagName = 'label';
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioOptionWidget.prototype.setSelected = function ( state ) {
+ OO.ui.RadioOptionWidget.parent.prototype.setSelected.call( this, state );
+
+ this.radio.setSelected( state );
+ this.$element
+ .attr( 'aria-checked', state.toString() )
+ .removeAttr( 'aria-selected' );
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioOptionWidget.prototype.setDisabled = function ( disabled ) {
+ OO.ui.RadioOptionWidget.parent.prototype.setDisabled.call( this, disabled );
+
+ this.radio.setDisabled( this.isDisabled() );
+
+ return this;
+};
+
+/**
+ * RadioSelectWidget is a {@link OO.ui.SelectWidget select widget} that contains radio
+ * options and is used together with OO.ui.RadioOptionWidget. The RadioSelectWidget provides
+ * an interface for adding, removing and selecting options.
+ * Please see the [OOjs UI documentation on MediaWiki][1] for more information.
+ *
+ * If you want to use this within an HTML form, such as a OO.ui.FormLayout, use
+ * OO.ui.RadioSelectInputWidget instead.
+ *
+ * @example
+ * // A RadioSelectWidget with RadioOptions.
+ * var option1 = new OO.ui.RadioOptionWidget( {
+ * data: 'a',
+ * label: 'Selected radio option'
+ * } );
+ *
+ * var option2 = new OO.ui.RadioOptionWidget( {
+ * data: 'b',
+ * label: 'Unselected radio option'
+ * } );
+ *
+ * var radioSelect=new OO.ui.RadioSelectWidget( {
+ * items: [ option1, option2 ]
+ * } );
+ *
+ * // Select 'option 1' using the RadioSelectWidget's selectItem() method.
+ * radioSelect.selectItem( option1 );
+ *
+ * $( 'body' ).append( radioSelect.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
+
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ * @mixins OO.ui.mixin.TabIndexedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.RadioSelectWidget = function OoUiRadioSelectWidget( config ) {
+ // Parent constructor
+ OO.ui.RadioSelectWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.TabIndexedElement.call( this, config );
+
+ // Events
+ this.$element.on( {
+ focus: this.bindKeyDownListener.bind( this ),
+ blur: this.unbindKeyDownListener.bind( this )
+ } );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-radioSelectWidget' )
+ .attr( 'role', 'radiogroup' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.RadioSelectWidget, OO.ui.SelectWidget );
+OO.mixinClass( OO.ui.RadioSelectWidget, OO.ui.mixin.TabIndexedElement );
+
+/**
+ * MultioptionWidgets are special elements that can be selected and configured with data. The
+ * data is often unique for each option, but it does not have to be. MultioptionWidgets are used
+ * with OO.ui.SelectWidget to create a selection of mutually exclusive options. For more information
+ * and examples, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Multioptions
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.ItemWidget
+ * @mixins OO.ui.mixin.LabelElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [selected=false] Whether the option is initially selected
+ */
+OO.ui.MultioptionWidget = function OoUiMultioptionWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.MultioptionWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.ItemWidget.call( this );
+ OO.ui.mixin.LabelElement.call( this, config );
+
+ // Properties
+ this.selected = null;
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-multioptionWidget' )
+ .append( this.$label );
+ this.setSelected( config.selected );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MultioptionWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.MultioptionWidget, OO.ui.mixin.ItemWidget );
+OO.mixinClass( OO.ui.MultioptionWidget, OO.ui.mixin.LabelElement );
+
+/* Events */
+
+/**
+ * @event change
+ *
+ * A change event is emitted when the selected state of the option changes.
+ *
+ * @param {boolean} selected Whether the option is now selected
+ */
+
+/* Methods */
+
+/**
+ * Check if the option is selected.
+ *
+ * @return {boolean} Item is selected
+ */
+OO.ui.MultioptionWidget.prototype.isSelected = function () {
+ return this.selected;
+};
+
+/**
+ * Set the option’s selected state. In general, all modifications to the selection
+ * should be handled by the SelectWidget’s {@link OO.ui.SelectWidget#selectItem selectItem( [item] )}
+ * method instead of this method.
+ *
+ * @param {boolean} [state=false] Select option
+ * @chainable
+ */
+OO.ui.MultioptionWidget.prototype.setSelected = function ( state ) {
+ state = !!state;
+ if ( this.selected !== state ) {
+ this.selected = state;
+ this.emit( 'change', state );
+ this.$element.toggleClass( 'oo-ui-multioptionWidget-selected', state );
+ }
+ return this;
+};
+
+/**
+ * MultiselectWidget allows selecting multiple options from a list.
+ *
+ * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options
+ *
+ * @class
+ * @abstract
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.GroupWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.MultioptionWidget[]} [items] An array of options to add to the multiselect.
+ */
+OO.ui.MultiselectWidget = function OoUiMultiselectWidget( config ) {
+ // Parent constructor
+ OO.ui.MultiselectWidget.parent.call( this, config );
+
+ // Configuration initialization
+ config = config || {};
+
+ // Mixin constructors
+ OO.ui.mixin.GroupWidget.call( this, config );
+
+ // Events
+ this.aggregate( { change: 'select' } );
+ // This is mostly for compatibility with CapsuleMultiselectWidget... normally, 'change' is emitted
+ // by GroupElement only when items are added/removed
+ this.connect( this, { select: [ 'emit', 'change' ] } );
+
+ // Initialization
+ if ( config.items ) {
+ this.addItems( config.items );
+ }
+ this.$group.addClass( 'oo-ui-multiselectWidget-group' );
+ this.$element.addClass( 'oo-ui-multiselectWidget' )
+ .append( this.$group );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MultiselectWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.MultiselectWidget, OO.ui.mixin.GroupWidget );
+
+/* Events */
+
+/**
+ * @event change
+ *
+ * A change event is emitted when the set of items changes, or an item is selected or deselected.
+ */
+
+/**
+ * @event select
+ *
+ * A select event is emitted when an item is selected or deselected.
+ */
+
+/* Methods */
+
+/**
+ * Get options that are selected.
+ *
+ * @return {OO.ui.MultioptionWidget[]} Selected options
+ */
+OO.ui.MultiselectWidget.prototype.getSelectedItems = function () {
+ return this.items.filter( function ( item ) {
+ return item.isSelected();
+ } );
+};
+
+/**
+ * Get the data of options that are selected.
+ *
+ * @return {Object[]|string[]} Values of selected options
+ */
+OO.ui.MultiselectWidget.prototype.getSelectedItemsData = function () {
+ return this.getSelectedItems().map( function ( item ) {
+ return item.data;
+ } );
+};
+
+/**
+ * Select options by reference. Options not mentioned in the `items` array will be deselected.
+ *
+ * @param {OO.ui.MultioptionWidget[]} items Items to select
+ * @chainable
+ */
+OO.ui.MultiselectWidget.prototype.selectItems = function ( items ) {
+ this.items.forEach( function ( item ) {
+ var selected = items.indexOf( item ) !== -1;
+ item.setSelected( selected );
+ } );
+ return this;
+};
+
+/**
+ * Select items by their data. Options not mentioned in the `datas` array will be deselected.
+ *
+ * @param {Object[]|string[]} datas Values of items to select
+ * @chainable
+ */
+OO.ui.MultiselectWidget.prototype.selectItemsByData = function ( datas ) {
+ var items,
+ widget = this;
+ items = datas.map( function ( data ) {
+ return widget.getItemFromData( data );
+ } );
+ this.selectItems( items );
+ return this;
+};
+
+/**
+ * CheckboxMultioptionWidget is an option widget that looks like a checkbox.
+ * The class is used with OO.ui.CheckboxMultiselectWidget to create a selection of checkbox options.
+ * Please see the [OOjs UI documentation on MediaWiki] [1] for more information.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Button_selects_and_option
+ *
+ * @class
+ * @extends OO.ui.MultioptionWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.CheckboxMultioptionWidget = function OoUiCheckboxMultioptionWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties (must be done before parent constructor which calls #setDisabled)
+ this.checkbox = new OO.ui.CheckboxInputWidget();
+
+ // Parent constructor
+ OO.ui.CheckboxMultioptionWidget.parent.call( this, config );
+
+ // Events
+ this.checkbox.on( 'change', this.onCheckboxChange.bind( this ) );
+ this.$element.on( 'keydown', this.onKeyDown.bind( this ) );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-checkboxMultioptionWidget' )
+ .prepend( this.checkbox.$element );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.CheckboxMultioptionWidget, OO.ui.MultioptionWidget );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.CheckboxMultioptionWidget.static.tagName = 'label';
+
+/* Methods */
+
+/**
+ * Handle checkbox selected state change.
+ *
+ * @private
+ */
+OO.ui.CheckboxMultioptionWidget.prototype.onCheckboxChange = function () {
+ this.setSelected( this.checkbox.isSelected() );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxMultioptionWidget.prototype.setSelected = function ( state ) {
+ OO.ui.CheckboxMultioptionWidget.parent.prototype.setSelected.call( this, state );
+ this.checkbox.setSelected( state );
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxMultioptionWidget.prototype.setDisabled = function ( disabled ) {
+ OO.ui.CheckboxMultioptionWidget.parent.prototype.setDisabled.call( this, disabled );
+ this.checkbox.setDisabled( this.isDisabled() );
+ return this;
+};
+
+/**
+ * Focus the widget.
+ */
+OO.ui.CheckboxMultioptionWidget.prototype.focus = function () {
+ this.checkbox.focus();
+};
+
+/**
+ * Handle key down events.
+ *
+ * @protected
+ * @param {jQuery.Event} e
+ */
+OO.ui.CheckboxMultioptionWidget.prototype.onKeyDown = function ( e ) {
+ var
+ element = this.getElementGroup(),
+ nextItem;
+
+ if ( e.keyCode === OO.ui.Keys.LEFT || e.keyCode === OO.ui.Keys.UP ) {
+ nextItem = element.getRelativeFocusableItem( this, -1 );
+ } else if ( e.keyCode === OO.ui.Keys.RIGHT || e.keyCode === OO.ui.Keys.DOWN ) {
+ nextItem = element.getRelativeFocusableItem( this, 1 );
+ }
+
+ if ( nextItem ) {
+ e.preventDefault();
+ nextItem.focus();
+ }
+};
+
+/**
+ * CheckboxMultiselectWidget is a {@link OO.ui.MultiselectWidget multiselect widget} that contains
+ * checkboxes and is used together with OO.ui.CheckboxMultioptionWidget. The
+ * CheckboxMultiselectWidget provides an interface for adding, removing and selecting options.
+ * Please see the [OOjs UI documentation on MediaWiki][1] for more information.
+ *
+ * If you want to use this within an HTML form, such as a OO.ui.FormLayout, use
+ * OO.ui.CheckboxMultiselectInputWidget instead.
+ *
+ * @example
+ * // A CheckboxMultiselectWidget with CheckboxMultioptions.
+ * var option1 = new OO.ui.CheckboxMultioptionWidget( {
+ * data: 'a',
+ * selected: true,
+ * label: 'Selected checkbox'
+ * } );
+ *
+ * var option2 = new OO.ui.CheckboxMultioptionWidget( {
+ * data: 'b',
+ * label: 'Unselected checkbox'
+ * } );
+ *
+ * var multiselect=new OO.ui.CheckboxMultiselectWidget( {
+ * items: [ option1, option2 ]
+ * } );
+ *
+ * $( 'body' ).append( multiselect.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
+ *
+ * @class
+ * @extends OO.ui.MultiselectWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.CheckboxMultiselectWidget = function OoUiCheckboxMultiselectWidget( config ) {
+ // Parent constructor
+ OO.ui.CheckboxMultiselectWidget.parent.call( this, config );
+
+ // Properties
+ this.$lastClicked = null;
+
+ // Events
+ this.$group.on( 'click', this.onClick.bind( this ) );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-checkboxMultiselectWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.CheckboxMultiselectWidget, OO.ui.MultiselectWidget );
+
+/* Methods */
+
+/**
+ * Get an option by its position relative to the specified item (or to the start of the option array,
+ * if item is `null`). The direction in which to search through the option array is specified with a
+ * number: -1 for reverse (the default) or 1 for forward. The method will return an option, or
+ * `null` if there are no options in the array.
+ *
+ * @param {OO.ui.CheckboxMultioptionWidget|null} item Item to describe the start position, or `null` to start at the beginning of the array.
+ * @param {number} direction Direction to move in: -1 to move backward, 1 to move forward
+ * @return {OO.ui.CheckboxMultioptionWidget|null} Item at position, `null` if there are no items in the select
+ */
+OO.ui.CheckboxMultiselectWidget.prototype.getRelativeFocusableItem = function ( item, direction ) {
+ var currentIndex, nextIndex, i,
+ increase = direction > 0 ? 1 : -1,
+ len = this.items.length;
+
+ if ( item ) {
+ currentIndex = this.items.indexOf( item );
+ nextIndex = ( currentIndex + increase + len ) % len;
+ } else {
+ // If no item is selected and moving forward, start at the beginning.
+ // If moving backward, start at the end.
+ nextIndex = direction > 0 ? 0 : len - 1;
+ }
+
+ for ( i = 0; i < len; i++ ) {
+ item = this.items[ nextIndex ];
+ if ( item && !item.isDisabled() ) {
+ return item;
+ }
+ nextIndex = ( nextIndex + increase + len ) % len;
+ }
+ return null;
+};
+
+/**
+ * Handle click events on checkboxes.
+ *
+ * @param {jQuery.Event} e
+ */
+OO.ui.CheckboxMultiselectWidget.prototype.onClick = function ( e ) {
+ var $options, lastClickedIndex, nowClickedIndex, i, direction, wasSelected, items,
+ $lastClicked = this.$lastClicked,
+ $nowClicked = $( e.target ).closest( '.oo-ui-checkboxMultioptionWidget' )
+ .not( '.oo-ui-widget-disabled' );
+
+ // Allow selecting multiple options at once by Shift-clicking them
+ if ( $lastClicked && $nowClicked.length && e.shiftKey ) {
+ $options = this.$group.find( '.oo-ui-checkboxMultioptionWidget' );
+ lastClickedIndex = $options.index( $lastClicked );
+ nowClickedIndex = $options.index( $nowClicked );
+ // If it's the same item, either the user is being silly, or it's a fake event generated by the
+ // browser. In either case we don't need custom handling.
+ if ( nowClickedIndex !== lastClickedIndex ) {
+ items = this.items;
+ wasSelected = items[ nowClickedIndex ].isSelected();
+ direction = nowClickedIndex > lastClickedIndex ? 1 : -1;
+
+ // This depends on the DOM order of the items and the order of the .items array being the same.
+ for ( i = lastClickedIndex; i !== nowClickedIndex; i += direction ) {
+ if ( !items[ i ].isDisabled() ) {
+ items[ i ].setSelected( !wasSelected );
+ }
+ }
+ // For the now-clicked element, use immediate timeout to allow the browser to do its own
+ // handling first, then set our value. The order in which events happen is different for
+ // clicks on the <input> and on the <label> and there are additional fake clicks fired for
+ // non-click actions that change the checkboxes.
+ e.preventDefault();
+ setTimeout( function () {
+ if ( !items[ nowClickedIndex ].isDisabled() ) {
+ items[ nowClickedIndex ].setSelected( !wasSelected );
+ }
+ } );
+ }
+ }
+
+ if ( $nowClicked.length ) {
+ this.$lastClicked = $nowClicked;
+ }
+};
+
+/**
+ * Focus the widget
+ *
+ * @chainable
+ */
+OO.ui.CheckboxMultiselectWidget.prototype.focus = function () {
+ var item;
+ if ( !this.isDisabled() ) {
+ item = this.getRelativeFocusableItem( null, 1 );
+ if ( item ) {
+ item.focus();
+ }
+ }
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxMultiselectWidget.prototype.simulateLabelClick = function () {
+ this.focus();
+};
+
+/**
+ * Progress bars visually display the status of an operation, such as a download,
+ * and can be either determinate or indeterminate:
+ *
+ * - **determinate** process bars show the percent of an operation that is complete.
+ *
+ * - **indeterminate** process bars use a visual display of motion to indicate that an operation
+ * is taking place. Because the extent of an indeterminate operation is unknown, the bar does
+ * not use percentages.
+ *
+ * The value of the `progress` configuration determines whether the bar is determinate or indeterminate.
+ *
+ * @example
+ * // Examples of determinate and indeterminate progress bars.
+ * var progressBar1 = new OO.ui.ProgressBarWidget( {
+ * progress: 33
+ * } );
+ * var progressBar2 = new OO.ui.ProgressBarWidget();
+ *
+ * // Create a FieldsetLayout to layout progress bars
+ * var fieldset = new OO.ui.FieldsetLayout;
+ * fieldset.addItems( [
+ * new OO.ui.FieldLayout( progressBar1, {label: 'Determinate', align: 'top'}),
+ * new OO.ui.FieldLayout( progressBar2, {label: 'Indeterminate', align: 'top'})
+ * ] );
+ * $( 'body' ).append( fieldset.$element );
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number|boolean} [progress=false] The type of progress bar (determinate or indeterminate).
+ * To create a determinate progress bar, specify a number that reflects the initial percent complete.
+ * By default, the progress bar is indeterminate.
+ */
+OO.ui.ProgressBarWidget = function OoUiProgressBarWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.ProgressBarWidget.parent.call( this, config );
+
+ // Properties
+ this.$bar = $( '<div>' );
+ this.progress = null;
+
+ // Initialization
+ this.setProgress( config.progress !== undefined ? config.progress : false );
+ this.$bar.addClass( 'oo-ui-progressBarWidget-bar' );
+ this.$element
+ .attr( {
+ role: 'progressbar',
+ 'aria-valuemin': 0,
+ 'aria-valuemax': 100
+ } )
+ .addClass( 'oo-ui-progressBarWidget' )
+ .append( this.$bar );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ProgressBarWidget, OO.ui.Widget );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.ProgressBarWidget.static.tagName = 'div';
+
+/* Methods */
+
+/**
+ * Get the percent of the progress that has been completed. Indeterminate progresses will return `false`.
+ *
+ * @return {number|boolean} Progress percent
+ */
+OO.ui.ProgressBarWidget.prototype.getProgress = function () {
+ return this.progress;
+};
+
+/**
+ * Set the percent of the process completed or `false` for an indeterminate process.
+ *
+ * @param {number|boolean} progress Progress percent or `false` for indeterminate
+ */
+OO.ui.ProgressBarWidget.prototype.setProgress = function ( progress ) {
+ this.progress = progress;
+
+ if ( progress !== false ) {
+ this.$bar.css( 'width', this.progress + '%' );
+ this.$element.attr( 'aria-valuenow', this.progress );
+ } else {
+ this.$bar.css( 'width', '' );
+ this.$element.removeAttr( 'aria-valuenow' );
+ }
+ this.$element.toggleClass( 'oo-ui-progressBarWidget-indeterminate', progress === false );
+};
+
+/**
+ * InputWidget is the base class for all input widgets, which
+ * include {@link OO.ui.TextInputWidget text inputs}, {@link OO.ui.CheckboxInputWidget checkbox inputs},
+ * {@link OO.ui.RadioInputWidget radio inputs}, and {@link OO.ui.ButtonInputWidget button inputs}.
+ * See the [OOjs UI documentation on MediaWiki] [1] for more information and examples.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.FlaggedElement
+ * @mixins OO.ui.mixin.TabIndexedElement
+ * @mixins OO.ui.mixin.TitledElement
+ * @mixins OO.ui.mixin.AccessKeyedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [name=''] The value of the input’s HTML `name` attribute.
+ * @cfg {string} [value=''] The value of the input.
+ * @cfg {string} [dir] The directionality of the input (ltr/rtl).
+ * @cfg {string} [inputId] The value of the input’s HTML `id` attribute.
+ * @cfg {Function} [inputFilter] The name of an input filter function. Input filters modify the value of an input
+ * before it is accepted.
+ */
+OO.ui.InputWidget = function OoUiInputWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.InputWidget.parent.call( this, config );
+
+ // Properties
+ // See #reusePreInfuseDOM about config.$input
+ this.$input = config.$input || this.getInputElement( config );
+ this.value = '';
+ this.inputFilter = config.inputFilter;
+
+ // Mixin constructors
+ OO.ui.mixin.FlaggedElement.call( this, config );
+ OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$input } ) );
+ OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$input } ) );
+ OO.ui.mixin.AccessKeyedElement.call( this, $.extend( {}, config, { $accessKeyed: this.$input } ) );
+
+ // Events
+ this.$input.on( 'keydown mouseup cut paste change input select', this.onEdit.bind( this ) );
+
+ // Initialization
+ this.$input
+ .addClass( 'oo-ui-inputWidget-input' )
+ .attr( 'name', config.name )
+ .prop( 'disabled', this.isDisabled() );
+ this.$element
+ .addClass( 'oo-ui-inputWidget' )
+ .append( this.$input );
+ this.setValue( config.value );
+ if ( config.dir ) {
+ this.setDir( config.dir );
+ }
+ if ( config.inputId !== undefined ) {
+ this.setInputId( config.inputId );
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.InputWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.FlaggedElement );
+OO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.TabIndexedElement );
+OO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.TitledElement );
+OO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.AccessKeyedElement );
+
+/* Static Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.InputWidget.static.reusePreInfuseDOM = function ( node, config ) {
+ config = OO.ui.InputWidget.parent.static.reusePreInfuseDOM( node, config );
+ // Reusing `$input` lets browsers preserve inputted values across page reloads, see T114134.
+ config.$input = $( node ).find( '.oo-ui-inputWidget-input' );
+ return config;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.InputWidget.static.gatherPreInfuseState = function ( node, config ) {
+ var state = OO.ui.InputWidget.parent.static.gatherPreInfuseState( node, config );
+ if ( config.$input && config.$input.length ) {
+ state.value = config.$input.val();
+ // Might be better in TabIndexedElement, but it's awkward to do there because mixins are awkward
+ state.focus = config.$input.is( ':focus' );
+ }
+ return state;
+};
+
+/* Events */
+
+/**
+ * @event change
+ *
+ * A change event is emitted when the value of the input changes.
+ *
+ * @param {string} value
+ */
+
+/* Methods */
+
+/**
+ * Get input element.
+ *
+ * Subclasses of OO.ui.InputWidget use the `config` parameter to produce different elements in
+ * different circumstances. The element must have a `value` property (like form elements).
+ *
+ * @protected
+ * @param {Object} config Configuration options
+ * @return {jQuery} Input element
+ */
+OO.ui.InputWidget.prototype.getInputElement = function () {
+ return $( '<input>' );
+};
+
+/**
+ * Handle potentially value-changing events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key down, mouse up, cut, paste, change, input, or select event
+ */
+OO.ui.InputWidget.prototype.onEdit = function () {
+ var widget = this;
+ if ( !this.isDisabled() ) {
+ // Allow the stack to clear so the value will be updated
+ setTimeout( function () {
+ widget.setValue( widget.$input.val() );
+ } );
+ }
+};
+
+/**
+ * Get the value of the input.
+ *
+ * @return {string} Input value
+ */
+OO.ui.InputWidget.prototype.getValue = function () {
+ // Resynchronize our internal data with DOM data. Other scripts executing on the page can modify
+ // it, and we won't know unless they're kind enough to trigger a 'change' event.
+ var value = this.$input.val();
+ if ( this.value !== value ) {
+ this.setValue( value );
+ }
+ return this.value;
+};
+
+/**
+ * Set the directionality of the input.
+ *
+ * @param {string} dir Text directionality: 'ltr', 'rtl' or 'auto'
+ * @chainable
+ */
+OO.ui.InputWidget.prototype.setDir = function ( dir ) {
+ this.$input.prop( 'dir', dir );
+ return this;
+};
+
+/**
+ * Set the value of the input.
+ *
+ * @param {string} value New value
+ * @fires change
+ * @chainable
+ */
+OO.ui.InputWidget.prototype.setValue = function ( value ) {
+ value = this.cleanUpValue( value );
+ // Update the DOM if it has changed. Note that with cleanUpValue, it
+ // is possible for the DOM value to change without this.value changing.
+ if ( this.$input.val() !== value ) {
+ this.$input.val( value );
+ }
+ if ( this.value !== value ) {
+ this.value = value;
+ this.emit( 'change', this.value );
+ }
+ return this;
+};
+
+/**
+ * Clean up incoming value.
+ *
+ * Ensures value is a string, and converts undefined and null to empty string.
+ *
+ * @private
+ * @param {string} value Original value
+ * @return {string} Cleaned up value
+ */
+OO.ui.InputWidget.prototype.cleanUpValue = function ( value ) {
+ if ( value === undefined || value === null ) {
+ return '';
+ } else if ( this.inputFilter ) {
+ return this.inputFilter( String( value ) );
+ } else {
+ return String( value );
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.InputWidget.prototype.setDisabled = function ( state ) {
+ OO.ui.InputWidget.parent.prototype.setDisabled.call( this, state );
+ if ( this.$input ) {
+ this.$input.prop( 'disabled', this.isDisabled() );
+ }
+ return this;
+};
+
+/**
+ * Set the 'id' attribute of the `<input>` element.
+ *
+ * @param {string} id
+ * @chainable
+ */
+OO.ui.InputWidget.prototype.setInputId = function ( id ) {
+ this.$input.attr( 'id', id );
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.InputWidget.prototype.restorePreInfuseState = function ( state ) {
+ OO.ui.InputWidget.parent.prototype.restorePreInfuseState.call( this, state );
+ if ( state.value !== undefined && state.value !== this.getValue() ) {
+ this.setValue( state.value );
+ }
+ if ( state.focus ) {
+ this.focus();
+ }
+};
+
+/**
+ * Data widget intended for creating 'hidden'-type inputs.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [value=''] The value of the input.
+ * @cfg {string} [name=''] The value of the input’s HTML `name` attribute.
+ */
+OO.ui.HiddenInputWidget = function OoUiHiddenInputWidget( config ) {
+ // Configuration initialization
+ config = $.extend( { value: '', name: '' }, config );
+
+ // Parent constructor
+ OO.ui.HiddenInputWidget.parent.call( this, config );
+
+ // Initialization
+ this.$element.attr( {
+ type: 'hidden',
+ value: config.value,
+ name: config.name
+ } );
+ this.$element.removeAttr( 'aria-disabled' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.HiddenInputWidget, OO.ui.Widget );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.HiddenInputWidget.static.tagName = 'input';
+
+/**
+ * ButtonInputWidget is used to submit HTML forms and is intended to be used within
+ * a OO.ui.FormLayout. If you do not need the button to work with HTML forms, you probably
+ * want to use OO.ui.ButtonWidget instead. Button input widgets can be rendered as either an
+ * HTML `<button>` (the default) or an HTML `<input>` tags. See the
+ * [OOjs UI documentation on MediaWiki] [1] for more information.
+ *
+ * @example
+ * // A ButtonInputWidget rendered as an HTML button, the default.
+ * var button = new OO.ui.ButtonInputWidget( {
+ * label: 'Input button',
+ * icon: 'check',
+ * value: 'check'
+ * } );
+ * $( 'body' ).append( button.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs#Button_inputs
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ * @mixins OO.ui.mixin.ButtonElement
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.TitledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [type='button'] The value of the HTML `'type'` attribute: 'button', 'submit' or 'reset'.
+ * @cfg {boolean} [useInputTag=false] Use an `<input>` tag instead of a `<button>` tag, the default.
+ * Widgets configured to be an `<input>` do not support {@link #icon icons} and {@link #indicator indicators},
+ * non-plaintext {@link #label labels}, or {@link #value values}. In general, useInputTag should only
+ * be set to `true` when there’s need to support IE 6 in a form with multiple buttons.
+ */
+OO.ui.ButtonInputWidget = function OoUiButtonInputWidget( config ) {
+ // Configuration initialization
+ config = $.extend( { type: 'button', useInputTag: false }, config );
+
+ // See InputWidget#reusePreInfuseDOM about config.$input
+ if ( config.$input ) {
+ config.$input.empty();
+ }
+
+ // Properties (must be set before parent constructor, which calls #setValue)
+ this.useInputTag = config.useInputTag;
+
+ // Parent constructor
+ OO.ui.ButtonInputWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.ButtonElement.call( this, $.extend( {}, config, { $button: this.$input } ) );
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.IndicatorElement.call( this, config );
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$input } ) );
+
+ // Initialization
+ if ( !config.useInputTag ) {
+ this.$input.append( this.$icon, this.$label, this.$indicator );
+ }
+ this.$element.addClass( 'oo-ui-buttonInputWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ButtonInputWidget, OO.ui.InputWidget );
+OO.mixinClass( OO.ui.ButtonInputWidget, OO.ui.mixin.ButtonElement );
+OO.mixinClass( OO.ui.ButtonInputWidget, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.ButtonInputWidget, OO.ui.mixin.IndicatorElement );
+OO.mixinClass( OO.ui.ButtonInputWidget, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.ButtonInputWidget, OO.ui.mixin.TitledElement );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.ButtonInputWidget.static.tagName = 'span';
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ * @protected
+ */
+OO.ui.ButtonInputWidget.prototype.getInputElement = function ( config ) {
+ var type;
+ type = [ 'button', 'submit', 'reset' ].indexOf( config.type ) !== -1 ? config.type : 'button';
+ return $( '<' + ( config.useInputTag ? 'input' : 'button' ) + ' type="' + type + '">' );
+};
+
+/**
+ * Set label value.
+ *
+ * If #useInputTag is `true`, the label is set as the `value` of the `<input>` tag.
+ *
+ * @param {jQuery|string|Function|null} label Label nodes, text, a function that returns nodes or
+ * text, or `null` for no label
+ * @chainable
+ */
+OO.ui.ButtonInputWidget.prototype.setLabel = function ( label ) {
+ if ( typeof label === 'function' ) {
+ label = OO.ui.resolveMsg( label );
+ }
+
+ if ( this.useInputTag ) {
+ // Discard non-plaintext labels
+ if ( typeof label !== 'string' ) {
+ label = '';
+ }
+
+ this.$input.val( label );
+ }
+
+ return OO.ui.mixin.LabelElement.prototype.setLabel.call( this, label );
+};
+
+/**
+ * Set the value of the input.
+ *
+ * This method is disabled for button inputs configured as {@link #useInputTag <input> tags}, as
+ * they do not support {@link #value values}.
+ *
+ * @param {string} value New value
+ * @chainable
+ */
+OO.ui.ButtonInputWidget.prototype.setValue = function ( value ) {
+ if ( !this.useInputTag ) {
+ OO.ui.ButtonInputWidget.parent.prototype.setValue.call( this, value );
+ }
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ButtonInputWidget.prototype.getInputId = function () {
+ // Disable generating `<label>` elements for buttons. One would very rarely need additional label
+ // for a button, and it's already a big clickable target, and it causes unexpected rendering.
+ return null;
+};
+
+/**
+ * CheckboxInputWidgets, like HTML checkboxes, can be selected and/or configured with a value.
+ * Note that these {@link OO.ui.InputWidget input widgets} are best laid out
+ * in {@link OO.ui.FieldLayout field layouts} that use the {@link OO.ui.FieldLayout#align inline}
+ * alignment. For more information, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * This widget can be used inside an HTML form, such as a OO.ui.FormLayout.
+ *
+ * @example
+ * // An example of selected, unselected, and disabled checkbox inputs
+ * var checkbox1=new OO.ui.CheckboxInputWidget( {
+ * value: 'a',
+ * selected: true
+ * } );
+ * var checkbox2=new OO.ui.CheckboxInputWidget( {
+ * value: 'b'
+ * } );
+ * var checkbox3=new OO.ui.CheckboxInputWidget( {
+ * value:'c',
+ * disabled: true
+ * } );
+ * // Create a fieldset layout with fields for each checkbox.
+ * var fieldset = new OO.ui.FieldsetLayout( {
+ * label: 'Checkboxes'
+ * } );
+ * fieldset.addItems( [
+ * new OO.ui.FieldLayout( checkbox1, { label: 'Selected checkbox', align: 'inline' } ),
+ * new OO.ui.FieldLayout( checkbox2, { label: 'Unselected checkbox', align: 'inline' } ),
+ * new OO.ui.FieldLayout( checkbox3, { label: 'Disabled checkbox', align: 'inline' } ),
+ * ] );
+ * $( 'body' ).append( fieldset.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [selected=false] Select the checkbox initially. By default, the checkbox is not selected.
+ */
+OO.ui.CheckboxInputWidget = function OoUiCheckboxInputWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.CheckboxInputWidget.parent.call( this, config );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-checkboxInputWidget' )
+ // Required for pretty styling in WikimediaUI theme
+ .append( $( '<span>' ) );
+ this.setSelected( config.selected !== undefined ? config.selected : false );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.CheckboxInputWidget, OO.ui.InputWidget );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.CheckboxInputWidget.static.tagName = 'span';
+
+/* Static Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxInputWidget.static.gatherPreInfuseState = function ( node, config ) {
+ var state = OO.ui.CheckboxInputWidget.parent.static.gatherPreInfuseState( node, config );
+ state.checked = config.$input.prop( 'checked' );
+ return state;
+};
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ * @protected
+ */
+OO.ui.CheckboxInputWidget.prototype.getInputElement = function () {
+ return $( '<input>' ).attr( 'type', 'checkbox' );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxInputWidget.prototype.onEdit = function () {
+ var widget = this;
+ if ( !this.isDisabled() ) {
+ // Allow the stack to clear so the value will be updated
+ setTimeout( function () {
+ widget.setSelected( widget.$input.prop( 'checked' ) );
+ } );
+ }
+};
+
+/**
+ * Set selection state of this checkbox.
+ *
+ * @param {boolean} state `true` for selected
+ * @chainable
+ */
+OO.ui.CheckboxInputWidget.prototype.setSelected = function ( state ) {
+ state = !!state;
+ if ( this.selected !== state ) {
+ this.selected = state;
+ this.$input.prop( 'checked', this.selected );
+ this.emit( 'change', this.selected );
+ }
+ return this;
+};
+
+/**
+ * Check if this checkbox is selected.
+ *
+ * @return {boolean} Checkbox is selected
+ */
+OO.ui.CheckboxInputWidget.prototype.isSelected = function () {
+ // Resynchronize our internal data with DOM data. Other scripts executing on the page can modify
+ // it, and we won't know unless they're kind enough to trigger a 'change' event.
+ var selected = this.$input.prop( 'checked' );
+ if ( this.selected !== selected ) {
+ this.setSelected( selected );
+ }
+ return this.selected;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxInputWidget.prototype.simulateLabelClick = function () {
+ if ( !this.isDisabled() ) {
+ this.$input.click();
+ }
+ this.focus();
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxInputWidget.prototype.restorePreInfuseState = function ( state ) {
+ OO.ui.CheckboxInputWidget.parent.prototype.restorePreInfuseState.call( this, state );
+ if ( state.checked !== undefined && state.checked !== this.isSelected() ) {
+ this.setSelected( state.checked );
+ }
+};
+
+/**
+ * DropdownInputWidget is a {@link OO.ui.DropdownWidget DropdownWidget} intended to be used
+ * within an HTML form, such as a OO.ui.FormLayout. The selected value is synchronized with the value
+ * of a hidden HTML `input` tag. Please see the [OOjs UI documentation on MediaWiki][1] for
+ * more information about input widgets.
+ *
+ * A DropdownInputWidget always has a value (one of the options is always selected), unless there
+ * are no options. If no `value` configuration option is provided, the first option is selected.
+ * If you need a state representing no value (no option being selected), use a DropdownWidget.
+ *
+ * This and OO.ui.RadioSelectInputWidget support the same configuration options.
+ *
+ * @example
+ * // Example: A DropdownInputWidget with three options
+ * var dropdownInput = new OO.ui.DropdownInputWidget( {
+ * options: [
+ * { data: 'a', label: 'First' },
+ * { data: 'b', label: 'Second'},
+ * { data: 'c', label: 'Third' }
+ * ]
+ * } );
+ * $( 'body' ).append( dropdownInput.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ * @mixins OO.ui.mixin.TitledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`
+ * @cfg {Object} [dropdown] Configuration options for {@link OO.ui.DropdownWidget DropdownWidget}
+ */
+OO.ui.DropdownInputWidget = function OoUiDropdownInputWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // See InputWidget#reusePreInfuseDOM about config.$input
+ if ( config.$input ) {
+ config.$input.addClass( 'oo-ui-element-hidden' );
+ }
+
+ // Properties (must be done before parent constructor which calls #setDisabled)
+ this.dropdownWidget = new OO.ui.DropdownWidget( config.dropdown );
+
+ // Parent constructor
+ OO.ui.DropdownInputWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.TitledElement.call( this, config );
+
+ // Events
+ this.dropdownWidget.getMenu().connect( this, { select: 'onMenuSelect' } );
+
+ // Initialization
+ this.setOptions( config.options || [] );
+ // Set the value again, after we did setOptions(). The call from parent doesn't work because the
+ // widget has no valid options when it happens.
+ this.setValue( config.value );
+ this.$element
+ .addClass( 'oo-ui-dropdownInputWidget' )
+ .append( this.dropdownWidget.$element );
+ this.setTabIndexedElement( null );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.DropdownInputWidget, OO.ui.InputWidget );
+OO.mixinClass( OO.ui.DropdownInputWidget, OO.ui.mixin.TitledElement );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ * @protected
+ */
+OO.ui.DropdownInputWidget.prototype.getInputElement = function () {
+ return $( '<input>' ).attr( 'type', 'hidden' );
+};
+
+/**
+ * Handles menu select events.
+ *
+ * @private
+ * @param {OO.ui.MenuOptionWidget|null} item Selected menu item
+ */
+OO.ui.DropdownInputWidget.prototype.onMenuSelect = function ( item ) {
+ this.setValue( item ? item.getData() : '' );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.DropdownInputWidget.prototype.setValue = function ( value ) {
+ var selected;
+ value = this.cleanUpValue( value );
+ // Only allow setting values that are actually present in the dropdown
+ selected = this.dropdownWidget.getMenu().getItemFromData( value ) ||
+ this.dropdownWidget.getMenu().getFirstSelectableItem();
+ this.dropdownWidget.getMenu().selectItem( selected );
+ value = selected ? selected.getData() : '';
+ OO.ui.DropdownInputWidget.parent.prototype.setValue.call( this, value );
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.DropdownInputWidget.prototype.setDisabled = function ( state ) {
+ this.dropdownWidget.setDisabled( state );
+ OO.ui.DropdownInputWidget.parent.prototype.setDisabled.call( this, state );
+ return this;
+};
+
+/**
+ * Set the options available for this input.
+ *
+ * @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`
+ * @chainable
+ */
+OO.ui.DropdownInputWidget.prototype.setOptions = function ( options ) {
+ var
+ value = this.getValue(),
+ widget = this;
+
+ // Rebuild the dropdown menu
+ this.dropdownWidget.getMenu()
+ .clearItems()
+ .addItems( options.map( function ( opt ) {
+ var optValue = widget.cleanUpValue( opt.data );
+
+ if ( opt.optgroup === undefined ) {
+ return new OO.ui.MenuOptionWidget( {
+ data: optValue,
+ label: opt.label !== undefined ? opt.label : optValue
+ } );
+ } else {
+ return new OO.ui.MenuSectionOptionWidget( {
+ label: opt.optgroup
+ } );
+ }
+ } ) );
+
+ // Restore the previous value, or reset to something sensible
+ if ( this.dropdownWidget.getMenu().getItemFromData( value ) ) {
+ // Previous value is still available, ensure consistency with the dropdown
+ this.setValue( value );
+ } else {
+ // No longer valid, reset
+ if ( options.length ) {
+ this.setValue( options[ 0 ].data );
+ }
+ }
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.DropdownInputWidget.prototype.focus = function () {
+ this.dropdownWidget.focus();
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.DropdownInputWidget.prototype.blur = function () {
+ this.dropdownWidget.blur();
+ return this;
+};
+
+/**
+ * RadioInputWidget creates a single radio button. Because radio buttons are usually used as a set,
+ * in most cases you will want to use a {@link OO.ui.RadioSelectWidget radio select}
+ * with {@link OO.ui.RadioOptionWidget radio options} instead of this class. For more information,
+ * please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * This widget can be used inside an HTML form, such as a OO.ui.FormLayout.
+ *
+ * @example
+ * // An example of selected, unselected, and disabled radio inputs
+ * var radio1 = new OO.ui.RadioInputWidget( {
+ * value: 'a',
+ * selected: true
+ * } );
+ * var radio2 = new OO.ui.RadioInputWidget( {
+ * value: 'b'
+ * } );
+ * var radio3 = new OO.ui.RadioInputWidget( {
+ * value: 'c',
+ * disabled: true
+ * } );
+ * // Create a fieldset layout with fields for each radio button.
+ * var fieldset = new OO.ui.FieldsetLayout( {
+ * label: 'Radio inputs'
+ * } );
+ * fieldset.addItems( [
+ * new OO.ui.FieldLayout( radio1, { label: 'Selected', align: 'inline' } ),
+ * new OO.ui.FieldLayout( radio2, { label: 'Unselected', align: 'inline' } ),
+ * new OO.ui.FieldLayout( radio3, { label: 'Disabled', align: 'inline' } ),
+ * ] );
+ * $( 'body' ).append( fieldset.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [selected=false] Select the radio button initially. By default, the radio button is not selected.
+ */
+OO.ui.RadioInputWidget = function OoUiRadioInputWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.RadioInputWidget.parent.call( this, config );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-radioInputWidget' )
+ // Required for pretty styling in WikimediaUI theme
+ .append( $( '<span>' ) );
+ this.setSelected( config.selected !== undefined ? config.selected : false );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.RadioInputWidget, OO.ui.InputWidget );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.RadioInputWidget.static.tagName = 'span';
+
+/* Static Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioInputWidget.static.gatherPreInfuseState = function ( node, config ) {
+ var state = OO.ui.RadioInputWidget.parent.static.gatherPreInfuseState( node, config );
+ state.checked = config.$input.prop( 'checked' );
+ return state;
+};
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ * @protected
+ */
+OO.ui.RadioInputWidget.prototype.getInputElement = function () {
+ return $( '<input>' ).attr( 'type', 'radio' );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioInputWidget.prototype.onEdit = function () {
+ // RadioInputWidget doesn't track its state.
+};
+
+/**
+ * Set selection state of this radio button.
+ *
+ * @param {boolean} state `true` for selected
+ * @chainable
+ */
+OO.ui.RadioInputWidget.prototype.setSelected = function ( state ) {
+ // RadioInputWidget doesn't track its state.
+ this.$input.prop( 'checked', state );
+ return this;
+};
+
+/**
+ * Check if this radio button is selected.
+ *
+ * @return {boolean} Radio is selected
+ */
+OO.ui.RadioInputWidget.prototype.isSelected = function () {
+ return this.$input.prop( 'checked' );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioInputWidget.prototype.simulateLabelClick = function () {
+ if ( !this.isDisabled() ) {
+ this.$input.click();
+ }
+ this.focus();
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioInputWidget.prototype.restorePreInfuseState = function ( state ) {
+ OO.ui.RadioInputWidget.parent.prototype.restorePreInfuseState.call( this, state );
+ if ( state.checked !== undefined && state.checked !== this.isSelected() ) {
+ this.setSelected( state.checked );
+ }
+};
+
+/**
+ * RadioSelectInputWidget is a {@link OO.ui.RadioSelectWidget RadioSelectWidget} intended to be used
+ * within an HTML form, such as a OO.ui.FormLayout. The selected value is synchronized with the value
+ * of a hidden HTML `input` tag. Please see the [OOjs UI documentation on MediaWiki][1] for
+ * more information about input widgets.
+ *
+ * This and OO.ui.DropdownInputWidget support the same configuration options.
+ *
+ * @example
+ * // Example: A RadioSelectInputWidget with three options
+ * var radioSelectInput = new OO.ui.RadioSelectInputWidget( {
+ * options: [
+ * { data: 'a', label: 'First' },
+ * { data: 'b', label: 'Second'},
+ * { data: 'c', label: 'Third' }
+ * ]
+ * } );
+ * $( 'body' ).append( radioSelectInput.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`
+ */
+OO.ui.RadioSelectInputWidget = function OoUiRadioSelectInputWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties (must be done before parent constructor which calls #setDisabled)
+ this.radioSelectWidget = new OO.ui.RadioSelectWidget();
+
+ // Parent constructor
+ OO.ui.RadioSelectInputWidget.parent.call( this, config );
+
+ // Events
+ this.radioSelectWidget.connect( this, { select: 'onMenuSelect' } );
+
+ // Initialization
+ this.setOptions( config.options || [] );
+ this.$element
+ .addClass( 'oo-ui-radioSelectInputWidget' )
+ .append( this.radioSelectWidget.$element );
+ this.setTabIndexedElement( null );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.RadioSelectInputWidget, OO.ui.InputWidget );
+
+/* Static Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioSelectInputWidget.static.gatherPreInfuseState = function ( node, config ) {
+ var state = OO.ui.RadioSelectInputWidget.parent.static.gatherPreInfuseState( node, config );
+ state.value = $( node ).find( '.oo-ui-radioInputWidget .oo-ui-inputWidget-input:checked' ).val();
+ return state;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioSelectInputWidget.static.reusePreInfuseDOM = function ( node, config ) {
+ config = OO.ui.RadioSelectInputWidget.parent.static.reusePreInfuseDOM( node, config );
+ // Cannot reuse the `<input type=radio>` set
+ delete config.$input;
+ return config;
+};
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ * @protected
+ */
+OO.ui.RadioSelectInputWidget.prototype.getInputElement = function () {
+ return $( '<input>' ).attr( 'type', 'hidden' );
+};
+
+/**
+ * Handles menu select events.
+ *
+ * @private
+ * @param {OO.ui.RadioOptionWidget} item Selected menu item
+ */
+OO.ui.RadioSelectInputWidget.prototype.onMenuSelect = function ( item ) {
+ this.setValue( item.getData() );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioSelectInputWidget.prototype.setValue = function ( value ) {
+ value = this.cleanUpValue( value );
+ this.radioSelectWidget.selectItemByData( value );
+ OO.ui.RadioSelectInputWidget.parent.prototype.setValue.call( this, value );
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioSelectInputWidget.prototype.setDisabled = function ( state ) {
+ this.radioSelectWidget.setDisabled( state );
+ OO.ui.RadioSelectInputWidget.parent.prototype.setDisabled.call( this, state );
+ return this;
+};
+
+/**
+ * Set the options available for this input.
+ *
+ * @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`
+ * @chainable
+ */
+OO.ui.RadioSelectInputWidget.prototype.setOptions = function ( options ) {
+ var
+ value = this.getValue(),
+ widget = this;
+
+ // Rebuild the radioSelect menu
+ this.radioSelectWidget
+ .clearItems()
+ .addItems( options.map( function ( opt ) {
+ var optValue = widget.cleanUpValue( opt.data );
+ return new OO.ui.RadioOptionWidget( {
+ data: optValue,
+ label: opt.label !== undefined ? opt.label : optValue
+ } );
+ } ) );
+
+ // Restore the previous value, or reset to something sensible
+ if ( this.radioSelectWidget.getItemFromData( value ) ) {
+ // Previous value is still available, ensure consistency with the radioSelect
+ this.setValue( value );
+ } else {
+ // No longer valid, reset
+ if ( options.length ) {
+ this.setValue( options[ 0 ].data );
+ }
+ }
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioSelectInputWidget.prototype.focus = function () {
+ this.radioSelectWidget.focus();
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.RadioSelectInputWidget.prototype.blur = function () {
+ this.radioSelectWidget.blur();
+ return this;
+};
+
+/**
+ * CheckboxMultiselectInputWidget is a
+ * {@link OO.ui.CheckboxMultiselectWidget CheckboxMultiselectWidget} intended to be used within a
+ * HTML form, such as a OO.ui.FormLayout. The selected values are synchronized with the value of
+ * HTML `<input type=checkbox>` tags. Please see the [OOjs UI documentation on MediaWiki][1] for
+ * more information about input widgets.
+ *
+ * @example
+ * // Example: A CheckboxMultiselectInputWidget with three options
+ * var multiselectInput = new OO.ui.CheckboxMultiselectInputWidget( {
+ * options: [
+ * { data: 'a', label: 'First' },
+ * { data: 'b', label: 'Second'},
+ * { data: 'c', label: 'Third' }
+ * ]
+ * } );
+ * $( 'body' ).append( multiselectInput.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: …, disabled: … }`
+ */
+OO.ui.CheckboxMultiselectInputWidget = function OoUiCheckboxMultiselectInputWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties (must be done before parent constructor which calls #setDisabled)
+ this.checkboxMultiselectWidget = new OO.ui.CheckboxMultiselectWidget();
+
+ // Parent constructor
+ OO.ui.CheckboxMultiselectInputWidget.parent.call( this, config );
+
+ // Properties
+ this.inputName = config.name;
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-checkboxMultiselectInputWidget' )
+ .append( this.checkboxMultiselectWidget.$element );
+ // We don't use this.$input, but rather the CheckboxInputWidgets inside each option
+ this.$input.detach();
+ this.setOptions( config.options || [] );
+ // Have to repeat this from parent, as we need options to be set up for this to make sense
+ this.setValue( config.value );
+
+ // setValue when checkboxMultiselectWidget changes
+ this.checkboxMultiselectWidget.on( 'change', function () {
+ this.setValue( this.checkboxMultiselectWidget.getSelectedItemsData() );
+ }.bind( this ) );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.CheckboxMultiselectInputWidget, OO.ui.InputWidget );
+
+/* Static Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxMultiselectInputWidget.static.gatherPreInfuseState = function ( node, config ) {
+ var state = OO.ui.CheckboxMultiselectInputWidget.parent.static.gatherPreInfuseState( node, config );
+ state.value = $( node ).find( '.oo-ui-checkboxInputWidget .oo-ui-inputWidget-input:checked' )
+ .toArray().map( function ( el ) { return el.value; } );
+ return state;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxMultiselectInputWidget.static.reusePreInfuseDOM = function ( node, config ) {
+ config = OO.ui.CheckboxMultiselectInputWidget.parent.static.reusePreInfuseDOM( node, config );
+ // Cannot reuse the `<input type=checkbox>` set
+ delete config.$input;
+ return config;
+};
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ * @protected
+ */
+OO.ui.CheckboxMultiselectInputWidget.prototype.getInputElement = function () {
+ // Actually unused
+ return $( '<unused>' );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxMultiselectInputWidget.prototype.getValue = function () {
+ var value = this.$element.find( '.oo-ui-checkboxInputWidget .oo-ui-inputWidget-input:checked' )
+ .toArray().map( function ( el ) { return el.value; } );
+ if ( this.value !== value ) {
+ this.setValue( value );
+ }
+ return this.value;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxMultiselectInputWidget.prototype.setValue = function ( value ) {
+ value = this.cleanUpValue( value );
+ this.checkboxMultiselectWidget.selectItemsByData( value );
+ OO.ui.CheckboxMultiselectInputWidget.parent.prototype.setValue.call( this, value );
+ return this;
+};
+
+/**
+ * Clean up incoming value.
+ *
+ * @param {string[]} value Original value
+ * @return {string[]} Cleaned up value
+ */
+OO.ui.CheckboxMultiselectInputWidget.prototype.cleanUpValue = function ( value ) {
+ var i, singleValue,
+ cleanValue = [];
+ if ( !Array.isArray( value ) ) {
+ return cleanValue;
+ }
+ for ( i = 0; i < value.length; i++ ) {
+ singleValue =
+ OO.ui.CheckboxMultiselectInputWidget.parent.prototype.cleanUpValue.call( this, value[ i ] );
+ // Remove options that we don't have here
+ if ( !this.checkboxMultiselectWidget.getItemFromData( singleValue ) ) {
+ continue;
+ }
+ cleanValue.push( singleValue );
+ }
+ return cleanValue;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxMultiselectInputWidget.prototype.setDisabled = function ( state ) {
+ this.checkboxMultiselectWidget.setDisabled( state );
+ OO.ui.CheckboxMultiselectInputWidget.parent.prototype.setDisabled.call( this, state );
+ return this;
+};
+
+/**
+ * Set the options available for this input.
+ *
+ * @param {Object[]} options Array of menu options in the format `{ data: …, label: …, disabled: … }`
+ * @chainable
+ */
+OO.ui.CheckboxMultiselectInputWidget.prototype.setOptions = function ( options ) {
+ var widget = this;
+
+ // Rebuild the checkboxMultiselectWidget menu
+ this.checkboxMultiselectWidget
+ .clearItems()
+ .addItems( options.map( function ( opt ) {
+ var optValue, item, optDisabled;
+ optValue =
+ OO.ui.CheckboxMultiselectInputWidget.parent.prototype.cleanUpValue.call( widget, opt.data );
+ optDisabled = opt.disabled !== undefined ? opt.disabled : false;
+ item = new OO.ui.CheckboxMultioptionWidget( {
+ data: optValue,
+ label: opt.label !== undefined ? opt.label : optValue,
+ disabled: optDisabled
+ } );
+ // Set the 'name' and 'value' for form submission
+ item.checkbox.$input.attr( 'name', widget.inputName );
+ item.checkbox.setValue( optValue );
+ return item;
+ } ) );
+
+ // Re-set the value, checking the checkboxes as needed.
+ // This will also get rid of any stale options that we just removed.
+ this.setValue( this.getValue() );
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CheckboxMultiselectInputWidget.prototype.focus = function () {
+ this.checkboxMultiselectWidget.focus();
+ return this;
+};
+
+/**
+ * TextInputWidgets, like HTML text inputs, can be configured with options that customize the
+ * size of the field as well as its presentation. In addition, these widgets can be configured
+ * with {@link OO.ui.mixin.IconElement icons}, {@link OO.ui.mixin.IndicatorElement indicators}, an optional
+ * validation-pattern (used to determine if an input value is valid or not) and an input filter,
+ * which modifies incoming values rather than validating them.
+ * Please see the [OOjs UI documentation on MediaWiki] [1] for more information and examples.
+ *
+ * This widget can be used inside an HTML form, such as a OO.ui.FormLayout.
+ *
+ * @example
+ * // Example of a text input widget
+ * var textInput = new OO.ui.TextInputWidget( {
+ * value: 'Text input'
+ * } )
+ * $( 'body' ).append( textInput.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.PendingElement
+ * @mixins OO.ui.mixin.LabelElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [type='text'] The value of the HTML `type` attribute: 'text', 'password'
+ * 'email', 'url' or 'number'.
+ * @cfg {string} [placeholder] Placeholder text
+ * @cfg {boolean} [autofocus=false] Use an HTML `autofocus` attribute to
+ * instruct the browser to focus this widget.
+ * @cfg {boolean} [readOnly=false] Prevent changes to the value of the text input.
+ * @cfg {number} [maxLength] Maximum number of characters allowed in the input.
+ * @cfg {string} [labelPosition='after'] The position of the inline label relative to that of
+ * the value or placeholder text: `'before'` or `'after'`
+ * @cfg {boolean} [required=false] Mark the field as required. Implies `indicator: 'required'`.
+ * @cfg {boolean} [autocomplete=true] Should the browser support autocomplete for this field
+ * @cfg {RegExp|Function|string} [validate] Validation pattern: when string, a symbolic name of a
+ * pattern defined by the class: 'non-empty' (the value cannot be an empty string) or 'integer'
+ * (the value must contain only numbers); when RegExp, a regular expression that must match the
+ * value for it to be considered valid; when Function, a function receiving the value as parameter
+ * that must return true, or promise resolving to true, for it to be considered valid.
+ */
+OO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {
+ // Configuration initialization
+ config = $.extend( {
+ type: 'text',
+ labelPosition: 'after'
+ }, config );
+
+ if ( config.multiline ) {
+ OO.ui.warnDeprecation( 'TextInputWidget: config.multiline is deprecated. Use the MultilineTextInputWidget instead. See T130434.' );
+ return new OO.ui.MultilineTextInputWidget( config );
+ }
+
+ // Parent constructor
+ OO.ui.TextInputWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.IndicatorElement.call( this, config );
+ OO.ui.mixin.PendingElement.call( this, $.extend( {}, config, { $pending: this.$input } ) );
+ OO.ui.mixin.LabelElement.call( this, config );
+
+ // Properties
+ this.type = this.getSaneType( config );
+ this.readOnly = false;
+ this.required = false;
+ this.validate = null;
+ this.styleHeight = null;
+ this.scrollWidth = null;
+
+ this.setValidation( config.validate );
+ this.setLabelPosition( config.labelPosition );
+
+ // Events
+ this.$input.on( {
+ keypress: this.onKeyPress.bind( this ),
+ blur: this.onBlur.bind( this ),
+ focus: this.onFocus.bind( this )
+ } );
+ this.$icon.on( 'mousedown', this.onIconMouseDown.bind( this ) );
+ this.$indicator.on( 'mousedown', this.onIndicatorMouseDown.bind( this ) );
+ this.on( 'labelChange', this.updatePosition.bind( this ) );
+ this.on( 'change', OO.ui.debounce( this.onDebouncedChange.bind( this ), 250 ) );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-textInputWidget oo-ui-textInputWidget-type-' + this.type )
+ .append( this.$icon, this.$indicator );
+ this.setReadOnly( !!config.readOnly );
+ this.setRequired( !!config.required );
+ if ( config.placeholder !== undefined ) {
+ this.$input.attr( 'placeholder', config.placeholder );
+ }
+ if ( config.maxLength !== undefined ) {
+ this.$input.attr( 'maxlength', config.maxLength );
+ }
+ if ( config.autofocus ) {
+ this.$input.attr( 'autofocus', 'autofocus' );
+ }
+ if ( config.autocomplete === false ) {
+ this.$input.attr( 'autocomplete', 'off' );
+ // Turning off autocompletion also disables "form caching" when the user navigates to a
+ // different page and then clicks "Back". Re-enable it when leaving. Borrowed from jQuery UI.
+ $( window ).on( {
+ beforeunload: function () {
+ this.$input.removeAttr( 'autocomplete' );
+ }.bind( this ),
+ pageshow: function () {
+ // Browsers don't seem to actually fire this event on "Back", they instead just reload the
+ // whole page... it shouldn't hurt, though.
+ this.$input.attr( 'autocomplete', 'off' );
+ }.bind( this )
+ } );
+ }
+ if ( this.label ) {
+ this.isWaitingToBeAttached = true;
+ this.installParentChangeDetector();
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.TextInputWidget, OO.ui.InputWidget );
+OO.mixinClass( OO.ui.TextInputWidget, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.TextInputWidget, OO.ui.mixin.IndicatorElement );
+OO.mixinClass( OO.ui.TextInputWidget, OO.ui.mixin.PendingElement );
+OO.mixinClass( OO.ui.TextInputWidget, OO.ui.mixin.LabelElement );
+
+/* Static Properties */
+
+OO.ui.TextInputWidget.static.validationPatterns = {
+ 'non-empty': /.+/,
+ integer: /^\d+$/
+};
+
+/* Static Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.TextInputWidget.static.gatherPreInfuseState = function ( node, config ) {
+ var state = OO.ui.TextInputWidget.parent.static.gatherPreInfuseState( node, config );
+ return state;
+};
+
+/* Events */
+
+/**
+ * An `enter` event is emitted when the user presses 'enter' inside the text box.
+ *
+ * @event enter
+ */
+
+/* Methods */
+
+/**
+ * Handle icon mouse down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.TextInputWidget.prototype.onIconMouseDown = function ( e ) {
+ if ( e.which === OO.ui.MouseButtons.LEFT ) {
+ this.focus();
+ return false;
+ }
+};
+
+/**
+ * Handle indicator mouse down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.TextInputWidget.prototype.onIndicatorMouseDown = function ( e ) {
+ if ( e.which === OO.ui.MouseButtons.LEFT ) {
+ this.focus();
+ return false;
+ }
+};
+
+/**
+ * Handle key press events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key press event
+ * @fires enter If enter key is pressed
+ */
+OO.ui.TextInputWidget.prototype.onKeyPress = function ( e ) {
+ if ( e.which === OO.ui.Keys.ENTER ) {
+ this.emit( 'enter', e );
+ }
+};
+
+/**
+ * Handle blur events.
+ *
+ * @private
+ * @param {jQuery.Event} e Blur event
+ */
+OO.ui.TextInputWidget.prototype.onBlur = function () {
+ this.setValidityFlag();
+};
+
+/**
+ * Handle focus events.
+ *
+ * @private
+ * @param {jQuery.Event} e Focus event
+ */
+OO.ui.TextInputWidget.prototype.onFocus = function () {
+ if ( this.isWaitingToBeAttached ) {
+ // If we've received focus, then we must be attached to the document, and if
+ // isWaitingToBeAttached is still true, that means the handler never fired. Fire it now.
+ this.onElementAttach();
+ }
+ this.setValidityFlag( true );
+};
+
+/**
+ * Handle element attach events.
+ *
+ * @private
+ * @param {jQuery.Event} e Element attach event
+ */
+OO.ui.TextInputWidget.prototype.onElementAttach = function () {
+ this.isWaitingToBeAttached = false;
+ // Any previously calculated size is now probably invalid if we reattached elsewhere
+ this.valCache = null;
+ this.positionLabel();
+};
+
+/**
+ * Handle debounced change events.
+ *
+ * @param {string} value
+ * @private
+ */
+OO.ui.TextInputWidget.prototype.onDebouncedChange = function () {
+ this.setValidityFlag();
+};
+
+/**
+ * Check if the input is {@link #readOnly read-only}.
+ *
+ * @return {boolean}
+ */
+OO.ui.TextInputWidget.prototype.isReadOnly = function () {
+ return this.readOnly;
+};
+
+/**
+ * Set the {@link #readOnly read-only} state of the input.
+ *
+ * @param {boolean} state Make input read-only
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.setReadOnly = function ( state ) {
+ this.readOnly = !!state;
+ this.$input.prop( 'readOnly', this.readOnly );
+ return this;
+};
+
+/**
+ * Check if the input is {@link #required required}.
+ *
+ * @return {boolean}
+ */
+OO.ui.TextInputWidget.prototype.isRequired = function () {
+ return this.required;
+};
+
+/**
+ * Set the {@link #required required} state of the input.
+ *
+ * @param {boolean} state Make input required
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.setRequired = function ( state ) {
+ this.required = !!state;
+ if ( this.required ) {
+ this.$input
+ .prop( 'required', true )
+ .attr( 'aria-required', 'true' );
+ if ( this.getIndicator() === null ) {
+ this.setIndicator( 'required' );
+ }
+ } else {
+ this.$input
+ .prop( 'required', false )
+ .removeAttr( 'aria-required' );
+ if ( this.getIndicator() === 'required' ) {
+ this.setIndicator( null );
+ }
+ }
+ return this;
+};
+
+/**
+ * Support function for making #onElementAttach work across browsers.
+ *
+ * This whole function could be replaced with one line of code using the DOMNodeInsertedIntoDocument
+ * event, but it's not supported by Firefox and allegedly deprecated, so we only use it as fallback.
+ *
+ * Due to MutationObserver performance woes, #onElementAttach is only somewhat reliably called the
+ * first time that the element gets attached to the documented.
+ */
+OO.ui.TextInputWidget.prototype.installParentChangeDetector = function () {
+ var mutationObserver, onRemove, topmostNode, fakeParentNode,
+ MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,
+ widget = this;
+
+ if ( MutationObserver ) {
+ // The new way. If only it wasn't so ugly.
+
+ if ( this.isElementAttached() ) {
+ // Widget is attached already, do nothing. This breaks the functionality of this function when
+ // the widget is detached and reattached. Alas, doing this correctly with MutationObserver
+ // would require observation of the whole document, which would hurt performance of other,
+ // more important code.
+ return;
+ }
+
+ // Find topmost node in the tree
+ topmostNode = this.$element[ 0 ];
+ while ( topmostNode.parentNode ) {
+ topmostNode = topmostNode.parentNode;
+ }
+
+ // We have no way to detect the $element being attached somewhere without observing the entire
+ // DOM with subtree modifications, which would hurt performance. So we cheat: we hook to the
+ // parent node of $element, and instead detect when $element is removed from it (and thus
+ // probably attached somewhere else). If there is no parent, we create a "fake" one. If it
+ // doesn't get attached, we end up back here and create the parent.
+
+ mutationObserver = new MutationObserver( function ( mutations ) {
+ var i, j, removedNodes;
+ for ( i = 0; i < mutations.length; i++ ) {
+ removedNodes = mutations[ i ].removedNodes;
+ for ( j = 0; j < removedNodes.length; j++ ) {
+ if ( removedNodes[ j ] === topmostNode ) {
+ setTimeout( onRemove, 0 );
+ return;
+ }
+ }
+ }
+ } );
+
+ onRemove = function () {
+ // If the node was attached somewhere else, report it
+ if ( widget.isElementAttached() ) {
+ widget.onElementAttach();
+ }
+ mutationObserver.disconnect();
+ widget.installParentChangeDetector();
+ };
+
+ // Create a fake parent and observe it
+ fakeParentNode = $( '<div>' ).append( topmostNode )[ 0 ];
+ mutationObserver.observe( fakeParentNode, { childList: true } );
+ } else {
+ // Using the DOMNodeInsertedIntoDocument event is much nicer and less magical, and works for
+ // detachment and reattachment, but it's not supported by Firefox and allegedly deprecated.
+ this.$element.on( 'DOMNodeInsertedIntoDocument', this.onElementAttach.bind( this ) );
+ }
+};
+
+/**
+ * @inheritdoc
+ * @protected
+ */
+OO.ui.TextInputWidget.prototype.getInputElement = function ( config ) {
+ if ( this.getSaneType( config ) === 'number' ) {
+ return $( '<input>' )
+ .attr( 'step', 'any' )
+ .attr( 'type', 'number' );
+ } else {
+ return $( '<input>' ).attr( 'type', this.getSaneType( config ) );
+ }
+};
+
+/**
+ * Get sanitized value for 'type' for given config.
+ *
+ * @param {Object} config Configuration options
+ * @return {string|null}
+ * @private
+ */
+OO.ui.TextInputWidget.prototype.getSaneType = function ( config ) {
+ var allowedTypes = [
+ 'text',
+ 'password',
+ 'email',
+ 'url',
+ 'number'
+ ];
+ return allowedTypes.indexOf( config.type ) !== -1 ? config.type : 'text';
+};
+
+/**
+ * Focus the input and select a specified range within the text.
+ *
+ * @param {number} from Select from offset
+ * @param {number} [to] Select to offset, defaults to from
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.selectRange = function ( from, to ) {
+ var isBackwards, start, end,
+ input = this.$input[ 0 ];
+
+ to = to || from;
+
+ isBackwards = to < from;
+ start = isBackwards ? to : from;
+ end = isBackwards ? from : to;
+
+ this.focus();
+
+ try {
+ input.setSelectionRange( start, end, isBackwards ? 'backward' : 'forward' );
+ } catch ( e ) {
+ // IE throws an exception if you call setSelectionRange on a unattached DOM node.
+ // Rather than expensively check if the input is attached every time, just check
+ // if it was the cause of an error being thrown. If not, rethrow the error.
+ if ( this.getElementDocument().body.contains( input ) ) {
+ throw e;
+ }
+ }
+ return this;
+};
+
+/**
+ * Get an object describing the current selection range in a directional manner
+ *
+ * @return {Object} Object containing 'from' and 'to' offsets
+ */
+OO.ui.TextInputWidget.prototype.getRange = function () {
+ var input = this.$input[ 0 ],
+ start = input.selectionStart,
+ end = input.selectionEnd,
+ isBackwards = input.selectionDirection === 'backward';
+
+ return {
+ from: isBackwards ? end : start,
+ to: isBackwards ? start : end
+ };
+};
+
+/**
+ * Get the length of the text input value.
+ *
+ * This could differ from the length of #getValue if the
+ * value gets filtered
+ *
+ * @return {number} Input length
+ */
+OO.ui.TextInputWidget.prototype.getInputLength = function () {
+ return this.$input[ 0 ].value.length;
+};
+
+/**
+ * Focus the input and select the entire text.
+ *
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.select = function () {
+ return this.selectRange( 0, this.getInputLength() );
+};
+
+/**
+ * Focus the input and move the cursor to the start.
+ *
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.moveCursorToStart = function () {
+ return this.selectRange( 0 );
+};
+
+/**
+ * Focus the input and move the cursor to the end.
+ *
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.moveCursorToEnd = function () {
+ return this.selectRange( this.getInputLength() );
+};
+
+/**
+ * Insert new content into the input.
+ *
+ * @param {string} content Content to be inserted
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.insertContent = function ( content ) {
+ var start, end,
+ range = this.getRange(),
+ value = this.getValue();
+
+ start = Math.min( range.from, range.to );
+ end = Math.max( range.from, range.to );
+
+ this.setValue( value.slice( 0, start ) + content + value.slice( end ) );
+ this.selectRange( start + content.length );
+ return this;
+};
+
+/**
+ * Insert new content either side of a selection.
+ *
+ * @param {string} pre Content to be inserted before the selection
+ * @param {string} post Content to be inserted after the selection
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.encapsulateContent = function ( pre, post ) {
+ var start, end,
+ range = this.getRange(),
+ offset = pre.length;
+
+ start = Math.min( range.from, range.to );
+ end = Math.max( range.from, range.to );
+
+ this.selectRange( start ).insertContent( pre );
+ this.selectRange( offset + end ).insertContent( post );
+
+ this.selectRange( offset + start, offset + end );
+ return this;
+};
+
+/**
+ * Set the validation pattern.
+ *
+ * The validation pattern is either a regular expression, a function, or the symbolic name of a
+ * pattern defined by the class: 'non-empty' (the value cannot be an empty string) or 'integer' (the
+ * value must contain only numbers).
+ *
+ * @param {RegExp|Function|string|null} validate Regular expression, function, or the symbolic name
+ * of a pattern (either ‘integer’ or ‘non-empty’) defined by the class.
+ */
+OO.ui.TextInputWidget.prototype.setValidation = function ( validate ) {
+ if ( validate instanceof RegExp || validate instanceof Function ) {
+ this.validate = validate;
+ } else {
+ this.validate = this.constructor.static.validationPatterns[ validate ] || /.*/;
+ }
+};
+
+/**
+ * Sets the 'invalid' flag appropriately.
+ *
+ * @param {boolean} [isValid] Optionally override validation result
+ */
+OO.ui.TextInputWidget.prototype.setValidityFlag = function ( isValid ) {
+ var widget = this,
+ setFlag = function ( valid ) {
+ if ( !valid ) {
+ widget.$input.attr( 'aria-invalid', 'true' );
+ } else {
+ widget.$input.removeAttr( 'aria-invalid' );
+ }
+ widget.setFlags( { invalid: !valid } );
+ };
+
+ if ( isValid !== undefined ) {
+ setFlag( isValid );
+ } else {
+ this.getValidity().then( function () {
+ setFlag( true );
+ }, function () {
+ setFlag( false );
+ } );
+ }
+};
+
+/**
+ * Get the validity of current value.
+ *
+ * This method returns a promise that resolves if the value is valid and rejects if
+ * it isn't. Uses the {@link #validate validation pattern} to check for validity.
+ *
+ * @return {jQuery.Promise} A promise that resolves if the value is valid, rejects if not.
+ */
+OO.ui.TextInputWidget.prototype.getValidity = function () {
+ var result;
+
+ function rejectOrResolve( valid ) {
+ if ( valid ) {
+ return $.Deferred().resolve().promise();
+ } else {
+ return $.Deferred().reject().promise();
+ }
+ }
+
+ // Check browser validity and reject if it is invalid
+ if (
+ this.$input[ 0 ].checkValidity !== undefined &&
+ this.$input[ 0 ].checkValidity() === false
+ ) {
+ return rejectOrResolve( false );
+ }
+
+ // Run our checks if the browser thinks the field is valid
+ if ( this.validate instanceof Function ) {
+ result = this.validate( this.getValue() );
+ if ( result && $.isFunction( result.promise ) ) {
+ return result.promise().then( function ( valid ) {
+ return rejectOrResolve( valid );
+ } );
+ } else {
+ return rejectOrResolve( result );
+ }
+ } else {
+ return rejectOrResolve( this.getValue().match( this.validate ) );
+ }
+};
+
+/**
+ * Set the position of the inline label relative to that of the value: `‘before’` or `‘after’`.
+ *
+ * @param {string} labelPosition Label position, 'before' or 'after'
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.setLabelPosition = function ( labelPosition ) {
+ this.labelPosition = labelPosition;
+ if ( this.label ) {
+ // If there is no label and we only change the position, #updatePosition is a no-op,
+ // but it takes really a lot of work to do nothing.
+ this.updatePosition();
+ }
+ return this;
+};
+
+/**
+ * Update the position of the inline label.
+ *
+ * This method is called by #setLabelPosition, and can also be called on its own if
+ * something causes the label to be mispositioned.
+ *
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.updatePosition = function () {
+ var after = this.labelPosition === 'after';
+
+ this.$element
+ .toggleClass( 'oo-ui-textInputWidget-labelPosition-after', !!this.label && after )
+ .toggleClass( 'oo-ui-textInputWidget-labelPosition-before', !!this.label && !after );
+
+ this.valCache = null;
+ this.scrollWidth = null;
+ this.positionLabel();
+
+ return this;
+};
+
+/**
+ * Position the label by setting the correct padding on the input.
+ *
+ * @private
+ * @chainable
+ */
+OO.ui.TextInputWidget.prototype.positionLabel = function () {
+ var after, rtl, property, newCss;
+
+ if ( this.isWaitingToBeAttached ) {
+ // #onElementAttach will be called soon, which calls this method
+ return this;
+ }
+
+ newCss = {
+ 'padding-right': '',
+ 'padding-left': ''
+ };
+
+ if ( this.label ) {
+ this.$element.append( this.$label );
+ } else {
+ this.$label.detach();
+ // Clear old values if present
+ this.$input.css( newCss );
+ return;
+ }
+
+ after = this.labelPosition === 'after';
+ rtl = this.$element.css( 'direction' ) === 'rtl';
+ property = after === rtl ? 'padding-left' : 'padding-right';
+
+ newCss[ property ] = this.$label.outerWidth( true ) + ( after ? this.scrollWidth : 0 );
+ // We have to clear the padding on the other side, in case the element direction changed
+ this.$input.css( newCss );
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.TextInputWidget.prototype.restorePreInfuseState = function ( state ) {
+ OO.ui.TextInputWidget.parent.prototype.restorePreInfuseState.call( this, state );
+ if ( state.scrollTop !== undefined ) {
+ this.$input.scrollTop( state.scrollTop );
+ }
+};
+
+/**
+ * @class
+ * @extends OO.ui.TextInputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.SearchInputWidget = function OoUiSearchInputWidget( config ) {
+ config = $.extend( {
+ icon: 'search'
+ }, config );
+
+ // Set type to text so that TextInputWidget doesn't
+ // get stuck in an infinite loop.
+ config.type = 'text';
+
+ // Parent constructor
+ OO.ui.SearchInputWidget.parent.call( this, config );
+
+ // Events
+ this.connect( this, {
+ change: 'onChange'
+ } );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-textInputWidget-type-search' );
+ this.updateSearchIndicator();
+ this.connect( this, {
+ disable: 'onDisable'
+ } );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.SearchInputWidget, OO.ui.TextInputWidget );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ * @protected
+ */
+OO.ui.SearchInputWidget.prototype.getInputElement = function () {
+ return $( '<input>' ).attr( 'type', 'search' );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.SearchInputWidget.prototype.onIndicatorMouseDown = function ( e ) {
+ if ( e.which === OO.ui.MouseButtons.LEFT ) {
+ // Clear the text field
+ this.setValue( '' );
+ this.focus();
+ return false;
+ }
+};
+
+/**
+ * Update the 'clear' indicator displayed on type: 'search' text
+ * fields, hiding it when the field is already empty or when it's not
+ * editable.
+ */
+OO.ui.SearchInputWidget.prototype.updateSearchIndicator = function () {
+ if ( this.getValue() === '' || this.isDisabled() || this.isReadOnly() ) {
+ this.setIndicator( null );
+ } else {
+ this.setIndicator( 'clear' );
+ }
+};
+
+/**
+ * Handle change events.
+ *
+ * @private
+ */
+OO.ui.SearchInputWidget.prototype.onChange = function () {
+ this.updateSearchIndicator();
+};
+
+/**
+ * Handle disable events.
+ *
+ * @param {boolean} disabled Element is disabled
+ * @private
+ */
+OO.ui.SearchInputWidget.prototype.onDisable = function () {
+ this.updateSearchIndicator();
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.SearchInputWidget.prototype.setReadOnly = function ( state ) {
+ OO.ui.SearchInputWidget.parent.prototype.setReadOnly.call( this, state );
+ this.updateSearchIndicator();
+ return this;
+};
+
+/**
+ * @class
+ * @extends OO.ui.TextInputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [rows] Number of visible lines in textarea. If used with `autosize`,
+ * specifies minimum number of rows to display.
+ * @cfg {string} [labelPosition='after'] The position of the inline label relative to that of
+ * @cfg {boolean} [autosize=false] Automatically resize the text input to fit its content.
+ * Use the #maxRows config to specify a maximum number of displayed rows.
+ * @cfg {boolean} [maxRows] Maximum number of rows to display when #autosize is set to true.
+ * Defaults to the maximum of `10` and `2 * rows`, or `10` if `rows` isn't provided.
+ */
+OO.ui.MultilineTextInputWidget = function OoUiMultilineTextInputWidget( config ) {
+ config = $.extend( {
+ type: 'text'
+ }, config );
+ config.multiline = false;
+ // Parent constructor
+ OO.ui.MultilineTextInputWidget.parent.call( this, config );
+
+ // Properties
+ this.multiline = true;
+ this.autosize = !!config.autosize;
+ this.minRows = config.rows !== undefined ? config.rows : '';
+ this.maxRows = config.maxRows || Math.max( 2 * ( this.minRows || 0 ), 10 );
+
+ // Clone for resizing
+ if ( this.autosize ) {
+ this.$clone = this.$input
+ .clone()
+ .insertAfter( this.$input )
+ .attr( 'aria-hidden', 'true' )
+ .addClass( 'oo-ui-element-hidden' );
+ }
+
+ // Events
+ this.connect( this, {
+ change: 'onChange'
+ } );
+
+ // Initialization
+ if ( this.multiline && config.rows ) {
+ this.$input.attr( 'rows', config.rows );
+ }
+ if ( this.autosize ) {
+ this.isWaitingToBeAttached = true;
+ this.installParentChangeDetector();
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MultilineTextInputWidget, OO.ui.TextInputWidget );
+
+/* Static Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MultilineTextInputWidget.static.gatherPreInfuseState = function ( node, config ) {
+ var state = OO.ui.MultilineTextInputWidget.parent.static.gatherPreInfuseState( node, config );
+ state.scrollTop = config.$input.scrollTop();
+ return state;
+};
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MultilineTextInputWidget.prototype.onElementAttach = function () {
+ OO.ui.MultilineTextInputWidget.parent.prototype.onElementAttach.call( this );
+ this.adjustSize();
+};
+
+/**
+ * Handle change events.
+ *
+ * @private
+ */
+OO.ui.MultilineTextInputWidget.prototype.onChange = function () {
+ this.adjustSize();
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MultilineTextInputWidget.prototype.updatePosition = function () {
+ OO.ui.MultilineTextInputWidget.parent.prototype.updatePosition.call( this );
+ this.adjustSize();
+};
+
+/**
+ * Override TextInputWidget so it doesn't emit the 'enter' event.
+ *
+ * @private
+ * @param {jQuery.Event} e Key press event
+ */
+OO.ui.MultilineTextInputWidget.prototype.onKeyPress = function () {
+ return;
+};
+
+/**
+ * Automatically adjust the size of the text input.
+ *
+ * This only affects multiline inputs that are {@link #autosize autosized}.
+ *
+ * @chainable
+ * @fires resize
+ */
+OO.ui.MultilineTextInputWidget.prototype.adjustSize = function () {
+ var scrollHeight, innerHeight, outerHeight, maxInnerHeight, measurementError,
+ idealHeight, newHeight, scrollWidth, property;
+
+ if ( this.$input.val() !== this.valCache ) {
+ if ( this.autosize ) {
+ this.$clone
+ .val( this.$input.val() )
+ .attr( 'rows', this.minRows )
+ // Set inline height property to 0 to measure scroll height
+ .css( 'height', 0 );
+
+ this.$clone.removeClass( 'oo-ui-element-hidden' );
+
+ this.valCache = this.$input.val();
+
+ scrollHeight = this.$clone[ 0 ].scrollHeight;
+
+ // Remove inline height property to measure natural heights
+ this.$clone.css( 'height', '' );
+ innerHeight = this.$clone.innerHeight();
+ outerHeight = this.$clone.outerHeight();
+
+ // Measure max rows height
+ this.$clone
+ .attr( 'rows', this.maxRows )
+ .css( 'height', 'auto' )
+ .val( '' );
+ maxInnerHeight = this.$clone.innerHeight();
+
+ // Difference between reported innerHeight and scrollHeight with no scrollbars present.
+ // This is sometimes non-zero on Blink-based browsers, depending on zoom level.
+ measurementError = maxInnerHeight - this.$clone[ 0 ].scrollHeight;
+ idealHeight = Math.min( maxInnerHeight, scrollHeight + measurementError );
+
+ this.$clone.addClass( 'oo-ui-element-hidden' );
+
+ // Only apply inline height when expansion beyond natural height is needed
+ // Use the difference between the inner and outer height as a buffer
+ newHeight = idealHeight > innerHeight ? idealHeight + ( outerHeight - innerHeight ) : '';
+ if ( newHeight !== this.styleHeight ) {
+ this.$input.css( 'height', newHeight );
+ this.styleHeight = newHeight;
+ this.emit( 'resize' );
+ }
+ }
+ scrollWidth = this.$input[ 0 ].offsetWidth - this.$input[ 0 ].clientWidth;
+ if ( scrollWidth !== this.scrollWidth ) {
+ property = this.$element.css( 'direction' ) === 'rtl' ? 'left' : 'right';
+ // Reset
+ this.$label.css( { right: '', left: '' } );
+ this.$indicator.css( { right: '', left: '' } );
+
+ if ( scrollWidth ) {
+ this.$indicator.css( property, scrollWidth );
+ if ( this.labelPosition === 'after' ) {
+ this.$label.css( property, scrollWidth );
+ }
+ }
+
+ this.scrollWidth = scrollWidth;
+ this.positionLabel();
+ }
+ }
+ return this;
+};
+
+/**
+ * @inheritdoc
+ * @protected
+ */
+OO.ui.MultilineTextInputWidget.prototype.getInputElement = function () {
+ return $( '<textarea>' );
+};
+
+/**
+ * Check if the input supports multiple lines.
+ *
+ * @return {boolean}
+ */
+OO.ui.MultilineTextInputWidget.prototype.isMultiline = function () {
+ return !!this.multiline;
+};
+
+/**
+ * Check if the input automatically adjusts its size.
+ *
+ * @return {boolean}
+ */
+OO.ui.MultilineTextInputWidget.prototype.isAutosizing = function () {
+ return !!this.autosize;
+};
+
+/**
+ * ComboBoxInputWidgets combine a {@link OO.ui.TextInputWidget text input} (where a value
+ * can be entered manually) and a {@link OO.ui.MenuSelectWidget menu of options} (from which
+ * a value can be chosen instead). Users can choose options from the combo box in one of two ways:
+ *
+ * - by typing a value in the text input field. If the value exactly matches the value of a menu
+ * option, that option will appear to be selected.
+ * - by choosing a value from the menu. The value of the chosen option will then appear in the text
+ * input field.
+ *
+ * After the user chooses an option, its `data` will be used as a new value for the widget.
+ * A `label` also can be specified for each option: if given, it will be shown instead of the
+ * `data` in the dropdown menu.
+ *
+ * This widget can be used inside an HTML form, such as a OO.ui.FormLayout.
+ *
+ * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * @example
+ * // Example: A ComboBoxInputWidget.
+ * var comboBox = new OO.ui.ComboBoxInputWidget( {
+ * value: 'Option 1',
+ * options: [
+ * { data: 'Option 1' },
+ * { data: 'Option 2' },
+ * { data: 'Option 3' }
+ * ]
+ * } );
+ * $( 'body' ).append( comboBox.$element );
+ *
+ * @example
+ * // Example: A ComboBoxInputWidget with additional option labels.
+ * var comboBox = new OO.ui.ComboBoxInputWidget( {
+ * value: 'Option 1',
+ * options: [
+ * {
+ * data: 'Option 1',
+ * label: 'Option One'
+ * },
+ * {
+ * data: 'Option 2',
+ * label: 'Option Two'
+ * },
+ * {
+ * data: 'Option 3',
+ * label: 'Option Three'
+ * }
+ * ]
+ * } );
+ * $( 'body' ).append( comboBox.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options
+ *
+ * @class
+ * @extends OO.ui.TextInputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`
+ * @cfg {Object} [menu] Configuration options to pass to the {@link OO.ui.MenuSelectWidget menu select widget}.
+ * @cfg {jQuery} [$overlay] Render the menu into a separate layer. This configuration is useful in cases where
+ * the expanded menu is larger than its containing `<div>`. The specified overlay layer is usually on top of the
+ * containing `<div>` and has a larger area. By default, the menu uses relative positioning.
+ * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.
+ */
+OO.ui.ComboBoxInputWidget = function OoUiComboBoxInputWidget( config ) {
+ // Configuration initialization
+ config = $.extend( {
+ autocomplete: false
+ }, config );
+
+ // ComboBoxInputWidget shouldn't support `multiline`
+ config.multiline = false;
+
+ // See InputWidget#reusePreInfuseDOM about `config.$input`
+ if ( config.$input ) {
+ config.$input.removeAttr( 'list' );
+ }
+
+ // Parent constructor
+ OO.ui.ComboBoxInputWidget.parent.call( this, config );
+
+ // Properties
+ this.$overlay = config.$overlay || this.$element;
+ this.dropdownButton = new OO.ui.ButtonWidget( {
+ classes: [ 'oo-ui-comboBoxInputWidget-dropdownButton' ],
+ indicator: 'down',
+ disabled: this.disabled
+ } );
+ this.menu = new OO.ui.MenuSelectWidget( $.extend(
+ {
+ widget: this,
+ input: this,
+ $floatableContainer: this.$element,
+ disabled: this.isDisabled()
+ },
+ config.menu
+ ) );
+
+ // Events
+ this.connect( this, {
+ change: 'onInputChange',
+ enter: 'onInputEnter'
+ } );
+ this.dropdownButton.connect( this, {
+ click: 'onDropdownButtonClick'
+ } );
+ this.menu.connect( this, {
+ choose: 'onMenuChoose',
+ add: 'onMenuItemsChange',
+ remove: 'onMenuItemsChange'
+ } );
+
+ // Initialization
+ this.$input.attr( {
+ role: 'combobox',
+ 'aria-owns': this.menu.getElementId(),
+ 'aria-autocomplete': 'list'
+ } );
+ // Do not override options set via config.menu.items
+ if ( config.options !== undefined ) {
+ this.setOptions( config.options );
+ }
+ this.$field = $( '<div>' )
+ .addClass( 'oo-ui-comboBoxInputWidget-field' )
+ .append( this.$input, this.dropdownButton.$element );
+ this.$element
+ .addClass( 'oo-ui-comboBoxInputWidget' )
+ .append( this.$field );
+ this.$overlay.append( this.menu.$element );
+ this.onMenuItemsChange();
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ComboBoxInputWidget, OO.ui.TextInputWidget );
+
+/* Methods */
+
+/**
+ * Get the combobox's menu.
+ *
+ * @return {OO.ui.MenuSelectWidget} Menu widget
+ */
+OO.ui.ComboBoxInputWidget.prototype.getMenu = function () {
+ return this.menu;
+};
+
+/**
+ * Get the combobox's text input widget.
+ *
+ * @return {OO.ui.TextInputWidget} Text input widget
+ */
+OO.ui.ComboBoxInputWidget.prototype.getInput = function () {
+ return this;
+};
+
+/**
+ * Handle input change events.
+ *
+ * @private
+ * @param {string} value New value
+ */
+OO.ui.ComboBoxInputWidget.prototype.onInputChange = function ( value ) {
+ var match = this.menu.getItemFromData( value );
+
+ this.menu.selectItem( match );
+ if ( this.menu.getHighlightedItem() ) {
+ this.menu.highlightItem( match );
+ }
+
+ if ( !this.isDisabled() ) {
+ this.menu.toggle( true );
+ }
+};
+
+/**
+ * Handle input enter events.
+ *
+ * @private
+ */
+OO.ui.ComboBoxInputWidget.prototype.onInputEnter = function () {
+ if ( !this.isDisabled() ) {
+ this.menu.toggle( false );
+ }
+};
+
+/**
+ * Handle button click events.
+ *
+ * @private
+ */
+OO.ui.ComboBoxInputWidget.prototype.onDropdownButtonClick = function () {
+ this.menu.toggle();
+ this.focus();
+};
+
+/**
+ * Handle menu choose events.
+ *
+ * @private
+ * @param {OO.ui.OptionWidget} item Chosen item
+ */
+OO.ui.ComboBoxInputWidget.prototype.onMenuChoose = function ( item ) {
+ this.setValue( item.getData() );
+};
+
+/**
+ * Handle menu item change events.
+ *
+ * @private
+ */
+OO.ui.ComboBoxInputWidget.prototype.onMenuItemsChange = function () {
+ var match = this.menu.getItemFromData( this.getValue() );
+ this.menu.selectItem( match );
+ if ( this.menu.getHighlightedItem() ) {
+ this.menu.highlightItem( match );
+ }
+ this.$element.toggleClass( 'oo-ui-comboBoxInputWidget-empty', this.menu.isEmpty() );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ComboBoxInputWidget.prototype.setDisabled = function ( disabled ) {
+ // Parent method
+ OO.ui.ComboBoxInputWidget.parent.prototype.setDisabled.call( this, disabled );
+
+ if ( this.dropdownButton ) {
+ this.dropdownButton.setDisabled( this.isDisabled() );
+ }
+ if ( this.menu ) {
+ this.menu.setDisabled( this.isDisabled() );
+ }
+
+ return this;
+};
+
+/**
+ * Set the options available for this input.
+ *
+ * @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`
+ * @chainable
+ */
+OO.ui.ComboBoxInputWidget.prototype.setOptions = function ( options ) {
+ this.getMenu()
+ .clearItems()
+ .addItems( options.map( function ( opt ) {
+ return new OO.ui.MenuOptionWidget( {
+ data: opt.data,
+ label: opt.label !== undefined ? opt.label : opt.data
+ } );
+ } ) );
+
+ return this;
+};
+
+/**
+ * FieldLayouts are used with OO.ui.FieldsetLayout. Each FieldLayout requires a field-widget,
+ * which is a widget that is specified by reference before any optional configuration settings.
+ *
+ * Field layouts can be configured with help text and/or labels. Labels are aligned in one of four ways:
+ *
+ * - **left**: The label is placed before the field-widget and aligned with the left margin.
+ * A left-alignment is used for forms with many fields.
+ * - **right**: The label is placed before the field-widget and aligned to the right margin.
+ * A right-alignment is used for long but familiar forms which users tab through,
+ * verifying the current field with a quick glance at the label.
+ * - **top**: The label is placed above the field-widget. A top-alignment is used for brief forms
+ * that users fill out from top to bottom.
+ * - **inline**: The label is placed after the field-widget and aligned to the left.
+ * An inline-alignment is best used with checkboxes or radio buttons.
+ *
+ * Help text is accessed via a help icon that appears in the upper right corner of the rendered field layout.
+ * Please see the [OOjs UI documentation on MediaWiki] [1] for examples and more information.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Layouts/Fields_and_Fieldsets
+ *
+ * @class
+ * @extends OO.ui.Layout
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.TitledElement
+ *
+ * @constructor
+ * @param {OO.ui.Widget} fieldWidget Field widget
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [align='left'] Alignment of the label: 'left', 'right', 'top' or 'inline'
+ * @cfg {Array} [errors] Error messages about the widget, which will be displayed below the widget.
+ * The array may contain strings or OO.ui.HtmlSnippet instances.
+ * @cfg {Array} [notices] Notices about the widget, which will be displayed below the widget.
+ * The array may contain strings or OO.ui.HtmlSnippet instances.
+ * @cfg {string|OO.ui.HtmlSnippet} [help] Help text. When help text is specified, a "help" icon will appear
+ * in the upper-right corner of the rendered field; clicking it will display the text in a popup.
+ * For important messages, you are advised to use `notices`, as they are always shown.
+ * @cfg {jQuery} [$overlay] Passed to OO.ui.PopupButtonWidget for help popup, if `help` is given.
+ * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.
+ *
+ * @throws {Error} An error is thrown if no widget is specified
+ */
+OO.ui.FieldLayout = function OoUiFieldLayout( fieldWidget, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( fieldWidget ) && config === undefined ) {
+ config = fieldWidget;
+ fieldWidget = config.fieldWidget;
+ }
+
+ // Make sure we have required constructor arguments
+ if ( fieldWidget === undefined ) {
+ throw new Error( 'Widget not found' );
+ }
+
+ // Configuration initialization
+ config = $.extend( { align: 'left' }, config );
+
+ // Parent constructor
+ OO.ui.FieldLayout.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.LabelElement.call( this, $.extend( {}, config, {
+ $label: $( '<label>' )
+ } ) );
+ OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$label } ) );
+
+ // Properties
+ this.fieldWidget = fieldWidget;
+ this.errors = [];
+ this.notices = [];
+ this.$field = this.isFieldInline() ? $( '<span>' ) : $( '<div>' );
+ this.$messages = $( '<ul>' );
+ this.$header = $( '<span>' );
+ this.$body = $( '<div>' );
+ this.align = null;
+ if ( config.help ) {
+ this.popupButtonWidget = new OO.ui.PopupButtonWidget( {
+ $overlay: config.$overlay,
+ popup: {
+ padded: true
+ },
+ classes: [ 'oo-ui-fieldLayout-help' ],
+ framed: false,
+ icon: 'info'
+ } );
+ if ( config.help instanceof OO.ui.HtmlSnippet ) {
+ this.popupButtonWidget.getPopup().$body.html( config.help.toString() );
+ } else {
+ this.popupButtonWidget.getPopup().$body.text( config.help );
+ }
+ this.$help = this.popupButtonWidget.$element;
+ } else {
+ this.$help = $( [] );
+ }
+
+ // Events
+ this.fieldWidget.connect( this, { disable: 'onFieldDisable' } );
+
+ // Initialization
+ if ( config.help ) {
+ // Set the 'aria-describedby' attribute on the fieldWidget
+ // Preference given to an input or a button
+ (
+ this.fieldWidget.$input ||
+ this.fieldWidget.$button ||
+ this.fieldWidget.$element
+ ).attr(
+ 'aria-describedby',
+ this.popupButtonWidget.getPopup().getBodyId()
+ );
+ }
+ if ( this.fieldWidget.getInputId() ) {
+ this.$label.attr( 'for', this.fieldWidget.getInputId() );
+ } else {
+ this.$label.on( 'click', function () {
+ this.fieldWidget.simulateLabelClick();
+ return false;
+ }.bind( this ) );
+ }
+ this.$element
+ .addClass( 'oo-ui-fieldLayout' )
+ .toggleClass( 'oo-ui-fieldLayout-disabled', this.fieldWidget.isDisabled() )
+ .append( this.$body );
+ this.$body.addClass( 'oo-ui-fieldLayout-body' );
+ this.$header.addClass( 'oo-ui-fieldLayout-header' );
+ this.$messages.addClass( 'oo-ui-fieldLayout-messages' );
+ this.$field
+ .addClass( 'oo-ui-fieldLayout-field' )
+ .append( this.fieldWidget.$element );
+
+ this.setErrors( config.errors || [] );
+ this.setNotices( config.notices || [] );
+ this.setAlignment( config.align );
+ // Call this again to take into account the widget's accessKey
+ this.updateTitle();
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.FieldLayout, OO.ui.Layout );
+OO.mixinClass( OO.ui.FieldLayout, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.FieldLayout, OO.ui.mixin.TitledElement );
+
+/* Methods */
+
+/**
+ * Handle field disable events.
+ *
+ * @private
+ * @param {boolean} value Field is disabled
+ */
+OO.ui.FieldLayout.prototype.onFieldDisable = function ( value ) {
+ this.$element.toggleClass( 'oo-ui-fieldLayout-disabled', value );
+};
+
+/**
+ * Get the widget contained by the field.
+ *
+ * @return {OO.ui.Widget} Field widget
+ */
+OO.ui.FieldLayout.prototype.getField = function () {
+ return this.fieldWidget;
+};
+
+/**
+ * Return `true` if the given field widget can be used with `'inline'` alignment (see
+ * #setAlignment). Return `false` if it can't or if this can't be determined.
+ *
+ * @return {boolean}
+ */
+OO.ui.FieldLayout.prototype.isFieldInline = function () {
+ // This is very simplistic, but should be good enough.
+ return this.getField().$element.prop( 'tagName' ).toLowerCase() === 'span';
+};
+
+/**
+ * @protected
+ * @param {string} kind 'error' or 'notice'
+ * @param {string|OO.ui.HtmlSnippet} text
+ * @return {jQuery}
+ */
+OO.ui.FieldLayout.prototype.makeMessage = function ( kind, text ) {
+ var $listItem, $icon, message;
+ $listItem = $( '<li>' );
+ if ( kind === 'error' ) {
+ $icon = new OO.ui.IconWidget( { icon: 'alert', flags: [ 'warning' ] } ).$element;
+ $listItem.attr( 'role', 'alert' );
+ } else if ( kind === 'notice' ) {
+ $icon = new OO.ui.IconWidget( { icon: 'info' } ).$element;
+ } else {
+ $icon = '';
+ }
+ message = new OO.ui.LabelWidget( { label: text } );
+ $listItem
+ .append( $icon, message.$element )
+ .addClass( 'oo-ui-fieldLayout-messages-' + kind );
+ return $listItem;
+};
+
+/**
+ * Set the field alignment mode.
+ *
+ * @private
+ * @param {string} value Alignment mode, either 'left', 'right', 'top' or 'inline'
+ * @chainable
+ */
+OO.ui.FieldLayout.prototype.setAlignment = function ( value ) {
+ if ( value !== this.align ) {
+ // Default to 'left'
+ if ( [ 'left', 'right', 'top', 'inline' ].indexOf( value ) === -1 ) {
+ value = 'left';
+ }
+ // Validate
+ if ( value === 'inline' && !this.isFieldInline() ) {
+ value = 'top';
+ }
+ // Reorder elements
+ if ( value === 'top' ) {
+ this.$header.append( this.$label, this.$help );
+ this.$body.append( this.$header, this.$field );
+ } else if ( value === 'inline' ) {
+ this.$header.append( this.$label, this.$help );
+ this.$body.append( this.$field, this.$header );
+ } else {
+ this.$header.append( this.$label );
+ this.$body.append( this.$header, this.$help, this.$field );
+ }
+ // Set classes. The following classes can be used here:
+ // * oo-ui-fieldLayout-align-left
+ // * oo-ui-fieldLayout-align-right
+ // * oo-ui-fieldLayout-align-top
+ // * oo-ui-fieldLayout-align-inline
+ if ( this.align ) {
+ this.$element.removeClass( 'oo-ui-fieldLayout-align-' + this.align );
+ }
+ this.$element.addClass( 'oo-ui-fieldLayout-align-' + value );
+ this.align = value;
+ }
+
+ return this;
+};
+
+/**
+ * Set the list of error messages.
+ *
+ * @param {Array} errors Error messages about the widget, which will be displayed below the widget.
+ * The array may contain strings or OO.ui.HtmlSnippet instances.
+ * @chainable
+ */
+OO.ui.FieldLayout.prototype.setErrors = function ( errors ) {
+ this.errors = errors.slice();
+ this.updateMessages();
+ return this;
+};
+
+/**
+ * Set the list of notice messages.
+ *
+ * @param {Array} notices Notices about the widget, which will be displayed below the widget.
+ * The array may contain strings or OO.ui.HtmlSnippet instances.
+ * @chainable
+ */
+OO.ui.FieldLayout.prototype.setNotices = function ( notices ) {
+ this.notices = notices.slice();
+ this.updateMessages();
+ return this;
+};
+
+/**
+ * Update the rendering of error and notice messages.
+ *
+ * @private
+ */
+OO.ui.FieldLayout.prototype.updateMessages = function () {
+ var i;
+ this.$messages.empty();
+
+ if ( this.errors.length || this.notices.length ) {
+ this.$body.after( this.$messages );
+ } else {
+ this.$messages.remove();
+ return;
+ }
+
+ for ( i = 0; i < this.notices.length; i++ ) {
+ this.$messages.append( this.makeMessage( 'notice', this.notices[ i ] ) );
+ }
+ for ( i = 0; i < this.errors.length; i++ ) {
+ this.$messages.append( this.makeMessage( 'error', this.errors[ i ] ) );
+ }
+};
+
+/**
+ * Include information about the widget's accessKey in our title. TitledElement calls this method.
+ * (This is a bit of a hack.)
+ *
+ * @protected
+ * @param {string} title Tooltip label for 'title' attribute
+ * @return {string}
+ */
+OO.ui.FieldLayout.prototype.formatTitleWithAccessKey = function ( title ) {
+ if ( this.fieldWidget && this.fieldWidget.formatTitleWithAccessKey ) {
+ return this.fieldWidget.formatTitleWithAccessKey( title );
+ }
+ return title;
+};
+
+/**
+ * ActionFieldLayouts are used with OO.ui.FieldsetLayout. The layout consists of a field-widget, a button,
+ * and an optional label and/or help text. The field-widget (e.g., a {@link OO.ui.TextInputWidget TextInputWidget}),
+ * is required and is specified before any optional configuration settings.
+ *
+ * Labels can be aligned in one of four ways:
+ *
+ * - **left**: The label is placed before the field-widget and aligned with the left margin.
+ * A left-alignment is used for forms with many fields.
+ * - **right**: The label is placed before the field-widget and aligned to the right margin.
+ * A right-alignment is used for long but familiar forms which users tab through,
+ * verifying the current field with a quick glance at the label.
+ * - **top**: The label is placed above the field-widget. A top-alignment is used for brief forms
+ * that users fill out from top to bottom.
+ * - **inline**: The label is placed after the field-widget and aligned to the left.
+ * An inline-alignment is best used with checkboxes or radio buttons.
+ *
+ * Help text is accessed via a help icon that appears in the upper right corner of the rendered field layout when help
+ * text is specified.
+ *
+ * @example
+ * // Example of an ActionFieldLayout
+ * var actionFieldLayout = new OO.ui.ActionFieldLayout(
+ * new OO.ui.TextInputWidget( {
+ * placeholder: 'Field widget'
+ * } ),
+ * new OO.ui.ButtonWidget( {
+ * label: 'Button'
+ * } ),
+ * {
+ * label: 'An ActionFieldLayout. This label is aligned top',
+ * align: 'top',
+ * help: 'This is help text'
+ * }
+ * );
+ *
+ * $( 'body' ).append( actionFieldLayout.$element );
+ *
+ * @class
+ * @extends OO.ui.FieldLayout
+ *
+ * @constructor
+ * @param {OO.ui.Widget} fieldWidget Field widget
+ * @param {OO.ui.ButtonWidget} buttonWidget Button widget
+ * @param {Object} config
+ */
+OO.ui.ActionFieldLayout = function OoUiActionFieldLayout( fieldWidget, buttonWidget, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( fieldWidget ) && config === undefined ) {
+ config = fieldWidget;
+ fieldWidget = config.fieldWidget;
+ buttonWidget = config.buttonWidget;
+ }
+
+ // Parent constructor
+ OO.ui.ActionFieldLayout.parent.call( this, fieldWidget, config );
+
+ // Properties
+ this.buttonWidget = buttonWidget;
+ this.$button = $( '<span>' );
+ this.$input = this.isFieldInline() ? $( '<span>' ) : $( '<div>' );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-actionFieldLayout' );
+ this.$button
+ .addClass( 'oo-ui-actionFieldLayout-button' )
+ .append( this.buttonWidget.$element );
+ this.$input
+ .addClass( 'oo-ui-actionFieldLayout-input' )
+ .append( this.fieldWidget.$element );
+ this.$field
+ .append( this.$input, this.$button );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ActionFieldLayout, OO.ui.FieldLayout );
+
+/**
+ * FieldsetLayouts are composed of one or more {@link OO.ui.FieldLayout FieldLayouts},
+ * which each contain an individual widget and, optionally, a label. Each Fieldset can be
+ * configured with a label as well. For more information and examples,
+ * please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * @example
+ * // Example of a fieldset layout
+ * var input1 = new OO.ui.TextInputWidget( {
+ * placeholder: 'A text input field'
+ * } );
+ *
+ * var input2 = new OO.ui.TextInputWidget( {
+ * placeholder: 'A text input field'
+ * } );
+ *
+ * var fieldset = new OO.ui.FieldsetLayout( {
+ * label: 'Example of a fieldset layout'
+ * } );
+ *
+ * fieldset.addItems( [
+ * new OO.ui.FieldLayout( input1, {
+ * label: 'Field One'
+ * } ),
+ * new OO.ui.FieldLayout( input2, {
+ * label: 'Field Two'
+ * } )
+ * ] );
+ * $( 'body' ).append( fieldset.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Layouts/Fields_and_Fieldsets
+ *
+ * @class
+ * @extends OO.ui.Layout
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.FieldLayout[]} [items] An array of fields to add to the fieldset. See OO.ui.FieldLayout for more information about fields.
+ * @cfg {string|OO.ui.HtmlSnippet} [help] Help text. When help text is specified, a "help" icon will appear
+ * in the upper-right corner of the rendered field; clicking it will display the text in a popup.
+ * For important messages, you are advised to use `notices`, as they are always shown.
+ * @cfg {jQuery} [$overlay] Passed to OO.ui.PopupButtonWidget for help popup, if `help` is given.
+ * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.
+ */
+OO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.FieldsetLayout.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.GroupElement.call( this, config );
+
+ // Properties
+ this.$header = $( '<legend>' );
+ if ( config.help ) {
+ this.popupButtonWidget = new OO.ui.PopupButtonWidget( {
+ $overlay: config.$overlay,
+ popup: {
+ padded: true
+ },
+ classes: [ 'oo-ui-fieldsetLayout-help' ],
+ framed: false,
+ icon: 'info'
+ } );
+ if ( config.help instanceof OO.ui.HtmlSnippet ) {
+ this.popupButtonWidget.getPopup().$body.html( config.help.toString() );
+ } else {
+ this.popupButtonWidget.getPopup().$body.text( config.help );
+ }
+ this.$help = this.popupButtonWidget.$element;
+ } else {
+ this.$help = $( [] );
+ }
+
+ // Initialization
+ this.$header
+ .addClass( 'oo-ui-fieldsetLayout-header' )
+ .append( this.$icon, this.$label, this.$help );
+ this.$group.addClass( 'oo-ui-fieldsetLayout-group' );
+ this.$element
+ .addClass( 'oo-ui-fieldsetLayout' )
+ .prepend( this.$header, this.$group );
+ if ( Array.isArray( config.items ) ) {
+ this.addItems( config.items );
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.FieldsetLayout, OO.ui.Layout );
+OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.FieldsetLayout, OO.ui.mixin.GroupElement );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.FieldsetLayout.static.tagName = 'fieldset';
+
+/**
+ * FormLayouts are used to wrap {@link OO.ui.FieldsetLayout FieldsetLayouts} when you intend to use browser-based
+ * form submission for the fields instead of handling them in JavaScript. Form layouts can be configured with an
+ * HTML form action, an encoding type, and a method using the #action, #enctype, and #method configs, respectively.
+ * See the [OOjs UI documentation on MediaWiki] [1] for more information and examples.
+ *
+ * Only widgets from the {@link OO.ui.InputWidget InputWidget} family support form submission. It
+ * includes standard form elements like {@link OO.ui.CheckboxInputWidget checkboxes}, {@link
+ * OO.ui.RadioInputWidget radio buttons} and {@link OO.ui.TextInputWidget text fields}, as well as
+ * some fancier controls. Some controls have both regular and InputWidget variants, for example
+ * OO.ui.DropdownWidget and OO.ui.DropdownInputWidget – only the latter support form submission and
+ * often have simplified APIs to match the capabilities of HTML forms.
+ * See the [OOjs UI Inputs documentation on MediaWiki] [2] for more information about InputWidgets.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Layouts/Forms
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
+ *
+ * @example
+ * // Example of a form layout that wraps a fieldset layout
+ * var input1 = new OO.ui.TextInputWidget( {
+ * placeholder: 'Username'
+ * } );
+ * var input2 = new OO.ui.TextInputWidget( {
+ * placeholder: 'Password',
+ * type: 'password'
+ * } );
+ * var submit = new OO.ui.ButtonInputWidget( {
+ * label: 'Submit'
+ * } );
+ *
+ * var fieldset = new OO.ui.FieldsetLayout( {
+ * label: 'A form layout'
+ * } );
+ * fieldset.addItems( [
+ * new OO.ui.FieldLayout( input1, {
+ * label: 'Username',
+ * align: 'top'
+ * } ),
+ * new OO.ui.FieldLayout( input2, {
+ * label: 'Password',
+ * align: 'top'
+ * } ),
+ * new OO.ui.FieldLayout( submit )
+ * ] );
+ * var form = new OO.ui.FormLayout( {
+ * items: [ fieldset ],
+ * action: '/api/formhandler',
+ * method: 'get'
+ * } )
+ * $( 'body' ).append( form.$element );
+ *
+ * @class
+ * @extends OO.ui.Layout
+ * @mixins OO.ui.mixin.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [method] HTML form `method` attribute
+ * @cfg {string} [action] HTML form `action` attribute
+ * @cfg {string} [enctype] HTML form `enctype` attribute
+ * @cfg {OO.ui.FieldsetLayout[]} [items] Fieldset layouts to add to the form layout.
+ */
+OO.ui.FormLayout = function OoUiFormLayout( config ) {
+ var action;
+
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.FormLayout.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.GroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );
+
+ // Events
+ this.$element.on( 'submit', this.onFormSubmit.bind( this ) );
+
+ // Make sure the action is safe
+ action = config.action;
+ if ( action !== undefined && !OO.ui.isSafeUrl( action ) ) {
+ action = './' + action;
+ }
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-formLayout' )
+ .attr( {
+ method: config.method,
+ action: action,
+ enctype: config.enctype
+ } );
+ if ( Array.isArray( config.items ) ) {
+ this.addItems( config.items );
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.FormLayout, OO.ui.Layout );
+OO.mixinClass( OO.ui.FormLayout, OO.ui.mixin.GroupElement );
+
+/* Events */
+
+/**
+ * A 'submit' event is emitted when the form is submitted.
+ *
+ * @event submit
+ */
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.FormLayout.static.tagName = 'form';
+
+/* Methods */
+
+/**
+ * Handle form submit events.
+ *
+ * @private
+ * @param {jQuery.Event} e Submit event
+ * @fires submit
+ */
+OO.ui.FormLayout.prototype.onFormSubmit = function () {
+ if ( this.emit( 'submit' ) ) {
+ return false;
+ }
+};
+
+/**
+ * PanelLayouts expand to cover the entire area of their parent. They can be configured with scrolling, padding,
+ * and a frame, and are often used together with {@link OO.ui.StackLayout StackLayouts}.
+ *
+ * @example
+ * // Example of a panel layout
+ * var panel = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * framed: true,
+ * padded: true,
+ * $content: $( '<p>A panel layout with padding and a frame.</p>' )
+ * } );
+ * $( 'body' ).append( panel.$element );
+ *
+ * @class
+ * @extends OO.ui.Layout
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [scrollable=false] Allow vertical scrolling
+ * @cfg {boolean} [padded=false] Add padding between the content and the edges of the panel.
+ * @cfg {boolean} [expanded=true] Expand the panel to fill the entire parent element.
+ * @cfg {boolean} [framed=false] Render the panel with a frame to visually separate it from outside content.
+ */
+OO.ui.PanelLayout = function OoUiPanelLayout( config ) {
+ // Configuration initialization
+ config = $.extend( {
+ scrollable: false,
+ padded: false,
+ expanded: true,
+ framed: false
+ }, config );
+
+ // Parent constructor
+ OO.ui.PanelLayout.parent.call( this, config );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-panelLayout' );
+ if ( config.scrollable ) {
+ this.$element.addClass( 'oo-ui-panelLayout-scrollable' );
+ }
+ if ( config.padded ) {
+ this.$element.addClass( 'oo-ui-panelLayout-padded' );
+ }
+ if ( config.expanded ) {
+ this.$element.addClass( 'oo-ui-panelLayout-expanded' );
+ }
+ if ( config.framed ) {
+ this.$element.addClass( 'oo-ui-panelLayout-framed' );
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PanelLayout, OO.ui.Layout );
+
+/* Methods */
+
+/**
+ * Focus the panel layout
+ *
+ * The default implementation just focuses the first focusable element in the panel
+ */
+OO.ui.PanelLayout.prototype.focus = function () {
+ OO.ui.findFocusable( this.$element ).focus();
+};
+
+/**
+ * HorizontalLayout arranges its contents in a single line (using `display: inline-block` for its
+ * items), with small margins between them. Convenient when you need to put a number of block-level
+ * widgets on a single line next to each other.
+ *
+ * Note that inline elements, such as OO.ui.ButtonWidgets, do not need this wrapper.
+ *
+ * @example
+ * // HorizontalLayout with a text input and a label
+ * var layout = new OO.ui.HorizontalLayout( {
+ * items: [
+ * new OO.ui.LabelWidget( { label: 'Label' } ),
+ * new OO.ui.TextInputWidget( { value: 'Text' } )
+ * ]
+ * } );
+ * $( 'body' ).append( layout.$element );
+ *
+ * @class
+ * @extends OO.ui.Layout
+ * @mixins OO.ui.mixin.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.ui.Widget[]|OO.ui.Layout[]} [items] Widgets or other layouts to add to the layout.
+ */
+OO.ui.HorizontalLayout = function OoUiHorizontalLayout( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.HorizontalLayout.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.GroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-horizontalLayout' );
+ if ( Array.isArray( config.items ) ) {
+ this.addItems( config.items );
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.HorizontalLayout, OO.ui.Layout );
+OO.mixinClass( OO.ui.HorizontalLayout, OO.ui.mixin.GroupElement );
+
+}( OO ) );
+
+//# sourceMappingURL=oojs-ui-core.js.map \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-core.js.map b/www/wiki/resources/lib/oojs-ui/oojs-ui-core.js.map
new file mode 100644
index 00000000..f31a5a52
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-core.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/intro.js.txt","../src/core.js","../src/mixin.js","../src/Element.js","../src/HtmlSnippet.js","../src/Layout.js","../src/Widget.js","../src/Theme.js","../src/mixins/TabIndexedElement.js","../src/mixins/ButtonElement.js","../src/mixins/GroupElement.js","../src/mixins/IconElement.js","../src/mixins/IndicatorElement.js","../src/mixins/LabelElement.js","../src/mixins/FlaggedElement.js","../src/mixins/TitledElement.js","../src/mixins/AccessKeyedElement.js","../src/widgets/ButtonWidget.js","../src/widgets/ButtonGroupWidget.js","../src/widgets/IconWidget.js","../src/widgets/IndicatorWidget.js","../src/widgets/LabelWidget.js","../src/mixins/PendingElement.js","../src/mixins/FloatableElement.js","../src/mixins/ClippableElement.js","../src/widgets/PopupWidget.js","../src/mixins/PopupElement.js","../src/widgets/PopupButtonWidget.js","../src/mixins/GroupWidget.js","../src/mixins/ItemWidget.js","../src/widgets/OptionWidget.js","../src/widgets/SelectWidget.js","../src/widgets/DecoratedOptionWidget.js","../src/widgets/MenuOptionWidget.js","../src/widgets/MenuSectionOptionWidget.js","../src/widgets/MenuSelectWidget.js","../src/widgets/DropdownWidget.js","../src/widgets/RadioOptionWidget.js","../src/widgets/RadioSelectWidget.js","../src/widgets/MultioptionWidget.js","../src/widgets/MultiselectWidget.js","../src/widgets/CheckboxMultioptionWidget.js","../src/widgets/CheckboxMultiselectWidget.js","../src/widgets/ProgressBarWidget.js","../src/widgets/InputWidget.js","../src/widgets/HiddenInputWidget.js","../src/widgets/ButtonInputWidget.js","../src/widgets/CheckboxInputWidget.js","../src/widgets/DropdownInputWidget.js","../src/widgets/RadioInputWidget.js","../src/widgets/RadioSelectInputWidget.js","../src/widgets/CheckboxMultiselectInputWidget.js","../src/widgets/TextInputWidget.js","../src/widgets/SearchInputWidget.js","../src/widgets/MultilineTextInputWidget.js","../src/widgets/ComboBoxInputWidget.js","../src/layouts/FieldLayout.js","../src/layouts/ActionFieldLayout.js","../src/layouts/FieldsetLayout.js","../src/layouts/FormLayout.js","../src/layouts/PanelLayout.js","../src/layouts/HorizontalLayout.js","../src/outro.js.txt"],"names":[],"mappings":"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","file":"oojs-ui-core.js","sourcesContent":["( function ( OO ) {\n\n'use strict';\n","/**\n * Namespace for all classes, static methods and static properties.\n *\n * @class\n * @singleton\n */\nOO.ui = {};\n\nOO.ui.bind = $.proxy;\n\n/**\n * @property {Object}\n */\nOO.ui.Keys = {\n\tUNDEFINED: 0,\n\tBACKSPACE: 8,\n\tDELETE: 46,\n\tLEFT: 37,\n\tRIGHT: 39,\n\tUP: 38,\n\tDOWN: 40,\n\tENTER: 13,\n\tEND: 35,\n\tHOME: 36,\n\tTAB: 9,\n\tPAGEUP: 33,\n\tPAGEDOWN: 34,\n\tESCAPE: 27,\n\tSHIFT: 16,\n\tSPACE: 32\n};\n\n/**\n * Constants for MouseEvent.which\n *\n * @property {Object}\n */\nOO.ui.MouseButtons = {\n\tLEFT: 1,\n\tMIDDLE: 2,\n\tRIGHT: 3\n};\n\n/**\n * @property {number}\n * @private\n */\nOO.ui.elementId = 0;\n\n/**\n * Generate a unique ID for element\n *\n * @return {string} ID\n */\nOO.ui.generateElementId = function () {\n\tOO.ui.elementId++;\n\treturn 'oojsui-' + OO.ui.elementId;\n};\n\n/**\n * Check if an element is focusable.\n * Inspired by :focusable in jQueryUI v1.11.4 - 2015-04-14\n *\n * @param {jQuery} $element Element to test\n * @return {boolean} Element is focusable\n */\nOO.ui.isFocusableElement = function ( $element ) {\n\tvar nodeName,\n\t\telement = $element[ 0 ];\n\n\t// Anything disabled is not focusable\n\tif ( element.disabled ) {\n\t\treturn false;\n\t}\n\n\t// Check if the element is visible\n\tif ( !(\n\t\t// This is quicker than calling $element.is( ':visible' )\n\t\t$.expr.pseudos.visible( element ) &&\n\t\t// Check that all parents are visible\n\t\t!$element.parents().addBack().filter( function () {\n\t\t\treturn $.css( this, 'visibility' ) === 'hidden';\n\t\t} ).length\n\t) ) {\n\t\treturn false;\n\t}\n\n\t// Check if the element is ContentEditable, which is the string 'true'\n\tif ( element.contentEditable === 'true' ) {\n\t\treturn true;\n\t}\n\n\t// Anything with a non-negative numeric tabIndex is focusable.\n\t// Use .prop to avoid browser bugs\n\tif ( $element.prop( 'tabIndex' ) >= 0 ) {\n\t\treturn true;\n\t}\n\n\t// Some element types are naturally focusable\n\t// (indexOf is much faster than regex in Chrome and about the\n\t// same in FF: https://jsperf.com/regex-vs-indexof-array2)\n\tnodeName = element.nodeName.toLowerCase();\n\tif ( [ 'input', 'select', 'textarea', 'button', 'object' ].indexOf( nodeName ) !== -1 ) {\n\t\treturn true;\n\t}\n\n\t// Links and areas are focusable if they have an href\n\tif ( ( nodeName === 'a' || nodeName === 'area' ) && $element.attr( 'href' ) !== undefined ) {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\n/**\n * Find a focusable child\n *\n * @param {jQuery} $container Container to search in\n * @param {boolean} [backwards] Search backwards\n * @return {jQuery} Focusable child, or an empty jQuery object if none found\n */\nOO.ui.findFocusable = function ( $container, backwards ) {\n\tvar $focusable = $( [] ),\n\t\t// $focusableCandidates is a superset of things that\n\t\t// could get matched by isFocusableElement\n\t\t$focusableCandidates = $container\n\t\t\t.find( 'input, select, textarea, button, object, a, area, [contenteditable], [tabindex]' );\n\n\tif ( backwards ) {\n\t\t$focusableCandidates = Array.prototype.reverse.call( $focusableCandidates );\n\t}\n\n\t$focusableCandidates.each( function () {\n\t\tvar $this = $( this );\n\t\tif ( OO.ui.isFocusableElement( $this ) ) {\n\t\t\t$focusable = $this;\n\t\t\treturn false;\n\t\t}\n\t} );\n\treturn $focusable;\n};\n\n/**\n * Get the user's language and any fallback languages.\n *\n * These language codes are used to localize user interface elements in the user's language.\n *\n * In environments that provide a localization system, this function should be overridden to\n * return the user's language(s). The default implementation returns English (en) only.\n *\n * @return {string[]} Language codes, in descending order of priority\n */\nOO.ui.getUserLanguages = function () {\n\treturn [ 'en' ];\n};\n\n/**\n * Get a value in an object keyed by language code.\n *\n * @param {Object.<string,Mixed>} obj Object keyed by language code\n * @param {string|null} [lang] Language code, if omitted or null defaults to any user language\n * @param {string} [fallback] Fallback code, used if no matching language can be found\n * @return {Mixed} Local value\n */\nOO.ui.getLocalValue = function ( obj, lang, fallback ) {\n\tvar i, len, langs;\n\n\t// Requested language\n\tif ( obj[ lang ] ) {\n\t\treturn obj[ lang ];\n\t}\n\t// Known user language\n\tlangs = OO.ui.getUserLanguages();\n\tfor ( i = 0, len = langs.length; i < len; i++ ) {\n\t\tlang = langs[ i ];\n\t\tif ( obj[ lang ] ) {\n\t\t\treturn obj[ lang ];\n\t\t}\n\t}\n\t// Fallback language\n\tif ( obj[ fallback ] ) {\n\t\treturn obj[ fallback ];\n\t}\n\t// First existing language\n\tfor ( lang in obj ) {\n\t\treturn obj[ lang ];\n\t}\n\n\treturn undefined;\n};\n\n/**\n * Check if a node is contained within another node\n *\n * Similar to jQuery#contains except a list of containers can be supplied\n * and a boolean argument allows you to include the container in the match list\n *\n * @param {HTMLElement|HTMLElement[]} containers Container node(s) to search in\n * @param {HTMLElement} contained Node to find\n * @param {boolean} [matchContainers] Include the container(s) in the list of nodes to match, otherwise only match descendants\n * @return {boolean} The node is in the list of target nodes\n */\nOO.ui.contains = function ( containers, contained, matchContainers ) {\n\tvar i;\n\tif ( !Array.isArray( containers ) ) {\n\t\tcontainers = [ containers ];\n\t}\n\tfor ( i = containers.length - 1; i >= 0; i-- ) {\n\t\tif ( ( matchContainers && contained === containers[ i ] ) || $.contains( containers[ i ], contained ) ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\treturn false;\n};\n\n/**\n * Return a function, that, as long as it continues to be invoked, will not\n * be triggered. The function will be called after it stops being called for\n * N milliseconds. If `immediate` is passed, trigger the function on the\n * leading edge, instead of the trailing.\n *\n * Ported from: http://underscorejs.org/underscore.js\n *\n * @param {Function} func Function to debounce\n * @param {number} [wait=0] Wait period in milliseconds\n * @param {boolean} [immediate] Trigger on leading edge\n * @return {Function} Debounced function\n */\nOO.ui.debounce = function ( func, wait, immediate ) {\n\tvar timeout;\n\treturn function () {\n\t\tvar context = this,\n\t\t\targs = arguments,\n\t\t\tlater = function () {\n\t\t\t\ttimeout = null;\n\t\t\t\tif ( !immediate ) {\n\t\t\t\t\tfunc.apply( context, args );\n\t\t\t\t}\n\t\t\t};\n\t\tif ( immediate && !timeout ) {\n\t\t\tfunc.apply( context, args );\n\t\t}\n\t\tif ( !timeout || wait ) {\n\t\t\tclearTimeout( timeout );\n\t\t\ttimeout = setTimeout( later, wait );\n\t\t}\n\t};\n};\n\n/**\n * Puts a console warning with provided message.\n *\n * @param {string} message Message\n */\nOO.ui.warnDeprecation = function ( message ) {\n\tif ( OO.getProp( window, 'console', 'warn' ) !== undefined ) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.warn( message );\n\t}\n};\n\n/**\n * Returns a function, that, when invoked, will only be triggered at most once\n * during a given window of time. If called again during that window, it will\n * wait until the window ends and then trigger itself again.\n *\n * As it's not knowable to the caller whether the function will actually run\n * when the wrapper is called, return values from the function are entirely\n * discarded.\n *\n * @param {Function} func Function to throttle\n * @param {number} wait Throttle window length, in milliseconds\n * @return {Function} Throttled function\n */\nOO.ui.throttle = function ( func, wait ) {\n\tvar context, args, timeout,\n\t\tprevious = 0,\n\t\trun = function () {\n\t\t\ttimeout = null;\n\t\t\tprevious = OO.ui.now();\n\t\t\tfunc.apply( context, args );\n\t\t};\n\treturn function () {\n\t\t// Check how long it's been since the last time the function was\n\t\t// called, and whether it's more or less than the requested throttle\n\t\t// period. If it's less, run the function immediately. If it's more,\n\t\t// set a timeout for the remaining time -- but don't replace an\n\t\t// existing timeout, since that'd indefinitely prolong the wait.\n\t\tvar remaining = wait - ( OO.ui.now() - previous );\n\t\tcontext = this;\n\t\targs = arguments;\n\t\tif ( remaining <= 0 ) {\n\t\t\t// Note: unless wait was ridiculously large, this means we'll\n\t\t\t// automatically run the first time the function was called in a\n\t\t\t// given period. (If you provide a wait period larger than the\n\t\t\t// current Unix timestamp, you *deserve* unexpected behavior.)\n\t\t\tclearTimeout( timeout );\n\t\t\trun();\n\t\t} else if ( !timeout ) {\n\t\t\ttimeout = setTimeout( run, remaining );\n\t\t}\n\t};\n};\n\n/**\n * A (possibly faster) way to get the current timestamp as an integer\n *\n * @return {number} Current timestamp, in milliseconds since the Unix epoch\n */\nOO.ui.now = Date.now || function () {\n\treturn new Date().getTime();\n};\n\n/**\n * Reconstitute a JavaScript object corresponding to a widget created by\n * the PHP implementation.\n *\n * This is an alias for `OO.ui.Element.static.infuse()`.\n *\n * @param {string|HTMLElement|jQuery} idOrNode\n * A DOM id (if a string) or node for the widget to infuse.\n * @return {OO.ui.Element}\n * The `OO.ui.Element` corresponding to this (infusable) document node.\n */\nOO.ui.infuse = function ( idOrNode ) {\n\treturn OO.ui.Element.static.infuse( idOrNode );\n};\n\n( function () {\n\t/**\n\t * Message store for the default implementation of OO.ui.msg\n\t *\n\t * Environments that provide a localization system should not use this, but should override\n\t * OO.ui.msg altogether.\n\t *\n\t * @private\n\t */\n\tvar messages = {\n\t\t// Tool tip for a button that moves items in a list down one place\n\t\t'ooui-outline-control-move-down': 'Move item down',\n\t\t// Tool tip for a button that moves items in a list up one place\n\t\t'ooui-outline-control-move-up': 'Move item up',\n\t\t// Tool tip for a button that removes items from a list\n\t\t'ooui-outline-control-remove': 'Remove item',\n\t\t// Label for the toolbar group that contains a list of all other available tools\n\t\t'ooui-toolbar-more': 'More',\n\t\t// Label for the fake tool that expands the full list of tools in a toolbar group\n\t\t'ooui-toolgroup-expand': 'More',\n\t\t// Label for the fake tool that collapses the full list of tools in a toolbar group\n\t\t'ooui-toolgroup-collapse': 'Fewer',\n\t\t// Default label for the tooltip for the button that removes a tag item\n\t\t'ooui-item-remove': 'Remove',\n\t\t// Default label for the accept button of a confirmation dialog\n\t\t'ooui-dialog-message-accept': 'OK',\n\t\t// Default label for the reject button of a confirmation dialog\n\t\t'ooui-dialog-message-reject': 'Cancel',\n\t\t// Title for process dialog error description\n\t\t'ooui-dialog-process-error': 'Something went wrong',\n\t\t// Label for process dialog dismiss error button, visible when describing errors\n\t\t'ooui-dialog-process-dismiss': 'Dismiss',\n\t\t// Label for process dialog retry action button, visible when describing only recoverable errors\n\t\t'ooui-dialog-process-retry': 'Try again',\n\t\t// Label for process dialog retry action button, visible when describing only warnings\n\t\t'ooui-dialog-process-continue': 'Continue',\n\t\t// Label for the file selection widget's select file button\n\t\t'ooui-selectfile-button-select': 'Select a file',\n\t\t// Label for the file selection widget if file selection is not supported\n\t\t'ooui-selectfile-not-supported': 'File selection is not supported',\n\t\t// Label for the file selection widget when no file is currently selected\n\t\t'ooui-selectfile-placeholder': 'No file is selected',\n\t\t// Label for the file selection widget's drop target\n\t\t'ooui-selectfile-dragdrop-placeholder': 'Drop file here'\n\t};\n\n\t/**\n\t * Get a localized message.\n\t *\n\t * After the message key, message parameters may optionally be passed. In the default implementation,\n\t * any occurrences of $1 are replaced with the first parameter, $2 with the second parameter, etc.\n\t * Alternative implementations of OO.ui.msg may use any substitution system they like, as long as\n\t * they support unnamed, ordered message parameters.\n\t *\n\t * In environments that provide a localization system, this function should be overridden to\n\t * return the message translated in the user's language. The default implementation always returns\n\t * English messages. An example of doing this with [jQuery.i18n](https://github.com/wikimedia/jquery.i18n)\n\t * follows.\n\t *\n\t * @example\n\t * var i, iLen, button,\n\t * messagePath = 'oojs-ui/dist/i18n/',\n\t * languages = [ $.i18n().locale, 'ur', 'en' ],\n\t * languageMap = {};\n\t *\n\t * for ( i = 0, iLen = languages.length; i < iLen; i++ ) {\n\t * languageMap[ languages[ i ] ] = messagePath + languages[ i ].toLowerCase() + '.json';\n\t * }\n\t *\n\t * $.i18n().load( languageMap ).done( function() {\n\t * // Replace the built-in `msg` only once we've loaded the internationalization.\n\t * // OOjs UI uses `OO.ui.deferMsg` for all initially-loaded messages. So long as\n\t * // you put off creating any widgets until this promise is complete, no English\n\t * // will be displayed.\n\t * OO.ui.msg = $.i18n;\n\t *\n\t * // A button displaying \"OK\" in the default locale\n\t * button = new OO.ui.ButtonWidget( {\n\t * label: OO.ui.msg( 'ooui-dialog-message-accept' ),\n\t * icon: 'check'\n\t * } );\n\t * $( 'body' ).append( button.$element );\n\t *\n\t * // A button displaying \"OK\" in Urdu\n\t * $.i18n().locale = 'ur';\n\t * button = new OO.ui.ButtonWidget( {\n\t * label: OO.ui.msg( 'ooui-dialog-message-accept' ),\n\t * icon: 'check'\n\t * } );\n\t * $( 'body' ).append( button.$element );\n\t * } );\n\t *\n\t * @param {string} key Message key\n\t * @param {...Mixed} [params] Message parameters\n\t * @return {string} Translated message with parameters substituted\n\t */\n\tOO.ui.msg = function ( key ) {\n\t\tvar message = messages[ key ],\n\t\t\tparams = Array.prototype.slice.call( arguments, 1 );\n\t\tif ( typeof message === 'string' ) {\n\t\t\t// Perform $1 substitution\n\t\t\tmessage = message.replace( /\\$(\\d+)/g, function ( unused, n ) {\n\t\t\t\tvar i = parseInt( n, 10 );\n\t\t\t\treturn params[ i - 1 ] !== undefined ? params[ i - 1 ] : '$' + n;\n\t\t\t} );\n\t\t} else {\n\t\t\t// Return placeholder if message not found\n\t\t\tmessage = '[' + key + ']';\n\t\t}\n\t\treturn message;\n\t};\n}() );\n\n/**\n * Package a message and arguments for deferred resolution.\n *\n * Use this when you are statically specifying a message and the message may not yet be present.\n *\n * @param {string} key Message key\n * @param {...Mixed} [params] Message parameters\n * @return {Function} Function that returns the resolved message when executed\n */\nOO.ui.deferMsg = function () {\n\tvar args = arguments;\n\treturn function () {\n\t\treturn OO.ui.msg.apply( OO.ui, args );\n\t};\n};\n\n/**\n * Resolve a message.\n *\n * If the message is a function it will be executed, otherwise it will pass through directly.\n *\n * @param {Function|string} msg Deferred message, or message text\n * @return {string} Resolved message\n */\nOO.ui.resolveMsg = function ( msg ) {\n\tif ( $.isFunction( msg ) ) {\n\t\treturn msg();\n\t}\n\treturn msg;\n};\n\n/**\n * @param {string} url\n * @return {boolean}\n */\nOO.ui.isSafeUrl = function ( url ) {\n\t// Keep this function in sync with php/Tag.php\n\tvar i, protocolWhitelist;\n\n\tfunction stringStartsWith( haystack, needle ) {\n\t\treturn haystack.substr( 0, needle.length ) === needle;\n\t}\n\n\tprotocolWhitelist = [\n\t\t'bitcoin', 'ftp', 'ftps', 'geo', 'git', 'gopher', 'http', 'https', 'irc', 'ircs',\n\t\t'magnet', 'mailto', 'mms', 'news', 'nntp', 'redis', 'sftp', 'sip', 'sips', 'sms', 'ssh',\n\t\t'svn', 'tel', 'telnet', 'urn', 'worldwind', 'xmpp'\n\t];\n\n\tif ( url === '' ) {\n\t\treturn true;\n\t}\n\n\tfor ( i = 0; i < protocolWhitelist.length; i++ ) {\n\t\tif ( stringStartsWith( url, protocolWhitelist[ i ] + ':' ) ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\t// This matches '//' too\n\tif ( stringStartsWith( url, '/' ) || stringStartsWith( url, './' ) ) {\n\t\treturn true;\n\t}\n\tif ( stringStartsWith( url, '?' ) || stringStartsWith( url, '#' ) ) {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\n/**\n * Check if the user has a 'mobile' device.\n *\n * For our purposes this means the user is primarily using an\n * on-screen keyboard, touch input instead of a mouse and may\n * have a physically small display.\n *\n * It is left up to implementors to decide how to compute this\n * so the default implementation always returns false.\n *\n * @return {boolean} Use is on a mobile device\n */\nOO.ui.isMobile = function () {\n\treturn false;\n};\n","/*!\n * Mixin namespace.\n */\n\n/**\n * Namespace for OOjs UI mixins.\n *\n * Mixins are named according to the type of object they are intended to\n * be mixed in to. For example, OO.ui.mixin.GroupElement is intended to be\n * mixed in to an instance of OO.ui.Element, and OO.ui.mixin.GroupWidget\n * is intended to be mixed in to an instance of OO.ui.Widget.\n *\n * @class\n * @singleton\n */\nOO.ui.mixin = {};\n","/**\n * Each Element represents a rendering in the DOM—a button or an icon, for example, or anything\n * that is visible to a user. Unlike {@link OO.ui.Widget widgets}, plain elements usually do not have events\n * connected to them and can't be interacted with.\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string[]} [classes] The names of the CSS classes to apply to the element. CSS styles are added\n * to the top level (e.g., the outermost div) of the element. See the [OOjs UI documentation on MediaWiki][2]\n * for an example.\n * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches#cssExample\n * @cfg {string} [id] The HTML id attribute used in the rendered tag.\n * @cfg {string} [text] Text to insert\n * @cfg {Array} [content] An array of content elements to append (after #text).\n * Strings will be html-escaped; use an OO.ui.HtmlSnippet to append raw HTML.\n * Instances of OO.ui.Element will have their $element appended.\n * @cfg {jQuery} [$content] Content elements to append (after #text).\n * @cfg {jQuery} [$element] Wrapper element. Defaults to a new element with #getTagName.\n * @cfg {Mixed} [data] Custom data of any type or combination of types (e.g., string, number, array, object).\n * Data can also be specified with the #setData method.\n */\nOO.ui.Element = function OoUiElement( config ) {\n\tthis.initialConfig = config;\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.$ = $;\n\tthis.elementId = null;\n\tthis.visible = true;\n\tthis.data = config.data;\n\tthis.$element = config.$element ||\n\t\t$( document.createElement( this.getTagName() ) );\n\tthis.elementGroup = null;\n\n\t// Initialization\n\tif ( Array.isArray( config.classes ) ) {\n\t\tthis.$element.addClass( config.classes.join( ' ' ) );\n\t}\n\tif ( config.id ) {\n\t\tthis.setElementId( config.id );\n\t}\n\tif ( config.text ) {\n\t\tthis.$element.text( config.text );\n\t}\n\tif ( config.content ) {\n\t\t// The `content` property treats plain strings as text; use an\n\t\t// HtmlSnippet to append HTML content. `OO.ui.Element`s get their\n\t\t// appropriate $element appended.\n\t\tthis.$element.append( config.content.map( function ( v ) {\n\t\t\tif ( typeof v === 'string' ) {\n\t\t\t\t// Escape string so it is properly represented in HTML.\n\t\t\t\treturn document.createTextNode( v );\n\t\t\t} else if ( v instanceof OO.ui.HtmlSnippet ) {\n\t\t\t\t// Bypass escaping.\n\t\t\t\treturn v.toString();\n\t\t\t} else if ( v instanceof OO.ui.Element ) {\n\t\t\t\treturn v.$element;\n\t\t\t}\n\t\t\treturn v;\n\t\t} ) );\n\t}\n\tif ( config.$content ) {\n\t\t// The `$content` property treats plain strings as HTML.\n\t\tthis.$element.append( config.$content );\n\t}\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.Element );\n\n/* Static Properties */\n\n/**\n * The name of the HTML tag used by the element.\n *\n * The static value may be ignored if the #getTagName method is overridden.\n *\n * @static\n * @inheritable\n * @property {string}\n */\nOO.ui.Element.static.tagName = 'div';\n\n/* Static Methods */\n\n/**\n * Reconstitute a JavaScript object corresponding to a widget created\n * by the PHP implementation.\n *\n * @param {string|HTMLElement|jQuery} idOrNode\n * A DOM id (if a string) or node for the widget to infuse.\n * @return {OO.ui.Element}\n * The `OO.ui.Element` corresponding to this (infusable) document node.\n * For `Tag` objects emitted on the HTML side (used occasionally for content)\n * the value returned is a newly-created Element wrapping around the existing\n * DOM node.\n */\nOO.ui.Element.static.infuse = function ( idOrNode ) {\n\tvar obj = OO.ui.Element.static.unsafeInfuse( idOrNode, false );\n\t// Verify that the type matches up.\n\t// FIXME: uncomment after T89721 is fixed, see T90929.\n\t/*\n\tif ( !( obj instanceof this['class'] ) ) {\n\t\tthrow new Error( 'Infusion type mismatch!' );\n\t}\n\t*/\n\treturn obj;\n};\n\n/**\n * Implementation helper for `infuse`; skips the type check and has an\n * extra property so that only the top-level invocation touches the DOM.\n *\n * @private\n * @param {string|HTMLElement|jQuery} idOrNode\n * @param {jQuery.Promise|boolean} domPromise A promise that will be resolved\n * when the top-level widget of this infusion is inserted into DOM,\n * replacing the original node; or false for top-level invocation.\n * @return {OO.ui.Element}\n */\nOO.ui.Element.static.unsafeInfuse = function ( idOrNode, domPromise ) {\n\t// look for a cached result of a previous infusion.\n\tvar id, $elem, error, data, cls, parts, parent, obj, top, state, infusedChildren;\n\tif ( typeof idOrNode === 'string' ) {\n\t\tid = idOrNode;\n\t\t$elem = $( document.getElementById( id ) );\n\t} else {\n\t\t$elem = $( idOrNode );\n\t\tid = $elem.attr( 'id' );\n\t}\n\tif ( !$elem.length ) {\n\t\tif ( typeof idOrNode === 'string' ) {\n\t\t\terror = 'Widget not found: ' + idOrNode;\n\t\t} else if ( idOrNode && idOrNode.selector ) {\n\t\t\terror = 'Widget not found: ' + idOrNode.selector;\n\t\t} else {\n\t\t\terror = 'Widget not found';\n\t\t}\n\t\tthrow new Error( error );\n\t}\n\tif ( $elem[ 0 ].oouiInfused ) {\n\t\t$elem = $elem[ 0 ].oouiInfused;\n\t}\n\tdata = $elem.data( 'ooui-infused' );\n\tif ( data ) {\n\t\t// cached!\n\t\tif ( data === true ) {\n\t\t\tthrow new Error( 'Circular dependency! ' + id );\n\t\t}\n\t\tif ( domPromise ) {\n\t\t\t// pick up dynamic state, like focus, value of form inputs, scroll position, etc.\n\t\t\tstate = data.constructor.static.gatherPreInfuseState( $elem, data );\n\t\t\t// restore dynamic state after the new element is re-inserted into DOM under infused parent\n\t\t\tdomPromise.done( data.restorePreInfuseState.bind( data, state ) );\n\t\t\tinfusedChildren = $elem.data( 'ooui-infused-children' );\n\t\t\tif ( infusedChildren && infusedChildren.length ) {\n\t\t\t\tinfusedChildren.forEach( function ( data ) {\n\t\t\t\t\tvar state = data.constructor.static.gatherPreInfuseState( $elem, data );\n\t\t\t\t\tdomPromise.done( data.restorePreInfuseState.bind( data, state ) );\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\treturn data;\n\t}\n\tdata = $elem.attr( 'data-ooui' );\n\tif ( !data ) {\n\t\tthrow new Error( 'No infusion data found: ' + id );\n\t}\n\ttry {\n\t\tdata = JSON.parse( data );\n\t} catch ( _ ) {\n\t\tdata = null;\n\t}\n\tif ( !( data && data._ ) ) {\n\t\tthrow new Error( 'No valid infusion data found: ' + id );\n\t}\n\tif ( data._ === 'Tag' ) {\n\t\t// Special case: this is a raw Tag; wrap existing node, don't rebuild.\n\t\treturn new OO.ui.Element( { $element: $elem } );\n\t}\n\tparts = data._.split( '.' );\n\tcls = OO.getProp.apply( OO, [ window ].concat( parts ) );\n\tif ( cls === undefined ) {\n\t\tthrow new Error( 'Unknown widget type: id: ' + id + ', class: ' + data._ );\n\t}\n\n\t// Verify that we're creating an OO.ui.Element instance\n\tparent = cls.parent;\n\n\twhile ( parent !== undefined ) {\n\t\tif ( parent === OO.ui.Element ) {\n\t\t\t// Safe\n\t\t\tbreak;\n\t\t}\n\n\t\tparent = parent.parent;\n\t}\n\n\tif ( parent !== OO.ui.Element ) {\n\t\tthrow new Error( 'Unknown widget type: id: ' + id + ', class: ' + data._ );\n\t}\n\n\tif ( domPromise === false ) {\n\t\ttop = $.Deferred();\n\t\tdomPromise = top.promise();\n\t}\n\t$elem.data( 'ooui-infused', true ); // prevent loops\n\tdata.id = id; // implicit\n\tinfusedChildren = [];\n\tdata = OO.copy( data, null, function deserialize( value ) {\n\t\tvar infused;\n\t\tif ( OO.isPlainObject( value ) ) {\n\t\t\tif ( value.tag ) {\n\t\t\t\tinfused = OO.ui.Element.static.unsafeInfuse( value.tag, domPromise );\n\t\t\t\tinfusedChildren.push( infused );\n\t\t\t\t// Flatten the structure\n\t\t\t\tinfusedChildren.push.apply( infusedChildren, infused.$element.data( 'ooui-infused-children' ) || [] );\n\t\t\t\tinfused.$element.removeData( 'ooui-infused-children' );\n\t\t\t\treturn infused;\n\t\t\t}\n\t\t\tif ( value.html !== undefined ) {\n\t\t\t\treturn new OO.ui.HtmlSnippet( value.html );\n\t\t\t}\n\t\t}\n\t} );\n\t// allow widgets to reuse parts of the DOM\n\tdata = cls.static.reusePreInfuseDOM( $elem[ 0 ], data );\n\t// pick up dynamic state, like focus, value of form inputs, scroll position, etc.\n\tstate = cls.static.gatherPreInfuseState( $elem[ 0 ], data );\n\t// rebuild widget\n\t// eslint-disable-next-line new-cap\n\tobj = new cls( data );\n\t// now replace old DOM with this new DOM.\n\tif ( top ) {\n\t\t// An efficient constructor might be able to reuse the entire DOM tree of the original element,\n\t\t// so only mutate the DOM if we need to.\n\t\tif ( $elem[ 0 ] !== obj.$element[ 0 ] ) {\n\t\t\t$elem.replaceWith( obj.$element );\n\t\t\t// This element is now gone from the DOM, but if anyone is holding a reference to it,\n\t\t\t// let's allow them to OO.ui.infuse() it and do what they expect, see T105828.\n\t\t\t// Do not use jQuery.data(), as using it on detached nodes leaks memory in 1.x line by design.\n\t\t\t$elem[ 0 ].oouiInfused = obj.$element;\n\t\t}\n\t\ttop.resolve();\n\t}\n\tobj.$element.data( 'ooui-infused', obj );\n\tobj.$element.data( 'ooui-infused-children', infusedChildren );\n\t// set the 'data-ooui' attribute so we can identify infused widgets\n\tobj.$element.attr( 'data-ooui', '' );\n\t// restore dynamic state after the new element is inserted into DOM\n\tdomPromise.done( obj.restorePreInfuseState.bind( obj, state ) );\n\treturn obj;\n};\n\n/**\n * Pick out parts of `node`'s DOM to be reused when infusing a widget.\n *\n * This method **must not** make any changes to the DOM, only find interesting pieces and add them\n * to `config` (which should then be returned). Actual DOM juggling should then be done by the\n * constructor, which will be given the enhanced config.\n *\n * @protected\n * @param {HTMLElement} node\n * @param {Object} config\n * @return {Object}\n */\nOO.ui.Element.static.reusePreInfuseDOM = function ( node, config ) {\n\treturn config;\n};\n\n/**\n * Gather the dynamic state (focus, value of form inputs, scroll position, etc.) of an HTML DOM node\n * (and its children) that represent an Element of the same class and the given configuration,\n * generated by the PHP implementation.\n *\n * This method is called just before `node` is detached from the DOM. The return value of this\n * function will be passed to #restorePreInfuseState after the newly created widget's #$element\n * is inserted into DOM to replace `node`.\n *\n * @protected\n * @param {HTMLElement} node\n * @param {Object} config\n * @return {Object}\n */\nOO.ui.Element.static.gatherPreInfuseState = function () {\n\treturn {};\n};\n\n/**\n * Get a jQuery function within a specific document.\n *\n * @static\n * @param {jQuery|HTMLElement|HTMLDocument|Window} context Context to bind the function to\n * @param {jQuery} [$iframe] HTML iframe element that contains the document, omit if document is\n * not in an iframe\n * @return {Function} Bound jQuery function\n */\nOO.ui.Element.static.getJQuery = function ( context, $iframe ) {\n\tfunction wrapper( selector ) {\n\t\treturn $( selector, wrapper.context );\n\t}\n\n\twrapper.context = this.getDocument( context );\n\n\tif ( $iframe ) {\n\t\twrapper.$iframe = $iframe;\n\t}\n\n\treturn wrapper;\n};\n\n/**\n * Get the document of an element.\n *\n * @static\n * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Object to get the document for\n * @return {HTMLDocument|null} Document object\n */\nOO.ui.Element.static.getDocument = function ( obj ) {\n\t// jQuery - selections created \"offscreen\" won't have a context, so .context isn't reliable\n\treturn ( obj[ 0 ] && obj[ 0 ].ownerDocument ) ||\n\t\t// Empty jQuery selections might have a context\n\t\tobj.context ||\n\t\t// HTMLElement\n\t\tobj.ownerDocument ||\n\t\t// Window\n\t\tobj.document ||\n\t\t// HTMLDocument\n\t\t( obj.nodeType === Node.DOCUMENT_NODE && obj ) ||\n\t\tnull;\n};\n\n/**\n * Get the window of an element or document.\n *\n * @static\n * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the window for\n * @return {Window} Window object\n */\nOO.ui.Element.static.getWindow = function ( obj ) {\n\tvar doc = this.getDocument( obj );\n\treturn doc.defaultView;\n};\n\n/**\n * Get the direction of an element or document.\n *\n * @static\n * @param {jQuery|HTMLElement|HTMLDocument|Window} obj Context to get the direction for\n * @return {string} Text direction, either 'ltr' or 'rtl'\n */\nOO.ui.Element.static.getDir = function ( obj ) {\n\tvar isDoc, isWin;\n\n\tif ( obj instanceof jQuery ) {\n\t\tobj = obj[ 0 ];\n\t}\n\tisDoc = obj.nodeType === Node.DOCUMENT_NODE;\n\tisWin = obj.document !== undefined;\n\tif ( isDoc || isWin ) {\n\t\tif ( isWin ) {\n\t\t\tobj = obj.document;\n\t\t}\n\t\tobj = obj.body;\n\t}\n\treturn $( obj ).css( 'direction' );\n};\n\n/**\n * Get the offset between two frames.\n *\n * TODO: Make this function not use recursion.\n *\n * @static\n * @param {Window} from Window of the child frame\n * @param {Window} [to=window] Window of the parent frame\n * @param {Object} [offset] Offset to start with, used internally\n * @return {Object} Offset object, containing left and top properties\n */\nOO.ui.Element.static.getFrameOffset = function ( from, to, offset ) {\n\tvar i, len, frames, frame, rect;\n\n\tif ( !to ) {\n\t\tto = window;\n\t}\n\tif ( !offset ) {\n\t\toffset = { top: 0, left: 0 };\n\t}\n\tif ( from.parent === from ) {\n\t\treturn offset;\n\t}\n\n\t// Get iframe element\n\tframes = from.parent.document.getElementsByTagName( 'iframe' );\n\tfor ( i = 0, len = frames.length; i < len; i++ ) {\n\t\tif ( frames[ i ].contentWindow === from ) {\n\t\t\tframe = frames[ i ];\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Recursively accumulate offset values\n\tif ( frame ) {\n\t\trect = frame.getBoundingClientRect();\n\t\toffset.left += rect.left;\n\t\toffset.top += rect.top;\n\t\tif ( from !== to ) {\n\t\t\tthis.getFrameOffset( from.parent, offset );\n\t\t}\n\t}\n\treturn offset;\n};\n\n/**\n * Get the offset between two elements.\n *\n * The two elements may be in a different frame, but in that case the frame $element is in must\n * be contained in the frame $anchor is in.\n *\n * @static\n * @param {jQuery} $element Element whose position to get\n * @param {jQuery} $anchor Element to get $element's position relative to\n * @return {Object} Translated position coordinates, containing top and left properties\n */\nOO.ui.Element.static.getRelativePosition = function ( $element, $anchor ) {\n\tvar iframe, iframePos,\n\t\tpos = $element.offset(),\n\t\tanchorPos = $anchor.offset(),\n\t\telementDocument = this.getDocument( $element ),\n\t\tanchorDocument = this.getDocument( $anchor );\n\n\t// If $element isn't in the same document as $anchor, traverse up\n\twhile ( elementDocument !== anchorDocument ) {\n\t\tiframe = elementDocument.defaultView.frameElement;\n\t\tif ( !iframe ) {\n\t\t\tthrow new Error( '$element frame is not contained in $anchor frame' );\n\t\t}\n\t\tiframePos = $( iframe ).offset();\n\t\tpos.left += iframePos.left;\n\t\tpos.top += iframePos.top;\n\t\telementDocument = iframe.ownerDocument;\n\t}\n\tpos.left -= anchorPos.left;\n\tpos.top -= anchorPos.top;\n\treturn pos;\n};\n\n/**\n * Get element border sizes.\n *\n * @static\n * @param {HTMLElement} el Element to measure\n * @return {Object} Dimensions object with `top`, `left`, `bottom` and `right` properties\n */\nOO.ui.Element.static.getBorders = function ( el ) {\n\tvar doc = el.ownerDocument,\n\t\twin = doc.defaultView,\n\t\tstyle = win.getComputedStyle( el, null ),\n\t\t$el = $( el ),\n\t\ttop = parseFloat( style ? style.borderTopWidth : $el.css( 'borderTopWidth' ) ) || 0,\n\t\tleft = parseFloat( style ? style.borderLeftWidth : $el.css( 'borderLeftWidth' ) ) || 0,\n\t\tbottom = parseFloat( style ? style.borderBottomWidth : $el.css( 'borderBottomWidth' ) ) || 0,\n\t\tright = parseFloat( style ? style.borderRightWidth : $el.css( 'borderRightWidth' ) ) || 0;\n\n\treturn {\n\t\ttop: top,\n\t\tleft: left,\n\t\tbottom: bottom,\n\t\tright: right\n\t};\n};\n\n/**\n * Get dimensions of an element or window.\n *\n * @static\n * @param {HTMLElement|Window} el Element to measure\n * @return {Object} Dimensions object with `borders`, `scroll`, `scrollbar` and `rect` properties\n */\nOO.ui.Element.static.getDimensions = function ( el ) {\n\tvar $el, $win,\n\t\tdoc = el.ownerDocument || el.document,\n\t\twin = doc.defaultView;\n\n\tif ( win === el || el === doc.documentElement ) {\n\t\t$win = $( win );\n\t\treturn {\n\t\t\tborders: { top: 0, left: 0, bottom: 0, right: 0 },\n\t\t\tscroll: {\n\t\t\t\ttop: $win.scrollTop(),\n\t\t\t\tleft: $win.scrollLeft()\n\t\t\t},\n\t\t\tscrollbar: { right: 0, bottom: 0 },\n\t\t\trect: {\n\t\t\t\ttop: 0,\n\t\t\t\tleft: 0,\n\t\t\t\tbottom: $win.innerHeight(),\n\t\t\t\tright: $win.innerWidth()\n\t\t\t}\n\t\t};\n\t} else {\n\t\t$el = $( el );\n\t\treturn {\n\t\t\tborders: this.getBorders( el ),\n\t\t\tscroll: {\n\t\t\t\ttop: $el.scrollTop(),\n\t\t\t\tleft: $el.scrollLeft()\n\t\t\t},\n\t\t\tscrollbar: {\n\t\t\t\tright: $el.innerWidth() - el.clientWidth,\n\t\t\t\tbottom: $el.innerHeight() - el.clientHeight\n\t\t\t},\n\t\t\trect: el.getBoundingClientRect()\n\t\t};\n\t}\n};\n\n/**\n * Get the number of pixels that an element's content is scrolled to the left.\n *\n * Adapted from <https://github.com/othree/jquery.rtl-scroll-type>.\n * Original code copyright 2012 Wei-Ko Kao, licensed under the MIT License.\n *\n * This function smooths out browser inconsistencies (nicely described in the README at\n * <https://github.com/othree/jquery.rtl-scroll-type>) and produces a result consistent\n * with Firefox's 'scrollLeft', which seems the sanest.\n *\n * @static\n * @method\n * @param {HTMLElement|Window} el Element to measure\n * @return {number} Scroll position from the left.\n * If the element's direction is LTR, this is a positive number between `0` (initial scroll position)\n * and `el.scrollWidth - el.clientWidth` (furthest possible scroll position).\n * If the element's direction is RTL, this is a negative number between `0` (initial scroll position)\n * and `-el.scrollWidth + el.clientWidth` (furthest possible scroll position).\n */\nOO.ui.Element.static.getScrollLeft = ( function () {\n\tvar rtlScrollType = null;\n\n\tfunction test() {\n\t\tvar $definer = $( '<div dir=\"rtl\" style=\"font-size: 14px; width: 1px; height: 1px; position: absolute; top: -1000px; overflow: scroll\">A</div>' ),\n\t\t\tdefiner = $definer[ 0 ];\n\n\t\t$definer.appendTo( 'body' );\n\t\tif ( definer.scrollLeft > 0 ) {\n\t\t\t// Safari, Chrome\n\t\t\trtlScrollType = 'default';\n\t\t} else {\n\t\t\tdefiner.scrollLeft = 1;\n\t\t\tif ( definer.scrollLeft === 0 ) {\n\t\t\t\t// Firefox, old Opera\n\t\t\t\trtlScrollType = 'negative';\n\t\t\t} else {\n\t\t\t\t// Internet Explorer, Edge\n\t\t\t\trtlScrollType = 'reverse';\n\t\t\t}\n\t\t}\n\t\t$definer.remove();\n\t}\n\n\treturn function getScrollLeft( el ) {\n\t\tvar isRoot = el.window === el ||\n\t\t\t\tel === el.ownerDocument.body ||\n\t\t\t\tel === el.ownerDocument.documentElement,\n\t\t\tscrollLeft = isRoot ? $( window ).scrollLeft() : el.scrollLeft,\n\t\t\t// All browsers use the correct scroll type ('negative') on the root, so don't\n\t\t\t// do any fixups when looking at the root element\n\t\t\tdirection = isRoot ? 'ltr' : $( el ).css( 'direction' );\n\n\t\tif ( direction === 'rtl' ) {\n\t\t\tif ( rtlScrollType === null ) {\n\t\t\t\ttest();\n\t\t\t}\n\t\t\tif ( rtlScrollType === 'reverse' ) {\n\t\t\t\tscrollLeft = -scrollLeft;\n\t\t\t} else if ( rtlScrollType === 'default' ) {\n\t\t\t\tscrollLeft = scrollLeft - el.scrollWidth + el.clientWidth;\n\t\t\t}\n\t\t}\n\n\t\treturn scrollLeft;\n\t};\n}() );\n\n/**\n * Get the root scrollable element of given element's document.\n *\n * On Blink-based browsers (Chrome etc.), `document.documentElement` can't be used to get or set\n * the scrollTop property; instead we have to use `document.body`. Changing and testing the value\n * lets us use 'body' or 'documentElement' based on what is working.\n *\n * https://code.google.com/p/chromium/issues/detail?id=303131\n *\n * @static\n * @param {HTMLElement} el Element to find root scrollable parent for\n * @return {HTMLElement} Scrollable parent, `document.body` or `document.documentElement`\n * depending on browser\n */\nOO.ui.Element.static.getRootScrollableElement = function ( el ) {\n\tvar scrollTop, body;\n\n\tif ( OO.ui.scrollableElement === undefined ) {\n\t\tbody = el.ownerDocument.body;\n\t\tscrollTop = body.scrollTop;\n\t\tbody.scrollTop = 1;\n\n\t\t// In some browsers (observed in Chrome 56 on Linux Mint 18.1),\n\t\t// body.scrollTop doesn't become exactly 1, but a fractional value like 0.76\n\t\tif ( Math.round( body.scrollTop ) === 1 ) {\n\t\t\tbody.scrollTop = scrollTop;\n\t\t\tOO.ui.scrollableElement = 'body';\n\t\t} else {\n\t\t\tOO.ui.scrollableElement = 'documentElement';\n\t\t}\n\t}\n\n\treturn el.ownerDocument[ OO.ui.scrollableElement ];\n};\n\n/**\n * Get closest scrollable container.\n *\n * Traverses up until either a scrollable element or the root is reached, in which case the root\n * scrollable element will be returned (see #getRootScrollableElement).\n *\n * @static\n * @param {HTMLElement} el Element to find scrollable container for\n * @param {string} [dimension] Dimension of scrolling to look for; `x`, `y` or omit for either\n * @return {HTMLElement} Closest scrollable container\n */\nOO.ui.Element.static.getClosestScrollableContainer = function ( el, dimension ) {\n\tvar i, val,\n\t\t// Browsers do not correctly return the computed value of 'overflow' when 'overflow-x' and\n\t\t// 'overflow-y' have different values, so we need to check the separate properties.\n\t\tprops = [ 'overflow-x', 'overflow-y' ],\n\t\t$parent = $( el ).parent();\n\n\tif ( dimension === 'x' || dimension === 'y' ) {\n\t\tprops = [ 'overflow-' + dimension ];\n\t}\n\n\t// Special case for the document root (which doesn't really have any scrollable container, since\n\t// it is the ultimate scrollable container, but this is probably saner than null or exception)\n\tif ( $( el ).is( 'html, body' ) ) {\n\t\treturn this.getRootScrollableElement( el );\n\t}\n\n\twhile ( $parent.length ) {\n\t\tif ( $parent[ 0 ] === this.getRootScrollableElement( el ) ) {\n\t\t\treturn $parent[ 0 ];\n\t\t}\n\t\ti = props.length;\n\t\twhile ( i-- ) {\n\t\t\tval = $parent.css( props[ i ] );\n\t\t\t// We assume that elements with 'overflow' (in any direction) set to 'hidden' will never be\n\t\t\t// scrolled in that direction, but they can actually be scrolled programatically. The user can\n\t\t\t// unintentionally perform a scroll in such case even if the application doesn't scroll\n\t\t\t// programatically, e.g. when jumping to an anchor, or when using built-in find functionality.\n\t\t\t// This could cause funny issues...\n\t\t\tif ( val === 'auto' || val === 'scroll' ) {\n\t\t\t\treturn $parent[ 0 ];\n\t\t\t}\n\t\t}\n\t\t$parent = $parent.parent();\n\t}\n\t// The element is unattached... return something mostly sane\n\treturn this.getRootScrollableElement( el );\n};\n\n/**\n * Scroll element into view.\n *\n * @static\n * @param {HTMLElement} el Element to scroll into view\n * @param {Object} [config] Configuration options\n * @param {string} [config.duration='fast'] jQuery animation duration value\n * @param {string} [config.direction] Scroll in only one direction, e.g. 'x' or 'y', omit\n * to scroll in both directions\n * @return {jQuery.Promise} Promise which resolves when the scroll is complete\n */\nOO.ui.Element.static.scrollIntoView = function ( el, config ) {\n\tvar position, animations, container, $container, elementDimensions, containerDimensions, $window,\n\t\tdeferred = $.Deferred();\n\n\t// Configuration initialization\n\tconfig = config || {};\n\n\tanimations = {};\n\tcontainer = this.getClosestScrollableContainer( el, config.direction );\n\t$container = $( container );\n\telementDimensions = this.getDimensions( el );\n\tcontainerDimensions = this.getDimensions( container );\n\t$window = $( this.getWindow( el ) );\n\n\t// Compute the element's position relative to the container\n\tif ( $container.is( 'html, body' ) ) {\n\t\t// If the scrollable container is the root, this is easy\n\t\tposition = {\n\t\t\ttop: elementDimensions.rect.top,\n\t\t\tbottom: $window.innerHeight() - elementDimensions.rect.bottom,\n\t\t\tleft: elementDimensions.rect.left,\n\t\t\tright: $window.innerWidth() - elementDimensions.rect.right\n\t\t};\n\t} else {\n\t\t// Otherwise, we have to subtract el's coordinates from container's coordinates\n\t\tposition = {\n\t\t\ttop: elementDimensions.rect.top - ( containerDimensions.rect.top + containerDimensions.borders.top ),\n\t\t\tbottom: containerDimensions.rect.bottom - containerDimensions.borders.bottom - containerDimensions.scrollbar.bottom - elementDimensions.rect.bottom,\n\t\t\tleft: elementDimensions.rect.left - ( containerDimensions.rect.left + containerDimensions.borders.left ),\n\t\t\tright: containerDimensions.rect.right - containerDimensions.borders.right - containerDimensions.scrollbar.right - elementDimensions.rect.right\n\t\t};\n\t}\n\n\tif ( !config.direction || config.direction === 'y' ) {\n\t\tif ( position.top < 0 ) {\n\t\t\tanimations.scrollTop = containerDimensions.scroll.top + position.top;\n\t\t} else if ( position.top > 0 && position.bottom < 0 ) {\n\t\t\tanimations.scrollTop = containerDimensions.scroll.top + Math.min( position.top, -position.bottom );\n\t\t}\n\t}\n\tif ( !config.direction || config.direction === 'x' ) {\n\t\tif ( position.left < 0 ) {\n\t\t\tanimations.scrollLeft = containerDimensions.scroll.left + position.left;\n\t\t} else if ( position.left > 0 && position.right < 0 ) {\n\t\t\tanimations.scrollLeft = containerDimensions.scroll.left + Math.min( position.left, -position.right );\n\t\t}\n\t}\n\tif ( !$.isEmptyObject( animations ) ) {\n\t\t$container.stop( true ).animate( animations, config.duration === undefined ? 'fast' : config.duration );\n\t\t$container.queue( function ( next ) {\n\t\t\tdeferred.resolve();\n\t\t\tnext();\n\t\t} );\n\t} else {\n\t\tdeferred.resolve();\n\t}\n\treturn deferred.promise();\n};\n\n/**\n * Force the browser to reconsider whether it really needs to render scrollbars inside the element\n * and reserve space for them, because it probably doesn't.\n *\n * Workaround primarily for <https://code.google.com/p/chromium/issues/detail?id=387290>, but also\n * similar bugs in other browsers. \"Just\" forcing a reflow is not sufficient in all cases, we need\n * to first actually detach (or hide, but detaching is simpler) all children, *then* force a reflow,\n * and then reattach (or show) them back.\n *\n * @static\n * @param {HTMLElement} el Element to reconsider the scrollbars on\n */\nOO.ui.Element.static.reconsiderScrollbars = function ( el ) {\n\tvar i, len, scrollLeft, scrollTop, nodes = [];\n\t// Save scroll position\n\tscrollLeft = el.scrollLeft;\n\tscrollTop = el.scrollTop;\n\t// Detach all children\n\twhile ( el.firstChild ) {\n\t\tnodes.push( el.firstChild );\n\t\tel.removeChild( el.firstChild );\n\t}\n\t// Force reflow\n\tvoid el.offsetHeight;\n\t// Reattach all children\n\tfor ( i = 0, len = nodes.length; i < len; i++ ) {\n\t\tel.appendChild( nodes[ i ] );\n\t}\n\t// Restore scroll position (no-op if scrollbars disappeared)\n\tel.scrollLeft = scrollLeft;\n\tel.scrollTop = scrollTop;\n};\n\n/* Methods */\n\n/**\n * Toggle visibility of an element.\n *\n * @param {boolean} [show] Make element visible, omit to toggle visibility\n * @fires visible\n * @chainable\n */\nOO.ui.Element.prototype.toggle = function ( show ) {\n\tshow = show === undefined ? !this.visible : !!show;\n\n\tif ( show !== this.isVisible() ) {\n\t\tthis.visible = show;\n\t\tthis.$element.toggleClass( 'oo-ui-element-hidden', !this.visible );\n\t\tthis.emit( 'toggle', show );\n\t}\n\n\treturn this;\n};\n\n/**\n * Check if element is visible.\n *\n * @return {boolean} element is visible\n */\nOO.ui.Element.prototype.isVisible = function () {\n\treturn this.visible;\n};\n\n/**\n * Get element data.\n *\n * @return {Mixed} Element data\n */\nOO.ui.Element.prototype.getData = function () {\n\treturn this.data;\n};\n\n/**\n * Set element data.\n *\n * @param {Mixed} data Element data\n * @chainable\n */\nOO.ui.Element.prototype.setData = function ( data ) {\n\tthis.data = data;\n\treturn this;\n};\n\n/**\n * Set the element has an 'id' attribute.\n *\n * @param {string} id\n * @chainable\n */\nOO.ui.Element.prototype.setElementId = function ( id ) {\n\tthis.elementId = id;\n\tthis.$element.attr( 'id', id );\n\treturn this;\n};\n\n/**\n * Ensure that the element has an 'id' attribute, setting it to an unique value if it's missing,\n * and return its value.\n *\n * @return {string}\n */\nOO.ui.Element.prototype.getElementId = function () {\n\tif ( this.elementId === null ) {\n\t\tthis.setElementId( OO.ui.generateElementId() );\n\t}\n\treturn this.elementId;\n};\n\n/**\n * Check if element supports one or more methods.\n *\n * @param {string|string[]} methods Method or list of methods to check\n * @return {boolean} All methods are supported\n */\nOO.ui.Element.prototype.supports = function ( methods ) {\n\tvar i, len,\n\t\tsupport = 0;\n\n\tmethods = Array.isArray( methods ) ? methods : [ methods ];\n\tfor ( i = 0, len = methods.length; i < len; i++ ) {\n\t\tif ( $.isFunction( this[ methods[ i ] ] ) ) {\n\t\t\tsupport++;\n\t\t}\n\t}\n\n\treturn methods.length === support;\n};\n\n/**\n * Update the theme-provided classes.\n *\n * @localdoc This is called in element mixins and widget classes any time state changes.\n * Updating is debounced, minimizing overhead of changing multiple attributes and\n * guaranteeing that theme updates do not occur within an element's constructor\n */\nOO.ui.Element.prototype.updateThemeClasses = function () {\n\tOO.ui.theme.queueUpdateElementClasses( this );\n};\n\n/**\n * Get the HTML tag name.\n *\n * Override this method to base the result on instance information.\n *\n * @return {string} HTML tag name\n */\nOO.ui.Element.prototype.getTagName = function () {\n\treturn this.constructor.static.tagName;\n};\n\n/**\n * Check if the element is attached to the DOM\n *\n * @return {boolean} The element is attached to the DOM\n */\nOO.ui.Element.prototype.isElementAttached = function () {\n\treturn $.contains( this.getElementDocument(), this.$element[ 0 ] );\n};\n\n/**\n * Get the DOM document.\n *\n * @return {HTMLDocument} Document object\n */\nOO.ui.Element.prototype.getElementDocument = function () {\n\t// Don't cache this in other ways either because subclasses could can change this.$element\n\treturn OO.ui.Element.static.getDocument( this.$element );\n};\n\n/**\n * Get the DOM window.\n *\n * @return {Window} Window object\n */\nOO.ui.Element.prototype.getElementWindow = function () {\n\treturn OO.ui.Element.static.getWindow( this.$element );\n};\n\n/**\n * Get closest scrollable container.\n *\n * @return {HTMLElement} Closest scrollable container\n */\nOO.ui.Element.prototype.getClosestScrollableElementContainer = function () {\n\treturn OO.ui.Element.static.getClosestScrollableContainer( this.$element[ 0 ] );\n};\n\n/**\n * Get group element is in.\n *\n * @return {OO.ui.mixin.GroupElement|null} Group element, null if none\n */\nOO.ui.Element.prototype.getElementGroup = function () {\n\treturn this.elementGroup;\n};\n\n/**\n * Set group element is in.\n *\n * @param {OO.ui.mixin.GroupElement|null} group Group element, null if none\n * @chainable\n */\nOO.ui.Element.prototype.setElementGroup = function ( group ) {\n\tthis.elementGroup = group;\n\treturn this;\n};\n\n/**\n * Scroll element into view.\n *\n * @param {Object} [config] Configuration options\n * @return {jQuery.Promise} Promise which resolves when the scroll is complete\n */\nOO.ui.Element.prototype.scrollElementIntoView = function ( config ) {\n\tif (\n\t\t!this.isElementAttached() ||\n\t\t!this.isVisible() ||\n\t\t( this.getElementGroup() && !this.getElementGroup().isVisible() )\n\t) {\n\t\treturn $.Deferred().resolve();\n\t}\n\treturn OO.ui.Element.static.scrollIntoView( this.$element[ 0 ], config );\n};\n\n/**\n * Restore the pre-infusion dynamic state for this widget.\n *\n * This method is called after #$element has been inserted into DOM. The parameter is the return\n * value of #gatherPreInfuseState.\n *\n * @protected\n * @param {Object} state\n */\nOO.ui.Element.prototype.restorePreInfuseState = function () {\n};\n","/**\n * Wraps an HTML snippet for use with configuration values which default\n * to strings. This bypasses the default html-escaping done to string\n * values.\n *\n * @class\n *\n * @constructor\n * @param {string} [content] HTML content\n */\nOO.ui.HtmlSnippet = function OoUiHtmlSnippet( content ) {\n\t// Properties\n\tthis.content = content;\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.HtmlSnippet );\n\n/* Methods */\n\n/**\n * Render into HTML.\n *\n * @return {string} Unchanged HTML snippet.\n */\nOO.ui.HtmlSnippet.prototype.toString = function () {\n\treturn this.content;\n};\n","/**\n * Layouts are containers for elements and are used to arrange other widgets of arbitrary type in a way\n * that is centrally controlled and can be updated dynamically. Layouts can be, and usually are, combined.\n * See {@link OO.ui.FieldsetLayout FieldsetLayout}, {@link OO.ui.FieldLayout FieldLayout}, {@link OO.ui.FormLayout FormLayout},\n * {@link OO.ui.PanelLayout PanelLayout}, {@link OO.ui.StackLayout StackLayout}, {@link OO.ui.PageLayout PageLayout},\n * {@link OO.ui.HorizontalLayout HorizontalLayout}, and {@link OO.ui.BookletLayout BookletLayout} for more information and examples.\n *\n * @abstract\n * @class\n * @extends OO.ui.Element\n * @mixins OO.EventEmitter\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.Layout = function OoUiLayout( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.Layout.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.EventEmitter.call( this );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-layout' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.Layout, OO.ui.Element );\nOO.mixinClass( OO.ui.Layout, OO.EventEmitter );\n","/**\n * Widgets are compositions of one or more OOjs UI elements that users can both view\n * and interact with. All widgets can be configured and modified via a standard API,\n * and their state can change dynamically according to a model.\n *\n * @abstract\n * @class\n * @extends OO.ui.Element\n * @mixins OO.EventEmitter\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [disabled=false] Disable the widget. Disabled widgets cannot be used and their\n * appearance reflects this state.\n */\nOO.ui.Widget = function OoUiWidget( config ) {\n\t// Initialize config\n\tconfig = $.extend( { disabled: false }, config );\n\n\t// Parent constructor\n\tOO.ui.Widget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.EventEmitter.call( this );\n\n\t// Properties\n\tthis.disabled = null;\n\tthis.wasDisabled = null;\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-widget' );\n\tthis.setDisabled( !!config.disabled );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.Widget, OO.ui.Element );\nOO.mixinClass( OO.ui.Widget, OO.EventEmitter );\n\n/* Events */\n\n/**\n * @event disable\n *\n * A 'disable' event is emitted when the disabled state of the widget changes\n * (i.e. on disable **and** enable).\n *\n * @param {boolean} disabled Widget is disabled\n */\n\n/**\n * @event toggle\n *\n * A 'toggle' event is emitted when the visibility of the widget changes.\n *\n * @param {boolean} visible Widget is visible\n */\n\n/* Methods */\n\n/**\n * Check if the widget is disabled.\n *\n * @return {boolean} Widget is disabled\n */\nOO.ui.Widget.prototype.isDisabled = function () {\n\treturn this.disabled;\n};\n\n/**\n * Set the 'disabled' state of the widget.\n *\n * When a widget is disabled, it cannot be used and its appearance is updated to reflect this state.\n *\n * @param {boolean} disabled Disable widget\n * @chainable\n */\nOO.ui.Widget.prototype.setDisabled = function ( disabled ) {\n\tvar isDisabled;\n\n\tthis.disabled = !!disabled;\n\tisDisabled = this.isDisabled();\n\tif ( isDisabled !== this.wasDisabled ) {\n\t\tthis.$element.toggleClass( 'oo-ui-widget-disabled', isDisabled );\n\t\tthis.$element.toggleClass( 'oo-ui-widget-enabled', !isDisabled );\n\t\tthis.$element.attr( 'aria-disabled', isDisabled.toString() );\n\t\tthis.emit( 'disable', isDisabled );\n\t\tthis.updateThemeClasses();\n\t}\n\tthis.wasDisabled = isDisabled;\n\n\treturn this;\n};\n\n/**\n * Update the disabled state, in case of changes in parent widget.\n *\n * @chainable\n */\nOO.ui.Widget.prototype.updateDisabled = function () {\n\tthis.setDisabled( this.disabled );\n\treturn this;\n};\n\n/**\n * Get an ID of a labelable node which is part of this widget, if any, to be used for `<label for>`\n * value.\n *\n * If this function returns null, the widget should have a meaningful #simulateLabelClick method\n * instead.\n *\n * @return {string|null} The ID of the labelable element\n */\nOO.ui.Widget.prototype.getInputId = function () {\n\treturn null;\n};\n\n/**\n * Simulate the behavior of clicking on a label (a HTML `<label>` element) bound to this input.\n * HTML only allows `<label>` to act on specific \"labelable\" elements; complex widgets might need to\n * override this method to provide intuitive, accessible behavior.\n *\n * By default, this does nothing. OO.ui.mixin.TabIndexedElement overrides it for focusable widgets.\n * Individual widgets may override it too.\n *\n * This method is called by OO.ui.LabelWidget and OO.ui.FieldLayout. It should not be called\n * directly.\n */\nOO.ui.Widget.prototype.simulateLabelClick = function () {\n};\n","/**\n * Theme logic.\n *\n * @abstract\n * @class\n *\n * @constructor\n */\nOO.ui.Theme = function OoUiTheme() {\n\tthis.elementClassesQueue = [];\n\tthis.debouncedUpdateQueuedElementClasses = OO.ui.debounce( this.updateQueuedElementClasses );\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.Theme );\n\n/* Methods */\n\n/**\n * Get a list of classes to be applied to a widget.\n *\n * The 'on' and 'off' lists combined MUST contain keys for all classes the theme adds or removes,\n * otherwise state transitions will not work properly.\n *\n * @param {OO.ui.Element} element Element for which to get classes\n * @return {Object.<string,string[]>} Categorized class names with `on` and `off` lists\n */\nOO.ui.Theme.prototype.getElementClasses = function () {\n\treturn { on: [], off: [] };\n};\n\n/**\n * Update CSS classes provided by the theme.\n *\n * For elements with theme logic hooks, this should be called any time there's a state change.\n *\n * @param {OO.ui.Element} element Element for which to update classes\n */\nOO.ui.Theme.prototype.updateElementClasses = function ( element ) {\n\tvar $elements = $( [] ),\n\t\tclasses = this.getElementClasses( element );\n\n\tif ( element.$icon ) {\n\t\t$elements = $elements.add( element.$icon );\n\t}\n\tif ( element.$indicator ) {\n\t\t$elements = $elements.add( element.$indicator );\n\t}\n\n\t$elements\n\t\t.removeClass( classes.off.join( ' ' ) )\n\t\t.addClass( classes.on.join( ' ' ) );\n};\n\n/**\n * @private\n */\nOO.ui.Theme.prototype.updateQueuedElementClasses = function () {\n\tvar i;\n\tfor ( i = 0; i < this.elementClassesQueue.length; i++ ) {\n\t\tthis.updateElementClasses( this.elementClassesQueue[ i ] );\n\t}\n\t// Clear the queue\n\tthis.elementClassesQueue = [];\n};\n\n/**\n * Queue #updateElementClasses to be called for this element.\n *\n * @localdoc QUnit tests override this method to directly call #queueUpdateElementClasses,\n * to make them synchronous.\n *\n * @param {OO.ui.Element} element Element for which to update classes\n */\nOO.ui.Theme.prototype.queueUpdateElementClasses = function ( element ) {\n\t// Keep items in the queue unique. Use lastIndexOf to start checking from the end because that's\n\t// the most common case (this method is often called repeatedly for the same element).\n\tif ( this.elementClassesQueue.lastIndexOf( element ) !== -1 ) {\n\t\treturn;\n\t}\n\tthis.elementClassesQueue.push( element );\n\tthis.debouncedUpdateQueuedElementClasses();\n};\n\n/**\n * Get the transition duration in milliseconds for dialogs opening/closing\n *\n * The dialog should be fully rendered this many milliseconds after the\n * ready process has executed.\n *\n * @return {number} Transition duration in milliseconds\n */\nOO.ui.Theme.prototype.getDialogTransitionDuration = function () {\n\treturn 0;\n};\n","/**\n * The TabIndexedElement class is an attribute mixin used to add additional functionality to an\n * element created by another class. The mixin provides a ‘tabIndex’ property, which specifies the\n * order in which users will navigate through the focusable elements via the \"tab\" key.\n *\n * @example\n * // TabIndexedElement is mixed into the ButtonWidget class\n * // to provide a tabIndex property.\n * var button1 = new OO.ui.ButtonWidget( {\n * label: 'fourth',\n * tabIndex: 4\n * } );\n * var button2 = new OO.ui.ButtonWidget( {\n * label: 'second',\n * tabIndex: 2\n * } );\n * var button3 = new OO.ui.ButtonWidget( {\n * label: 'third',\n * tabIndex: 3\n * } );\n * var button4 = new OO.ui.ButtonWidget( {\n * label: 'first',\n * tabIndex: 1\n * } );\n * $( 'body' ).append( button1.$element, button2.$element, button3.$element, button4.$element );\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$tabIndexed] The element that should use the tabindex functionality. By default,\n * the functionality is applied to the element created by the class ($element). If a different element is specified, the tabindex\n * functionality will be applied to it instead.\n * @cfg {string|number|null} [tabIndex=0] Number that specifies the element’s position in the tab-navigation\n * order (e.g., 1 for the first focusable element). Use 0 to use the default navigation order; use -1\n * to remove the element from the tab-navigation flow.\n */\nOO.ui.mixin.TabIndexedElement = function OoUiMixinTabIndexedElement( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( { tabIndex: 0 }, config );\n\n\t// Properties\n\tthis.$tabIndexed = null;\n\tthis.tabIndex = null;\n\n\t// Events\n\tthis.connect( this, { disable: 'onTabIndexedElementDisable' } );\n\n\t// Initialization\n\tthis.setTabIndex( config.tabIndex );\n\tthis.setTabIndexedElement( config.$tabIndexed || this.$element );\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.mixin.TabIndexedElement );\n\n/* Methods */\n\n/**\n * Set the element that should use the tabindex functionality.\n *\n * This method is used to retarget a tabindex mixin so that its functionality applies\n * to the specified element. If an element is currently using the functionality, the mixin’s\n * effect on that element is removed before the new element is set up.\n *\n * @param {jQuery} $tabIndexed Element that should use the tabindex functionality\n * @chainable\n */\nOO.ui.mixin.TabIndexedElement.prototype.setTabIndexedElement = function ( $tabIndexed ) {\n\tvar tabIndex = this.tabIndex;\n\t// Remove attributes from old $tabIndexed\n\tthis.setTabIndex( null );\n\t// Force update of new $tabIndexed\n\tthis.$tabIndexed = $tabIndexed;\n\tthis.tabIndex = tabIndex;\n\treturn this.updateTabIndex();\n};\n\n/**\n * Set the value of the tabindex.\n *\n * @param {string|number|null} tabIndex Tabindex value, or `null` for no tabindex\n * @chainable\n */\nOO.ui.mixin.TabIndexedElement.prototype.setTabIndex = function ( tabIndex ) {\n\ttabIndex = /^-?\\d+$/.test( tabIndex ) ? Number( tabIndex ) : null;\n\n\tif ( this.tabIndex !== tabIndex ) {\n\t\tthis.tabIndex = tabIndex;\n\t\tthis.updateTabIndex();\n\t}\n\n\treturn this;\n};\n\n/**\n * Update the `tabindex` attribute, in case of changes to tab index or\n * disabled state.\n *\n * @private\n * @chainable\n */\nOO.ui.mixin.TabIndexedElement.prototype.updateTabIndex = function () {\n\tif ( this.$tabIndexed ) {\n\t\tif ( this.tabIndex !== null ) {\n\t\t\t// Do not index over disabled elements\n\t\t\tthis.$tabIndexed.attr( {\n\t\t\t\ttabindex: this.isDisabled() ? -1 : this.tabIndex,\n\t\t\t\t// Support: ChromeVox and NVDA\n\t\t\t\t// These do not seem to inherit aria-disabled from parent elements\n\t\t\t\t'aria-disabled': this.isDisabled().toString()\n\t\t\t} );\n\t\t} else {\n\t\t\tthis.$tabIndexed.removeAttr( 'tabindex aria-disabled' );\n\t\t}\n\t}\n\treturn this;\n};\n\n/**\n * Handle disable events.\n *\n * @private\n * @param {boolean} disabled Element is disabled\n */\nOO.ui.mixin.TabIndexedElement.prototype.onTabIndexedElementDisable = function () {\n\tthis.updateTabIndex();\n};\n\n/**\n * Get the value of the tabindex.\n *\n * @return {number|null} Tabindex value\n */\nOO.ui.mixin.TabIndexedElement.prototype.getTabIndex = function () {\n\treturn this.tabIndex;\n};\n\n/**\n * Get an ID of a focusable element of this widget, if any, to be used for `<label for>` value.\n *\n * If the element already has an ID then that is returned, otherwise unique ID is\n * generated, set on the element, and returned.\n *\n * @return {string|null} The ID of the focusable element\n */\nOO.ui.mixin.TabIndexedElement.prototype.getInputId = function () {\n\tvar id;\n\n\tif ( !this.$tabIndexed ) {\n\t\treturn null;\n\t}\n\tif ( !this.isLabelableNode( this.$tabIndexed ) ) {\n\t\treturn null;\n\t}\n\n\tid = this.$tabIndexed.attr( 'id' );\n\tif ( id === undefined ) {\n\t\tid = OO.ui.generateElementId();\n\t\tthis.$tabIndexed.attr( 'id', id );\n\t}\n\n\treturn id;\n};\n\n/**\n * Whether the node is 'labelable' according to the HTML spec\n * (i.e., whether it can be interacted with through a `<label for=\"…\">`).\n * See: <https://html.spec.whatwg.org/multipage/forms.html#category-label>.\n *\n * @private\n * @param {jQuery} $node\n * @return {boolean}\n */\nOO.ui.mixin.TabIndexedElement.prototype.isLabelableNode = function ( $node ) {\n\tvar\n\t\tlabelableTags = [ 'button', 'meter', 'output', 'progress', 'select', 'textarea' ],\n\t\ttagName = $node.prop( 'tagName' ).toLowerCase();\n\n\tif ( tagName === 'input' && $node.attr( 'type' ) !== 'hidden' ) {\n\t\treturn true;\n\t}\n\tif ( labelableTags.indexOf( tagName ) !== -1 ) {\n\t\treturn true;\n\t}\n\treturn false;\n};\n\n/**\n * Focus this element.\n *\n * @chainable\n */\nOO.ui.mixin.TabIndexedElement.prototype.focus = function () {\n\tif ( !this.isDisabled() ) {\n\t\tthis.$tabIndexed.focus();\n\t}\n\treturn this;\n};\n\n/**\n * Blur this element.\n *\n * @chainable\n */\nOO.ui.mixin.TabIndexedElement.prototype.blur = function () {\n\tthis.$tabIndexed.blur();\n\treturn this;\n};\n\n/**\n * @inheritdoc OO.ui.Widget\n */\nOO.ui.mixin.TabIndexedElement.prototype.simulateLabelClick = function () {\n\tthis.focus();\n};\n","/**\n * ButtonElement is often mixed into other classes to generate a button, which is a clickable\n * interface element that can be configured with access keys for accessibility.\n * See the [OOjs UI documentation on MediaWiki] [1] for examples.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches#Buttons\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$button] The button element created by the class.\n * If this configuration is omitted, the button element will use a generated `<a>`.\n * @cfg {boolean} [framed=true] Render the button with a frame\n */\nOO.ui.mixin.ButtonElement = function OoUiMixinButtonElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.$button = null;\n\tthis.framed = null;\n\tthis.active = config.active !== undefined && config.active;\n\tthis.onMouseUpHandler = this.onMouseUp.bind( this );\n\tthis.onMouseDownHandler = this.onMouseDown.bind( this );\n\tthis.onKeyDownHandler = this.onKeyDown.bind( this );\n\tthis.onKeyUpHandler = this.onKeyUp.bind( this );\n\tthis.onClickHandler = this.onClick.bind( this );\n\tthis.onKeyPressHandler = this.onKeyPress.bind( this );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-buttonElement' );\n\tthis.toggleFramed( config.framed === undefined || config.framed );\n\tthis.setButtonElement( config.$button || $( '<a>' ) );\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.mixin.ButtonElement );\n\n/* Static Properties */\n\n/**\n * Cancel mouse down events.\n *\n * This property is usually set to `true` to prevent the focus from changing when the button is clicked.\n * Classes such as {@link OO.ui.mixin.DraggableElement DraggableElement} and {@link OO.ui.ButtonOptionWidget ButtonOptionWidget}\n * use a value of `false` so that dragging behavior is possible and mousedown events can be handled by a\n * parent widget.\n *\n * @static\n * @inheritable\n * @property {boolean}\n */\nOO.ui.mixin.ButtonElement.static.cancelButtonMouseDownEvents = true;\n\n/* Events */\n\n/**\n * A 'click' event is emitted when the button element is clicked.\n *\n * @event click\n */\n\n/* Methods */\n\n/**\n * Set the button element.\n *\n * This method is used to retarget a button mixin so that its functionality applies to\n * the specified button element instead of the one created by the class. If a button element\n * is already set, the method will remove the mixin’s effect on that element.\n *\n * @param {jQuery} $button Element to use as button\n */\nOO.ui.mixin.ButtonElement.prototype.setButtonElement = function ( $button ) {\n\tif ( this.$button ) {\n\t\tthis.$button\n\t\t\t.removeClass( 'oo-ui-buttonElement-button' )\n\t\t\t.removeAttr( 'role accesskey' )\n\t\t\t.off( {\n\t\t\t\tmousedown: this.onMouseDownHandler,\n\t\t\t\tkeydown: this.onKeyDownHandler,\n\t\t\t\tclick: this.onClickHandler,\n\t\t\t\tkeypress: this.onKeyPressHandler\n\t\t\t} );\n\t}\n\n\tthis.$button = $button\n\t\t.addClass( 'oo-ui-buttonElement-button' )\n\t\t.on( {\n\t\t\tmousedown: this.onMouseDownHandler,\n\t\t\tkeydown: this.onKeyDownHandler,\n\t\t\tclick: this.onClickHandler,\n\t\t\tkeypress: this.onKeyPressHandler\n\t\t} );\n\n\t// Add `role=\"button\"` on `<a>` elements, where it's needed\n\t// `toUppercase()` is added for XHTML documents\n\tif ( this.$button.prop( 'tagName' ).toUpperCase() === 'A' ) {\n\t\tthis.$button.attr( 'role', 'button' );\n\t}\n};\n\n/**\n * Handles mouse down events.\n *\n * @protected\n * @param {jQuery.Event} e Mouse down event\n */\nOO.ui.mixin.ButtonElement.prototype.onMouseDown = function ( e ) {\n\tif ( this.isDisabled() || e.which !== OO.ui.MouseButtons.LEFT ) {\n\t\treturn;\n\t}\n\tthis.$element.addClass( 'oo-ui-buttonElement-pressed' );\n\t// Run the mouseup handler no matter where the mouse is when the button is let go, so we can\n\t// reliably remove the pressed class\n\tthis.getElementDocument().addEventListener( 'mouseup', this.onMouseUpHandler, true );\n\t// Prevent change of focus unless specifically configured otherwise\n\tif ( this.constructor.static.cancelButtonMouseDownEvents ) {\n\t\treturn false;\n\t}\n};\n\n/**\n * Handles mouse up events.\n *\n * @protected\n * @param {MouseEvent} e Mouse up event\n */\nOO.ui.mixin.ButtonElement.prototype.onMouseUp = function ( e ) {\n\tif ( this.isDisabled() || e.which !== OO.ui.MouseButtons.LEFT ) {\n\t\treturn;\n\t}\n\tthis.$element.removeClass( 'oo-ui-buttonElement-pressed' );\n\t// Stop listening for mouseup, since we only needed this once\n\tthis.getElementDocument().removeEventListener( 'mouseup', this.onMouseUpHandler, true );\n};\n\n/**\n * Handles mouse click events.\n *\n * @protected\n * @param {jQuery.Event} e Mouse click event\n * @fires click\n */\nOO.ui.mixin.ButtonElement.prototype.onClick = function ( e ) {\n\tif ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {\n\t\tif ( this.emit( 'click' ) ) {\n\t\t\treturn false;\n\t\t}\n\t}\n};\n\n/**\n * Handles key down events.\n *\n * @protected\n * @param {jQuery.Event} e Key down event\n */\nOO.ui.mixin.ButtonElement.prototype.onKeyDown = function ( e ) {\n\tif ( this.isDisabled() || ( e.which !== OO.ui.Keys.SPACE && e.which !== OO.ui.Keys.ENTER ) ) {\n\t\treturn;\n\t}\n\tthis.$element.addClass( 'oo-ui-buttonElement-pressed' );\n\t// Run the keyup handler no matter where the key is when the button is let go, so we can\n\t// reliably remove the pressed class\n\tthis.getElementDocument().addEventListener( 'keyup', this.onKeyUpHandler, true );\n};\n\n/**\n * Handles key up events.\n *\n * @protected\n * @param {KeyboardEvent} e Key up event\n */\nOO.ui.mixin.ButtonElement.prototype.onKeyUp = function ( e ) {\n\tif ( this.isDisabled() || ( e.which !== OO.ui.Keys.SPACE && e.which !== OO.ui.Keys.ENTER ) ) {\n\t\treturn;\n\t}\n\tthis.$element.removeClass( 'oo-ui-buttonElement-pressed' );\n\t// Stop listening for keyup, since we only needed this once\n\tthis.getElementDocument().removeEventListener( 'keyup', this.onKeyUpHandler, true );\n};\n\n/**\n * Handles key press events.\n *\n * @protected\n * @param {jQuery.Event} e Key press event\n * @fires click\n */\nOO.ui.mixin.ButtonElement.prototype.onKeyPress = function ( e ) {\n\tif ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) {\n\t\tif ( this.emit( 'click' ) ) {\n\t\t\treturn false;\n\t\t}\n\t}\n};\n\n/**\n * Check if button has a frame.\n *\n * @return {boolean} Button is framed\n */\nOO.ui.mixin.ButtonElement.prototype.isFramed = function () {\n\treturn this.framed;\n};\n\n/**\n * Render the button with or without a frame. Omit the `framed` parameter to toggle the button frame on and off.\n *\n * @param {boolean} [framed] Make button framed, omit to toggle\n * @chainable\n */\nOO.ui.mixin.ButtonElement.prototype.toggleFramed = function ( framed ) {\n\tframed = framed === undefined ? !this.framed : !!framed;\n\tif ( framed !== this.framed ) {\n\t\tthis.framed = framed;\n\t\tthis.$element\n\t\t\t.toggleClass( 'oo-ui-buttonElement-frameless', !framed )\n\t\t\t.toggleClass( 'oo-ui-buttonElement-framed', framed );\n\t\tthis.updateThemeClasses();\n\t}\n\n\treturn this;\n};\n\n/**\n * Set the button's active state.\n *\n * The active state can be set on:\n *\n * - {@link OO.ui.ButtonOptionWidget ButtonOptionWidget} when it is selected\n * - {@link OO.ui.ToggleButtonWidget ToggleButtonWidget} when it is toggle on\n * - {@link OO.ui.ButtonWidget ButtonWidget} when clicking the button would only refresh the page\n *\n * @protected\n * @param {boolean} value Make button active\n * @chainable\n */\nOO.ui.mixin.ButtonElement.prototype.setActive = function ( value ) {\n\tthis.active = !!value;\n\tthis.$element.toggleClass( 'oo-ui-buttonElement-active', this.active );\n\tthis.updateThemeClasses();\n\treturn this;\n};\n\n/**\n * Check if the button is active\n *\n * @protected\n * @return {boolean} The button is active\n */\nOO.ui.mixin.ButtonElement.prototype.isActive = function () {\n\treturn this.active;\n};\n","/**\n * Any OOjs UI widget that contains other widgets (such as {@link OO.ui.ButtonWidget buttons} or\n * {@link OO.ui.OptionWidget options}) mixes in GroupElement. Adding, removing, and clearing\n * items from the group is done through the interface the class provides.\n * For more information, please see the [OOjs UI documentation on MediaWiki] [1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Elements/Groups\n *\n * @abstract\n * @mixins OO.EmitterList\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$group] The container element created by the class. If this configuration\n * is omitted, the group element will use a generated `<div>`.\n */\nOO.ui.mixin.GroupElement = function OoUiMixinGroupElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Mixin constructors\n\tOO.EmitterList.call( this, config );\n\n\t// Properties\n\tthis.$group = null;\n\n\t// Initialization\n\tthis.setGroupElement( config.$group || $( '<div>' ) );\n};\n\n/* Setup */\n\nOO.mixinClass( OO.ui.mixin.GroupElement, OO.EmitterList );\n\n/* Events */\n\n/**\n * @event change\n *\n * A change event is emitted when the set of selected items changes.\n *\n * @param {OO.ui.Element[]} items Items currently in the group\n */\n\n/* Methods */\n\n/**\n * Set the group element.\n *\n * If an element is already set, items will be moved to the new element.\n *\n * @param {jQuery} $group Element to use as group\n */\nOO.ui.mixin.GroupElement.prototype.setGroupElement = function ( $group ) {\n\tvar i, len;\n\n\tthis.$group = $group;\n\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\tthis.$group.append( this.items[ i ].$element );\n\t}\n};\n\n/**\n * Get an item by its data.\n *\n * Only the first item with matching data will be returned. To return all matching items,\n * use the #getItemsFromData method.\n *\n * @param {Object} data Item data to search for\n * @return {OO.ui.Element|null} Item with equivalent data, `null` if none exists\n */\nOO.ui.mixin.GroupElement.prototype.getItemFromData = function ( data ) {\n\tvar i, len, item,\n\t\thash = OO.getHash( data );\n\n\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\titem = this.items[ i ];\n\t\tif ( hash === OO.getHash( item.getData() ) ) {\n\t\t\treturn item;\n\t\t}\n\t}\n\n\treturn null;\n};\n\n/**\n * Get items by their data.\n *\n * All items with matching data will be returned. To return only the first match, use the #getItemFromData method instead.\n *\n * @param {Object} data Item data to search for\n * @return {OO.ui.Element[]} Items with equivalent data\n */\nOO.ui.mixin.GroupElement.prototype.getItemsFromData = function ( data ) {\n\tvar i, len, item,\n\t\thash = OO.getHash( data ),\n\t\titems = [];\n\n\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\titem = this.items[ i ];\n\t\tif ( hash === OO.getHash( item.getData() ) ) {\n\t\t\titems.push( item );\n\t\t}\n\t}\n\n\treturn items;\n};\n\n/**\n * Add items to the group.\n *\n * Items will be added to the end of the group array unless the optional `index` parameter specifies\n * a different insertion point. Adding an existing item will move it to the end of the array or the point specified by the `index`.\n *\n * @param {OO.ui.Element[]} items An array of items to add to the group\n * @param {number} [index] Index of the insertion point\n * @chainable\n */\nOO.ui.mixin.GroupElement.prototype.addItems = function ( items, index ) {\n\t// Mixin method\n\tOO.EmitterList.prototype.addItems.call( this, items, index );\n\n\tthis.emit( 'change', this.getItems() );\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.mixin.GroupElement.prototype.moveItem = function ( items, newIndex ) {\n\t// insertItemElements expects this.items to not have been modified yet, so call before the mixin\n\tthis.insertItemElements( items, newIndex );\n\n\t// Mixin method\n\tnewIndex = OO.EmitterList.prototype.moveItem.call( this, items, newIndex );\n\n\treturn newIndex;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.mixin.GroupElement.prototype.insertItem = function ( item, index ) {\n\titem.setElementGroup( this );\n\tthis.insertItemElements( item, index );\n\n\t// Mixin method\n\tindex = OO.EmitterList.prototype.insertItem.call( this, item, index );\n\n\treturn index;\n};\n\n/**\n * Insert elements into the group\n *\n * @private\n * @param {OO.ui.Element} itemWidget Item to insert\n * @param {number} index Insertion index\n */\nOO.ui.mixin.GroupElement.prototype.insertItemElements = function ( itemWidget, index ) {\n\tif ( index === undefined || index < 0 || index >= this.items.length ) {\n\t\tthis.$group.append( itemWidget.$element );\n\t} else if ( index === 0 ) {\n\t\tthis.$group.prepend( itemWidget.$element );\n\t} else {\n\t\tthis.items[ index ].$element.before( itemWidget.$element );\n\t}\n};\n\n/**\n * Remove the specified items from a group.\n *\n * Removed items are detached (not removed) from the DOM so that they may be reused.\n * To remove all items from a group, you may wish to use the #clearItems method instead.\n *\n * @param {OO.ui.Element[]} items An array of items to remove\n * @chainable\n */\nOO.ui.mixin.GroupElement.prototype.removeItems = function ( items ) {\n\tvar i, len, item, index;\n\n\t// Remove specific items elements\n\tfor ( i = 0, len = items.length; i < len; i++ ) {\n\t\titem = items[ i ];\n\t\tindex = this.items.indexOf( item );\n\t\tif ( index !== -1 ) {\n\t\t\titem.setElementGroup( null );\n\t\t\titem.$element.detach();\n\t\t}\n\t}\n\n\t// Mixin method\n\tOO.EmitterList.prototype.removeItems.call( this, items );\n\n\tthis.emit( 'change', this.getItems() );\n\treturn this;\n};\n\n/**\n * Clear all items from the group.\n *\n * Cleared items are detached from the DOM, not removed, so that they may be reused.\n * To remove only a subset of items from a group, use the #removeItems method.\n *\n * @chainable\n */\nOO.ui.mixin.GroupElement.prototype.clearItems = function () {\n\tvar i, len;\n\n\t// Remove all item elements\n\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\tthis.items[ i ].setElementGroup( null );\n\t\tthis.items[ i ].$element.detach();\n\t}\n\n\t// Mixin method\n\tOO.EmitterList.prototype.clearItems.call( this );\n\n\tthis.emit( 'change', this.getItems() );\n\treturn this;\n};\n","/**\n * IconElement is often mixed into other classes to generate an icon.\n * Icons are graphics, about the size of normal text. They are used to aid the user\n * in locating a control or to convey information in a space-efficient way. See the\n * [OOjs UI documentation on MediaWiki] [1] for a list of icons\n * included in the library.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Icons\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$icon] The icon element created by the class. If this configuration is omitted,\n * the icon element will use a generated `<span>`. To use a different HTML tag, or to specify that\n * the icon element be set to an existing icon instead of the one generated by this class, set a\n * value using a jQuery selection. For example:\n *\n * // Use a <div> tag instead of a <span>\n * $icon: $(\"<div>\")\n * // Use an existing icon element instead of the one generated by the class\n * $icon: this.$element\n * // Use an icon element from a child widget\n * $icon: this.childwidget.$element\n * @cfg {Object|string} [icon=''] The symbolic name of the icon (e.g., ‘remove’ or ‘menu’), or a map of\n * symbolic names. A map is used for i18n purposes and contains a `default` icon\n * name and additional names keyed by language code. The `default` name is used when no icon is keyed\n * by the user's language.\n *\n * Example of an i18n map:\n *\n * { default: 'bold-a', en: 'bold-b', de: 'bold-f' }\n * See the [OOjs UI documentation on MediaWiki] [2] for a list of icons included in the library.\n * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Icons\n * @cfg {string|Function} [iconTitle] A text string used as the icon title, or a function that returns title\n * text. The icon title is displayed when users move the mouse over the icon.\n */\nOO.ui.mixin.IconElement = function OoUiMixinIconElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.$icon = null;\n\tthis.icon = null;\n\tthis.iconTitle = null;\n\n\t// Initialization\n\tthis.setIcon( config.icon || this.constructor.static.icon );\n\tthis.setIconTitle( config.iconTitle || this.constructor.static.iconTitle );\n\tthis.setIconElement( config.$icon || $( '<span>' ) );\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.mixin.IconElement );\n\n/* Static Properties */\n\n/**\n * The symbolic name of the icon (e.g., ‘remove’ or ‘menu’), or a map of symbolic names. A map is used\n * for i18n purposes and contains a `default` icon name and additional names keyed by\n * language code. The `default` name is used when no icon is keyed by the user's language.\n *\n * Example of an i18n map:\n *\n * { default: 'bold-a', en: 'bold-b', de: 'bold-f' }\n *\n * Note: the static property will be overridden if the #icon configuration is used.\n *\n * @static\n * @inheritable\n * @property {Object|string}\n */\nOO.ui.mixin.IconElement.static.icon = null;\n\n/**\n * The icon title, displayed when users move the mouse over the icon. The value can be text, a\n * function that returns title text, or `null` for no title.\n *\n * The static property will be overridden if the #iconTitle configuration is used.\n *\n * @static\n * @inheritable\n * @property {string|Function|null}\n */\nOO.ui.mixin.IconElement.static.iconTitle = null;\n\n/* Methods */\n\n/**\n * Set the icon element. This method is used to retarget an icon mixin so that its functionality\n * applies to the specified icon element instead of the one created by the class. If an icon\n * element is already set, the mixin’s effect on that element is removed. Generated CSS classes\n * and mixin methods will no longer affect the element.\n *\n * @param {jQuery} $icon Element to use as icon\n */\nOO.ui.mixin.IconElement.prototype.setIconElement = function ( $icon ) {\n\tif ( this.$icon ) {\n\t\tthis.$icon\n\t\t\t.removeClass( 'oo-ui-iconElement-icon oo-ui-icon-' + this.icon )\n\t\t\t.removeAttr( 'title' );\n\t}\n\n\tthis.$icon = $icon\n\t\t.addClass( 'oo-ui-iconElement-icon' )\n\t\t.toggleClass( 'oo-ui-icon-' + this.icon, !!this.icon );\n\tif ( this.iconTitle !== null ) {\n\t\tthis.$icon.attr( 'title', this.iconTitle );\n\t}\n\n\tthis.updateThemeClasses();\n};\n\n/**\n * Set icon by symbolic name (e.g., ‘remove’ or ‘menu’). Use `null` to remove an icon.\n * The icon parameter can also be set to a map of icon names. See the #icon config setting\n * for an example.\n *\n * @param {Object|string|null} icon A symbolic icon name, a {@link #icon map of icon names} keyed\n * by language code, or `null` to remove the icon.\n * @chainable\n */\nOO.ui.mixin.IconElement.prototype.setIcon = function ( icon ) {\n\ticon = OO.isPlainObject( icon ) ? OO.ui.getLocalValue( icon, null, 'default' ) : icon;\n\ticon = typeof icon === 'string' && icon.trim().length ? icon.trim() : null;\n\n\tif ( this.icon !== icon ) {\n\t\tif ( this.$icon ) {\n\t\t\tif ( this.icon !== null ) {\n\t\t\t\tthis.$icon.removeClass( 'oo-ui-icon-' + this.icon );\n\t\t\t}\n\t\t\tif ( icon !== null ) {\n\t\t\t\tthis.$icon.addClass( 'oo-ui-icon-' + icon );\n\t\t\t}\n\t\t}\n\t\tthis.icon = icon;\n\t}\n\n\tthis.$element.toggleClass( 'oo-ui-iconElement', !!this.icon );\n\tthis.updateThemeClasses();\n\n\treturn this;\n};\n\n/**\n * Set the icon title. Use `null` to remove the title.\n *\n * @param {string|Function|null} iconTitle A text string used as the icon title,\n * a function that returns title text, or `null` for no title.\n * @chainable\n */\nOO.ui.mixin.IconElement.prototype.setIconTitle = function ( iconTitle ) {\n\ticonTitle =\n\t\t( typeof iconTitle === 'function' || ( typeof iconTitle === 'string' && iconTitle.length ) ) ?\n\t\t\tOO.ui.resolveMsg( iconTitle ) : null;\n\n\tif ( this.iconTitle !== iconTitle ) {\n\t\tthis.iconTitle = iconTitle;\n\t\tif ( this.$icon ) {\n\t\t\tif ( this.iconTitle !== null ) {\n\t\t\t\tthis.$icon.attr( 'title', iconTitle );\n\t\t\t} else {\n\t\t\t\tthis.$icon.removeAttr( 'title' );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Get the symbolic name of the icon.\n *\n * @return {string} Icon name\n */\nOO.ui.mixin.IconElement.prototype.getIcon = function () {\n\treturn this.icon;\n};\n\n/**\n * Get the icon title. The title text is displayed when a user moves the mouse over the icon.\n *\n * @return {string} Icon title text\n */\nOO.ui.mixin.IconElement.prototype.getIconTitle = function () {\n\treturn this.iconTitle;\n};\n","/**\n * IndicatorElement is often mixed into other classes to generate an indicator.\n * Indicators are small graphics that are generally used in two ways:\n *\n * - To draw attention to the status of an item. For example, an indicator might be\n * used to show that an item in a list has errors that need to be resolved.\n * - To clarify the function of a control that acts in an exceptional way (a button\n * that opens a menu instead of performing an action directly, for example).\n *\n * For a list of indicators included in the library, please see the\n * [OOjs UI documentation on MediaWiki] [1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Indicators\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$indicator] The indicator element created by the class. If this\n * configuration is omitted, the indicator element will use a generated `<span>`.\n * @cfg {string} [indicator] Symbolic name of the indicator (e.g., ‘alert’ or ‘down’).\n * See the [OOjs UI documentation on MediaWiki][2] for a list of indicators included\n * in the library.\n * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Indicators\n * @cfg {string|Function} [indicatorTitle] A text string used as the indicator title,\n * or a function that returns title text. The indicator title is displayed when users move\n * the mouse over the indicator.\n */\nOO.ui.mixin.IndicatorElement = function OoUiMixinIndicatorElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.$indicator = null;\n\tthis.indicator = null;\n\tthis.indicatorTitle = null;\n\n\t// Initialization\n\tthis.setIndicator( config.indicator || this.constructor.static.indicator );\n\tthis.setIndicatorTitle( config.indicatorTitle || this.constructor.static.indicatorTitle );\n\tthis.setIndicatorElement( config.$indicator || $( '<span>' ) );\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.mixin.IndicatorElement );\n\n/* Static Properties */\n\n/**\n * Symbolic name of the indicator (e.g., ‘alert’ or ‘down’).\n * The static property will be overridden if the #indicator configuration is used.\n *\n * @static\n * @inheritable\n * @property {string|null}\n */\nOO.ui.mixin.IndicatorElement.static.indicator = null;\n\n/**\n * A text string used as the indicator title, a function that returns title text, or `null`\n * for no title. The static property will be overridden if the #indicatorTitle configuration is used.\n *\n * @static\n * @inheritable\n * @property {string|Function|null}\n */\nOO.ui.mixin.IndicatorElement.static.indicatorTitle = null;\n\n/* Methods */\n\n/**\n * Set the indicator element.\n *\n * If an element is already set, it will be cleaned up before setting up the new element.\n *\n * @param {jQuery} $indicator Element to use as indicator\n */\nOO.ui.mixin.IndicatorElement.prototype.setIndicatorElement = function ( $indicator ) {\n\tif ( this.$indicator ) {\n\t\tthis.$indicator\n\t\t\t.removeClass( 'oo-ui-indicatorElement-indicator oo-ui-indicator-' + this.indicator )\n\t\t\t.removeAttr( 'title' );\n\t}\n\n\tthis.$indicator = $indicator\n\t\t.addClass( 'oo-ui-indicatorElement-indicator' )\n\t\t.toggleClass( 'oo-ui-indicator-' + this.indicator, !!this.indicator );\n\tif ( this.indicatorTitle !== null ) {\n\t\tthis.$indicator.attr( 'title', this.indicatorTitle );\n\t}\n\n\tthis.updateThemeClasses();\n};\n\n/**\n * Set the indicator by its symbolic name: ‘alert’, ‘down’, ‘next’, ‘previous’, ‘required’, ‘up’. Use `null` to remove the indicator.\n *\n * @param {string|null} indicator Symbolic name of indicator, or `null` for no indicator\n * @chainable\n */\nOO.ui.mixin.IndicatorElement.prototype.setIndicator = function ( indicator ) {\n\tindicator = typeof indicator === 'string' && indicator.length ? indicator.trim() : null;\n\n\tif ( this.indicator !== indicator ) {\n\t\tif ( this.$indicator ) {\n\t\t\tif ( this.indicator !== null ) {\n\t\t\t\tthis.$indicator.removeClass( 'oo-ui-indicator-' + this.indicator );\n\t\t\t}\n\t\t\tif ( indicator !== null ) {\n\t\t\t\tthis.$indicator.addClass( 'oo-ui-indicator-' + indicator );\n\t\t\t}\n\t\t}\n\t\tthis.indicator = indicator;\n\t}\n\n\tthis.$element.toggleClass( 'oo-ui-indicatorElement', !!this.indicator );\n\tthis.updateThemeClasses();\n\n\treturn this;\n};\n\n/**\n * Set the indicator title.\n *\n * The title is displayed when a user moves the mouse over the indicator.\n *\n * @param {string|Function|null} indicatorTitle Indicator title text, a function that returns text, or\n * `null` for no indicator title\n * @chainable\n */\nOO.ui.mixin.IndicatorElement.prototype.setIndicatorTitle = function ( indicatorTitle ) {\n\tindicatorTitle =\n\t\t( typeof indicatorTitle === 'function' || ( typeof indicatorTitle === 'string' && indicatorTitle.length ) ) ?\n\t\t\tOO.ui.resolveMsg( indicatorTitle ) : null;\n\n\tif ( this.indicatorTitle !== indicatorTitle ) {\n\t\tthis.indicatorTitle = indicatorTitle;\n\t\tif ( this.$indicator ) {\n\t\t\tif ( this.indicatorTitle !== null ) {\n\t\t\t\tthis.$indicator.attr( 'title', indicatorTitle );\n\t\t\t} else {\n\t\t\t\tthis.$indicator.removeAttr( 'title' );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Get the symbolic name of the indicator (e.g., ‘alert’ or ‘down’).\n *\n * @return {string} Symbolic name of indicator\n */\nOO.ui.mixin.IndicatorElement.prototype.getIndicator = function () {\n\treturn this.indicator;\n};\n\n/**\n * Get the indicator title.\n *\n * The title is displayed when a user moves the mouse over the indicator.\n *\n * @return {string} Indicator title text\n */\nOO.ui.mixin.IndicatorElement.prototype.getIndicatorTitle = function () {\n\treturn this.indicatorTitle;\n};\n","/**\n * LabelElement is often mixed into other classes to generate a label, which\n * helps identify the function of an interface element.\n * See the [OOjs UI documentation on MediaWiki] [1] for more information.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Labels\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$label] The label element created by the class. If this\n * configuration is omitted, the label element will use a generated `<span>`.\n * @cfg {jQuery|string|Function|OO.ui.HtmlSnippet} [label] The label text. The label can be specified\n * as a plaintext string, a jQuery selection of elements, or a function that will produce a string\n * in the future. See the [OOjs UI documentation on MediaWiki] [2] for examples.\n * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Labels\n */\nOO.ui.mixin.LabelElement = function OoUiMixinLabelElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.$label = null;\n\tthis.label = null;\n\n\t// Initialization\n\tthis.setLabel( config.label || this.constructor.static.label );\n\tthis.setLabelElement( config.$label || $( '<span>' ) );\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.mixin.LabelElement );\n\n/* Events */\n\n/**\n * @event labelChange\n * @param {string} value\n */\n\n/* Static Properties */\n\n/**\n * The label text. The label can be specified as a plaintext string, a function that will\n * produce a string in the future, or `null` for no label. The static value will\n * be overridden if a label is specified with the #label config option.\n *\n * @static\n * @inheritable\n * @property {string|Function|null}\n */\nOO.ui.mixin.LabelElement.static.label = null;\n\n/* Static methods */\n\n/**\n * Highlight the first occurrence of the query in the given text\n *\n * @param {string} text Text\n * @param {string} query Query to find\n * @return {jQuery} Text with the first match of the query\n * sub-string wrapped in highlighted span\n */\nOO.ui.mixin.LabelElement.static.highlightQuery = function ( text, query ) {\n\tvar $result = $( '<span>' ),\n\t\toffset = text.toLowerCase().indexOf( query.toLowerCase() );\n\n\tif ( !query.length || offset === -1 ) {\n\t\treturn $result.text( text );\n\t}\n\t$result.append(\n\t\tdocument.createTextNode( text.slice( 0, offset ) ),\n\t\t$( '<span>' )\n\t\t\t.addClass( 'oo-ui-labelElement-label-highlight' )\n\t\t\t.text( text.slice( offset, offset + query.length ) ),\n\t\tdocument.createTextNode( text.slice( offset + query.length ) )\n\t);\n\treturn $result.contents();\n};\n\n/* Methods */\n\n/**\n * Set the label element.\n *\n * If an element is already set, it will be cleaned up before setting up the new element.\n *\n * @param {jQuery} $label Element to use as label\n */\nOO.ui.mixin.LabelElement.prototype.setLabelElement = function ( $label ) {\n\tif ( this.$label ) {\n\t\tthis.$label.removeClass( 'oo-ui-labelElement-label' ).empty();\n\t}\n\n\tthis.$label = $label.addClass( 'oo-ui-labelElement-label' );\n\tthis.setLabelContent( this.label );\n};\n\n/**\n * Set the label.\n *\n * An empty string will result in the label being hidden. A string containing only whitespace will\n * be converted to a single `&nbsp;`.\n *\n * @param {jQuery|string|OO.ui.HtmlSnippet|Function|null} label Label nodes; text; a function that returns nodes or\n * text; or null for no label\n * @chainable\n */\nOO.ui.mixin.LabelElement.prototype.setLabel = function ( label ) {\n\tlabel = typeof label === 'function' ? OO.ui.resolveMsg( label ) : label;\n\tlabel = ( ( typeof label === 'string' || label instanceof jQuery ) && label.length ) || ( label instanceof OO.ui.HtmlSnippet && label.toString().length ) ? label : null;\n\n\tif ( this.label !== label ) {\n\t\tif ( this.$label ) {\n\t\t\tthis.setLabelContent( label );\n\t\t}\n\t\tthis.label = label;\n\t\tthis.emit( 'labelChange' );\n\t}\n\n\tthis.$element.toggleClass( 'oo-ui-labelElement', !!this.label );\n\n\treturn this;\n};\n\n/**\n * Set the label as plain text with a highlighted query\n *\n * @param {string} text Text label to set\n * @param {string} query Substring of text to highlight\n * @chainable\n */\nOO.ui.mixin.LabelElement.prototype.setHighlightedQuery = function ( text, query ) {\n\treturn this.setLabel( this.constructor.static.highlightQuery( text, query ) );\n};\n\n/**\n * Get the label.\n *\n * @return {jQuery|string|Function|null} Label nodes; text; a function that returns nodes or\n * text; or null for no label\n */\nOO.ui.mixin.LabelElement.prototype.getLabel = function () {\n\treturn this.label;\n};\n\n/**\n * Set the content of the label.\n *\n * Do not call this method until after the label element has been set by #setLabelElement.\n *\n * @private\n * @param {jQuery|string|Function|null} label Label nodes; text; a function that returns nodes or\n * text; or null for no label\n */\nOO.ui.mixin.LabelElement.prototype.setLabelContent = function ( label ) {\n\tif ( typeof label === 'string' ) {\n\t\tif ( label.match( /^\\s*$/ ) ) {\n\t\t\t// Convert whitespace only string to a single non-breaking space\n\t\t\tthis.$label.html( '&nbsp;' );\n\t\t} else {\n\t\t\tthis.$label.text( label );\n\t\t}\n\t} else if ( label instanceof OO.ui.HtmlSnippet ) {\n\t\tthis.$label.html( label.toString() );\n\t} else if ( label instanceof jQuery ) {\n\t\tthis.$label.empty().append( label );\n\t} else {\n\t\tthis.$label.empty();\n\t}\n};\n","/**\n * The FlaggedElement class is an attribute mixin, meaning that it is used to add\n * additional functionality to an element created by another class. The class provides\n * a ‘flags’ property assigned the name (or an array of names) of styling flags,\n * which are used to customize the look and feel of a widget to better describe its\n * importance and functionality.\n *\n * The library currently contains the following styling flags for general use:\n *\n * - **progressive**: Progressive styling is applied to convey that the widget will move the user forward in a process.\n * - **destructive**: Destructive styling is applied to convey that the widget will remove something.\n * - **constructive**: Constructive styling is applied to convey that the widget will create something.\n *\n * The flags affect the appearance of the buttons:\n *\n * @example\n * // FlaggedElement is mixed into ButtonWidget to provide styling flags\n * var button1 = new OO.ui.ButtonWidget( {\n * label: 'Constructive',\n * flags: 'constructive'\n * } );\n * var button2 = new OO.ui.ButtonWidget( {\n * label: 'Destructive',\n * flags: 'destructive'\n * } );\n * var button3 = new OO.ui.ButtonWidget( {\n * label: 'Progressive',\n * flags: 'progressive'\n * } );\n * $( 'body' ).append( button1.$element, button2.$element, button3.$element );\n *\n * {@link OO.ui.ActionWidget ActionWidgets}, which are a special kind of button that execute an action, use these flags: **primary** and **safe**.\n * Please see the [OOjs UI documentation on MediaWiki] [1] for more information.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Elements/Flagged\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string|string[]} [flags] The name or names of the flags (e.g., 'constructive' or 'primary') to apply.\n * Please see the [OOjs UI documentation on MediaWiki] [2] for more information about available flags.\n * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Elements/Flagged\n * @cfg {jQuery} [$flagged] The flagged element. By default,\n * the flagged functionality is applied to the element created by the class ($element).\n * If a different element is specified, the flagged functionality will be applied to it instead.\n */\nOO.ui.mixin.FlaggedElement = function OoUiMixinFlaggedElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.flags = {};\n\tthis.$flagged = null;\n\n\t// Initialization\n\tthis.setFlags( config.flags );\n\tthis.setFlaggedElement( config.$flagged || this.$element );\n};\n\n/* Events */\n\n/**\n * @event flag\n * A flag event is emitted when the #clearFlags or #setFlags methods are used. The `changes`\n * parameter contains the name of each modified flag and indicates whether it was\n * added or removed.\n *\n * @param {Object.<string,boolean>} changes Object keyed by flag name. A Boolean `true` indicates\n * that the flag was added, `false` that the flag was removed.\n */\n\n/* Methods */\n\n/**\n * Set the flagged element.\n *\n * This method is used to retarget a flagged mixin so that its functionality applies to the specified element.\n * If an element is already set, the method will remove the mixin’s effect on that element.\n *\n * @param {jQuery} $flagged Element that should be flagged\n */\nOO.ui.mixin.FlaggedElement.prototype.setFlaggedElement = function ( $flagged ) {\n\tvar classNames = Object.keys( this.flags ).map( function ( flag ) {\n\t\treturn 'oo-ui-flaggedElement-' + flag;\n\t} ).join( ' ' );\n\n\tif ( this.$flagged ) {\n\t\tthis.$flagged.removeClass( classNames );\n\t}\n\n\tthis.$flagged = $flagged.addClass( classNames );\n};\n\n/**\n * Check if the specified flag is set.\n *\n * @param {string} flag Name of flag\n * @return {boolean} The flag is set\n */\nOO.ui.mixin.FlaggedElement.prototype.hasFlag = function ( flag ) {\n\t// This may be called before the constructor, thus before this.flags is set\n\treturn this.flags && ( flag in this.flags );\n};\n\n/**\n * Get the names of all flags set.\n *\n * @return {string[]} Flag names\n */\nOO.ui.mixin.FlaggedElement.prototype.getFlags = function () {\n\t// This may be called before the constructor, thus before this.flags is set\n\treturn Object.keys( this.flags || {} );\n};\n\n/**\n * Clear all flags.\n *\n * @chainable\n * @fires flag\n */\nOO.ui.mixin.FlaggedElement.prototype.clearFlags = function () {\n\tvar flag, className,\n\t\tchanges = {},\n\t\tremove = [],\n\t\tclassPrefix = 'oo-ui-flaggedElement-';\n\n\tfor ( flag in this.flags ) {\n\t\tclassName = classPrefix + flag;\n\t\tchanges[ flag ] = false;\n\t\tdelete this.flags[ flag ];\n\t\tremove.push( className );\n\t}\n\n\tif ( this.$flagged ) {\n\t\tthis.$flagged.removeClass( remove.join( ' ' ) );\n\t}\n\n\tthis.updateThemeClasses();\n\tthis.emit( 'flag', changes );\n\n\treturn this;\n};\n\n/**\n * Add one or more flags.\n *\n * @param {string|string[]|Object.<string, boolean>} flags A flag name, an array of flag names,\n * or an object keyed by flag name with a boolean value that indicates whether the flag should\n * be added (`true`) or removed (`false`).\n * @chainable\n * @fires flag\n */\nOO.ui.mixin.FlaggedElement.prototype.setFlags = function ( flags ) {\n\tvar i, len, flag, className,\n\t\tchanges = {},\n\t\tadd = [],\n\t\tremove = [],\n\t\tclassPrefix = 'oo-ui-flaggedElement-';\n\n\tif ( typeof flags === 'string' ) {\n\t\tclassName = classPrefix + flags;\n\t\t// Set\n\t\tif ( !this.flags[ flags ] ) {\n\t\t\tthis.flags[ flags ] = true;\n\t\t\tadd.push( className );\n\t\t}\n\t} else if ( Array.isArray( flags ) ) {\n\t\tfor ( i = 0, len = flags.length; i < len; i++ ) {\n\t\t\tflag = flags[ i ];\n\t\t\tclassName = classPrefix + flag;\n\t\t\t// Set\n\t\t\tif ( !this.flags[ flag ] ) {\n\t\t\t\tchanges[ flag ] = true;\n\t\t\t\tthis.flags[ flag ] = true;\n\t\t\t\tadd.push( className );\n\t\t\t}\n\t\t}\n\t} else if ( OO.isPlainObject( flags ) ) {\n\t\tfor ( flag in flags ) {\n\t\t\tclassName = classPrefix + flag;\n\t\t\tif ( flags[ flag ] ) {\n\t\t\t\t// Set\n\t\t\t\tif ( !this.flags[ flag ] ) {\n\t\t\t\t\tchanges[ flag ] = true;\n\t\t\t\t\tthis.flags[ flag ] = true;\n\t\t\t\t\tadd.push( className );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// Remove\n\t\t\t\tif ( this.flags[ flag ] ) {\n\t\t\t\t\tchanges[ flag ] = false;\n\t\t\t\t\tdelete this.flags[ flag ];\n\t\t\t\t\tremove.push( className );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( this.$flagged ) {\n\t\tthis.$flagged\n\t\t\t.addClass( add.join( ' ' ) )\n\t\t\t.removeClass( remove.join( ' ' ) );\n\t}\n\n\tthis.updateThemeClasses();\n\tthis.emit( 'flag', changes );\n\n\treturn this;\n};\n","/**\n * TitledElement is mixed into other classes to provide a `title` attribute.\n * Titles are rendered by the browser and are made visible when the user moves\n * the mouse over the element. Titles are not visible on touch devices.\n *\n * @example\n * // TitledElement provides a 'title' attribute to the\n * // ButtonWidget class\n * var button = new OO.ui.ButtonWidget( {\n * label: 'Button with Title',\n * title: 'I am a button'\n * } );\n * $( 'body' ).append( button.$element );\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$titled] The element to which the `title` attribute is applied.\n * If this config is omitted, the title functionality is applied to $element, the\n * element created by the class.\n * @cfg {string|Function} [title] The title text or a function that returns text. If\n * this config is omitted, the value of the {@link #static-title static title} property is used.\n */\nOO.ui.mixin.TitledElement = function OoUiMixinTitledElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.$titled = null;\n\tthis.title = null;\n\n\t// Initialization\n\tthis.setTitle( config.title !== undefined ? config.title : this.constructor.static.title );\n\tthis.setTitledElement( config.$titled || this.$element );\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.mixin.TitledElement );\n\n/* Static Properties */\n\n/**\n * The title text, a function that returns text, or `null` for no title. The value of the static property\n * is overridden if the #title config option is used.\n *\n * @static\n * @inheritable\n * @property {string|Function|null}\n */\nOO.ui.mixin.TitledElement.static.title = null;\n\n/* Methods */\n\n/**\n * Set the titled element.\n *\n * This method is used to retarget a titledElement mixin so that its functionality applies to the specified element.\n * If an element is already set, the mixin’s effect on that element is removed before the new element is set up.\n *\n * @param {jQuery} $titled Element that should use the 'titled' functionality\n */\nOO.ui.mixin.TitledElement.prototype.setTitledElement = function ( $titled ) {\n\tif ( this.$titled ) {\n\t\tthis.$titled.removeAttr( 'title' );\n\t}\n\n\tthis.$titled = $titled;\n\tif ( this.title ) {\n\t\tthis.updateTitle();\n\t}\n};\n\n/**\n * Set title.\n *\n * @param {string|Function|null} title Title text, a function that returns text, or `null` for no title\n * @chainable\n */\nOO.ui.mixin.TitledElement.prototype.setTitle = function ( title ) {\n\ttitle = typeof title === 'function' ? OO.ui.resolveMsg( title ) : title;\n\ttitle = ( typeof title === 'string' && title.length ) ? title : null;\n\n\tif ( this.title !== title ) {\n\t\tthis.title = title;\n\t\tthis.updateTitle();\n\t}\n\n\treturn this;\n};\n\n/**\n * Update the title attribute, in case of changes to title or accessKey.\n *\n * @protected\n * @chainable\n */\nOO.ui.mixin.TitledElement.prototype.updateTitle = function () {\n\tvar title = this.getTitle();\n\tif ( this.$titled ) {\n\t\tif ( title !== null ) {\n\t\t\t// Only if this is an AccessKeyedElement\n\t\t\tif ( this.formatTitleWithAccessKey ) {\n\t\t\t\ttitle = this.formatTitleWithAccessKey( title );\n\t\t\t}\n\t\t\tthis.$titled.attr( 'title', title );\n\t\t} else {\n\t\t\tthis.$titled.removeAttr( 'title' );\n\t\t}\n\t}\n\treturn this;\n};\n\n/**\n * Get title.\n *\n * @return {string} Title string\n */\nOO.ui.mixin.TitledElement.prototype.getTitle = function () {\n\treturn this.title;\n};\n","/**\n * AccessKeyedElement is mixed into other classes to provide an `accesskey` attribute.\n * Accesskeys allow an user to go to a specific element by using\n * a shortcut combination of a browser specific keys + the key\n * set to the field.\n *\n * @example\n * // AccessKeyedElement provides an 'accesskey' attribute to the\n * // ButtonWidget class\n * var button = new OO.ui.ButtonWidget( {\n * label: 'Button with Accesskey',\n * accessKey: 'k'\n * } );\n * $( 'body' ).append( button.$element );\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$accessKeyed] The element to which the `accesskey` attribute is applied.\n * If this config is omitted, the accesskey functionality is applied to $element, the\n * element created by the class.\n * @cfg {string|Function} [accessKey] The key or a function that returns the key. If\n * this config is omitted, no accesskey will be added.\n */\nOO.ui.mixin.AccessKeyedElement = function OoUiMixinAccessKeyedElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.$accessKeyed = null;\n\tthis.accessKey = null;\n\n\t// Initialization\n\tthis.setAccessKey( config.accessKey || null );\n\tthis.setAccessKeyedElement( config.$accessKeyed || this.$element );\n\n\t// If this is also a TitledElement and it initialized before we did, we may have\n\t// to update the title with the access key\n\tif ( this.updateTitle ) {\n\t\tthis.updateTitle();\n\t}\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.mixin.AccessKeyedElement );\n\n/* Static Properties */\n\n/**\n * The access key, a function that returns a key, or `null` for no accesskey.\n *\n * @static\n * @inheritable\n * @property {string|Function|null}\n */\nOO.ui.mixin.AccessKeyedElement.static.accessKey = null;\n\n/* Methods */\n\n/**\n * Set the accesskeyed element.\n *\n * This method is used to retarget a AccessKeyedElement mixin so that its functionality applies to the specified element.\n * If an element is already set, the mixin's effect on that element is removed before the new element is set up.\n *\n * @param {jQuery} $accessKeyed Element that should use the 'accesskeyes' functionality\n */\nOO.ui.mixin.AccessKeyedElement.prototype.setAccessKeyedElement = function ( $accessKeyed ) {\n\tif ( this.$accessKeyed ) {\n\t\tthis.$accessKeyed.removeAttr( 'accesskey' );\n\t}\n\n\tthis.$accessKeyed = $accessKeyed;\n\tif ( this.accessKey ) {\n\t\tthis.$accessKeyed.attr( 'accesskey', this.accessKey );\n\t}\n};\n\n/**\n * Set accesskey.\n *\n * @param {string|Function|null} accessKey Key, a function that returns a key, or `null` for no accesskey\n * @chainable\n */\nOO.ui.mixin.AccessKeyedElement.prototype.setAccessKey = function ( accessKey ) {\n\taccessKey = typeof accessKey === 'string' ? OO.ui.resolveMsg( accessKey ) : null;\n\n\tif ( this.accessKey !== accessKey ) {\n\t\tif ( this.$accessKeyed ) {\n\t\t\tif ( accessKey !== null ) {\n\t\t\t\tthis.$accessKeyed.attr( 'accesskey', accessKey );\n\t\t\t} else {\n\t\t\t\tthis.$accessKeyed.removeAttr( 'accesskey' );\n\t\t\t}\n\t\t}\n\t\tthis.accessKey = accessKey;\n\n\t\t// Only if this is a TitledElement\n\t\tif ( this.updateTitle ) {\n\t\t\tthis.updateTitle();\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Get accesskey.\n *\n * @return {string} accessKey string\n */\nOO.ui.mixin.AccessKeyedElement.prototype.getAccessKey = function () {\n\treturn this.accessKey;\n};\n\n/**\n * Add information about the access key to the element's tooltip label.\n * (This is only public for hacky usage in FieldLayout.)\n *\n * @param {string} title Tooltip label for `title` attribute\n * @return {string}\n */\nOO.ui.mixin.AccessKeyedElement.prototype.formatTitleWithAccessKey = function ( title ) {\n\tvar accessKey;\n\n\tif ( !this.$accessKeyed ) {\n\t\t// Not initialized yet; the constructor will call updateTitle() which will rerun this function\n\t\treturn title;\n\t}\n\t// Use jquery.accessKeyLabel if available to show modifiers, otherwise just display the single key\n\tif ( $.fn.updateTooltipAccessKeys && $.fn.updateTooltipAccessKeys.getAccessKeyLabel ) {\n\t\taccessKey = $.fn.updateTooltipAccessKeys.getAccessKeyLabel( this.$accessKeyed[ 0 ] );\n\t} else {\n\t\taccessKey = this.getAccessKey();\n\t}\n\tif ( accessKey ) {\n\t\ttitle += ' [' + accessKey + ']';\n\t}\n\treturn title;\n};\n","/**\n * ButtonWidget is a generic widget for buttons. A wide variety of looks,\n * feels, and functionality can be customized via the class’s configuration options\n * and methods. Please see the [OOjs UI documentation on MediaWiki] [1] for more information\n * and examples.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches\n *\n * @example\n * // A button widget\n * var button = new OO.ui.ButtonWidget( {\n * label: 'Button with Icon',\n * icon: 'trash',\n * iconTitle: 'Remove'\n * } );\n * $( 'body' ).append( button.$element );\n *\n * NOTE: HTML form buttons should use the OO.ui.ButtonInputWidget class.\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.ButtonElement\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.IndicatorElement\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.TitledElement\n * @mixins OO.ui.mixin.FlaggedElement\n * @mixins OO.ui.mixin.TabIndexedElement\n * @mixins OO.ui.mixin.AccessKeyedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [active=false] Whether button should be shown as active\n * @cfg {string} [href] Hyperlink to visit when the button is clicked.\n * @cfg {string} [target] The frame or window in which to open the hyperlink.\n * @cfg {boolean} [noFollow] Search engine traversal hint (default: true)\n */\nOO.ui.ButtonWidget = function OoUiButtonWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.ButtonWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.ButtonElement.call( this, config );\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.IndicatorElement.call( this, config );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\tOO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$button } ) );\n\tOO.ui.mixin.FlaggedElement.call( this, config );\n\tOO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$button } ) );\n\tOO.ui.mixin.AccessKeyedElement.call( this, $.extend( {}, config, { $accessKeyed: this.$button } ) );\n\n\t// Properties\n\tthis.href = null;\n\tthis.target = null;\n\tthis.noFollow = false;\n\n\t// Events\n\tthis.connect( this, { disable: 'onDisable' } );\n\n\t// Initialization\n\tthis.$button.append( this.$icon, this.$label, this.$indicator );\n\tthis.$element\n\t\t.addClass( 'oo-ui-buttonWidget' )\n\t\t.append( this.$button );\n\tthis.setActive( config.active );\n\tthis.setHref( config.href );\n\tthis.setTarget( config.target );\n\tthis.setNoFollow( config.noFollow );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ButtonWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.ButtonElement );\nOO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.IndicatorElement );\nOO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.TitledElement );\nOO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.FlaggedElement );\nOO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.TabIndexedElement );\nOO.mixinClass( OO.ui.ButtonWidget, OO.ui.mixin.AccessKeyedElement );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.ButtonWidget.static.cancelButtonMouseDownEvents = false;\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.ButtonWidget.static.tagName = 'span';\n\n/* Methods */\n\n/**\n * Get hyperlink location.\n *\n * @return {string} Hyperlink location\n */\nOO.ui.ButtonWidget.prototype.getHref = function () {\n\treturn this.href;\n};\n\n/**\n * Get hyperlink target.\n *\n * @return {string} Hyperlink target\n */\nOO.ui.ButtonWidget.prototype.getTarget = function () {\n\treturn this.target;\n};\n\n/**\n * Get search engine traversal hint.\n *\n * @return {boolean} Whether search engines should avoid traversing this hyperlink\n */\nOO.ui.ButtonWidget.prototype.getNoFollow = function () {\n\treturn this.noFollow;\n};\n\n/**\n * Set hyperlink location.\n *\n * @param {string|null} href Hyperlink location, null to remove\n */\nOO.ui.ButtonWidget.prototype.setHref = function ( href ) {\n\thref = typeof href === 'string' ? href : null;\n\tif ( href !== null && !OO.ui.isSafeUrl( href ) ) {\n\t\thref = './' + href;\n\t}\n\n\tif ( href !== this.href ) {\n\t\tthis.href = href;\n\t\tthis.updateHref();\n\t}\n\n\treturn this;\n};\n\n/**\n * Update the `href` attribute, in case of changes to href or\n * disabled state.\n *\n * @private\n * @chainable\n */\nOO.ui.ButtonWidget.prototype.updateHref = function () {\n\tif ( this.href !== null && !this.isDisabled() ) {\n\t\tthis.$button.attr( 'href', this.href );\n\t} else {\n\t\tthis.$button.removeAttr( 'href' );\n\t}\n\n\treturn this;\n};\n\n/**\n * Handle disable events.\n *\n * @private\n * @param {boolean} disabled Element is disabled\n */\nOO.ui.ButtonWidget.prototype.onDisable = function () {\n\tthis.updateHref();\n};\n\n/**\n * Set hyperlink target.\n *\n * @param {string|null} target Hyperlink target, null to remove\n */\nOO.ui.ButtonWidget.prototype.setTarget = function ( target ) {\n\ttarget = typeof target === 'string' ? target : null;\n\n\tif ( target !== this.target ) {\n\t\tthis.target = target;\n\t\tif ( target !== null ) {\n\t\t\tthis.$button.attr( 'target', target );\n\t\t} else {\n\t\t\tthis.$button.removeAttr( 'target' );\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Set search engine traversal hint.\n *\n * @param {boolean} noFollow True if search engines should avoid traversing this hyperlink\n */\nOO.ui.ButtonWidget.prototype.setNoFollow = function ( noFollow ) {\n\tnoFollow = typeof noFollow === 'boolean' ? noFollow : true;\n\n\tif ( noFollow !== this.noFollow ) {\n\t\tthis.noFollow = noFollow;\n\t\tif ( noFollow ) {\n\t\t\tthis.$button.attr( 'rel', 'nofollow' );\n\t\t} else {\n\t\t\tthis.$button.removeAttr( 'rel' );\n\t\t}\n\t}\n\n\treturn this;\n};\n\n// Override method visibility hints from ButtonElement\n/**\n * @method setActive\n * @inheritdoc\n */\n/**\n * @method isActive\n * @inheritdoc\n */\n","/**\n * A ButtonGroupWidget groups related buttons and is used together with OO.ui.ButtonWidget and\n * its subclasses. Each button in a group is addressed by a unique reference. Buttons can be added,\n * removed, and cleared from the group.\n *\n * @example\n * // Example: A ButtonGroupWidget with two buttons\n * var button1 = new OO.ui.PopupButtonWidget( {\n * label: 'Select a category',\n * icon: 'menu',\n * popup: {\n * $content: $( '<p>List of categories...</p>' ),\n * padded: true,\n * align: 'left'\n * }\n * } );\n * var button2 = new OO.ui.ButtonWidget( {\n * label: 'Add item'\n * });\n * var buttonGroup = new OO.ui.ButtonGroupWidget( {\n * items: [button1, button2]\n * } );\n * $( 'body' ).append( buttonGroup.$element );\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.GroupElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {OO.ui.ButtonWidget[]} [items] Buttons to add\n */\nOO.ui.ButtonGroupWidget = function OoUiButtonGroupWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.ButtonGroupWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.GroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-buttonGroupWidget' );\n\tif ( Array.isArray( config.items ) ) {\n\t\tthis.addItems( config.items );\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ButtonGroupWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.ButtonGroupWidget, OO.ui.mixin.GroupElement );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.ButtonGroupWidget.static.tagName = 'span';\n\n/* Methods */\n\n/**\n * Focus the widget\n *\n * @chainable\n */\nOO.ui.ButtonGroupWidget.prototype.focus = function () {\n\tif ( !this.isDisabled() ) {\n\t\tif ( this.items[ 0 ] ) {\n\t\t\tthis.items[ 0 ].focus();\n\t\t}\n\t}\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ButtonGroupWidget.prototype.simulateLabelClick = function () {\n\tthis.focus();\n};\n","/**\n * IconWidget is a generic widget for {@link OO.ui.mixin.IconElement icons}. In general, IconWidgets should be used with OO.ui.LabelWidget,\n * which creates a label that identifies the icon’s function. See the [OOjs UI documentation on MediaWiki] [1]\n * for a list of icons included in the library.\n *\n * @example\n * // An icon widget with a label\n * var myIcon = new OO.ui.IconWidget( {\n * icon: 'help',\n * iconTitle: 'Help'\n * } );\n * // Create a label.\n * var iconLabel = new OO.ui.LabelWidget( {\n * label: 'Help'\n * } );\n * $( 'body' ).append( myIcon.$element, iconLabel.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Icons\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.TitledElement\n * @mixins OO.ui.mixin.FlaggedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.IconWidget = function OoUiIconWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.IconWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.IconElement.call( this, $.extend( {}, config, { $icon: this.$element } ) );\n\tOO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) );\n\tOO.ui.mixin.FlaggedElement.call( this, $.extend( {}, config, { $flagged: this.$element } ) );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-iconWidget' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.IconWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.IconWidget, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.IconWidget, OO.ui.mixin.TitledElement );\nOO.mixinClass( OO.ui.IconWidget, OO.ui.mixin.FlaggedElement );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.IconWidget.static.tagName = 'span';\n","/**\n * IndicatorWidgets create indicators, which are small graphics that are generally used to draw\n * attention to the status of an item or to clarify the function of a control. For a list of\n * indicators included in the library, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * @example\n * // Example of an indicator widget\n * var indicator1 = new OO.ui.IndicatorWidget( {\n * indicator: 'alert'\n * } );\n *\n * // Create a fieldset layout to add a label\n * var fieldset = new OO.ui.FieldsetLayout();\n * fieldset.addItems( [\n * new OO.ui.FieldLayout( indicator1, { label: 'An alert indicator:' } )\n * ] );\n * $( 'body' ).append( fieldset.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Icons,_Indicators,_and_Labels#Indicators\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.IndicatorElement\n * @mixins OO.ui.mixin.TitledElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.IndicatorWidget = function OoUiIndicatorWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.IndicatorWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.IndicatorElement.call( this, $.extend( {}, config, { $indicator: this.$element } ) );\n\tOO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$element } ) );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-indicatorWidget' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.IndicatorWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.IndicatorWidget, OO.ui.mixin.IndicatorElement );\nOO.mixinClass( OO.ui.IndicatorWidget, OO.ui.mixin.TitledElement );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.IndicatorWidget.static.tagName = 'span';\n","/**\n * LabelWidgets help identify the function of interface elements. Each LabelWidget can\n * be configured with a `label` option that is set to a string, a label node, or a function:\n *\n * - String: a plaintext string\n * - jQuery selection: a jQuery selection, used for anything other than a plaintext label, e.g., a\n * label that includes a link or special styling, such as a gray color or additional graphical elements.\n * - Function: a function that will produce a string in the future. Functions are used\n * in cases where the value of the label is not currently defined.\n *\n * In addition, the LabelWidget can be associated with an {@link OO.ui.InputWidget input widget}, which\n * will come into focus when the label is clicked.\n *\n * @example\n * // Examples of LabelWidgets\n * var label1 = new OO.ui.LabelWidget( {\n * label: 'plaintext label'\n * } );\n * var label2 = new OO.ui.LabelWidget( {\n * label: $( '<a href=\"default.html\">jQuery label</a>' )\n * } );\n * // Create a fieldset layout with fields for each example\n * var fieldset = new OO.ui.FieldsetLayout();\n * fieldset.addItems( [\n * new OO.ui.FieldLayout( label1 ),\n * new OO.ui.FieldLayout( label2 )\n * ] );\n * $( 'body' ).append( fieldset.$element );\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.TitledElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {OO.ui.InputWidget} [input] {@link OO.ui.InputWidget Input widget} that uses the label.\n * Clicking the label will focus the specified input field.\n */\nOO.ui.LabelWidget = function OoUiLabelWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.LabelWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.LabelElement.call( this, $.extend( {}, config, { $label: this.$element } ) );\n\tOO.ui.mixin.TitledElement.call( this, config );\n\n\t// Properties\n\tthis.input = config.input;\n\n\t// Initialization\n\tif ( this.input ) {\n\t\tif ( this.input.getInputId() ) {\n\t\t\tthis.$element.attr( 'for', this.input.getInputId() );\n\t\t} else {\n\t\t\tthis.$label.on( 'click', function () {\n\t\t\t\tthis.input.simulateLabelClick();\n\t\t\t\treturn false;\n\t\t\t}.bind( this ) );\n\t\t}\n\t}\n\tthis.$element.addClass( 'oo-ui-labelWidget' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.LabelWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.LabelWidget, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.LabelWidget, OO.ui.mixin.TitledElement );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.LabelWidget.static.tagName = 'label';\n","/**\n * PendingElement is a mixin that is used to create elements that notify users that something is happening\n * and that they should wait before proceeding. The pending state is visually represented with a pending\n * texture that appears in the head of a pending {@link OO.ui.ProcessDialog process dialog} or in the input\n * field of a {@link OO.ui.TextInputWidget text input widget}.\n *\n * Currently, {@link OO.ui.ActionWidget Action widgets}, which mix in this class, can also be marked as pending, but only when\n * used in {@link OO.ui.MessageDialog message dialogs}. The behavior is not currently supported for action widgets used\n * in process dialogs.\n *\n * @example\n * function MessageDialog( config ) {\n * MessageDialog.parent.call( this, config );\n * }\n * OO.inheritClass( MessageDialog, OO.ui.MessageDialog );\n *\n * MessageDialog.static.name = 'myMessageDialog';\n * MessageDialog.static.actions = [\n * { action: 'save', label: 'Done', flags: 'primary' },\n * { label: 'Cancel', flags: 'safe' }\n * ];\n *\n * MessageDialog.prototype.initialize = function () {\n * MessageDialog.parent.prototype.initialize.apply( this, arguments );\n * this.content = new OO.ui.PanelLayout( { $: this.$, padded: true } );\n * this.content.$element.append( '<p>Click the \\'Done\\' action widget to see its pending state. Note that action widgets can be marked pending in message dialogs but not process dialogs.</p>' );\n * this.$body.append( this.content.$element );\n * };\n * MessageDialog.prototype.getBodyHeight = function () {\n * return 100;\n * }\n * MessageDialog.prototype.getActionProcess = function ( action ) {\n * var dialog = this;\n * if ( action === 'save' ) {\n * dialog.getActions().get({actions: 'save'})[0].pushPending();\n * return new OO.ui.Process()\n * .next( 1000 )\n * .next( function () {\n * dialog.getActions().get({actions: 'save'})[0].popPending();\n * } );\n * }\n * return MessageDialog.parent.prototype.getActionProcess.call( this, action );\n * };\n *\n * var windowManager = new OO.ui.WindowManager();\n * $( 'body' ).append( windowManager.$element );\n *\n * var dialog = new MessageDialog();\n * windowManager.addWindows( [ dialog ] );\n * windowManager.openWindow( dialog );\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$pending] Element to mark as pending, defaults to this.$element\n */\nOO.ui.mixin.PendingElement = function OoUiMixinPendingElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.pending = 0;\n\tthis.$pending = null;\n\n\t// Initialisation\n\tthis.setPendingElement( config.$pending || this.$element );\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.mixin.PendingElement );\n\n/* Methods */\n\n/**\n * Set the pending element (and clean up any existing one).\n *\n * @param {jQuery} $pending The element to set to pending.\n */\nOO.ui.mixin.PendingElement.prototype.setPendingElement = function ( $pending ) {\n\tif ( this.$pending ) {\n\t\tthis.$pending.removeClass( 'oo-ui-pendingElement-pending' );\n\t}\n\n\tthis.$pending = $pending;\n\tif ( this.pending > 0 ) {\n\t\tthis.$pending.addClass( 'oo-ui-pendingElement-pending' );\n\t}\n};\n\n/**\n * Check if an element is pending.\n *\n * @return {boolean} Element is pending\n */\nOO.ui.mixin.PendingElement.prototype.isPending = function () {\n\treturn !!this.pending;\n};\n\n/**\n * Increase the pending counter. The pending state will remain active until the counter is zero\n * (i.e., the number of calls to #pushPending and #popPending is the same).\n *\n * @chainable\n */\nOO.ui.mixin.PendingElement.prototype.pushPending = function () {\n\tif ( this.pending === 0 ) {\n\t\tthis.$pending.addClass( 'oo-ui-pendingElement-pending' );\n\t\tthis.updateThemeClasses();\n\t}\n\tthis.pending++;\n\n\treturn this;\n};\n\n/**\n * Decrease the pending counter. The pending state will remain active until the counter is zero\n * (i.e., the number of calls to #pushPending and #popPending is the same).\n *\n * @chainable\n */\nOO.ui.mixin.PendingElement.prototype.popPending = function () {\n\tif ( this.pending === 1 ) {\n\t\tthis.$pending.removeClass( 'oo-ui-pendingElement-pending' );\n\t\tthis.updateThemeClasses();\n\t}\n\tthis.pending = Math.max( 0, this.pending - 1 );\n\n\treturn this;\n};\n","/**\n * Element that will stick adjacent to a specified container, even when it is inserted elsewhere\n * in the document (for example, in an OO.ui.Window's $overlay).\n *\n * The elements's position is automatically calculated and maintained when window is resized or the\n * page is scrolled. If you reposition the container manually, you have to call #position to make\n * sure the element is still placed correctly.\n *\n * As positioning is only possible when both the element and the container are attached to the DOM\n * and visible, it's only done after you call #togglePositioning. You might want to do this inside\n * the #toggle method to display a floating popup, for example.\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$floatable] Node to position, assigned to #$floatable, omit to use #$element\n * @cfg {jQuery} [$floatableContainer] Node to position adjacent to\n * @cfg {string} [verticalPosition='below'] Where to position $floatable vertically:\n * 'below': Directly below $floatableContainer, aligning f's top edge with fC's bottom edge\n * 'above': Directly above $floatableContainer, aligning f's bottom edge with fC's top edge\n * 'top': Align the top edge with $floatableContainer's top edge\n * 'bottom': Align the bottom edge with $floatableContainer's bottom edge\n * 'center': Vertically align the center with $floatableContainer's center\n * @cfg {string} [horizontalPosition='start'] Where to position $floatable horizontally:\n * 'before': Directly before $floatableContainer, aligning f's end edge with fC's start edge\n * 'after': Directly after $floatableContainer, algining f's start edge with fC's end edge\n * 'start': Align the start (left in LTR, right in RTL) edge with $floatableContainer's start edge\n * 'end': Align the end (right in LTR, left in RTL) edge with $floatableContainer's end edge\n * 'center': Horizontally align the center with $floatableContainer's center\n * @cfg {boolean} [hideWhenOutOfView=true] Whether to hide the floatable element if the container\n * is out of view\n */\nOO.ui.mixin.FloatableElement = function OoUiMixinFloatableElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.$floatable = null;\n\tthis.$floatableContainer = null;\n\tthis.$floatableWindow = null;\n\tthis.$floatableClosestScrollable = null;\n\tthis.onFloatableScrollHandler = this.position.bind( this );\n\tthis.onFloatableWindowResizeHandler = this.position.bind( this );\n\n\t// Initialization\n\tthis.setFloatableContainer( config.$floatableContainer );\n\tthis.setFloatableElement( config.$floatable || this.$element );\n\tthis.setVerticalPosition( config.verticalPosition || 'below' );\n\tthis.setHorizontalPosition( config.horizontalPosition || 'start' );\n\tthis.hideWhenOutOfView = config.hideWhenOutOfView === undefined ? true : !!config.hideWhenOutOfView;\n};\n\n/* Methods */\n\n/**\n * Set floatable element.\n *\n * If an element is already set, it will be cleaned up before setting up the new element.\n *\n * @param {jQuery} $floatable Element to make floatable\n */\nOO.ui.mixin.FloatableElement.prototype.setFloatableElement = function ( $floatable ) {\n\tif ( this.$floatable ) {\n\t\tthis.$floatable.removeClass( 'oo-ui-floatableElement-floatable' );\n\t\tthis.$floatable.css( { left: '', top: '' } );\n\t}\n\n\tthis.$floatable = $floatable.addClass( 'oo-ui-floatableElement-floatable' );\n\tthis.position();\n};\n\n/**\n * Set floatable container.\n *\n * The element will be positioned relative to the specified container.\n *\n * @param {jQuery|null} $floatableContainer Container to keep visible, or null to unset\n */\nOO.ui.mixin.FloatableElement.prototype.setFloatableContainer = function ( $floatableContainer ) {\n\tthis.$floatableContainer = $floatableContainer;\n\tif ( this.$floatable ) {\n\t\tthis.position();\n\t}\n};\n\n/**\n * Change how the element is positioned vertically.\n *\n * @param {string} position 'below', 'above', 'top', 'bottom' or 'center'\n */\nOO.ui.mixin.FloatableElement.prototype.setVerticalPosition = function ( position ) {\n\tif ( [ 'below', 'above', 'top', 'bottom', 'center' ].indexOf( position ) === -1 ) {\n\t\tthrow new Error( 'Invalid value for vertical position: ' + position );\n\t}\n\tif ( this.verticalPosition !== position ) {\n\t\tthis.verticalPosition = position;\n\t\tif ( this.$floatable ) {\n\t\t\tthis.position();\n\t\t}\n\t}\n};\n\n/**\n * Change how the element is positioned horizontally.\n *\n * @param {string} position 'before', 'after', 'start', 'end' or 'center'\n */\nOO.ui.mixin.FloatableElement.prototype.setHorizontalPosition = function ( position ) {\n\tif ( [ 'before', 'after', 'start', 'end', 'center' ].indexOf( position ) === -1 ) {\n\t\tthrow new Error( 'Invalid value for horizontal position: ' + position );\n\t}\n\tif ( this.horizontalPosition !== position ) {\n\t\tthis.horizontalPosition = position;\n\t\tif ( this.$floatable ) {\n\t\t\tthis.position();\n\t\t}\n\t}\n};\n\n/**\n * Toggle positioning.\n *\n * Do not turn positioning on until after the element is attached to the DOM and visible.\n *\n * @param {boolean} [positioning] Enable positioning, omit to toggle\n * @chainable\n */\nOO.ui.mixin.FloatableElement.prototype.togglePositioning = function ( positioning ) {\n\tvar closestScrollableOfContainer;\n\n\tif ( !this.$floatable || !this.$floatableContainer ) {\n\t\treturn this;\n\t}\n\n\tpositioning = positioning === undefined ? !this.positioning : !!positioning;\n\n\tif ( positioning && !this.warnedUnattached && !this.isElementAttached() ) {\n\t\tOO.ui.warnDeprecation( 'FloatableElement#togglePositioning: Before calling this method, the element must be attached to the DOM.' );\n\t\tthis.warnedUnattached = true;\n\t}\n\n\tif ( this.positioning !== positioning ) {\n\t\tthis.positioning = positioning;\n\n\t\tthis.needsCustomPosition =\n\t\t\tthis.verticalPostion !== 'below' ||\n\t\t\tthis.horizontalPosition !== 'start' ||\n\t\t\t!OO.ui.contains( this.$floatableContainer[ 0 ], this.$floatable[ 0 ] );\n\n\t\tclosestScrollableOfContainer = OO.ui.Element.static.getClosestScrollableContainer( this.$floatableContainer[ 0 ] );\n\t\t// If the scrollable is the root, we have to listen to scroll events\n\t\t// on the window because of browser inconsistencies.\n\t\tif ( $( closestScrollableOfContainer ).is( 'html, body' ) ) {\n\t\t\tclosestScrollableOfContainer = OO.ui.Element.static.getWindow( closestScrollableOfContainer );\n\t\t}\n\n\t\tif ( positioning ) {\n\t\t\tthis.$floatableWindow = $( this.getElementWindow() );\n\t\t\tthis.$floatableWindow.on( 'resize', this.onFloatableWindowResizeHandler );\n\n\t\t\tthis.$floatableClosestScrollable = $( closestScrollableOfContainer );\n\t\t\tthis.$floatableClosestScrollable.on( 'scroll', this.onFloatableScrollHandler );\n\n\t\t\t// Initial position after visible\n\t\t\tthis.position();\n\t\t} else {\n\t\t\tif ( this.$floatableWindow ) {\n\t\t\t\tthis.$floatableWindow.off( 'resize', this.onFloatableWindowResizeHandler );\n\t\t\t\tthis.$floatableWindow = null;\n\t\t\t}\n\n\t\t\tif ( this.$floatableClosestScrollable ) {\n\t\t\t\tthis.$floatableClosestScrollable.off( 'scroll', this.onFloatableScrollHandler );\n\t\t\t\tthis.$floatableClosestScrollable = null;\n\t\t\t}\n\n\t\t\tthis.$floatable.css( { left: '', right: '', top: '' } );\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Check whether the bottom edge of the given element is within the viewport of the given container.\n *\n * @private\n * @param {jQuery} $element\n * @param {jQuery} $container\n * @return {boolean}\n */\nOO.ui.mixin.FloatableElement.prototype.isElementInViewport = function ( $element, $container ) {\n\tvar elemRect, contRect, topEdgeInBounds, bottomEdgeInBounds, leftEdgeInBounds, rightEdgeInBounds,\n\t\tstartEdgeInBounds, endEdgeInBounds,\n\t\tdirection = $element.css( 'direction' );\n\n\telemRect = $element[ 0 ].getBoundingClientRect();\n\tif ( $container[ 0 ] === window ) {\n\t\tcontRect = {\n\t\t\ttop: 0,\n\t\t\tleft: 0,\n\t\t\tright: document.documentElement.clientWidth,\n\t\t\tbottom: document.documentElement.clientHeight\n\t\t};\n\t} else {\n\t\tcontRect = $container[ 0 ].getBoundingClientRect();\n\t}\n\n\ttopEdgeInBounds = elemRect.top >= contRect.top && elemRect.top <= contRect.bottom;\n\tbottomEdgeInBounds = elemRect.bottom >= contRect.top && elemRect.bottom <= contRect.bottom;\n\tleftEdgeInBounds = elemRect.left >= contRect.left && elemRect.left <= contRect.right;\n\trightEdgeInBounds = elemRect.right >= contRect.left && elemRect.right <= contRect.right;\n\tif ( direction === 'rtl' ) {\n\t\tstartEdgeInBounds = rightEdgeInBounds;\n\t\tendEdgeInBounds = leftEdgeInBounds;\n\t} else {\n\t\tstartEdgeInBounds = leftEdgeInBounds;\n\t\tendEdgeInBounds = rightEdgeInBounds;\n\t}\n\n\tif ( this.verticalPosition === 'below' && !bottomEdgeInBounds ) {\n\t\treturn false;\n\t}\n\tif ( this.verticalPosition === 'above' && !topEdgeInBounds ) {\n\t\treturn false;\n\t}\n\tif ( this.horizontalPosition === 'before' && !startEdgeInBounds ) {\n\t\treturn false;\n\t}\n\tif ( this.horizontalPosition === 'after' && !endEdgeInBounds ) {\n\t\treturn false;\n\t}\n\n\t// The other positioning values are all about being inside the container,\n\t// so in those cases all we care about is that any part of the container is visible.\n\treturn elemRect.top <= contRect.bottom && elemRect.bottom >= contRect.top &&\n\t\telemRect.left <= contRect.right && elemRect.right >= contRect.left;\n};\n\n/**\n * Position the floatable below its container.\n *\n * This should only be done when both of them are attached to the DOM and visible.\n *\n * @chainable\n */\nOO.ui.mixin.FloatableElement.prototype.position = function () {\n\tif ( !this.positioning ) {\n\t\treturn this;\n\t}\n\n\tif ( !(\n\t\t// To continue, some things need to be true:\n\t\t// The element must actually be in the DOM\n\t\tthis.isElementAttached() && (\n\t\t\t// The closest scrollable is the current window\n\t\t\tthis.$floatableClosestScrollable[ 0 ] === this.getElementWindow() ||\n\t\t\t// OR is an element in the element's DOM\n\t\t\t$.contains( this.getElementDocument(), this.$floatableClosestScrollable[ 0 ] )\n\t\t)\n\t) ) {\n\t\t// Abort early if important parts of the widget are no longer attached to the DOM\n\t\treturn this;\n\t}\n\n\tif ( this.hideWhenOutOfView && !this.isElementInViewport( this.$floatableContainer, this.$floatableClosestScrollable ) ) {\n\t\tthis.$floatable.addClass( 'oo-ui-element-hidden' );\n\t\treturn this;\n\t} else {\n\t\tthis.$floatable.removeClass( 'oo-ui-element-hidden' );\n\t}\n\n\tif ( !this.needsCustomPosition ) {\n\t\treturn this;\n\t}\n\n\tthis.$floatable.css( this.computePosition() );\n\n\t// We updated the position, so re-evaluate the clipping state.\n\t// (ClippableElement does not listen to 'scroll' events on $floatableContainer's parent, and so\n\t// will not notice the need to update itself.)\n\t// TODO: This is terrible, we shouldn't need to know about ClippableElement at all here. Why does\n\t// it not listen to the right events in the right places?\n\tif ( this.clip ) {\n\t\tthis.clip();\n\t}\n\n\treturn this;\n};\n\n/**\n * Compute how #$floatable should be positioned based on the position of #$floatableContainer\n * and the positioning settings. This is a helper for #position that shouldn't be called directly,\n * but may be overridden by subclasses if they want to change or add to the positioning logic.\n *\n * @return {Object} New position to apply with .css(). Keys are 'top', 'left', 'bottom' and 'right'.\n */\nOO.ui.mixin.FloatableElement.prototype.computePosition = function () {\n\tvar isBody, scrollableX, scrollableY, containerPos,\n\t\thorizScrollbarHeight, vertScrollbarWidth, scrollTop, scrollLeft,\n\t\tnewPos = { top: '', left: '', bottom: '', right: '' },\n\t\tdirection = this.$floatableContainer.css( 'direction' ),\n\t\t$offsetParent = this.$floatable.offsetParent();\n\n\tif ( $offsetParent.is( 'html' ) ) {\n\t\t// The innerHeight/Width and clientHeight/Width calculations don't work well on the\n\t\t// <html> element, but they do work on the <body>\n\t\t$offsetParent = $( $offsetParent[ 0 ].ownerDocument.body );\n\t}\n\tisBody = $offsetParent.is( 'body' );\n\tscrollableX = $offsetParent.css( 'overflow-x' ) === 'scroll' || $offsetParent.css( 'overflow-x' ) === 'auto';\n\tscrollableY = $offsetParent.css( 'overflow-y' ) === 'scroll' || $offsetParent.css( 'overflow-y' ) === 'auto';\n\n\tvertScrollbarWidth = $offsetParent.innerWidth() - $offsetParent.prop( 'clientWidth' );\n\thorizScrollbarHeight = $offsetParent.innerHeight() - $offsetParent.prop( 'clientHeight' );\n\t// We don't need to compute and add scrollTop and scrollLeft if the scrollable container is the body,\n\t// or if it isn't scrollable\n\tscrollTop = scrollableY && !isBody ? $offsetParent.scrollTop() : 0;\n\tscrollLeft = scrollableX && !isBody ? OO.ui.Element.static.getScrollLeft( $offsetParent[ 0 ] ) : 0;\n\n\t// Avoid passing the <body> to getRelativePosition(), because it won't return what we expect\n\t// if the <body> has a margin\n\tcontainerPos = isBody ?\n\t\tthis.$floatableContainer.offset() :\n\t\tOO.ui.Element.static.getRelativePosition( this.$floatableContainer, $offsetParent );\n\tcontainerPos.bottom = containerPos.top + this.$floatableContainer.outerHeight();\n\tcontainerPos.right = containerPos.left + this.$floatableContainer.outerWidth();\n\tcontainerPos.start = direction === 'rtl' ? containerPos.right : containerPos.left;\n\tcontainerPos.end = direction === 'rtl' ? containerPos.left : containerPos.right;\n\n\tif ( this.verticalPosition === 'below' ) {\n\t\tnewPos.top = containerPos.bottom;\n\t} else if ( this.verticalPosition === 'above' ) {\n\t\tnewPos.bottom = $offsetParent.outerHeight() - containerPos.top;\n\t} else if ( this.verticalPosition === 'top' ) {\n\t\tnewPos.top = containerPos.top;\n\t} else if ( this.verticalPosition === 'bottom' ) {\n\t\tnewPos.bottom = $offsetParent.outerHeight() - containerPos.bottom;\n\t} else if ( this.verticalPosition === 'center' ) {\n\t\tnewPos.top = containerPos.top +\n\t\t\t( this.$floatableContainer.height() - this.$floatable.height() ) / 2;\n\t}\n\n\tif ( this.horizontalPosition === 'before' ) {\n\t\tnewPos.end = containerPos.start;\n\t} else if ( this.horizontalPosition === 'after' ) {\n\t\tnewPos.start = containerPos.end;\n\t} else if ( this.horizontalPosition === 'start' ) {\n\t\tnewPos.start = containerPos.start;\n\t} else if ( this.horizontalPosition === 'end' ) {\n\t\tnewPos.end = containerPos.end;\n\t} else if ( this.horizontalPosition === 'center' ) {\n\t\tnewPos.left = containerPos.left +\n\t\t\t( this.$floatableContainer.width() - this.$floatable.width() ) / 2;\n\t}\n\n\tif ( newPos.start !== undefined ) {\n\t\tif ( direction === 'rtl' ) {\n\t\t\tnewPos.right = ( isBody ? $( $offsetParent[ 0 ].ownerDocument.documentElement ) : $offsetParent ).outerWidth() - newPos.start;\n\t\t} else {\n\t\t\tnewPos.left = newPos.start;\n\t\t}\n\t\tdelete newPos.start;\n\t}\n\tif ( newPos.end !== undefined ) {\n\t\tif ( direction === 'rtl' ) {\n\t\t\tnewPos.left = newPos.end;\n\t\t} else {\n\t\t\tnewPos.right = ( isBody ? $( $offsetParent[ 0 ].ownerDocument.documentElement ) : $offsetParent ).outerWidth() - newPos.end;\n\t\t}\n\t\tdelete newPos.end;\n\t}\n\n\t// Account for scroll position\n\tif ( newPos.top !== '' ) {\n\t\tnewPos.top += scrollTop;\n\t}\n\tif ( newPos.bottom !== '' ) {\n\t\tnewPos.bottom -= scrollTop;\n\t}\n\tif ( newPos.left !== '' ) {\n\t\tnewPos.left += scrollLeft;\n\t}\n\tif ( newPos.right !== '' ) {\n\t\tnewPos.right -= scrollLeft;\n\t}\n\n\t// Account for scrollbar gutter\n\tif ( newPos.bottom !== '' ) {\n\t\tnewPos.bottom -= horizScrollbarHeight;\n\t}\n\tif ( direction === 'rtl' ) {\n\t\tif ( newPos.left !== '' ) {\n\t\t\tnewPos.left -= vertScrollbarWidth;\n\t\t}\n\t} else {\n\t\tif ( newPos.right !== '' ) {\n\t\t\tnewPos.right -= vertScrollbarWidth;\n\t\t}\n\t}\n\n\treturn newPos;\n};\n","/**\n * Element that can be automatically clipped to visible boundaries.\n *\n * Whenever the element's natural height changes, you have to call\n * {@link OO.ui.mixin.ClippableElement#clip} to make sure it's still\n * clipping correctly.\n *\n * The dimensions of #$clippableContainer will be compared to the boundaries of the\n * nearest scrollable container. If #$clippableContainer is too tall and/or too wide,\n * then #$clippable will be given a fixed reduced height and/or width and will be made\n * scrollable. By default, #$clippable and #$clippableContainer are the same element,\n * but you can build a static footer by setting #$clippableContainer to an element that contains\n * #$clippable and the footer.\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$clippable] Node to clip, assigned to #$clippable, omit to use #$element\n * @cfg {jQuery} [$clippableContainer] Node to keep visible, assigned to #$clippableContainer,\n * omit to use #$clippable\n */\nOO.ui.mixin.ClippableElement = function OoUiMixinClippableElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.$clippable = null;\n\tthis.$clippableContainer = null;\n\tthis.clipping = false;\n\tthis.clippedHorizontally = false;\n\tthis.clippedVertically = false;\n\tthis.$clippableScrollableContainer = null;\n\tthis.$clippableScroller = null;\n\tthis.$clippableWindow = null;\n\tthis.idealWidth = null;\n\tthis.idealHeight = null;\n\tthis.onClippableScrollHandler = this.clip.bind( this );\n\tthis.onClippableWindowResizeHandler = this.clip.bind( this );\n\n\t// Initialization\n\tif ( config.$clippableContainer ) {\n\t\tthis.setClippableContainer( config.$clippableContainer );\n\t}\n\tthis.setClippableElement( config.$clippable || this.$element );\n};\n\n/* Methods */\n\n/**\n * Set clippable element.\n *\n * If an element is already set, it will be cleaned up before setting up the new element.\n *\n * @param {jQuery} $clippable Element to make clippable\n */\nOO.ui.mixin.ClippableElement.prototype.setClippableElement = function ( $clippable ) {\n\tif ( this.$clippable ) {\n\t\tthis.$clippable.removeClass( 'oo-ui-clippableElement-clippable' );\n\t\tthis.$clippable.css( { width: '', height: '', overflowX: '', overflowY: '' } );\n\t\tOO.ui.Element.static.reconsiderScrollbars( this.$clippable[ 0 ] );\n\t}\n\n\tthis.$clippable = $clippable.addClass( 'oo-ui-clippableElement-clippable' );\n\tthis.clip();\n};\n\n/**\n * Set clippable container.\n *\n * This is the container that will be measured when deciding whether to clip. When clipping,\n * #$clippable will be resized in order to keep the clippable container fully visible.\n *\n * If the clippable container is unset, #$clippable will be used.\n *\n * @param {jQuery|null} $clippableContainer Container to keep visible, or null to unset\n */\nOO.ui.mixin.ClippableElement.prototype.setClippableContainer = function ( $clippableContainer ) {\n\tthis.$clippableContainer = $clippableContainer;\n\tif ( this.$clippable ) {\n\t\tthis.clip();\n\t}\n};\n\n/**\n * Toggle clipping.\n *\n * Do not turn clipping on until after the element is attached to the DOM and visible.\n *\n * @param {boolean} [clipping] Enable clipping, omit to toggle\n * @chainable\n */\nOO.ui.mixin.ClippableElement.prototype.toggleClipping = function ( clipping ) {\n\tclipping = clipping === undefined ? !this.clipping : !!clipping;\n\n\tif ( clipping && !this.warnedUnattached && !this.isElementAttached() ) {\n\t\tOO.ui.warnDeprecation( 'ClippableElement#toggleClipping: Before calling this method, the element must be attached to the DOM.' );\n\t\tthis.warnedUnattached = true;\n\t}\n\n\tif ( this.clipping !== clipping ) {\n\t\tthis.clipping = clipping;\n\t\tif ( clipping ) {\n\t\t\tthis.$clippableScrollableContainer = $( this.getClosestScrollableElementContainer() );\n\t\t\t// If the clippable container is the root, we have to listen to scroll events and check\n\t\t\t// jQuery.scrollTop on the window because of browser inconsistencies\n\t\t\tthis.$clippableScroller = this.$clippableScrollableContainer.is( 'html, body' ) ?\n\t\t\t\t$( OO.ui.Element.static.getWindow( this.$clippableScrollableContainer ) ) :\n\t\t\t\tthis.$clippableScrollableContainer;\n\t\t\tthis.$clippableScroller.on( 'scroll', this.onClippableScrollHandler );\n\t\t\tthis.$clippableWindow = $( this.getElementWindow() )\n\t\t\t\t.on( 'resize', this.onClippableWindowResizeHandler );\n\t\t\t// Initial clip after visible\n\t\t\tthis.clip();\n\t\t} else {\n\t\t\tthis.$clippable.css( {\n\t\t\t\twidth: '',\n\t\t\t\theight: '',\n\t\t\t\tmaxWidth: '',\n\t\t\t\tmaxHeight: '',\n\t\t\t\toverflowX: '',\n\t\t\t\toverflowY: ''\n\t\t\t} );\n\t\t\tOO.ui.Element.static.reconsiderScrollbars( this.$clippable[ 0 ] );\n\n\t\t\tthis.$clippableScrollableContainer = null;\n\t\t\tthis.$clippableScroller.off( 'scroll', this.onClippableScrollHandler );\n\t\t\tthis.$clippableScroller = null;\n\t\t\tthis.$clippableWindow.off( 'resize', this.onClippableWindowResizeHandler );\n\t\t\tthis.$clippableWindow = null;\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Check if the element will be clipped to fit the visible area of the nearest scrollable container.\n *\n * @return {boolean} Element will be clipped to the visible area\n */\nOO.ui.mixin.ClippableElement.prototype.isClipping = function () {\n\treturn this.clipping;\n};\n\n/**\n * Check if the bottom or right of the element is being clipped by the nearest scrollable container.\n *\n * @return {boolean} Part of the element is being clipped\n */\nOO.ui.mixin.ClippableElement.prototype.isClipped = function () {\n\treturn this.clippedHorizontally || this.clippedVertically;\n};\n\n/**\n * Check if the right of the element is being clipped by the nearest scrollable container.\n *\n * @return {boolean} Part of the element is being clipped\n */\nOO.ui.mixin.ClippableElement.prototype.isClippedHorizontally = function () {\n\treturn this.clippedHorizontally;\n};\n\n/**\n * Check if the bottom of the element is being clipped by the nearest scrollable container.\n *\n * @return {boolean} Part of the element is being clipped\n */\nOO.ui.mixin.ClippableElement.prototype.isClippedVertically = function () {\n\treturn this.clippedVertically;\n};\n\n/**\n * Set the ideal size. These are the dimensions #$clippable will have when it's not being clipped.\n *\n * @param {number|string} [width] Width as a number of pixels or CSS string with unit suffix\n * @param {number|string} [height] Height as a number of pixels or CSS string with unit suffix\n */\nOO.ui.mixin.ClippableElement.prototype.setIdealSize = function ( width, height ) {\n\tthis.idealWidth = width;\n\tthis.idealHeight = height;\n\n\tif ( !this.clipping ) {\n\t\t// Update dimensions\n\t\tthis.$clippable.css( { width: width, height: height } );\n\t}\n\t// While clipping, idealWidth and idealHeight are not considered\n};\n\n/**\n * Clip element to visible boundaries and allow scrolling when needed. You should call this method\n * when the element's natural height changes.\n *\n * Element will be clipped the bottom or right of the element is within 10px of the edge of, or\n * overlapped by, the visible area of the nearest scrollable container.\n *\n * Because calling clip() when the natural height changes isn't always possible, we also set\n * max-height when the element isn't being clipped. This means that if the element tries to grow\n * beyond the edge, something reasonable will happen before clip() is called.\n *\n * @chainable\n */\nOO.ui.mixin.ClippableElement.prototype.clip = function () {\n\tvar $container, extraHeight, extraWidth, ccOffset,\n\t\t$scrollableContainer, scOffset, scHeight, scWidth,\n\t\tccWidth, scrollerIsWindow, scrollTop, scrollLeft,\n\t\tdesiredWidth, desiredHeight, allotedWidth, allotedHeight,\n\t\tnaturalWidth, naturalHeight, clipWidth, clipHeight,\n\t\tbuffer = 7; // Chosen by fair dice roll\n\n\tif ( !this.clipping ) {\n\t\t// this.$clippableScrollableContainer and this.$clippableWindow are null, so the below will fail\n\t\treturn this;\n\t}\n\n\t$container = this.$clippableContainer || this.$clippable;\n\textraHeight = $container.outerHeight() - this.$clippable.outerHeight();\n\textraWidth = $container.outerWidth() - this.$clippable.outerWidth();\n\tccOffset = $container.offset();\n\tif ( this.$clippableScrollableContainer.is( 'html, body' ) ) {\n\t\t$scrollableContainer = this.$clippableWindow;\n\t\tscOffset = { top: 0, left: 0 };\n\t} else {\n\t\t$scrollableContainer = this.$clippableScrollableContainer;\n\t\tscOffset = $scrollableContainer.offset();\n\t}\n\tscHeight = $scrollableContainer.innerHeight() - buffer;\n\tscWidth = $scrollableContainer.innerWidth() - buffer;\n\tccWidth = $container.outerWidth() + buffer;\n\tscrollerIsWindow = this.$clippableScroller[ 0 ] === this.$clippableWindow[ 0 ];\n\tscrollTop = scrollerIsWindow ? this.$clippableScroller.scrollTop() : 0;\n\tscrollLeft = scrollerIsWindow ? this.$clippableScroller.scrollLeft() : 0;\n\tdesiredWidth = ccOffset.left < 0 ?\n\t\tccWidth + ccOffset.left :\n\t\t( scOffset.left + scrollLeft + scWidth ) - ccOffset.left;\n\tdesiredHeight = ( scOffset.top + scrollTop + scHeight ) - ccOffset.top;\n\t// It should never be desirable to exceed the dimensions of the browser viewport... right?\n\tdesiredWidth = Math.min( desiredWidth, document.documentElement.clientWidth );\n\tdesiredHeight = Math.min( desiredHeight, document.documentElement.clientHeight );\n\tallotedWidth = Math.ceil( desiredWidth - extraWidth );\n\tallotedHeight = Math.ceil( desiredHeight - extraHeight );\n\tnaturalWidth = this.$clippable.prop( 'scrollWidth' );\n\tnaturalHeight = this.$clippable.prop( 'scrollHeight' );\n\tclipWidth = allotedWidth < naturalWidth;\n\tclipHeight = allotedHeight < naturalHeight;\n\n\tif ( clipWidth ) {\n\t\t// The order matters here. If overflow is not set first, Chrome displays bogus scrollbars. See T157672.\n\t\t// Forcing a reflow is a smaller workaround than calling reconsiderScrollbars() for this case.\n\t\tthis.$clippable.css( 'overflowX', 'scroll' );\n\t\tvoid this.$clippable[ 0 ].offsetHeight; // Force reflow\n\t\tthis.$clippable.css( {\n\t\t\twidth: Math.max( 0, allotedWidth ),\n\t\t\tmaxWidth: ''\n\t\t} );\n\t} else {\n\t\tthis.$clippable.css( {\n\t\t\toverflowX: '',\n\t\t\twidth: this.idealWidth || '',\n\t\t\tmaxWidth: Math.max( 0, allotedWidth )\n\t\t} );\n\t}\n\tif ( clipHeight ) {\n\t\t// The order matters here. If overflow is not set first, Chrome displays bogus scrollbars. See T157672.\n\t\t// Forcing a reflow is a smaller workaround than calling reconsiderScrollbars() for this case.\n\t\tthis.$clippable.css( 'overflowY', 'scroll' );\n\t\tvoid this.$clippable[ 0 ].offsetHeight; // Force reflow\n\t\tthis.$clippable.css( {\n\t\t\theight: Math.max( 0, allotedHeight ),\n\t\t\tmaxHeight: ''\n\t\t} );\n\t} else {\n\t\tthis.$clippable.css( {\n\t\t\toverflowY: '',\n\t\t\theight: this.idealHeight || '',\n\t\t\tmaxHeight: Math.max( 0, allotedHeight )\n\t\t} );\n\t}\n\n\t// If we stopped clipping in at least one of the dimensions\n\tif ( ( this.clippedHorizontally && !clipWidth ) || ( this.clippedVertically && !clipHeight ) ) {\n\t\tOO.ui.Element.static.reconsiderScrollbars( this.$clippable[ 0 ] );\n\t}\n\n\tthis.clippedHorizontally = clipWidth;\n\tthis.clippedVertically = clipHeight;\n\n\treturn this;\n};\n","/**\n * PopupWidget is a container for content. The popup is overlaid and positioned absolutely.\n * By default, each popup has an anchor that points toward its origin.\n * Please see the [OOjs UI documentation on Mediawiki] [1] for more information and examples.\n *\n * Unlike most widgets, PopupWidget is initially hidden and must be shown by calling #toggle.\n *\n * @example\n * // A popup widget.\n * var popup = new OO.ui.PopupWidget( {\n * $content: $( '<p>Hi there!</p>' ),\n * padded: true,\n * width: 300\n * } );\n *\n * $( 'body' ).append( popup.$element );\n * // To display the popup, toggle the visibility to 'true'.\n * popup.toggle( true );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Popups\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.ClippableElement\n * @mixins OO.ui.mixin.FloatableElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {number} [width=320] Width of popup in pixels\n * @cfg {number} [height] Height of popup in pixels. Omit to use the automatic height.\n * @cfg {boolean} [anchor=true] Show anchor pointing to origin of popup\n * @cfg {string} [position='below'] Where to position the popup relative to $floatableContainer\n * 'above': Put popup above $floatableContainer; anchor points down to the horizontal center\n * of $floatableContainer\n * 'below': Put popup below $floatableContainer; anchor points up to the horizontal center\n * of $floatableContainer\n * 'before': Put popup to the left (LTR) / right (RTL) of $floatableContainer; anchor points\n * endwards (right/left) to the vertical center of $floatableContainer\n * 'after': Put popup to the right (LTR) / left (RTL) of $floatableContainer; anchor points\n * startwards (left/right) to the vertical center of $floatableContainer\n * @cfg {string} [align='center'] How to align the popup to $floatableContainer\n * 'forwards': If position is above/below, move the popup as far endwards (right in LTR, left in RTL)\n * as possible while still keeping the anchor within the popup;\n * if position is before/after, move the popup as far downwards as possible.\n * 'backwards': If position is above/below, move the popup as far startwards (left in LTR, right in RTL)\n * as possible while still keeping the anchor within the popup;\n * if position in before/after, move the popup as far upwards as possible.\n * 'center': Horizontally (if position is above/below) or vertically (before/after) align the center\n * of the popup with the center of $floatableContainer.\n * 'force-left': Alias for 'forwards' in LTR and 'backwards' in RTL\n * 'force-right': Alias for 'backwards' in RTL and 'forwards' in LTR\n * @cfg {jQuery} [$container] Constrain the popup to the boundaries of the specified container.\n * See the [OOjs UI docs on MediaWiki][3] for an example.\n * [3]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Popups#containerExample\n * @cfg {number} [containerPadding=10] Padding between the popup and its container, specified as a number of pixels.\n * @cfg {jQuery} [$content] Content to append to the popup's body\n * @cfg {jQuery} [$footer] Content to append to the popup's footer\n * @cfg {boolean} [autoClose=false] Automatically close the popup when it loses focus.\n * @cfg {jQuery} [$autoCloseIgnore] Elements that will not close the popup when clicked.\n * This config option is only relevant if #autoClose is set to `true`. See the [OOjs UI docs on MediaWiki][2]\n * for an example.\n * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Popups#autocloseExample\n * @cfg {boolean} [head=false] Show a popup header that contains a #label (if specified) and close\n * button.\n * @cfg {boolean} [padded=false] Add padding to the popup's body\n */\nOO.ui.PopupWidget = function OoUiPopupWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.PopupWidget.parent.call( this, config );\n\n\t// Properties (must be set before ClippableElement constructor call)\n\tthis.$body = $( '<div>' );\n\tthis.$popup = $( '<div>' );\n\n\t// Mixin constructors\n\tOO.ui.mixin.LabelElement.call( this, config );\n\tOO.ui.mixin.ClippableElement.call( this, $.extend( {}, config, {\n\t\t$clippable: this.$body,\n\t\t$clippableContainer: this.$popup\n\t} ) );\n\tOO.ui.mixin.FloatableElement.call( this, config );\n\n\t// Properties\n\tthis.$anchor = $( '<div>' );\n\t// If undefined, will be computed lazily in computePosition()\n\tthis.$container = config.$container;\n\tthis.containerPadding = config.containerPadding !== undefined ? config.containerPadding : 10;\n\tthis.autoClose = !!config.autoClose;\n\tthis.$autoCloseIgnore = config.$autoCloseIgnore;\n\tthis.transitionTimeout = null;\n\tthis.anchored = false;\n\tthis.width = config.width !== undefined ? config.width : 320;\n\tthis.height = config.height !== undefined ? config.height : null;\n\tthis.onMouseDownHandler = this.onMouseDown.bind( this );\n\tthis.onDocumentKeyDownHandler = this.onDocumentKeyDown.bind( this );\n\n\t// Initialization\n\tthis.toggleAnchor( config.anchor === undefined || config.anchor );\n\tthis.setAlignment( config.align || 'center' );\n\tthis.setPosition( config.position || 'below' );\n\tthis.$body.addClass( 'oo-ui-popupWidget-body' );\n\tthis.$anchor.addClass( 'oo-ui-popupWidget-anchor' );\n\tthis.$popup\n\t\t.addClass( 'oo-ui-popupWidget-popup' )\n\t\t.append( this.$body );\n\tthis.$element\n\t\t.addClass( 'oo-ui-popupWidget' )\n\t\t.append( this.$popup, this.$anchor );\n\t// Move content, which was added to #$element by OO.ui.Widget, to the body\n\t// FIXME This is gross, we should use '$body' or something for the config\n\tif ( config.$content instanceof jQuery ) {\n\t\tthis.$body.append( config.$content );\n\t}\n\n\tif ( config.padded ) {\n\t\tthis.$body.addClass( 'oo-ui-popupWidget-body-padded' );\n\t}\n\n\tif ( config.head ) {\n\t\tthis.closeButton = new OO.ui.ButtonWidget( { framed: false, icon: 'close' } );\n\t\tthis.closeButton.connect( this, { click: 'onCloseButtonClick' } );\n\t\tthis.$head = $( '<div>' )\n\t\t\t.addClass( 'oo-ui-popupWidget-head' )\n\t\t\t.append( this.$label, this.closeButton.$element );\n\t\tthis.$popup.prepend( this.$head );\n\t}\n\n\tif ( config.$footer ) {\n\t\tthis.$footer = $( '<div>' )\n\t\t\t.addClass( 'oo-ui-popupWidget-footer' )\n\t\t\t.append( config.$footer );\n\t\tthis.$popup.append( this.$footer );\n\t}\n\n\t// Initially hidden - using #toggle may cause errors if subclasses override toggle with methods\n\t// that reference properties not initialized at that time of parent class construction\n\t// TODO: Find a better way to handle post-constructor setup\n\tthis.visible = false;\n\tthis.$element.addClass( 'oo-ui-element-hidden' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.PopupWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.PopupWidget, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.PopupWidget, OO.ui.mixin.ClippableElement );\nOO.mixinClass( OO.ui.PopupWidget, OO.ui.mixin.FloatableElement );\n\n/* Events */\n\n/**\n * @event ready\n *\n * The popup is ready: it is visible and has been positioned and clipped.\n */\n\n/* Methods */\n\n/**\n * Handles mouse down events.\n *\n * @private\n * @param {MouseEvent} e Mouse down event\n */\nOO.ui.PopupWidget.prototype.onMouseDown = function ( e ) {\n\tif (\n\t\tthis.isVisible() &&\n\t\t!OO.ui.contains( this.$element.add( this.$autoCloseIgnore ).get(), e.target, true )\n\t) {\n\t\tthis.toggle( false );\n\t}\n};\n\n/**\n * Bind mouse down listener.\n *\n * @private\n */\nOO.ui.PopupWidget.prototype.bindMouseDownListener = function () {\n\t// Capture clicks outside popup\n\tthis.getElementWindow().addEventListener( 'mousedown', this.onMouseDownHandler, true );\n};\n\n/**\n * Handles close button click events.\n *\n * @private\n */\nOO.ui.PopupWidget.prototype.onCloseButtonClick = function () {\n\tif ( this.isVisible() ) {\n\t\tthis.toggle( false );\n\t}\n};\n\n/**\n * Unbind mouse down listener.\n *\n * @private\n */\nOO.ui.PopupWidget.prototype.unbindMouseDownListener = function () {\n\tthis.getElementWindow().removeEventListener( 'mousedown', this.onMouseDownHandler, true );\n};\n\n/**\n * Handles key down events.\n *\n * @private\n * @param {KeyboardEvent} e Key down event\n */\nOO.ui.PopupWidget.prototype.onDocumentKeyDown = function ( e ) {\n\tif (\n\t\te.which === OO.ui.Keys.ESCAPE &&\n\t\tthis.isVisible()\n\t) {\n\t\tthis.toggle( false );\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t}\n};\n\n/**\n * Bind key down listener.\n *\n * @private\n */\nOO.ui.PopupWidget.prototype.bindKeyDownListener = function () {\n\tthis.getElementWindow().addEventListener( 'keydown', this.onDocumentKeyDownHandler, true );\n};\n\n/**\n * Unbind key down listener.\n *\n * @private\n */\nOO.ui.PopupWidget.prototype.unbindKeyDownListener = function () {\n\tthis.getElementWindow().removeEventListener( 'keydown', this.onDocumentKeyDownHandler, true );\n};\n\n/**\n * Show, hide, or toggle the visibility of the anchor.\n *\n * @param {boolean} [show] Show anchor, omit to toggle\n */\nOO.ui.PopupWidget.prototype.toggleAnchor = function ( show ) {\n\tshow = show === undefined ? !this.anchored : !!show;\n\n\tif ( this.anchored !== show ) {\n\t\tif ( show ) {\n\t\t\tthis.$element.addClass( 'oo-ui-popupWidget-anchored' );\n\t\t\tthis.$element.addClass( 'oo-ui-popupWidget-anchored-' + this.anchorEdge );\n\t\t} else {\n\t\t\tthis.$element.removeClass( 'oo-ui-popupWidget-anchored' );\n\t\t\tthis.$element.removeClass( 'oo-ui-popupWidget-anchored-' + this.anchorEdge );\n\t\t}\n\t\tthis.anchored = show;\n\t}\n};\n/**\n * Change which edge the anchor appears on.\n *\n * @param {string} edge 'top', 'bottom', 'start' or 'end'\n */\nOO.ui.PopupWidget.prototype.setAnchorEdge = function ( edge ) {\n\tif ( [ 'top', 'bottom', 'start', 'end' ].indexOf( edge ) === -1 ) {\n\t\tthrow new Error( 'Invalid value for edge: ' + edge );\n\t}\n\tif ( this.anchorEdge !== null ) {\n\t\tthis.$element.removeClass( 'oo-ui-popupWidget-anchored-' + this.anchorEdge );\n\t}\n\tthis.anchorEdge = edge;\n\tif ( this.anchored ) {\n\t\tthis.$element.addClass( 'oo-ui-popupWidget-anchored-' + edge );\n\t}\n};\n\n/**\n * Check if the anchor is visible.\n *\n * @return {boolean} Anchor is visible\n */\nOO.ui.PopupWidget.prototype.hasAnchor = function () {\n\treturn this.anchored;\n};\n\n/**\n * Toggle visibility of the popup. The popup is initially hidden and must be shown by calling\n * `.toggle( true )` after its #$element is attached to the DOM.\n *\n * Do not show the popup while it is not attached to the DOM. The calculations required to display\n * it in the right place and with the right dimensions only work correctly while it is attached.\n * Side-effects may include broken interface and exceptions being thrown. This wasn't always\n * strictly enforced, so currently it only generates a warning in the browser console.\n *\n * @fires ready\n * @inheritdoc\n */\nOO.ui.PopupWidget.prototype.toggle = function ( show ) {\n\tvar change;\n\tshow = show === undefined ? !this.isVisible() : !!show;\n\n\tchange = show !== this.isVisible();\n\n\tif ( show && !this.warnedUnattached && !this.isElementAttached() ) {\n\t\tOO.ui.warnDeprecation( 'PopupWidget#toggle: Before calling this method, the popup must be attached to the DOM.' );\n\t\tthis.warnedUnattached = true;\n\t}\n\tif ( show && !this.$floatableContainer && this.isElementAttached() ) {\n\t\t// Fall back to the parent node if the floatableContainer is not set\n\t\tthis.setFloatableContainer( this.$element.parent() );\n\t}\n\n\t// Parent method\n\tOO.ui.PopupWidget.parent.prototype.toggle.call( this, show );\n\n\tif ( change ) {\n\t\tthis.togglePositioning( show && !!this.$floatableContainer );\n\n\t\tif ( show ) {\n\t\t\tif ( this.autoClose ) {\n\t\t\t\tthis.bindMouseDownListener();\n\t\t\t\tthis.bindKeyDownListener();\n\t\t\t}\n\t\t\tthis.updateDimensions();\n\t\t\tthis.toggleClipping( true );\n\t\t\tthis.emit( 'ready' );\n\t\t} else {\n\t\t\tthis.toggleClipping( false );\n\t\t\tif ( this.autoClose ) {\n\t\t\t\tthis.unbindMouseDownListener();\n\t\t\t\tthis.unbindKeyDownListener();\n\t\t\t}\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Set the size of the popup.\n *\n * Changing the size may also change the popup's position depending on the alignment.\n *\n * @param {number} width Width in pixels\n * @param {number} height Height in pixels\n * @param {boolean} [transition=false] Use a smooth transition\n * @chainable\n */\nOO.ui.PopupWidget.prototype.setSize = function ( width, height, transition ) {\n\tthis.width = width;\n\tthis.height = height !== undefined ? height : null;\n\tif ( this.isVisible() ) {\n\t\tthis.updateDimensions( transition );\n\t}\n};\n\n/**\n * Update the size and position.\n *\n * Only use this to keep the popup properly anchored. Use #setSize to change the size, and this will\n * be called automatically.\n *\n * @param {boolean} [transition=false] Use a smooth transition\n * @chainable\n */\nOO.ui.PopupWidget.prototype.updateDimensions = function ( transition ) {\n\tvar widget = this;\n\n\t// Prevent transition from being interrupted\n\tclearTimeout( this.transitionTimeout );\n\tif ( transition ) {\n\t\t// Enable transition\n\t\tthis.$element.addClass( 'oo-ui-popupWidget-transitioning' );\n\t}\n\n\tthis.position();\n\n\tif ( transition ) {\n\t\t// Prevent transitioning after transition is complete\n\t\tthis.transitionTimeout = setTimeout( function () {\n\t\t\twidget.$element.removeClass( 'oo-ui-popupWidget-transitioning' );\n\t\t}, 200 );\n\t} else {\n\t\t// Prevent transitioning immediately\n\t\tthis.$element.removeClass( 'oo-ui-popupWidget-transitioning' );\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.PopupWidget.prototype.computePosition = function () {\n\tvar direction, align, vertical, start, end, near, far, sizeProp, popupSize, anchorSize, anchorPos,\n\t\tanchorOffset, anchorMargin, parentPosition, positionProp, positionAdjustment, floatablePos,\n\t\toffsetParentPos, containerPos,\n\t\tpopupPos = {},\n\t\tanchorCss = { left: '', right: '', top: '', bottom: '' },\n\t\talignMap = {\n\t\t\tltr: {\n\t\t\t\t'force-left': 'backwards',\n\t\t\t\t'force-right': 'forwards'\n\t\t\t},\n\t\t\trtl: {\n\t\t\t\t'force-left': 'forwards',\n\t\t\t\t'force-right': 'backwards'\n\t\t\t}\n\t\t},\n\t\tanchorEdgeMap = {\n\t\t\tabove: 'bottom',\n\t\t\tbelow: 'top',\n\t\t\tbefore: 'end',\n\t\t\tafter: 'start'\n\t\t},\n\t\thPosMap = {\n\t\t\tforwards: 'start',\n\t\t\tcenter: 'center',\n\t\t\tbackwards: this.anchored ? 'before' : 'end'\n\t\t},\n\t\tvPosMap = {\n\t\t\tforwards: 'top',\n\t\t\tcenter: 'center',\n\t\t\tbackwards: 'bottom'\n\t\t};\n\n\tif ( !this.$container ) {\n\t\t// Lazy-initialize $container if not specified in constructor\n\t\tthis.$container = $( this.getClosestScrollableElementContainer() );\n\t}\n\tdirection = this.$container.css( 'direction' );\n\n\t// Set height and width before we do anything else, since it might cause our measurements\n\t// to change (e.g. due to scrollbars appearing or disappearing), and it also affects centering\n\tthis.$popup.css( {\n\t\twidth: this.width,\n\t\theight: this.height !== null ? this.height : 'auto'\n\t} );\n\n\talign = alignMap[ direction ][ this.align ] || this.align;\n\t// If the popup is positioned before or after, then the anchor positioning is vertical, otherwise horizontal\n\tvertical = this.popupPosition === 'before' || this.popupPosition === 'after';\n\tstart = vertical ? 'top' : ( direction === 'rtl' ? 'right' : 'left' );\n\tend = vertical ? 'bottom' : ( direction === 'rtl' ? 'left' : 'right' );\n\tnear = vertical ? 'top' : 'left';\n\tfar = vertical ? 'bottom' : 'right';\n\tsizeProp = vertical ? 'Height' : 'Width';\n\tpopupSize = vertical ? ( this.height || this.$popup.height() ) : this.width;\n\n\tthis.setAnchorEdge( anchorEdgeMap[ this.popupPosition ] );\n\tthis.horizontalPosition = vertical ? this.popupPosition : hPosMap[ align ];\n\tthis.verticalPosition = vertical ? vPosMap[ align ] : this.popupPosition;\n\n\t// Parent method\n\tparentPosition = OO.ui.mixin.FloatableElement.prototype.computePosition.call( this );\n\t// Find out which property FloatableElement used for positioning, and adjust that value\n\tpositionProp = vertical ?\n\t\t( parentPosition.top !== '' ? 'top' : 'bottom' ) :\n\t\t( parentPosition.left !== '' ? 'left' : 'right' );\n\n\t// Figure out where the near and far edges of the popup and $floatableContainer are\n\tfloatablePos = this.$floatableContainer.offset();\n\tfloatablePos[ far ] = floatablePos[ near ] + this.$floatableContainer[ 'outer' + sizeProp ]();\n\t// Measure where the offsetParent is and compute our position based on that and parentPosition\n\toffsetParentPos = this.$element.offsetParent().offset();\n\n\tif ( positionProp === near ) {\n\t\tpopupPos[ near ] = offsetParentPos[ near ] + parentPosition[ near ];\n\t\tpopupPos[ far ] = popupPos[ near ] + popupSize;\n\t} else {\n\t\tpopupPos[ far ] = offsetParentPos[ near ] +\n\t\t\tthis.$element.offsetParent()[ 'inner' + sizeProp ]() - parentPosition[ far ];\n\t\tpopupPos[ near ] = popupPos[ far ] - popupSize;\n\t}\n\n\tif ( this.anchored ) {\n\t\t// Position the anchor (which is positioned relative to the popup) to point to $floatableContainer\n\t\tanchorPos = ( floatablePos[ start ] + floatablePos[ end ] ) / 2;\n\t\tanchorOffset = ( start === far ? -1 : 1 ) * ( anchorPos - popupPos[ start ] );\n\n\t\t// If the anchor is less than 2*anchorSize from either edge, move the popup to make more space\n\t\t// this.$anchor.width()/height() returns 0 because of the CSS trickery we use, so use scrollWidth/Height\n\t\tanchorSize = this.$anchor[ 0 ][ 'scroll' + sizeProp ];\n\t\tanchorMargin = parseFloat( this.$anchor.css( 'margin-' + start ) );\n\t\tif ( anchorOffset + anchorMargin < 2 * anchorSize ) {\n\t\t\t// Not enough space for the anchor on the start side; pull the popup startwards\n\t\t\tpositionAdjustment = ( positionProp === start ? -1 : 1 ) *\n\t\t\t\t( 2 * anchorSize - ( anchorOffset + anchorMargin ) );\n\t\t} else if ( anchorOffset + anchorMargin > popupSize - 2 * anchorSize ) {\n\t\t\t// Not enough space for the anchor on the end side; pull the popup endwards\n\t\t\tpositionAdjustment = ( positionProp === end ? -1 : 1 ) *\n\t\t\t\t( anchorOffset + anchorMargin - ( popupSize - 2 * anchorSize ) );\n\t\t} else {\n\t\t\tpositionAdjustment = 0;\n\t\t}\n\t} else {\n\t\tpositionAdjustment = 0;\n\t}\n\n\t// Check if the popup will go beyond the edge of this.$container\n\tcontainerPos = this.$container.offset();\n\tcontainerPos[ far ] = containerPos[ near ] + this.$container[ 'inner' + sizeProp ]();\n\t// Take into account how much the popup will move because of the adjustments we're going to make\n\tpopupPos[ near ] += ( positionProp === near ? 1 : -1 ) * positionAdjustment;\n\tpopupPos[ far ] += ( positionProp === near ? 1 : -1 ) * positionAdjustment;\n\tif ( containerPos[ near ] + this.containerPadding > popupPos[ near ] ) {\n\t\t// Popup goes beyond the near (left/top) edge, move it to the right/bottom\n\t\tpositionAdjustment += ( positionProp === near ? 1 : -1 ) *\n\t\t\t( containerPos[ near ] + this.containerPadding - popupPos[ near ] );\n\t} else if ( containerPos[ far ] - this.containerPadding < popupPos[ far ] ) {\n\t\t// Popup goes beyond the far (right/bottom) edge, move it to the left/top\n\t\tpositionAdjustment += ( positionProp === far ? 1 : -1 ) *\n\t\t\t( popupPos[ far ] - ( containerPos[ far ] - this.containerPadding ) );\n\t}\n\n\tif ( this.anchored ) {\n\t\t// Adjust anchorOffset for positionAdjustment\n\t\tanchorOffset += ( positionProp === start ? -1 : 1 ) * positionAdjustment;\n\n\t\t// Position the anchor\n\t\tanchorCss[ start ] = anchorOffset;\n\t\tthis.$anchor.css( anchorCss );\n\t}\n\n\t// Move the popup if needed\n\tparentPosition[ positionProp ] += positionAdjustment;\n\n\treturn parentPosition;\n};\n\n/**\n * Set popup alignment\n *\n * @param {string} [align=center] Alignment of the popup, `center`, `force-left`, `force-right`,\n * `backwards` or `forwards`.\n */\nOO.ui.PopupWidget.prototype.setAlignment = function ( align ) {\n\t// Validate alignment\n\tif ( [ 'force-left', 'force-right', 'backwards', 'forwards', 'center' ].indexOf( align ) > -1 ) {\n\t\tthis.align = align;\n\t} else {\n\t\tthis.align = 'center';\n\t}\n\tthis.position();\n};\n\n/**\n * Get popup alignment\n *\n * @return {string} Alignment of the popup, `center`, `force-left`, `force-right`,\n * `backwards` or `forwards`.\n */\nOO.ui.PopupWidget.prototype.getAlignment = function () {\n\treturn this.align;\n};\n\n/**\n * Change the positioning of the popup.\n *\n * @param {string} position 'above', 'below', 'before' or 'after'\n */\nOO.ui.PopupWidget.prototype.setPosition = function ( position ) {\n\tif ( [ 'above', 'below', 'before', 'after' ].indexOf( position ) === -1 ) {\n\t\tposition = 'below';\n\t}\n\tthis.popupPosition = position;\n\tthis.position();\n};\n\n/**\n * Get popup positioning.\n *\n * @return {string} 'above', 'below', 'before' or 'after'\n */\nOO.ui.PopupWidget.prototype.getPosition = function () {\n\treturn this.popupPosition;\n};\n\n/**\n * Get an ID of the body element, this can be used as the\n * `aria-describedby` attribute for an input field.\n *\n * @return {string} The ID of the body element\n */\nOO.ui.PopupWidget.prototype.getBodyId = function () {\n\tvar id = this.$body.attr( 'id' );\n\tif ( id === undefined ) {\n\t\tid = OO.ui.generateElementId();\n\t\tthis.$body.attr( 'id', id );\n\t}\n\treturn id;\n};\n","/**\n * PopupElement is mixed into other classes to generate a {@link OO.ui.PopupWidget popup widget}.\n * A popup is a container for content. It is overlaid and positioned absolutely. By default, each\n * popup has an anchor, which is an arrow-like protrusion that points toward the popup’s origin.\n * See {@link OO.ui.PopupWidget PopupWidget} for an example.\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {Object} [popup] Configuration to pass to popup\n * @cfg {boolean} [popup.autoClose=true] Popup auto-closes when it loses focus\n */\nOO.ui.mixin.PopupElement = function OoUiMixinPopupElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.popup = new OO.ui.PopupWidget( $.extend(\n\t\t{\n\t\t\tautoClose: true,\n\t\t\t$floatableContainer: this.$element\n\t\t},\n\t\tconfig.popup,\n\t\t{\n\t\t\t$autoCloseIgnore: this.$element.add( config.popup && config.popup.$autoCloseIgnore )\n\t\t}\n\t) );\n};\n\n/* Methods */\n\n/**\n * Get popup.\n *\n * @return {OO.ui.PopupWidget} Popup widget\n */\nOO.ui.mixin.PopupElement.prototype.getPopup = function () {\n\treturn this.popup;\n};\n","/**\n * PopupButtonWidgets toggle the visibility of a contained {@link OO.ui.PopupWidget PopupWidget},\n * which is used to display additional information or options.\n *\n * @example\n * // Example of a popup button.\n * var popupButton = new OO.ui.PopupButtonWidget( {\n * label: 'Popup button with options',\n * icon: 'menu',\n * popup: {\n * $content: $( '<p>Additional options here.</p>' ),\n * padded: true,\n * align: 'force-left'\n * }\n * } );\n * // Append the button to the DOM.\n * $( 'body' ).append( popupButton.$element );\n *\n * @class\n * @extends OO.ui.ButtonWidget\n * @mixins OO.ui.mixin.PopupElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$overlay] Render the popup into a separate layer. This configuration is useful in cases where\n * the expanded popup is larger than its containing `<div>`. The specified overlay layer is usually on top of the\n * containing `<div>` and has a larger area. By default, the popup uses relative positioning.\n * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.\n */\nOO.ui.PopupButtonWidget = function OoUiPopupButtonWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.PopupButtonWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.PopupElement.call( this, config );\n\n\t// Properties\n\tthis.$overlay = config.$overlay || this.$element;\n\n\t// Events\n\tthis.connect( this, { click: 'onAction' } );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-popupButtonWidget' )\n\t\t.attr( 'aria-haspopup', 'true' );\n\tthis.popup.$element\n\t\t.addClass( 'oo-ui-popupButtonWidget-popup' )\n\t\t.toggleClass( 'oo-ui-popupButtonWidget-framed-popup', this.isFramed() )\n\t\t.toggleClass( 'oo-ui-popupButtonWidget-frameless-popup', !this.isFramed() );\n\tthis.$overlay.append( this.popup.$element );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.PopupButtonWidget, OO.ui.ButtonWidget );\nOO.mixinClass( OO.ui.PopupButtonWidget, OO.ui.mixin.PopupElement );\n\n/* Methods */\n\n/**\n * Handle the button action being triggered.\n *\n * @private\n */\nOO.ui.PopupButtonWidget.prototype.onAction = function () {\n\tthis.popup.toggle();\n};\n","/**\n * Mixin for OO.ui.Widget subclasses to provide OO.ui.mixin.GroupElement.\n *\n * Use together with OO.ui.mixin.ItemWidget to make disabled state inheritable.\n *\n * @private\n * @abstract\n * @class\n * @mixins OO.ui.mixin.GroupElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.mixin.GroupWidget = function OoUiMixinGroupWidget( config ) {\n\t// Mixin constructors\n\tOO.ui.mixin.GroupElement.call( this, config );\n};\n\n/* Setup */\n\nOO.mixinClass( OO.ui.mixin.GroupWidget, OO.ui.mixin.GroupElement );\n\n/* Methods */\n\n/**\n * Set the disabled state of the widget.\n *\n * This will also update the disabled state of child widgets.\n *\n * @param {boolean} disabled Disable widget\n * @chainable\n */\nOO.ui.mixin.GroupWidget.prototype.setDisabled = function ( disabled ) {\n\tvar i, len;\n\n\t// Parent method\n\t// Note: Calling #setDisabled this way assumes this is mixed into an OO.ui.Widget\n\tOO.ui.Widget.prototype.setDisabled.call( this, disabled );\n\n\t// During construction, #setDisabled is called before the OO.ui.mixin.GroupElement constructor\n\tif ( this.items ) {\n\t\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\t\tthis.items[ i ].updateDisabled();\n\t\t}\n\t}\n\n\treturn this;\n};\n","/**\n * Mixin for widgets used as items in widgets that mix in OO.ui.mixin.GroupWidget.\n *\n * Item widgets have a reference to a OO.ui.mixin.GroupWidget while they are attached to the group. This\n * allows bidirectional communication.\n *\n * Use together with OO.ui.mixin.GroupWidget to make disabled state inheritable.\n *\n * @private\n * @abstract\n * @class\n *\n * @constructor\n */\nOO.ui.mixin.ItemWidget = function OoUiMixinItemWidget() {\n\t//\n};\n\n/* Methods */\n\n/**\n * Check if widget is disabled.\n *\n * Checks parent if present, making disabled state inheritable.\n *\n * @return {boolean} Widget is disabled\n */\nOO.ui.mixin.ItemWidget.prototype.isDisabled = function () {\n\treturn this.disabled ||\n\t\t( this.elementGroup instanceof OO.ui.Widget && this.elementGroup.isDisabled() );\n};\n\n/**\n * Set group element is in.\n *\n * @param {OO.ui.mixin.GroupElement|null} group Group element, null if none\n * @chainable\n */\nOO.ui.mixin.ItemWidget.prototype.setElementGroup = function ( group ) {\n\t// Parent method\n\t// Note: Calling #setElementGroup this way assumes this is mixed into an OO.ui.Element\n\tOO.ui.Element.prototype.setElementGroup.call( this, group );\n\n\t// Initialize item disabled states\n\tthis.updateDisabled();\n\n\treturn this;\n};\n","/**\n * OptionWidgets are special elements that can be selected and configured with data. The\n * data is often unique for each option, but it does not have to be. OptionWidgets are used\n * with OO.ui.SelectWidget to create a selection of mutually exclusive options. For more information\n * and examples, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.ItemWidget\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.FlaggedElement\n * @mixins OO.ui.mixin.AccessKeyedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.OptionWidget = function OoUiOptionWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.OptionWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.ItemWidget.call( this );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\tOO.ui.mixin.FlaggedElement.call( this, config );\n\tOO.ui.mixin.AccessKeyedElement.call( this, config );\n\n\t// Properties\n\tthis.selected = false;\n\tthis.highlighted = false;\n\tthis.pressed = false;\n\n\t// Initialization\n\tthis.$element\n\t\t.data( 'oo-ui-optionWidget', this )\n\t\t// Allow programmatic focussing (and by accesskey), but not tabbing\n\t\t.attr( 'tabindex', '-1' )\n\t\t.attr( 'role', 'option' )\n\t\t.attr( 'aria-selected', 'false' )\n\t\t.addClass( 'oo-ui-optionWidget' )\n\t\t.append( this.$label );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.OptionWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.OptionWidget, OO.ui.mixin.ItemWidget );\nOO.mixinClass( OO.ui.OptionWidget, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.OptionWidget, OO.ui.mixin.FlaggedElement );\nOO.mixinClass( OO.ui.OptionWidget, OO.ui.mixin.AccessKeyedElement );\n\n/* Static Properties */\n\n/**\n * Whether this option can be selected. See #setSelected.\n *\n * @static\n * @inheritable\n * @property {boolean}\n */\nOO.ui.OptionWidget.static.selectable = true;\n\n/**\n * Whether this option can be highlighted. See #setHighlighted.\n *\n * @static\n * @inheritable\n * @property {boolean}\n */\nOO.ui.OptionWidget.static.highlightable = true;\n\n/**\n * Whether this option can be pressed. See #setPressed.\n *\n * @static\n * @inheritable\n * @property {boolean}\n */\nOO.ui.OptionWidget.static.pressable = true;\n\n/**\n * Whether this option will be scrolled into view when it is selected.\n *\n * @static\n * @inheritable\n * @property {boolean}\n */\nOO.ui.OptionWidget.static.scrollIntoViewOnSelect = false;\n\n/* Methods */\n\n/**\n * Check if the option can be selected.\n *\n * @return {boolean} Item is selectable\n */\nOO.ui.OptionWidget.prototype.isSelectable = function () {\n\treturn this.constructor.static.selectable && !this.isDisabled() && this.isVisible();\n};\n\n/**\n * Check if the option can be highlighted. A highlight indicates that the option\n * may be selected when a user presses enter or clicks. Disabled items cannot\n * be highlighted.\n *\n * @return {boolean} Item is highlightable\n */\nOO.ui.OptionWidget.prototype.isHighlightable = function () {\n\treturn this.constructor.static.highlightable && !this.isDisabled() && this.isVisible();\n};\n\n/**\n * Check if the option can be pressed. The pressed state occurs when a user mouses\n * down on an item, but has not yet let go of the mouse.\n *\n * @return {boolean} Item is pressable\n */\nOO.ui.OptionWidget.prototype.isPressable = function () {\n\treturn this.constructor.static.pressable && !this.isDisabled() && this.isVisible();\n};\n\n/**\n * Check if the option is selected.\n *\n * @return {boolean} Item is selected\n */\nOO.ui.OptionWidget.prototype.isSelected = function () {\n\treturn this.selected;\n};\n\n/**\n * Check if the option is highlighted. A highlight indicates that the\n * item may be selected when a user presses enter or clicks.\n *\n * @return {boolean} Item is highlighted\n */\nOO.ui.OptionWidget.prototype.isHighlighted = function () {\n\treturn this.highlighted;\n};\n\n/**\n * Check if the option is pressed. The pressed state occurs when a user mouses\n * down on an item, but has not yet let go of the mouse. The item may appear\n * selected, but it will not be selected until the user releases the mouse.\n *\n * @return {boolean} Item is pressed\n */\nOO.ui.OptionWidget.prototype.isPressed = function () {\n\treturn this.pressed;\n};\n\n/**\n * Set the option’s selected state. In general, all modifications to the selection\n * should be handled by the SelectWidget’s {@link OO.ui.SelectWidget#selectItem selectItem( [item] )}\n * method instead of this method.\n *\n * @param {boolean} [state=false] Select option\n * @chainable\n */\nOO.ui.OptionWidget.prototype.setSelected = function ( state ) {\n\tif ( this.constructor.static.selectable ) {\n\t\tthis.selected = !!state;\n\t\tthis.$element\n\t\t\t.toggleClass( 'oo-ui-optionWidget-selected', state )\n\t\t\t.attr( 'aria-selected', state.toString() );\n\t\tif ( state && this.constructor.static.scrollIntoViewOnSelect ) {\n\t\t\tthis.scrollElementIntoView();\n\t\t}\n\t\tthis.updateThemeClasses();\n\t}\n\treturn this;\n};\n\n/**\n * Set the option’s highlighted state. In general, all programmatic\n * modifications to the highlight should be handled by the\n * SelectWidget’s {@link OO.ui.SelectWidget#highlightItem highlightItem( [item] )}\n * method instead of this method.\n *\n * @param {boolean} [state=false] Highlight option\n * @chainable\n */\nOO.ui.OptionWidget.prototype.setHighlighted = function ( state ) {\n\tif ( this.constructor.static.highlightable ) {\n\t\tthis.highlighted = !!state;\n\t\tthis.$element.toggleClass( 'oo-ui-optionWidget-highlighted', state );\n\t\tthis.updateThemeClasses();\n\t}\n\treturn this;\n};\n\n/**\n * Set the option’s pressed state. In general, all\n * programmatic modifications to the pressed state should be handled by the\n * SelectWidget’s {@link OO.ui.SelectWidget#pressItem pressItem( [item] )}\n * method instead of this method.\n *\n * @param {boolean} [state=false] Press option\n * @chainable\n */\nOO.ui.OptionWidget.prototype.setPressed = function ( state ) {\n\tif ( this.constructor.static.pressable ) {\n\t\tthis.pressed = !!state;\n\t\tthis.$element.toggleClass( 'oo-ui-optionWidget-pressed', state );\n\t\tthis.updateThemeClasses();\n\t}\n\treturn this;\n};\n\n/**\n * Get text to match search strings against.\n *\n * The default implementation returns the label text, but subclasses\n * can override this to provide more complex behavior.\n *\n * @return {string|boolean} String to match search string against\n */\nOO.ui.OptionWidget.prototype.getMatchText = function () {\n\tvar label = this.getLabel();\n\treturn typeof label === 'string' ? label : this.$label.text();\n};\n","/**\n * A SelectWidget is of a generic selection of options. The OOjs UI library contains several types of\n * select widgets, including {@link OO.ui.ButtonSelectWidget button selects},\n * {@link OO.ui.RadioSelectWidget radio selects}, and {@link OO.ui.MenuSelectWidget\n * menu selects}.\n *\n * This class should be used together with OO.ui.OptionWidget or OO.ui.DecoratedOptionWidget. For more\n * information, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * @example\n * // Example of a select widget with three options\n * var select = new OO.ui.SelectWidget( {\n * items: [\n * new OO.ui.OptionWidget( {\n * data: 'a',\n * label: 'Option One',\n * } ),\n * new OO.ui.OptionWidget( {\n * data: 'b',\n * label: 'Option Two',\n * } ),\n * new OO.ui.OptionWidget( {\n * data: 'c',\n * label: 'Option Three',\n * } )\n * ]\n * } );\n * $( 'body' ).append( select.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options\n *\n * @abstract\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.GroupWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {OO.ui.OptionWidget[]} [items] An array of options to add to the select.\n * Options are created with {@link OO.ui.OptionWidget OptionWidget} classes. See\n * the [OOjs UI documentation on MediaWiki] [2] for examples.\n * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options\n */\nOO.ui.SelectWidget = function OoUiSelectWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.SelectWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.GroupWidget.call( this, $.extend( {}, config, { $group: this.$element } ) );\n\n\t// Properties\n\tthis.pressed = false;\n\tthis.selecting = null;\n\tthis.onMouseUpHandler = this.onMouseUp.bind( this );\n\tthis.onMouseMoveHandler = this.onMouseMove.bind( this );\n\tthis.onKeyDownHandler = this.onKeyDown.bind( this );\n\tthis.onKeyPressHandler = this.onKeyPress.bind( this );\n\tthis.keyPressBuffer = '';\n\tthis.keyPressBufferTimer = null;\n\tthis.blockMouseOverEvents = 0;\n\n\t// Events\n\tthis.connect( this, {\n\t\ttoggle: 'onToggle'\n\t} );\n\tthis.$element.on( {\n\t\tfocusin: this.onFocus.bind( this ),\n\t\tmousedown: this.onMouseDown.bind( this ),\n\t\tmouseover: this.onMouseOver.bind( this ),\n\t\tmouseleave: this.onMouseLeave.bind( this )\n\t} );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-selectWidget oo-ui-selectWidget-depressed' )\n\t\t.attr( 'role', 'listbox' );\n\tthis.setFocusOwner( this.$element );\n\tif ( Array.isArray( config.items ) ) {\n\t\tthis.addItems( config.items );\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.SelectWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.SelectWidget, OO.ui.mixin.GroupWidget );\n\n/* Events */\n\n/**\n * @event highlight\n *\n * A `highlight` event is emitted when the highlight is changed with the #highlightItem method.\n *\n * @param {OO.ui.OptionWidget|null} item Highlighted item\n */\n\n/**\n * @event press\n *\n * A `press` event is emitted when the #pressItem method is used to programmatically modify the\n * pressed state of an option.\n *\n * @param {OO.ui.OptionWidget|null} item Pressed item\n */\n\n/**\n * @event select\n *\n * A `select` event is emitted when the selection is modified programmatically with the #selectItem method.\n *\n * @param {OO.ui.OptionWidget|null} item Selected item\n */\n\n/**\n * @event choose\n * A `choose` event is emitted when an item is chosen with the #chooseItem method.\n * @param {OO.ui.OptionWidget} item Chosen item\n */\n\n/**\n * @event add\n *\n * An `add` event is emitted when options are added to the select with the #addItems method.\n *\n * @param {OO.ui.OptionWidget[]} items Added items\n * @param {number} index Index of insertion point\n */\n\n/**\n * @event remove\n *\n * A `remove` event is emitted when options are removed from the select with the #clearItems\n * or #removeItems methods.\n *\n * @param {OO.ui.OptionWidget[]} items Removed items\n */\n\n/* Methods */\n\n/**\n * Handle focus events\n *\n * @private\n * @param {jQuery.Event} event\n */\nOO.ui.SelectWidget.prototype.onFocus = function ( event ) {\n\tvar item;\n\tif ( event.target === this.$element[ 0 ] ) {\n\t\t// This widget was focussed, e.g. by the user tabbing to it.\n\t\t// The styles for focus state depend on one of the items being selected.\n\t\tif ( !this.getSelectedItem() ) {\n\t\t\titem = this.getFirstSelectableItem();\n\t\t}\n\t} else {\n\t\t// One of the options got focussed (and the event bubbled up here).\n\t\t// They can't be tabbed to, but they can be activated using accesskeys.\n\t\titem = this.findTargetItem( event );\n\t}\n\n\tif ( item ) {\n\t\tif ( item.constructor.static.highlightable ) {\n\t\t\tthis.highlightItem( item );\n\t\t} else {\n\t\t\tthis.selectItem( item );\n\t\t}\n\t}\n\n\tif ( event.target !== this.$element[ 0 ] ) {\n\t\tthis.$focusOwner.focus();\n\t}\n};\n\n/**\n * Handle mouse down events.\n *\n * @private\n * @param {jQuery.Event} e Mouse down event\n */\nOO.ui.SelectWidget.prototype.onMouseDown = function ( e ) {\n\tvar item;\n\n\tif ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {\n\t\tthis.togglePressed( true );\n\t\titem = this.findTargetItem( e );\n\t\tif ( item && item.isSelectable() ) {\n\t\t\tthis.pressItem( item );\n\t\t\tthis.selecting = item;\n\t\t\tthis.getElementDocument().addEventListener( 'mouseup', this.onMouseUpHandler, true );\n\t\t\tthis.getElementDocument().addEventListener( 'mousemove', this.onMouseMoveHandler, true );\n\t\t}\n\t}\n\treturn false;\n};\n\n/**\n * Handle mouse up events.\n *\n * @private\n * @param {MouseEvent} e Mouse up event\n */\nOO.ui.SelectWidget.prototype.onMouseUp = function ( e ) {\n\tvar item;\n\n\tthis.togglePressed( false );\n\tif ( !this.selecting ) {\n\t\titem = this.findTargetItem( e );\n\t\tif ( item && item.isSelectable() ) {\n\t\t\tthis.selecting = item;\n\t\t}\n\t}\n\tif ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT && this.selecting ) {\n\t\tthis.pressItem( null );\n\t\tthis.chooseItem( this.selecting );\n\t\tthis.selecting = null;\n\t}\n\n\tthis.getElementDocument().removeEventListener( 'mouseup', this.onMouseUpHandler, true );\n\tthis.getElementDocument().removeEventListener( 'mousemove', this.onMouseMoveHandler, true );\n\n\treturn false;\n};\n\n/**\n * Handle mouse move events.\n *\n * @private\n * @param {MouseEvent} e Mouse move event\n */\nOO.ui.SelectWidget.prototype.onMouseMove = function ( e ) {\n\tvar item;\n\n\tif ( !this.isDisabled() && this.pressed ) {\n\t\titem = this.findTargetItem( e );\n\t\tif ( item && item !== this.selecting && item.isSelectable() ) {\n\t\t\tthis.pressItem( item );\n\t\t\tthis.selecting = item;\n\t\t}\n\t}\n};\n\n/**\n * Handle mouse over events.\n *\n * @private\n * @param {jQuery.Event} e Mouse over event\n */\nOO.ui.SelectWidget.prototype.onMouseOver = function ( e ) {\n\tvar item;\n\tif ( this.blockMouseOverEvents ) {\n\t\treturn;\n\t}\n\tif ( !this.isDisabled() ) {\n\t\titem = this.findTargetItem( e );\n\t\tthis.highlightItem( item && item.isHighlightable() ? item : null );\n\t}\n\treturn false;\n};\n\n/**\n * Handle mouse leave events.\n *\n * @private\n * @param {jQuery.Event} e Mouse over event\n */\nOO.ui.SelectWidget.prototype.onMouseLeave = function () {\n\tif ( !this.isDisabled() ) {\n\t\tthis.highlightItem( null );\n\t}\n\treturn false;\n};\n\n/**\n * Handle key down events.\n *\n * @protected\n * @param {KeyboardEvent} e Key down event\n */\nOO.ui.SelectWidget.prototype.onKeyDown = function ( e ) {\n\tvar nextItem,\n\t\thandled = false,\n\t\tcurrentItem = this.getHighlightedItem() || this.getSelectedItem();\n\n\tif ( !this.isDisabled() && this.isVisible() ) {\n\t\tswitch ( e.keyCode ) {\n\t\t\tcase OO.ui.Keys.ENTER:\n\t\t\t\tif ( currentItem && currentItem.constructor.static.highlightable ) {\n\t\t\t\t\t// Was only highlighted, now let's select it. No-op if already selected.\n\t\t\t\t\tthis.chooseItem( currentItem );\n\t\t\t\t\thandled = true;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OO.ui.Keys.UP:\n\t\t\tcase OO.ui.Keys.LEFT:\n\t\t\t\tthis.clearKeyPressBuffer();\n\t\t\t\tnextItem = this.getRelativeSelectableItem( currentItem, -1 );\n\t\t\t\thandled = true;\n\t\t\t\tbreak;\n\t\t\tcase OO.ui.Keys.DOWN:\n\t\t\tcase OO.ui.Keys.RIGHT:\n\t\t\t\tthis.clearKeyPressBuffer();\n\t\t\t\tnextItem = this.getRelativeSelectableItem( currentItem, 1 );\n\t\t\t\thandled = true;\n\t\t\t\tbreak;\n\t\t\tcase OO.ui.Keys.ESCAPE:\n\t\t\tcase OO.ui.Keys.TAB:\n\t\t\t\tif ( currentItem && currentItem.constructor.static.highlightable ) {\n\t\t\t\t\tcurrentItem.setHighlighted( false );\n\t\t\t\t}\n\t\t\t\tthis.unbindKeyDownListener();\n\t\t\t\tthis.unbindKeyPressListener();\n\t\t\t\t// Don't prevent tabbing away / defocusing\n\t\t\t\thandled = false;\n\t\t\t\tbreak;\n\t\t}\n\n\t\tif ( nextItem ) {\n\t\t\tif ( nextItem.constructor.static.highlightable ) {\n\t\t\t\tthis.highlightItem( nextItem );\n\t\t\t} else {\n\t\t\t\tthis.chooseItem( nextItem );\n\t\t\t}\n\t\t\tthis.scrollItemIntoView( nextItem );\n\t\t}\n\n\t\tif ( handled ) {\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t}\n\t}\n};\n\n/**\n * Bind key down listener.\n *\n * @protected\n */\nOO.ui.SelectWidget.prototype.bindKeyDownListener = function () {\n\tthis.getElementWindow().addEventListener( 'keydown', this.onKeyDownHandler, true );\n};\n\n/**\n * Unbind key down listener.\n *\n * @protected\n */\nOO.ui.SelectWidget.prototype.unbindKeyDownListener = function () {\n\tthis.getElementWindow().removeEventListener( 'keydown', this.onKeyDownHandler, true );\n};\n\n/**\n * Scroll item into view, preventing spurious mouse highlight actions from happening.\n *\n * @param {OO.ui.OptionWidget} item Item to scroll into view\n */\nOO.ui.SelectWidget.prototype.scrollItemIntoView = function ( item ) {\n\tvar widget = this;\n\t// Chromium's Blink engine will generate spurious 'mouseover' events during programmatic scrolling\n\t// and around 100-150 ms after it is finished.\n\tthis.blockMouseOverEvents++;\n\titem.scrollElementIntoView().done( function () {\n\t\tsetTimeout( function () {\n\t\t\twidget.blockMouseOverEvents--;\n\t\t}, 200 );\n\t} );\n};\n\n/**\n * Clear the key-press buffer\n *\n * @protected\n */\nOO.ui.SelectWidget.prototype.clearKeyPressBuffer = function () {\n\tif ( this.keyPressBufferTimer ) {\n\t\tclearTimeout( this.keyPressBufferTimer );\n\t\tthis.keyPressBufferTimer = null;\n\t}\n\tthis.keyPressBuffer = '';\n};\n\n/**\n * Handle key press events.\n *\n * @protected\n * @param {KeyboardEvent} e Key press event\n */\nOO.ui.SelectWidget.prototype.onKeyPress = function ( e ) {\n\tvar c, filter, item;\n\n\tif ( !e.charCode ) {\n\t\tif ( e.keyCode === OO.ui.Keys.BACKSPACE && this.keyPressBuffer !== '' ) {\n\t\t\tthis.keyPressBuffer = this.keyPressBuffer.substr( 0, this.keyPressBuffer.length - 1 );\n\t\t\treturn false;\n\t\t}\n\t\treturn;\n\t}\n\tif ( String.fromCodePoint ) {\n\t\tc = String.fromCodePoint( e.charCode );\n\t} else {\n\t\tc = String.fromCharCode( e.charCode );\n\t}\n\n\tif ( this.keyPressBufferTimer ) {\n\t\tclearTimeout( this.keyPressBufferTimer );\n\t}\n\tthis.keyPressBufferTimer = setTimeout( this.clearKeyPressBuffer.bind( this ), 1500 );\n\n\titem = this.getHighlightedItem() || this.getSelectedItem();\n\n\tif ( this.keyPressBuffer === c ) {\n\t\t// Common (if weird) special case: typing \"xxxx\" will cycle through all\n\t\t// the items beginning with \"x\".\n\t\tif ( item ) {\n\t\t\titem = this.getRelativeSelectableItem( item, 1 );\n\t\t}\n\t} else {\n\t\tthis.keyPressBuffer += c;\n\t}\n\n\tfilter = this.getItemMatcher( this.keyPressBuffer, false );\n\tif ( !item || !filter( item ) ) {\n\t\titem = this.getRelativeSelectableItem( item, 1, filter );\n\t}\n\tif ( item ) {\n\t\tif ( this.isVisible() && item.constructor.static.highlightable ) {\n\t\t\tthis.highlightItem( item );\n\t\t} else {\n\t\t\tthis.chooseItem( item );\n\t\t}\n\t\tthis.scrollItemIntoView( item );\n\t}\n\n\te.preventDefault();\n\te.stopPropagation();\n};\n\n/**\n * Get a matcher for the specific string\n *\n * @protected\n * @param {string} s String to match against items\n * @param {boolean} [exact=false] Only accept exact matches\n * @return {Function} function ( OO.ui.OptionWidget ) => boolean\n */\nOO.ui.SelectWidget.prototype.getItemMatcher = function ( s, exact ) {\n\tvar re;\n\n\tif ( s.normalize ) {\n\t\ts = s.normalize();\n\t}\n\ts = exact ? s.trim() : s.replace( /^\\s+/, '' );\n\tre = '^\\\\s*' + s.replace( /([\\\\{}()|.?*+\\-^$[\\]])/g, '\\\\$1' ).replace( /\\s+/g, '\\\\s+' );\n\tif ( exact ) {\n\t\tre += '\\\\s*$';\n\t}\n\tre = new RegExp( re, 'i' );\n\treturn function ( item ) {\n\t\tvar matchText = item.getMatchText();\n\t\tif ( matchText.normalize ) {\n\t\t\tmatchText = matchText.normalize();\n\t\t}\n\t\treturn re.test( matchText );\n\t};\n};\n\n/**\n * Bind key press listener.\n *\n * @protected\n */\nOO.ui.SelectWidget.prototype.bindKeyPressListener = function () {\n\tthis.getElementWindow().addEventListener( 'keypress', this.onKeyPressHandler, true );\n};\n\n/**\n * Unbind key down listener.\n *\n * If you override this, be sure to call this.clearKeyPressBuffer() from your\n * implementation.\n *\n * @protected\n */\nOO.ui.SelectWidget.prototype.unbindKeyPressListener = function () {\n\tthis.getElementWindow().removeEventListener( 'keypress', this.onKeyPressHandler, true );\n\tthis.clearKeyPressBuffer();\n};\n\n/**\n * Visibility change handler\n *\n * @protected\n * @param {boolean} visible\n */\nOO.ui.SelectWidget.prototype.onToggle = function ( visible ) {\n\tif ( !visible ) {\n\t\tthis.clearKeyPressBuffer();\n\t}\n};\n\n/**\n * Get the closest item to a jQuery.Event.\n *\n * @private\n * @param {jQuery.Event} e\n * @return {OO.ui.OptionWidget|null} Outline item widget, `null` if none was found\n */\nOO.ui.SelectWidget.prototype.findTargetItem = function ( e ) {\n\tvar $option = $( e.target ).closest( '.oo-ui-optionWidget' );\n\tif ( !$option.closest( '.oo-ui-selectWidget' ).is( this.$element ) ) {\n\t\treturn null;\n\t}\n\treturn $option.data( 'oo-ui-optionWidget' ) || null;\n};\n\n/**\n * Get selected item.\n *\n * @return {OO.ui.OptionWidget|null} Selected item, `null` if no item is selected\n */\nOO.ui.SelectWidget.prototype.getSelectedItem = function () {\n\tvar i, len;\n\n\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\tif ( this.items[ i ].isSelected() ) {\n\t\t\treturn this.items[ i ];\n\t\t}\n\t}\n\treturn null;\n};\n\n/**\n * Get highlighted item.\n *\n * @return {OO.ui.OptionWidget|null} Highlighted item, `null` if no item is highlighted\n */\nOO.ui.SelectWidget.prototype.getHighlightedItem = function () {\n\tvar i, len;\n\n\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\tif ( this.items[ i ].isHighlighted() ) {\n\t\t\treturn this.items[ i ];\n\t\t}\n\t}\n\treturn null;\n};\n\n/**\n * Toggle pressed state.\n *\n * Press is a state that occurs when a user mouses down on an item, but\n * has not yet let go of the mouse. The item may appear selected, but it will not be selected\n * until the user releases the mouse.\n *\n * @param {boolean} pressed An option is being pressed\n */\nOO.ui.SelectWidget.prototype.togglePressed = function ( pressed ) {\n\tif ( pressed === undefined ) {\n\t\tpressed = !this.pressed;\n\t}\n\tif ( pressed !== this.pressed ) {\n\t\tthis.$element\n\t\t\t.toggleClass( 'oo-ui-selectWidget-pressed', pressed )\n\t\t\t.toggleClass( 'oo-ui-selectWidget-depressed', !pressed );\n\t\tthis.pressed = pressed;\n\t}\n};\n\n/**\n * Highlight an option. If the `item` param is omitted, no options will be highlighted\n * and any existing highlight will be removed. The highlight is mutually exclusive.\n *\n * @param {OO.ui.OptionWidget} [item] Item to highlight, omit for no highlight\n * @fires highlight\n * @chainable\n */\nOO.ui.SelectWidget.prototype.highlightItem = function ( item ) {\n\tvar i, len, highlighted,\n\t\tchanged = false;\n\n\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\thighlighted = this.items[ i ] === item;\n\t\tif ( this.items[ i ].isHighlighted() !== highlighted ) {\n\t\t\tthis.items[ i ].setHighlighted( highlighted );\n\t\t\tchanged = true;\n\t\t}\n\t}\n\tif ( changed ) {\n\t\tif ( item ) {\n\t\t\tthis.$focusOwner.attr( 'aria-activedescendant', item.getElementId() );\n\t\t} else {\n\t\t\tthis.$focusOwner.removeAttr( 'aria-activedescendant' );\n\t\t}\n\t\tthis.emit( 'highlight', item );\n\t}\n\n\treturn this;\n};\n\n/**\n * Fetch an item by its label.\n *\n * @param {string} label Label of the item to select.\n * @param {boolean} [prefix=false] Allow a prefix match, if only a single item matches\n * @return {OO.ui.Element|null} Item with equivalent label, `null` if none exists\n */\nOO.ui.SelectWidget.prototype.getItemFromLabel = function ( label, prefix ) {\n\tvar i, item, found,\n\t\tlen = this.items.length,\n\t\tfilter = this.getItemMatcher( label, true );\n\n\tfor ( i = 0; i < len; i++ ) {\n\t\titem = this.items[ i ];\n\t\tif ( item instanceof OO.ui.OptionWidget && item.isSelectable() && filter( item ) ) {\n\t\t\treturn item;\n\t\t}\n\t}\n\n\tif ( prefix ) {\n\t\tfound = null;\n\t\tfilter = this.getItemMatcher( label, false );\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\titem = this.items[ i ];\n\t\t\tif ( item instanceof OO.ui.OptionWidget && item.isSelectable() && filter( item ) ) {\n\t\t\t\tif ( found ) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tfound = item;\n\t\t\t}\n\t\t}\n\t\tif ( found ) {\n\t\t\treturn found;\n\t\t}\n\t}\n\n\treturn null;\n};\n\n/**\n * Programmatically select an option by its label. If the item does not exist,\n * all options will be deselected.\n *\n * @param {string} [label] Label of the item to select.\n * @param {boolean} [prefix=false] Allow a prefix match, if only a single item matches\n * @fires select\n * @chainable\n */\nOO.ui.SelectWidget.prototype.selectItemByLabel = function ( label, prefix ) {\n\tvar itemFromLabel = this.getItemFromLabel( label, !!prefix );\n\tif ( label === undefined || !itemFromLabel ) {\n\t\treturn this.selectItem();\n\t}\n\treturn this.selectItem( itemFromLabel );\n};\n\n/**\n * Programmatically select an option by its data. If the `data` parameter is omitted,\n * or if the item does not exist, all options will be deselected.\n *\n * @param {Object|string} [data] Value of the item to select, omit to deselect all\n * @fires select\n * @chainable\n */\nOO.ui.SelectWidget.prototype.selectItemByData = function ( data ) {\n\tvar itemFromData = this.getItemFromData( data );\n\tif ( data === undefined || !itemFromData ) {\n\t\treturn this.selectItem();\n\t}\n\treturn this.selectItem( itemFromData );\n};\n\n/**\n * Programmatically select an option by its reference. If the `item` parameter is omitted,\n * all options will be deselected.\n *\n * @param {OO.ui.OptionWidget} [item] Item to select, omit to deselect all\n * @fires select\n * @chainable\n */\nOO.ui.SelectWidget.prototype.selectItem = function ( item ) {\n\tvar i, len, selected,\n\t\tchanged = false;\n\n\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\tselected = this.items[ i ] === item;\n\t\tif ( this.items[ i ].isSelected() !== selected ) {\n\t\t\tthis.items[ i ].setSelected( selected );\n\t\t\tchanged = true;\n\t\t}\n\t}\n\tif ( changed ) {\n\t\tif ( item && !item.constructor.static.highlightable ) {\n\t\t\tif ( item ) {\n\t\t\t\tthis.$focusOwner.attr( 'aria-activedescendant', item.getElementId() );\n\t\t\t} else {\n\t\t\t\tthis.$focusOwner.removeAttr( 'aria-activedescendant' );\n\t\t\t}\n\t\t}\n\t\tthis.emit( 'select', item );\n\t}\n\n\treturn this;\n};\n\n/**\n * Press an item.\n *\n * Press is a state that occurs when a user mouses down on an item, but has not\n * yet let go of the mouse. The item may appear selected, but it will not be selected until the user\n * releases the mouse.\n *\n * @param {OO.ui.OptionWidget} [item] Item to press, omit to depress all\n * @fires press\n * @chainable\n */\nOO.ui.SelectWidget.prototype.pressItem = function ( item ) {\n\tvar i, len, pressed,\n\t\tchanged = false;\n\n\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\tpressed = this.items[ i ] === item;\n\t\tif ( this.items[ i ].isPressed() !== pressed ) {\n\t\t\tthis.items[ i ].setPressed( pressed );\n\t\t\tchanged = true;\n\t\t}\n\t}\n\tif ( changed ) {\n\t\tthis.emit( 'press', item );\n\t}\n\n\treturn this;\n};\n\n/**\n * Choose an item.\n *\n * Note that ‘choose’ should never be modified programmatically. A user can choose\n * an option with the keyboard or mouse and it becomes selected. To select an item programmatically,\n * use the #selectItem method.\n *\n * This method is identical to #selectItem, but may vary in subclasses that take additional action\n * when users choose an item with the keyboard or mouse.\n *\n * @param {OO.ui.OptionWidget} item Item to choose\n * @fires choose\n * @chainable\n */\nOO.ui.SelectWidget.prototype.chooseItem = function ( item ) {\n\tif ( item ) {\n\t\tthis.selectItem( item );\n\t\tthis.emit( 'choose', item );\n\t}\n\n\treturn this;\n};\n\n/**\n * Get an option by its position relative to the specified item (or to the start of the option array,\n * if item is `null`). The direction in which to search through the option array is specified with a\n * number: -1 for reverse (the default) or 1 for forward. The method will return an option, or\n * `null` if there are no options in the array.\n *\n * @param {OO.ui.OptionWidget|null} item Item to describe the start position, or `null` to start at the beginning of the array.\n * @param {number} direction Direction to move in: -1 to move backward, 1 to move forward\n * @param {Function} [filter] Only consider items for which this function returns\n * true. Function takes an OO.ui.OptionWidget and returns a boolean.\n * @return {OO.ui.OptionWidget|null} Item at position, `null` if there are no items in the select\n */\nOO.ui.SelectWidget.prototype.getRelativeSelectableItem = function ( item, direction, filter ) {\n\tvar currentIndex, nextIndex, i,\n\t\tincrease = direction > 0 ? 1 : -1,\n\t\tlen = this.items.length;\n\n\tif ( item instanceof OO.ui.OptionWidget ) {\n\t\tcurrentIndex = this.items.indexOf( item );\n\t\tnextIndex = ( currentIndex + increase + len ) % len;\n\t} else {\n\t\t// If no item is selected and moving forward, start at the beginning.\n\t\t// If moving backward, start at the end.\n\t\tnextIndex = direction > 0 ? 0 : len - 1;\n\t}\n\n\tfor ( i = 0; i < len; i++ ) {\n\t\titem = this.items[ nextIndex ];\n\t\tif (\n\t\t\titem instanceof OO.ui.OptionWidget && item.isSelectable() &&\n\t\t\t( !filter || filter( item ) )\n\t\t) {\n\t\t\treturn item;\n\t\t}\n\t\tnextIndex = ( nextIndex + increase + len ) % len;\n\t}\n\treturn null;\n};\n\n/**\n * Get the next selectable item or `null` if there are no selectable items.\n * Disabled options and menu-section markers and breaks are not selectable.\n *\n * @return {OO.ui.OptionWidget|null} Item, `null` if there aren't any selectable items\n */\nOO.ui.SelectWidget.prototype.getFirstSelectableItem = function () {\n\treturn this.getRelativeSelectableItem( null, 1 );\n};\n\n/**\n * Add an array of options to the select. Optionally, an index number can be used to\n * specify an insertion point.\n *\n * @param {OO.ui.OptionWidget[]} items Items to add\n * @param {number} [index] Index to insert items after\n * @fires add\n * @chainable\n */\nOO.ui.SelectWidget.prototype.addItems = function ( items, index ) {\n\t// Mixin method\n\tOO.ui.mixin.GroupWidget.prototype.addItems.call( this, items, index );\n\n\t// Always provide an index, even if it was omitted\n\tthis.emit( 'add', items, index === undefined ? this.items.length - items.length - 1 : index );\n\n\treturn this;\n};\n\n/**\n * Remove the specified array of options from the select. Options will be detached\n * from the DOM, not removed, so they can be reused later. To remove all options from\n * the select, you may wish to use the #clearItems method instead.\n *\n * @param {OO.ui.OptionWidget[]} items Items to remove\n * @fires remove\n * @chainable\n */\nOO.ui.SelectWidget.prototype.removeItems = function ( items ) {\n\tvar i, len, item;\n\n\t// Deselect items being removed\n\tfor ( i = 0, len = items.length; i < len; i++ ) {\n\t\titem = items[ i ];\n\t\tif ( item.isSelected() ) {\n\t\t\tthis.selectItem( null );\n\t\t}\n\t}\n\n\t// Mixin method\n\tOO.ui.mixin.GroupWidget.prototype.removeItems.call( this, items );\n\n\tthis.emit( 'remove', items );\n\n\treturn this;\n};\n\n/**\n * Clear all options from the select. Options will be detached from the DOM, not removed,\n * so that they can be reused later. To remove a subset of options from the select, use\n * the #removeItems method.\n *\n * @fires remove\n * @chainable\n */\nOO.ui.SelectWidget.prototype.clearItems = function () {\n\tvar items = this.items.slice();\n\n\t// Mixin method\n\tOO.ui.mixin.GroupWidget.prototype.clearItems.call( this );\n\n\t// Clear selection\n\tthis.selectItem( null );\n\n\tthis.emit( 'remove', items );\n\n\treturn this;\n};\n\n/**\n * Set the DOM element which has focus while the user is interacting with this SelectWidget.\n *\n * Currently this is just used to set `aria-activedescendant` on it.\n *\n * @protected\n * @param {jQuery} $focusOwner\n */\nOO.ui.SelectWidget.prototype.setFocusOwner = function ( $focusOwner ) {\n\tthis.$focusOwner = $focusOwner;\n};\n","/**\n * DecoratedOptionWidgets are {@link OO.ui.OptionWidget options} that can be configured\n * with an {@link OO.ui.mixin.IconElement icon} and/or {@link OO.ui.mixin.IndicatorElement indicator}.\n * This class is used with OO.ui.SelectWidget to create a selection of mutually exclusive\n * options. For more information about options and selects, please see the\n * [OOjs UI documentation on MediaWiki][1].\n *\n * @example\n * // Decorated options in a select widget\n * var select = new OO.ui.SelectWidget( {\n * items: [\n * new OO.ui.DecoratedOptionWidget( {\n * data: 'a',\n * label: 'Option with icon',\n * icon: 'help'\n * } ),\n * new OO.ui.DecoratedOptionWidget( {\n * data: 'b',\n * label: 'Option with indicator',\n * indicator: 'next'\n * } )\n * ]\n * } );\n * $( 'body' ).append( select.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options\n *\n * @class\n * @extends OO.ui.OptionWidget\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.IndicatorElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.DecoratedOptionWidget = function OoUiDecoratedOptionWidget( config ) {\n\t// Parent constructor\n\tOO.ui.DecoratedOptionWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.IndicatorElement.call( this, config );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-decoratedOptionWidget' )\n\t\t.prepend( this.$icon )\n\t\t.append( this.$indicator );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.DecoratedOptionWidget, OO.ui.OptionWidget );\nOO.mixinClass( OO.ui.DecoratedOptionWidget, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.DecoratedOptionWidget, OO.ui.mixin.IndicatorElement );\n","/**\n * MenuOptionWidget is an option widget that looks like a menu item. The class is used with\n * OO.ui.MenuSelectWidget to create a menu of mutually exclusive options. Please see\n * the [OOjs UI documentation on MediaWiki] [1] for more information.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options\n *\n * @class\n * @extends OO.ui.DecoratedOptionWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.MenuOptionWidget = function OoUiMenuOptionWidget( config ) {\n\t// Parent constructor\n\tOO.ui.MenuOptionWidget.parent.call( this, config );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-menuOptionWidget' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.MenuOptionWidget, OO.ui.DecoratedOptionWidget );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.MenuOptionWidget.static.scrollIntoViewOnSelect = true;\n","/**\n * MenuSectionOptionWidgets are used inside {@link OO.ui.MenuSelectWidget menu select widgets} to group one or more related\n * {@link OO.ui.MenuOptionWidget menu options}. MenuSectionOptionWidgets cannot be highlighted or selected.\n *\n * @example\n * var myDropdown = new OO.ui.DropdownWidget( {\n * menu: {\n * items: [\n * new OO.ui.MenuSectionOptionWidget( {\n * label: 'Dogs'\n * } ),\n * new OO.ui.MenuOptionWidget( {\n * data: 'corgi',\n * label: 'Welsh Corgi'\n * } ),\n * new OO.ui.MenuOptionWidget( {\n * data: 'poodle',\n * label: 'Standard Poodle'\n * } ),\n * new OO.ui.MenuSectionOptionWidget( {\n * label: 'Cats'\n * } ),\n * new OO.ui.MenuOptionWidget( {\n * data: 'lion',\n * label: 'Lion'\n * } )\n * ]\n * }\n * } );\n * $( 'body' ).append( myDropdown.$element );\n *\n * @class\n * @extends OO.ui.DecoratedOptionWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.MenuSectionOptionWidget = function OoUiMenuSectionOptionWidget( config ) {\n\t// Parent constructor\n\tOO.ui.MenuSectionOptionWidget.parent.call( this, config );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-menuSectionOptionWidget' )\n\t\t.removeAttr( 'role aria-selected' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.MenuSectionOptionWidget, OO.ui.DecoratedOptionWidget );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.MenuSectionOptionWidget.static.selectable = false;\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.MenuSectionOptionWidget.static.highlightable = false;\n","/**\n * MenuSelectWidget is a {@link OO.ui.SelectWidget select widget} that contains options and\n * is used together with OO.ui.MenuOptionWidget. It is designed be used as part of another widget.\n * See {@link OO.ui.DropdownWidget DropdownWidget}, {@link OO.ui.ComboBoxInputWidget ComboBoxInputWidget},\n * and {@link OO.ui.mixin.LookupElement LookupElement} for examples of widgets that contain menus.\n * MenuSelectWidgets themselves are not instantiated directly, rather subclassed\n * and customized to be opened, closed, and displayed as needed.\n *\n * By default, menus are clipped to the visible viewport and are not visible when a user presses the\n * mouse outside the menu.\n *\n * Menus also have support for keyboard interaction:\n *\n * - Enter/Return key: choose and select a menu option\n * - Up-arrow key: highlight the previous menu option\n * - Down-arrow key: highlight the next menu option\n * - Esc key: hide the menu\n *\n * Unlike most widgets, MenuSelectWidget is initially hidden and must be shown by calling #toggle.\n *\n * Please see the [OOjs UI documentation on MediaWiki][1] for more information.\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options\n *\n * @class\n * @extends OO.ui.SelectWidget\n * @mixins OO.ui.mixin.ClippableElement\n * @mixins OO.ui.mixin.FloatableElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {OO.ui.TextInputWidget} [input] Text input used to implement option highlighting for menu items that match\n * the text the user types. This config is used by {@link OO.ui.ComboBoxInputWidget ComboBoxInputWidget}\n * and {@link OO.ui.mixin.LookupElement LookupElement}\n * @cfg {jQuery} [$input] Text input used to implement option highlighting for menu items that match\n * the text the user types. This config is used by {@link OO.ui.CapsuleMultiselectWidget CapsuleMultiselectWidget}\n * @cfg {OO.ui.Widget} [widget] Widget associated with the menu's active state. If the user clicks the mouse\n * anywhere on the page outside of this widget, the menu is hidden. For example, if there is a button\n * that toggles the menu's visibility on click, the menu will be hidden then re-shown when the user clicks\n * that button, unless the button (or its parent widget) is passed in here.\n * @cfg {boolean} [autoHide=true] Hide the menu when the mouse is pressed outside the menu.\n * @cfg {jQuery} [$autoCloseIgnore] If these elements are clicked, don't auto-hide the menu.\n * @cfg {boolean} [hideOnChoose=true] Hide the menu when the user chooses an option.\n * @cfg {boolean} [filterFromInput=false] Filter the displayed options from the input\n * @cfg {boolean} [highlightOnFilter] Highlight the first result when filtering\n * @cfg {number} [width] Width of the menu\n */\nOO.ui.MenuSelectWidget = function OoUiMenuSelectWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.MenuSelectWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.ClippableElement.call( this, $.extend( {}, config, { $clippable: this.$group } ) );\n\tOO.ui.mixin.FloatableElement.call( this, config );\n\n\t// Properties\n\tthis.autoHide = config.autoHide === undefined || !!config.autoHide;\n\tthis.hideOnChoose = config.hideOnChoose === undefined || !!config.hideOnChoose;\n\tthis.filterFromInput = !!config.filterFromInput;\n\tthis.$input = config.$input ? config.$input : config.input ? config.input.$input : null;\n\tthis.$widget = config.widget ? config.widget.$element : null;\n\tthis.$autoCloseIgnore = config.$autoCloseIgnore || $( [] );\n\tthis.onDocumentMouseDownHandler = this.onDocumentMouseDown.bind( this );\n\tthis.onInputEditHandler = OO.ui.debounce( this.updateItemVisibility.bind( this ), 100 );\n\tthis.highlightOnFilter = !!config.highlightOnFilter;\n\tthis.width = config.width;\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-menuSelectWidget' );\n\tif ( config.widget ) {\n\t\tthis.setFocusOwner( config.widget.$tabIndexed );\n\t}\n\n\t// Initially hidden - using #toggle may cause errors if subclasses override toggle with methods\n\t// that reference properties not initialized at that time of parent class construction\n\t// TODO: Find a better way to handle post-constructor setup\n\tthis.visible = false;\n\tthis.$element.addClass( 'oo-ui-element-hidden' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.MenuSelectWidget, OO.ui.SelectWidget );\nOO.mixinClass( OO.ui.MenuSelectWidget, OO.ui.mixin.ClippableElement );\nOO.mixinClass( OO.ui.MenuSelectWidget, OO.ui.mixin.FloatableElement );\n\n/* Events */\n\n/**\n * @event ready\n *\n * The menu is ready: it is visible and has been positioned and clipped.\n */\n\n/* Methods */\n\n/**\n * Handles document mouse down events.\n *\n * @protected\n * @param {MouseEvent} e Mouse down event\n */\nOO.ui.MenuSelectWidget.prototype.onDocumentMouseDown = function ( e ) {\n\tif (\n\t\tthis.isVisible() &&\n\t\t!OO.ui.contains(\n\t\t\tthis.$element.add( this.$widget ).add( this.$autoCloseIgnore ).get(),\n\t\t\te.target,\n\t\t\ttrue\n\t\t)\n\t) {\n\t\tthis.toggle( false );\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MenuSelectWidget.prototype.onKeyDown = function ( e ) {\n\tvar currentItem = this.getHighlightedItem() || this.getSelectedItem();\n\n\tif ( !this.isDisabled() && this.isVisible() ) {\n\t\tswitch ( e.keyCode ) {\n\t\t\tcase OO.ui.Keys.LEFT:\n\t\t\tcase OO.ui.Keys.RIGHT:\n\t\t\t\t// Do nothing if a text field is associated, arrow keys will be handled natively\n\t\t\t\tif ( !this.$input ) {\n\t\t\t\t\tOO.ui.MenuSelectWidget.parent.prototype.onKeyDown.call( this, e );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OO.ui.Keys.ESCAPE:\n\t\t\tcase OO.ui.Keys.TAB:\n\t\t\t\tif ( currentItem ) {\n\t\t\t\t\tcurrentItem.setHighlighted( false );\n\t\t\t\t}\n\t\t\t\tthis.toggle( false );\n\t\t\t\t// Don't prevent tabbing away, prevent defocusing\n\t\t\t\tif ( e.keyCode === OO.ui.Keys.ESCAPE ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\te.stopPropagation();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tOO.ui.MenuSelectWidget.parent.prototype.onKeyDown.call( this, e );\n\t\t\t\treturn;\n\t\t}\n\t}\n};\n\n/**\n * Update menu item visibility and clipping after input changes (if filterFromInput is enabled)\n * or after items were added/removed (always).\n *\n * @protected\n */\nOO.ui.MenuSelectWidget.prototype.updateItemVisibility = function () {\n\tvar i, item, visible, section, sectionEmpty, filter, exactFilter,\n\t\tfirstItemFound = false,\n\t\tanyVisible = false,\n\t\tlen = this.items.length,\n\t\tshowAll = !this.isVisible(),\n\t\texactMatch = false;\n\n\tif ( this.$input && this.filterFromInput ) {\n\t\tfilter = showAll ? null : this.getItemMatcher( this.$input.val() );\n\t\texactFilter = this.getItemMatcher( this.$input.val(), true );\n\n\t\t// Hide non-matching options, and also hide section headers if all options\n\t\t// in their section are hidden.\n\t\tfor ( i = 0; i < len; i++ ) {\n\t\t\titem = this.items[ i ];\n\t\t\tif ( item instanceof OO.ui.MenuSectionOptionWidget ) {\n\t\t\t\tif ( section ) {\n\t\t\t\t\t// If the previous section was empty, hide its header\n\t\t\t\t\tsection.toggle( showAll || !sectionEmpty );\n\t\t\t\t}\n\t\t\t\tsection = item;\n\t\t\t\tsectionEmpty = true;\n\t\t\t} else if ( item instanceof OO.ui.OptionWidget ) {\n\t\t\t\tvisible = showAll || filter( item );\n\t\t\t\texactMatch = exactMatch || exactFilter( item );\n\t\t\t\tanyVisible = anyVisible || visible;\n\t\t\t\tsectionEmpty = sectionEmpty && !visible;\n\t\t\t\titem.toggle( visible );\n\t\t\t\tif ( this.highlightOnFilter && visible && !firstItemFound ) {\n\t\t\t\t\t// Highlight the first item in the list\n\t\t\t\t\tthis.highlightItem( item );\n\t\t\t\t\tfirstItemFound = true;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Process the final section\n\t\tif ( section ) {\n\t\t\tsection.toggle( showAll || !sectionEmpty );\n\t\t}\n\n\t\tif ( anyVisible && this.items.length && !exactMatch ) {\n\t\t\tthis.scrollItemIntoView( this.items[ 0 ] );\n\t\t}\n\n\t\tthis.$element.toggleClass( 'oo-ui-menuSelectWidget-invisible', !anyVisible );\n\t}\n\n\t// Reevaluate clipping\n\tthis.clip();\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MenuSelectWidget.prototype.bindKeyDownListener = function () {\n\tif ( this.$input ) {\n\t\tthis.$input.on( 'keydown', this.onKeyDownHandler );\n\t} else {\n\t\tOO.ui.MenuSelectWidget.parent.prototype.bindKeyDownListener.call( this );\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MenuSelectWidget.prototype.unbindKeyDownListener = function () {\n\tif ( this.$input ) {\n\t\tthis.$input.off( 'keydown', this.onKeyDownHandler );\n\t} else {\n\t\tOO.ui.MenuSelectWidget.parent.prototype.unbindKeyDownListener.call( this );\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MenuSelectWidget.prototype.bindKeyPressListener = function () {\n\tif ( this.$input ) {\n\t\tif ( this.filterFromInput ) {\n\t\t\tthis.$input.on( 'keydown mouseup cut paste change input select', this.onInputEditHandler );\n\t\t\tthis.updateItemVisibility();\n\t\t}\n\t} else {\n\t\tOO.ui.MenuSelectWidget.parent.prototype.bindKeyPressListener.call( this );\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MenuSelectWidget.prototype.unbindKeyPressListener = function () {\n\tif ( this.$input ) {\n\t\tif ( this.filterFromInput ) {\n\t\t\tthis.$input.off( 'keydown mouseup cut paste change input select', this.onInputEditHandler );\n\t\t\tthis.updateItemVisibility();\n\t\t}\n\t} else {\n\t\tOO.ui.MenuSelectWidget.parent.prototype.unbindKeyPressListener.call( this );\n\t}\n};\n\n/**\n * Choose an item.\n *\n * When a user chooses an item, the menu is closed, unless the hideOnChoose config option is set to false.\n *\n * Note that ‘choose’ should never be modified programmatically. A user can choose an option with the keyboard\n * or mouse and it becomes selected. To select an item programmatically, use the #selectItem method.\n *\n * @param {OO.ui.OptionWidget} item Item to choose\n * @chainable\n */\nOO.ui.MenuSelectWidget.prototype.chooseItem = function ( item ) {\n\tOO.ui.MenuSelectWidget.parent.prototype.chooseItem.call( this, item );\n\tif ( this.hideOnChoose ) {\n\t\tthis.toggle( false );\n\t}\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MenuSelectWidget.prototype.addItems = function ( items, index ) {\n\t// Parent method\n\tOO.ui.MenuSelectWidget.parent.prototype.addItems.call( this, items, index );\n\n\tthis.updateItemVisibility();\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MenuSelectWidget.prototype.removeItems = function ( items ) {\n\t// Parent method\n\tOO.ui.MenuSelectWidget.parent.prototype.removeItems.call( this, items );\n\n\tthis.updateItemVisibility();\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MenuSelectWidget.prototype.clearItems = function () {\n\t// Parent method\n\tOO.ui.MenuSelectWidget.parent.prototype.clearItems.call( this );\n\n\tthis.updateItemVisibility();\n\n\treturn this;\n};\n\n/**\n * Toggle visibility of the menu. The menu is initially hidden and must be shown by calling\n * `.toggle( true )` after its #$element is attached to the DOM.\n *\n * Do not show the menu while it is not attached to the DOM. The calculations required to display\n * it in the right place and with the right dimensions only work correctly while it is attached.\n * Side-effects may include broken interface and exceptions being thrown. This wasn't always\n * strictly enforced, so currently it only generates a warning in the browser console.\n *\n * @fires ready\n * @inheritdoc\n */\nOO.ui.MenuSelectWidget.prototype.toggle = function ( visible ) {\n\tvar change;\n\n\tvisible = ( visible === undefined ? !this.visible : !!visible ) && !!this.items.length;\n\tchange = visible !== this.isVisible();\n\n\tif ( visible && !this.warnedUnattached && !this.isElementAttached() ) {\n\t\tOO.ui.warnDeprecation( 'MenuSelectWidget#toggle: Before calling this method, the menu must be attached to the DOM.' );\n\t\tthis.warnedUnattached = true;\n\t}\n\n\tif ( change && visible && ( this.width || this.$floatableContainer ) ) {\n\t\tthis.setIdealSize( this.width || this.$floatableContainer.width() );\n\t}\n\n\t// Parent method\n\tOO.ui.MenuSelectWidget.parent.prototype.toggle.call( this, visible );\n\n\tif ( change ) {\n\t\tif ( visible ) {\n\t\t\tthis.bindKeyDownListener();\n\t\t\tthis.bindKeyPressListener();\n\n\t\t\tthis.togglePositioning( !!this.$floatableContainer );\n\t\t\tthis.toggleClipping( true );\n\n\t\t\tthis.$focusOwner.attr( 'aria-expanded', 'true' );\n\n\t\t\tif ( this.getSelectedItem() ) {\n\t\t\t\tthis.$focusOwner.attr( 'aria-activedescendant', this.getSelectedItem().getElementId() );\n\t\t\t\tthis.getSelectedItem().scrollElementIntoView( { duration: 0 } );\n\t\t\t}\n\n\t\t\t// Auto-hide\n\t\t\tif ( this.autoHide ) {\n\t\t\t\tthis.getElementDocument().addEventListener( 'mousedown', this.onDocumentMouseDownHandler, true );\n\t\t\t}\n\n\t\t\tthis.emit( 'ready' );\n\t\t} else {\n\t\t\tthis.$focusOwner.removeAttr( 'aria-activedescendant' );\n\t\t\tthis.unbindKeyDownListener();\n\t\t\tthis.unbindKeyPressListener();\n\t\t\tthis.$focusOwner.attr( 'aria-expanded', 'false' );\n\t\t\tthis.getElementDocument().removeEventListener( 'mousedown', this.onDocumentMouseDownHandler, true );\n\t\t\tthis.togglePositioning( false );\n\t\t\tthis.toggleClipping( false );\n\t\t}\n\t}\n\n\treturn this;\n};\n","/**\n * DropdownWidgets are not menus themselves, rather they contain a menu of options created with\n * OO.ui.MenuOptionWidget. The DropdownWidget takes care of opening and displaying the menu so that\n * users can interact with it.\n *\n * If you want to use this within an HTML form, such as a OO.ui.FormLayout, use\n * OO.ui.DropdownInputWidget instead.\n *\n * @example\n * // Example: A DropdownWidget with a menu that contains three options\n * var dropDown = new OO.ui.DropdownWidget( {\n * label: 'Dropdown menu: Select a menu option',\n * menu: {\n * items: [\n * new OO.ui.MenuOptionWidget( {\n * data: 'a',\n * label: 'First'\n * } ),\n * new OO.ui.MenuOptionWidget( {\n * data: 'b',\n * label: 'Second'\n * } ),\n * new OO.ui.MenuOptionWidget( {\n * data: 'c',\n * label: 'Third'\n * } )\n * ]\n * }\n * } );\n *\n * $( 'body' ).append( dropDown.$element );\n *\n * dropDown.getMenu().selectItemByData( 'b' );\n *\n * dropDown.getMenu().getSelectedItem().getData(); // returns 'b'\n *\n * For more information, please see the [OOjs UI documentation on MediaWiki] [1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.IndicatorElement\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.TitledElement\n * @mixins OO.ui.mixin.TabIndexedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {Object} [menu] Configuration options to pass to {@link OO.ui.MenuSelectWidget menu select widget}\n * @cfg {jQuery} [$overlay] Render the menu into a separate layer. This configuration is useful in cases where\n * the expanded menu is larger than its containing `<div>`. The specified overlay layer is usually on top of the\n * containing `<div>` and has a larger area. By default, the menu uses relative positioning.\n * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.\n */\nOO.ui.DropdownWidget = function OoUiDropdownWidget( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( { indicator: 'down' }, config );\n\n\t// Parent constructor\n\tOO.ui.DropdownWidget.parent.call( this, config );\n\n\t// Properties (must be set before TabIndexedElement constructor call)\n\tthis.$handle = this.$( '<span>' );\n\tthis.$overlay = config.$overlay || this.$element;\n\n\t// Mixin constructors\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.IndicatorElement.call( this, config );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\tOO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$label } ) );\n\tOO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$handle } ) );\n\n\t// Properties\n\tthis.menu = new OO.ui.MenuSelectWidget( $.extend( {\n\t\twidget: this,\n\t\t$floatableContainer: this.$element\n\t}, config.menu ) );\n\n\t// Events\n\tthis.$handle.on( {\n\t\tclick: this.onClick.bind( this ),\n\t\tkeydown: this.onKeyDown.bind( this ),\n\t\t// Hack? Handle type-to-search when menu is not expanded and not handling its own events\n\t\tkeypress: this.menu.onKeyPressHandler,\n\t\tblur: this.menu.clearKeyPressBuffer.bind( this.menu )\n\t} );\n\tthis.menu.connect( this, {\n\t\tselect: 'onMenuSelect',\n\t\ttoggle: 'onMenuToggle'\n\t} );\n\n\t// Initialization\n\tthis.$handle\n\t\t.addClass( 'oo-ui-dropdownWidget-handle' )\n\t\t.attr( {\n\t\t\trole: 'combobox',\n\t\t\t'aria-owns': this.menu.getElementId(),\n\t\t\t'aria-autocomplete': 'list'\n\t\t} )\n\t\t.append( this.$icon, this.$label, this.$indicator );\n\tthis.$element\n\t\t.addClass( 'oo-ui-dropdownWidget' )\n\t\t.append( this.$handle );\n\tthis.$overlay.append( this.menu.$element );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.DropdownWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.DropdownWidget, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.DropdownWidget, OO.ui.mixin.IndicatorElement );\nOO.mixinClass( OO.ui.DropdownWidget, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.DropdownWidget, OO.ui.mixin.TitledElement );\nOO.mixinClass( OO.ui.DropdownWidget, OO.ui.mixin.TabIndexedElement );\n\n/* Methods */\n\n/**\n * Get the menu.\n *\n * @return {OO.ui.MenuSelectWidget} Menu of widget\n */\nOO.ui.DropdownWidget.prototype.getMenu = function () {\n\treturn this.menu;\n};\n\n/**\n * Handles menu select events.\n *\n * @private\n * @param {OO.ui.MenuOptionWidget} item Selected menu item\n */\nOO.ui.DropdownWidget.prototype.onMenuSelect = function ( item ) {\n\tvar selectedLabel;\n\n\tif ( !item ) {\n\t\tthis.setLabel( null );\n\t\treturn;\n\t}\n\n\tselectedLabel = item.getLabel();\n\n\t// If the label is a DOM element, clone it, because setLabel will append() it\n\tif ( selectedLabel instanceof jQuery ) {\n\t\tselectedLabel = selectedLabel.clone();\n\t}\n\n\tthis.setLabel( selectedLabel );\n};\n\n/**\n * Handle menu toggle events.\n *\n * @private\n * @param {boolean} isVisible Menu toggle event\n */\nOO.ui.DropdownWidget.prototype.onMenuToggle = function ( isVisible ) {\n\tthis.$element.toggleClass( 'oo-ui-dropdownWidget-open', isVisible );\n\tthis.$handle.attr(\n\t\t'aria-expanded',\n\t\tthis.$element.hasClass( 'oo-ui-dropdownWidget-open' ).toString()\n\t);\n};\n\n/**\n * Handle mouse click events.\n *\n * @private\n * @param {jQuery.Event} e Mouse click event\n */\nOO.ui.DropdownWidget.prototype.onClick = function ( e ) {\n\tif ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {\n\t\tthis.menu.toggle();\n\t}\n\treturn false;\n};\n\n/**\n * Handle key down events.\n *\n * @private\n * @param {jQuery.Event} e Key down event\n */\nOO.ui.DropdownWidget.prototype.onKeyDown = function ( e ) {\n\tif (\n\t\t!this.isDisabled() &&\n\t\t(\n\t\t\te.which === OO.ui.Keys.ENTER ||\n\t\t\t(\n\t\t\t\t!this.menu.isVisible() &&\n\t\t\t\t(\n\t\t\t\t\te.which === OO.ui.Keys.SPACE ||\n\t\t\t\t\te.which === OO.ui.Keys.UP ||\n\t\t\t\t\te.which === OO.ui.Keys.DOWN\n\t\t\t\t)\n\t\t\t)\n\t\t)\n\t) {\n\t\tthis.menu.toggle();\n\t\treturn false;\n\t}\n};\n","/**\n * RadioOptionWidget is an option widget that looks like a radio button.\n * The class is used with OO.ui.RadioSelectWidget to create a selection of radio options.\n * Please see the [OOjs UI documentation on MediaWiki] [1] for more information.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Button_selects_and_option\n *\n * @class\n * @extends OO.ui.OptionWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.RadioOptionWidget = function OoUiRadioOptionWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties (must be done before parent constructor which calls #setDisabled)\n\tthis.radio = new OO.ui.RadioInputWidget( { value: config.data, tabIndex: -1 } );\n\n\t// Parent constructor\n\tOO.ui.RadioOptionWidget.parent.call( this, config );\n\n\t// Initialization\n\t// Remove implicit role, we're handling it ourselves\n\tthis.radio.$input.attr( 'role', 'presentation' );\n\tthis.$element\n\t\t.addClass( 'oo-ui-radioOptionWidget' )\n\t\t.attr( 'role', 'radio' )\n\t\t.attr( 'aria-checked', 'false' )\n\t\t.removeAttr( 'aria-selected' )\n\t\t.prepend( this.radio.$element );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.RadioOptionWidget, OO.ui.OptionWidget );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.RadioOptionWidget.static.highlightable = false;\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.RadioOptionWidget.static.scrollIntoViewOnSelect = true;\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.RadioOptionWidget.static.pressable = false;\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.RadioOptionWidget.static.tagName = 'label';\n\n/* Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioOptionWidget.prototype.setSelected = function ( state ) {\n\tOO.ui.RadioOptionWidget.parent.prototype.setSelected.call( this, state );\n\n\tthis.radio.setSelected( state );\n\tthis.$element\n\t\t.attr( 'aria-checked', state.toString() )\n\t\t.removeAttr( 'aria-selected' );\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioOptionWidget.prototype.setDisabled = function ( disabled ) {\n\tOO.ui.RadioOptionWidget.parent.prototype.setDisabled.call( this, disabled );\n\n\tthis.radio.setDisabled( this.isDisabled() );\n\n\treturn this;\n};\n","/**\n * RadioSelectWidget is a {@link OO.ui.SelectWidget select widget} that contains radio\n * options and is used together with OO.ui.RadioOptionWidget. The RadioSelectWidget provides\n * an interface for adding, removing and selecting options.\n * Please see the [OOjs UI documentation on MediaWiki][1] for more information.\n *\n * If you want to use this within an HTML form, such as a OO.ui.FormLayout, use\n * OO.ui.RadioSelectInputWidget instead.\n *\n * @example\n * // A RadioSelectWidget with RadioOptions.\n * var option1 = new OO.ui.RadioOptionWidget( {\n * data: 'a',\n * label: 'Selected radio option'\n * } );\n *\n * var option2 = new OO.ui.RadioOptionWidget( {\n * data: 'b',\n * label: 'Unselected radio option'\n * } );\n *\n * var radioSelect=new OO.ui.RadioSelectWidget( {\n * items: [ option1, option2 ]\n * } );\n *\n * // Select 'option 1' using the RadioSelectWidget's selectItem() method.\n * radioSelect.selectItem( option1 );\n *\n * $( 'body' ).append( radioSelect.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options\n\n *\n * @class\n * @extends OO.ui.SelectWidget\n * @mixins OO.ui.mixin.TabIndexedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.RadioSelectWidget = function OoUiRadioSelectWidget( config ) {\n\t// Parent constructor\n\tOO.ui.RadioSelectWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.TabIndexedElement.call( this, config );\n\n\t// Events\n\tthis.$element.on( {\n\t\tfocus: this.bindKeyDownListener.bind( this ),\n\t\tblur: this.unbindKeyDownListener.bind( this )\n\t} );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-radioSelectWidget' )\n\t\t.attr( 'role', 'radiogroup' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.RadioSelectWidget, OO.ui.SelectWidget );\nOO.mixinClass( OO.ui.RadioSelectWidget, OO.ui.mixin.TabIndexedElement );\n","/**\n * MultioptionWidgets are special elements that can be selected and configured with data. The\n * data is often unique for each option, but it does not have to be. MultioptionWidgets are used\n * with OO.ui.SelectWidget to create a selection of mutually exclusive options. For more information\n * and examples, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Multioptions\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.ItemWidget\n * @mixins OO.ui.mixin.LabelElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [selected=false] Whether the option is initially selected\n */\nOO.ui.MultioptionWidget = function OoUiMultioptionWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.MultioptionWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.ItemWidget.call( this );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\n\t// Properties\n\tthis.selected = null;\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-multioptionWidget' )\n\t\t.append( this.$label );\n\tthis.setSelected( config.selected );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.MultioptionWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.MultioptionWidget, OO.ui.mixin.ItemWidget );\nOO.mixinClass( OO.ui.MultioptionWidget, OO.ui.mixin.LabelElement );\n\n/* Events */\n\n/**\n * @event change\n *\n * A change event is emitted when the selected state of the option changes.\n *\n * @param {boolean} selected Whether the option is now selected\n */\n\n/* Methods */\n\n/**\n * Check if the option is selected.\n *\n * @return {boolean} Item is selected\n */\nOO.ui.MultioptionWidget.prototype.isSelected = function () {\n\treturn this.selected;\n};\n\n/**\n * Set the option’s selected state. In general, all modifications to the selection\n * should be handled by the SelectWidget’s {@link OO.ui.SelectWidget#selectItem selectItem( [item] )}\n * method instead of this method.\n *\n * @param {boolean} [state=false] Select option\n * @chainable\n */\nOO.ui.MultioptionWidget.prototype.setSelected = function ( state ) {\n\tstate = !!state;\n\tif ( this.selected !== state ) {\n\t\tthis.selected = state;\n\t\tthis.emit( 'change', state );\n\t\tthis.$element.toggleClass( 'oo-ui-multioptionWidget-selected', state );\n\t}\n\treturn this;\n};\n","/**\n * MultiselectWidget allows selecting multiple options from a list.\n *\n * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options\n *\n * @class\n * @abstract\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.GroupWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {OO.ui.MultioptionWidget[]} [items] An array of options to add to the multiselect.\n */\nOO.ui.MultiselectWidget = function OoUiMultiselectWidget( config ) {\n\t// Parent constructor\n\tOO.ui.MultiselectWidget.parent.call( this, config );\n\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Mixin constructors\n\tOO.ui.mixin.GroupWidget.call( this, config );\n\n\t// Events\n\tthis.aggregate( { change: 'select' } );\n\t// This is mostly for compatibility with CapsuleMultiselectWidget... normally, 'change' is emitted\n\t// by GroupElement only when items are added/removed\n\tthis.connect( this, { select: [ 'emit', 'change' ] } );\n\n\t// Initialization\n\tif ( config.items ) {\n\t\tthis.addItems( config.items );\n\t}\n\tthis.$group.addClass( 'oo-ui-multiselectWidget-group' );\n\tthis.$element.addClass( 'oo-ui-multiselectWidget' )\n\t\t.append( this.$group );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.MultiselectWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.MultiselectWidget, OO.ui.mixin.GroupWidget );\n\n/* Events */\n\n/**\n * @event change\n *\n * A change event is emitted when the set of items changes, or an item is selected or deselected.\n */\n\n/**\n * @event select\n *\n * A select event is emitted when an item is selected or deselected.\n */\n\n/* Methods */\n\n/**\n * Get options that are selected.\n *\n * @return {OO.ui.MultioptionWidget[]} Selected options\n */\nOO.ui.MultiselectWidget.prototype.getSelectedItems = function () {\n\treturn this.items.filter( function ( item ) {\n\t\treturn item.isSelected();\n\t} );\n};\n\n/**\n * Get the data of options that are selected.\n *\n * @return {Object[]|string[]} Values of selected options\n */\nOO.ui.MultiselectWidget.prototype.getSelectedItemsData = function () {\n\treturn this.getSelectedItems().map( function ( item ) {\n\t\treturn item.data;\n\t} );\n};\n\n/**\n * Select options by reference. Options not mentioned in the `items` array will be deselected.\n *\n * @param {OO.ui.MultioptionWidget[]} items Items to select\n * @chainable\n */\nOO.ui.MultiselectWidget.prototype.selectItems = function ( items ) {\n\tthis.items.forEach( function ( item ) {\n\t\tvar selected = items.indexOf( item ) !== -1;\n\t\titem.setSelected( selected );\n\t} );\n\treturn this;\n};\n\n/**\n * Select items by their data. Options not mentioned in the `datas` array will be deselected.\n *\n * @param {Object[]|string[]} datas Values of items to select\n * @chainable\n */\nOO.ui.MultiselectWidget.prototype.selectItemsByData = function ( datas ) {\n\tvar items,\n\t\twidget = this;\n\titems = datas.map( function ( data ) {\n\t\treturn widget.getItemFromData( data );\n\t} );\n\tthis.selectItems( items );\n\treturn this;\n};\n","/**\n * CheckboxMultioptionWidget is an option widget that looks like a checkbox.\n * The class is used with OO.ui.CheckboxMultiselectWidget to create a selection of checkbox options.\n * Please see the [OOjs UI documentation on MediaWiki] [1] for more information.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Button_selects_and_option\n *\n * @class\n * @extends OO.ui.MultioptionWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.CheckboxMultioptionWidget = function OoUiCheckboxMultioptionWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties (must be done before parent constructor which calls #setDisabled)\n\tthis.checkbox = new OO.ui.CheckboxInputWidget();\n\n\t// Parent constructor\n\tOO.ui.CheckboxMultioptionWidget.parent.call( this, config );\n\n\t// Events\n\tthis.checkbox.on( 'change', this.onCheckboxChange.bind( this ) );\n\tthis.$element.on( 'keydown', this.onKeyDown.bind( this ) );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-checkboxMultioptionWidget' )\n\t\t.prepend( this.checkbox.$element );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.CheckboxMultioptionWidget, OO.ui.MultioptionWidget );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.CheckboxMultioptionWidget.static.tagName = 'label';\n\n/* Methods */\n\n/**\n * Handle checkbox selected state change.\n *\n * @private\n */\nOO.ui.CheckboxMultioptionWidget.prototype.onCheckboxChange = function () {\n\tthis.setSelected( this.checkbox.isSelected() );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxMultioptionWidget.prototype.setSelected = function ( state ) {\n\tOO.ui.CheckboxMultioptionWidget.parent.prototype.setSelected.call( this, state );\n\tthis.checkbox.setSelected( state );\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxMultioptionWidget.prototype.setDisabled = function ( disabled ) {\n\tOO.ui.CheckboxMultioptionWidget.parent.prototype.setDisabled.call( this, disabled );\n\tthis.checkbox.setDisabled( this.isDisabled() );\n\treturn this;\n};\n\n/**\n * Focus the widget.\n */\nOO.ui.CheckboxMultioptionWidget.prototype.focus = function () {\n\tthis.checkbox.focus();\n};\n\n/**\n * Handle key down events.\n *\n * @protected\n * @param {jQuery.Event} e\n */\nOO.ui.CheckboxMultioptionWidget.prototype.onKeyDown = function ( e ) {\n\tvar\n\t\telement = this.getElementGroup(),\n\t\tnextItem;\n\n\tif ( e.keyCode === OO.ui.Keys.LEFT || e.keyCode === OO.ui.Keys.UP ) {\n\t\tnextItem = element.getRelativeFocusableItem( this, -1 );\n\t} else if ( e.keyCode === OO.ui.Keys.RIGHT || e.keyCode === OO.ui.Keys.DOWN ) {\n\t\tnextItem = element.getRelativeFocusableItem( this, 1 );\n\t}\n\n\tif ( nextItem ) {\n\t\te.preventDefault();\n\t\tnextItem.focus();\n\t}\n};\n","/**\n * CheckboxMultiselectWidget is a {@link OO.ui.MultiselectWidget multiselect widget} that contains\n * checkboxes and is used together with OO.ui.CheckboxMultioptionWidget. The\n * CheckboxMultiselectWidget provides an interface for adding, removing and selecting options.\n * Please see the [OOjs UI documentation on MediaWiki][1] for more information.\n *\n * If you want to use this within an HTML form, such as a OO.ui.FormLayout, use\n * OO.ui.CheckboxMultiselectInputWidget instead.\n *\n * @example\n * // A CheckboxMultiselectWidget with CheckboxMultioptions.\n * var option1 = new OO.ui.CheckboxMultioptionWidget( {\n * data: 'a',\n * selected: true,\n * label: 'Selected checkbox'\n * } );\n *\n * var option2 = new OO.ui.CheckboxMultioptionWidget( {\n * data: 'b',\n * label: 'Unselected checkbox'\n * } );\n *\n * var multiselect=new OO.ui.CheckboxMultiselectWidget( {\n * items: [ option1, option2 ]\n * } );\n *\n * $( 'body' ).append( multiselect.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options\n *\n * @class\n * @extends OO.ui.MultiselectWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.CheckboxMultiselectWidget = function OoUiCheckboxMultiselectWidget( config ) {\n\t// Parent constructor\n\tOO.ui.CheckboxMultiselectWidget.parent.call( this, config );\n\n\t// Properties\n\tthis.$lastClicked = null;\n\n\t// Events\n\tthis.$group.on( 'click', this.onClick.bind( this ) );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-checkboxMultiselectWidget' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.CheckboxMultiselectWidget, OO.ui.MultiselectWidget );\n\n/* Methods */\n\n/**\n * Get an option by its position relative to the specified item (or to the start of the option array,\n * if item is `null`). The direction in which to search through the option array is specified with a\n * number: -1 for reverse (the default) or 1 for forward. The method will return an option, or\n * `null` if there are no options in the array.\n *\n * @param {OO.ui.CheckboxMultioptionWidget|null} item Item to describe the start position, or `null` to start at the beginning of the array.\n * @param {number} direction Direction to move in: -1 to move backward, 1 to move forward\n * @return {OO.ui.CheckboxMultioptionWidget|null} Item at position, `null` if there are no items in the select\n */\nOO.ui.CheckboxMultiselectWidget.prototype.getRelativeFocusableItem = function ( item, direction ) {\n\tvar currentIndex, nextIndex, i,\n\t\tincrease = direction > 0 ? 1 : -1,\n\t\tlen = this.items.length;\n\n\tif ( item ) {\n\t\tcurrentIndex = this.items.indexOf( item );\n\t\tnextIndex = ( currentIndex + increase + len ) % len;\n\t} else {\n\t\t// If no item is selected and moving forward, start at the beginning.\n\t\t// If moving backward, start at the end.\n\t\tnextIndex = direction > 0 ? 0 : len - 1;\n\t}\n\n\tfor ( i = 0; i < len; i++ ) {\n\t\titem = this.items[ nextIndex ];\n\t\tif ( item && !item.isDisabled() ) {\n\t\t\treturn item;\n\t\t}\n\t\tnextIndex = ( nextIndex + increase + len ) % len;\n\t}\n\treturn null;\n};\n\n/**\n * Handle click events on checkboxes.\n *\n * @param {jQuery.Event} e\n */\nOO.ui.CheckboxMultiselectWidget.prototype.onClick = function ( e ) {\n\tvar $options, lastClickedIndex, nowClickedIndex, i, direction, wasSelected, items,\n\t\t$lastClicked = this.$lastClicked,\n\t\t$nowClicked = $( e.target ).closest( '.oo-ui-checkboxMultioptionWidget' )\n\t\t\t.not( '.oo-ui-widget-disabled' );\n\n\t// Allow selecting multiple options at once by Shift-clicking them\n\tif ( $lastClicked && $nowClicked.length && e.shiftKey ) {\n\t\t$options = this.$group.find( '.oo-ui-checkboxMultioptionWidget' );\n\t\tlastClickedIndex = $options.index( $lastClicked );\n\t\tnowClickedIndex = $options.index( $nowClicked );\n\t\t// If it's the same item, either the user is being silly, or it's a fake event generated by the\n\t\t// browser. In either case we don't need custom handling.\n\t\tif ( nowClickedIndex !== lastClickedIndex ) {\n\t\t\titems = this.items;\n\t\t\twasSelected = items[ nowClickedIndex ].isSelected();\n\t\t\tdirection = nowClickedIndex > lastClickedIndex ? 1 : -1;\n\n\t\t\t// This depends on the DOM order of the items and the order of the .items array being the same.\n\t\t\tfor ( i = lastClickedIndex; i !== nowClickedIndex; i += direction ) {\n\t\t\t\tif ( !items[ i ].isDisabled() ) {\n\t\t\t\t\titems[ i ].setSelected( !wasSelected );\n\t\t\t\t}\n\t\t\t}\n\t\t\t// For the now-clicked element, use immediate timeout to allow the browser to do its own\n\t\t\t// handling first, then set our value. The order in which events happen is different for\n\t\t\t// clicks on the <input> and on the <label> and there are additional fake clicks fired for\n\t\t\t// non-click actions that change the checkboxes.\n\t\t\te.preventDefault();\n\t\t\tsetTimeout( function () {\n\t\t\t\tif ( !items[ nowClickedIndex ].isDisabled() ) {\n\t\t\t\t\titems[ nowClickedIndex ].setSelected( !wasSelected );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t}\n\n\tif ( $nowClicked.length ) {\n\t\tthis.$lastClicked = $nowClicked;\n\t}\n};\n\n/**\n * Focus the widget\n *\n * @chainable\n */\nOO.ui.CheckboxMultiselectWidget.prototype.focus = function () {\n\tvar item;\n\tif ( !this.isDisabled() ) {\n\t\titem = this.getRelativeFocusableItem( null, 1 );\n\t\tif ( item ) {\n\t\t\titem.focus();\n\t\t}\n\t}\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxMultiselectWidget.prototype.simulateLabelClick = function () {\n\tthis.focus();\n};\n","/**\n * Progress bars visually display the status of an operation, such as a download,\n * and can be either determinate or indeterminate:\n *\n * - **determinate** process bars show the percent of an operation that is complete.\n *\n * - **indeterminate** process bars use a visual display of motion to indicate that an operation\n * is taking place. Because the extent of an indeterminate operation is unknown, the bar does\n * not use percentages.\n *\n * The value of the `progress` configuration determines whether the bar is determinate or indeterminate.\n *\n * @example\n * // Examples of determinate and indeterminate progress bars.\n * var progressBar1 = new OO.ui.ProgressBarWidget( {\n * progress: 33\n * } );\n * var progressBar2 = new OO.ui.ProgressBarWidget();\n *\n * // Create a FieldsetLayout to layout progress bars\n * var fieldset = new OO.ui.FieldsetLayout;\n * fieldset.addItems( [\n * new OO.ui.FieldLayout( progressBar1, {label: 'Determinate', align: 'top'}),\n * new OO.ui.FieldLayout( progressBar2, {label: 'Indeterminate', align: 'top'})\n * ] );\n * $( 'body' ).append( fieldset.$element );\n *\n * @class\n * @extends OO.ui.Widget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {number|boolean} [progress=false] The type of progress bar (determinate or indeterminate).\n * To create a determinate progress bar, specify a number that reflects the initial percent complete.\n * By default, the progress bar is indeterminate.\n */\nOO.ui.ProgressBarWidget = function OoUiProgressBarWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.ProgressBarWidget.parent.call( this, config );\n\n\t// Properties\n\tthis.$bar = $( '<div>' );\n\tthis.progress = null;\n\n\t// Initialization\n\tthis.setProgress( config.progress !== undefined ? config.progress : false );\n\tthis.$bar.addClass( 'oo-ui-progressBarWidget-bar' );\n\tthis.$element\n\t\t.attr( {\n\t\t\trole: 'progressbar',\n\t\t\t'aria-valuemin': 0,\n\t\t\t'aria-valuemax': 100\n\t\t} )\n\t\t.addClass( 'oo-ui-progressBarWidget' )\n\t\t.append( this.$bar );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ProgressBarWidget, OO.ui.Widget );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.ProgressBarWidget.static.tagName = 'div';\n\n/* Methods */\n\n/**\n * Get the percent of the progress that has been completed. Indeterminate progresses will return `false`.\n *\n * @return {number|boolean} Progress percent\n */\nOO.ui.ProgressBarWidget.prototype.getProgress = function () {\n\treturn this.progress;\n};\n\n/**\n * Set the percent of the process completed or `false` for an indeterminate process.\n *\n * @param {number|boolean} progress Progress percent or `false` for indeterminate\n */\nOO.ui.ProgressBarWidget.prototype.setProgress = function ( progress ) {\n\tthis.progress = progress;\n\n\tif ( progress !== false ) {\n\t\tthis.$bar.css( 'width', this.progress + '%' );\n\t\tthis.$element.attr( 'aria-valuenow', this.progress );\n\t} else {\n\t\tthis.$bar.css( 'width', '' );\n\t\tthis.$element.removeAttr( 'aria-valuenow' );\n\t}\n\tthis.$element.toggleClass( 'oo-ui-progressBarWidget-indeterminate', progress === false );\n};\n","/**\n * InputWidget is the base class for all input widgets, which\n * include {@link OO.ui.TextInputWidget text inputs}, {@link OO.ui.CheckboxInputWidget checkbox inputs},\n * {@link OO.ui.RadioInputWidget radio inputs}, and {@link OO.ui.ButtonInputWidget button inputs}.\n * See the [OOjs UI documentation on MediaWiki] [1] for more information and examples.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs\n *\n * @abstract\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.FlaggedElement\n * @mixins OO.ui.mixin.TabIndexedElement\n * @mixins OO.ui.mixin.TitledElement\n * @mixins OO.ui.mixin.AccessKeyedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string} [name=''] The value of the input’s HTML `name` attribute.\n * @cfg {string} [value=''] The value of the input.\n * @cfg {string} [dir] The directionality of the input (ltr/rtl).\n * @cfg {string} [inputId] The value of the input’s HTML `id` attribute.\n * @cfg {Function} [inputFilter] The name of an input filter function. Input filters modify the value of an input\n * before it is accepted.\n */\nOO.ui.InputWidget = function OoUiInputWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.InputWidget.parent.call( this, config );\n\n\t// Properties\n\t// See #reusePreInfuseDOM about config.$input\n\tthis.$input = config.$input || this.getInputElement( config );\n\tthis.value = '';\n\tthis.inputFilter = config.inputFilter;\n\n\t// Mixin constructors\n\tOO.ui.mixin.FlaggedElement.call( this, config );\n\tOO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$input } ) );\n\tOO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$input } ) );\n\tOO.ui.mixin.AccessKeyedElement.call( this, $.extend( {}, config, { $accessKeyed: this.$input } ) );\n\n\t// Events\n\tthis.$input.on( 'keydown mouseup cut paste change input select', this.onEdit.bind( this ) );\n\n\t// Initialization\n\tthis.$input\n\t\t.addClass( 'oo-ui-inputWidget-input' )\n\t\t.attr( 'name', config.name )\n\t\t.prop( 'disabled', this.isDisabled() );\n\tthis.$element\n\t\t.addClass( 'oo-ui-inputWidget' )\n\t\t.append( this.$input );\n\tthis.setValue( config.value );\n\tif ( config.dir ) {\n\t\tthis.setDir( config.dir );\n\t}\n\tif ( config.inputId !== undefined ) {\n\t\tthis.setInputId( config.inputId );\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.InputWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.FlaggedElement );\nOO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.TabIndexedElement );\nOO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.TitledElement );\nOO.mixinClass( OO.ui.InputWidget, OO.ui.mixin.AccessKeyedElement );\n\n/* Static Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.InputWidget.static.reusePreInfuseDOM = function ( node, config ) {\n\tconfig = OO.ui.InputWidget.parent.static.reusePreInfuseDOM( node, config );\n\t// Reusing `$input` lets browsers preserve inputted values across page reloads, see T114134.\n\tconfig.$input = $( node ).find( '.oo-ui-inputWidget-input' );\n\treturn config;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.InputWidget.static.gatherPreInfuseState = function ( node, config ) {\n\tvar state = OO.ui.InputWidget.parent.static.gatherPreInfuseState( node, config );\n\tif ( config.$input && config.$input.length ) {\n\t\tstate.value = config.$input.val();\n\t\t// Might be better in TabIndexedElement, but it's awkward to do there because mixins are awkward\n\t\tstate.focus = config.$input.is( ':focus' );\n\t}\n\treturn state;\n};\n\n/* Events */\n\n/**\n * @event change\n *\n * A change event is emitted when the value of the input changes.\n *\n * @param {string} value\n */\n\n/* Methods */\n\n/**\n * Get input element.\n *\n * Subclasses of OO.ui.InputWidget use the `config` parameter to produce different elements in\n * different circumstances. The element must have a `value` property (like form elements).\n *\n * @protected\n * @param {Object} config Configuration options\n * @return {jQuery} Input element\n */\nOO.ui.InputWidget.prototype.getInputElement = function () {\n\treturn $( '<input>' );\n};\n\n/**\n * Handle potentially value-changing events.\n *\n * @private\n * @param {jQuery.Event} e Key down, mouse up, cut, paste, change, input, or select event\n */\nOO.ui.InputWidget.prototype.onEdit = function () {\n\tvar widget = this;\n\tif ( !this.isDisabled() ) {\n\t\t// Allow the stack to clear so the value will be updated\n\t\tsetTimeout( function () {\n\t\t\twidget.setValue( widget.$input.val() );\n\t\t} );\n\t}\n};\n\n/**\n * Get the value of the input.\n *\n * @return {string} Input value\n */\nOO.ui.InputWidget.prototype.getValue = function () {\n\t// Resynchronize our internal data with DOM data. Other scripts executing on the page can modify\n\t// it, and we won't know unless they're kind enough to trigger a 'change' event.\n\tvar value = this.$input.val();\n\tif ( this.value !== value ) {\n\t\tthis.setValue( value );\n\t}\n\treturn this.value;\n};\n\n/**\n * Set the directionality of the input.\n *\n * @param {string} dir Text directionality: 'ltr', 'rtl' or 'auto'\n * @chainable\n */\nOO.ui.InputWidget.prototype.setDir = function ( dir ) {\n\tthis.$input.prop( 'dir', dir );\n\treturn this;\n};\n\n/**\n * Set the value of the input.\n *\n * @param {string} value New value\n * @fires change\n * @chainable\n */\nOO.ui.InputWidget.prototype.setValue = function ( value ) {\n\tvalue = this.cleanUpValue( value );\n\t// Update the DOM if it has changed. Note that with cleanUpValue, it\n\t// is possible for the DOM value to change without this.value changing.\n\tif ( this.$input.val() !== value ) {\n\t\tthis.$input.val( value );\n\t}\n\tif ( this.value !== value ) {\n\t\tthis.value = value;\n\t\tthis.emit( 'change', this.value );\n\t}\n\treturn this;\n};\n\n/**\n * Clean up incoming value.\n *\n * Ensures value is a string, and converts undefined and null to empty string.\n *\n * @private\n * @param {string} value Original value\n * @return {string} Cleaned up value\n */\nOO.ui.InputWidget.prototype.cleanUpValue = function ( value ) {\n\tif ( value === undefined || value === null ) {\n\t\treturn '';\n\t} else if ( this.inputFilter ) {\n\t\treturn this.inputFilter( String( value ) );\n\t} else {\n\t\treturn String( value );\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.InputWidget.prototype.setDisabled = function ( state ) {\n\tOO.ui.InputWidget.parent.prototype.setDisabled.call( this, state );\n\tif ( this.$input ) {\n\t\tthis.$input.prop( 'disabled', this.isDisabled() );\n\t}\n\treturn this;\n};\n\n/**\n * Set the 'id' attribute of the `<input>` element.\n *\n * @param {string} id\n * @chainable\n */\nOO.ui.InputWidget.prototype.setInputId = function ( id ) {\n\tthis.$input.attr( 'id', id );\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.InputWidget.prototype.restorePreInfuseState = function ( state ) {\n\tOO.ui.InputWidget.parent.prototype.restorePreInfuseState.call( this, state );\n\tif ( state.value !== undefined && state.value !== this.getValue() ) {\n\t\tthis.setValue( state.value );\n\t}\n\tif ( state.focus ) {\n\t\tthis.focus();\n\t}\n};\n","/**\n * Data widget intended for creating 'hidden'-type inputs.\n *\n * @class\n * @extends OO.ui.Widget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string} [value=''] The value of the input.\n * @cfg {string} [name=''] The value of the input’s HTML `name` attribute.\n */\nOO.ui.HiddenInputWidget = function OoUiHiddenInputWidget( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( { value: '', name: '' }, config );\n\n\t// Parent constructor\n\tOO.ui.HiddenInputWidget.parent.call( this, config );\n\n\t// Initialization\n\tthis.$element.attr( {\n\t\ttype: 'hidden',\n\t\tvalue: config.value,\n\t\tname: config.name\n\t} );\n\tthis.$element.removeAttr( 'aria-disabled' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.HiddenInputWidget, OO.ui.Widget );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.HiddenInputWidget.static.tagName = 'input';\n","/**\n * ButtonInputWidget is used to submit HTML forms and is intended to be used within\n * a OO.ui.FormLayout. If you do not need the button to work with HTML forms, you probably\n * want to use OO.ui.ButtonWidget instead. Button input widgets can be rendered as either an\n * HTML `<button>` (the default) or an HTML `<input>` tags. See the\n * [OOjs UI documentation on MediaWiki] [1] for more information.\n *\n * @example\n * // A ButtonInputWidget rendered as an HTML button, the default.\n * var button = new OO.ui.ButtonInputWidget( {\n * label: 'Input button',\n * icon: 'check',\n * value: 'check'\n * } );\n * $( 'body' ).append( button.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs#Button_inputs\n *\n * @class\n * @extends OO.ui.InputWidget\n * @mixins OO.ui.mixin.ButtonElement\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.IndicatorElement\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.TitledElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string} [type='button'] The value of the HTML `'type'` attribute: 'button', 'submit' or 'reset'.\n * @cfg {boolean} [useInputTag=false] Use an `<input>` tag instead of a `<button>` tag, the default.\n * Widgets configured to be an `<input>` do not support {@link #icon icons} and {@link #indicator indicators},\n * non-plaintext {@link #label labels}, or {@link #value values}. In general, useInputTag should only\n * be set to `true` when there’s need to support IE 6 in a form with multiple buttons.\n */\nOO.ui.ButtonInputWidget = function OoUiButtonInputWidget( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( { type: 'button', useInputTag: false }, config );\n\n\t// See InputWidget#reusePreInfuseDOM about config.$input\n\tif ( config.$input ) {\n\t\tconfig.$input.empty();\n\t}\n\n\t// Properties (must be set before parent constructor, which calls #setValue)\n\tthis.useInputTag = config.useInputTag;\n\n\t// Parent constructor\n\tOO.ui.ButtonInputWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.ButtonElement.call( this, $.extend( {}, config, { $button: this.$input } ) );\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.IndicatorElement.call( this, config );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\tOO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$input } ) );\n\n\t// Initialization\n\tif ( !config.useInputTag ) {\n\t\tthis.$input.append( this.$icon, this.$label, this.$indicator );\n\t}\n\tthis.$element.addClass( 'oo-ui-buttonInputWidget' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ButtonInputWidget, OO.ui.InputWidget );\nOO.mixinClass( OO.ui.ButtonInputWidget, OO.ui.mixin.ButtonElement );\nOO.mixinClass( OO.ui.ButtonInputWidget, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.ButtonInputWidget, OO.ui.mixin.IndicatorElement );\nOO.mixinClass( OO.ui.ButtonInputWidget, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.ButtonInputWidget, OO.ui.mixin.TitledElement );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.ButtonInputWidget.static.tagName = 'span';\n\n/* Methods */\n\n/**\n * @inheritdoc\n * @protected\n */\nOO.ui.ButtonInputWidget.prototype.getInputElement = function ( config ) {\n\tvar type;\n\ttype = [ 'button', 'submit', 'reset' ].indexOf( config.type ) !== -1 ? config.type : 'button';\n\treturn $( '<' + ( config.useInputTag ? 'input' : 'button' ) + ' type=\"' + type + '\">' );\n};\n\n/**\n * Set label value.\n *\n * If #useInputTag is `true`, the label is set as the `value` of the `<input>` tag.\n *\n * @param {jQuery|string|Function|null} label Label nodes, text, a function that returns nodes or\n * text, or `null` for no label\n * @chainable\n */\nOO.ui.ButtonInputWidget.prototype.setLabel = function ( label ) {\n\tif ( typeof label === 'function' ) {\n\t\tlabel = OO.ui.resolveMsg( label );\n\t}\n\n\tif ( this.useInputTag ) {\n\t\t// Discard non-plaintext labels\n\t\tif ( typeof label !== 'string' ) {\n\t\t\tlabel = '';\n\t\t}\n\n\t\tthis.$input.val( label );\n\t}\n\n\treturn OO.ui.mixin.LabelElement.prototype.setLabel.call( this, label );\n};\n\n/**\n * Set the value of the input.\n *\n * This method is disabled for button inputs configured as {@link #useInputTag <input> tags}, as\n * they do not support {@link #value values}.\n *\n * @param {string} value New value\n * @chainable\n */\nOO.ui.ButtonInputWidget.prototype.setValue = function ( value ) {\n\tif ( !this.useInputTag ) {\n\t\tOO.ui.ButtonInputWidget.parent.prototype.setValue.call( this, value );\n\t}\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ButtonInputWidget.prototype.getInputId = function () {\n\t// Disable generating `<label>` elements for buttons. One would very rarely need additional label\n\t// for a button, and it's already a big clickable target, and it causes unexpected rendering.\n\treturn null;\n};\n","/**\n * CheckboxInputWidgets, like HTML checkboxes, can be selected and/or configured with a value.\n * Note that these {@link OO.ui.InputWidget input widgets} are best laid out\n * in {@link OO.ui.FieldLayout field layouts} that use the {@link OO.ui.FieldLayout#align inline}\n * alignment. For more information, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * This widget can be used inside an HTML form, such as a OO.ui.FormLayout.\n *\n * @example\n * // An example of selected, unselected, and disabled checkbox inputs\n * var checkbox1=new OO.ui.CheckboxInputWidget( {\n * value: 'a',\n * selected: true\n * } );\n * var checkbox2=new OO.ui.CheckboxInputWidget( {\n * value: 'b'\n * } );\n * var checkbox3=new OO.ui.CheckboxInputWidget( {\n * value:'c',\n * disabled: true\n * } );\n * // Create a fieldset layout with fields for each checkbox.\n * var fieldset = new OO.ui.FieldsetLayout( {\n * label: 'Checkboxes'\n * } );\n * fieldset.addItems( [\n * new OO.ui.FieldLayout( checkbox1, { label: 'Selected checkbox', align: 'inline' } ),\n * new OO.ui.FieldLayout( checkbox2, { label: 'Unselected checkbox', align: 'inline' } ),\n * new OO.ui.FieldLayout( checkbox3, { label: 'Disabled checkbox', align: 'inline' } ),\n * ] );\n * $( 'body' ).append( fieldset.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs\n *\n * @class\n * @extends OO.ui.InputWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [selected=false] Select the checkbox initially. By default, the checkbox is not selected.\n */\nOO.ui.CheckboxInputWidget = function OoUiCheckboxInputWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.CheckboxInputWidget.parent.call( this, config );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-checkboxInputWidget' )\n\t\t// Required for pretty styling in WikimediaUI theme\n\t\t.append( $( '<span>' ) );\n\tthis.setSelected( config.selected !== undefined ? config.selected : false );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.CheckboxInputWidget, OO.ui.InputWidget );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.CheckboxInputWidget.static.tagName = 'span';\n\n/* Static Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxInputWidget.static.gatherPreInfuseState = function ( node, config ) {\n\tvar state = OO.ui.CheckboxInputWidget.parent.static.gatherPreInfuseState( node, config );\n\tstate.checked = config.$input.prop( 'checked' );\n\treturn state;\n};\n\n/* Methods */\n\n/**\n * @inheritdoc\n * @protected\n */\nOO.ui.CheckboxInputWidget.prototype.getInputElement = function () {\n\treturn $( '<input>' ).attr( 'type', 'checkbox' );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxInputWidget.prototype.onEdit = function () {\n\tvar widget = this;\n\tif ( !this.isDisabled() ) {\n\t\t// Allow the stack to clear so the value will be updated\n\t\tsetTimeout( function () {\n\t\t\twidget.setSelected( widget.$input.prop( 'checked' ) );\n\t\t} );\n\t}\n};\n\n/**\n * Set selection state of this checkbox.\n *\n * @param {boolean} state `true` for selected\n * @chainable\n */\nOO.ui.CheckboxInputWidget.prototype.setSelected = function ( state ) {\n\tstate = !!state;\n\tif ( this.selected !== state ) {\n\t\tthis.selected = state;\n\t\tthis.$input.prop( 'checked', this.selected );\n\t\tthis.emit( 'change', this.selected );\n\t}\n\treturn this;\n};\n\n/**\n * Check if this checkbox is selected.\n *\n * @return {boolean} Checkbox is selected\n */\nOO.ui.CheckboxInputWidget.prototype.isSelected = function () {\n\t// Resynchronize our internal data with DOM data. Other scripts executing on the page can modify\n\t// it, and we won't know unless they're kind enough to trigger a 'change' event.\n\tvar selected = this.$input.prop( 'checked' );\n\tif ( this.selected !== selected ) {\n\t\tthis.setSelected( selected );\n\t}\n\treturn this.selected;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxInputWidget.prototype.simulateLabelClick = function () {\n\tif ( !this.isDisabled() ) {\n\t\tthis.$input.click();\n\t}\n\tthis.focus();\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxInputWidget.prototype.restorePreInfuseState = function ( state ) {\n\tOO.ui.CheckboxInputWidget.parent.prototype.restorePreInfuseState.call( this, state );\n\tif ( state.checked !== undefined && state.checked !== this.isSelected() ) {\n\t\tthis.setSelected( state.checked );\n\t}\n};\n","/**\n * DropdownInputWidget is a {@link OO.ui.DropdownWidget DropdownWidget} intended to be used\n * within an HTML form, such as a OO.ui.FormLayout. The selected value is synchronized with the value\n * of a hidden HTML `input` tag. Please see the [OOjs UI documentation on MediaWiki][1] for\n * more information about input widgets.\n *\n * A DropdownInputWidget always has a value (one of the options is always selected), unless there\n * are no options. If no `value` configuration option is provided, the first option is selected.\n * If you need a state representing no value (no option being selected), use a DropdownWidget.\n *\n * This and OO.ui.RadioSelectInputWidget support the same configuration options.\n *\n * @example\n * // Example: A DropdownInputWidget with three options\n * var dropdownInput = new OO.ui.DropdownInputWidget( {\n * options: [\n * { data: 'a', label: 'First' },\n * { data: 'b', label: 'Second'},\n * { data: 'c', label: 'Third' }\n * ]\n * } );\n * $( 'body' ).append( dropdownInput.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs\n *\n * @class\n * @extends OO.ui.InputWidget\n * @mixins OO.ui.mixin.TitledElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`\n * @cfg {Object} [dropdown] Configuration options for {@link OO.ui.DropdownWidget DropdownWidget}\n */\nOO.ui.DropdownInputWidget = function OoUiDropdownInputWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// See InputWidget#reusePreInfuseDOM about config.$input\n\tif ( config.$input ) {\n\t\tconfig.$input.addClass( 'oo-ui-element-hidden' );\n\t}\n\n\t// Properties (must be done before parent constructor which calls #setDisabled)\n\tthis.dropdownWidget = new OO.ui.DropdownWidget( config.dropdown );\n\n\t// Parent constructor\n\tOO.ui.DropdownInputWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.TitledElement.call( this, config );\n\n\t// Events\n\tthis.dropdownWidget.getMenu().connect( this, { select: 'onMenuSelect' } );\n\n\t// Initialization\n\tthis.setOptions( config.options || [] );\n\t// Set the value again, after we did setOptions(). The call from parent doesn't work because the\n\t// widget has no valid options when it happens.\n\tthis.setValue( config.value );\n\tthis.$element\n\t\t.addClass( 'oo-ui-dropdownInputWidget' )\n\t\t.append( this.dropdownWidget.$element );\n\tthis.setTabIndexedElement( null );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.DropdownInputWidget, OO.ui.InputWidget );\nOO.mixinClass( OO.ui.DropdownInputWidget, OO.ui.mixin.TitledElement );\n\n/* Methods */\n\n/**\n * @inheritdoc\n * @protected\n */\nOO.ui.DropdownInputWidget.prototype.getInputElement = function () {\n\treturn $( '<input>' ).attr( 'type', 'hidden' );\n};\n\n/**\n * Handles menu select events.\n *\n * @private\n * @param {OO.ui.MenuOptionWidget|null} item Selected menu item\n */\nOO.ui.DropdownInputWidget.prototype.onMenuSelect = function ( item ) {\n\tthis.setValue( item ? item.getData() : '' );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.DropdownInputWidget.prototype.setValue = function ( value ) {\n\tvar selected;\n\tvalue = this.cleanUpValue( value );\n\t// Only allow setting values that are actually present in the dropdown\n\tselected = this.dropdownWidget.getMenu().getItemFromData( value ) ||\n\t\tthis.dropdownWidget.getMenu().getFirstSelectableItem();\n\tthis.dropdownWidget.getMenu().selectItem( selected );\n\tvalue = selected ? selected.getData() : '';\n\tOO.ui.DropdownInputWidget.parent.prototype.setValue.call( this, value );\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.DropdownInputWidget.prototype.setDisabled = function ( state ) {\n\tthis.dropdownWidget.setDisabled( state );\n\tOO.ui.DropdownInputWidget.parent.prototype.setDisabled.call( this, state );\n\treturn this;\n};\n\n/**\n * Set the options available for this input.\n *\n * @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`\n * @chainable\n */\nOO.ui.DropdownInputWidget.prototype.setOptions = function ( options ) {\n\tvar\n\t\tvalue = this.getValue(),\n\t\twidget = this;\n\n\t// Rebuild the dropdown menu\n\tthis.dropdownWidget.getMenu()\n\t\t.clearItems()\n\t\t.addItems( options.map( function ( opt ) {\n\t\t\tvar optValue = widget.cleanUpValue( opt.data );\n\n\t\t\tif ( opt.optgroup === undefined ) {\n\t\t\t\treturn new OO.ui.MenuOptionWidget( {\n\t\t\t\t\tdata: optValue,\n\t\t\t\t\tlabel: opt.label !== undefined ? opt.label : optValue\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\treturn new OO.ui.MenuSectionOptionWidget( {\n\t\t\t\t\tlabel: opt.optgroup\n\t\t\t\t} );\n\t\t\t}\n\t\t} ) );\n\n\t// Restore the previous value, or reset to something sensible\n\tif ( this.dropdownWidget.getMenu().getItemFromData( value ) ) {\n\t\t// Previous value is still available, ensure consistency with the dropdown\n\t\tthis.setValue( value );\n\t} else {\n\t\t// No longer valid, reset\n\t\tif ( options.length ) {\n\t\t\tthis.setValue( options[ 0 ].data );\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.DropdownInputWidget.prototype.focus = function () {\n\tthis.dropdownWidget.focus();\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.DropdownInputWidget.prototype.blur = function () {\n\tthis.dropdownWidget.blur();\n\treturn this;\n};\n","/**\n * RadioInputWidget creates a single radio button. Because radio buttons are usually used as a set,\n * in most cases you will want to use a {@link OO.ui.RadioSelectWidget radio select}\n * with {@link OO.ui.RadioOptionWidget radio options} instead of this class. For more information,\n * please see the [OOjs UI documentation on MediaWiki][1].\n *\n * This widget can be used inside an HTML form, such as a OO.ui.FormLayout.\n *\n * @example\n * // An example of selected, unselected, and disabled radio inputs\n * var radio1 = new OO.ui.RadioInputWidget( {\n * value: 'a',\n * selected: true\n * } );\n * var radio2 = new OO.ui.RadioInputWidget( {\n * value: 'b'\n * } );\n * var radio3 = new OO.ui.RadioInputWidget( {\n * value: 'c',\n * disabled: true\n * } );\n * // Create a fieldset layout with fields for each radio button.\n * var fieldset = new OO.ui.FieldsetLayout( {\n * label: 'Radio inputs'\n * } );\n * fieldset.addItems( [\n * new OO.ui.FieldLayout( radio1, { label: 'Selected', align: 'inline' } ),\n * new OO.ui.FieldLayout( radio2, { label: 'Unselected', align: 'inline' } ),\n * new OO.ui.FieldLayout( radio3, { label: 'Disabled', align: 'inline' } ),\n * ] );\n * $( 'body' ).append( fieldset.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs\n *\n * @class\n * @extends OO.ui.InputWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [selected=false] Select the radio button initially. By default, the radio button is not selected.\n */\nOO.ui.RadioInputWidget = function OoUiRadioInputWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.RadioInputWidget.parent.call( this, config );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-radioInputWidget' )\n\t\t// Required for pretty styling in WikimediaUI theme\n\t\t.append( $( '<span>' ) );\n\tthis.setSelected( config.selected !== undefined ? config.selected : false );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.RadioInputWidget, OO.ui.InputWidget );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.RadioInputWidget.static.tagName = 'span';\n\n/* Static Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioInputWidget.static.gatherPreInfuseState = function ( node, config ) {\n\tvar state = OO.ui.RadioInputWidget.parent.static.gatherPreInfuseState( node, config );\n\tstate.checked = config.$input.prop( 'checked' );\n\treturn state;\n};\n\n/* Methods */\n\n/**\n * @inheritdoc\n * @protected\n */\nOO.ui.RadioInputWidget.prototype.getInputElement = function () {\n\treturn $( '<input>' ).attr( 'type', 'radio' );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioInputWidget.prototype.onEdit = function () {\n\t// RadioInputWidget doesn't track its state.\n};\n\n/**\n * Set selection state of this radio button.\n *\n * @param {boolean} state `true` for selected\n * @chainable\n */\nOO.ui.RadioInputWidget.prototype.setSelected = function ( state ) {\n\t// RadioInputWidget doesn't track its state.\n\tthis.$input.prop( 'checked', state );\n\treturn this;\n};\n\n/**\n * Check if this radio button is selected.\n *\n * @return {boolean} Radio is selected\n */\nOO.ui.RadioInputWidget.prototype.isSelected = function () {\n\treturn this.$input.prop( 'checked' );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioInputWidget.prototype.simulateLabelClick = function () {\n\tif ( !this.isDisabled() ) {\n\t\tthis.$input.click();\n\t}\n\tthis.focus();\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioInputWidget.prototype.restorePreInfuseState = function ( state ) {\n\tOO.ui.RadioInputWidget.parent.prototype.restorePreInfuseState.call( this, state );\n\tif ( state.checked !== undefined && state.checked !== this.isSelected() ) {\n\t\tthis.setSelected( state.checked );\n\t}\n};\n","/**\n * RadioSelectInputWidget is a {@link OO.ui.RadioSelectWidget RadioSelectWidget} intended to be used\n * within an HTML form, such as a OO.ui.FormLayout. The selected value is synchronized with the value\n * of a hidden HTML `input` tag. Please see the [OOjs UI documentation on MediaWiki][1] for\n * more information about input widgets.\n *\n * This and OO.ui.DropdownInputWidget support the same configuration options.\n *\n * @example\n * // Example: A RadioSelectInputWidget with three options\n * var radioSelectInput = new OO.ui.RadioSelectInputWidget( {\n * options: [\n * { data: 'a', label: 'First' },\n * { data: 'b', label: 'Second'},\n * { data: 'c', label: 'Third' }\n * ]\n * } );\n * $( 'body' ).append( radioSelectInput.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs\n *\n * @class\n * @extends OO.ui.InputWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`\n */\nOO.ui.RadioSelectInputWidget = function OoUiRadioSelectInputWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties (must be done before parent constructor which calls #setDisabled)\n\tthis.radioSelectWidget = new OO.ui.RadioSelectWidget();\n\n\t// Parent constructor\n\tOO.ui.RadioSelectInputWidget.parent.call( this, config );\n\n\t// Events\n\tthis.radioSelectWidget.connect( this, { select: 'onMenuSelect' } );\n\n\t// Initialization\n\tthis.setOptions( config.options || [] );\n\tthis.$element\n\t\t.addClass( 'oo-ui-radioSelectInputWidget' )\n\t\t.append( this.radioSelectWidget.$element );\n\tthis.setTabIndexedElement( null );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.RadioSelectInputWidget, OO.ui.InputWidget );\n\n/* Static Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioSelectInputWidget.static.gatherPreInfuseState = function ( node, config ) {\n\tvar state = OO.ui.RadioSelectInputWidget.parent.static.gatherPreInfuseState( node, config );\n\tstate.value = $( node ).find( '.oo-ui-radioInputWidget .oo-ui-inputWidget-input:checked' ).val();\n\treturn state;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioSelectInputWidget.static.reusePreInfuseDOM = function ( node, config ) {\n\tconfig = OO.ui.RadioSelectInputWidget.parent.static.reusePreInfuseDOM( node, config );\n\t// Cannot reuse the `<input type=radio>` set\n\tdelete config.$input;\n\treturn config;\n};\n\n/* Methods */\n\n/**\n * @inheritdoc\n * @protected\n */\nOO.ui.RadioSelectInputWidget.prototype.getInputElement = function () {\n\treturn $( '<input>' ).attr( 'type', 'hidden' );\n};\n\n/**\n * Handles menu select events.\n *\n * @private\n * @param {OO.ui.RadioOptionWidget} item Selected menu item\n */\nOO.ui.RadioSelectInputWidget.prototype.onMenuSelect = function ( item ) {\n\tthis.setValue( item.getData() );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioSelectInputWidget.prototype.setValue = function ( value ) {\n\tvalue = this.cleanUpValue( value );\n\tthis.radioSelectWidget.selectItemByData( value );\n\tOO.ui.RadioSelectInputWidget.parent.prototype.setValue.call( this, value );\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioSelectInputWidget.prototype.setDisabled = function ( state ) {\n\tthis.radioSelectWidget.setDisabled( state );\n\tOO.ui.RadioSelectInputWidget.parent.prototype.setDisabled.call( this, state );\n\treturn this;\n};\n\n/**\n * Set the options available for this input.\n *\n * @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`\n * @chainable\n */\nOO.ui.RadioSelectInputWidget.prototype.setOptions = function ( options ) {\n\tvar\n\t\tvalue = this.getValue(),\n\t\twidget = this;\n\n\t// Rebuild the radioSelect menu\n\tthis.radioSelectWidget\n\t\t.clearItems()\n\t\t.addItems( options.map( function ( opt ) {\n\t\t\tvar optValue = widget.cleanUpValue( opt.data );\n\t\t\treturn new OO.ui.RadioOptionWidget( {\n\t\t\t\tdata: optValue,\n\t\t\t\tlabel: opt.label !== undefined ? opt.label : optValue\n\t\t\t} );\n\t\t} ) );\n\n\t// Restore the previous value, or reset to something sensible\n\tif ( this.radioSelectWidget.getItemFromData( value ) ) {\n\t\t// Previous value is still available, ensure consistency with the radioSelect\n\t\tthis.setValue( value );\n\t} else {\n\t\t// No longer valid, reset\n\t\tif ( options.length ) {\n\t\t\tthis.setValue( options[ 0 ].data );\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioSelectInputWidget.prototype.focus = function () {\n\tthis.radioSelectWidget.focus();\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.RadioSelectInputWidget.prototype.blur = function () {\n\tthis.radioSelectWidget.blur();\n\treturn this;\n};\n","/**\n * CheckboxMultiselectInputWidget is a\n * {@link OO.ui.CheckboxMultiselectWidget CheckboxMultiselectWidget} intended to be used within a\n * HTML form, such as a OO.ui.FormLayout. The selected values are synchronized with the value of\n * HTML `<input type=checkbox>` tags. Please see the [OOjs UI documentation on MediaWiki][1] for\n * more information about input widgets.\n *\n * @example\n * // Example: A CheckboxMultiselectInputWidget with three options\n * var multiselectInput = new OO.ui.CheckboxMultiselectInputWidget( {\n * options: [\n * { data: 'a', label: 'First' },\n * { data: 'b', label: 'Second'},\n * { data: 'c', label: 'Third' }\n * ]\n * } );\n * $( 'body' ).append( multiselectInput.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs\n *\n * @class\n * @extends OO.ui.InputWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: …, disabled: … }`\n */\nOO.ui.CheckboxMultiselectInputWidget = function OoUiCheckboxMultiselectInputWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties (must be done before parent constructor which calls #setDisabled)\n\tthis.checkboxMultiselectWidget = new OO.ui.CheckboxMultiselectWidget();\n\n\t// Parent constructor\n\tOO.ui.CheckboxMultiselectInputWidget.parent.call( this, config );\n\n\t// Properties\n\tthis.inputName = config.name;\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-checkboxMultiselectInputWidget' )\n\t\t.append( this.checkboxMultiselectWidget.$element );\n\t// We don't use this.$input, but rather the CheckboxInputWidgets inside each option\n\tthis.$input.detach();\n\tthis.setOptions( config.options || [] );\n\t// Have to repeat this from parent, as we need options to be set up for this to make sense\n\tthis.setValue( config.value );\n\n\t// setValue when checkboxMultiselectWidget changes\n\tthis.checkboxMultiselectWidget.on( 'change', function () {\n\t\tthis.setValue( this.checkboxMultiselectWidget.getSelectedItemsData() );\n\t}.bind( this ) );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.CheckboxMultiselectInputWidget, OO.ui.InputWidget );\n\n/* Static Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxMultiselectInputWidget.static.gatherPreInfuseState = function ( node, config ) {\n\tvar state = OO.ui.CheckboxMultiselectInputWidget.parent.static.gatherPreInfuseState( node, config );\n\tstate.value = $( node ).find( '.oo-ui-checkboxInputWidget .oo-ui-inputWidget-input:checked' )\n\t\t.toArray().map( function ( el ) { return el.value; } );\n\treturn state;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxMultiselectInputWidget.static.reusePreInfuseDOM = function ( node, config ) {\n\tconfig = OO.ui.CheckboxMultiselectInputWidget.parent.static.reusePreInfuseDOM( node, config );\n\t// Cannot reuse the `<input type=checkbox>` set\n\tdelete config.$input;\n\treturn config;\n};\n\n/* Methods */\n\n/**\n * @inheritdoc\n * @protected\n */\nOO.ui.CheckboxMultiselectInputWidget.prototype.getInputElement = function () {\n\t// Actually unused\n\treturn $( '<unused>' );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxMultiselectInputWidget.prototype.getValue = function () {\n\tvar value = this.$element.find( '.oo-ui-checkboxInputWidget .oo-ui-inputWidget-input:checked' )\n\t\t.toArray().map( function ( el ) { return el.value; } );\n\tif ( this.value !== value ) {\n\t\tthis.setValue( value );\n\t}\n\treturn this.value;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxMultiselectInputWidget.prototype.setValue = function ( value ) {\n\tvalue = this.cleanUpValue( value );\n\tthis.checkboxMultiselectWidget.selectItemsByData( value );\n\tOO.ui.CheckboxMultiselectInputWidget.parent.prototype.setValue.call( this, value );\n\treturn this;\n};\n\n/**\n * Clean up incoming value.\n *\n * @param {string[]} value Original value\n * @return {string[]} Cleaned up value\n */\nOO.ui.CheckboxMultiselectInputWidget.prototype.cleanUpValue = function ( value ) {\n\tvar i, singleValue,\n\t\tcleanValue = [];\n\tif ( !Array.isArray( value ) ) {\n\t\treturn cleanValue;\n\t}\n\tfor ( i = 0; i < value.length; i++ ) {\n\t\tsingleValue =\n\t\t\tOO.ui.CheckboxMultiselectInputWidget.parent.prototype.cleanUpValue.call( this, value[ i ] );\n\t\t// Remove options that we don't have here\n\t\tif ( !this.checkboxMultiselectWidget.getItemFromData( singleValue ) ) {\n\t\t\tcontinue;\n\t\t}\n\t\tcleanValue.push( singleValue );\n\t}\n\treturn cleanValue;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxMultiselectInputWidget.prototype.setDisabled = function ( state ) {\n\tthis.checkboxMultiselectWidget.setDisabled( state );\n\tOO.ui.CheckboxMultiselectInputWidget.parent.prototype.setDisabled.call( this, state );\n\treturn this;\n};\n\n/**\n * Set the options available for this input.\n *\n * @param {Object[]} options Array of menu options in the format `{ data: …, label: …, disabled: … }`\n * @chainable\n */\nOO.ui.CheckboxMultiselectInputWidget.prototype.setOptions = function ( options ) {\n\tvar widget = this;\n\n\t// Rebuild the checkboxMultiselectWidget menu\n\tthis.checkboxMultiselectWidget\n\t\t.clearItems()\n\t\t.addItems( options.map( function ( opt ) {\n\t\t\tvar optValue, item, optDisabled;\n\t\t\toptValue =\n\t\t\t\tOO.ui.CheckboxMultiselectInputWidget.parent.prototype.cleanUpValue.call( widget, opt.data );\n\t\t\toptDisabled = opt.disabled !== undefined ? opt.disabled : false;\n\t\t\titem = new OO.ui.CheckboxMultioptionWidget( {\n\t\t\t\tdata: optValue,\n\t\t\t\tlabel: opt.label !== undefined ? opt.label : optValue,\n\t\t\t\tdisabled: optDisabled\n\t\t\t} );\n\t\t\t// Set the 'name' and 'value' for form submission\n\t\t\titem.checkbox.$input.attr( 'name', widget.inputName );\n\t\t\titem.checkbox.setValue( optValue );\n\t\t\treturn item;\n\t\t} ) );\n\n\t// Re-set the value, checking the checkboxes as needed.\n\t// This will also get rid of any stale options that we just removed.\n\tthis.setValue( this.getValue() );\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CheckboxMultiselectInputWidget.prototype.focus = function () {\n\tthis.checkboxMultiselectWidget.focus();\n\treturn this;\n};\n","/**\n * TextInputWidgets, like HTML text inputs, can be configured with options that customize the\n * size of the field as well as its presentation. In addition, these widgets can be configured\n * with {@link OO.ui.mixin.IconElement icons}, {@link OO.ui.mixin.IndicatorElement indicators}, an optional\n * validation-pattern (used to determine if an input value is valid or not) and an input filter,\n * which modifies incoming values rather than validating them.\n * Please see the [OOjs UI documentation on MediaWiki] [1] for more information and examples.\n *\n * This widget can be used inside an HTML form, such as a OO.ui.FormLayout.\n *\n * @example\n * // Example of a text input widget\n * var textInput = new OO.ui.TextInputWidget( {\n * value: 'Text input'\n * } )\n * $( 'body' ).append( textInput.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs\n *\n * @class\n * @extends OO.ui.InputWidget\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.IndicatorElement\n * @mixins OO.ui.mixin.PendingElement\n * @mixins OO.ui.mixin.LabelElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string} [type='text'] The value of the HTML `type` attribute: 'text', 'password'\n * 'email', 'url' or 'number'.\n * @cfg {string} [placeholder] Placeholder text\n * @cfg {boolean} [autofocus=false] Use an HTML `autofocus` attribute to\n * instruct the browser to focus this widget.\n * @cfg {boolean} [readOnly=false] Prevent changes to the value of the text input.\n * @cfg {number} [maxLength] Maximum number of characters allowed in the input.\n * @cfg {string} [labelPosition='after'] The position of the inline label relative to that of\n * the value or placeholder text: `'before'` or `'after'`\n * @cfg {boolean} [required=false] Mark the field as required. Implies `indicator: 'required'`.\n * @cfg {boolean} [autocomplete=true] Should the browser support autocomplete for this field\n * @cfg {RegExp|Function|string} [validate] Validation pattern: when string, a symbolic name of a\n * pattern defined by the class: 'non-empty' (the value cannot be an empty string) or 'integer'\n * (the value must contain only numbers); when RegExp, a regular expression that must match the\n * value for it to be considered valid; when Function, a function receiving the value as parameter\n * that must return true, or promise resolving to true, for it to be considered valid.\n */\nOO.ui.TextInputWidget = function OoUiTextInputWidget( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( {\n\t\ttype: 'text',\n\t\tlabelPosition: 'after'\n\t}, config );\n\n\tif ( config.multiline ) {\n\t\tOO.ui.warnDeprecation( 'TextInputWidget: config.multiline is deprecated. Use the MultilineTextInputWidget instead. See T130434.' );\n\t\treturn new OO.ui.MultilineTextInputWidget( config );\n\t}\n\n\t// Parent constructor\n\tOO.ui.TextInputWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.IndicatorElement.call( this, config );\n\tOO.ui.mixin.PendingElement.call( this, $.extend( {}, config, { $pending: this.$input } ) );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\n\t// Properties\n\tthis.type = this.getSaneType( config );\n\tthis.readOnly = false;\n\tthis.required = false;\n\tthis.validate = null;\n\tthis.styleHeight = null;\n\tthis.scrollWidth = null;\n\n\tthis.setValidation( config.validate );\n\tthis.setLabelPosition( config.labelPosition );\n\n\t// Events\n\tthis.$input.on( {\n\t\tkeypress: this.onKeyPress.bind( this ),\n\t\tblur: this.onBlur.bind( this ),\n\t\tfocus: this.onFocus.bind( this )\n\t} );\n\tthis.$icon.on( 'mousedown', this.onIconMouseDown.bind( this ) );\n\tthis.$indicator.on( 'mousedown', this.onIndicatorMouseDown.bind( this ) );\n\tthis.on( 'labelChange', this.updatePosition.bind( this ) );\n\tthis.on( 'change', OO.ui.debounce( this.onDebouncedChange.bind( this ), 250 ) );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-textInputWidget oo-ui-textInputWidget-type-' + this.type )\n\t\t.append( this.$icon, this.$indicator );\n\tthis.setReadOnly( !!config.readOnly );\n\tthis.setRequired( !!config.required );\n\tif ( config.placeholder !== undefined ) {\n\t\tthis.$input.attr( 'placeholder', config.placeholder );\n\t}\n\tif ( config.maxLength !== undefined ) {\n\t\tthis.$input.attr( 'maxlength', config.maxLength );\n\t}\n\tif ( config.autofocus ) {\n\t\tthis.$input.attr( 'autofocus', 'autofocus' );\n\t}\n\tif ( config.autocomplete === false ) {\n\t\tthis.$input.attr( 'autocomplete', 'off' );\n\t\t// Turning off autocompletion also disables \"form caching\" when the user navigates to a\n\t\t// different page and then clicks \"Back\". Re-enable it when leaving. Borrowed from jQuery UI.\n\t\t$( window ).on( {\n\t\t\tbeforeunload: function () {\n\t\t\t\tthis.$input.removeAttr( 'autocomplete' );\n\t\t\t}.bind( this ),\n\t\t\tpageshow: function () {\n\t\t\t\t// Browsers don't seem to actually fire this event on \"Back\", they instead just reload the\n\t\t\t\t// whole page... it shouldn't hurt, though.\n\t\t\t\tthis.$input.attr( 'autocomplete', 'off' );\n\t\t\t}.bind( this )\n\t\t} );\n\t}\n\tif ( this.label ) {\n\t\tthis.isWaitingToBeAttached = true;\n\t\tthis.installParentChangeDetector();\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.TextInputWidget, OO.ui.InputWidget );\nOO.mixinClass( OO.ui.TextInputWidget, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.TextInputWidget, OO.ui.mixin.IndicatorElement );\nOO.mixinClass( OO.ui.TextInputWidget, OO.ui.mixin.PendingElement );\nOO.mixinClass( OO.ui.TextInputWidget, OO.ui.mixin.LabelElement );\n\n/* Static Properties */\n\nOO.ui.TextInputWidget.static.validationPatterns = {\n\t'non-empty': /.+/,\n\tinteger: /^\\d+$/\n};\n\n/* Static Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.TextInputWidget.static.gatherPreInfuseState = function ( node, config ) {\n\tvar state = OO.ui.TextInputWidget.parent.static.gatherPreInfuseState( node, config );\n\treturn state;\n};\n\n/* Events */\n\n/**\n * An `enter` event is emitted when the user presses 'enter' inside the text box.\n *\n * @event enter\n */\n\n/* Methods */\n\n/**\n * Handle icon mouse down events.\n *\n * @private\n * @param {jQuery.Event} e Mouse down event\n */\nOO.ui.TextInputWidget.prototype.onIconMouseDown = function ( e ) {\n\tif ( e.which === OO.ui.MouseButtons.LEFT ) {\n\t\tthis.focus();\n\t\treturn false;\n\t}\n};\n\n/**\n * Handle indicator mouse down events.\n *\n * @private\n * @param {jQuery.Event} e Mouse down event\n */\nOO.ui.TextInputWidget.prototype.onIndicatorMouseDown = function ( e ) {\n\tif ( e.which === OO.ui.MouseButtons.LEFT ) {\n\t\tthis.focus();\n\t\treturn false;\n\t}\n};\n\n/**\n * Handle key press events.\n *\n * @private\n * @param {jQuery.Event} e Key press event\n * @fires enter If enter key is pressed\n */\nOO.ui.TextInputWidget.prototype.onKeyPress = function ( e ) {\n\tif ( e.which === OO.ui.Keys.ENTER ) {\n\t\tthis.emit( 'enter', e );\n\t}\n};\n\n/**\n * Handle blur events.\n *\n * @private\n * @param {jQuery.Event} e Blur event\n */\nOO.ui.TextInputWidget.prototype.onBlur = function () {\n\tthis.setValidityFlag();\n};\n\n/**\n * Handle focus events.\n *\n * @private\n * @param {jQuery.Event} e Focus event\n */\nOO.ui.TextInputWidget.prototype.onFocus = function () {\n\tif ( this.isWaitingToBeAttached ) {\n\t\t// If we've received focus, then we must be attached to the document, and if\n\t\t// isWaitingToBeAttached is still true, that means the handler never fired. Fire it now.\n\t\tthis.onElementAttach();\n\t}\n\tthis.setValidityFlag( true );\n};\n\n/**\n * Handle element attach events.\n *\n * @private\n * @param {jQuery.Event} e Element attach event\n */\nOO.ui.TextInputWidget.prototype.onElementAttach = function () {\n\tthis.isWaitingToBeAttached = false;\n\t// Any previously calculated size is now probably invalid if we reattached elsewhere\n\tthis.valCache = null;\n\tthis.positionLabel();\n};\n\n/**\n * Handle debounced change events.\n *\n * @param {string} value\n * @private\n */\nOO.ui.TextInputWidget.prototype.onDebouncedChange = function () {\n\tthis.setValidityFlag();\n};\n\n/**\n * Check if the input is {@link #readOnly read-only}.\n *\n * @return {boolean}\n */\nOO.ui.TextInputWidget.prototype.isReadOnly = function () {\n\treturn this.readOnly;\n};\n\n/**\n * Set the {@link #readOnly read-only} state of the input.\n *\n * @param {boolean} state Make input read-only\n * @chainable\n */\nOO.ui.TextInputWidget.prototype.setReadOnly = function ( state ) {\n\tthis.readOnly = !!state;\n\tthis.$input.prop( 'readOnly', this.readOnly );\n\treturn this;\n};\n\n/**\n * Check if the input is {@link #required required}.\n *\n * @return {boolean}\n */\nOO.ui.TextInputWidget.prototype.isRequired = function () {\n\treturn this.required;\n};\n\n/**\n * Set the {@link #required required} state of the input.\n *\n * @param {boolean} state Make input required\n * @chainable\n */\nOO.ui.TextInputWidget.prototype.setRequired = function ( state ) {\n\tthis.required = !!state;\n\tif ( this.required ) {\n\t\tthis.$input\n\t\t\t.prop( 'required', true )\n\t\t\t.attr( 'aria-required', 'true' );\n\t\tif ( this.getIndicator() === null ) {\n\t\t\tthis.setIndicator( 'required' );\n\t\t}\n\t} else {\n\t\tthis.$input\n\t\t\t.prop( 'required', false )\n\t\t\t.removeAttr( 'aria-required' );\n\t\tif ( this.getIndicator() === 'required' ) {\n\t\t\tthis.setIndicator( null );\n\t\t}\n\t}\n\treturn this;\n};\n\n/**\n * Support function for making #onElementAttach work across browsers.\n *\n * This whole function could be replaced with one line of code using the DOMNodeInsertedIntoDocument\n * event, but it's not supported by Firefox and allegedly deprecated, so we only use it as fallback.\n *\n * Due to MutationObserver performance woes, #onElementAttach is only somewhat reliably called the\n * first time that the element gets attached to the documented.\n */\nOO.ui.TextInputWidget.prototype.installParentChangeDetector = function () {\n\tvar mutationObserver, onRemove, topmostNode, fakeParentNode,\n\t\tMutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver,\n\t\twidget = this;\n\n\tif ( MutationObserver ) {\n\t\t// The new way. If only it wasn't so ugly.\n\n\t\tif ( this.isElementAttached() ) {\n\t\t\t// Widget is attached already, do nothing. This breaks the functionality of this function when\n\t\t\t// the widget is detached and reattached. Alas, doing this correctly with MutationObserver\n\t\t\t// would require observation of the whole document, which would hurt performance of other,\n\t\t\t// more important code.\n\t\t\treturn;\n\t\t}\n\n\t\t// Find topmost node in the tree\n\t\ttopmostNode = this.$element[ 0 ];\n\t\twhile ( topmostNode.parentNode ) {\n\t\t\ttopmostNode = topmostNode.parentNode;\n\t\t}\n\n\t\t// We have no way to detect the $element being attached somewhere without observing the entire\n\t\t// DOM with subtree modifications, which would hurt performance. So we cheat: we hook to the\n\t\t// parent node of $element, and instead detect when $element is removed from it (and thus\n\t\t// probably attached somewhere else). If there is no parent, we create a \"fake\" one. If it\n\t\t// doesn't get attached, we end up back here and create the parent.\n\n\t\tmutationObserver = new MutationObserver( function ( mutations ) {\n\t\t\tvar i, j, removedNodes;\n\t\t\tfor ( i = 0; i < mutations.length; i++ ) {\n\t\t\t\tremovedNodes = mutations[ i ].removedNodes;\n\t\t\t\tfor ( j = 0; j < removedNodes.length; j++ ) {\n\t\t\t\t\tif ( removedNodes[ j ] === topmostNode ) {\n\t\t\t\t\t\tsetTimeout( onRemove, 0 );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\tonRemove = function () {\n\t\t\t// If the node was attached somewhere else, report it\n\t\t\tif ( widget.isElementAttached() ) {\n\t\t\t\twidget.onElementAttach();\n\t\t\t}\n\t\t\tmutationObserver.disconnect();\n\t\t\twidget.installParentChangeDetector();\n\t\t};\n\n\t\t// Create a fake parent and observe it\n\t\tfakeParentNode = $( '<div>' ).append( topmostNode )[ 0 ];\n\t\tmutationObserver.observe( fakeParentNode, { childList: true } );\n\t} else {\n\t\t// Using the DOMNodeInsertedIntoDocument event is much nicer and less magical, and works for\n\t\t// detachment and reattachment, but it's not supported by Firefox and allegedly deprecated.\n\t\tthis.$element.on( 'DOMNodeInsertedIntoDocument', this.onElementAttach.bind( this ) );\n\t}\n};\n\n/**\n * @inheritdoc\n * @protected\n */\nOO.ui.TextInputWidget.prototype.getInputElement = function ( config ) {\n\tif ( this.getSaneType( config ) === 'number' ) {\n\t\treturn $( '<input>' )\n\t\t\t.attr( 'step', 'any' )\n\t\t\t.attr( 'type', 'number' );\n\t} else {\n\t\treturn $( '<input>' ).attr( 'type', this.getSaneType( config ) );\n\t}\n};\n\n/**\n * Get sanitized value for 'type' for given config.\n *\n * @param {Object} config Configuration options\n * @return {string|null}\n * @private\n */\nOO.ui.TextInputWidget.prototype.getSaneType = function ( config ) {\n\tvar allowedTypes = [\n\t\t'text',\n\t\t'password',\n\t\t'email',\n\t\t'url',\n\t\t'number'\n\t];\n\treturn allowedTypes.indexOf( config.type ) !== -1 ? config.type : 'text';\n};\n\n/**\n * Focus the input and select a specified range within the text.\n *\n * @param {number} from Select from offset\n * @param {number} [to] Select to offset, defaults to from\n * @chainable\n */\nOO.ui.TextInputWidget.prototype.selectRange = function ( from, to ) {\n\tvar isBackwards, start, end,\n\t\tinput = this.$input[ 0 ];\n\n\tto = to || from;\n\n\tisBackwards = to < from;\n\tstart = isBackwards ? to : from;\n\tend = isBackwards ? from : to;\n\n\tthis.focus();\n\n\ttry {\n\t\tinput.setSelectionRange( start, end, isBackwards ? 'backward' : 'forward' );\n\t} catch ( e ) {\n\t\t// IE throws an exception if you call setSelectionRange on a unattached DOM node.\n\t\t// Rather than expensively check if the input is attached every time, just check\n\t\t// if it was the cause of an error being thrown. If not, rethrow the error.\n\t\tif ( this.getElementDocument().body.contains( input ) ) {\n\t\t\tthrow e;\n\t\t}\n\t}\n\treturn this;\n};\n\n/**\n * Get an object describing the current selection range in a directional manner\n *\n * @return {Object} Object containing 'from' and 'to' offsets\n */\nOO.ui.TextInputWidget.prototype.getRange = function () {\n\tvar input = this.$input[ 0 ],\n\t\tstart = input.selectionStart,\n\t\tend = input.selectionEnd,\n\t\tisBackwards = input.selectionDirection === 'backward';\n\n\treturn {\n\t\tfrom: isBackwards ? end : start,\n\t\tto: isBackwards ? start : end\n\t};\n};\n\n/**\n * Get the length of the text input value.\n *\n * This could differ from the length of #getValue if the\n * value gets filtered\n *\n * @return {number} Input length\n */\nOO.ui.TextInputWidget.prototype.getInputLength = function () {\n\treturn this.$input[ 0 ].value.length;\n};\n\n/**\n * Focus the input and select the entire text.\n *\n * @chainable\n */\nOO.ui.TextInputWidget.prototype.select = function () {\n\treturn this.selectRange( 0, this.getInputLength() );\n};\n\n/**\n * Focus the input and move the cursor to the start.\n *\n * @chainable\n */\nOO.ui.TextInputWidget.prototype.moveCursorToStart = function () {\n\treturn this.selectRange( 0 );\n};\n\n/**\n * Focus the input and move the cursor to the end.\n *\n * @chainable\n */\nOO.ui.TextInputWidget.prototype.moveCursorToEnd = function () {\n\treturn this.selectRange( this.getInputLength() );\n};\n\n/**\n * Insert new content into the input.\n *\n * @param {string} content Content to be inserted\n * @chainable\n */\nOO.ui.TextInputWidget.prototype.insertContent = function ( content ) {\n\tvar start, end,\n\t\trange = this.getRange(),\n\t\tvalue = this.getValue();\n\n\tstart = Math.min( range.from, range.to );\n\tend = Math.max( range.from, range.to );\n\n\tthis.setValue( value.slice( 0, start ) + content + value.slice( end ) );\n\tthis.selectRange( start + content.length );\n\treturn this;\n};\n\n/**\n * Insert new content either side of a selection.\n *\n * @param {string} pre Content to be inserted before the selection\n * @param {string} post Content to be inserted after the selection\n * @chainable\n */\nOO.ui.TextInputWidget.prototype.encapsulateContent = function ( pre, post ) {\n\tvar start, end,\n\t\trange = this.getRange(),\n\t\toffset = pre.length;\n\n\tstart = Math.min( range.from, range.to );\n\tend = Math.max( range.from, range.to );\n\n\tthis.selectRange( start ).insertContent( pre );\n\tthis.selectRange( offset + end ).insertContent( post );\n\n\tthis.selectRange( offset + start, offset + end );\n\treturn this;\n};\n\n/**\n * Set the validation pattern.\n *\n * The validation pattern is either a regular expression, a function, or the symbolic name of a\n * pattern defined by the class: 'non-empty' (the value cannot be an empty string) or 'integer' (the\n * value must contain only numbers).\n *\n * @param {RegExp|Function|string|null} validate Regular expression, function, or the symbolic name\n * of a pattern (either ‘integer’ or ‘non-empty’) defined by the class.\n */\nOO.ui.TextInputWidget.prototype.setValidation = function ( validate ) {\n\tif ( validate instanceof RegExp || validate instanceof Function ) {\n\t\tthis.validate = validate;\n\t} else {\n\t\tthis.validate = this.constructor.static.validationPatterns[ validate ] || /.*/;\n\t}\n};\n\n/**\n * Sets the 'invalid' flag appropriately.\n *\n * @param {boolean} [isValid] Optionally override validation result\n */\nOO.ui.TextInputWidget.prototype.setValidityFlag = function ( isValid ) {\n\tvar widget = this,\n\t\tsetFlag = function ( valid ) {\n\t\t\tif ( !valid ) {\n\t\t\t\twidget.$input.attr( 'aria-invalid', 'true' );\n\t\t\t} else {\n\t\t\t\twidget.$input.removeAttr( 'aria-invalid' );\n\t\t\t}\n\t\t\twidget.setFlags( { invalid: !valid } );\n\t\t};\n\n\tif ( isValid !== undefined ) {\n\t\tsetFlag( isValid );\n\t} else {\n\t\tthis.getValidity().then( function () {\n\t\t\tsetFlag( true );\n\t\t}, function () {\n\t\t\tsetFlag( false );\n\t\t} );\n\t}\n};\n\n/**\n * Get the validity of current value.\n *\n * This method returns a promise that resolves if the value is valid and rejects if\n * it isn't. Uses the {@link #validate validation pattern} to check for validity.\n *\n * @return {jQuery.Promise} A promise that resolves if the value is valid, rejects if not.\n */\nOO.ui.TextInputWidget.prototype.getValidity = function () {\n\tvar result;\n\n\tfunction rejectOrResolve( valid ) {\n\t\tif ( valid ) {\n\t\t\treturn $.Deferred().resolve().promise();\n\t\t} else {\n\t\t\treturn $.Deferred().reject().promise();\n\t\t}\n\t}\n\n\t// Check browser validity and reject if it is invalid\n\tif (\n\t\tthis.$input[ 0 ].checkValidity !== undefined &&\n\t\tthis.$input[ 0 ].checkValidity() === false\n\t) {\n\t\treturn rejectOrResolve( false );\n\t}\n\n\t// Run our checks if the browser thinks the field is valid\n\tif ( this.validate instanceof Function ) {\n\t\tresult = this.validate( this.getValue() );\n\t\tif ( result && $.isFunction( result.promise ) ) {\n\t\t\treturn result.promise().then( function ( valid ) {\n\t\t\t\treturn rejectOrResolve( valid );\n\t\t\t} );\n\t\t} else {\n\t\t\treturn rejectOrResolve( result );\n\t\t}\n\t} else {\n\t\treturn rejectOrResolve( this.getValue().match( this.validate ) );\n\t}\n};\n\n/**\n * Set the position of the inline label relative to that of the value: `‘before’` or `‘after’`.\n *\n * @param {string} labelPosition Label position, 'before' or 'after'\n * @chainable\n */\nOO.ui.TextInputWidget.prototype.setLabelPosition = function ( labelPosition ) {\n\tthis.labelPosition = labelPosition;\n\tif ( this.label ) {\n\t\t// If there is no label and we only change the position, #updatePosition is a no-op,\n\t\t// but it takes really a lot of work to do nothing.\n\t\tthis.updatePosition();\n\t}\n\treturn this;\n};\n\n/**\n * Update the position of the inline label.\n *\n * This method is called by #setLabelPosition, and can also be called on its own if\n * something causes the label to be mispositioned.\n *\n * @chainable\n */\nOO.ui.TextInputWidget.prototype.updatePosition = function () {\n\tvar after = this.labelPosition === 'after';\n\n\tthis.$element\n\t\t.toggleClass( 'oo-ui-textInputWidget-labelPosition-after', !!this.label && after )\n\t\t.toggleClass( 'oo-ui-textInputWidget-labelPosition-before', !!this.label && !after );\n\n\tthis.valCache = null;\n\tthis.scrollWidth = null;\n\tthis.positionLabel();\n\n\treturn this;\n};\n\n/**\n * Position the label by setting the correct padding on the input.\n *\n * @private\n * @chainable\n */\nOO.ui.TextInputWidget.prototype.positionLabel = function () {\n\tvar after, rtl, property, newCss;\n\n\tif ( this.isWaitingToBeAttached ) {\n\t\t// #onElementAttach will be called soon, which calls this method\n\t\treturn this;\n\t}\n\n\tnewCss = {\n\t\t'padding-right': '',\n\t\t'padding-left': ''\n\t};\n\n\tif ( this.label ) {\n\t\tthis.$element.append( this.$label );\n\t} else {\n\t\tthis.$label.detach();\n\t\t// Clear old values if present\n\t\tthis.$input.css( newCss );\n\t\treturn;\n\t}\n\n\tafter = this.labelPosition === 'after';\n\trtl = this.$element.css( 'direction' ) === 'rtl';\n\tproperty = after === rtl ? 'padding-left' : 'padding-right';\n\n\tnewCss[ property ] = this.$label.outerWidth( true ) + ( after ? this.scrollWidth : 0 );\n\t// We have to clear the padding on the other side, in case the element direction changed\n\tthis.$input.css( newCss );\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.TextInputWidget.prototype.restorePreInfuseState = function ( state ) {\n\tOO.ui.TextInputWidget.parent.prototype.restorePreInfuseState.call( this, state );\n\tif ( state.scrollTop !== undefined ) {\n\t\tthis.$input.scrollTop( state.scrollTop );\n\t}\n};\n","/**\n * @class\n * @extends OO.ui.TextInputWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.SearchInputWidget = function OoUiSearchInputWidget( config ) {\n\tconfig = $.extend( {\n\t\ticon: 'search'\n\t}, config );\n\n\t// Set type to text so that TextInputWidget doesn't\n\t// get stuck in an infinite loop.\n\tconfig.type = 'text';\n\n\t// Parent constructor\n\tOO.ui.SearchInputWidget.parent.call( this, config );\n\n\t// Events\n\tthis.connect( this, {\n\t\tchange: 'onChange'\n\t} );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-textInputWidget-type-search' );\n\tthis.updateSearchIndicator();\n\tthis.connect( this, {\n\t\tdisable: 'onDisable'\n\t} );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.SearchInputWidget, OO.ui.TextInputWidget );\n\n/* Methods */\n\n/**\n * @inheritdoc\n * @protected\n */\nOO.ui.SearchInputWidget.prototype.getInputElement = function () {\n\treturn $( '<input>' ).attr( 'type', 'search' );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.SearchInputWidget.prototype.onIndicatorMouseDown = function ( e ) {\n\tif ( e.which === OO.ui.MouseButtons.LEFT ) {\n\t\t// Clear the text field\n\t\tthis.setValue( '' );\n\t\tthis.focus();\n\t\treturn false;\n\t}\n};\n\n/**\n * Update the 'clear' indicator displayed on type: 'search' text\n * fields, hiding it when the field is already empty or when it's not\n * editable.\n */\nOO.ui.SearchInputWidget.prototype.updateSearchIndicator = function () {\n\tif ( this.getValue() === '' || this.isDisabled() || this.isReadOnly() ) {\n\t\tthis.setIndicator( null );\n\t} else {\n\t\tthis.setIndicator( 'clear' );\n\t}\n};\n\n/**\n * Handle change events.\n *\n * @private\n */\nOO.ui.SearchInputWidget.prototype.onChange = function () {\n\tthis.updateSearchIndicator();\n};\n\n/**\n * Handle disable events.\n *\n * @param {boolean} disabled Element is disabled\n * @private\n */\nOO.ui.SearchInputWidget.prototype.onDisable = function () {\n\tthis.updateSearchIndicator();\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.SearchInputWidget.prototype.setReadOnly = function ( state ) {\n\tOO.ui.SearchInputWidget.parent.prototype.setReadOnly.call( this, state );\n\tthis.updateSearchIndicator();\n\treturn this;\n};\n","/**\n * @class\n * @extends OO.ui.TextInputWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {number} [rows] Number of visible lines in textarea. If used with `autosize`,\n * specifies minimum number of rows to display.\n * @cfg {string} [labelPosition='after'] The position of the inline label relative to that of\n * @cfg {boolean} [autosize=false] Automatically resize the text input to fit its content.\n * Use the #maxRows config to specify a maximum number of displayed rows.\n * @cfg {boolean} [maxRows] Maximum number of rows to display when #autosize is set to true.\n * Defaults to the maximum of `10` and `2 * rows`, or `10` if `rows` isn't provided.\n */\nOO.ui.MultilineTextInputWidget = function OoUiMultilineTextInputWidget( config ) {\n\tconfig = $.extend( {\n\t\ttype: 'text'\n\t}, config );\n\tconfig.multiline = false;\n\t// Parent constructor\n\tOO.ui.MultilineTextInputWidget.parent.call( this, config );\n\n\t// Properties\n\tthis.multiline = true;\n\tthis.autosize = !!config.autosize;\n\tthis.minRows = config.rows !== undefined ? config.rows : '';\n\tthis.maxRows = config.maxRows || Math.max( 2 * ( this.minRows || 0 ), 10 );\n\n\t// Clone for resizing\n\tif ( this.autosize ) {\n\t\tthis.$clone = this.$input\n\t\t\t.clone()\n\t\t\t.insertAfter( this.$input )\n\t\t\t.attr( 'aria-hidden', 'true' )\n\t\t\t.addClass( 'oo-ui-element-hidden' );\n\t}\n\n\t// Events\n\tthis.connect( this, {\n\t\tchange: 'onChange'\n\t} );\n\n\t// Initialization\n\tif ( this.multiline && config.rows ) {\n\t\tthis.$input.attr( 'rows', config.rows );\n\t}\n\tif ( this.autosize ) {\n\t\tthis.isWaitingToBeAttached = true;\n\t\tthis.installParentChangeDetector();\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.MultilineTextInputWidget, OO.ui.TextInputWidget );\n\n/* Static Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.MultilineTextInputWidget.static.gatherPreInfuseState = function ( node, config ) {\n\tvar state = OO.ui.MultilineTextInputWidget.parent.static.gatherPreInfuseState( node, config );\n\tstate.scrollTop = config.$input.scrollTop();\n\treturn state;\n};\n\n/* Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.MultilineTextInputWidget.prototype.onElementAttach = function () {\n\tOO.ui.MultilineTextInputWidget.parent.prototype.onElementAttach.call( this );\n\tthis.adjustSize();\n};\n\n/**\n * Handle change events.\n *\n * @private\n */\nOO.ui.MultilineTextInputWidget.prototype.onChange = function () {\n\tthis.adjustSize();\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MultilineTextInputWidget.prototype.updatePosition = function () {\n\tOO.ui.MultilineTextInputWidget.parent.prototype.updatePosition.call( this );\n\tthis.adjustSize();\n};\n\n/**\n * Override TextInputWidget so it doesn't emit the 'enter' event.\n *\n * @private\n * @param {jQuery.Event} e Key press event\n */\nOO.ui.MultilineTextInputWidget.prototype.onKeyPress = function () {\n\treturn;\n};\n\n/**\n * Automatically adjust the size of the text input.\n *\n * This only affects multiline inputs that are {@link #autosize autosized}.\n *\n * @chainable\n * @fires resize\n */\nOO.ui.MultilineTextInputWidget.prototype.adjustSize = function () {\n\tvar scrollHeight, innerHeight, outerHeight, maxInnerHeight, measurementError,\n\t\tidealHeight, newHeight, scrollWidth, property;\n\n\tif ( this.$input.val() !== this.valCache ) {\n\t\tif ( this.autosize ) {\n\t\t\tthis.$clone\n\t\t\t\t.val( this.$input.val() )\n\t\t\t\t.attr( 'rows', this.minRows )\n\t\t\t\t// Set inline height property to 0 to measure scroll height\n\t\t\t\t.css( 'height', 0 );\n\n\t\t\tthis.$clone.removeClass( 'oo-ui-element-hidden' );\n\n\t\t\tthis.valCache = this.$input.val();\n\n\t\t\tscrollHeight = this.$clone[ 0 ].scrollHeight;\n\n\t\t\t// Remove inline height property to measure natural heights\n\t\t\tthis.$clone.css( 'height', '' );\n\t\t\tinnerHeight = this.$clone.innerHeight();\n\t\t\touterHeight = this.$clone.outerHeight();\n\n\t\t\t// Measure max rows height\n\t\t\tthis.$clone\n\t\t\t\t.attr( 'rows', this.maxRows )\n\t\t\t\t.css( 'height', 'auto' )\n\t\t\t\t.val( '' );\n\t\t\tmaxInnerHeight = this.$clone.innerHeight();\n\n\t\t\t// Difference between reported innerHeight and scrollHeight with no scrollbars present.\n\t\t\t// This is sometimes non-zero on Blink-based browsers, depending on zoom level.\n\t\t\tmeasurementError = maxInnerHeight - this.$clone[ 0 ].scrollHeight;\n\t\t\tidealHeight = Math.min( maxInnerHeight, scrollHeight + measurementError );\n\n\t\t\tthis.$clone.addClass( 'oo-ui-element-hidden' );\n\n\t\t\t// Only apply inline height when expansion beyond natural height is needed\n\t\t\t// Use the difference between the inner and outer height as a buffer\n\t\t\tnewHeight = idealHeight > innerHeight ? idealHeight + ( outerHeight - innerHeight ) : '';\n\t\t\tif ( newHeight !== this.styleHeight ) {\n\t\t\t\tthis.$input.css( 'height', newHeight );\n\t\t\t\tthis.styleHeight = newHeight;\n\t\t\t\tthis.emit( 'resize' );\n\t\t\t}\n\t\t}\n\t\tscrollWidth = this.$input[ 0 ].offsetWidth - this.$input[ 0 ].clientWidth;\n\t\tif ( scrollWidth !== this.scrollWidth ) {\n\t\t\tproperty = this.$element.css( 'direction' ) === 'rtl' ? 'left' : 'right';\n\t\t\t// Reset\n\t\t\tthis.$label.css( { right: '', left: '' } );\n\t\t\tthis.$indicator.css( { right: '', left: '' } );\n\n\t\t\tif ( scrollWidth ) {\n\t\t\t\tthis.$indicator.css( property, scrollWidth );\n\t\t\t\tif ( this.labelPosition === 'after' ) {\n\t\t\t\t\tthis.$label.css( property, scrollWidth );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.scrollWidth = scrollWidth;\n\t\t\tthis.positionLabel();\n\t\t}\n\t}\n\treturn this;\n};\n\n/**\n * @inheritdoc\n * @protected\n */\nOO.ui.MultilineTextInputWidget.prototype.getInputElement = function () {\n\treturn $( '<textarea>' );\n};\n\n/**\n * Check if the input supports multiple lines.\n *\n * @return {boolean}\n */\nOO.ui.MultilineTextInputWidget.prototype.isMultiline = function () {\n\treturn !!this.multiline;\n};\n\n/**\n * Check if the input automatically adjusts its size.\n *\n * @return {boolean}\n */\nOO.ui.MultilineTextInputWidget.prototype.isAutosizing = function () {\n\treturn !!this.autosize;\n};\n","/**\n * ComboBoxInputWidgets combine a {@link OO.ui.TextInputWidget text input} (where a value\n * can be entered manually) and a {@link OO.ui.MenuSelectWidget menu of options} (from which\n * a value can be chosen instead). Users can choose options from the combo box in one of two ways:\n *\n * - by typing a value in the text input field. If the value exactly matches the value of a menu\n * option, that option will appear to be selected.\n * - by choosing a value from the menu. The value of the chosen option will then appear in the text\n * input field.\n *\n * After the user chooses an option, its `data` will be used as a new value for the widget.\n * A `label` also can be specified for each option: if given, it will be shown instead of the\n * `data` in the dropdown menu.\n *\n * This widget can be used inside an HTML form, such as a OO.ui.FormLayout.\n *\n * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * @example\n * // Example: A ComboBoxInputWidget.\n * var comboBox = new OO.ui.ComboBoxInputWidget( {\n * value: 'Option 1',\n * options: [\n * { data: 'Option 1' },\n * { data: 'Option 2' },\n * { data: 'Option 3' }\n * ]\n * } );\n * $( 'body' ).append( comboBox.$element );\n *\n * @example\n * // Example: A ComboBoxInputWidget with additional option labels.\n * var comboBox = new OO.ui.ComboBoxInputWidget( {\n * value: 'Option 1',\n * options: [\n * {\n * data: 'Option 1',\n * label: 'Option One'\n * },\n * {\n * data: 'Option 2',\n * label: 'Option Two'\n * },\n * {\n * data: 'Option 3',\n * label: 'Option Three'\n * }\n * ]\n * } );\n * $( 'body' ).append( comboBox.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options\n *\n * @class\n * @extends OO.ui.TextInputWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`\n * @cfg {Object} [menu] Configuration options to pass to the {@link OO.ui.MenuSelectWidget menu select widget}.\n * @cfg {jQuery} [$overlay] Render the menu into a separate layer. This configuration is useful in cases where\n * the expanded menu is larger than its containing `<div>`. The specified overlay layer is usually on top of the\n * containing `<div>` and has a larger area. By default, the menu uses relative positioning.\n * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.\n */\nOO.ui.ComboBoxInputWidget = function OoUiComboBoxInputWidget( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( {\n\t\tautocomplete: false\n\t}, config );\n\n\t// ComboBoxInputWidget shouldn't support `multiline`\n\tconfig.multiline = false;\n\n\t// See InputWidget#reusePreInfuseDOM about `config.$input`\n\tif ( config.$input ) {\n\t\tconfig.$input.removeAttr( 'list' );\n\t}\n\n\t// Parent constructor\n\tOO.ui.ComboBoxInputWidget.parent.call( this, config );\n\n\t// Properties\n\tthis.$overlay = config.$overlay || this.$element;\n\tthis.dropdownButton = new OO.ui.ButtonWidget( {\n\t\tclasses: [ 'oo-ui-comboBoxInputWidget-dropdownButton' ],\n\t\tindicator: 'down',\n\t\tdisabled: this.disabled\n\t} );\n\tthis.menu = new OO.ui.MenuSelectWidget( $.extend(\n\t\t{\n\t\t\twidget: this,\n\t\t\tinput: this,\n\t\t\t$floatableContainer: this.$element,\n\t\t\tdisabled: this.isDisabled()\n\t\t},\n\t\tconfig.menu\n\t) );\n\n\t// Events\n\tthis.connect( this, {\n\t\tchange: 'onInputChange',\n\t\tenter: 'onInputEnter'\n\t} );\n\tthis.dropdownButton.connect( this, {\n\t\tclick: 'onDropdownButtonClick'\n\t} );\n\tthis.menu.connect( this, {\n\t\tchoose: 'onMenuChoose',\n\t\tadd: 'onMenuItemsChange',\n\t\tremove: 'onMenuItemsChange'\n\t} );\n\n\t// Initialization\n\tthis.$input.attr( {\n\t\trole: 'combobox',\n\t\t'aria-owns': this.menu.getElementId(),\n\t\t'aria-autocomplete': 'list'\n\t} );\n\t// Do not override options set via config.menu.items\n\tif ( config.options !== undefined ) {\n\t\tthis.setOptions( config.options );\n\t}\n\tthis.$field = $( '<div>' )\n\t\t.addClass( 'oo-ui-comboBoxInputWidget-field' )\n\t\t.append( this.$input, this.dropdownButton.$element );\n\tthis.$element\n\t\t.addClass( 'oo-ui-comboBoxInputWidget' )\n\t\t.append( this.$field );\n\tthis.$overlay.append( this.menu.$element );\n\tthis.onMenuItemsChange();\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ComboBoxInputWidget, OO.ui.TextInputWidget );\n\n/* Methods */\n\n/**\n * Get the combobox's menu.\n *\n * @return {OO.ui.MenuSelectWidget} Menu widget\n */\nOO.ui.ComboBoxInputWidget.prototype.getMenu = function () {\n\treturn this.menu;\n};\n\n/**\n * Get the combobox's text input widget.\n *\n * @return {OO.ui.TextInputWidget} Text input widget\n */\nOO.ui.ComboBoxInputWidget.prototype.getInput = function () {\n\treturn this;\n};\n\n/**\n * Handle input change events.\n *\n * @private\n * @param {string} value New value\n */\nOO.ui.ComboBoxInputWidget.prototype.onInputChange = function ( value ) {\n\tvar match = this.menu.getItemFromData( value );\n\n\tthis.menu.selectItem( match );\n\tif ( this.menu.getHighlightedItem() ) {\n\t\tthis.menu.highlightItem( match );\n\t}\n\n\tif ( !this.isDisabled() ) {\n\t\tthis.menu.toggle( true );\n\t}\n};\n\n/**\n * Handle input enter events.\n *\n * @private\n */\nOO.ui.ComboBoxInputWidget.prototype.onInputEnter = function () {\n\tif ( !this.isDisabled() ) {\n\t\tthis.menu.toggle( false );\n\t}\n};\n\n/**\n * Handle button click events.\n *\n * @private\n */\nOO.ui.ComboBoxInputWidget.prototype.onDropdownButtonClick = function () {\n\tthis.menu.toggle();\n\tthis.focus();\n};\n\n/**\n * Handle menu choose events.\n *\n * @private\n * @param {OO.ui.OptionWidget} item Chosen item\n */\nOO.ui.ComboBoxInputWidget.prototype.onMenuChoose = function ( item ) {\n\tthis.setValue( item.getData() );\n};\n\n/**\n * Handle menu item change events.\n *\n * @private\n */\nOO.ui.ComboBoxInputWidget.prototype.onMenuItemsChange = function () {\n\tvar match = this.menu.getItemFromData( this.getValue() );\n\tthis.menu.selectItem( match );\n\tif ( this.menu.getHighlightedItem() ) {\n\t\tthis.menu.highlightItem( match );\n\t}\n\tthis.$element.toggleClass( 'oo-ui-comboBoxInputWidget-empty', this.menu.isEmpty() );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ComboBoxInputWidget.prototype.setDisabled = function ( disabled ) {\n\t// Parent method\n\tOO.ui.ComboBoxInputWidget.parent.prototype.setDisabled.call( this, disabled );\n\n\tif ( this.dropdownButton ) {\n\t\tthis.dropdownButton.setDisabled( this.isDisabled() );\n\t}\n\tif ( this.menu ) {\n\t\tthis.menu.setDisabled( this.isDisabled() );\n\t}\n\n\treturn this;\n};\n\n/**\n * Set the options available for this input.\n *\n * @param {Object[]} options Array of menu options in the format `{ data: …, label: … }`\n * @chainable\n */\nOO.ui.ComboBoxInputWidget.prototype.setOptions = function ( options ) {\n\tthis.getMenu()\n\t\t.clearItems()\n\t\t.addItems( options.map( function ( opt ) {\n\t\t\treturn new OO.ui.MenuOptionWidget( {\n\t\t\t\tdata: opt.data,\n\t\t\t\tlabel: opt.label !== undefined ? opt.label : opt.data\n\t\t\t} );\n\t\t} ) );\n\n\treturn this;\n};\n","/**\n * FieldLayouts are used with OO.ui.FieldsetLayout. Each FieldLayout requires a field-widget,\n * which is a widget that is specified by reference before any optional configuration settings.\n *\n * Field layouts can be configured with help text and/or labels. Labels are aligned in one of four ways:\n *\n * - **left**: The label is placed before the field-widget and aligned with the left margin.\n * A left-alignment is used for forms with many fields.\n * - **right**: The label is placed before the field-widget and aligned to the right margin.\n * A right-alignment is used for long but familiar forms which users tab through,\n * verifying the current field with a quick glance at the label.\n * - **top**: The label is placed above the field-widget. A top-alignment is used for brief forms\n * that users fill out from top to bottom.\n * - **inline**: The label is placed after the field-widget and aligned to the left.\n * An inline-alignment is best used with checkboxes or radio buttons.\n *\n * Help text is accessed via a help icon that appears in the upper right corner of the rendered field layout.\n * Please see the [OOjs UI documentation on MediaWiki] [1] for examples and more information.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Layouts/Fields_and_Fieldsets\n *\n * @class\n * @extends OO.ui.Layout\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.TitledElement\n *\n * @constructor\n * @param {OO.ui.Widget} fieldWidget Field widget\n * @param {Object} [config] Configuration options\n * @cfg {string} [align='left'] Alignment of the label: 'left', 'right', 'top' or 'inline'\n * @cfg {Array} [errors] Error messages about the widget, which will be displayed below the widget.\n * The array may contain strings or OO.ui.HtmlSnippet instances.\n * @cfg {Array} [notices] Notices about the widget, which will be displayed below the widget.\n * The array may contain strings or OO.ui.HtmlSnippet instances.\n * @cfg {string|OO.ui.HtmlSnippet} [help] Help text. When help text is specified, a \"help\" icon will appear\n * in the upper-right corner of the rendered field; clicking it will display the text in a popup.\n * For important messages, you are advised to use `notices`, as they are always shown.\n * @cfg {jQuery} [$overlay] Passed to OO.ui.PopupButtonWidget for help popup, if `help` is given.\n * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.\n *\n * @throws {Error} An error is thrown if no widget is specified\n */\nOO.ui.FieldLayout = function OoUiFieldLayout( fieldWidget, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( fieldWidget ) && config === undefined ) {\n\t\tconfig = fieldWidget;\n\t\tfieldWidget = config.fieldWidget;\n\t}\n\n\t// Make sure we have required constructor arguments\n\tif ( fieldWidget === undefined ) {\n\t\tthrow new Error( 'Widget not found' );\n\t}\n\n\t// Configuration initialization\n\tconfig = $.extend( { align: 'left' }, config );\n\n\t// Parent constructor\n\tOO.ui.FieldLayout.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.LabelElement.call( this, $.extend( {}, config, {\n\t\t$label: $( '<label>' )\n\t} ) );\n\tOO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$label } ) );\n\n\t// Properties\n\tthis.fieldWidget = fieldWidget;\n\tthis.errors = [];\n\tthis.notices = [];\n\tthis.$field = this.isFieldInline() ? $( '<span>' ) : $( '<div>' );\n\tthis.$messages = $( '<ul>' );\n\tthis.$header = $( '<span>' );\n\tthis.$body = $( '<div>' );\n\tthis.align = null;\n\tif ( config.help ) {\n\t\tthis.popupButtonWidget = new OO.ui.PopupButtonWidget( {\n\t\t\t$overlay: config.$overlay,\n\t\t\tpopup: {\n\t\t\t\tpadded: true\n\t\t\t},\n\t\t\tclasses: [ 'oo-ui-fieldLayout-help' ],\n\t\t\tframed: false,\n\t\t\ticon: 'info'\n\t\t} );\n\t\tif ( config.help instanceof OO.ui.HtmlSnippet ) {\n\t\t\tthis.popupButtonWidget.getPopup().$body.html( config.help.toString() );\n\t\t} else {\n\t\t\tthis.popupButtonWidget.getPopup().$body.text( config.help );\n\t\t}\n\t\tthis.$help = this.popupButtonWidget.$element;\n\t} else {\n\t\tthis.$help = $( [] );\n\t}\n\n\t// Events\n\tthis.fieldWidget.connect( this, { disable: 'onFieldDisable' } );\n\n\t// Initialization\n\tif ( config.help ) {\n\t\t// Set the 'aria-describedby' attribute on the fieldWidget\n\t\t// Preference given to an input or a button\n\t\t(\n\t\t\tthis.fieldWidget.$input ||\n\t\t\tthis.fieldWidget.$button ||\n\t\t\tthis.fieldWidget.$element\n\t\t).attr(\n\t\t\t'aria-describedby',\n\t\t\tthis.popupButtonWidget.getPopup().getBodyId()\n\t\t);\n\t}\n\tif ( this.fieldWidget.getInputId() ) {\n\t\tthis.$label.attr( 'for', this.fieldWidget.getInputId() );\n\t} else {\n\t\tthis.$label.on( 'click', function () {\n\t\t\tthis.fieldWidget.simulateLabelClick();\n\t\t\treturn false;\n\t\t}.bind( this ) );\n\t}\n\tthis.$element\n\t\t.addClass( 'oo-ui-fieldLayout' )\n\t\t.toggleClass( 'oo-ui-fieldLayout-disabled', this.fieldWidget.isDisabled() )\n\t\t.append( this.$body );\n\tthis.$body.addClass( 'oo-ui-fieldLayout-body' );\n\tthis.$header.addClass( 'oo-ui-fieldLayout-header' );\n\tthis.$messages.addClass( 'oo-ui-fieldLayout-messages' );\n\tthis.$field\n\t\t.addClass( 'oo-ui-fieldLayout-field' )\n\t\t.append( this.fieldWidget.$element );\n\n\tthis.setErrors( config.errors || [] );\n\tthis.setNotices( config.notices || [] );\n\tthis.setAlignment( config.align );\n\t// Call this again to take into account the widget's accessKey\n\tthis.updateTitle();\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.FieldLayout, OO.ui.Layout );\nOO.mixinClass( OO.ui.FieldLayout, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.FieldLayout, OO.ui.mixin.TitledElement );\n\n/* Methods */\n\n/**\n * Handle field disable events.\n *\n * @private\n * @param {boolean} value Field is disabled\n */\nOO.ui.FieldLayout.prototype.onFieldDisable = function ( value ) {\n\tthis.$element.toggleClass( 'oo-ui-fieldLayout-disabled', value );\n};\n\n/**\n * Get the widget contained by the field.\n *\n * @return {OO.ui.Widget} Field widget\n */\nOO.ui.FieldLayout.prototype.getField = function () {\n\treturn this.fieldWidget;\n};\n\n/**\n * Return `true` if the given field widget can be used with `'inline'` alignment (see\n * #setAlignment). Return `false` if it can't or if this can't be determined.\n *\n * @return {boolean}\n */\nOO.ui.FieldLayout.prototype.isFieldInline = function () {\n\t// This is very simplistic, but should be good enough.\n\treturn this.getField().$element.prop( 'tagName' ).toLowerCase() === 'span';\n};\n\n/**\n * @protected\n * @param {string} kind 'error' or 'notice'\n * @param {string|OO.ui.HtmlSnippet} text\n * @return {jQuery}\n */\nOO.ui.FieldLayout.prototype.makeMessage = function ( kind, text ) {\n\tvar $listItem, $icon, message;\n\t$listItem = $( '<li>' );\n\tif ( kind === 'error' ) {\n\t\t$icon = new OO.ui.IconWidget( { icon: 'alert', flags: [ 'warning' ] } ).$element;\n\t\t$listItem.attr( 'role', 'alert' );\n\t} else if ( kind === 'notice' ) {\n\t\t$icon = new OO.ui.IconWidget( { icon: 'info' } ).$element;\n\t} else {\n\t\t$icon = '';\n\t}\n\tmessage = new OO.ui.LabelWidget( { label: text } );\n\t$listItem\n\t\t.append( $icon, message.$element )\n\t\t.addClass( 'oo-ui-fieldLayout-messages-' + kind );\n\treturn $listItem;\n};\n\n/**\n * Set the field alignment mode.\n *\n * @private\n * @param {string} value Alignment mode, either 'left', 'right', 'top' or 'inline'\n * @chainable\n */\nOO.ui.FieldLayout.prototype.setAlignment = function ( value ) {\n\tif ( value !== this.align ) {\n\t\t// Default to 'left'\n\t\tif ( [ 'left', 'right', 'top', 'inline' ].indexOf( value ) === -1 ) {\n\t\t\tvalue = 'left';\n\t\t}\n\t\t// Validate\n\t\tif ( value === 'inline' && !this.isFieldInline() ) {\n\t\t\tvalue = 'top';\n\t\t}\n\t\t// Reorder elements\n\t\tif ( value === 'top' ) {\n\t\t\tthis.$header.append( this.$label, this.$help );\n\t\t\tthis.$body.append( this.$header, this.$field );\n\t\t} else if ( value === 'inline' ) {\n\t\t\tthis.$header.append( this.$label, this.$help );\n\t\t\tthis.$body.append( this.$field, this.$header );\n\t\t} else {\n\t\t\tthis.$header.append( this.$label );\n\t\t\tthis.$body.append( this.$header, this.$help, this.$field );\n\t\t}\n\t\t// Set classes. The following classes can be used here:\n\t\t// * oo-ui-fieldLayout-align-left\n\t\t// * oo-ui-fieldLayout-align-right\n\t\t// * oo-ui-fieldLayout-align-top\n\t\t// * oo-ui-fieldLayout-align-inline\n\t\tif ( this.align ) {\n\t\t\tthis.$element.removeClass( 'oo-ui-fieldLayout-align-' + this.align );\n\t\t}\n\t\tthis.$element.addClass( 'oo-ui-fieldLayout-align-' + value );\n\t\tthis.align = value;\n\t}\n\n\treturn this;\n};\n\n/**\n * Set the list of error messages.\n *\n * @param {Array} errors Error messages about the widget, which will be displayed below the widget.\n * The array may contain strings or OO.ui.HtmlSnippet instances.\n * @chainable\n */\nOO.ui.FieldLayout.prototype.setErrors = function ( errors ) {\n\tthis.errors = errors.slice();\n\tthis.updateMessages();\n\treturn this;\n};\n\n/**\n * Set the list of notice messages.\n *\n * @param {Array} notices Notices about the widget, which will be displayed below the widget.\n * The array may contain strings or OO.ui.HtmlSnippet instances.\n * @chainable\n */\nOO.ui.FieldLayout.prototype.setNotices = function ( notices ) {\n\tthis.notices = notices.slice();\n\tthis.updateMessages();\n\treturn this;\n};\n\n/**\n * Update the rendering of error and notice messages.\n *\n * @private\n */\nOO.ui.FieldLayout.prototype.updateMessages = function () {\n\tvar i;\n\tthis.$messages.empty();\n\n\tif ( this.errors.length || this.notices.length ) {\n\t\tthis.$body.after( this.$messages );\n\t} else {\n\t\tthis.$messages.remove();\n\t\treturn;\n\t}\n\n\tfor ( i = 0; i < this.notices.length; i++ ) {\n\t\tthis.$messages.append( this.makeMessage( 'notice', this.notices[ i ] ) );\n\t}\n\tfor ( i = 0; i < this.errors.length; i++ ) {\n\t\tthis.$messages.append( this.makeMessage( 'error', this.errors[ i ] ) );\n\t}\n};\n\n/**\n * Include information about the widget's accessKey in our title. TitledElement calls this method.\n * (This is a bit of a hack.)\n *\n * @protected\n * @param {string} title Tooltip label for 'title' attribute\n * @return {string}\n */\nOO.ui.FieldLayout.prototype.formatTitleWithAccessKey = function ( title ) {\n\tif ( this.fieldWidget && this.fieldWidget.formatTitleWithAccessKey ) {\n\t\treturn this.fieldWidget.formatTitleWithAccessKey( title );\n\t}\n\treturn title;\n};\n","/**\n * ActionFieldLayouts are used with OO.ui.FieldsetLayout. The layout consists of a field-widget, a button,\n * and an optional label and/or help text. The field-widget (e.g., a {@link OO.ui.TextInputWidget TextInputWidget}),\n * is required and is specified before any optional configuration settings.\n *\n * Labels can be aligned in one of four ways:\n *\n * - **left**: The label is placed before the field-widget and aligned with the left margin.\n * A left-alignment is used for forms with many fields.\n * - **right**: The label is placed before the field-widget and aligned to the right margin.\n * A right-alignment is used for long but familiar forms which users tab through,\n * verifying the current field with a quick glance at the label.\n * - **top**: The label is placed above the field-widget. A top-alignment is used for brief forms\n * that users fill out from top to bottom.\n * - **inline**: The label is placed after the field-widget and aligned to the left.\n * An inline-alignment is best used with checkboxes or radio buttons.\n *\n * Help text is accessed via a help icon that appears in the upper right corner of the rendered field layout when help\n * text is specified.\n *\n * @example\n * // Example of an ActionFieldLayout\n * var actionFieldLayout = new OO.ui.ActionFieldLayout(\n * new OO.ui.TextInputWidget( {\n * placeholder: 'Field widget'\n * } ),\n * new OO.ui.ButtonWidget( {\n * label: 'Button'\n * } ),\n * {\n * label: 'An ActionFieldLayout. This label is aligned top',\n * align: 'top',\n * help: 'This is help text'\n * }\n * );\n *\n * $( 'body' ).append( actionFieldLayout.$element );\n *\n * @class\n * @extends OO.ui.FieldLayout\n *\n * @constructor\n * @param {OO.ui.Widget} fieldWidget Field widget\n * @param {OO.ui.ButtonWidget} buttonWidget Button widget\n * @param {Object} config\n */\nOO.ui.ActionFieldLayout = function OoUiActionFieldLayout( fieldWidget, buttonWidget, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( fieldWidget ) && config === undefined ) {\n\t\tconfig = fieldWidget;\n\t\tfieldWidget = config.fieldWidget;\n\t\tbuttonWidget = config.buttonWidget;\n\t}\n\n\t// Parent constructor\n\tOO.ui.ActionFieldLayout.parent.call( this, fieldWidget, config );\n\n\t// Properties\n\tthis.buttonWidget = buttonWidget;\n\tthis.$button = $( '<span>' );\n\tthis.$input = this.isFieldInline() ? $( '<span>' ) : $( '<div>' );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-actionFieldLayout' );\n\tthis.$button\n\t\t.addClass( 'oo-ui-actionFieldLayout-button' )\n\t\t.append( this.buttonWidget.$element );\n\tthis.$input\n\t\t.addClass( 'oo-ui-actionFieldLayout-input' )\n\t\t.append( this.fieldWidget.$element );\n\tthis.$field\n\t\t.append( this.$input, this.$button );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ActionFieldLayout, OO.ui.FieldLayout );\n","/**\n * FieldsetLayouts are composed of one or more {@link OO.ui.FieldLayout FieldLayouts},\n * which each contain an individual widget and, optionally, a label. Each Fieldset can be\n * configured with a label as well. For more information and examples,\n * please see the [OOjs UI documentation on MediaWiki][1].\n *\n * @example\n * // Example of a fieldset layout\n * var input1 = new OO.ui.TextInputWidget( {\n * placeholder: 'A text input field'\n * } );\n *\n * var input2 = new OO.ui.TextInputWidget( {\n * placeholder: 'A text input field'\n * } );\n *\n * var fieldset = new OO.ui.FieldsetLayout( {\n * label: 'Example of a fieldset layout'\n * } );\n *\n * fieldset.addItems( [\n * new OO.ui.FieldLayout( input1, {\n * label: 'Field One'\n * } ),\n * new OO.ui.FieldLayout( input2, {\n * label: 'Field Two'\n * } )\n * ] );\n * $( 'body' ).append( fieldset.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Layouts/Fields_and_Fieldsets\n *\n * @class\n * @extends OO.ui.Layout\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.GroupElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {OO.ui.FieldLayout[]} [items] An array of fields to add to the fieldset. See OO.ui.FieldLayout for more information about fields.\n * @cfg {string|OO.ui.HtmlSnippet} [help] Help text. When help text is specified, a \"help\" icon will appear\n * in the upper-right corner of the rendered field; clicking it will display the text in a popup.\n * For important messages, you are advised to use `notices`, as they are always shown.\n * @cfg {jQuery} [$overlay] Passed to OO.ui.PopupButtonWidget for help popup, if `help` is given.\n * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.\n */\nOO.ui.FieldsetLayout = function OoUiFieldsetLayout( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.FieldsetLayout.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\tOO.ui.mixin.GroupElement.call( this, config );\n\n\t// Properties\n\tthis.$header = $( '<legend>' );\n\tif ( config.help ) {\n\t\tthis.popupButtonWidget = new OO.ui.PopupButtonWidget( {\n\t\t\t$overlay: config.$overlay,\n\t\t\tpopup: {\n\t\t\t\tpadded: true\n\t\t\t},\n\t\t\tclasses: [ 'oo-ui-fieldsetLayout-help' ],\n\t\t\tframed: false,\n\t\t\ticon: 'info'\n\t\t} );\n\t\tif ( config.help instanceof OO.ui.HtmlSnippet ) {\n\t\t\tthis.popupButtonWidget.getPopup().$body.html( config.help.toString() );\n\t\t} else {\n\t\t\tthis.popupButtonWidget.getPopup().$body.text( config.help );\n\t\t}\n\t\tthis.$help = this.popupButtonWidget.$element;\n\t} else {\n\t\tthis.$help = $( [] );\n\t}\n\n\t// Initialization\n\tthis.$header\n\t\t.addClass( 'oo-ui-fieldsetLayout-header' )\n\t\t.append( this.$icon, this.$label, this.$help );\n\tthis.$group.addClass( 'oo-ui-fieldsetLayout-group' );\n\tthis.$element\n\t\t.addClass( 'oo-ui-fieldsetLayout' )\n\t\t.prepend( this.$header, this.$group );\n\tif ( Array.isArray( config.items ) ) {\n\t\tthis.addItems( config.items );\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.FieldsetLayout, OO.ui.Layout );\nOO.mixinClass( OO.ui.FieldsetLayout, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.FieldsetLayout, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.FieldsetLayout, OO.ui.mixin.GroupElement );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.FieldsetLayout.static.tagName = 'fieldset';\n","/**\n * FormLayouts are used to wrap {@link OO.ui.FieldsetLayout FieldsetLayouts} when you intend to use browser-based\n * form submission for the fields instead of handling them in JavaScript. Form layouts can be configured with an\n * HTML form action, an encoding type, and a method using the #action, #enctype, and #method configs, respectively.\n * See the [OOjs UI documentation on MediaWiki] [1] for more information and examples.\n *\n * Only widgets from the {@link OO.ui.InputWidget InputWidget} family support form submission. It\n * includes standard form elements like {@link OO.ui.CheckboxInputWidget checkboxes}, {@link\n * OO.ui.RadioInputWidget radio buttons} and {@link OO.ui.TextInputWidget text fields}, as well as\n * some fancier controls. Some controls have both regular and InputWidget variants, for example\n * OO.ui.DropdownWidget and OO.ui.DropdownInputWidget – only the latter support form submission and\n * often have simplified APIs to match the capabilities of HTML forms.\n * See the [OOjs UI Inputs documentation on MediaWiki] [2] for more information about InputWidgets.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Layouts/Forms\n * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs\n *\n * @example\n * // Example of a form layout that wraps a fieldset layout\n * var input1 = new OO.ui.TextInputWidget( {\n * placeholder: 'Username'\n * } );\n * var input2 = new OO.ui.TextInputWidget( {\n * placeholder: 'Password',\n * type: 'password'\n * } );\n * var submit = new OO.ui.ButtonInputWidget( {\n * label: 'Submit'\n * } );\n *\n * var fieldset = new OO.ui.FieldsetLayout( {\n * label: 'A form layout'\n * } );\n * fieldset.addItems( [\n * new OO.ui.FieldLayout( input1, {\n * label: 'Username',\n * align: 'top'\n * } ),\n * new OO.ui.FieldLayout( input2, {\n * label: 'Password',\n * align: 'top'\n * } ),\n * new OO.ui.FieldLayout( submit )\n * ] );\n * var form = new OO.ui.FormLayout( {\n * items: [ fieldset ],\n * action: '/api/formhandler',\n * method: 'get'\n * } )\n * $( 'body' ).append( form.$element );\n *\n * @class\n * @extends OO.ui.Layout\n * @mixins OO.ui.mixin.GroupElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string} [method] HTML form `method` attribute\n * @cfg {string} [action] HTML form `action` attribute\n * @cfg {string} [enctype] HTML form `enctype` attribute\n * @cfg {OO.ui.FieldsetLayout[]} [items] Fieldset layouts to add to the form layout.\n */\nOO.ui.FormLayout = function OoUiFormLayout( config ) {\n\tvar action;\n\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.FormLayout.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.GroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );\n\n\t// Events\n\tthis.$element.on( 'submit', this.onFormSubmit.bind( this ) );\n\n\t// Make sure the action is safe\n\taction = config.action;\n\tif ( action !== undefined && !OO.ui.isSafeUrl( action ) ) {\n\t\taction = './' + action;\n\t}\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-formLayout' )\n\t\t.attr( {\n\t\t\tmethod: config.method,\n\t\t\taction: action,\n\t\t\tenctype: config.enctype\n\t\t} );\n\tif ( Array.isArray( config.items ) ) {\n\t\tthis.addItems( config.items );\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.FormLayout, OO.ui.Layout );\nOO.mixinClass( OO.ui.FormLayout, OO.ui.mixin.GroupElement );\n\n/* Events */\n\n/**\n * A 'submit' event is emitted when the form is submitted.\n *\n * @event submit\n */\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.FormLayout.static.tagName = 'form';\n\n/* Methods */\n\n/**\n * Handle form submit events.\n *\n * @private\n * @param {jQuery.Event} e Submit event\n * @fires submit\n */\nOO.ui.FormLayout.prototype.onFormSubmit = function () {\n\tif ( this.emit( 'submit' ) ) {\n\t\treturn false;\n\t}\n};\n","/**\n * PanelLayouts expand to cover the entire area of their parent. They can be configured with scrolling, padding,\n * and a frame, and are often used together with {@link OO.ui.StackLayout StackLayouts}.\n *\n * @example\n * // Example of a panel layout\n * var panel = new OO.ui.PanelLayout( {\n * expanded: false,\n * framed: true,\n * padded: true,\n * $content: $( '<p>A panel layout with padding and a frame.</p>' )\n * } );\n * $( 'body' ).append( panel.$element );\n *\n * @class\n * @extends OO.ui.Layout\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [scrollable=false] Allow vertical scrolling\n * @cfg {boolean} [padded=false] Add padding between the content and the edges of the panel.\n * @cfg {boolean} [expanded=true] Expand the panel to fill the entire parent element.\n * @cfg {boolean} [framed=false] Render the panel with a frame to visually separate it from outside content.\n */\nOO.ui.PanelLayout = function OoUiPanelLayout( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( {\n\t\tscrollable: false,\n\t\tpadded: false,\n\t\texpanded: true,\n\t\tframed: false\n\t}, config );\n\n\t// Parent constructor\n\tOO.ui.PanelLayout.parent.call( this, config );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-panelLayout' );\n\tif ( config.scrollable ) {\n\t\tthis.$element.addClass( 'oo-ui-panelLayout-scrollable' );\n\t}\n\tif ( config.padded ) {\n\t\tthis.$element.addClass( 'oo-ui-panelLayout-padded' );\n\t}\n\tif ( config.expanded ) {\n\t\tthis.$element.addClass( 'oo-ui-panelLayout-expanded' );\n\t}\n\tif ( config.framed ) {\n\t\tthis.$element.addClass( 'oo-ui-panelLayout-framed' );\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.PanelLayout, OO.ui.Layout );\n\n/* Methods */\n\n/**\n * Focus the panel layout\n *\n * The default implementation just focuses the first focusable element in the panel\n */\nOO.ui.PanelLayout.prototype.focus = function () {\n\tOO.ui.findFocusable( this.$element ).focus();\n};\n","/**\n * HorizontalLayout arranges its contents in a single line (using `display: inline-block` for its\n * items), with small margins between them. Convenient when you need to put a number of block-level\n * widgets on a single line next to each other.\n *\n * Note that inline elements, such as OO.ui.ButtonWidgets, do not need this wrapper.\n *\n * @example\n * // HorizontalLayout with a text input and a label\n * var layout = new OO.ui.HorizontalLayout( {\n * items: [\n * new OO.ui.LabelWidget( { label: 'Label' } ),\n * new OO.ui.TextInputWidget( { value: 'Text' } )\n * ]\n * } );\n * $( 'body' ).append( layout.$element );\n *\n * @class\n * @extends OO.ui.Layout\n * @mixins OO.ui.mixin.GroupElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {OO.ui.Widget[]|OO.ui.Layout[]} [items] Widgets or other layouts to add to the layout.\n */\nOO.ui.HorizontalLayout = function OoUiHorizontalLayout( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.HorizontalLayout.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.GroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-horizontalLayout' );\n\tif ( Array.isArray( config.items ) ) {\n\t\tthis.addItems( config.items );\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.HorizontalLayout, OO.ui.Layout );\nOO.mixinClass( OO.ui.HorizontalLayout, OO.ui.mixin.GroupElement );\n","}( OO ) );\n"]} \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-mediawiki.js b/www/wiki/resources/lib/oojs-ui/oojs-ui-mediawiki.js
new file mode 100644
index 00000000..c1150d07
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-mediawiki.js
@@ -0,0 +1,79 @@
+/*!
+ * OOjs UI v0.17.1
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2016 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2016-05-03T22:58:02Z
+ */
+( function ( OO ) {
+
+'use strict';
+
+/**
+ * @class
+ * @extends OO.ui.Theme
+ *
+ * @constructor
+ */
+OO.ui.MediaWikiTheme = function OoUiMediaWikiTheme() {
+ // Parent constructor
+ OO.ui.MediaWikiTheme.parent.call( this );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MediaWikiTheme, OO.ui.Theme );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MediaWikiTheme.prototype.getElementClasses = function ( element ) {
+ // Parent method
+ var variant, isFramed, isActive,
+ variants = {
+ warning: false,
+ invert: false,
+ progressive: false,
+ constructive: false,
+ destructive: false
+ },
+ // Parent method
+ classes = OO.ui.MediaWikiTheme.parent.prototype.getElementClasses.call( this, element );
+
+ if ( element.supports( [ 'hasFlag' ] ) ) {
+ isFramed = element.supports( [ 'isFramed' ] ) && element.isFramed();
+ isActive = element.supports( [ 'isActive' ] ) && element.isActive();
+ if (
+ ( isFramed && ( isActive || element.isDisabled() || element.hasFlag( 'primary' ) ) )
+ ) {
+ // Button with a dark background, use white icon
+ variants.invert = true;
+ } else if ( !isFramed && element.isDisabled() ) {
+ // Frameless disabled button, always use black icon regardless of flags
+ variants.invert = false;
+ } else {
+ // Any other kind of button, use the right colored icon if available
+ variants.progressive = element.hasFlag( 'progressive' );
+ variants.constructive = element.hasFlag( 'constructive' );
+ variants.destructive = element.hasFlag( 'destructive' );
+ variants.warning = element.hasFlag( 'warning' );
+ }
+ }
+
+ for ( variant in variants ) {
+ classes[ variants[ variant ] ? 'on' : 'off' ].push( 'oo-ui-image-' + variant );
+ }
+
+ return classes;
+};
+
+/* Instantiation */
+
+OO.ui.theme = new OO.ui.MediaWikiTheme();
+
+}( OO ) );
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-apex.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-apex.css
new file mode 100644
index 00000000..2108973d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-apex.css
@@ -0,0 +1,559 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:24:03Z
+ */
+.oo-ui-popupTool .oo-ui-popupWidget-popup,
+.oo-ui-popupTool .oo-ui-popupWidget-anchor {
+ z-index: 4;
+}
+.oo-ui-toolGroupTool > .oo-ui-popupToolGroup {
+ border: 0;
+ border-radius: 0;
+ margin: 0;
+}
+.oo-ui-toolGroupTool:first-child > .oo-ui-popupToolGroup {
+ border-top-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+.oo-ui-toolGroupTool:last-child > .oo-ui-popupToolGroup {
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+}
+.oo-ui-toolGroupTool > .oo-ui-popupToolGroup > .oo-ui-popupToolGroup-handle {
+ height: 1.875em;
+ padding: 0.3125em;
+}
+.oo-ui-toolGroupTool > .oo-ui-popupToolGroup > .oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ height: 1.875em;
+ width: 1.875em;
+}
+.oo-ui-toolGroupTool > .oo-ui-popupToolGroup.oo-ui-labelElement > .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ line-height: 2.1em;
+}
+.oo-ui-toolGroup {
+ display: inline-block;
+ vertical-align: middle;
+ margin: 0.375em;
+ border-radius: 4px;
+ border: 1px solid transparent;
+ -webkit-transition: border-color 250ms ease;
+ -moz-transition: border-color 250ms ease;
+ transition: border-color 250ms ease;
+}
+.oo-ui-toolGroup-empty {
+ display: none;
+}
+.oo-ui-toolGroup .oo-ui-tool-link {
+ text-decoration: none;
+ cursor: pointer;
+}
+.oo-ui-toolGroup.oo-ui-widget-disabled .oo-ui-tool-link,
+.oo-ui-toolGroup .oo-ui-widget-disabled > .oo-ui-tool-link {
+ outline: 0;
+ cursor: default;
+}
+.oo-ui-toolbar-narrow .oo-ui-toolGroup + .oo-ui-toolGroup {
+ margin-left: 0;
+}
+.oo-ui-toolGroup.oo-ui-widget-enabled:hover {
+ border-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-toolGroup.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-tool-title {
+ color: #000;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool {
+ display: inline-block;
+ position: relative;
+ vertical-align: top;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link {
+ display: block;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-tool-accel {
+ display: none;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-iconElement > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ display: inline-block;
+ vertical-align: top;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-iconElement > .oo-ui-tool-link .oo-ui-tool-title {
+ display: none;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-iconElement.oo-ui-tool-with-label > .oo-ui-tool-link .oo-ui-tool-title {
+ display: inline;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool {
+ margin: -1px 0 -1px -1px;
+ border: 1px solid transparent;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool:first-child {
+ border-top-left-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool:last-child {
+ margin-right: -1px;
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 4px;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link {
+ height: 1.875em;
+ padding: 0.3125em;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ height: 1.875em;
+ width: 1.875em;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-tool-title {
+ line-height: 2.1em;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled:hover {
+ border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-tool-active.oo-ui-widget-enabled {
+ border-color: rgba(0, 0, 0, 0.2);
+ box-shadow: inset 0 0.0875em 0.0875em 0 rgba(0, 0, 0, 0.07);
+ background-color: #f8fbfd;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #f1f7fb), color-stop(100%, #fff));
+ background-image: -webkit-linear-gradient(top, #f1f7fb 0, #fff 100%);
+ background-image: -moz-linear-gradient(top, #f1f7fb 0, #fff 100%);
+ background-image: linear-gradient(to bottom, #f1f7fb 0, #fff 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#fff1f7fb', endColorstr='#ffffffff' )";
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
+ border-left-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link:focus {
+ outline: 0;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link .oo-ui-tool-title {
+ color: #ccc;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled:hover > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 1;
+}
+.oo-ui-barToolGroup.oo-ui-widget-disabled > .oo-ui-toolGroup-tools > .oo-ui-tool:focus {
+ outline: 0;
+}
+.oo-ui-barToolGroup.oo-ui-widget-disabled > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link:focus {
+ outline: 0;
+}
+.oo-ui-barToolGroup.oo-ui-widget-disabled > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-tool-title {
+ color: #ccc;
+}
+.oo-ui-barToolGroup.oo-ui-widget-disabled > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-popupToolGroup {
+ position: relative;
+ height: 2.5em;
+ min-width: 2.5em;
+}
+.oo-ui-popupToolGroup-handle {
+ display: block;
+ cursor: pointer;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ position: absolute;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
+ outline: 0;
+ cursor: default;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+ display: none;
+ position: absolute;
+ z-index: 4;
+}
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled > .oo-ui-toolGroup-tools {
+ display: block;
+}
+.oo-ui-popupToolGroup-left > .oo-ui-toolGroup-tools {
+ left: 0;
+}
+.oo-ui-popupToolGroup-right > .oo-ui-toolGroup-tools {
+ right: 0;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link {
+ display: table;
+ width: 100%;
+ vertical-align: middle;
+ white-space: nowrap;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon,
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel,
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+ display: table-cell;
+ vertical-align: middle;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel {
+ text-align: right;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel:not( :empty ) {
+ padding-left: 3em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup {
+ min-width: 1.875em;
+}
+.oo-ui-popupToolGroup.oo-ui-iconElement {
+ min-width: 3.125em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-iconElement {
+ min-width: 2.5em;
+}
+.oo-ui-popupToolGroup.oo-ui-indicatorElement.oo-ui-iconElement {
+ min-width: 4.375em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-indicatorElement.oo-ui-iconElement {
+ min-width: 3.75em;
+}
+.oo-ui-popupToolGroup.oo-ui-labelElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ line-height: 2.6em;
+ margin: 0 1em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-labelElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin: 0 0.5em;
+}
+.oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-iconElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-left: 3em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-iconElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-left: 2.5em;
+}
+.oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-indicatorElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-right: 2.25em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-indicatorElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-right: 1.75em;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive > .oo-ui-popupToolGroup-handle {
+ border: 1px solid #a6cee1;
+ background-color: #cde7f4;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #eaf4fa), color-stop(100%, #b0d9ee));
+ background-image: -webkit-linear-gradient(top, #eaf4fa 0, #b0d9ee 100%);
+ background-image: -moz-linear-gradient(top, #eaf4fa 0, #b0d9ee 100%);
+ background-image: linear-gradient(to bottom, #eaf4fa 0, #b0d9ee 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffeaf4fa', endColorstr='#ffb0d9ee' )";
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive > .oo-ui-popupToolGroup-handle:hover,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive > .oo-ui-popupToolGroup-handle:focus {
+ border-color: #9dc2d4;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive.oo-ui-widget-enabled > .oo-ui-popupToolGroup-handle:active,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive.oo-ui-popupToolGroup-active > .oo-ui-popupToolGroup-handle {
+ border: 1px solid #a6cee1;
+ background-color: #cde7f4;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #b0d9ee), color-stop(100%, #eaf4fa));
+ background-image: -webkit-linear-gradient(top, #b0d9ee 0, #eaf4fa 100%);
+ background-image: -moz-linear-gradient(top, #b0d9ee 0, #eaf4fa 100%);
+ background-image: linear-gradient(to bottom, #b0d9ee 0, #eaf4fa 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffb0d9ee', endColorstr='#ffeaf4fa' )";
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive > .oo-ui-popupToolGroup-handle {
+ border: 1px solid #b8d892;
+ background-color: #daf0bd;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #f0fbe1), color-stop(100%, #c3e59a));
+ background-image: -webkit-linear-gradient(top, #f0fbe1 0, #c3e59a 100%);
+ background-image: -moz-linear-gradient(top, #f0fbe1 0, #c3e59a 100%);
+ background-image: linear-gradient(to bottom, #f0fbe1 0, #c3e59a 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#fff0fbe1', endColorstr='#ffc3e59a' )";
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive > .oo-ui-popupToolGroup-handle:hover,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive > .oo-ui-popupToolGroup-handle:focus {
+ border-color: #adcb89;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive.oo-ui-widget-enabled > .oo-ui-popupToolGroup-handle:active,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive.oo-ui-popupToolGroup-active > .oo-ui-popupToolGroup-handle {
+ border: 1px solid #b8d892;
+ background-color: #daf0bd;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #c3e59a), color-stop(100%, #f0fbe1));
+ background-image: -webkit-linear-gradient(top, #c3e59a 0, #f0fbe1 100%);
+ background-image: -moz-linear-gradient(top, #c3e59a 0, #f0fbe1 100%);
+ background-image: linear-gradient(to bottom, #c3e59a 0, #f0fbe1 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffc3e59a', endColorstr='#fff0fbe1' )";
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-destructive > .oo-ui-popupToolGroup-handle {
+ color: #d45353;
+}
+.oo-ui-buttonGroupWidget .oo-ui-popupToolGroup {
+ margin-left: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-popupToolGroup > .oo-ui-popupToolGroup-handle {
+ height: 2.4em;
+ border-radius: 0;
+ margin-left: -2px;
+}
+.oo-ui-buttonGroupWidget .oo-ui-popupToolGroup:first-child > .oo-ui-popupToolGroup-handle {
+ border-bottom-left-radius: 4px;
+ border-top-left-radius: 4px;
+ margin-left: 0;
+}
+.oo-ui-buttonGroupWidget .oo-ui-popupToolGroup:last-child {
+ margin-right: 0.5em;
+}
+.oo-ui-buttonGroupWidget .oo-ui-popupToolGroup:last-child > .oo-ui-popupToolGroup-handle {
+ border-bottom-right-radius: 4px;
+ border-top-right-radius: 4px;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator {
+ width: 0.9375em;
+ height: 0.9375em;
+ margin: 0.78125em;
+ top: 0;
+ right: 0;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator {
+ right: -0.3125em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ width: 1.875em;
+ height: 1.875em;
+ margin: 0.3125em;
+ top: 0;
+ left: 0.3125em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ left: 0;
+}
+.oo-ui-popupToolGroup-header {
+ line-height: 2.6em;
+ margin: 0 0.6em;
+ font-weight: bold;
+}
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ box-shadow: inset 0 0.0875em 0.0875em 0 rgba(0, 0, 0, 0.07);
+ background-color: #f8fbfd;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #f1f7fb), color-stop(100%, #fff));
+ background-image: -webkit-linear-gradient(top, #f1f7fb 0, #fff 100%);
+ background-image: -moz-linear-gradient(top, #f1f7fb 0, #fff 100%);
+ background-image: linear-gradient(to bottom, #f1f7fb 0, #fff 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#fff1f7fb', endColorstr='#ffffffff' )";
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+ margin: 0 -1px;
+ border: 1px solid #ccc;
+ background-color: #fff;
+ box-shadow: 0 0.3125em 1.25em rgba(0, 0, 0, 0.25);
+}
+.oo-ui-toolbar-position-top .oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+ top: 2.5em;
+}
+.oo-ui-toolbar-position-bottom .oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+ bottom: 2.5em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link {
+ padding: 0.3125em 0 0.3125em 0.3125em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+ height: 1.875em;
+ width: 1.875em;
+ min-width: 1.875em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+ padding-left: 0.5em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel,
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+ line-height: 2em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel {
+ color: #767676;
+}
+.oo-ui-listToolGroup .oo-ui-tool {
+ display: block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-listToolGroup .oo-ui-toolGroup-tools {
+ padding: 0.3125em;
+}
+.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
+ border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-listToolGroup .oo-ui-tool {
+ border: 1px solid transparent;
+ margin: -1px 0;
+ padding: 0 0.625em 0 0;
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled {
+ border-color: rgba(0, 0, 0, 0.1);
+ box-shadow: inset 0 0.0875em 0.0875em 0 rgba(0, 0, 0, 0.07);
+ background-color: #f8fbfd;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #f1f7fb), color-stop(100%, #fff));
+ background-image: -webkit-linear-gradient(top, #f1f7fb 0, #fff 100%);
+ background-image: -moz-linear-gradient(top, #f1f7fb 0, #fff 100%);
+ background-image: linear-gradient(to bottom, #f1f7fb 0, #fff 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#fff1f7fb', endColorstr='#ffffffff' )";
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
+ border-top-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled:hover {
+ border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+ border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 1;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
+ color: #ccc;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-accel {
+ color: #ddd;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-listToolGroup.oo-ui-widget-disabled {
+ color: #ccc;
+}
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator,
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-menuToolGroup {
+ border-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-menuToolGroup .oo-ui-tool {
+ display: block;
+}
+.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+ min-width: 10em;
+}
+.oo-ui-toolbar-narrow .oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+ min-width: 8.125em;
+}
+.oo-ui-menuToolGroup .oo-ui-toolGroup-tools {
+ padding: 0.3125em 0 0.3125em 0;
+}
+.oo-ui-menuToolGroup.oo-ui-widget-enabled:hover {
+ border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-menuToolGroup.oo-ui-popupToolGroup-active {
+ border-color: rgba(0, 0, 0, 0.25);
+}
+.oo-ui-menuToolGroup .oo-ui-tool {
+ padding: 0 1.25em 0 0.3125em;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+ background-image: none;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconElement-icon {
+ background-image: url('themes/apex/images/icons/check.png');
+ background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url('themes/apex/images/icons/check.svg');
+ background-image: linear-gradient(transparent, transparent), /* @embed */ url('themes/apex/images/icons/check.svg');
+ background-image: -o-linear-gradient(transparent, transparent), url('themes/apex/images/icons/check.png');
+ background-size: contain;
+ background-position: center center;
+ background-repeat: no-repeat;
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+ background-color: #e1f3ff;
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
+ color: #ccc;
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-menuToolGroup.oo-ui-widget-disabled {
+ color: #ccc;
+ border-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator,
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-toolbar {
+ clear: both;
+}
+.oo-ui-toolbar-bar {
+ line-height: 1;
+ position: relative;
+}
+.oo-ui-toolbar-tools,
+.oo-ui-toolbar-actions {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-toolbar-tools {
+ display: inline;
+ white-space: nowrap;
+}
+.oo-ui-toolbar-narrow .oo-ui-toolbar-tools {
+ white-space: normal;
+}
+.oo-ui-toolbar-tools .oo-ui-tool {
+ white-space: normal;
+}
+.oo-ui-toolbar-actions {
+ float: right;
+}
+.oo-ui-toolbar-actions .oo-ui-toolbar {
+ display: inline-block;
+}
+.oo-ui-toolbar-actions .oo-ui-popupWidget {
+ -webkit-touch-callout: default;
+ -webkit-user-select: all;
+ -moz-user-select: all;
+ -ms-user-select: all;
+ user-select: all;
+}
+.oo-ui-toolbar-bar {
+ background-color: #f8fbfd;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #fff), color-stop(100%, #f1f7fb));
+ background-image: -webkit-linear-gradient(top, #fff 0, #f1f7fb 100%);
+ background-image: -moz-linear-gradient(top, #fff 0, #f1f7fb 100%);
+ background-image: linear-gradient(to bottom, #fff 0, #f1f7fb 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffffff', endColorstr='#fff1f7fb' )";
+}
+.oo-ui-toolbar-position-top > .oo-ui-toolbar-bar {
+ border-bottom: 1px solid #ccc;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.1);
+}
+.oo-ui-toolbar-position-bottom > .oo-ui-toolbar-bar {
+ border-top: 1px solid #ccc;
+ box-shadow: 0 -2px 2px 0 rgba(0, 0, 0, 0.1);
+}
+.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
+ border: 0;
+ background: none;
+ box-shadow: none;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonElement-framed,
+.oo-ui-toolbar-actions > .oo-ui-buttonElement-framed:last-child {
+ margin-top: 0.4em;
+ margin-bottom: 0.4em;
+ margin-right: 0.5em;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonElement-frameless.oo-ui-labelElement,
+.oo-ui-toolbar-actions > .oo-ui-buttonElement-frameless:last-child.oo-ui-labelElement {
+ margin: 0;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonElement-frameless.oo-ui-labelElement > .oo-ui-buttonElement-button,
+.oo-ui-toolbar-actions > .oo-ui-buttonElement-frameless:last-child.oo-ui-labelElement > .oo-ui-buttonElement-button {
+ margin: 0;
+ padding: 0 0.3125em;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonElement-frameless.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
+.oo-ui-toolbar-actions > .oo-ui-buttonElement-frameless:last-child.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ margin: 0 1em;
+ line-height: 3.40625em;
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-mediawiki.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-mediawiki.css
new file mode 100644
index 00000000..1faf7e52
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-mediawiki.css
@@ -0,0 +1,459 @@
+/*!
+ * OOjs UI v0.17.1
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2016 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2016-05-03T22:58:06Z
+ */
+.oo-ui-popupTool .oo-ui-popupWidget-popup,
+.oo-ui-popupTool .oo-ui-popupWidget-anchor {
+ z-index: 4;
+}
+.oo-ui-popupTool .oo-ui-popupWidget {
+ /* @noflip */
+ margin-left: 1.25em;
+}
+.oo-ui-toolGroupTool > .oo-ui-popupToolGroup {
+ border: 0;
+ border-radius: 0;
+ margin: 0;
+}
+.oo-ui-toolGroupTool > .oo-ui-toolGroup {
+ border-right: none;
+}
+.oo-ui-toolGroupTool > .oo-ui-popupToolGroup > .oo-ui-popupToolGroup-handle {
+ height: 2.5em;
+ padding: 0.3125em;
+}
+.oo-ui-toolGroupTool > .oo-ui-popupToolGroup > .oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ height: 2.5em;
+ width: 1.875em;
+}
+.oo-ui-toolGroupTool > .oo-ui-popupToolGroup.oo-ui-labelElement > .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ line-height: 2.1em;
+}
+.oo-ui-toolGroup {
+ display: inline-block;
+ vertical-align: middle;
+ border-radius: 0;
+ border-right: 1px solid #dddddd;
+}
+.oo-ui-toolGroup-empty {
+ display: none;
+}
+.oo-ui-toolGroup .oo-ui-tool-link {
+ text-decoration: none;
+}
+.oo-ui-toolbar-narrow .oo-ui-toolGroup + .oo-ui-toolGroup {
+ margin-left: 0;
+}
+.oo-ui-toolGroup .oo-ui-toolGroup .oo-ui-widget-enabled {
+ border-right: none !important;
+}
+.oo-ui-barToolGroup > .oo-ui-iconElement-icon,
+.oo-ui-barToolGroup > .oo-ui-labelElement-label {
+ display: none;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link {
+ cursor: pointer;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool {
+ display: inline-block;
+ position: relative;
+ vertical-align: top;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link {
+ display: block;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-tool-accel {
+ display: none;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-iconElement > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ display: inline-block;
+ vertical-align: top;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-iconElement > .oo-ui-tool-link .oo-ui-tool-title {
+ display: none;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-iconElement.oo-ui-tool-with-label > .oo-ui-tool-link .oo-ui-tool-title {
+ display: inline;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link {
+ outline: 0;
+ cursor: default;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link {
+ height: 1.875em;
+ padding: 0.625em;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ height: 1.875em;
+ width: 1.875em;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-tool-title {
+ line-height: 2.1em;
+ padding: 0 0.4em;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled:hover {
+ border-color: rgba(0, 0, 0, 0.2);
+ background-color: #eeeeee;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool > a.oo-ui-tool-link .oo-ui-tool-title {
+ color: #555555;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-tool-active.oo-ui-widget-enabled {
+ border-color: rgba(0, 0, 0, 0.2);
+ box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+ background-color: #e5e5e5;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-tool-active.oo-ui-widget-enabled:hover {
+ background-color: #eeeeee;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
+ border-left-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link .oo-ui-tool-title {
+ color: #cccccc;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.7;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled:hover > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.9;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled:active {
+ background-color: #e7e7e7;
+}
+.oo-ui-barToolGroup.oo-ui-widget-disabled > .oo-ui-toolGroup-tools > .oo-ui-tool > a.oo-ui-tool-link .oo-ui-tool-title {
+ color: #cccccc;
+}
+.oo-ui-barToolGroup.oo-ui-widget-disabled > .oo-ui-toolGroup-tools > .oo-ui-tool > a.oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-popupToolGroup {
+ position: relative;
+ height: 3.125em;
+ min-width: 2em;
+}
+.oo-ui-popupToolGroup-handle {
+ display: block;
+ cursor: pointer;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ position: absolute;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
+ outline: 0;
+ cursor: default;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+ display: none;
+ position: absolute;
+ z-index: 4;
+}
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled > .oo-ui-toolGroup-tools {
+ display: block;
+}
+.oo-ui-popupToolGroup-left > .oo-ui-toolGroup-tools {
+ left: 0;
+}
+.oo-ui-popupToolGroup-right > .oo-ui-toolGroup-tools {
+ right: 0;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link {
+ display: table;
+ width: 100%;
+ vertical-align: middle;
+ white-space: nowrap;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon,
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel,
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+ display: table-cell;
+ vertical-align: middle;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel {
+ text-align: right;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel:not(:empty) {
+ padding-left: 3em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup {
+ min-width: 1.875em;
+}
+.oo-ui-popupToolGroup.oo-ui-iconElement {
+ min-width: 3.125em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-iconElement {
+ min-width: 2.5em;
+}
+.oo-ui-popupToolGroup.oo-ui-indicatorElement.oo-ui-iconElement {
+ min-width: 4.375em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-indicatorElement.oo-ui-iconElement {
+ min-width: 3.75em;
+}
+.oo-ui-popupToolGroup.oo-ui-labelElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ line-height: 2.6em;
+ margin: 0 1em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-labelElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin: 0 0.5em;
+}
+.oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-iconElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-left: 3em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-iconElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-left: 2.5em;
+}
+.oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-indicatorElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-right: 2em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-indicatorElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-right: 1.75em;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-enabled .oo-ui-popupToolGroup-handle:hover {
+ background-color: #eeeeee;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-enabled .oo-ui-popupToolGroup-handle:active {
+ background-color: #e5e5e5;
+}
+.oo-ui-popupToolGroup-handle {
+ padding: 0.3125em;
+ height: 2.5em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator {
+ width: 0.9375em;
+ height: 1.625em;
+ margin: 0.78125em 0.5em;
+ top: 0;
+ right: 0;
+ opacity: 0.3;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator {
+ right: -0.3125em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ width: 1.875em;
+ height: 2.6em;
+ margin: 0.25em;
+ top: 0;
+ left: 0.3125em;
+ opacity: 0.7;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ left: 0;
+}
+.oo-ui-popupToolGroup-header {
+ line-height: 2.6em;
+ margin: 0 0.6em;
+ font-weight: bold;
+}
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled {
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+ box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+ background-color: #eeeeee;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+ top: 3.125em;
+ margin: 0 -1px;
+ border: 1px solid #cccccc;
+ background-color: #ffffff;
+ box-shadow: 0 2px 3px rgba(0, 0, 0, 0.2);
+ min-width: 16em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link {
+ padding: 0.4em 0.625em;
+ box-sizing: border-box;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+ height: 2.5em;
+ width: 1.875em;
+ min-width: 1.875em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+ padding-left: 0.5em;
+ color: #555555;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel,
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+ line-height: 2em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel {
+ color: #888888;
+}
+.oo-ui-listToolGroup .oo-ui-tool {
+ display: block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-listToolGroup .oo-ui-tool-link {
+ cursor: pointer;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+ cursor: default;
+}
+.oo-ui-listToolGroup.oo-ui-popupToolGroup-active {
+ border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+ border-color: rgba(0, 0, 0, 0.2);
+ background-color: #eeeeee;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:active {
+ background-color: #e7e7e7;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.9;
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled {
+ border-color: rgba(0, 0, 0, 0.1);
+ box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+ background-color: #e5e5e5;
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled + .oo-ui-tool-active.oo-ui-widget-enabled {
+ border-top-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled:hover {
+ border-color: rgba(0, 0, 0, 0.2);
+ background-color: #eeeeee;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
+ color: #cccccc;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-accel {
+ color: #dddddd;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-listToolGroup.oo-ui-widget-disabled {
+ color: #cccccc;
+}
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator,
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-menuToolGroup .oo-ui-tool {
+ display: block;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link {
+ cursor: pointer;
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link {
+ cursor: default;
+}
+.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+ min-width: 10em;
+}
+.oo-ui-toolbar-narrow .oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+ min-width: 8.125em;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+ background-image: none;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconElement-icon {
+ background-image: url("themes/mediawiki/images/icons/check.png");
+ background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check.svg");
+ background-image: linear-gradient(transparent, transparent), /* @embed */ url("themes/mediawiki/images/icons/check.svg");
+ background-image: -o-linear-gradient(transparent, transparent), url("themes/mediawiki/images/icons/check.png");
+ background-size: contain;
+ background-position: center center;
+ background-repeat: no-repeat;
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+ background-color: #eeeeee;
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-tool-title {
+ color: #cccccc;
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-menuToolGroup.oo-ui-widget-disabled {
+ color: #cccccc;
+}
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator,
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-iconElement-icon {
+ opacity: 0.2;
+}
+.oo-ui-toolbar {
+ clear: both;
+}
+.oo-ui-toolbar-bar {
+ line-height: 1em;
+ position: relative;
+}
+.oo-ui-toolbar-actions {
+ float: right;
+}
+.oo-ui-toolbar-actions .oo-ui-toolbar {
+ display: inline-block;
+}
+.oo-ui-toolbar-tools {
+ display: inline;
+ white-space: nowrap;
+}
+.oo-ui-toolbar-narrow .oo-ui-toolbar-tools {
+ white-space: normal;
+}
+.oo-ui-toolbar-tools .oo-ui-tool {
+ white-space: normal;
+}
+.oo-ui-toolbar-tools,
+.oo-ui-toolbar-actions,
+.oo-ui-toolbar-shadow {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-toolbar-actions .oo-ui-popupWidget {
+ -webkit-touch-callout: default;
+ -webkit-user-select: all;
+ -moz-user-select: all;
+ -ms-user-select: all;
+ user-select: all;
+}
+.oo-ui-toolbar-shadow {
+ background-position: left top;
+ background-repeat: repeat-x;
+ position: absolute;
+ width: 100%;
+ pointer-events: none;
+}
+.oo-ui-toolbar-bar {
+ border-bottom: 1px solid #cccccc;
+ background-color: #ffffff;
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
+ font-weight: 500;
+ color: #555555;
+}
+.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
+ border: 0;
+ background: none;
+ box-shadow: none;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonElement.oo-ui-labelElement {
+ margin: 0;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonElement.oo-ui-labelElement > .oo-ui-buttonElement-button {
+ border: 0;
+ border-radius: 0;
+ margin: 0;
+ padding: 0 0.3125em;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ margin: 0 1em;
+ line-height: 3.125em;
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-wikimediaui.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-wikimediaui.css
new file mode 100644
index 00000000..ab60c4e1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars-wikimediaui.css
@@ -0,0 +1,540 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:24:03Z
+ */
+/**
+ * WikimediaUI Base v0.9.2
+ * Wikimedia Foundation user interface base variables
+ */
+/* Colors */
+/* Positioning */
+/* Box Model properties */
+/* Max Widths */
+/* Typography incl. print properties */
+/* Other Properties */
+/* Animation & Transition */
+.oo-ui-tool.oo-ui-widget-enabled {
+ -webkit-transition: background-color 100ms;
+ -moz-transition: background-color 100ms;
+ transition: background-color 100ms;
+}
+.oo-ui-tool.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-tool-title {
+ -webkit-transition: color 100ms;
+ -moz-transition: color 100ms;
+ transition: color 100ms;
+}
+.oo-ui-popupTool .oo-ui-popupWidget-popup,
+.oo-ui-popupTool .oo-ui-popupWidget-anchor {
+ z-index: 4;
+}
+.oo-ui-toolGroupTool > .oo-ui-toolGroup {
+ border-right: 0;
+}
+.oo-ui-toolGroupTool > .oo-ui-popupToolGroup > .oo-ui-popupToolGroup-handle {
+ height: 2.5em;
+ padding: 0.3125em;
+}
+.oo-ui-toolGroupTool > .oo-ui-popupToolGroup > .oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ height: 2.5em;
+ width: 1.875em;
+}
+.oo-ui-toolGroup {
+ display: inline-block;
+ vertical-align: middle;
+ border-right: 1px solid #c8ccd1;
+}
+.oo-ui-toolGroup-empty {
+ display: none;
+}
+.oo-ui-toolGroup .oo-ui-tool-link {
+ text-decoration: none;
+ cursor: pointer;
+}
+.oo-ui-toolGroup.oo-ui-widget-disabled .oo-ui-tool-link,
+.oo-ui-toolGroup .oo-ui-widget-disabled > .oo-ui-tool-link {
+ outline: 0;
+ cursor: default;
+}
+.oo-ui-toolbar-actions .oo-ui-toolGroup {
+ border-right: 0;
+ border-left: 1px solid #c8ccd1;
+}
+.oo-ui-toolbar-narrow .oo-ui-toolGroup + .oo-ui-toolGroup {
+ margin-left: 0;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool {
+ display: inline-block;
+ position: relative;
+ vertical-align: top;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link {
+ display: block;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-tool-accel {
+ display: none;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-iconElement > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ display: inline-block;
+ vertical-align: top;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-iconElement > .oo-ui-tool-link .oo-ui-tool-title {
+ display: none;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-iconElement.oo-ui-tool-with-label > .oo-ui-tool-link .oo-ui-tool-title {
+ display: inline;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link {
+ height: 1.875em;
+ padding: 0.625em;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ height: 1.875em;
+ width: 1.875em;
+}
+.oo-ui-barToolGroup > .oo-ui-toolGroup-tools > .oo-ui-tool > .oo-ui-tool-link .oo-ui-tool-title {
+ line-height: 2.1;
+ padding: 0 0.4em;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled:hover {
+ background-color: #eaecf0;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled > .oo-ui-tool-link .oo-ui-tool-title {
+ color: #222;
+ -webkit-transition: color 100ms;
+ -moz-transition: color 100ms;
+ transition: color 100ms;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled.oo-ui-tool-active {
+ background-color: #eaf3ff;
+ box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled.oo-ui-tool-active:hover {
+ background-color: rgba(41, 98, 204, 0.1);
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled > .oo-ui-toolGroup-tools > .oo-ui-tool.oo-ui-widget-enabled.oo-ui-tool-active > .oo-ui-tool-link .oo-ui-tool-title {
+ color: #36c;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link .oo-ui-tool-title,
+.oo-ui-barToolGroup.oo-ui-widget-disabled .oo-ui-tool > .oo-ui-tool-link .oo-ui-tool-title {
+ color: #72777d;
+}
+.oo-ui-barToolGroup.oo-ui-widget-enabled .oo-ui-tool.oo-ui-widget-disabled > .oo-ui-tool-link .oo-ui-iconElement-icon,
+.oo-ui-barToolGroup.oo-ui-widget-disabled .oo-ui-tool > .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.3;
+}
+.oo-ui-popupToolGroup {
+ position: relative;
+ height: 3.125em;
+ min-width: 2em;
+}
+.oo-ui-popupToolGroup-handle {
+ display: block;
+ cursor: pointer;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator,
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ position: absolute;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-disabled .oo-ui-popupToolGroup-handle {
+ outline: 0;
+ cursor: default;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+ display: none;
+ position: absolute;
+ z-index: 4;
+}
+.oo-ui-popupToolGroup-active.oo-ui-widget-enabled > .oo-ui-toolGroup-tools {
+ display: block;
+}
+.oo-ui-popupToolGroup-left > .oo-ui-toolGroup-tools {
+ left: 0;
+}
+.oo-ui-popupToolGroup-right > .oo-ui-toolGroup-tools {
+ right: 0;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link {
+ display: table;
+ width: 100%;
+ vertical-align: middle;
+ white-space: nowrap;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon,
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel,
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+ display: table-cell;
+ vertical-align: middle;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel {
+ text-align: right;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel:not( :empty ) {
+ padding-left: 3em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup {
+ min-width: 1.875em;
+}
+.oo-ui-popupToolGroup.oo-ui-iconElement {
+ min-width: 3.125em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-iconElement {
+ min-width: 2.5em;
+}
+.oo-ui-popupToolGroup.oo-ui-indicatorElement.oo-ui-iconElement {
+ min-width: 4.375em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-indicatorElement.oo-ui-iconElement {
+ min-width: 3.75em;
+}
+.oo-ui-popupToolGroup.oo-ui-labelElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ line-height: 2.6;
+ margin: 0 1em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-labelElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin: 0 0.5em;
+}
+.oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-iconElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-left: 3em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-iconElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-left: 2.5em;
+}
+.oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-indicatorElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-right: 2em;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup.oo-ui-labelElement.oo-ui-indicatorElement .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin-right: 1.75em;
+}
+.oo-ui-popupToolGroup.oo-ui-labelElement:not( .oo-ui-indicatorElement ) .oo-ui-popupToolGroup-handle .oo-ui-labelElement-label {
+ margin: 0 0.5em;
+}
+.oo-ui-popupToolGroup-header {
+ line-height: 2.6;
+ margin: 0 0.6em;
+ font-weight: bold;
+}
+.oo-ui-popupToolGroup-handle {
+ padding: 0.3125em;
+ height: 2.5em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator {
+ top: 0;
+ right: 0;
+ width: 0.9375em;
+ height: 100%;
+ margin: 0 0.5em;
+ opacity: 0.87;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup-handle .oo-ui-indicatorElement-indicator {
+ right: -0.3125em;
+}
+.oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ width: 1.875em;
+ height: 2.6em;
+ margin: 0.25em;
+ top: 0;
+ left: 0.3125em;
+ opacity: 0.7;
+}
+.oo-ui-toolbar-narrow .oo-ui-popupToolGroup-handle .oo-ui-iconElement-icon {
+ left: 0;
+}
+.oo-ui-popupToolGroup:not( .oo-ui-labelElement ):not( .oo-ui-iconElement ) .oo-ui-indicatorElement-indicator {
+ opacity: 1;
+}
+.oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+ margin: 0 -1px;
+ border: 1px solid #c8ccd1;
+ background-color: #fff;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.25);
+ min-width: 16em;
+}
+.oo-ui-toolbar-position-top .oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+ top: 3.125em;
+}
+.oo-ui-toolbar-position-bottom .oo-ui-popupToolGroup .oo-ui-toolGroup-tools {
+ bottom: 3.125em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link {
+ padding: 0.4em 0.625em;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+ height: 2.5em;
+ width: 1.875em;
+ min-width: 1.875em;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-title {
+ padding-left: 0.5em;
+ color: #222;
+}
+.oo-ui-popupToolGroup .oo-ui-tool-link .oo-ui-tool-accel {
+ color: #72777d;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-enabled {
+ -webkit-transition: background-color 100ms, box-shadow 100ms;
+ -moz-transition: background-color 100ms, box-shadow 100ms;
+ transition: background-color 100ms, box-shadow 100ms;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-enabled.oo-ui-popupToolGroup-active {
+ box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+ background-color: #eaecf0;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-enabled.oo-ui-popupToolGroup-active .oo-ui-tool-active.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-tool-title {
+ color: #36c;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-enabled > .oo-ui-popupToolGroup-handle {
+ -webkit-transition: background-color 100ms, box-shadow 100ms;
+ -moz-transition: background-color 100ms, box-shadow 100ms;
+ transition: background-color 100ms, box-shadow 100ms;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-enabled > .oo-ui-popupToolGroup-handle:hover {
+ background-color: #eaecf0;
+}
+.oo-ui-popupToolGroup.oo-ui-widget-enabled > .oo-ui-popupToolGroup-handle:active {
+ background-color: #eaf3ff;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive > .oo-ui-popupToolGroup-handle {
+ color: #fff;
+ background-color: #36c;
+ border-color: #36c;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive > .oo-ui-popupToolGroup-handle:hover {
+ background-color: #447ff5;
+ border-color: #447ff5;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive > .oo-ui-popupToolGroup-handle:active,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive > .oo-ui-popupToolGroup-handle:active:focus,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive.oo-ui-buttonElement-pressed > .oo-ui-popupToolGroup-handle,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive.oo-ui-buttonElement-active > .oo-ui-popupToolGroup-handle,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive.oo-ui-popupToolGroup-active > .oo-ui-popupToolGroup-handle {
+ color: #fff;
+ background-color: #2a4b8d;
+ border-color: #2a4b8d;
+ box-shadow: none;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-progressive > .oo-ui-popupToolGroup-handle:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c, inset 0 0 0 2px #fff;
+ outline: 0;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive > .oo-ui-popupToolGroup-handle {
+ color: #fff;
+ background-color: #36c;
+ border-color: #36c;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive > .oo-ui-popupToolGroup-handle:hover {
+ background-color: #447ff5;
+ border-color: #447ff5;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive > .oo-ui-popupToolGroup-handle:active,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive > .oo-ui-popupToolGroup-handle:active:focus,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-pressed > .oo-ui-popupToolGroup-handle,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive.oo-ui-buttonElement-active > .oo-ui-popupToolGroup-handle,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive.oo-ui-popupToolGroup-active > .oo-ui-popupToolGroup-handle {
+ color: #fff;
+ background-color: #2a4b8d;
+ border-color: #2a4b8d;
+ box-shadow: none;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-constructive > .oo-ui-popupToolGroup-handle:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c, inset 0 0 0 2px #fff;
+ outline: 0;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-destructive > .oo-ui-popupToolGroup-handle {
+ color: #fff;
+ background-color: #d33;
+ border-color: #d33;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-destructive > .oo-ui-popupToolGroup-handle:hover {
+ background-color: #ff4242;
+ border-color: #ff4242;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-destructive > .oo-ui-popupToolGroup-handle:active,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-destructive > .oo-ui-popupToolGroup-handle:active:focus,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-pressed > .oo-ui-popupToolGroup-handle,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-destructive.oo-ui-buttonElement-active > .oo-ui-popupToolGroup-handle,
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-destructive.oo-ui-popupToolGroup-active > .oo-ui-popupToolGroup-handle {
+ color: #fff;
+ background-color: #b32424;
+ border-color: #b32424;
+ box-shadow: none;
+}
+.oo-ui-popupToolGroup.oo-ui-flaggedElement-destructive > .oo-ui-popupToolGroup-handle:focus {
+ border-color: #d33;
+ box-shadow: inset 0 0 0 1px #d33, inset 0 0 0 2px #fff;
+ outline: 0;
+}
+.oo-ui-listToolGroup .oo-ui-tool {
+ display: block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+ background-color: #eaecf0;
+}
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover .oo-ui-tool-link .oo-ui-iconElement-icon {
+ opacity: 0.9;
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled {
+ background-color: #eaf3ff;
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled:first-child {
+ box-shadow: inset 0 0.07em 0.07em 0 rgba(0, 0, 0, 0.07);
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled:hover {
+ background-color: rgba(41, 98, 204, 0.1);
+}
+.oo-ui-listToolGroup .oo-ui-tool-active.oo-ui-widget-enabled .oo-ui-tool-link .oo-ui-tool-title {
+ color: #36c;
+}
+.oo-ui-listToolGroup.oo-ui-widget-disabled,
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-title {
+ color: #72777d;
+}
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator,
+.oo-ui-listToolGroup.oo-ui-widget-disabled .oo-ui-iconElement-icon,
+.oo-ui-listToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-iconElement-icon {
+ opacity: 0.3;
+}
+.oo-ui-menuToolGroup .oo-ui-tool {
+ display: block;
+}
+.oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+ min-width: 10em;
+}
+.oo-ui-toolbar-narrow .oo-ui-menuToolGroup .oo-ui-popupToolGroup-handle {
+ min-width: 8.125em;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-link .oo-ui-iconElement-icon {
+ background-image: none;
+}
+.oo-ui-menuToolGroup .oo-ui-tool-active .oo-ui-tool-link .oo-ui-iconElement-icon {
+ background-image: url('themes/wikimediaui/images/icons/check-progressive.png');
+ background-image: -webkit-linear-gradient(transparent, transparent), /* @embed */ url('themes/wikimediaui/images/icons/check-progressive.svg');
+ background-image: linear-gradient(transparent, transparent), /* @embed */ url('themes/wikimediaui/images/icons/check-progressive.svg');
+ background-image: -o-linear-gradient(transparent, transparent), url('themes/wikimediaui/images/icons/check-progressive.png');
+ background-size: contain;
+ background-position: center center;
+ background-repeat: no-repeat;
+}
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-enabled:hover {
+ background-color: rgba(41, 98, 204, 0.1);
+}
+.oo-ui-menuToolGroup .oo-ui-tool-name-menuTool.oo-ui-tool-active {
+ background-color: #eaf3ff;
+}
+.oo-ui-menuToolGroup.oo-ui-widget-disabled,
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-tool-title {
+ color: #72777d;
+}
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-indicatorElement-indicator,
+.oo-ui-menuToolGroup.oo-ui-widget-disabled .oo-ui-iconElement-icon,
+.oo-ui-menuToolGroup .oo-ui-tool.oo-ui-widget-disabled .oo-ui-iconElement-icon {
+ opacity: 0.3;
+}
+.oo-ui-toolbar {
+ clear: both;
+}
+.oo-ui-toolbar-bar {
+ line-height: 1;
+ position: relative;
+}
+.oo-ui-toolbar-tools,
+.oo-ui-toolbar-actions {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-toolbar-tools {
+ display: inline;
+ white-space: nowrap;
+}
+.oo-ui-toolbar-narrow .oo-ui-toolbar-tools {
+ white-space: normal;
+}
+.oo-ui-toolbar-tools .oo-ui-tool {
+ white-space: normal;
+}
+.oo-ui-toolbar-actions {
+ float: right;
+}
+.oo-ui-toolbar-actions .oo-ui-toolbar {
+ display: inline-block;
+}
+.oo-ui-toolbar-actions .oo-ui-popupWidget {
+ -webkit-touch-callout: default;
+ -webkit-user-select: all;
+ -moz-user-select: all;
+ -ms-user-select: all;
+ user-select: all;
+}
+.oo-ui-toolbar-bar {
+ background-color: #fff;
+ color: #222;
+}
+.oo-ui-toolbar-position-top > .oo-ui-toolbar-bar {
+ border-bottom: 1px solid #c8ccd1;
+ box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
+}
+.oo-ui-toolbar-position-bottom > .oo-ui-toolbar-bar {
+ border-top: 1px solid #c8ccd1;
+ box-shadow: 0 -1px 1px 0 rgba(0, 0, 0, 0.1);
+}
+.oo-ui-toolbar-bar .oo-ui-toolbar-bar {
+ border: 0;
+ background-color: transparent;
+ box-shadow: none;
+}
+.oo-ui-toolbar-narrow .oo-ui-toolbar-bar:after {
+ content: '';
+ display: block;
+ position: absolute;
+ top: 3.125em;
+ left: 0;
+ width: 100%;
+ height: 0;
+ border-bottom: 1px solid #c8ccd1;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonElement.oo-ui-labelElement,
+.oo-ui-toolbar-actions > .oo-ui-buttonElement.oo-ui-indicatorElement,
+.oo-ui-toolbar-actions > .oo-ui-buttonGroupWidget > .oo-ui-buttonElement.oo-ui-labelElement,
+.oo-ui-toolbar-actions > .oo-ui-buttonGroupWidget > .oo-ui-buttonElement.oo-ui-indicatorElement {
+ margin: 0;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonElement.oo-ui-labelElement > .oo-ui-buttonElement-button,
+.oo-ui-toolbar-actions > .oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button,
+.oo-ui-toolbar-actions > .oo-ui-buttonGroupWidget > .oo-ui-buttonElement.oo-ui-labelElement > .oo-ui-buttonElement-button,
+.oo-ui-toolbar-actions > .oo-ui-buttonGroupWidget > .oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button {
+ border: 0;
+ border-radius: 0;
+ padding: 0 0.3125em;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
+.oo-ui-toolbar-actions > .oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
+.oo-ui-toolbar-actions > .oo-ui-buttonGroupWidget > .oo-ui-buttonElement.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label,
+.oo-ui-toolbar-actions > .oo-ui-buttonGroupWidget > .oo-ui-buttonElement.oo-ui-indicatorElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ margin: 0 1em;
+ line-height: 3.125em;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonGroupWidget > .oo-ui-buttonElement.oo-ui-indicatorElement:not( .oo-ui-labelElement ) > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ margin: 0;
+}
+.oo-ui-toolbar-actions > .oo-ui-buttonGroupWidget > .oo-ui-buttonElement.oo-ui-indicatorElement:not( .oo-ui-labelElement ) > .oo-ui-buttonElement-button > .oo-ui-indicatorElement-indicator {
+ margin: 0 0.3125em;
+}
+.oo-ui-toolbar-actions > .oo-ui-toolbar:not( :last-child ) {
+ border-right: 1px solid #c8ccd1;
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars.js b/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars.js
new file mode 100644
index 00000000..8d20835e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars.js
@@ -0,0 +1,2366 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:23:58Z
+ */
+( function ( OO ) {
+
+'use strict';
+
+/**
+ * Toolbars are complex interface components that permit users to easily access a variety
+ * of {@link OO.ui.Tool tools} (e.g., formatting commands) and actions, which are additional commands that are
+ * part of the toolbar, but not configured as tools.
+ *
+ * Individual tools are customized and then registered with a {@link OO.ui.ToolFactory tool factory}, which creates
+ * the tools on demand. Each tool has a symbolic name (used when registering the tool), a title (e.g., ‘Insert
+ * image’), and an icon.
+ *
+ * Individual tools are organized in {@link OO.ui.ToolGroup toolgroups}, which can be {@link OO.ui.MenuToolGroup menus}
+ * of tools, {@link OO.ui.ListToolGroup lists} of tools, or a single {@link OO.ui.BarToolGroup bar} of tools.
+ * The arrangement and order of the toolgroups is customized when the toolbar is set up. Tools can be presented in
+ * any order, but each can only appear once in the toolbar.
+ *
+ * The toolbar can be synchronized with the state of the external "application", like a text
+ * editor's editing area, marking tools as active/inactive (e.g. a 'bold' tool would be shown as
+ * active when the text cursor was inside bolded text) or enabled/disabled (e.g. a table caption
+ * tool would be disabled while the user is not editing a table). A state change is signalled by
+ * emitting the {@link #event-updateState 'updateState' event}, which calls Tools'
+ * {@link OO.ui.Tool#onUpdateState onUpdateState method}.
+ *
+ * The following is an example of a basic toolbar.
+ *
+ * @example
+ * // Example of a toolbar
+ * // Create the toolbar
+ * var toolFactory = new OO.ui.ToolFactory();
+ * var toolGroupFactory = new OO.ui.ToolGroupFactory();
+ * var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory );
+ *
+ * // We will be placing status text in this element when tools are used
+ * var $area = $( '<p>' ).text( 'Toolbar example' );
+ *
+ * // Define the tools that we're going to place in our toolbar
+ *
+ * // Create a class inheriting from OO.ui.Tool
+ * function SearchTool() {
+ * SearchTool.parent.apply( this, arguments );
+ * }
+ * OO.inheritClass( SearchTool, OO.ui.Tool );
+ * // Each tool must have a 'name' (used as an internal identifier, see later) and at least one
+ * // of 'icon' and 'title' (displayed icon and text).
+ * SearchTool.static.name = 'search';
+ * SearchTool.static.icon = 'search';
+ * SearchTool.static.title = 'Search...';
+ * // Defines the action that will happen when this tool is selected (clicked).
+ * SearchTool.prototype.onSelect = function () {
+ * $area.text( 'Search tool clicked!' );
+ * // Never display this tool as "active" (selected).
+ * this.setActive( false );
+ * };
+ * SearchTool.prototype.onUpdateState = function () {};
+ * // Make this tool available in our toolFactory and thus our toolbar
+ * toolFactory.register( SearchTool );
+ *
+ * // Register two more tools, nothing interesting here
+ * function SettingsTool() {
+ * SettingsTool.parent.apply( this, arguments );
+ * }
+ * OO.inheritClass( SettingsTool, OO.ui.Tool );
+ * SettingsTool.static.name = 'settings';
+ * SettingsTool.static.icon = 'settings';
+ * SettingsTool.static.title = 'Change settings';
+ * SettingsTool.prototype.onSelect = function () {
+ * $area.text( 'Settings tool clicked!' );
+ * this.setActive( false );
+ * };
+ * SettingsTool.prototype.onUpdateState = function () {};
+ * toolFactory.register( SettingsTool );
+ *
+ * // Register two more tools, nothing interesting here
+ * function StuffTool() {
+ * StuffTool.parent.apply( this, arguments );
+ * }
+ * OO.inheritClass( StuffTool, OO.ui.Tool );
+ * StuffTool.static.name = 'stuff';
+ * StuffTool.static.icon = 'ellipsis';
+ * StuffTool.static.title = 'More stuff';
+ * StuffTool.prototype.onSelect = function () {
+ * $area.text( 'More stuff tool clicked!' );
+ * this.setActive( false );
+ * };
+ * StuffTool.prototype.onUpdateState = function () {};
+ * toolFactory.register( StuffTool );
+ *
+ * // This is a PopupTool. Rather than having a custom 'onSelect' action, it will display a
+ * // little popup window (a PopupWidget).
+ * function HelpTool( toolGroup, config ) {
+ * OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {
+ * padded: true,
+ * label: 'Help',
+ * head: true
+ * } }, config ) );
+ * this.popup.$body.append( '<p>I am helpful!</p>' );
+ * }
+ * OO.inheritClass( HelpTool, OO.ui.PopupTool );
+ * HelpTool.static.name = 'help';
+ * HelpTool.static.icon = 'help';
+ * HelpTool.static.title = 'Help';
+ * toolFactory.register( HelpTool );
+ *
+ * // Finally define which tools and in what order appear in the toolbar. Each tool may only be
+ * // used once (but not all defined tools must be used).
+ * toolbar.setup( [
+ * {
+ * // 'bar' tool groups display tools' icons only, side-by-side.
+ * type: 'bar',
+ * include: [ 'search', 'help' ]
+ * },
+ * {
+ * // 'list' tool groups display both the titles and icons, in a dropdown list.
+ * type: 'list',
+ * indicator: 'down',
+ * label: 'More',
+ * include: [ 'settings', 'stuff' ]
+ * }
+ * // Note how the tools themselves are toolgroup-agnostic - the same tool can be displayed
+ * // either in a 'list' or a 'bar'. There is a 'menu' tool group too, not showcased here,
+ * // since it's more complicated to use. (See the next example snippet on this page.)
+ * ] );
+ *
+ * // Create some UI around the toolbar and place it in the document
+ * var frame = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * framed: true
+ * } );
+ * var contentFrame = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * padded: true
+ * } );
+ * frame.$element.append(
+ * toolbar.$element,
+ * contentFrame.$element.append( $area )
+ * );
+ * $( 'body' ).append( frame.$element );
+ *
+ * // Here is where the toolbar is actually built. This must be done after inserting it into the
+ * // document.
+ * toolbar.initialize();
+ * toolbar.emit( 'updateState' );
+ *
+ * The following example extends the previous one to illustrate 'menu' toolgroups and the usage of
+ * {@link #event-updateState 'updateState' event}.
+ *
+ * @example
+ * // Create the toolbar
+ * var toolFactory = new OO.ui.ToolFactory();
+ * var toolGroupFactory = new OO.ui.ToolGroupFactory();
+ * var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory );
+ *
+ * // We will be placing status text in this element when tools are used
+ * var $area = $( '<p>' ).text( 'Toolbar example' );
+ *
+ * // Define the tools that we're going to place in our toolbar
+ *
+ * // Create a class inheriting from OO.ui.Tool
+ * function SearchTool() {
+ * SearchTool.parent.apply( this, arguments );
+ * }
+ * OO.inheritClass( SearchTool, OO.ui.Tool );
+ * // Each tool must have a 'name' (used as an internal identifier, see later) and at least one
+ * // of 'icon' and 'title' (displayed icon and text).
+ * SearchTool.static.name = 'search';
+ * SearchTool.static.icon = 'search';
+ * SearchTool.static.title = 'Search...';
+ * // Defines the action that will happen when this tool is selected (clicked).
+ * SearchTool.prototype.onSelect = function () {
+ * $area.text( 'Search tool clicked!' );
+ * // Never display this tool as "active" (selected).
+ * this.setActive( false );
+ * };
+ * SearchTool.prototype.onUpdateState = function () {};
+ * // Make this tool available in our toolFactory and thus our toolbar
+ * toolFactory.register( SearchTool );
+ *
+ * // Register two more tools, nothing interesting here
+ * function SettingsTool() {
+ * SettingsTool.parent.apply( this, arguments );
+ * this.reallyActive = false;
+ * }
+ * OO.inheritClass( SettingsTool, OO.ui.Tool );
+ * SettingsTool.static.name = 'settings';
+ * SettingsTool.static.icon = 'settings';
+ * SettingsTool.static.title = 'Change settings';
+ * SettingsTool.prototype.onSelect = function () {
+ * $area.text( 'Settings tool clicked!' );
+ * // Toggle the active state on each click
+ * this.reallyActive = !this.reallyActive;
+ * this.setActive( this.reallyActive );
+ * // To update the menu label
+ * this.toolbar.emit( 'updateState' );
+ * };
+ * SettingsTool.prototype.onUpdateState = function () {};
+ * toolFactory.register( SettingsTool );
+ *
+ * // Register two more tools, nothing interesting here
+ * function StuffTool() {
+ * StuffTool.parent.apply( this, arguments );
+ * this.reallyActive = false;
+ * }
+ * OO.inheritClass( StuffTool, OO.ui.Tool );
+ * StuffTool.static.name = 'stuff';
+ * StuffTool.static.icon = 'ellipsis';
+ * StuffTool.static.title = 'More stuff';
+ * StuffTool.prototype.onSelect = function () {
+ * $area.text( 'More stuff tool clicked!' );
+ * // Toggle the active state on each click
+ * this.reallyActive = !this.reallyActive;
+ * this.setActive( this.reallyActive );
+ * // To update the menu label
+ * this.toolbar.emit( 'updateState' );
+ * };
+ * StuffTool.prototype.onUpdateState = function () {};
+ * toolFactory.register( StuffTool );
+ *
+ * // This is a PopupTool. Rather than having a custom 'onSelect' action, it will display a
+ * // little popup window (a PopupWidget). 'onUpdateState' is also already implemented.
+ * function HelpTool( toolGroup, config ) {
+ * OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {
+ * padded: true,
+ * label: 'Help',
+ * head: true
+ * } }, config ) );
+ * this.popup.$body.append( '<p>I am helpful!</p>' );
+ * }
+ * OO.inheritClass( HelpTool, OO.ui.PopupTool );
+ * HelpTool.static.name = 'help';
+ * HelpTool.static.icon = 'help';
+ * HelpTool.static.title = 'Help';
+ * toolFactory.register( HelpTool );
+ *
+ * // Finally define which tools and in what order appear in the toolbar. Each tool may only be
+ * // used once (but not all defined tools must be used).
+ * toolbar.setup( [
+ * {
+ * // 'bar' tool groups display tools' icons only, side-by-side.
+ * type: 'bar',
+ * include: [ 'search', 'help' ]
+ * },
+ * {
+ * // 'menu' tool groups display both the titles and icons, in a dropdown menu.
+ * // Menu label indicates which items are selected.
+ * type: 'menu',
+ * indicator: 'down',
+ * include: [ 'settings', 'stuff' ]
+ * }
+ * ] );
+ *
+ * // Create some UI around the toolbar and place it in the document
+ * var frame = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * framed: true
+ * } );
+ * var contentFrame = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * padded: true
+ * } );
+ * frame.$element.append(
+ * toolbar.$element,
+ * contentFrame.$element.append( $area )
+ * );
+ * $( 'body' ).append( frame.$element );
+ *
+ * // Here is where the toolbar is actually built. This must be done after inserting it into the
+ * // document.
+ * toolbar.initialize();
+ * toolbar.emit( 'updateState' );
+ *
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ * @mixins OO.ui.mixin.GroupElement
+ *
+ * @constructor
+ * @param {OO.ui.ToolFactory} toolFactory Factory for creating tools
+ * @param {OO.ui.ToolGroupFactory} toolGroupFactory Factory for creating toolgroups
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [actions] Add an actions section to the toolbar. Actions are commands that are included
+ * in the toolbar, but are not configured as tools. By default, actions are displayed on the right side of
+ * the toolbar.
+ * @cfg {string} [position='top'] Whether the toolbar is positioned above ('top') or below ('bottom') content.
+ */
+OO.ui.Toolbar = function OoUiToolbar( toolFactory, toolGroupFactory, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( toolFactory ) && config === undefined ) {
+ config = toolFactory;
+ toolFactory = config.toolFactory;
+ toolGroupFactory = config.toolGroupFactory;
+ }
+
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.Toolbar.parent.call( this, config );
+
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+ OO.ui.mixin.GroupElement.call( this, config );
+
+ // Properties
+ this.toolFactory = toolFactory;
+ this.toolGroupFactory = toolGroupFactory;
+ this.groups = [];
+ this.tools = {};
+ this.position = config.position || 'top';
+ this.$bar = $( '<div>' );
+ this.$actions = $( '<div>' );
+ this.initialized = false;
+ this.narrowThreshold = null;
+ this.onWindowResizeHandler = this.onWindowResize.bind( this );
+
+ // Events
+ this.$element
+ .add( this.$bar ).add( this.$group ).add( this.$actions )
+ .on( 'mousedown keydown', this.onPointerDown.bind( this ) );
+
+ // Initialization
+ this.$group.addClass( 'oo-ui-toolbar-tools' );
+ if ( config.actions ) {
+ this.$bar.append( this.$actions.addClass( 'oo-ui-toolbar-actions' ) );
+ }
+ this.$bar
+ .addClass( 'oo-ui-toolbar-bar' )
+ .append( this.$group, '<div style="clear:both"></div>' );
+ // Possible classes: oo-ui-toolbar-position-top, oo-ui-toolbar-position-bottom
+ this.$element.addClass( 'oo-ui-toolbar oo-ui-toolbar-position-' + this.position ).append( this.$bar );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Toolbar, OO.ui.Element );
+OO.mixinClass( OO.ui.Toolbar, OO.EventEmitter );
+OO.mixinClass( OO.ui.Toolbar, OO.ui.mixin.GroupElement );
+
+/* Events */
+
+/**
+ * @event updateState
+ *
+ * An 'updateState' event must be emitted on the Toolbar (by calling `toolbar.emit( 'updateState' )`)
+ * every time the state of the application using the toolbar changes, and an update to the state of
+ * tools is required.
+ *
+ * @param {...Mixed} data Application-defined parameters
+ */
+
+/* Methods */
+
+/**
+ * Get the tool factory.
+ *
+ * @return {OO.ui.ToolFactory} Tool factory
+ */
+OO.ui.Toolbar.prototype.getToolFactory = function () {
+ return this.toolFactory;
+};
+
+/**
+ * Get the toolgroup factory.
+ *
+ * @return {OO.Factory} Toolgroup factory
+ */
+OO.ui.Toolbar.prototype.getToolGroupFactory = function () {
+ return this.toolGroupFactory;
+};
+
+/**
+ * Handles mouse down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.Toolbar.prototype.onPointerDown = function ( e ) {
+ var $closestWidgetToEvent = $( e.target ).closest( '.oo-ui-widget' ),
+ $closestWidgetToToolbar = this.$element.closest( '.oo-ui-widget' );
+ if ( !$closestWidgetToEvent.length || $closestWidgetToEvent[ 0 ] === $closestWidgetToToolbar[ 0 ] ) {
+ return false;
+ }
+};
+
+/**
+ * Handle window resize event.
+ *
+ * @private
+ * @param {jQuery.Event} e Window resize event
+ */
+OO.ui.Toolbar.prototype.onWindowResize = function () {
+ this.$element.toggleClass(
+ 'oo-ui-toolbar-narrow',
+ this.$bar.width() <= this.getNarrowThreshold()
+ );
+};
+
+/**
+ * Get the (lazily-computed) width threshold for applying the oo-ui-toolbar-narrow
+ * class.
+ *
+ * @private
+ * @return {number} Width threshold in pixels
+ */
+OO.ui.Toolbar.prototype.getNarrowThreshold = function () {
+ if ( this.narrowThreshold === null ) {
+ this.narrowThreshold = this.$group.width() + this.$actions.width();
+ }
+ return this.narrowThreshold;
+};
+
+/**
+ * Sets up handles and preloads required information for the toolbar to work.
+ * This must be called after it is attached to a visible document and before doing anything else.
+ */
+OO.ui.Toolbar.prototype.initialize = function () {
+ if ( !this.initialized ) {
+ this.initialized = true;
+ $( this.getElementWindow() ).on( 'resize', this.onWindowResizeHandler );
+ this.onWindowResize();
+ }
+};
+
+/**
+ * Set up the toolbar.
+ *
+ * The toolbar is set up with a list of toolgroup configurations that specify the type of
+ * toolgroup ({@link OO.ui.BarToolGroup bar}, {@link OO.ui.MenuToolGroup menu}, or {@link OO.ui.ListToolGroup list})
+ * to add and which tools to include, exclude, promote, or demote within that toolgroup. Please
+ * see {@link OO.ui.ToolGroup toolgroups} for more information about including tools in toolgroups.
+ *
+ * @param {Object.<string,Array>} groups List of toolgroup configurations
+ * @param {Array|string} [groups.include] Tools to include in the toolgroup
+ * @param {Array|string} [groups.exclude] Tools to exclude from the toolgroup
+ * @param {Array|string} [groups.promote] Tools to promote to the beginning of the toolgroup
+ * @param {Array|string} [groups.demote] Tools to demote to the end of the toolgroup
+ */
+OO.ui.Toolbar.prototype.setup = function ( groups ) {
+ var i, len, type, group,
+ items = [],
+ defaultType = 'bar';
+
+ // Cleanup previous groups
+ this.reset();
+
+ // Build out new groups
+ for ( i = 0, len = groups.length; i < len; i++ ) {
+ group = groups[ i ];
+ if ( group.include === '*' ) {
+ // Apply defaults to catch-all groups
+ if ( group.type === undefined ) {
+ group.type = 'list';
+ }
+ if ( group.label === undefined ) {
+ group.label = OO.ui.msg( 'ooui-toolbar-more' );
+ }
+ }
+ // Check type has been registered
+ type = this.getToolGroupFactory().lookup( group.type ) ? group.type : defaultType;
+ items.push(
+ this.getToolGroupFactory().create( type, this, group )
+ );
+ }
+ this.addItems( items );
+};
+
+/**
+ * Remove all tools and toolgroups from the toolbar.
+ */
+OO.ui.Toolbar.prototype.reset = function () {
+ var i, len;
+
+ this.groups = [];
+ this.tools = {};
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ this.items[ i ].destroy();
+ }
+ this.clearItems();
+};
+
+/**
+ * Destroy the toolbar.
+ *
+ * Destroying the toolbar removes all event handlers and DOM elements that constitute the toolbar. Call
+ * this method whenever you are done using a toolbar.
+ */
+OO.ui.Toolbar.prototype.destroy = function () {
+ $( this.getElementWindow() ).off( 'resize', this.onWindowResizeHandler );
+ this.reset();
+ this.$element.remove();
+};
+
+/**
+ * Check if the tool is available.
+ *
+ * Available tools are ones that have not yet been added to the toolbar.
+ *
+ * @param {string} name Symbolic name of tool
+ * @return {boolean} Tool is available
+ */
+OO.ui.Toolbar.prototype.isToolAvailable = function ( name ) {
+ return !this.tools[ name ];
+};
+
+/**
+ * Prevent tool from being used again.
+ *
+ * @param {OO.ui.Tool} tool Tool to reserve
+ */
+OO.ui.Toolbar.prototype.reserveTool = function ( tool ) {
+ this.tools[ tool.getName() ] = tool;
+};
+
+/**
+ * Allow tool to be used again.
+ *
+ * @param {OO.ui.Tool} tool Tool to release
+ */
+OO.ui.Toolbar.prototype.releaseTool = function ( tool ) {
+ delete this.tools[ tool.getName() ];
+};
+
+/**
+ * Get accelerator label for tool.
+ *
+ * The OOjs UI library does not contain an accelerator system, but this is the hook for one. To
+ * use an accelerator system, subclass the toolbar and override this method, which is meant to return a label
+ * that describes the accelerator keys for the tool passed (by symbolic name) to the method.
+ *
+ * @param {string} name Symbolic name of tool
+ * @return {string|undefined} Tool accelerator label if available
+ */
+OO.ui.Toolbar.prototype.getToolAccelerator = function () {
+ return undefined;
+};
+
+/**
+ * Tools, together with {@link OO.ui.ToolGroup toolgroups}, constitute {@link OO.ui.Toolbar toolbars}.
+ * Each tool is configured with a static name, title, and icon and is customized with the command to carry
+ * out when the tool is selected. Tools must also be registered with a {@link OO.ui.ToolFactory tool factory},
+ * which creates the tools on demand.
+ *
+ * Every Tool subclass must implement two methods:
+ *
+ * - {@link #onUpdateState}
+ * - {@link #onSelect}
+ *
+ * Tools are added to toolgroups ({@link OO.ui.ListToolGroup ListToolGroup},
+ * {@link OO.ui.BarToolGroup BarToolGroup}, or {@link OO.ui.MenuToolGroup MenuToolGroup}), which determine how
+ * the tool is displayed in the toolbar. See {@link OO.ui.Toolbar toolbars} for an example.
+ *
+ * For more information, please see the [OOjs UI documentation on MediaWiki][1].
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.FlaggedElement
+ * @mixins OO.ui.mixin.TabIndexedElement
+ *
+ * @constructor
+ * @param {OO.ui.ToolGroup} toolGroup
+ * @param {Object} [config] Configuration options
+ * @cfg {string|Function} [title] Title text or a function that returns text. If this config is omitted, the value of
+ * the {@link #static-title static title} property is used.
+ *
+ * The title is used in different ways depending on the type of toolgroup that contains the tool. The
+ * title is used as a tooltip if the tool is part of a {@link OO.ui.BarToolGroup bar} toolgroup, or as the label text if the tool is
+ * part of a {@link OO.ui.ListToolGroup list} or {@link OO.ui.MenuToolGroup menu} toolgroup.
+ *
+ * For bar toolgroups, a description of the accelerator key is appended to the title if an accelerator key
+ * is associated with an action by the same name as the tool and accelerator functionality has been added to the application.
+ * To add accelerator key functionality, you must subclass OO.ui.Toolbar and override the {@link OO.ui.Toolbar#getToolAccelerator getToolAccelerator} method.
+ */
+OO.ui.Tool = function OoUiTool( toolGroup, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( toolGroup ) && config === undefined ) {
+ config = toolGroup;
+ toolGroup = config.toolGroup;
+ }
+
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.Tool.parent.call( this, config );
+
+ // Properties
+ this.toolGroup = toolGroup;
+ this.toolbar = this.toolGroup.getToolbar();
+ this.active = false;
+ this.$title = $( '<span>' );
+ this.$accel = $( '<span>' );
+ this.$link = $( '<a>' );
+ this.title = null;
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.FlaggedElement.call( this, config );
+ OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$link } ) );
+
+ // Events
+ this.toolbar.connect( this, { updateState: 'onUpdateState' } );
+
+ // Initialization
+ this.$title.addClass( 'oo-ui-tool-title' );
+ this.$accel
+ .addClass( 'oo-ui-tool-accel' )
+ .prop( {
+ // This may need to be changed if the key names are ever localized,
+ // but for now they are essentially written in English
+ dir: 'ltr',
+ lang: 'en'
+ } );
+ this.$link
+ .addClass( 'oo-ui-tool-link' )
+ .append( this.$icon, this.$title, this.$accel )
+ .attr( 'role', 'button' );
+ this.$element
+ .data( 'oo-ui-tool', this )
+ .addClass( 'oo-ui-tool' )
+ .addClass( 'oo-ui-tool-name-' + this.constructor.static.name.replace( /^([^/]+)\/([^/]+).*$/, '$1-$2' ) )
+ .toggleClass( 'oo-ui-tool-with-label', this.constructor.static.displayBothIconAndLabel )
+ .append( this.$link );
+ this.setTitle( config.title || this.constructor.static.title );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Tool, OO.ui.Widget );
+OO.mixinClass( OO.ui.Tool, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.Tool, OO.ui.mixin.FlaggedElement );
+OO.mixinClass( OO.ui.Tool, OO.ui.mixin.TabIndexedElement );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.Tool.static.tagName = 'span';
+
+/**
+ * Symbolic name of tool.
+ *
+ * The symbolic name is used internally to register the tool with a {@link OO.ui.ToolFactory ToolFactory}. It can
+ * also be used when adding tools to toolgroups.
+ *
+ * @abstract
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.Tool.static.name = '';
+
+/**
+ * Symbolic name of the group.
+ *
+ * The group name is used to associate tools with each other so that they can be selected later by
+ * a {@link OO.ui.ToolGroup toolgroup}.
+ *
+ * @abstract
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.Tool.static.group = '';
+
+/**
+ * Tool title text or a function that returns title text. The value of the static property is overridden if the #title config option is used.
+ *
+ * @abstract
+ * @static
+ * @inheritable
+ * @property {string|Function}
+ */
+OO.ui.Tool.static.title = '';
+
+/**
+ * Display both icon and label when the tool is used in a {@link OO.ui.BarToolGroup bar} toolgroup.
+ * Normally only the icon is displayed, or only the label if no icon is given.
+ *
+ * @static
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.Tool.static.displayBothIconAndLabel = false;
+
+/**
+ * Add tool to catch-all groups automatically.
+ *
+ * A catch-all group, which contains all tools that do not currently belong to a toolgroup,
+ * can be included in a toolgroup using the wildcard selector, an asterisk (*).
+ *
+ * @static
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.Tool.static.autoAddToCatchall = true;
+
+/**
+ * Add tool to named groups automatically.
+ *
+ * By default, tools that are configured with a static ‘group’ property are added
+ * to that group and will be selected when the symbolic name of the group is specified (e.g., when
+ * toolgroups include tools by group name).
+ *
+ * @static
+ * @property {boolean}
+ * @inheritable
+ */
+OO.ui.Tool.static.autoAddToGroup = true;
+
+/**
+ * Check if this tool is compatible with given data.
+ *
+ * This is a stub that can be overridden to provide support for filtering tools based on an
+ * arbitrary piece of information (e.g., where the cursor is in a document). The implementation
+ * must also call this method so that the compatibility check can be performed.
+ *
+ * @static
+ * @inheritable
+ * @param {Mixed} data Data to check
+ * @return {boolean} Tool can be used with data
+ */
+OO.ui.Tool.static.isCompatibleWith = function () {
+ return false;
+};
+
+/* Methods */
+
+/**
+ * Handle the toolbar state being updated. This method is called when the
+ * {@link OO.ui.Toolbar#event-updateState 'updateState' event} is emitted on the
+ * {@link OO.ui.Toolbar Toolbar} that uses this tool, and should set the state of this tool
+ * depending on application state (usually by calling #setDisabled to enable or disable the tool,
+ * or #setActive to mark is as currently in-use or not).
+ *
+ * This is an abstract method that must be overridden in a concrete subclass.
+ *
+ * @method
+ * @protected
+ * @abstract
+ */
+OO.ui.Tool.prototype.onUpdateState = null;
+
+/**
+ * Handle the tool being selected. This method is called when the user triggers this tool,
+ * usually by clicking on its label/icon.
+ *
+ * This is an abstract method that must be overridden in a concrete subclass.
+ *
+ * @method
+ * @protected
+ * @abstract
+ */
+OO.ui.Tool.prototype.onSelect = null;
+
+/**
+ * Check if the tool is active.
+ *
+ * Tools become active when their #onSelect or #onUpdateState handlers change them to appear pressed
+ * with the #setActive method. Additional CSS is applied to the tool to reflect the active state.
+ *
+ * @return {boolean} Tool is active
+ */
+OO.ui.Tool.prototype.isActive = function () {
+ return this.active;
+};
+
+/**
+ * Make the tool appear active or inactive.
+ *
+ * This method should be called within #onSelect or #onUpdateState event handlers to make the tool
+ * appear pressed or not.
+ *
+ * @param {boolean} state Make tool appear active
+ */
+OO.ui.Tool.prototype.setActive = function ( state ) {
+ this.active = !!state;
+ if ( this.active ) {
+ this.$element.addClass( 'oo-ui-tool-active' );
+ this.setFlags( { progressive: true } );
+ } else {
+ this.$element.removeClass( 'oo-ui-tool-active' );
+ this.setFlags( { progressive: false } );
+ }
+};
+
+/**
+ * Set the tool #title.
+ *
+ * @param {string|Function} title Title text or a function that returns text
+ * @chainable
+ */
+OO.ui.Tool.prototype.setTitle = function ( title ) {
+ this.title = OO.ui.resolveMsg( title );
+ this.updateTitle();
+ return this;
+};
+
+/**
+ * Get the tool #title.
+ *
+ * @return {string} Title text
+ */
+OO.ui.Tool.prototype.getTitle = function () {
+ return this.title;
+};
+
+/**
+ * Get the tool's symbolic name.
+ *
+ * @return {string} Symbolic name of tool
+ */
+OO.ui.Tool.prototype.getName = function () {
+ return this.constructor.static.name;
+};
+
+/**
+ * Update the title.
+ */
+OO.ui.Tool.prototype.updateTitle = function () {
+ var titleTooltips = this.toolGroup.constructor.static.titleTooltips,
+ accelTooltips = this.toolGroup.constructor.static.accelTooltips,
+ accel = this.toolbar.getToolAccelerator( this.constructor.static.name ),
+ tooltipParts = [];
+
+ this.$title.text( this.title );
+ this.$accel.text( accel );
+
+ if ( titleTooltips && typeof this.title === 'string' && this.title.length ) {
+ tooltipParts.push( this.title );
+ }
+ if ( accelTooltips && typeof accel === 'string' && accel.length ) {
+ tooltipParts.push( accel );
+ }
+ if ( tooltipParts.length ) {
+ this.$link.attr( 'title', tooltipParts.join( ' ' ) );
+ } else {
+ this.$link.removeAttr( 'title' );
+ }
+};
+
+/**
+ * Destroy tool.
+ *
+ * Destroying the tool removes all event handlers and the tool’s DOM elements.
+ * Call this method whenever you are done using a tool.
+ */
+OO.ui.Tool.prototype.destroy = function () {
+ this.toolbar.disconnect( this );
+ this.$element.remove();
+};
+
+/**
+ * ToolGroups are collections of {@link OO.ui.Tool tools} that are used in a {@link OO.ui.Toolbar toolbar}.
+ * The type of toolgroup ({@link OO.ui.ListToolGroup list}, {@link OO.ui.BarToolGroup bar}, or {@link OO.ui.MenuToolGroup menu})
+ * to which a tool belongs determines how the tool is arranged and displayed in the toolbar. Toolgroups
+ * themselves are created on demand with a {@link OO.ui.ToolGroupFactory toolgroup factory}.
+ *
+ * Toolgroups can contain individual tools, groups of tools, or all available tools, as specified
+ * using the `include` config option. See OO.ui.ToolFactory#extract on documentation of the format.
+ * The options `exclude`, `promote`, and `demote` support the same formats.
+ *
+ * See {@link OO.ui.Toolbar toolbars} for a full example. For more information about toolbars in general,
+ * please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.GroupElement
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ * @cfg {Array|string} [include] List of tools to include in the toolgroup, see above.
+ * @cfg {Array|string} [exclude] List of tools to exclude from the toolgroup, see above.
+ * @cfg {Array|string} [promote] List of tools to promote to the beginning of the toolgroup, see above.
+ * @cfg {Array|string} [demote] List of tools to demote to the end of the toolgroup, see above.
+ * This setting is particularly useful when tools have been added to the toolgroup
+ * en masse (e.g., via the catch-all selector).
+ */
+OO.ui.ToolGroup = function OoUiToolGroup( toolbar, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( toolbar ) && config === undefined ) {
+ config = toolbar;
+ toolbar = config.toolbar;
+ }
+
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.ToolGroup.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.GroupElement.call( this, config );
+
+ // Properties
+ this.toolbar = toolbar;
+ this.tools = {};
+ this.pressed = null;
+ this.autoDisabled = false;
+ this.include = config.include || [];
+ this.exclude = config.exclude || [];
+ this.promote = config.promote || [];
+ this.demote = config.demote || [];
+ this.onCapturedMouseKeyUpHandler = this.onCapturedMouseKeyUp.bind( this );
+
+ // Events
+ this.$element.on( {
+ mousedown: this.onMouseKeyDown.bind( this ),
+ mouseup: this.onMouseKeyUp.bind( this ),
+ keydown: this.onMouseKeyDown.bind( this ),
+ keyup: this.onMouseKeyUp.bind( this ),
+ focus: this.onMouseOverFocus.bind( this ),
+ blur: this.onMouseOutBlur.bind( this ),
+ mouseover: this.onMouseOverFocus.bind( this ),
+ mouseout: this.onMouseOutBlur.bind( this )
+ } );
+ this.toolbar.getToolFactory().connect( this, { register: 'onToolFactoryRegister' } );
+ this.aggregate( { disable: 'itemDisable' } );
+ this.connect( this, { itemDisable: 'updateDisabled' } );
+
+ // Initialization
+ this.$group.addClass( 'oo-ui-toolGroup-tools' );
+ this.$element
+ .addClass( 'oo-ui-toolGroup' )
+ .append( this.$group );
+ this.populate();
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToolGroup, OO.ui.Widget );
+OO.mixinClass( OO.ui.ToolGroup, OO.ui.mixin.GroupElement );
+
+/* Events */
+
+/**
+ * @event update
+ */
+
+/* Static Properties */
+
+/**
+ * Show labels in tooltips.
+ *
+ * @static
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.ToolGroup.static.titleTooltips = false;
+
+/**
+ * Show acceleration labels in tooltips.
+ *
+ * Note: The OOjs UI library does not include an accelerator system, but does contain
+ * a hook for one. To use an accelerator system, subclass the {@link OO.ui.Toolbar toolbar} and
+ * override the {@link OO.ui.Toolbar#getToolAccelerator getToolAccelerator} method, which is
+ * meant to return a label that describes the accelerator keys for a given tool (e.g., 'Ctrl + M').
+ *
+ * @static
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.ToolGroup.static.accelTooltips = false;
+
+/**
+ * Automatically disable the toolgroup when all tools are disabled
+ *
+ * @static
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.ToolGroup.static.autoDisable = true;
+
+/**
+ * @abstract
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.ToolGroup.static.name = null;
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToolGroup.prototype.isDisabled = function () {
+ return this.autoDisabled || OO.ui.ToolGroup.parent.prototype.isDisabled.apply( this, arguments );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToolGroup.prototype.updateDisabled = function () {
+ var i, item, allDisabled = true;
+
+ if ( this.constructor.static.autoDisable ) {
+ for ( i = this.items.length - 1; i >= 0; i-- ) {
+ item = this.items[ i ];
+ if ( !item.isDisabled() ) {
+ allDisabled = false;
+ break;
+ }
+ }
+ this.autoDisabled = allDisabled;
+ }
+ OO.ui.ToolGroup.parent.prototype.updateDisabled.apply( this, arguments );
+};
+
+/**
+ * Handle mouse down and key down events.
+ *
+ * @protected
+ * @param {jQuery.Event} e Mouse down or key down event
+ */
+OO.ui.ToolGroup.prototype.onMouseKeyDown = function ( e ) {
+ if (
+ !this.isDisabled() &&
+ ( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
+ ) {
+ this.pressed = this.findTargetTool( e );
+ if ( this.pressed ) {
+ this.pressed.setActive( true );
+ this.getElementDocument().addEventListener( 'mouseup', this.onCapturedMouseKeyUpHandler, true );
+ this.getElementDocument().addEventListener( 'keyup', this.onCapturedMouseKeyUpHandler, true );
+ return false;
+ }
+ }
+};
+
+/**
+ * Handle captured mouse up and key up events.
+ *
+ * @protected
+ * @param {MouseEvent|KeyboardEvent} e Mouse up or key up event
+ */
+OO.ui.ToolGroup.prototype.onCapturedMouseKeyUp = function ( e ) {
+ this.getElementDocument().removeEventListener( 'mouseup', this.onCapturedMouseKeyUpHandler, true );
+ this.getElementDocument().removeEventListener( 'keyup', this.onCapturedMouseKeyUpHandler, true );
+ // onMouseKeyUp may be called a second time, depending on where the mouse is when the button is
+ // released, but since `this.pressed` will no longer be true, the second call will be ignored.
+ this.onMouseKeyUp( e );
+};
+
+/**
+ * Handle mouse up and key up events.
+ *
+ * @protected
+ * @param {MouseEvent|KeyboardEvent} e Mouse up or key up event
+ */
+OO.ui.ToolGroup.prototype.onMouseKeyUp = function ( e ) {
+ var tool = this.findTargetTool( e );
+
+ if (
+ !this.isDisabled() && this.pressed && this.pressed === tool &&
+ ( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
+ ) {
+ this.pressed.onSelect();
+ this.pressed = null;
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ this.pressed = null;
+};
+
+/**
+ * Handle mouse over and focus events.
+ *
+ * @protected
+ * @param {jQuery.Event} e Mouse over or focus event
+ */
+OO.ui.ToolGroup.prototype.onMouseOverFocus = function ( e ) {
+ var tool = this.findTargetTool( e );
+
+ if ( this.pressed && this.pressed === tool ) {
+ this.pressed.setActive( true );
+ }
+};
+
+/**
+ * Handle mouse out and blur events.
+ *
+ * @protected
+ * @param {jQuery.Event} e Mouse out or blur event
+ */
+OO.ui.ToolGroup.prototype.onMouseOutBlur = function ( e ) {
+ var tool = this.findTargetTool( e );
+
+ if ( this.pressed && this.pressed === tool ) {
+ this.pressed.setActive( false );
+ }
+};
+
+/**
+ * Get the closest tool to a jQuery.Event.
+ *
+ * Only tool links are considered, which prevents other elements in the tool such as popups from
+ * triggering tool group interactions.
+ *
+ * @private
+ * @param {jQuery.Event} e
+ * @return {OO.ui.Tool|null} Tool, `null` if none was found
+ */
+OO.ui.ToolGroup.prototype.findTargetTool = function ( e ) {
+ var tool,
+ $item = $( e.target ).closest( '.oo-ui-tool-link' );
+
+ if ( $item.length ) {
+ tool = $item.parent().data( 'oo-ui-tool' );
+ }
+
+ return tool && !tool.isDisabled() ? tool : null;
+};
+
+/**
+ * Handle tool registry register events.
+ *
+ * If a tool is registered after the group is created, we must repopulate the list to account for:
+ *
+ * - a tool being added that may be included
+ * - a tool already included being overridden
+ *
+ * @protected
+ * @param {string} name Symbolic name of tool
+ */
+OO.ui.ToolGroup.prototype.onToolFactoryRegister = function () {
+ this.populate();
+};
+
+/**
+ * Get the toolbar that contains the toolgroup.
+ *
+ * @return {OO.ui.Toolbar} Toolbar that contains the toolgroup
+ */
+OO.ui.ToolGroup.prototype.getToolbar = function () {
+ return this.toolbar;
+};
+
+/**
+ * Add and remove tools based on configuration.
+ */
+OO.ui.ToolGroup.prototype.populate = function () {
+ var i, len, name, tool,
+ toolFactory = this.toolbar.getToolFactory(),
+ names = {},
+ add = [],
+ remove = [],
+ list = this.toolbar.getToolFactory().getTools(
+ this.include, this.exclude, this.promote, this.demote
+ );
+
+ // Build a list of needed tools
+ for ( i = 0, len = list.length; i < len; i++ ) {
+ name = list[ i ];
+ if (
+ // Tool exists
+ toolFactory.lookup( name ) &&
+ // Tool is available or is already in this group
+ ( this.toolbar.isToolAvailable( name ) || this.tools[ name ] )
+ ) {
+ // Hack to prevent infinite recursion via ToolGroupTool. We need to reserve the tool before
+ // creating it, but we can't call reserveTool() yet because we haven't created the tool.
+ this.toolbar.tools[ name ] = true;
+ tool = this.tools[ name ];
+ if ( !tool ) {
+ // Auto-initialize tools on first use
+ this.tools[ name ] = tool = toolFactory.create( name, this );
+ tool.updateTitle();
+ }
+ this.toolbar.reserveTool( tool );
+ add.push( tool );
+ names[ name ] = true;
+ }
+ }
+ // Remove tools that are no longer needed
+ for ( name in this.tools ) {
+ if ( !names[ name ] ) {
+ this.tools[ name ].destroy();
+ this.toolbar.releaseTool( this.tools[ name ] );
+ remove.push( this.tools[ name ] );
+ delete this.tools[ name ];
+ }
+ }
+ if ( remove.length ) {
+ this.removeItems( remove );
+ }
+ // Update emptiness state
+ if ( add.length ) {
+ this.$element.removeClass( 'oo-ui-toolGroup-empty' );
+ } else {
+ this.$element.addClass( 'oo-ui-toolGroup-empty' );
+ }
+ // Re-add tools (moving existing ones to new locations)
+ this.addItems( add );
+ // Disabled state may depend on items
+ this.updateDisabled();
+};
+
+/**
+ * Destroy toolgroup.
+ */
+OO.ui.ToolGroup.prototype.destroy = function () {
+ var name;
+
+ this.clearItems();
+ this.toolbar.getToolFactory().disconnect( this );
+ for ( name in this.tools ) {
+ this.toolbar.releaseTool( this.tools[ name ] );
+ this.tools[ name ].disconnect( this ).destroy();
+ delete this.tools[ name ];
+ }
+ this.$element.remove();
+};
+
+/**
+ * A ToolFactory creates tools on demand. All tools ({@link OO.ui.Tool Tools}, {@link OO.ui.PopupTool PopupTools},
+ * and {@link OO.ui.ToolGroupTool ToolGroupTools}) must be registered with a tool factory. Tools are
+ * registered by their symbolic name. See {@link OO.ui.Toolbar toolbars} for an example.
+ *
+ * For more information about toolbars in general, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars
+ *
+ * @class
+ * @extends OO.Factory
+ * @constructor
+ */
+OO.ui.ToolFactory = function OoUiToolFactory() {
+ // Parent constructor
+ OO.ui.ToolFactory.parent.call( this );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToolFactory, OO.Factory );
+
+/* Methods */
+
+/**
+ * Get tools from the factory
+ *
+ * @param {Array|string} [include] Included tools, see #extract for format
+ * @param {Array|string} [exclude] Excluded tools, see #extract for format
+ * @param {Array|string} [promote] Promoted tools, see #extract for format
+ * @param {Array|string} [demote] Demoted tools, see #extract for format
+ * @return {string[]} List of tools
+ */
+OO.ui.ToolFactory.prototype.getTools = function ( include, exclude, promote, demote ) {
+ var i, len, included, promoted, demoted,
+ auto = [],
+ used = {};
+
+ // Collect included and not excluded tools
+ included = OO.simpleArrayDifference( this.extract( include ), this.extract( exclude ) );
+
+ // Promotion
+ promoted = this.extract( promote, used );
+ demoted = this.extract( demote, used );
+
+ // Auto
+ for ( i = 0, len = included.length; i < len; i++ ) {
+ if ( !used[ included[ i ] ] ) {
+ auto.push( included[ i ] );
+ }
+ }
+
+ return promoted.concat( auto ).concat( demoted );
+};
+
+/**
+ * Get a flat list of names from a list of names or groups.
+ *
+ * Normally, `collection` is an array of tool specifications. Tools can be specified in the
+ * following ways:
+ *
+ * - To include an individual tool, use the symbolic name: `{ name: 'tool-name' }` or `'tool-name'`.
+ * - To include all tools in a group, use the group name: `{ group: 'group-name' }`. (To assign the
+ * tool to a group, use OO.ui.Tool.static.group.)
+ *
+ * Alternatively, to include all tools that are not yet assigned to any other toolgroup, use the
+ * catch-all selector `'*'`.
+ *
+ * If `used` is passed, tool names that appear as properties in this object will be considered
+ * already assigned, and will not be returned even if specified otherwise. The tool names extracted
+ * by this function call will be added as new properties in the object.
+ *
+ * @private
+ * @param {Array|string} collection List of tools, see above
+ * @param {Object} [used] Object containing information about used tools, see above
+ * @return {string[]} List of extracted tool names
+ */
+OO.ui.ToolFactory.prototype.extract = function ( collection, used ) {
+ var i, len, item, name, tool,
+ names = [];
+
+ collection = !Array.isArray( collection ) ? [ collection ] : collection;
+
+ for ( i = 0, len = collection.length; i < len; i++ ) {
+ item = collection[ i ];
+ if ( item === '*' ) {
+ for ( name in this.registry ) {
+ tool = this.registry[ name ];
+ if (
+ // Only add tools by group name when auto-add is enabled
+ tool.static.autoAddToCatchall &&
+ // Exclude already used tools
+ ( !used || !used[ name ] )
+ ) {
+ names.push( name );
+ if ( used ) {
+ used[ name ] = true;
+ }
+ }
+ }
+ } else {
+ // Allow plain strings as shorthand for named tools
+ if ( typeof item === 'string' ) {
+ item = { name: item };
+ }
+ if ( OO.isPlainObject( item ) ) {
+ if ( item.group ) {
+ for ( name in this.registry ) {
+ tool = this.registry[ name ];
+ if (
+ // Include tools with matching group
+ tool.static.group === item.group &&
+ // Only add tools by group name when auto-add is enabled
+ tool.static.autoAddToGroup &&
+ // Exclude already used tools
+ ( !used || !used[ name ] )
+ ) {
+ names.push( name );
+ if ( used ) {
+ used[ name ] = true;
+ }
+ }
+ }
+ // Include tools with matching name and exclude already used tools
+ } else if ( item.name && ( !used || !used[ item.name ] ) ) {
+ names.push( item.name );
+ if ( used ) {
+ used[ item.name ] = true;
+ }
+ }
+ }
+ }
+ }
+ return names;
+};
+
+/**
+ * ToolGroupFactories create {@link OO.ui.ToolGroup toolgroups} on demand. The toolgroup classes must
+ * specify a symbolic name and be registered with the factory. The following classes are registered by
+ * default:
+ *
+ * - {@link OO.ui.BarToolGroup BarToolGroups} (‘bar’)
+ * - {@link OO.ui.MenuToolGroup MenuToolGroups} (‘menu’)
+ * - {@link OO.ui.ListToolGroup ListToolGroups} (‘list’)
+ *
+ * See {@link OO.ui.Toolbar toolbars} for an example.
+ *
+ * For more information about toolbars in general, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars
+ *
+ * @class
+ * @extends OO.Factory
+ * @constructor
+ */
+OO.ui.ToolGroupFactory = function OoUiToolGroupFactory() {
+ var i, l, defaultClasses;
+ // Parent constructor
+ OO.Factory.call( this );
+
+ defaultClasses = this.constructor.static.getDefaultClasses();
+
+ // Register default toolgroups
+ for ( i = 0, l = defaultClasses.length; i < l; i++ ) {
+ this.register( defaultClasses[ i ] );
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToolGroupFactory, OO.Factory );
+
+/* Static Methods */
+
+/**
+ * Get a default set of classes to be registered on construction.
+ *
+ * @return {Function[]} Default classes
+ */
+OO.ui.ToolGroupFactory.static.getDefaultClasses = function () {
+ return [
+ OO.ui.BarToolGroup,
+ OO.ui.ListToolGroup,
+ OO.ui.MenuToolGroup
+ ];
+};
+
+/**
+ * Popup tools open a popup window when they are selected from the {@link OO.ui.Toolbar toolbar}. Each popup tool is configured
+ * with a static name, title, and icon, as well with as any popup configurations. Unlike other tools, popup tools do not require that developers specify
+ * an #onSelect or #onUpdateState method, as these methods have been implemented already.
+ *
+ * // Example of a popup tool. When selected, a popup tool displays
+ * // a popup window.
+ * function HelpTool( toolGroup, config ) {
+ * OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {
+ * padded: true,
+ * label: 'Help',
+ * head: true
+ * } }, config ) );
+ * this.popup.$body.append( '<p>I am helpful!</p>' );
+ * };
+ * OO.inheritClass( HelpTool, OO.ui.PopupTool );
+ * HelpTool.static.name = 'help';
+ * HelpTool.static.icon = 'help';
+ * HelpTool.static.title = 'Help';
+ * toolFactory.register( HelpTool );
+ *
+ * For an example of a toolbar that contains a popup tool, see {@link OO.ui.Toolbar toolbars}. For more information about
+ * toolbars in genreral, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Tool
+ * @mixins OO.ui.mixin.PopupElement
+ *
+ * @constructor
+ * @param {OO.ui.ToolGroup} toolGroup
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.PopupTool = function OoUiPopupTool( toolGroup, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( toolGroup ) && config === undefined ) {
+ config = toolGroup;
+ toolGroup = config.toolGroup;
+ }
+
+ // Parent constructor
+ OO.ui.PopupTool.parent.call( this, toolGroup, config );
+
+ // Mixin constructors
+ OO.ui.mixin.PopupElement.call( this, config );
+
+ // Initialization
+ this.popup.setPosition( toolGroup.getToolbar().position === 'bottom' ? 'above' : 'below' );
+ this.$element
+ .addClass( 'oo-ui-popupTool' )
+ .append( this.popup.$element );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PopupTool, OO.ui.Tool );
+OO.mixinClass( OO.ui.PopupTool, OO.ui.mixin.PopupElement );
+
+/* Methods */
+
+/**
+ * Handle the tool being selected.
+ *
+ * @inheritdoc
+ */
+OO.ui.PopupTool.prototype.onSelect = function () {
+ if ( !this.isDisabled() ) {
+ this.popup.toggle();
+ }
+ this.setActive( false );
+ return false;
+};
+
+/**
+ * Handle the toolbar state being updated.
+ *
+ * @inheritdoc
+ */
+OO.ui.PopupTool.prototype.onUpdateState = function () {
+ this.setActive( false );
+};
+
+/**
+ * A ToolGroupTool is a special sort of tool that can contain other {@link OO.ui.Tool tools}
+ * and {@link OO.ui.ToolGroup toolgroups}. The ToolGroupTool was specifically designed to be used
+ * inside a {@link OO.ui.BarToolGroup bar} toolgroup to provide access to additional tools from
+ * the bar item. Included tools will be displayed in a dropdown {@link OO.ui.ListToolGroup list}
+ * when the ToolGroupTool is selected.
+ *
+ * // Example: ToolGroupTool with two nested tools, 'setting1' and 'setting2', defined elsewhere.
+ *
+ * function SettingsTool() {
+ * SettingsTool.parent.apply( this, arguments );
+ * };
+ * OO.inheritClass( SettingsTool, OO.ui.ToolGroupTool );
+ * SettingsTool.static.name = 'settings';
+ * SettingsTool.static.title = 'Change settings';
+ * SettingsTool.static.groupConfig = {
+ * icon: 'settings',
+ * label: 'ToolGroupTool',
+ * include: [ 'setting1', 'setting2' ]
+ * };
+ * toolFactory.register( SettingsTool );
+ *
+ * For more information, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * Please note that this implementation is subject to change per [T74159] [2].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars#ToolGroupTool
+ * [2]: https://phabricator.wikimedia.org/T74159
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Tool
+ *
+ * @constructor
+ * @param {OO.ui.ToolGroup} toolGroup
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ToolGroupTool = function OoUiToolGroupTool( toolGroup, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( toolGroup ) && config === undefined ) {
+ config = toolGroup;
+ toolGroup = config.toolGroup;
+ }
+
+ // Parent constructor
+ OO.ui.ToolGroupTool.parent.call( this, toolGroup, config );
+
+ // Properties
+ this.innerToolGroup = this.createGroup( this.constructor.static.groupConfig );
+
+ // Events
+ this.innerToolGroup.connect( this, { disable: 'onToolGroupDisable' } );
+
+ // Initialization
+ this.$link.remove();
+ this.$element
+ .addClass( 'oo-ui-toolGroupTool' )
+ .append( this.innerToolGroup.$element );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToolGroupTool, OO.ui.Tool );
+
+/* Static Properties */
+
+/**
+ * Toolgroup configuration.
+ *
+ * The toolgroup configuration consists of the tools to include, as well as an icon and label
+ * to use for the bar item. Tools can be included by symbolic name, group, or with the
+ * wildcard selector. Please see {@link OO.ui.ToolGroup toolgroup} for more information.
+ *
+ * @property {Object.<string,Array>}
+ */
+OO.ui.ToolGroupTool.static.groupConfig = {};
+
+/* Methods */
+
+/**
+ * Handle the tool being selected.
+ *
+ * @inheritdoc
+ */
+OO.ui.ToolGroupTool.prototype.onSelect = function () {
+ this.innerToolGroup.setActive( !this.innerToolGroup.active );
+ return false;
+};
+
+/**
+ * Synchronize disabledness state of the tool with the inner toolgroup.
+ *
+ * @private
+ * @param {boolean} disabled Element is disabled
+ */
+OO.ui.ToolGroupTool.prototype.onToolGroupDisable = function ( disabled ) {
+ this.setDisabled( disabled );
+};
+
+/**
+ * Handle the toolbar state being updated.
+ *
+ * @inheritdoc
+ */
+OO.ui.ToolGroupTool.prototype.onUpdateState = function () {
+ this.setActive( false );
+};
+
+/**
+ * Build a {@link OO.ui.ToolGroup toolgroup} from the specified configuration.
+ *
+ * @param {Object.<string,Array>} group Toolgroup configuration. Please see {@link OO.ui.ToolGroup toolgroup} for
+ * more information.
+ * @return {OO.ui.ListToolGroup}
+ */
+OO.ui.ToolGroupTool.prototype.createGroup = function ( group ) {
+ if ( group.include === '*' ) {
+ // Apply defaults to catch-all groups
+ if ( group.label === undefined ) {
+ group.label = OO.ui.msg( 'ooui-toolbar-more' );
+ }
+ }
+
+ return this.toolbar.getToolGroupFactory().create( 'list', this.toolbar, group );
+};
+
+/**
+ * BarToolGroups are one of three types of {@link OO.ui.ToolGroup toolgroups} that are used to
+ * create {@link OO.ui.Toolbar toolbars} (the other types of groups are {@link OO.ui.MenuToolGroup MenuToolGroup}
+ * and {@link OO.ui.ListToolGroup ListToolGroup}). The {@link OO.ui.Tool tools} in a BarToolGroup are
+ * displayed by icon in a single row. The title of the tool is displayed when users move the mouse over
+ * the tool.
+ *
+ * BarToolGroups are created by a {@link OO.ui.ToolGroupFactory tool group factory} when the toolbar is
+ * set up.
+ *
+ * @example
+ * // Example of a BarToolGroup with two tools
+ * var toolFactory = new OO.ui.ToolFactory();
+ * var toolGroupFactory = new OO.ui.ToolGroupFactory();
+ * var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory );
+ *
+ * // We will be placing status text in this element when tools are used
+ * var $area = $( '<p>' ).text( 'Example of a BarToolGroup with two tools.' );
+ *
+ * // Define the tools that we're going to place in our toolbar
+ *
+ * // Create a class inheriting from OO.ui.Tool
+ * function SearchTool() {
+ * SearchTool.parent.apply( this, arguments );
+ * }
+ * OO.inheritClass( SearchTool, OO.ui.Tool );
+ * // Each tool must have a 'name' (used as an internal identifier, see later) and at least one
+ * // of 'icon' and 'title' (displayed icon and text).
+ * SearchTool.static.name = 'search';
+ * SearchTool.static.icon = 'search';
+ * SearchTool.static.title = 'Search...';
+ * // Defines the action that will happen when this tool is selected (clicked).
+ * SearchTool.prototype.onSelect = function () {
+ * $area.text( 'Search tool clicked!' );
+ * // Never display this tool as "active" (selected).
+ * this.setActive( false );
+ * };
+ * SearchTool.prototype.onUpdateState = function () {};
+ * // Make this tool available in our toolFactory and thus our toolbar
+ * toolFactory.register( SearchTool );
+ *
+ * // This is a PopupTool. Rather than having a custom 'onSelect' action, it will display a
+ * // little popup window (a PopupWidget).
+ * function HelpTool( toolGroup, config ) {
+ * OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {
+ * padded: true,
+ * label: 'Help',
+ * head: true
+ * } }, config ) );
+ * this.popup.$body.append( '<p>I am helpful!</p>' );
+ * }
+ * OO.inheritClass( HelpTool, OO.ui.PopupTool );
+ * HelpTool.static.name = 'help';
+ * HelpTool.static.icon = 'help';
+ * HelpTool.static.title = 'Help';
+ * toolFactory.register( HelpTool );
+ *
+ * // Finally define which tools and in what order appear in the toolbar. Each tool may only be
+ * // used once (but not all defined tools must be used).
+ * toolbar.setup( [
+ * {
+ * // 'bar' tool groups display tools by icon only
+ * type: 'bar',
+ * include: [ 'search', 'help' ]
+ * }
+ * ] );
+ *
+ * // Create some UI around the toolbar and place it in the document
+ * var frame = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * framed: true
+ * } );
+ * var contentFrame = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * padded: true
+ * } );
+ * frame.$element.append(
+ * toolbar.$element,
+ * contentFrame.$element.append( $area )
+ * );
+ * $( 'body' ).append( frame.$element );
+ *
+ * // Here is where the toolbar is actually built. This must be done after inserting it into the
+ * // document.
+ * toolbar.initialize();
+ *
+ * For more information about how to add tools to a bar tool group, please see {@link OO.ui.ToolGroup toolgroup}.
+ * For more information about toolbars in general, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars
+ *
+ * @class
+ * @extends OO.ui.ToolGroup
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.BarToolGroup = function OoUiBarToolGroup( toolbar, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( toolbar ) && config === undefined ) {
+ config = toolbar;
+ toolbar = config.toolbar;
+ }
+
+ // Parent constructor
+ OO.ui.BarToolGroup.parent.call( this, toolbar, config );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-barToolGroup' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.BarToolGroup, OO.ui.ToolGroup );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.BarToolGroup.static.titleTooltips = true;
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.BarToolGroup.static.accelTooltips = true;
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.BarToolGroup.static.name = 'bar';
+
+/**
+ * PopupToolGroup is an abstract base class used by both {@link OO.ui.MenuToolGroup MenuToolGroup}
+ * and {@link OO.ui.ListToolGroup ListToolGroup} to provide a popup--an overlaid menu or list of tools with an
+ * optional icon and label. This class can be used for other base classes that also use this functionality.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.ToolGroup
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.TitledElement
+ * @mixins OO.ui.mixin.FlaggedElement
+ * @mixins OO.ui.mixin.ClippableElement
+ * @mixins OO.ui.mixin.TabIndexedElement
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [header] Text to display at the top of the popup
+ */
+OO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( toolbar ) && config === undefined ) {
+ config = toolbar;
+ toolbar = config.toolbar;
+ }
+
+ // Configuration initialization
+ config = $.extend( {
+ indicator: config.indicator === undefined ? ( toolbar.position === 'bottom' ? 'up' : 'down' ) : config.indicator
+ }, config );
+
+ // Parent constructor
+ OO.ui.PopupToolGroup.parent.call( this, toolbar, config );
+
+ // Properties
+ this.active = false;
+ this.dragging = false;
+ this.onBlurHandler = this.onBlur.bind( this );
+ this.$handle = $( '<span>' );
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.IndicatorElement.call( this, config );
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.TitledElement.call( this, config );
+ OO.ui.mixin.FlaggedElement.call( this, config );
+ OO.ui.mixin.ClippableElement.call( this, $.extend( {}, config, { $clippable: this.$group } ) );
+ OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$handle } ) );
+
+ // Events
+ this.$handle.on( {
+ keydown: this.onHandleMouseKeyDown.bind( this ),
+ keyup: this.onHandleMouseKeyUp.bind( this ),
+ mousedown: this.onHandleMouseKeyDown.bind( this ),
+ mouseup: this.onHandleMouseKeyUp.bind( this )
+ } );
+
+ // Initialization
+ this.$handle
+ .addClass( 'oo-ui-popupToolGroup-handle' )
+ .attr( 'role', 'button' )
+ .append( this.$icon, this.$label, this.$indicator );
+ // If the pop-up should have a header, add it to the top of the toolGroup.
+ // Note: If this feature is useful for other widgets, we could abstract it into an
+ // OO.ui.HeaderedElement mixin constructor.
+ if ( config.header !== undefined ) {
+ this.$group
+ .prepend( $( '<span>' )
+ .addClass( 'oo-ui-popupToolGroup-header' )
+ .text( config.header )
+ );
+ }
+ this.$element
+ .addClass( 'oo-ui-popupToolGroup' )
+ .prepend( this.$handle );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PopupToolGroup, OO.ui.ToolGroup );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.IndicatorElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.TitledElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.FlaggedElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.ClippableElement );
+OO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.TabIndexedElement );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.PopupToolGroup.prototype.setDisabled = function () {
+ // Parent method
+ OO.ui.PopupToolGroup.parent.prototype.setDisabled.apply( this, arguments );
+
+ if ( this.isDisabled() && this.isElementAttached() ) {
+ this.setActive( false );
+ }
+};
+
+/**
+ * Handle focus being lost.
+ *
+ * The event is actually generated from a mouseup/keyup, so it is not a normal blur event object.
+ *
+ * @protected
+ * @param {MouseEvent|KeyboardEvent} e Mouse up or key up event
+ */
+OO.ui.PopupToolGroup.prototype.onBlur = function ( e ) {
+ // Only deactivate when clicking outside the dropdown element
+ if ( $( e.target ).closest( '.oo-ui-popupToolGroup' )[ 0 ] !== this.$element[ 0 ] ) {
+ this.setActive( false );
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.PopupToolGroup.prototype.onMouseKeyUp = function ( e ) {
+ // Only close toolgroup when a tool was actually selected
+ if (
+ !this.isDisabled() && this.pressed && this.pressed === this.findTargetTool( e ) &&
+ ( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
+ ) {
+ this.setActive( false );
+ }
+ return OO.ui.PopupToolGroup.parent.prototype.onMouseKeyUp.call( this, e );
+};
+
+/**
+ * Handle mouse up and key up events.
+ *
+ * @protected
+ * @param {jQuery.Event} e Mouse up or key up event
+ */
+OO.ui.PopupToolGroup.prototype.onHandleMouseKeyUp = function ( e ) {
+ if (
+ !this.isDisabled() &&
+ ( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
+ ) {
+ return false;
+ }
+};
+
+/**
+ * Handle mouse down and key down events.
+ *
+ * @protected
+ * @param {jQuery.Event} e Mouse down or key down event
+ */
+OO.ui.PopupToolGroup.prototype.onHandleMouseKeyDown = function ( e ) {
+ if (
+ !this.isDisabled() &&
+ ( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
+ ) {
+ this.setActive( !this.active );
+ return false;
+ }
+};
+
+/**
+ * Switch into 'active' mode.
+ *
+ * When active, the popup is visible. A mouseup event anywhere in the document will trigger
+ * deactivation.
+ *
+ * @param {boolean} value The active state to set
+ */
+OO.ui.PopupToolGroup.prototype.setActive = function ( value ) {
+ var containerWidth, containerLeft;
+ value = !!value;
+ if ( this.active !== value ) {
+ this.active = value;
+ if ( value ) {
+ this.getElementDocument().addEventListener( 'mouseup', this.onBlurHandler, true );
+ this.getElementDocument().addEventListener( 'keyup', this.onBlurHandler, true );
+
+ this.$clippable.css( 'left', '' );
+ // Try anchoring the popup to the left first
+ this.$element.addClass( 'oo-ui-popupToolGroup-active oo-ui-popupToolGroup-left' );
+ this.toggleClipping( true );
+ if ( this.isClippedHorizontally() ) {
+ // Anchoring to the left caused the popup to clip, so anchor it to the right instead
+ this.toggleClipping( false );
+ this.$element
+ .removeClass( 'oo-ui-popupToolGroup-left' )
+ .addClass( 'oo-ui-popupToolGroup-right' );
+ this.toggleClipping( true );
+ }
+ if ( this.isClippedHorizontally() ) {
+ // Anchoring to the right also caused the popup to clip, so just make it fill the container
+ containerWidth = this.$clippableScrollableContainer.width();
+ containerLeft = this.$clippableScrollableContainer.offset().left;
+
+ this.toggleClipping( false );
+ this.$element.removeClass( 'oo-ui-popupToolGroup-right' );
+
+ this.$clippable.css( {
+ left: -( this.$element.offset().left - containerLeft ),
+ width: containerWidth
+ } );
+ }
+ } else {
+ this.getElementDocument().removeEventListener( 'mouseup', this.onBlurHandler, true );
+ this.getElementDocument().removeEventListener( 'keyup', this.onBlurHandler, true );
+ this.$element.removeClass(
+ 'oo-ui-popupToolGroup-active oo-ui-popupToolGroup-left oo-ui-popupToolGroup-right'
+ );
+ this.toggleClipping( false );
+ }
+ }
+};
+
+/**
+ * ListToolGroups are one of three types of {@link OO.ui.ToolGroup toolgroups} that are used to
+ * create {@link OO.ui.Toolbar toolbars} (the other types of groups are {@link OO.ui.MenuToolGroup MenuToolGroup}
+ * and {@link OO.ui.BarToolGroup BarToolGroup}). The {@link OO.ui.Tool tools} in a ListToolGroup are displayed
+ * by label in a dropdown menu. The title of the tool is used as the label text. The menu itself can be configured
+ * with a label, icon, indicator, header, and title.
+ *
+ * ListToolGroups can be configured to be expanded and collapsed. Collapsed lists will have a ‘More’ option that
+ * users can select to see the full list of tools. If a collapsed toolgroup is expanded, a ‘Fewer’ option permits
+ * users to collapse the list again.
+ *
+ * ListToolGroups are created by a {@link OO.ui.ToolGroupFactory toolgroup factory} when the toolbar is set up. The factory
+ * requires the ListToolGroup's symbolic name, 'list', which is specified along with the other configurations. For more
+ * information about how to add tools to a ListToolGroup, please see {@link OO.ui.ToolGroup toolgroup}.
+ *
+ * @example
+ * // Example of a ListToolGroup
+ * var toolFactory = new OO.ui.ToolFactory();
+ * var toolGroupFactory = new OO.ui.ToolGroupFactory();
+ * var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory );
+ *
+ * // Configure and register two tools
+ * function SettingsTool() {
+ * SettingsTool.parent.apply( this, arguments );
+ * }
+ * OO.inheritClass( SettingsTool, OO.ui.Tool );
+ * SettingsTool.static.name = 'settings';
+ * SettingsTool.static.icon = 'settings';
+ * SettingsTool.static.title = 'Change settings';
+ * SettingsTool.prototype.onSelect = function () {
+ * this.setActive( false );
+ * };
+ * SettingsTool.prototype.onUpdateState = function () {};
+ * toolFactory.register( SettingsTool );
+ * // Register two more tools, nothing interesting here
+ * function StuffTool() {
+ * StuffTool.parent.apply( this, arguments );
+ * }
+ * OO.inheritClass( StuffTool, OO.ui.Tool );
+ * StuffTool.static.name = 'stuff';
+ * StuffTool.static.icon = 'search';
+ * StuffTool.static.title = 'Change the world';
+ * StuffTool.prototype.onSelect = function () {
+ * this.setActive( false );
+ * };
+ * StuffTool.prototype.onUpdateState = function () {};
+ * toolFactory.register( StuffTool );
+ * toolbar.setup( [
+ * {
+ * // Configurations for list toolgroup.
+ * type: 'list',
+ * label: 'ListToolGroup',
+ * icon: 'ellipsis',
+ * title: 'This is the title, displayed when user moves the mouse over the list toolgroup',
+ * header: 'This is the header',
+ * include: [ 'settings', 'stuff' ],
+ * allowCollapse: ['stuff']
+ * }
+ * ] );
+ *
+ * // Create some UI around the toolbar and place it in the document
+ * var frame = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * framed: true
+ * } );
+ * frame.$element.append(
+ * toolbar.$element
+ * );
+ * $( 'body' ).append( frame.$element );
+ * // Build the toolbar. This must be done after the toolbar has been appended to the document.
+ * toolbar.initialize();
+ *
+ * For more information about toolbars in general, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars
+ *
+ * @class
+ * @extends OO.ui.PopupToolGroup
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ * @cfg {Array} [allowCollapse] Allow the specified tools to be collapsed. By default, collapsible tools
+ * will only be displayed if users click the ‘More’ option displayed at the bottom of the list. If
+ * the list is expanded, a ‘Fewer’ option permits users to collapse the list again. Any tools that
+ * are included in the toolgroup, but are not designated as collapsible, will always be displayed.
+ * To open a collapsible list in its expanded state, set #expanded to 'true'.
+ * @cfg {Array} [forceExpand] Expand the specified tools. All other tools will be designated as collapsible.
+ * Unless #expanded is set to true, the collapsible tools will be collapsed when the list is first opened.
+ * @cfg {boolean} [expanded=false] Expand collapsible tools. This config is only relevant if tools have
+ * been designated as collapsible. When expanded is set to true, all tools in the group will be displayed
+ * when the list is first opened. Users can collapse the list with a ‘Fewer’ option at the bottom.
+ */
+OO.ui.ListToolGroup = function OoUiListToolGroup( toolbar, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( toolbar ) && config === undefined ) {
+ config = toolbar;
+ toolbar = config.toolbar;
+ }
+
+ // Configuration initialization
+ config = config || {};
+
+ // Properties (must be set before parent constructor, which calls #populate)
+ this.allowCollapse = config.allowCollapse;
+ this.forceExpand = config.forceExpand;
+ this.expanded = config.expanded !== undefined ? config.expanded : false;
+ this.collapsibleTools = [];
+
+ // Parent constructor
+ OO.ui.ListToolGroup.parent.call( this, toolbar, config );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-listToolGroup' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ListToolGroup, OO.ui.PopupToolGroup );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.ListToolGroup.static.name = 'list';
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ListToolGroup.prototype.populate = function () {
+ var i, len, allowCollapse = [];
+
+ OO.ui.ListToolGroup.parent.prototype.populate.call( this );
+
+ // Update the list of collapsible tools
+ if ( this.allowCollapse !== undefined ) {
+ allowCollapse = this.allowCollapse;
+ } else if ( this.forceExpand !== undefined ) {
+ allowCollapse = OO.simpleArrayDifference( Object.keys( this.tools ), this.forceExpand );
+ }
+
+ this.collapsibleTools = [];
+ for ( i = 0, len = allowCollapse.length; i < len; i++ ) {
+ if ( this.tools[ allowCollapse[ i ] ] !== undefined ) {
+ this.collapsibleTools.push( this.tools[ allowCollapse[ i ] ] );
+ }
+ }
+
+ // Keep at the end, even when tools are added
+ this.$group.append( this.getExpandCollapseTool().$element );
+
+ this.getExpandCollapseTool().toggle( this.collapsibleTools.length !== 0 );
+ this.updateCollapsibleState();
+};
+
+/**
+ * Get the expand/collapse tool for this group
+ *
+ * @return {OO.ui.Tool} Expand collapse tool
+ */
+OO.ui.ListToolGroup.prototype.getExpandCollapseTool = function () {
+ var ExpandCollapseTool;
+ if ( this.expandCollapseTool === undefined ) {
+ ExpandCollapseTool = function () {
+ ExpandCollapseTool.parent.apply( this, arguments );
+ };
+
+ OO.inheritClass( ExpandCollapseTool, OO.ui.Tool );
+
+ ExpandCollapseTool.prototype.onSelect = function () {
+ this.toolGroup.expanded = !this.toolGroup.expanded;
+ this.toolGroup.updateCollapsibleState();
+ this.setActive( false );
+ };
+ ExpandCollapseTool.prototype.onUpdateState = function () {
+ // Do nothing. Tool interface requires an implementation of this function.
+ };
+
+ ExpandCollapseTool.static.name = 'more-fewer';
+
+ this.expandCollapseTool = new ExpandCollapseTool( this );
+ }
+ return this.expandCollapseTool;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ListToolGroup.prototype.onMouseKeyUp = function ( e ) {
+ // Do not close the popup when the user wants to show more/fewer tools
+ if (
+ $( e.target ).closest( '.oo-ui-tool-name-more-fewer' ).length &&
+ ( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
+ ) {
+ // HACK: Prevent the popup list from being hidden. Skip the PopupToolGroup implementation (which
+ // hides the popup list when a tool is selected) and call ToolGroup's implementation directly.
+ return OO.ui.ListToolGroup.parent.parent.prototype.onMouseKeyUp.call( this, e );
+ } else {
+ return OO.ui.ListToolGroup.parent.prototype.onMouseKeyUp.call( this, e );
+ }
+};
+
+OO.ui.ListToolGroup.prototype.updateCollapsibleState = function () {
+ var i, len;
+
+ this.getExpandCollapseTool()
+ .setIcon( this.expanded ? 'collapse' : 'expand' )
+ .setTitle( OO.ui.msg( this.expanded ? 'ooui-toolgroup-collapse' : 'ooui-toolgroup-expand' ) );
+
+ for ( i = 0, len = this.collapsibleTools.length; i < len; i++ ) {
+ this.collapsibleTools[ i ].toggle( this.expanded );
+ }
+
+ // Re-evaluate clipping, because our height has changed
+ this.clip();
+};
+
+/**
+ * MenuToolGroups are one of three types of {@link OO.ui.ToolGroup toolgroups} that are used to
+ * create {@link OO.ui.Toolbar toolbars} (the other types of groups are {@link OO.ui.BarToolGroup BarToolGroup}
+ * and {@link OO.ui.ListToolGroup ListToolGroup}). MenuToolGroups contain selectable {@link OO.ui.Tool tools},
+ * which are displayed by label in a dropdown menu. The tool's title is used as the label text, and the
+ * menu label is updated to reflect which tool or tools are currently selected. If no tools are selected,
+ * the menu label is empty. The menu can be configured with an indicator, icon, title, and/or header.
+ *
+ * MenuToolGroups are created by a {@link OO.ui.ToolGroupFactory tool group factory} when the toolbar
+ * is set up.
+ *
+ * @example
+ * // Example of a MenuToolGroup
+ * var toolFactory = new OO.ui.ToolFactory();
+ * var toolGroupFactory = new OO.ui.ToolGroupFactory();
+ * var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory );
+ *
+ * // We will be placing status text in this element when tools are used
+ * var $area = $( '<p>' ).text( 'An example of a MenuToolGroup. Select a tool from the dropdown menu.' );
+ *
+ * // Define the tools that we're going to place in our toolbar
+ *
+ * function SettingsTool() {
+ * SettingsTool.parent.apply( this, arguments );
+ * this.reallyActive = false;
+ * }
+ * OO.inheritClass( SettingsTool, OO.ui.Tool );
+ * SettingsTool.static.name = 'settings';
+ * SettingsTool.static.icon = 'settings';
+ * SettingsTool.static.title = 'Change settings';
+ * SettingsTool.prototype.onSelect = function () {
+ * $area.text( 'Settings tool clicked!' );
+ * // Toggle the active state on each click
+ * this.reallyActive = !this.reallyActive;
+ * this.setActive( this.reallyActive );
+ * // To update the menu label
+ * this.toolbar.emit( 'updateState' );
+ * };
+ * SettingsTool.prototype.onUpdateState = function () {};
+ * toolFactory.register( SettingsTool );
+ *
+ * function StuffTool() {
+ * StuffTool.parent.apply( this, arguments );
+ * this.reallyActive = false;
+ * }
+ * OO.inheritClass( StuffTool, OO.ui.Tool );
+ * StuffTool.static.name = 'stuff';
+ * StuffTool.static.icon = 'ellipsis';
+ * StuffTool.static.title = 'More stuff';
+ * StuffTool.prototype.onSelect = function () {
+ * $area.text( 'More stuff tool clicked!' );
+ * // Toggle the active state on each click
+ * this.reallyActive = !this.reallyActive;
+ * this.setActive( this.reallyActive );
+ * // To update the menu label
+ * this.toolbar.emit( 'updateState' );
+ * };
+ * StuffTool.prototype.onUpdateState = function () {};
+ * toolFactory.register( StuffTool );
+ *
+ * // Finally define which tools and in what order appear in the toolbar. Each tool may only be
+ * // used once (but not all defined tools must be used).
+ * toolbar.setup( [
+ * {
+ * type: 'menu',
+ * header: 'This is the (optional) header',
+ * title: 'This is the (optional) title',
+ * include: [ 'settings', 'stuff' ]
+ * }
+ * ] );
+ *
+ * // Create some UI around the toolbar and place it in the document
+ * var frame = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * framed: true
+ * } );
+ * var contentFrame = new OO.ui.PanelLayout( {
+ * expanded: false,
+ * padded: true
+ * } );
+ * frame.$element.append(
+ * toolbar.$element,
+ * contentFrame.$element.append( $area )
+ * );
+ * $( 'body' ).append( frame.$element );
+ *
+ * // Here is where the toolbar is actually built. This must be done after inserting it into the
+ * // document.
+ * toolbar.initialize();
+ * toolbar.emit( 'updateState' );
+ *
+ * For more information about how to add tools to a MenuToolGroup, please see {@link OO.ui.ToolGroup toolgroup}.
+ * For more information about toolbars in general, please see the [OOjs UI documentation on MediaWiki] [1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars
+ *
+ * @class
+ * @extends OO.ui.PopupToolGroup
+ *
+ * @constructor
+ * @param {OO.ui.Toolbar} toolbar
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.MenuToolGroup = function OoUiMenuToolGroup( toolbar, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( toolbar ) && config === undefined ) {
+ config = toolbar;
+ toolbar = config.toolbar;
+ }
+
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.MenuToolGroup.parent.call( this, toolbar, config );
+
+ // Events
+ this.toolbar.connect( this, { updateState: 'onUpdateState' } );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-menuToolGroup' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MenuToolGroup, OO.ui.PopupToolGroup );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.MenuToolGroup.static.name = 'menu';
+
+/* Methods */
+
+/**
+ * Handle the toolbar state being updated.
+ *
+ * When the state changes, the title of each active item in the menu will be joined together and
+ * used as a label for the group. The label will be empty if none of the items are active.
+ *
+ * @private
+ */
+OO.ui.MenuToolGroup.prototype.onUpdateState = function () {
+ var name,
+ labelTexts = [];
+
+ for ( name in this.tools ) {
+ if ( this.tools[ name ].isActive() ) {
+ labelTexts.push( this.tools[ name ].getTitle() );
+ }
+ }
+
+ this.setLabel( labelTexts.join( ', ' ) || ' ' );
+};
+
+}( OO ) );
+
+//# sourceMappingURL=oojs-ui-toolbars.js.map \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars.js.map b/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars.js.map
new file mode 100644
index 00000000..0c1c4bb3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-toolbars.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/intro.js.txt","../src/Toolbar.js","../src/Tool.js","../src/ToolGroup.js","../src/ToolFactory.js","../src/ToolGroupFactory.js","../src/tools/PopupTool.js","../src/tools/ToolGroupTool.js","../src/toolgroups/BarToolGroup.js","../src/toolgroups/PopupToolGroup.js","../src/toolgroups/ListToolGroup.js","../src/toolgroups/MenuToolGroup.js","../src/outro.js.txt"],"names":[],"mappings":"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","file":"oojs-ui-toolbars.js","sourcesContent":["( function ( OO ) {\n\n'use strict';\n","/**\n * Toolbars are complex interface components that permit users to easily access a variety\n * of {@link OO.ui.Tool tools} (e.g., formatting commands) and actions, which are additional commands that are\n * part of the toolbar, but not configured as tools.\n *\n * Individual tools are customized and then registered with a {@link OO.ui.ToolFactory tool factory}, which creates\n * the tools on demand. Each tool has a symbolic name (used when registering the tool), a title (e.g., ‘Insert\n * image’), and an icon.\n *\n * Individual tools are organized in {@link OO.ui.ToolGroup toolgroups}, which can be {@link OO.ui.MenuToolGroup menus}\n * of tools, {@link OO.ui.ListToolGroup lists} of tools, or a single {@link OO.ui.BarToolGroup bar} of tools.\n * The arrangement and order of the toolgroups is customized when the toolbar is set up. Tools can be presented in\n * any order, but each can only appear once in the toolbar.\n *\n * The toolbar can be synchronized with the state of the external \"application\", like a text\n * editor's editing area, marking tools as active/inactive (e.g. a 'bold' tool would be shown as\n * active when the text cursor was inside bolded text) or enabled/disabled (e.g. a table caption\n * tool would be disabled while the user is not editing a table). A state change is signalled by\n * emitting the {@link #event-updateState 'updateState' event}, which calls Tools'\n * {@link OO.ui.Tool#onUpdateState onUpdateState method}.\n *\n * The following is an example of a basic toolbar.\n *\n * @example\n * // Example of a toolbar\n * // Create the toolbar\n * var toolFactory = new OO.ui.ToolFactory();\n * var toolGroupFactory = new OO.ui.ToolGroupFactory();\n * var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory );\n *\n * // We will be placing status text in this element when tools are used\n * var $area = $( '<p>' ).text( 'Toolbar example' );\n *\n * // Define the tools that we're going to place in our toolbar\n *\n * // Create a class inheriting from OO.ui.Tool\n * function SearchTool() {\n * SearchTool.parent.apply( this, arguments );\n * }\n * OO.inheritClass( SearchTool, OO.ui.Tool );\n * // Each tool must have a 'name' (used as an internal identifier, see later) and at least one\n * // of 'icon' and 'title' (displayed icon and text).\n * SearchTool.static.name = 'search';\n * SearchTool.static.icon = 'search';\n * SearchTool.static.title = 'Search...';\n * // Defines the action that will happen when this tool is selected (clicked).\n * SearchTool.prototype.onSelect = function () {\n * $area.text( 'Search tool clicked!' );\n * // Never display this tool as \"active\" (selected).\n * this.setActive( false );\n * };\n * SearchTool.prototype.onUpdateState = function () {};\n * // Make this tool available in our toolFactory and thus our toolbar\n * toolFactory.register( SearchTool );\n *\n * // Register two more tools, nothing interesting here\n * function SettingsTool() {\n * SettingsTool.parent.apply( this, arguments );\n * }\n * OO.inheritClass( SettingsTool, OO.ui.Tool );\n * SettingsTool.static.name = 'settings';\n * SettingsTool.static.icon = 'settings';\n * SettingsTool.static.title = 'Change settings';\n * SettingsTool.prototype.onSelect = function () {\n * $area.text( 'Settings tool clicked!' );\n * this.setActive( false );\n * };\n * SettingsTool.prototype.onUpdateState = function () {};\n * toolFactory.register( SettingsTool );\n *\n * // Register two more tools, nothing interesting here\n * function StuffTool() {\n * StuffTool.parent.apply( this, arguments );\n * }\n * OO.inheritClass( StuffTool, OO.ui.Tool );\n * StuffTool.static.name = 'stuff';\n * StuffTool.static.icon = 'ellipsis';\n * StuffTool.static.title = 'More stuff';\n * StuffTool.prototype.onSelect = function () {\n * $area.text( 'More stuff tool clicked!' );\n * this.setActive( false );\n * };\n * StuffTool.prototype.onUpdateState = function () {};\n * toolFactory.register( StuffTool );\n *\n * // This is a PopupTool. Rather than having a custom 'onSelect' action, it will display a\n * // little popup window (a PopupWidget).\n * function HelpTool( toolGroup, config ) {\n * OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {\n * padded: true,\n * label: 'Help',\n * head: true\n * } }, config ) );\n * this.popup.$body.append( '<p>I am helpful!</p>' );\n * }\n * OO.inheritClass( HelpTool, OO.ui.PopupTool );\n * HelpTool.static.name = 'help';\n * HelpTool.static.icon = 'help';\n * HelpTool.static.title = 'Help';\n * toolFactory.register( HelpTool );\n *\n * // Finally define which tools and in what order appear in the toolbar. Each tool may only be\n * // used once (but not all defined tools must be used).\n * toolbar.setup( [\n * {\n * // 'bar' tool groups display tools' icons only, side-by-side.\n * type: 'bar',\n * include: [ 'search', 'help' ]\n * },\n * {\n * // 'list' tool groups display both the titles and icons, in a dropdown list.\n * type: 'list',\n * indicator: 'down',\n * label: 'More',\n * include: [ 'settings', 'stuff' ]\n * }\n * // Note how the tools themselves are toolgroup-agnostic - the same tool can be displayed\n * // either in a 'list' or a 'bar'. There is a 'menu' tool group too, not showcased here,\n * // since it's more complicated to use. (See the next example snippet on this page.)\n * ] );\n *\n * // Create some UI around the toolbar and place it in the document\n * var frame = new OO.ui.PanelLayout( {\n * expanded: false,\n * framed: true\n * } );\n * var contentFrame = new OO.ui.PanelLayout( {\n * expanded: false,\n * padded: true\n * } );\n * frame.$element.append(\n * toolbar.$element,\n * contentFrame.$element.append( $area )\n * );\n * $( 'body' ).append( frame.$element );\n *\n * // Here is where the toolbar is actually built. This must be done after inserting it into the\n * // document.\n * toolbar.initialize();\n * toolbar.emit( 'updateState' );\n *\n * The following example extends the previous one to illustrate 'menu' toolgroups and the usage of\n * {@link #event-updateState 'updateState' event}.\n *\n * @example\n * // Create the toolbar\n * var toolFactory = new OO.ui.ToolFactory();\n * var toolGroupFactory = new OO.ui.ToolGroupFactory();\n * var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory );\n *\n * // We will be placing status text in this element when tools are used\n * var $area = $( '<p>' ).text( 'Toolbar example' );\n *\n * // Define the tools that we're going to place in our toolbar\n *\n * // Create a class inheriting from OO.ui.Tool\n * function SearchTool() {\n * SearchTool.parent.apply( this, arguments );\n * }\n * OO.inheritClass( SearchTool, OO.ui.Tool );\n * // Each tool must have a 'name' (used as an internal identifier, see later) and at least one\n * // of 'icon' and 'title' (displayed icon and text).\n * SearchTool.static.name = 'search';\n * SearchTool.static.icon = 'search';\n * SearchTool.static.title = 'Search...';\n * // Defines the action that will happen when this tool is selected (clicked).\n * SearchTool.prototype.onSelect = function () {\n * $area.text( 'Search tool clicked!' );\n * // Never display this tool as \"active\" (selected).\n * this.setActive( false );\n * };\n * SearchTool.prototype.onUpdateState = function () {};\n * // Make this tool available in our toolFactory and thus our toolbar\n * toolFactory.register( SearchTool );\n *\n * // Register two more tools, nothing interesting here\n * function SettingsTool() {\n * SettingsTool.parent.apply( this, arguments );\n * this.reallyActive = false;\n * }\n * OO.inheritClass( SettingsTool, OO.ui.Tool );\n * SettingsTool.static.name = 'settings';\n * SettingsTool.static.icon = 'settings';\n * SettingsTool.static.title = 'Change settings';\n * SettingsTool.prototype.onSelect = function () {\n * $area.text( 'Settings tool clicked!' );\n * // Toggle the active state on each click\n * this.reallyActive = !this.reallyActive;\n * this.setActive( this.reallyActive );\n * // To update the menu label\n * this.toolbar.emit( 'updateState' );\n * };\n * SettingsTool.prototype.onUpdateState = function () {};\n * toolFactory.register( SettingsTool );\n *\n * // Register two more tools, nothing interesting here\n * function StuffTool() {\n * StuffTool.parent.apply( this, arguments );\n * this.reallyActive = false;\n * }\n * OO.inheritClass( StuffTool, OO.ui.Tool );\n * StuffTool.static.name = 'stuff';\n * StuffTool.static.icon = 'ellipsis';\n * StuffTool.static.title = 'More stuff';\n * StuffTool.prototype.onSelect = function () {\n * $area.text( 'More stuff tool clicked!' );\n * // Toggle the active state on each click\n * this.reallyActive = !this.reallyActive;\n * this.setActive( this.reallyActive );\n * // To update the menu label\n * this.toolbar.emit( 'updateState' );\n * };\n * StuffTool.prototype.onUpdateState = function () {};\n * toolFactory.register( StuffTool );\n *\n * // This is a PopupTool. Rather than having a custom 'onSelect' action, it will display a\n * // little popup window (a PopupWidget). 'onUpdateState' is also already implemented.\n * function HelpTool( toolGroup, config ) {\n * OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {\n * padded: true,\n * label: 'Help',\n * head: true\n * } }, config ) );\n * this.popup.$body.append( '<p>I am helpful!</p>' );\n * }\n * OO.inheritClass( HelpTool, OO.ui.PopupTool );\n * HelpTool.static.name = 'help';\n * HelpTool.static.icon = 'help';\n * HelpTool.static.title = 'Help';\n * toolFactory.register( HelpTool );\n *\n * // Finally define which tools and in what order appear in the toolbar. Each tool may only be\n * // used once (but not all defined tools must be used).\n * toolbar.setup( [\n * {\n * // 'bar' tool groups display tools' icons only, side-by-side.\n * type: 'bar',\n * include: [ 'search', 'help' ]\n * },\n * {\n * // 'menu' tool groups display both the titles and icons, in a dropdown menu.\n * // Menu label indicates which items are selected.\n * type: 'menu',\n * indicator: 'down',\n * include: [ 'settings', 'stuff' ]\n * }\n * ] );\n *\n * // Create some UI around the toolbar and place it in the document\n * var frame = new OO.ui.PanelLayout( {\n * expanded: false,\n * framed: true\n * } );\n * var contentFrame = new OO.ui.PanelLayout( {\n * expanded: false,\n * padded: true\n * } );\n * frame.$element.append(\n * toolbar.$element,\n * contentFrame.$element.append( $area )\n * );\n * $( 'body' ).append( frame.$element );\n *\n * // Here is where the toolbar is actually built. This must be done after inserting it into the\n * // document.\n * toolbar.initialize();\n * toolbar.emit( 'updateState' );\n *\n * @class\n * @extends OO.ui.Element\n * @mixins OO.EventEmitter\n * @mixins OO.ui.mixin.GroupElement\n *\n * @constructor\n * @param {OO.ui.ToolFactory} toolFactory Factory for creating tools\n * @param {OO.ui.ToolGroupFactory} toolGroupFactory Factory for creating toolgroups\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [actions] Add an actions section to the toolbar. Actions are commands that are included\n * in the toolbar, but are not configured as tools. By default, actions are displayed on the right side of\n * the toolbar.\n * @cfg {string} [position='top'] Whether the toolbar is positioned above ('top') or below ('bottom') content.\n */\nOO.ui.Toolbar = function OoUiToolbar( toolFactory, toolGroupFactory, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( toolFactory ) && config === undefined ) {\n\t\tconfig = toolFactory;\n\t\ttoolFactory = config.toolFactory;\n\t\ttoolGroupFactory = config.toolGroupFactory;\n\t}\n\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.Toolbar.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.EventEmitter.call( this );\n\tOO.ui.mixin.GroupElement.call( this, config );\n\n\t// Properties\n\tthis.toolFactory = toolFactory;\n\tthis.toolGroupFactory = toolGroupFactory;\n\tthis.groups = [];\n\tthis.tools = {};\n\tthis.position = config.position || 'top';\n\tthis.$bar = $( '<div>' );\n\tthis.$actions = $( '<div>' );\n\tthis.initialized = false;\n\tthis.narrowThreshold = null;\n\tthis.onWindowResizeHandler = this.onWindowResize.bind( this );\n\n\t// Events\n\tthis.$element\n\t\t.add( this.$bar ).add( this.$group ).add( this.$actions )\n\t\t.on( 'mousedown keydown', this.onPointerDown.bind( this ) );\n\n\t// Initialization\n\tthis.$group.addClass( 'oo-ui-toolbar-tools' );\n\tif ( config.actions ) {\n\t\tthis.$bar.append( this.$actions.addClass( 'oo-ui-toolbar-actions' ) );\n\t}\n\tthis.$bar\n\t\t.addClass( 'oo-ui-toolbar-bar' )\n\t\t.append( this.$group, '<div style=\"clear:both\"></div>' );\n\t// Possible classes: oo-ui-toolbar-position-top, oo-ui-toolbar-position-bottom\n\tthis.$element.addClass( 'oo-ui-toolbar oo-ui-toolbar-position-' + this.position ).append( this.$bar );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.Toolbar, OO.ui.Element );\nOO.mixinClass( OO.ui.Toolbar, OO.EventEmitter );\nOO.mixinClass( OO.ui.Toolbar, OO.ui.mixin.GroupElement );\n\n/* Events */\n\n/**\n * @event updateState\n *\n * An 'updateState' event must be emitted on the Toolbar (by calling `toolbar.emit( 'updateState' )`)\n * every time the state of the application using the toolbar changes, and an update to the state of\n * tools is required.\n *\n * @param {...Mixed} data Application-defined parameters\n */\n\n/* Methods */\n\n/**\n * Get the tool factory.\n *\n * @return {OO.ui.ToolFactory} Tool factory\n */\nOO.ui.Toolbar.prototype.getToolFactory = function () {\n\treturn this.toolFactory;\n};\n\n/**\n * Get the toolgroup factory.\n *\n * @return {OO.Factory} Toolgroup factory\n */\nOO.ui.Toolbar.prototype.getToolGroupFactory = function () {\n\treturn this.toolGroupFactory;\n};\n\n/**\n * Handles mouse down events.\n *\n * @private\n * @param {jQuery.Event} e Mouse down event\n */\nOO.ui.Toolbar.prototype.onPointerDown = function ( e ) {\n\tvar $closestWidgetToEvent = $( e.target ).closest( '.oo-ui-widget' ),\n\t\t$closestWidgetToToolbar = this.$element.closest( '.oo-ui-widget' );\n\tif ( !$closestWidgetToEvent.length || $closestWidgetToEvent[ 0 ] === $closestWidgetToToolbar[ 0 ] ) {\n\t\treturn false;\n\t}\n};\n\n/**\n * Handle window resize event.\n *\n * @private\n * @param {jQuery.Event} e Window resize event\n */\nOO.ui.Toolbar.prototype.onWindowResize = function () {\n\tthis.$element.toggleClass(\n\t\t'oo-ui-toolbar-narrow',\n\t\tthis.$bar.width() <= this.getNarrowThreshold()\n\t);\n};\n\n/**\n * Get the (lazily-computed) width threshold for applying the oo-ui-toolbar-narrow\n * class.\n *\n * @private\n * @return {number} Width threshold in pixels\n */\nOO.ui.Toolbar.prototype.getNarrowThreshold = function () {\n\tif ( this.narrowThreshold === null ) {\n\t\tthis.narrowThreshold = this.$group.width() + this.$actions.width();\n\t}\n\treturn this.narrowThreshold;\n};\n\n/**\n * Sets up handles and preloads required information for the toolbar to work.\n * This must be called after it is attached to a visible document and before doing anything else.\n */\nOO.ui.Toolbar.prototype.initialize = function () {\n\tif ( !this.initialized ) {\n\t\tthis.initialized = true;\n\t\t$( this.getElementWindow() ).on( 'resize', this.onWindowResizeHandler );\n\t\tthis.onWindowResize();\n\t}\n};\n\n/**\n * Set up the toolbar.\n *\n * The toolbar is set up with a list of toolgroup configurations that specify the type of\n * toolgroup ({@link OO.ui.BarToolGroup bar}, {@link OO.ui.MenuToolGroup menu}, or {@link OO.ui.ListToolGroup list})\n * to add and which tools to include, exclude, promote, or demote within that toolgroup. Please\n * see {@link OO.ui.ToolGroup toolgroups} for more information about including tools in toolgroups.\n *\n * @param {Object.<string,Array>} groups List of toolgroup configurations\n * @param {Array|string} [groups.include] Tools to include in the toolgroup\n * @param {Array|string} [groups.exclude] Tools to exclude from the toolgroup\n * @param {Array|string} [groups.promote] Tools to promote to the beginning of the toolgroup\n * @param {Array|string} [groups.demote] Tools to demote to the end of the toolgroup\n */\nOO.ui.Toolbar.prototype.setup = function ( groups ) {\n\tvar i, len, type, group,\n\t\titems = [],\n\t\tdefaultType = 'bar';\n\n\t// Cleanup previous groups\n\tthis.reset();\n\n\t// Build out new groups\n\tfor ( i = 0, len = groups.length; i < len; i++ ) {\n\t\tgroup = groups[ i ];\n\t\tif ( group.include === '*' ) {\n\t\t\t// Apply defaults to catch-all groups\n\t\t\tif ( group.type === undefined ) {\n\t\t\t\tgroup.type = 'list';\n\t\t\t}\n\t\t\tif ( group.label === undefined ) {\n\t\t\t\tgroup.label = OO.ui.msg( 'ooui-toolbar-more' );\n\t\t\t}\n\t\t}\n\t\t// Check type has been registered\n\t\ttype = this.getToolGroupFactory().lookup( group.type ) ? group.type : defaultType;\n\t\titems.push(\n\t\t\tthis.getToolGroupFactory().create( type, this, group )\n\t\t);\n\t}\n\tthis.addItems( items );\n};\n\n/**\n * Remove all tools and toolgroups from the toolbar.\n */\nOO.ui.Toolbar.prototype.reset = function () {\n\tvar i, len;\n\n\tthis.groups = [];\n\tthis.tools = {};\n\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\tthis.items[ i ].destroy();\n\t}\n\tthis.clearItems();\n};\n\n/**\n * Destroy the toolbar.\n *\n * Destroying the toolbar removes all event handlers and DOM elements that constitute the toolbar. Call\n * this method whenever you are done using a toolbar.\n */\nOO.ui.Toolbar.prototype.destroy = function () {\n\t$( this.getElementWindow() ).off( 'resize', this.onWindowResizeHandler );\n\tthis.reset();\n\tthis.$element.remove();\n};\n\n/**\n * Check if the tool is available.\n *\n * Available tools are ones that have not yet been added to the toolbar.\n *\n * @param {string} name Symbolic name of tool\n * @return {boolean} Tool is available\n */\nOO.ui.Toolbar.prototype.isToolAvailable = function ( name ) {\n\treturn !this.tools[ name ];\n};\n\n/**\n * Prevent tool from being used again.\n *\n * @param {OO.ui.Tool} tool Tool to reserve\n */\nOO.ui.Toolbar.prototype.reserveTool = function ( tool ) {\n\tthis.tools[ tool.getName() ] = tool;\n};\n\n/**\n * Allow tool to be used again.\n *\n * @param {OO.ui.Tool} tool Tool to release\n */\nOO.ui.Toolbar.prototype.releaseTool = function ( tool ) {\n\tdelete this.tools[ tool.getName() ];\n};\n\n/**\n * Get accelerator label for tool.\n *\n * The OOjs UI library does not contain an accelerator system, but this is the hook for one. To\n * use an accelerator system, subclass the toolbar and override this method, which is meant to return a label\n * that describes the accelerator keys for the tool passed (by symbolic name) to the method.\n *\n * @param {string} name Symbolic name of tool\n * @return {string|undefined} Tool accelerator label if available\n */\nOO.ui.Toolbar.prototype.getToolAccelerator = function () {\n\treturn undefined;\n};\n","/**\n * Tools, together with {@link OO.ui.ToolGroup toolgroups}, constitute {@link OO.ui.Toolbar toolbars}.\n * Each tool is configured with a static name, title, and icon and is customized with the command to carry\n * out when the tool is selected. Tools must also be registered with a {@link OO.ui.ToolFactory tool factory},\n * which creates the tools on demand.\n *\n * Every Tool subclass must implement two methods:\n *\n * - {@link #onUpdateState}\n * - {@link #onSelect}\n *\n * Tools are added to toolgroups ({@link OO.ui.ListToolGroup ListToolGroup},\n * {@link OO.ui.BarToolGroup BarToolGroup}, or {@link OO.ui.MenuToolGroup MenuToolGroup}), which determine how\n * the tool is displayed in the toolbar. See {@link OO.ui.Toolbar toolbars} for an example.\n *\n * For more information, please see the [OOjs UI documentation on MediaWiki][1].\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars\n *\n * @abstract\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.FlaggedElement\n * @mixins OO.ui.mixin.TabIndexedElement\n *\n * @constructor\n * @param {OO.ui.ToolGroup} toolGroup\n * @param {Object} [config] Configuration options\n * @cfg {string|Function} [title] Title text or a function that returns text. If this config is omitted, the value of\n * the {@link #static-title static title} property is used.\n *\n * The title is used in different ways depending on the type of toolgroup that contains the tool. The\n * title is used as a tooltip if the tool is part of a {@link OO.ui.BarToolGroup bar} toolgroup, or as the label text if the tool is\n * part of a {@link OO.ui.ListToolGroup list} or {@link OO.ui.MenuToolGroup menu} toolgroup.\n *\n * For bar toolgroups, a description of the accelerator key is appended to the title if an accelerator key\n * is associated with an action by the same name as the tool and accelerator functionality has been added to the application.\n * To add accelerator key functionality, you must subclass OO.ui.Toolbar and override the {@link OO.ui.Toolbar#getToolAccelerator getToolAccelerator} method.\n */\nOO.ui.Tool = function OoUiTool( toolGroup, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( toolGroup ) && config === undefined ) {\n\t\tconfig = toolGroup;\n\t\ttoolGroup = config.toolGroup;\n\t}\n\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.Tool.parent.call( this, config );\n\n\t// Properties\n\tthis.toolGroup = toolGroup;\n\tthis.toolbar = this.toolGroup.getToolbar();\n\tthis.active = false;\n\tthis.$title = $( '<span>' );\n\tthis.$accel = $( '<span>' );\n\tthis.$link = $( '<a>' );\n\tthis.title = null;\n\n\t// Mixin constructors\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.FlaggedElement.call( this, config );\n\tOO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$link } ) );\n\n\t// Events\n\tthis.toolbar.connect( this, { updateState: 'onUpdateState' } );\n\n\t// Initialization\n\tthis.$title.addClass( 'oo-ui-tool-title' );\n\tthis.$accel\n\t\t.addClass( 'oo-ui-tool-accel' )\n\t\t.prop( {\n\t\t\t// This may need to be changed if the key names are ever localized,\n\t\t\t// but for now they are essentially written in English\n\t\t\tdir: 'ltr',\n\t\t\tlang: 'en'\n\t\t} );\n\tthis.$link\n\t\t.addClass( 'oo-ui-tool-link' )\n\t\t.append( this.$icon, this.$title, this.$accel )\n\t\t.attr( 'role', 'button' );\n\tthis.$element\n\t\t.data( 'oo-ui-tool', this )\n\t\t.addClass( 'oo-ui-tool' )\n\t\t.addClass( 'oo-ui-tool-name-' + this.constructor.static.name.replace( /^([^/]+)\\/([^/]+).*$/, '$1-$2' ) )\n\t\t.toggleClass( 'oo-ui-tool-with-label', this.constructor.static.displayBothIconAndLabel )\n\t\t.append( this.$link );\n\tthis.setTitle( config.title || this.constructor.static.title );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.Tool, OO.ui.Widget );\nOO.mixinClass( OO.ui.Tool, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.Tool, OO.ui.mixin.FlaggedElement );\nOO.mixinClass( OO.ui.Tool, OO.ui.mixin.TabIndexedElement );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.Tool.static.tagName = 'span';\n\n/**\n * Symbolic name of tool.\n *\n * The symbolic name is used internally to register the tool with a {@link OO.ui.ToolFactory ToolFactory}. It can\n * also be used when adding tools to toolgroups.\n *\n * @abstract\n * @static\n * @inheritable\n * @property {string}\n */\nOO.ui.Tool.static.name = '';\n\n/**\n * Symbolic name of the group.\n *\n * The group name is used to associate tools with each other so that they can be selected later by\n * a {@link OO.ui.ToolGroup toolgroup}.\n *\n * @abstract\n * @static\n * @inheritable\n * @property {string}\n */\nOO.ui.Tool.static.group = '';\n\n/**\n * Tool title text or a function that returns title text. The value of the static property is overridden if the #title config option is used.\n *\n * @abstract\n * @static\n * @inheritable\n * @property {string|Function}\n */\nOO.ui.Tool.static.title = '';\n\n/**\n * Display both icon and label when the tool is used in a {@link OO.ui.BarToolGroup bar} toolgroup.\n * Normally only the icon is displayed, or only the label if no icon is given.\n *\n * @static\n * @inheritable\n * @property {boolean}\n */\nOO.ui.Tool.static.displayBothIconAndLabel = false;\n\n/**\n * Add tool to catch-all groups automatically.\n *\n * A catch-all group, which contains all tools that do not currently belong to a toolgroup,\n * can be included in a toolgroup using the wildcard selector, an asterisk (*).\n *\n * @static\n * @inheritable\n * @property {boolean}\n */\nOO.ui.Tool.static.autoAddToCatchall = true;\n\n/**\n * Add tool to named groups automatically.\n *\n * By default, tools that are configured with a static ‘group’ property are added\n * to that group and will be selected when the symbolic name of the group is specified (e.g., when\n * toolgroups include tools by group name).\n *\n * @static\n * @property {boolean}\n * @inheritable\n */\nOO.ui.Tool.static.autoAddToGroup = true;\n\n/**\n * Check if this tool is compatible with given data.\n *\n * This is a stub that can be overridden to provide support for filtering tools based on an\n * arbitrary piece of information (e.g., where the cursor is in a document). The implementation\n * must also call this method so that the compatibility check can be performed.\n *\n * @static\n * @inheritable\n * @param {Mixed} data Data to check\n * @return {boolean} Tool can be used with data\n */\nOO.ui.Tool.static.isCompatibleWith = function () {\n\treturn false;\n};\n\n/* Methods */\n\n/**\n * Handle the toolbar state being updated. This method is called when the\n * {@link OO.ui.Toolbar#event-updateState 'updateState' event} is emitted on the\n * {@link OO.ui.Toolbar Toolbar} that uses this tool, and should set the state of this tool\n * depending on application state (usually by calling #setDisabled to enable or disable the tool,\n * or #setActive to mark is as currently in-use or not).\n *\n * This is an abstract method that must be overridden in a concrete subclass.\n *\n * @method\n * @protected\n * @abstract\n */\nOO.ui.Tool.prototype.onUpdateState = null;\n\n/**\n * Handle the tool being selected. This method is called when the user triggers this tool,\n * usually by clicking on its label/icon.\n *\n * This is an abstract method that must be overridden in a concrete subclass.\n *\n * @method\n * @protected\n * @abstract\n */\nOO.ui.Tool.prototype.onSelect = null;\n\n/**\n * Check if the tool is active.\n *\n * Tools become active when their #onSelect or #onUpdateState handlers change them to appear pressed\n * with the #setActive method. Additional CSS is applied to the tool to reflect the active state.\n *\n * @return {boolean} Tool is active\n */\nOO.ui.Tool.prototype.isActive = function () {\n\treturn this.active;\n};\n\n/**\n * Make the tool appear active or inactive.\n *\n * This method should be called within #onSelect or #onUpdateState event handlers to make the tool\n * appear pressed or not.\n *\n * @param {boolean} state Make tool appear active\n */\nOO.ui.Tool.prototype.setActive = function ( state ) {\n\tthis.active = !!state;\n\tif ( this.active ) {\n\t\tthis.$element.addClass( 'oo-ui-tool-active' );\n\t\tthis.setFlags( { progressive: true } );\n\t} else {\n\t\tthis.$element.removeClass( 'oo-ui-tool-active' );\n\t\tthis.setFlags( { progressive: false } );\n\t}\n};\n\n/**\n * Set the tool #title.\n *\n * @param {string|Function} title Title text or a function that returns text\n * @chainable\n */\nOO.ui.Tool.prototype.setTitle = function ( title ) {\n\tthis.title = OO.ui.resolveMsg( title );\n\tthis.updateTitle();\n\treturn this;\n};\n\n/**\n * Get the tool #title.\n *\n * @return {string} Title text\n */\nOO.ui.Tool.prototype.getTitle = function () {\n\treturn this.title;\n};\n\n/**\n * Get the tool's symbolic name.\n *\n * @return {string} Symbolic name of tool\n */\nOO.ui.Tool.prototype.getName = function () {\n\treturn this.constructor.static.name;\n};\n\n/**\n * Update the title.\n */\nOO.ui.Tool.prototype.updateTitle = function () {\n\tvar titleTooltips = this.toolGroup.constructor.static.titleTooltips,\n\t\taccelTooltips = this.toolGroup.constructor.static.accelTooltips,\n\t\taccel = this.toolbar.getToolAccelerator( this.constructor.static.name ),\n\t\ttooltipParts = [];\n\n\tthis.$title.text( this.title );\n\tthis.$accel.text( accel );\n\n\tif ( titleTooltips && typeof this.title === 'string' && this.title.length ) {\n\t\ttooltipParts.push( this.title );\n\t}\n\tif ( accelTooltips && typeof accel === 'string' && accel.length ) {\n\t\ttooltipParts.push( accel );\n\t}\n\tif ( tooltipParts.length ) {\n\t\tthis.$link.attr( 'title', tooltipParts.join( ' ' ) );\n\t} else {\n\t\tthis.$link.removeAttr( 'title' );\n\t}\n};\n\n/**\n * Destroy tool.\n *\n * Destroying the tool removes all event handlers and the tool’s DOM elements.\n * Call this method whenever you are done using a tool.\n */\nOO.ui.Tool.prototype.destroy = function () {\n\tthis.toolbar.disconnect( this );\n\tthis.$element.remove();\n};\n","/**\n * ToolGroups are collections of {@link OO.ui.Tool tools} that are used in a {@link OO.ui.Toolbar toolbar}.\n * The type of toolgroup ({@link OO.ui.ListToolGroup list}, {@link OO.ui.BarToolGroup bar}, or {@link OO.ui.MenuToolGroup menu})\n * to which a tool belongs determines how the tool is arranged and displayed in the toolbar. Toolgroups\n * themselves are created on demand with a {@link OO.ui.ToolGroupFactory toolgroup factory}.\n *\n * Toolgroups can contain individual tools, groups of tools, or all available tools, as specified\n * using the `include` config option. See OO.ui.ToolFactory#extract on documentation of the format.\n * The options `exclude`, `promote`, and `demote` support the same formats.\n *\n * See {@link OO.ui.Toolbar toolbars} for a full example. For more information about toolbars in general,\n * please see the [OOjs UI documentation on MediaWiki][1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars\n *\n * @abstract\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.GroupElement\n *\n * @constructor\n * @param {OO.ui.Toolbar} toolbar\n * @param {Object} [config] Configuration options\n * @cfg {Array|string} [include] List of tools to include in the toolgroup, see above.\n * @cfg {Array|string} [exclude] List of tools to exclude from the toolgroup, see above.\n * @cfg {Array|string} [promote] List of tools to promote to the beginning of the toolgroup, see above.\n * @cfg {Array|string} [demote] List of tools to demote to the end of the toolgroup, see above.\n * This setting is particularly useful when tools have been added to the toolgroup\n * en masse (e.g., via the catch-all selector).\n */\nOO.ui.ToolGroup = function OoUiToolGroup( toolbar, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( toolbar ) && config === undefined ) {\n\t\tconfig = toolbar;\n\t\ttoolbar = config.toolbar;\n\t}\n\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.ToolGroup.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.GroupElement.call( this, config );\n\n\t// Properties\n\tthis.toolbar = toolbar;\n\tthis.tools = {};\n\tthis.pressed = null;\n\tthis.autoDisabled = false;\n\tthis.include = config.include || [];\n\tthis.exclude = config.exclude || [];\n\tthis.promote = config.promote || [];\n\tthis.demote = config.demote || [];\n\tthis.onCapturedMouseKeyUpHandler = this.onCapturedMouseKeyUp.bind( this );\n\n\t// Events\n\tthis.$element.on( {\n\t\tmousedown: this.onMouseKeyDown.bind( this ),\n\t\tmouseup: this.onMouseKeyUp.bind( this ),\n\t\tkeydown: this.onMouseKeyDown.bind( this ),\n\t\tkeyup: this.onMouseKeyUp.bind( this ),\n\t\tfocus: this.onMouseOverFocus.bind( this ),\n\t\tblur: this.onMouseOutBlur.bind( this ),\n\t\tmouseover: this.onMouseOverFocus.bind( this ),\n\t\tmouseout: this.onMouseOutBlur.bind( this )\n\t} );\n\tthis.toolbar.getToolFactory().connect( this, { register: 'onToolFactoryRegister' } );\n\tthis.aggregate( { disable: 'itemDisable' } );\n\tthis.connect( this, { itemDisable: 'updateDisabled' } );\n\n\t// Initialization\n\tthis.$group.addClass( 'oo-ui-toolGroup-tools' );\n\tthis.$element\n\t\t.addClass( 'oo-ui-toolGroup' )\n\t\t.append( this.$group );\n\tthis.populate();\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ToolGroup, OO.ui.Widget );\nOO.mixinClass( OO.ui.ToolGroup, OO.ui.mixin.GroupElement );\n\n/* Events */\n\n/**\n * @event update\n */\n\n/* Static Properties */\n\n/**\n * Show labels in tooltips.\n *\n * @static\n * @inheritable\n * @property {boolean}\n */\nOO.ui.ToolGroup.static.titleTooltips = false;\n\n/**\n * Show acceleration labels in tooltips.\n *\n * Note: The OOjs UI library does not include an accelerator system, but does contain\n * a hook for one. To use an accelerator system, subclass the {@link OO.ui.Toolbar toolbar} and\n * override the {@link OO.ui.Toolbar#getToolAccelerator getToolAccelerator} method, which is\n * meant to return a label that describes the accelerator keys for a given tool (e.g., 'Ctrl + M').\n *\n * @static\n * @inheritable\n * @property {boolean}\n */\nOO.ui.ToolGroup.static.accelTooltips = false;\n\n/**\n * Automatically disable the toolgroup when all tools are disabled\n *\n * @static\n * @inheritable\n * @property {boolean}\n */\nOO.ui.ToolGroup.static.autoDisable = true;\n\n/**\n * @abstract\n * @static\n * @inheritable\n * @property {string}\n */\nOO.ui.ToolGroup.static.name = null;\n\n/* Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.ToolGroup.prototype.isDisabled = function () {\n\treturn this.autoDisabled || OO.ui.ToolGroup.parent.prototype.isDisabled.apply( this, arguments );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ToolGroup.prototype.updateDisabled = function () {\n\tvar i, item, allDisabled = true;\n\n\tif ( this.constructor.static.autoDisable ) {\n\t\tfor ( i = this.items.length - 1; i >= 0; i-- ) {\n\t\t\titem = this.items[ i ];\n\t\t\tif ( !item.isDisabled() ) {\n\t\t\t\tallDisabled = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tthis.autoDisabled = allDisabled;\n\t}\n\tOO.ui.ToolGroup.parent.prototype.updateDisabled.apply( this, arguments );\n};\n\n/**\n * Handle mouse down and key down events.\n *\n * @protected\n * @param {jQuery.Event} e Mouse down or key down event\n */\nOO.ui.ToolGroup.prototype.onMouseKeyDown = function ( e ) {\n\tif (\n\t\t!this.isDisabled() &&\n\t\t( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )\n\t) {\n\t\tthis.pressed = this.findTargetTool( e );\n\t\tif ( this.pressed ) {\n\t\t\tthis.pressed.setActive( true );\n\t\t\tthis.getElementDocument().addEventListener( 'mouseup', this.onCapturedMouseKeyUpHandler, true );\n\t\t\tthis.getElementDocument().addEventListener( 'keyup', this.onCapturedMouseKeyUpHandler, true );\n\t\t\treturn false;\n\t\t}\n\t}\n};\n\n/**\n * Handle captured mouse up and key up events.\n *\n * @protected\n * @param {MouseEvent|KeyboardEvent} e Mouse up or key up event\n */\nOO.ui.ToolGroup.prototype.onCapturedMouseKeyUp = function ( e ) {\n\tthis.getElementDocument().removeEventListener( 'mouseup', this.onCapturedMouseKeyUpHandler, true );\n\tthis.getElementDocument().removeEventListener( 'keyup', this.onCapturedMouseKeyUpHandler, true );\n\t// onMouseKeyUp may be called a second time, depending on where the mouse is when the button is\n\t// released, but since `this.pressed` will no longer be true, the second call will be ignored.\n\tthis.onMouseKeyUp( e );\n};\n\n/**\n * Handle mouse up and key up events.\n *\n * @protected\n * @param {MouseEvent|KeyboardEvent} e Mouse up or key up event\n */\nOO.ui.ToolGroup.prototype.onMouseKeyUp = function ( e ) {\n\tvar tool = this.findTargetTool( e );\n\n\tif (\n\t\t!this.isDisabled() && this.pressed && this.pressed === tool &&\n\t\t( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )\n\t) {\n\t\tthis.pressed.onSelect();\n\t\tthis.pressed = null;\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t}\n\n\tthis.pressed = null;\n};\n\n/**\n * Handle mouse over and focus events.\n *\n * @protected\n * @param {jQuery.Event} e Mouse over or focus event\n */\nOO.ui.ToolGroup.prototype.onMouseOverFocus = function ( e ) {\n\tvar tool = this.findTargetTool( e );\n\n\tif ( this.pressed && this.pressed === tool ) {\n\t\tthis.pressed.setActive( true );\n\t}\n};\n\n/**\n * Handle mouse out and blur events.\n *\n * @protected\n * @param {jQuery.Event} e Mouse out or blur event\n */\nOO.ui.ToolGroup.prototype.onMouseOutBlur = function ( e ) {\n\tvar tool = this.findTargetTool( e );\n\n\tif ( this.pressed && this.pressed === tool ) {\n\t\tthis.pressed.setActive( false );\n\t}\n};\n\n/**\n * Get the closest tool to a jQuery.Event.\n *\n * Only tool links are considered, which prevents other elements in the tool such as popups from\n * triggering tool group interactions.\n *\n * @private\n * @param {jQuery.Event} e\n * @return {OO.ui.Tool|null} Tool, `null` if none was found\n */\nOO.ui.ToolGroup.prototype.findTargetTool = function ( e ) {\n\tvar tool,\n\t\t$item = $( e.target ).closest( '.oo-ui-tool-link' );\n\n\tif ( $item.length ) {\n\t\ttool = $item.parent().data( 'oo-ui-tool' );\n\t}\n\n\treturn tool && !tool.isDisabled() ? tool : null;\n};\n\n/**\n * Handle tool registry register events.\n *\n * If a tool is registered after the group is created, we must repopulate the list to account for:\n *\n * - a tool being added that may be included\n * - a tool already included being overridden\n *\n * @protected\n * @param {string} name Symbolic name of tool\n */\nOO.ui.ToolGroup.prototype.onToolFactoryRegister = function () {\n\tthis.populate();\n};\n\n/**\n * Get the toolbar that contains the toolgroup.\n *\n * @return {OO.ui.Toolbar} Toolbar that contains the toolgroup\n */\nOO.ui.ToolGroup.prototype.getToolbar = function () {\n\treturn this.toolbar;\n};\n\n/**\n * Add and remove tools based on configuration.\n */\nOO.ui.ToolGroup.prototype.populate = function () {\n\tvar i, len, name, tool,\n\t\ttoolFactory = this.toolbar.getToolFactory(),\n\t\tnames = {},\n\t\tadd = [],\n\t\tremove = [],\n\t\tlist = this.toolbar.getToolFactory().getTools(\n\t\t\tthis.include, this.exclude, this.promote, this.demote\n\t\t);\n\n\t// Build a list of needed tools\n\tfor ( i = 0, len = list.length; i < len; i++ ) {\n\t\tname = list[ i ];\n\t\tif (\n\t\t\t// Tool exists\n\t\t\ttoolFactory.lookup( name ) &&\n\t\t\t// Tool is available or is already in this group\n\t\t\t( this.toolbar.isToolAvailable( name ) || this.tools[ name ] )\n\t\t) {\n\t\t\t// Hack to prevent infinite recursion via ToolGroupTool. We need to reserve the tool before\n\t\t\t// creating it, but we can't call reserveTool() yet because we haven't created the tool.\n\t\t\tthis.toolbar.tools[ name ] = true;\n\t\t\ttool = this.tools[ name ];\n\t\t\tif ( !tool ) {\n\t\t\t\t// Auto-initialize tools on first use\n\t\t\t\tthis.tools[ name ] = tool = toolFactory.create( name, this );\n\t\t\t\ttool.updateTitle();\n\t\t\t}\n\t\t\tthis.toolbar.reserveTool( tool );\n\t\t\tadd.push( tool );\n\t\t\tnames[ name ] = true;\n\t\t}\n\t}\n\t// Remove tools that are no longer needed\n\tfor ( name in this.tools ) {\n\t\tif ( !names[ name ] ) {\n\t\t\tthis.tools[ name ].destroy();\n\t\t\tthis.toolbar.releaseTool( this.tools[ name ] );\n\t\t\tremove.push( this.tools[ name ] );\n\t\t\tdelete this.tools[ name ];\n\t\t}\n\t}\n\tif ( remove.length ) {\n\t\tthis.removeItems( remove );\n\t}\n\t// Update emptiness state\n\tif ( add.length ) {\n\t\tthis.$element.removeClass( 'oo-ui-toolGroup-empty' );\n\t} else {\n\t\tthis.$element.addClass( 'oo-ui-toolGroup-empty' );\n\t}\n\t// Re-add tools (moving existing ones to new locations)\n\tthis.addItems( add );\n\t// Disabled state may depend on items\n\tthis.updateDisabled();\n};\n\n/**\n * Destroy toolgroup.\n */\nOO.ui.ToolGroup.prototype.destroy = function () {\n\tvar name;\n\n\tthis.clearItems();\n\tthis.toolbar.getToolFactory().disconnect( this );\n\tfor ( name in this.tools ) {\n\t\tthis.toolbar.releaseTool( this.tools[ name ] );\n\t\tthis.tools[ name ].disconnect( this ).destroy();\n\t\tdelete this.tools[ name ];\n\t}\n\tthis.$element.remove();\n};\n","/**\n * A ToolFactory creates tools on demand. All tools ({@link OO.ui.Tool Tools}, {@link OO.ui.PopupTool PopupTools},\n * and {@link OO.ui.ToolGroupTool ToolGroupTools}) must be registered with a tool factory. Tools are\n * registered by their symbolic name. See {@link OO.ui.Toolbar toolbars} for an example.\n *\n * For more information about toolbars in general, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars\n *\n * @class\n * @extends OO.Factory\n * @constructor\n */\nOO.ui.ToolFactory = function OoUiToolFactory() {\n\t// Parent constructor\n\tOO.ui.ToolFactory.parent.call( this );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ToolFactory, OO.Factory );\n\n/* Methods */\n\n/**\n * Get tools from the factory\n *\n * @param {Array|string} [include] Included tools, see #extract for format\n * @param {Array|string} [exclude] Excluded tools, see #extract for format\n * @param {Array|string} [promote] Promoted tools, see #extract for format\n * @param {Array|string} [demote] Demoted tools, see #extract for format\n * @return {string[]} List of tools\n */\nOO.ui.ToolFactory.prototype.getTools = function ( include, exclude, promote, demote ) {\n\tvar i, len, included, promoted, demoted,\n\t\tauto = [],\n\t\tused = {};\n\n\t// Collect included and not excluded tools\n\tincluded = OO.simpleArrayDifference( this.extract( include ), this.extract( exclude ) );\n\n\t// Promotion\n\tpromoted = this.extract( promote, used );\n\tdemoted = this.extract( demote, used );\n\n\t// Auto\n\tfor ( i = 0, len = included.length; i < len; i++ ) {\n\t\tif ( !used[ included[ i ] ] ) {\n\t\t\tauto.push( included[ i ] );\n\t\t}\n\t}\n\n\treturn promoted.concat( auto ).concat( demoted );\n};\n\n/**\n * Get a flat list of names from a list of names or groups.\n *\n * Normally, `collection` is an array of tool specifications. Tools can be specified in the\n * following ways:\n *\n * - To include an individual tool, use the symbolic name: `{ name: 'tool-name' }` or `'tool-name'`.\n * - To include all tools in a group, use the group name: `{ group: 'group-name' }`. (To assign the\n * tool to a group, use OO.ui.Tool.static.group.)\n *\n * Alternatively, to include all tools that are not yet assigned to any other toolgroup, use the\n * catch-all selector `'*'`.\n *\n * If `used` is passed, tool names that appear as properties in this object will be considered\n * already assigned, and will not be returned even if specified otherwise. The tool names extracted\n * by this function call will be added as new properties in the object.\n *\n * @private\n * @param {Array|string} collection List of tools, see above\n * @param {Object} [used] Object containing information about used tools, see above\n * @return {string[]} List of extracted tool names\n */\nOO.ui.ToolFactory.prototype.extract = function ( collection, used ) {\n\tvar i, len, item, name, tool,\n\t\tnames = [];\n\n\tcollection = !Array.isArray( collection ) ? [ collection ] : collection;\n\n\tfor ( i = 0, len = collection.length; i < len; i++ ) {\n\t\titem = collection[ i ];\n\t\tif ( item === '*' ) {\n\t\t\tfor ( name in this.registry ) {\n\t\t\t\ttool = this.registry[ name ];\n\t\t\t\tif (\n\t\t\t\t\t// Only add tools by group name when auto-add is enabled\n\t\t\t\t\ttool.static.autoAddToCatchall &&\n\t\t\t\t\t// Exclude already used tools\n\t\t\t\t\t( !used || !used[ name ] )\n\t\t\t\t) {\n\t\t\t\t\tnames.push( name );\n\t\t\t\t\tif ( used ) {\n\t\t\t\t\t\tused[ name ] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t// Allow plain strings as shorthand for named tools\n\t\t\tif ( typeof item === 'string' ) {\n\t\t\t\titem = { name: item };\n\t\t\t}\n\t\t\tif ( OO.isPlainObject( item ) ) {\n\t\t\t\tif ( item.group ) {\n\t\t\t\t\tfor ( name in this.registry ) {\n\t\t\t\t\t\ttool = this.registry[ name ];\n\t\t\t\t\t\tif (\n\t\t\t\t\t\t\t// Include tools with matching group\n\t\t\t\t\t\t\ttool.static.group === item.group &&\n\t\t\t\t\t\t\t// Only add tools by group name when auto-add is enabled\n\t\t\t\t\t\t\ttool.static.autoAddToGroup &&\n\t\t\t\t\t\t\t// Exclude already used tools\n\t\t\t\t\t\t\t( !used || !used[ name ] )\n\t\t\t\t\t\t) {\n\t\t\t\t\t\t\tnames.push( name );\n\t\t\t\t\t\t\tif ( used ) {\n\t\t\t\t\t\t\t\tused[ name ] = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t// Include tools with matching name and exclude already used tools\n\t\t\t\t} else if ( item.name && ( !used || !used[ item.name ] ) ) {\n\t\t\t\t\tnames.push( item.name );\n\t\t\t\t\tif ( used ) {\n\t\t\t\t\t\tused[ item.name ] = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\treturn names;\n};\n","/**\n * ToolGroupFactories create {@link OO.ui.ToolGroup toolgroups} on demand. The toolgroup classes must\n * specify a symbolic name and be registered with the factory. The following classes are registered by\n * default:\n *\n * - {@link OO.ui.BarToolGroup BarToolGroups} (‘bar’)\n * - {@link OO.ui.MenuToolGroup MenuToolGroups} (‘menu’)\n * - {@link OO.ui.ListToolGroup ListToolGroups} (‘list’)\n *\n * See {@link OO.ui.Toolbar toolbars} for an example.\n *\n * For more information about toolbars in general, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars\n *\n * @class\n * @extends OO.Factory\n * @constructor\n */\nOO.ui.ToolGroupFactory = function OoUiToolGroupFactory() {\n\tvar i, l, defaultClasses;\n\t// Parent constructor\n\tOO.Factory.call( this );\n\n\tdefaultClasses = this.constructor.static.getDefaultClasses();\n\n\t// Register default toolgroups\n\tfor ( i = 0, l = defaultClasses.length; i < l; i++ ) {\n\t\tthis.register( defaultClasses[ i ] );\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ToolGroupFactory, OO.Factory );\n\n/* Static Methods */\n\n/**\n * Get a default set of classes to be registered on construction.\n *\n * @return {Function[]} Default classes\n */\nOO.ui.ToolGroupFactory.static.getDefaultClasses = function () {\n\treturn [\n\t\tOO.ui.BarToolGroup,\n\t\tOO.ui.ListToolGroup,\n\t\tOO.ui.MenuToolGroup\n\t];\n};\n","/**\n * Popup tools open a popup window when they are selected from the {@link OO.ui.Toolbar toolbar}. Each popup tool is configured\n * with a static name, title, and icon, as well with as any popup configurations. Unlike other tools, popup tools do not require that developers specify\n * an #onSelect or #onUpdateState method, as these methods have been implemented already.\n *\n * // Example of a popup tool. When selected, a popup tool displays\n * // a popup window.\n * function HelpTool( toolGroup, config ) {\n * OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {\n * padded: true,\n * label: 'Help',\n * head: true\n * } }, config ) );\n * this.popup.$body.append( '<p>I am helpful!</p>' );\n * };\n * OO.inheritClass( HelpTool, OO.ui.PopupTool );\n * HelpTool.static.name = 'help';\n * HelpTool.static.icon = 'help';\n * HelpTool.static.title = 'Help';\n * toolFactory.register( HelpTool );\n *\n * For an example of a toolbar that contains a popup tool, see {@link OO.ui.Toolbar toolbars}. For more information about\n * toolbars in genreral, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars\n *\n * @abstract\n * @class\n * @extends OO.ui.Tool\n * @mixins OO.ui.mixin.PopupElement\n *\n * @constructor\n * @param {OO.ui.ToolGroup} toolGroup\n * @param {Object} [config] Configuration options\n */\nOO.ui.PopupTool = function OoUiPopupTool( toolGroup, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( toolGroup ) && config === undefined ) {\n\t\tconfig = toolGroup;\n\t\ttoolGroup = config.toolGroup;\n\t}\n\n\t// Parent constructor\n\tOO.ui.PopupTool.parent.call( this, toolGroup, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.PopupElement.call( this, config );\n\n\t// Initialization\n\tthis.popup.setPosition( toolGroup.getToolbar().position === 'bottom' ? 'above' : 'below' );\n\tthis.$element\n\t\t.addClass( 'oo-ui-popupTool' )\n\t\t.append( this.popup.$element );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.PopupTool, OO.ui.Tool );\nOO.mixinClass( OO.ui.PopupTool, OO.ui.mixin.PopupElement );\n\n/* Methods */\n\n/**\n * Handle the tool being selected.\n *\n * @inheritdoc\n */\nOO.ui.PopupTool.prototype.onSelect = function () {\n\tif ( !this.isDisabled() ) {\n\t\tthis.popup.toggle();\n\t}\n\tthis.setActive( false );\n\treturn false;\n};\n\n/**\n * Handle the toolbar state being updated.\n *\n * @inheritdoc\n */\nOO.ui.PopupTool.prototype.onUpdateState = function () {\n\tthis.setActive( false );\n};\n","/**\n * A ToolGroupTool is a special sort of tool that can contain other {@link OO.ui.Tool tools}\n * and {@link OO.ui.ToolGroup toolgroups}. The ToolGroupTool was specifically designed to be used\n * inside a {@link OO.ui.BarToolGroup bar} toolgroup to provide access to additional tools from\n * the bar item. Included tools will be displayed in a dropdown {@link OO.ui.ListToolGroup list}\n * when the ToolGroupTool is selected.\n *\n * // Example: ToolGroupTool with two nested tools, 'setting1' and 'setting2', defined elsewhere.\n *\n * function SettingsTool() {\n * SettingsTool.parent.apply( this, arguments );\n * };\n * OO.inheritClass( SettingsTool, OO.ui.ToolGroupTool );\n * SettingsTool.static.name = 'settings';\n * SettingsTool.static.title = 'Change settings';\n * SettingsTool.static.groupConfig = {\n * icon: 'settings',\n * label: 'ToolGroupTool',\n * include: [ 'setting1', 'setting2' ]\n * };\n * toolFactory.register( SettingsTool );\n *\n * For more information, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * Please note that this implementation is subject to change per [T74159] [2].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars#ToolGroupTool\n * [2]: https://phabricator.wikimedia.org/T74159\n *\n * @abstract\n * @class\n * @extends OO.ui.Tool\n *\n * @constructor\n * @param {OO.ui.ToolGroup} toolGroup\n * @param {Object} [config] Configuration options\n */\nOO.ui.ToolGroupTool = function OoUiToolGroupTool( toolGroup, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( toolGroup ) && config === undefined ) {\n\t\tconfig = toolGroup;\n\t\ttoolGroup = config.toolGroup;\n\t}\n\n\t// Parent constructor\n\tOO.ui.ToolGroupTool.parent.call( this, toolGroup, config );\n\n\t// Properties\n\tthis.innerToolGroup = this.createGroup( this.constructor.static.groupConfig );\n\n\t// Events\n\tthis.innerToolGroup.connect( this, { disable: 'onToolGroupDisable' } );\n\n\t// Initialization\n\tthis.$link.remove();\n\tthis.$element\n\t\t.addClass( 'oo-ui-toolGroupTool' )\n\t\t.append( this.innerToolGroup.$element );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ToolGroupTool, OO.ui.Tool );\n\n/* Static Properties */\n\n/**\n * Toolgroup configuration.\n *\n * The toolgroup configuration consists of the tools to include, as well as an icon and label\n * to use for the bar item. Tools can be included by symbolic name, group, or with the\n * wildcard selector. Please see {@link OO.ui.ToolGroup toolgroup} for more information.\n *\n * @property {Object.<string,Array>}\n */\nOO.ui.ToolGroupTool.static.groupConfig = {};\n\n/* Methods */\n\n/**\n * Handle the tool being selected.\n *\n * @inheritdoc\n */\nOO.ui.ToolGroupTool.prototype.onSelect = function () {\n\tthis.innerToolGroup.setActive( !this.innerToolGroup.active );\n\treturn false;\n};\n\n/**\n * Synchronize disabledness state of the tool with the inner toolgroup.\n *\n * @private\n * @param {boolean} disabled Element is disabled\n */\nOO.ui.ToolGroupTool.prototype.onToolGroupDisable = function ( disabled ) {\n\tthis.setDisabled( disabled );\n};\n\n/**\n * Handle the toolbar state being updated.\n *\n * @inheritdoc\n */\nOO.ui.ToolGroupTool.prototype.onUpdateState = function () {\n\tthis.setActive( false );\n};\n\n/**\n * Build a {@link OO.ui.ToolGroup toolgroup} from the specified configuration.\n *\n * @param {Object.<string,Array>} group Toolgroup configuration. Please see {@link OO.ui.ToolGroup toolgroup} for\n * more information.\n * @return {OO.ui.ListToolGroup}\n */\nOO.ui.ToolGroupTool.prototype.createGroup = function ( group ) {\n\tif ( group.include === '*' ) {\n\t\t// Apply defaults to catch-all groups\n\t\tif ( group.label === undefined ) {\n\t\t\tgroup.label = OO.ui.msg( 'ooui-toolbar-more' );\n\t\t}\n\t}\n\n\treturn this.toolbar.getToolGroupFactory().create( 'list', this.toolbar, group );\n};\n","/**\n * BarToolGroups are one of three types of {@link OO.ui.ToolGroup toolgroups} that are used to\n * create {@link OO.ui.Toolbar toolbars} (the other types of groups are {@link OO.ui.MenuToolGroup MenuToolGroup}\n * and {@link OO.ui.ListToolGroup ListToolGroup}). The {@link OO.ui.Tool tools} in a BarToolGroup are\n * displayed by icon in a single row. The title of the tool is displayed when users move the mouse over\n * the tool.\n *\n * BarToolGroups are created by a {@link OO.ui.ToolGroupFactory tool group factory} when the toolbar is\n * set up.\n *\n * @example\n * // Example of a BarToolGroup with two tools\n * var toolFactory = new OO.ui.ToolFactory();\n * var toolGroupFactory = new OO.ui.ToolGroupFactory();\n * var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory );\n *\n * // We will be placing status text in this element when tools are used\n * var $area = $( '<p>' ).text( 'Example of a BarToolGroup with two tools.' );\n *\n * // Define the tools that we're going to place in our toolbar\n *\n * // Create a class inheriting from OO.ui.Tool\n * function SearchTool() {\n * SearchTool.parent.apply( this, arguments );\n * }\n * OO.inheritClass( SearchTool, OO.ui.Tool );\n * // Each tool must have a 'name' (used as an internal identifier, see later) and at least one\n * // of 'icon' and 'title' (displayed icon and text).\n * SearchTool.static.name = 'search';\n * SearchTool.static.icon = 'search';\n * SearchTool.static.title = 'Search...';\n * // Defines the action that will happen when this tool is selected (clicked).\n * SearchTool.prototype.onSelect = function () {\n * $area.text( 'Search tool clicked!' );\n * // Never display this tool as \"active\" (selected).\n * this.setActive( false );\n * };\n * SearchTool.prototype.onUpdateState = function () {};\n * // Make this tool available in our toolFactory and thus our toolbar\n * toolFactory.register( SearchTool );\n *\n * // This is a PopupTool. Rather than having a custom 'onSelect' action, it will display a\n * // little popup window (a PopupWidget).\n * function HelpTool( toolGroup, config ) {\n * OO.ui.PopupTool.call( this, toolGroup, $.extend( { popup: {\n * padded: true,\n * label: 'Help',\n * head: true\n * } }, config ) );\n * this.popup.$body.append( '<p>I am helpful!</p>' );\n * }\n * OO.inheritClass( HelpTool, OO.ui.PopupTool );\n * HelpTool.static.name = 'help';\n * HelpTool.static.icon = 'help';\n * HelpTool.static.title = 'Help';\n * toolFactory.register( HelpTool );\n *\n * // Finally define which tools and in what order appear in the toolbar. Each tool may only be\n * // used once (but not all defined tools must be used).\n * toolbar.setup( [\n * {\n * // 'bar' tool groups display tools by icon only\n * type: 'bar',\n * include: [ 'search', 'help' ]\n * }\n * ] );\n *\n * // Create some UI around the toolbar and place it in the document\n * var frame = new OO.ui.PanelLayout( {\n * expanded: false,\n * framed: true\n * } );\n * var contentFrame = new OO.ui.PanelLayout( {\n * expanded: false,\n * padded: true\n * } );\n * frame.$element.append(\n * toolbar.$element,\n * contentFrame.$element.append( $area )\n * );\n * $( 'body' ).append( frame.$element );\n *\n * // Here is where the toolbar is actually built. This must be done after inserting it into the\n * // document.\n * toolbar.initialize();\n *\n * For more information about how to add tools to a bar tool group, please see {@link OO.ui.ToolGroup toolgroup}.\n * For more information about toolbars in general, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars\n *\n * @class\n * @extends OO.ui.ToolGroup\n *\n * @constructor\n * @param {OO.ui.Toolbar} toolbar\n * @param {Object} [config] Configuration options\n */\nOO.ui.BarToolGroup = function OoUiBarToolGroup( toolbar, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( toolbar ) && config === undefined ) {\n\t\tconfig = toolbar;\n\t\ttoolbar = config.toolbar;\n\t}\n\n\t// Parent constructor\n\tOO.ui.BarToolGroup.parent.call( this, toolbar, config );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-barToolGroup' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.BarToolGroup, OO.ui.ToolGroup );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.BarToolGroup.static.titleTooltips = true;\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.BarToolGroup.static.accelTooltips = true;\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.BarToolGroup.static.name = 'bar';\n","/**\n * PopupToolGroup is an abstract base class used by both {@link OO.ui.MenuToolGroup MenuToolGroup}\n * and {@link OO.ui.ListToolGroup ListToolGroup} to provide a popup--an overlaid menu or list of tools with an\n * optional icon and label. This class can be used for other base classes that also use this functionality.\n *\n * @abstract\n * @class\n * @extends OO.ui.ToolGroup\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.IndicatorElement\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.TitledElement\n * @mixins OO.ui.mixin.FlaggedElement\n * @mixins OO.ui.mixin.ClippableElement\n * @mixins OO.ui.mixin.TabIndexedElement\n *\n * @constructor\n * @param {OO.ui.Toolbar} toolbar\n * @param {Object} [config] Configuration options\n * @cfg {string} [header] Text to display at the top of the popup\n */\nOO.ui.PopupToolGroup = function OoUiPopupToolGroup( toolbar, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( toolbar ) && config === undefined ) {\n\t\tconfig = toolbar;\n\t\ttoolbar = config.toolbar;\n\t}\n\n\t// Configuration initialization\n\tconfig = $.extend( {\n\t\tindicator: config.indicator === undefined ? ( toolbar.position === 'bottom' ? 'up' : 'down' ) : config.indicator\n\t}, config );\n\n\t// Parent constructor\n\tOO.ui.PopupToolGroup.parent.call( this, toolbar, config );\n\n\t// Properties\n\tthis.active = false;\n\tthis.dragging = false;\n\tthis.onBlurHandler = this.onBlur.bind( this );\n\tthis.$handle = $( '<span>' );\n\n\t// Mixin constructors\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.IndicatorElement.call( this, config );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\tOO.ui.mixin.TitledElement.call( this, config );\n\tOO.ui.mixin.FlaggedElement.call( this, config );\n\tOO.ui.mixin.ClippableElement.call( this, $.extend( {}, config, { $clippable: this.$group } ) );\n\tOO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$handle } ) );\n\n\t// Events\n\tthis.$handle.on( {\n\t\tkeydown: this.onHandleMouseKeyDown.bind( this ),\n\t\tkeyup: this.onHandleMouseKeyUp.bind( this ),\n\t\tmousedown: this.onHandleMouseKeyDown.bind( this ),\n\t\tmouseup: this.onHandleMouseKeyUp.bind( this )\n\t} );\n\n\t// Initialization\n\tthis.$handle\n\t\t.addClass( 'oo-ui-popupToolGroup-handle' )\n\t\t.attr( 'role', 'button' )\n\t\t.append( this.$icon, this.$label, this.$indicator );\n\t// If the pop-up should have a header, add it to the top of the toolGroup.\n\t// Note: If this feature is useful for other widgets, we could abstract it into an\n\t// OO.ui.HeaderedElement mixin constructor.\n\tif ( config.header !== undefined ) {\n\t\tthis.$group\n\t\t\t.prepend( $( '<span>' )\n\t\t\t\t.addClass( 'oo-ui-popupToolGroup-header' )\n\t\t\t\t.text( config.header )\n\t\t\t);\n\t}\n\tthis.$element\n\t\t.addClass( 'oo-ui-popupToolGroup' )\n\t\t.prepend( this.$handle );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.PopupToolGroup, OO.ui.ToolGroup );\nOO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.IndicatorElement );\nOO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.TitledElement );\nOO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.FlaggedElement );\nOO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.ClippableElement );\nOO.mixinClass( OO.ui.PopupToolGroup, OO.ui.mixin.TabIndexedElement );\n\n/* Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.PopupToolGroup.prototype.setDisabled = function () {\n\t// Parent method\n\tOO.ui.PopupToolGroup.parent.prototype.setDisabled.apply( this, arguments );\n\n\tif ( this.isDisabled() && this.isElementAttached() ) {\n\t\tthis.setActive( false );\n\t}\n};\n\n/**\n * Handle focus being lost.\n *\n * The event is actually generated from a mouseup/keyup, so it is not a normal blur event object.\n *\n * @protected\n * @param {MouseEvent|KeyboardEvent} e Mouse up or key up event\n */\nOO.ui.PopupToolGroup.prototype.onBlur = function ( e ) {\n\t// Only deactivate when clicking outside the dropdown element\n\tif ( $( e.target ).closest( '.oo-ui-popupToolGroup' )[ 0 ] !== this.$element[ 0 ] ) {\n\t\tthis.setActive( false );\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.PopupToolGroup.prototype.onMouseKeyUp = function ( e ) {\n\t// Only close toolgroup when a tool was actually selected\n\tif (\n\t\t!this.isDisabled() && this.pressed && this.pressed === this.findTargetTool( e ) &&\n\t\t( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )\n\t) {\n\t\tthis.setActive( false );\n\t}\n\treturn OO.ui.PopupToolGroup.parent.prototype.onMouseKeyUp.call( this, e );\n};\n\n/**\n * Handle mouse up and key up events.\n *\n * @protected\n * @param {jQuery.Event} e Mouse up or key up event\n */\nOO.ui.PopupToolGroup.prototype.onHandleMouseKeyUp = function ( e ) {\n\tif (\n\t\t!this.isDisabled() &&\n\t\t( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )\n\t) {\n\t\treturn false;\n\t}\n};\n\n/**\n * Handle mouse down and key down events.\n *\n * @protected\n * @param {jQuery.Event} e Mouse down or key down event\n */\nOO.ui.PopupToolGroup.prototype.onHandleMouseKeyDown = function ( e ) {\n\tif (\n\t\t!this.isDisabled() &&\n\t\t( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )\n\t) {\n\t\tthis.setActive( !this.active );\n\t\treturn false;\n\t}\n};\n\n/**\n * Switch into 'active' mode.\n *\n * When active, the popup is visible. A mouseup event anywhere in the document will trigger\n * deactivation.\n *\n * @param {boolean} value The active state to set\n */\nOO.ui.PopupToolGroup.prototype.setActive = function ( value ) {\n\tvar containerWidth, containerLeft;\n\tvalue = !!value;\n\tif ( this.active !== value ) {\n\t\tthis.active = value;\n\t\tif ( value ) {\n\t\t\tthis.getElementDocument().addEventListener( 'mouseup', this.onBlurHandler, true );\n\t\t\tthis.getElementDocument().addEventListener( 'keyup', this.onBlurHandler, true );\n\n\t\t\tthis.$clippable.css( 'left', '' );\n\t\t\t// Try anchoring the popup to the left first\n\t\t\tthis.$element.addClass( 'oo-ui-popupToolGroup-active oo-ui-popupToolGroup-left' );\n\t\t\tthis.toggleClipping( true );\n\t\t\tif ( this.isClippedHorizontally() ) {\n\t\t\t\t// Anchoring to the left caused the popup to clip, so anchor it to the right instead\n\t\t\t\tthis.toggleClipping( false );\n\t\t\t\tthis.$element\n\t\t\t\t\t.removeClass( 'oo-ui-popupToolGroup-left' )\n\t\t\t\t\t.addClass( 'oo-ui-popupToolGroup-right' );\n\t\t\t\tthis.toggleClipping( true );\n\t\t\t}\n\t\t\tif ( this.isClippedHorizontally() ) {\n\t\t\t\t// Anchoring to the right also caused the popup to clip, so just make it fill the container\n\t\t\t\tcontainerWidth = this.$clippableScrollableContainer.width();\n\t\t\t\tcontainerLeft = this.$clippableScrollableContainer.offset().left;\n\n\t\t\t\tthis.toggleClipping( false );\n\t\t\t\tthis.$element.removeClass( 'oo-ui-popupToolGroup-right' );\n\n\t\t\t\tthis.$clippable.css( {\n\t\t\t\t\tleft: -( this.$element.offset().left - containerLeft ),\n\t\t\t\t\twidth: containerWidth\n\t\t\t\t} );\n\t\t\t}\n\t\t} else {\n\t\t\tthis.getElementDocument().removeEventListener( 'mouseup', this.onBlurHandler, true );\n\t\t\tthis.getElementDocument().removeEventListener( 'keyup', this.onBlurHandler, true );\n\t\t\tthis.$element.removeClass(\n\t\t\t\t'oo-ui-popupToolGroup-active oo-ui-popupToolGroup-left oo-ui-popupToolGroup-right'\n\t\t\t);\n\t\t\tthis.toggleClipping( false );\n\t\t}\n\t}\n};\n","/**\n * ListToolGroups are one of three types of {@link OO.ui.ToolGroup toolgroups} that are used to\n * create {@link OO.ui.Toolbar toolbars} (the other types of groups are {@link OO.ui.MenuToolGroup MenuToolGroup}\n * and {@link OO.ui.BarToolGroup BarToolGroup}). The {@link OO.ui.Tool tools} in a ListToolGroup are displayed\n * by label in a dropdown menu. The title of the tool is used as the label text. The menu itself can be configured\n * with a label, icon, indicator, header, and title.\n *\n * ListToolGroups can be configured to be expanded and collapsed. Collapsed lists will have a ‘More’ option that\n * users can select to see the full list of tools. If a collapsed toolgroup is expanded, a ‘Fewer’ option permits\n * users to collapse the list again.\n *\n * ListToolGroups are created by a {@link OO.ui.ToolGroupFactory toolgroup factory} when the toolbar is set up. The factory\n * requires the ListToolGroup's symbolic name, 'list', which is specified along with the other configurations. For more\n * information about how to add tools to a ListToolGroup, please see {@link OO.ui.ToolGroup toolgroup}.\n *\n * @example\n * // Example of a ListToolGroup\n * var toolFactory = new OO.ui.ToolFactory();\n * var toolGroupFactory = new OO.ui.ToolGroupFactory();\n * var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory );\n *\n * // Configure and register two tools\n * function SettingsTool() {\n * SettingsTool.parent.apply( this, arguments );\n * }\n * OO.inheritClass( SettingsTool, OO.ui.Tool );\n * SettingsTool.static.name = 'settings';\n * SettingsTool.static.icon = 'settings';\n * SettingsTool.static.title = 'Change settings';\n * SettingsTool.prototype.onSelect = function () {\n * this.setActive( false );\n * };\n * SettingsTool.prototype.onUpdateState = function () {};\n * toolFactory.register( SettingsTool );\n * // Register two more tools, nothing interesting here\n * function StuffTool() {\n * StuffTool.parent.apply( this, arguments );\n * }\n * OO.inheritClass( StuffTool, OO.ui.Tool );\n * StuffTool.static.name = 'stuff';\n * StuffTool.static.icon = 'search';\n * StuffTool.static.title = 'Change the world';\n * StuffTool.prototype.onSelect = function () {\n * this.setActive( false );\n * };\n * StuffTool.prototype.onUpdateState = function () {};\n * toolFactory.register( StuffTool );\n * toolbar.setup( [\n * {\n * // Configurations for list toolgroup.\n * type: 'list',\n * label: 'ListToolGroup',\n * icon: 'ellipsis',\n * title: 'This is the title, displayed when user moves the mouse over the list toolgroup',\n * header: 'This is the header',\n * include: [ 'settings', 'stuff' ],\n * allowCollapse: ['stuff']\n * }\n * ] );\n *\n * // Create some UI around the toolbar and place it in the document\n * var frame = new OO.ui.PanelLayout( {\n * expanded: false,\n * framed: true\n * } );\n * frame.$element.append(\n * toolbar.$element\n * );\n * $( 'body' ).append( frame.$element );\n * // Build the toolbar. This must be done after the toolbar has been appended to the document.\n * toolbar.initialize();\n *\n * For more information about toolbars in general, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars\n *\n * @class\n * @extends OO.ui.PopupToolGroup\n *\n * @constructor\n * @param {OO.ui.Toolbar} toolbar\n * @param {Object} [config] Configuration options\n * @cfg {Array} [allowCollapse] Allow the specified tools to be collapsed. By default, collapsible tools\n * will only be displayed if users click the ‘More’ option displayed at the bottom of the list. If\n * the list is expanded, a ‘Fewer’ option permits users to collapse the list again. Any tools that\n * are included in the toolgroup, but are not designated as collapsible, will always be displayed.\n * To open a collapsible list in its expanded state, set #expanded to 'true'.\n * @cfg {Array} [forceExpand] Expand the specified tools. All other tools will be designated as collapsible.\n * Unless #expanded is set to true, the collapsible tools will be collapsed when the list is first opened.\n * @cfg {boolean} [expanded=false] Expand collapsible tools. This config is only relevant if tools have\n * been designated as collapsible. When expanded is set to true, all tools in the group will be displayed\n * when the list is first opened. Users can collapse the list with a ‘Fewer’ option at the bottom.\n */\nOO.ui.ListToolGroup = function OoUiListToolGroup( toolbar, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( toolbar ) && config === undefined ) {\n\t\tconfig = toolbar;\n\t\ttoolbar = config.toolbar;\n\t}\n\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties (must be set before parent constructor, which calls #populate)\n\tthis.allowCollapse = config.allowCollapse;\n\tthis.forceExpand = config.forceExpand;\n\tthis.expanded = config.expanded !== undefined ? config.expanded : false;\n\tthis.collapsibleTools = [];\n\n\t// Parent constructor\n\tOO.ui.ListToolGroup.parent.call( this, toolbar, config );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-listToolGroup' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ListToolGroup, OO.ui.PopupToolGroup );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.ListToolGroup.static.name = 'list';\n\n/* Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.ListToolGroup.prototype.populate = function () {\n\tvar i, len, allowCollapse = [];\n\n\tOO.ui.ListToolGroup.parent.prototype.populate.call( this );\n\n\t// Update the list of collapsible tools\n\tif ( this.allowCollapse !== undefined ) {\n\t\tallowCollapse = this.allowCollapse;\n\t} else if ( this.forceExpand !== undefined ) {\n\t\tallowCollapse = OO.simpleArrayDifference( Object.keys( this.tools ), this.forceExpand );\n\t}\n\n\tthis.collapsibleTools = [];\n\tfor ( i = 0, len = allowCollapse.length; i < len; i++ ) {\n\t\tif ( this.tools[ allowCollapse[ i ] ] !== undefined ) {\n\t\t\tthis.collapsibleTools.push( this.tools[ allowCollapse[ i ] ] );\n\t\t}\n\t}\n\n\t// Keep at the end, even when tools are added\n\tthis.$group.append( this.getExpandCollapseTool().$element );\n\n\tthis.getExpandCollapseTool().toggle( this.collapsibleTools.length !== 0 );\n\tthis.updateCollapsibleState();\n};\n\n/**\n * Get the expand/collapse tool for this group\n *\n * @return {OO.ui.Tool} Expand collapse tool\n */\nOO.ui.ListToolGroup.prototype.getExpandCollapseTool = function () {\n\tvar ExpandCollapseTool;\n\tif ( this.expandCollapseTool === undefined ) {\n\t\tExpandCollapseTool = function () {\n\t\t\tExpandCollapseTool.parent.apply( this, arguments );\n\t\t};\n\n\t\tOO.inheritClass( ExpandCollapseTool, OO.ui.Tool );\n\n\t\tExpandCollapseTool.prototype.onSelect = function () {\n\t\t\tthis.toolGroup.expanded = !this.toolGroup.expanded;\n\t\t\tthis.toolGroup.updateCollapsibleState();\n\t\t\tthis.setActive( false );\n\t\t};\n\t\tExpandCollapseTool.prototype.onUpdateState = function () {\n\t\t\t// Do nothing. Tool interface requires an implementation of this function.\n\t\t};\n\n\t\tExpandCollapseTool.static.name = 'more-fewer';\n\n\t\tthis.expandCollapseTool = new ExpandCollapseTool( this );\n\t}\n\treturn this.expandCollapseTool;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ListToolGroup.prototype.onMouseKeyUp = function ( e ) {\n\t// Do not close the popup when the user wants to show more/fewer tools\n\tif (\n\t\t$( e.target ).closest( '.oo-ui-tool-name-more-fewer' ).length &&\n\t\t( e.which === OO.ui.MouseButtons.LEFT || e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )\n\t) {\n\t\t// HACK: Prevent the popup list from being hidden. Skip the PopupToolGroup implementation (which\n\t\t// hides the popup list when a tool is selected) and call ToolGroup's implementation directly.\n\t\treturn OO.ui.ListToolGroup.parent.parent.prototype.onMouseKeyUp.call( this, e );\n\t} else {\n\t\treturn OO.ui.ListToolGroup.parent.prototype.onMouseKeyUp.call( this, e );\n\t}\n};\n\nOO.ui.ListToolGroup.prototype.updateCollapsibleState = function () {\n\tvar i, len;\n\n\tthis.getExpandCollapseTool()\n\t\t.setIcon( this.expanded ? 'collapse' : 'expand' )\n\t\t.setTitle( OO.ui.msg( this.expanded ? 'ooui-toolgroup-collapse' : 'ooui-toolgroup-expand' ) );\n\n\tfor ( i = 0, len = this.collapsibleTools.length; i < len; i++ ) {\n\t\tthis.collapsibleTools[ i ].toggle( this.expanded );\n\t}\n\n\t// Re-evaluate clipping, because our height has changed\n\tthis.clip();\n};\n","/**\n * MenuToolGroups are one of three types of {@link OO.ui.ToolGroup toolgroups} that are used to\n * create {@link OO.ui.Toolbar toolbars} (the other types of groups are {@link OO.ui.BarToolGroup BarToolGroup}\n * and {@link OO.ui.ListToolGroup ListToolGroup}). MenuToolGroups contain selectable {@link OO.ui.Tool tools},\n * which are displayed by label in a dropdown menu. The tool's title is used as the label text, and the\n * menu label is updated to reflect which tool or tools are currently selected. If no tools are selected,\n * the menu label is empty. The menu can be configured with an indicator, icon, title, and/or header.\n *\n * MenuToolGroups are created by a {@link OO.ui.ToolGroupFactory tool group factory} when the toolbar\n * is set up.\n *\n * @example\n * // Example of a MenuToolGroup\n * var toolFactory = new OO.ui.ToolFactory();\n * var toolGroupFactory = new OO.ui.ToolGroupFactory();\n * var toolbar = new OO.ui.Toolbar( toolFactory, toolGroupFactory );\n *\n * // We will be placing status text in this element when tools are used\n * var $area = $( '<p>' ).text( 'An example of a MenuToolGroup. Select a tool from the dropdown menu.' );\n *\n * // Define the tools that we're going to place in our toolbar\n *\n * function SettingsTool() {\n * SettingsTool.parent.apply( this, arguments );\n * this.reallyActive = false;\n * }\n * OO.inheritClass( SettingsTool, OO.ui.Tool );\n * SettingsTool.static.name = 'settings';\n * SettingsTool.static.icon = 'settings';\n * SettingsTool.static.title = 'Change settings';\n * SettingsTool.prototype.onSelect = function () {\n * $area.text( 'Settings tool clicked!' );\n * // Toggle the active state on each click\n * this.reallyActive = !this.reallyActive;\n * this.setActive( this.reallyActive );\n * // To update the menu label\n * this.toolbar.emit( 'updateState' );\n * };\n * SettingsTool.prototype.onUpdateState = function () {};\n * toolFactory.register( SettingsTool );\n *\n * function StuffTool() {\n * StuffTool.parent.apply( this, arguments );\n * this.reallyActive = false;\n * }\n * OO.inheritClass( StuffTool, OO.ui.Tool );\n * StuffTool.static.name = 'stuff';\n * StuffTool.static.icon = 'ellipsis';\n * StuffTool.static.title = 'More stuff';\n * StuffTool.prototype.onSelect = function () {\n * $area.text( 'More stuff tool clicked!' );\n * // Toggle the active state on each click\n * this.reallyActive = !this.reallyActive;\n * this.setActive( this.reallyActive );\n * // To update the menu label\n * this.toolbar.emit( 'updateState' );\n * };\n * StuffTool.prototype.onUpdateState = function () {};\n * toolFactory.register( StuffTool );\n *\n * // Finally define which tools and in what order appear in the toolbar. Each tool may only be\n * // used once (but not all defined tools must be used).\n * toolbar.setup( [\n * {\n * type: 'menu',\n * header: 'This is the (optional) header',\n * title: 'This is the (optional) title',\n * include: [ 'settings', 'stuff' ]\n * }\n * ] );\n *\n * // Create some UI around the toolbar and place it in the document\n * var frame = new OO.ui.PanelLayout( {\n * expanded: false,\n * framed: true\n * } );\n * var contentFrame = new OO.ui.PanelLayout( {\n * expanded: false,\n * padded: true\n * } );\n * frame.$element.append(\n * toolbar.$element,\n * contentFrame.$element.append( $area )\n * );\n * $( 'body' ).append( frame.$element );\n *\n * // Here is where the toolbar is actually built. This must be done after inserting it into the\n * // document.\n * toolbar.initialize();\n * toolbar.emit( 'updateState' );\n *\n * For more information about how to add tools to a MenuToolGroup, please see {@link OO.ui.ToolGroup toolgroup}.\n * For more information about toolbars in general, please see the [OOjs UI documentation on MediaWiki] [1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Toolbars\n *\n * @class\n * @extends OO.ui.PopupToolGroup\n *\n * @constructor\n * @param {OO.ui.Toolbar} toolbar\n * @param {Object} [config] Configuration options\n */\nOO.ui.MenuToolGroup = function OoUiMenuToolGroup( toolbar, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( toolbar ) && config === undefined ) {\n\t\tconfig = toolbar;\n\t\ttoolbar = config.toolbar;\n\t}\n\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.MenuToolGroup.parent.call( this, toolbar, config );\n\n\t// Events\n\tthis.toolbar.connect( this, { updateState: 'onUpdateState' } );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-menuToolGroup' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.MenuToolGroup, OO.ui.PopupToolGroup );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.MenuToolGroup.static.name = 'menu';\n\n/* Methods */\n\n/**\n * Handle the toolbar state being updated.\n *\n * When the state changes, the title of each active item in the menu will be joined together and\n * used as a label for the group. The label will be empty if none of the items are active.\n *\n * @private\n */\nOO.ui.MenuToolGroup.prototype.onUpdateState = function () {\n\tvar name,\n\t\tlabelTexts = [];\n\n\tfor ( name in this.tools ) {\n\t\tif ( this.tools[ name ].isActive() ) {\n\t\t\tlabelTexts.push( this.tools[ name ].getTitle() );\n\t\t}\n\t}\n\n\tthis.setLabel( labelTexts.join( ', ' ) || ' ' );\n};\n","}( OO ) );\n"]} \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-apex.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-apex.css
new file mode 100644
index 00000000..660f5476
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-apex.css
@@ -0,0 +1,1154 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:24:03Z
+ */
+.oo-ui-draggableElement-handle:not( .oo-ui-draggableElement-undraggable ).oo-ui-widget {
+ cursor: move;
+ cursor: url(images/grab.cur );
+ cursor: -webkit-grab;
+ cursor: -moz-grab;
+ cursor: grab;
+}
+.oo-ui-draggableElement-handle:not( .oo-ui-draggableElement-undraggable ):active {
+ cursor: url(images/grabbing.cur );
+ cursor: -webkit-grabbing;
+ cursor: -moz-grabbing;
+ cursor: grabbing;
+}
+.oo-ui-draggableElement-handle.oo-ui-widget-disabled,
+.oo-ui-widget-disabled .oo-ui-draggableElement-handle {
+ cursor: default;
+}
+.oo-ui-draggableElement-placeholder {
+ opacity: 0.2;
+}
+.oo-ui-draggableGroupElement-horizontal .oo-ui-draggableElement {
+ display: inline-block;
+}
+.oo-ui-bookletLayout-stackLayout.oo-ui-stackLayout-continuous > .oo-ui-panelLayout-scrollable {
+ overflow: hidden;
+}
+.oo-ui-bookletLayout-stackLayout > .oo-ui-panelLayout {
+ width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-bookletLayout-outlinePanel-editable > .oo-ui-outlineSelectWidget {
+ height: auto;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 2.5em;
+ overflow: auto;
+}
+.oo-ui-bookletLayout-outlinePanel > .oo-ui-outlineControlsWidget {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 2.5em;
+}
+.oo-ui-bookletLayout-stackLayout > .oo-ui-panelLayout {
+ padding: 1.5em;
+}
+.oo-ui-bookletLayout-outlinePanel {
+ border-right: 1px solid #ddd;
+}
+.oo-ui-bookletLayout-outlinePanel > .oo-ui-outlineControlsWidget {
+ box-shadow: 0 0 0.25em rgba(0, 0, 0, 0.25);
+}
+.oo-ui-indexLayout > .oo-ui-menuLayout-menu {
+ height: 3em;
+}
+.oo-ui-indexLayout > .oo-ui-menuLayout-content {
+ top: 3em;
+}
+.oo-ui-indexLayout-stackLayout > .oo-ui-panelLayout {
+ padding: 1.5em;
+}
+.oo-ui-menuLayout {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-menuLayout-menu,
+.oo-ui-menuLayout-content {
+ position: absolute;
+ -webkit-transition: all 200ms ease;
+ -moz-transition: all 200ms ease;
+ transition: all 200ms ease;
+}
+.oo-ui-menuLayout-menu {
+ height: 18em;
+ width: 18em;
+}
+.oo-ui-menuLayout-content {
+ top: 18em;
+ left: 18em;
+ right: 18em;
+ bottom: 18em;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu > .oo-ui-menuLayout-menu {
+ width: 0 !important;
+ height: 0 !important;
+ overflow: hidden;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu > .oo-ui-menuLayout-content {
+ top: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ bottom: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top > .oo-ui-menuLayout-menu {
+ width: auto !important;
+ left: 0;
+ top: 0;
+ right: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top > .oo-ui-menuLayout-content {
+ right: 0 !important;
+ bottom: 0 !important;
+ left: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after > .oo-ui-menuLayout-menu {
+ height: auto !important;
+ top: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after > .oo-ui-menuLayout-content {
+ bottom: 0 !important;
+ left: 0 !important;
+ top: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom > .oo-ui-menuLayout-menu {
+ width: auto !important;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom > .oo-ui-menuLayout-content {
+ left: 0 !important;
+ top: 0 !important;
+ right: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before > .oo-ui-menuLayout-menu {
+ height: auto !important;
+ bottom: 0;
+ left: 0;
+ top: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before > .oo-ui-menuLayout-content {
+ top: 0 !important;
+ right: 0 !important;
+ bottom: 0 !important;
+}
+.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
+ display: block;
+ position: relative;
+}
+.oo-ui-buttonSelectWidget {
+ display: inline-block;
+ white-space: nowrap;
+ border-radius: 4px;
+ margin-right: 0.5em;
+ z-index: 0;
+ position: relative;
+}
+.oo-ui-buttonSelectWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonSelectWidget:focus {
+ outline: 0;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+ border-radius: 0;
+ margin-left: -1px;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonElement-button {
+ border-bottom-left-radius: 4px;
+ border-top-left-radius: 4px;
+ margin-left: 0;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonElement-button {
+ border-bottom-right-radius: 4px;
+ border-top-right-radius: 4px;
+}
+.oo-ui-buttonSelectWidget.oo-ui-widget-enabled:focus .oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected .oo-ui-buttonElement-button {
+ border-color: #ace;
+ box-shadow: 0 0 2px 2px #ace;
+}
+.oo-ui-buttonSelectWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonSelectWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active {
+ z-index: 1;
+}
+.oo-ui-buttonSelectWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ z-index: 3;
+}
+.oo-ui-buttonSelectWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ z-index: -1;
+}
+.oo-ui-buttonOptionWidget {
+ display: inline-block;
+ padding: 0;
+ background-color: transparent;
+}
+.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active .oo-ui-buttonElement-button {
+ cursor: default;
+}
+.oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ position: static;
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected,
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-highlighted {
+ background-color: transparent;
+}
+.oo-ui-toggleButtonWidget {
+ margin-right: 0.5em;
+}
+.oo-ui-toggleButtonWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-toggleSwitchWidget {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+ overflow: hidden;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
+ height: 2em;
+ width: 4em;
+ border-radius: 1em;
+ box-shadow: 0 0 0 #fff, inset 0 0.1em 0.2em #ddd;
+ border: 1px solid #ccc;
+ margin-right: 0.5em;
+ background-color: #eeeeee;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #ddd), color-stop(100%, #fff));
+ background-image: -webkit-linear-gradient(top, #ddd 0, #fff 100%);
+ background-image: -moz-linear-gradient(top, #ddd 0, #fff 100%);
+ background-image: linear-gradient(to bottom, #ddd 0, #fff 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffdddddd', endColorstr='#ffffffff' )";
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled {
+ cursor: pointer;
+}
+.oo-ui-toggleSwitchWidget-grip {
+ position: absolute;
+ display: block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-toggleSwitchWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+ opacity: 0.5;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover .oo-ui-toggleSwitchWidget-grip {
+ border-color: #aaa;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus {
+ outline: 0;
+ border-color: #ace;
+ box-shadow: 0 0 2px 2px #ace;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus .oo-ui-toggleSwitchWidget-grip {
+ border-color: #ace;
+}
+.oo-ui-toggleSwitchWidget-grip {
+ top: 0.25em;
+ left: 0.25em;
+ width: 1.5em;
+ height: 1.5em;
+ margin-top: -1px;
+ border-radius: 1em;
+ box-shadow: 0 0.1em 0.25em rgba(0, 0, 0, 0.1);
+ border: 1px #c9c9c9 solid;
+ -webkit-transition: left 250ms ease, margin-left 250ms ease;
+ -moz-transition: left 250ms ease, margin-left 250ms ease;
+ transition: left 250ms ease, margin-left 250ms ease;
+ background-color: #eeeeee;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #fff), color-stop(100%, #ddd));
+ background-image: -webkit-linear-gradient(top, #fff 0, #ddd 100%);
+ background-image: -moz-linear-gradient(top, #fff 0, #ddd 100%);
+ background-image: linear-gradient(to bottom, #fff 0, #ddd 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffffff', endColorstr='#ffdddddd' )";
+}
+.oo-ui-toggleSwitchWidget-glow {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ left: 0;
+ border-radius: 1em;
+ box-shadow: inset 0 1px 4px 0 rgba(0, 0, 0, 0.07);
+ -webkit-transition: opacity 250ms ease;
+ -moz-transition: opacity 250ms ease;
+ transition: opacity 250ms ease;
+ background-color: #cde7f4;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #b0d9ee), color-stop(100%, #eaf4fa));
+ background-image: -webkit-linear-gradient(top, #b0d9ee 0, #eaf4fa 100%);
+ background-image: -moz-linear-gradient(top, #b0d9ee 0, #eaf4fa 100%);
+ background-image: linear-gradient(to bottom, #b0d9ee 0, #eaf4fa 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffb0d9ee', endColorstr='#ffeaf4fa' )";
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+ opacity: 0;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
+ left: 0.25em;
+ margin-left: 0;
+}
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-glow {
+ opacity: 1;
+}
+.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+ left: 2.25em;
+ margin-left: -2px;
+}
+.oo-ui-selectFileWidget {
+ display: inline-block;
+ vertical-align: middle;
+ width: 100%;
+ max-width: 50em;
+ margin-right: 0.5em;
+}
+.oo-ui-selectFileWidget-selectButton {
+ display: table-cell;
+}
+.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
+ position: relative;
+ overflow: hidden;
+}
+.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button > [type='file'] {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ z-index: 1;
+ cursor: pointer;
+ padding-top: 100px;
+}
+.oo-ui-selectFileWidget-selectButton.oo-ui-widget-disabled > .oo-ui-buttonElement-button > [type='file'] {
+ display: none;
+}
+.oo-ui-selectFileWidget-info {
+ width: 100%;
+ display: table-cell;
+ vertical-align: middle;
+ position: relative;
+ overflow: hidden;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator,
+.oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon {
+ position: absolute;
+ top: 0;
+ height: 100%;
+}
+.oo-ui-widget-disabled .oo-ui-selectFileWidget-info {
+ cursor: default;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-selectFileWidget-label {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-overflow: ellipsis;
+}
+.oo-ui-selectFileWidget-clearButton {
+ position: absolute;
+ z-index: 2;
+}
+.oo-ui-selectFileWidget-dropTarget {
+ position: relative;
+ cursor: default;
+ height: 8.815em;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel,
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton,
+.oo-ui-selectFileWidget-dropTarget .oo-ui-iconElement-icon {
+ display: none;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail {
+ width: 7.815em;
+ position: absolute;
+ top: 0.5em;
+ bottom: 0.5em;
+ left: 0.5em;
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: contain;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail.oo-ui-pendingElement-pending {
+ background-repeat: repeat;
+ background-size: auto;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail > .oo-ui-selectFileWidget-noThumbnail-icon {
+ opacity: 0.4;
+ height: 7.815em;
+ width: 7.815em;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+ display: block;
+ height: 100%;
+ width: auto;
+ margin-left: 8.815em;
+ border: 0;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-label {
+ display: block;
+ position: relative;
+ top: inherit;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-fileName {
+ display: block;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail,
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+ display: none;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
+ display: block;
+ margin: 2.2em 1em 1em;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
+ text-align: center;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+ margin: 0;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-clearButton,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-clearButton {
+ display: none;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-enabled .oo-ui-selectFileWidget-label {
+ cursor: default;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-enabled .oo-ui-selectFileWidget-dropLabel {
+ display: block;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button {
+ cursor: no-drop;
+}
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
+ height: auto;
+}
+.oo-ui-selectFileWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
+ border-radius: 0 0.25em 0.25em 0;
+}
+.oo-ui-selectFileWidget-info {
+ height: 2.4em;
+ background-color: #fff;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ border-radius: 0.25em 0 0 0.25em;
+ border-width: 1px 0 1px 1px;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon {
+ left: 0;
+ margin-left: 0.3em;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator {
+ right: 0;
+ margin-right: 0.775em;
+}
+.oo-ui-selectFileWidget-label {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ left: 0.5em;
+ right: 2.175em;
+ line-height: 2.3em;
+ margin: 0;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+}
+.oo-ui-selectFileWidget-clearButton {
+ top: 0;
+ right: 0;
+ width: 1.875em;
+ margin-right: 0;
+}
+.oo-ui-selectFileWidget-clearButton .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ height: 2.3em;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-label {
+ color: #ccc;
+}
+.oo-ui-selectFileWidget.oo-ui-iconElement .oo-ui-selectFileWidget-label {
+ left: 2.475em;
+}
+.oo-ui-selectFileWidget.oo-ui-indicatorElement .oo-ui-selectFileWidget-label {
+ right: 4.2625em;
+}
+.oo-ui-selectFileWidget.oo-ui-indicatorElement .oo-ui-selectFileWidget-clearButton {
+ right: 2.0875em;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-label,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-label {
+ right: 0.5em;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-indicatorElement .oo-ui-selectFileWidget-label,
+.oo-ui-selectFileWidget-notsupported.oo-ui-indicatorElement .oo-ui-selectFileWidget-label,
+.oo-ui-selectFileWidget-empty.oo-ui-indicatorElement .oo-ui-selectFileWidget-label,
+.oo-ui-selectFileWidget-notsupported.oo-ui-indicatorElement .oo-ui-selectFileWidget-label {
+ right: 2em;
+}
+.oo-ui-selectFileWidget-supported.oo-ui-widget-enabled.oo-ui-selectFileWidget-canDrop.oo-ui-selectFileWidget-dropTarget {
+ background-color: #e1f3ff;
+}
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-label {
+ padding: 1em;
+}
+.oo-ui-selectFileWidget-dropTarget {
+ background-color: #fff;
+ border: 1px solid #aaa;
+ vertical-align: middle;
+ border-radius: 0.25em;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
+ border-radius: 0.25em;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-label {
+ line-height: 1.4;
+ overflow: inherit;
+ white-space: normal;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-fileName {
+ padding-top: 0.5em;
+ padding-right: 2.375em;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-clearButton {
+ right: 0.5em;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget {
+ border-style: dashed;
+}
+.oo-ui-selectFileWidget.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
+ background-color: #f3f3f3;
+ color: #ccc;
+ border-color: #ddd;
+ text-shadow: 0 1px 1px #fff;
+}
+.oo-ui-selectFileWidget.oo-ui-widget-disabled .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-info {
+ background-color: #f3f3f3;
+ color: #ccc;
+ border-color: #ddd;
+ text-shadow: 0 1px 1px #fff;
+}
+.oo-ui-selectFileWidget.oo-ui-widget-disabled .oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon,
+.oo-ui-selectFileWidget.oo-ui-widget-disabled .oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-outlineOptionWidget {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ font-size: 1.1em;
+ padding: 0.75em;
+}
+.oo-ui-outlineOptionWidget .oo-ui-iconElement-icon {
+ font-size: 90.90909%;
+}
+.oo-ui-outlineOptionWidget.oo-ui-indicatorElement .oo-ui-labelElement-label {
+ padding-right: 1.5em;
+}
+.oo-ui-outlineOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ opacity: 0.5;
+}
+.oo-ui-outlineOptionWidget-level-0.oo-ui-iconElement {
+ padding-left: 2.5em;
+}
+.oo-ui-outlineOptionWidget-level-1 {
+ padding-left: 2.5em;
+}
+.oo-ui-outlineOptionWidget-level-1.oo-ui-iconElement {
+ padding-left: 4.5em;
+}
+.oo-ui-outlineOptionWidget-level-1.oo-ui-iconElement .oo-ui-iconElement-icon {
+ left: 2.5em;
+}
+.oo-ui-outlineOptionWidget-level-2 {
+ padding-left: 5em;
+}
+.oo-ui-outlineOptionWidget-level-2.oo-ui-iconElement {
+ padding-left: 7em;
+}
+.oo-ui-outlineOptionWidget-level-2.oo-ui-iconElement .oo-ui-iconElement-icon {
+ left: 5em;
+}
+.oo-ui-selectWidget-depressed .oo-ui-outlineOptionWidget.oo-ui-optionWidget-selected {
+ background-color: #a7dcff;
+ text-shadow: 0 1px 1px rgba(255, 255, 255, 0.5);
+}
+.oo-ui-outlineControlsWidget {
+ overflow: hidden;
+ background-color: #fff;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+ float: left;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+ float: left;
+ background-position: right center;
+}
+.oo-ui-outlineControlsWidget-items {
+ float: left;
+}
+.oo-ui-outlineControlsWidget-items .oo-ui-buttonWidget {
+ float: left;
+}
+.oo-ui-outlineControlsWidget-movers {
+ float: right;
+}
+.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
+ float: right;
+}
+.oo-ui-outlineControlsWidget-items > .oo-ui-buttonWidget,
+.oo-ui-outlineControlsWidget-movers > .oo-ui-buttonWidget {
+ height: 2.5em;
+ width: 2.5em;
+ margin: 0 !important;
+ /* stylelint-disable-line declaration-no-important */
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+ height: 2.5em;
+ opacity: 0.2;
+}
+.oo-ui-tabSelectWidget {
+ text-align: left;
+ white-space: nowrap;
+ overflow: hidden;
+ background-color: #eee;
+ box-shadow: inset 0 -0.015em 0.1em rgba(0, 0, 0, 0.1);
+}
+.oo-ui-tabOptionWidget {
+ display: inline-block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ vertical-align: bottom;
+ margin: 0.5em 0 0 0.75em;
+ border-color: transparent;
+ border-style: solid;
+ border-width: 1px 1px 0 1px;
+ border-top-left-radius: 0.5em;
+ border-top-right-radius: 0.5em;
+ padding: 0.5em 1em;
+}
+.oo-ui-tabOptionWidget.oo-ui-optionWidget-selected {
+ background-color: #fff;
+ border-color: #ddd;
+}
+.oo-ui-tabOptionWidget.oo-ui-widget-enabled:hover {
+ background-color: rgba(255, 255, 255, 0.2);
+ border-color: #ddd;
+}
+.oo-ui-tabOptionWidget.oo-ui-widget-enabled:active {
+ background-color: #fff;
+ border-color: #ddd;
+}
+.oo-ui-tabOptionWidget.oo-ui-widget-enabled.oo-ui-optionWidget-selected:hover {
+ background-color: #fff;
+}
+.oo-ui-tagMultiselectWidget {
+ display: inline-block;
+ position: relative;
+ width: 100%;
+ max-width: 50em;
+}
+.oo-ui-tagMultiselectWidget-handle {
+ width: 100%;
+ display: block;
+ position: relative;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-iconElement-icon,
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ position: absolute;
+ top: 0;
+ height: 100%;
+}
+.oo-ui-tagMultiselectWidget-content {
+ position: relative;
+}
+.oo-ui-tagMultiselectWidget-group {
+ display: inline;
+}
+.oo-ui-tagMultiselectWidget-outlined {
+ width: 100%;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-enabled.oo-ui-tagMultiselectWidget-inlined .oo-ui-tagMultiselectWidget-handle {
+ cursor: text;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-disabled .oo-ui-tagMultiselectWidget-content > input {
+ display: none;
+}
+.oo-ui-tagMultiselectWidget-focusTrap {
+ display: inline-block;
+ height: 1px;
+ width: 1px;
+}
+.oo-ui-tagMultiselectWidget-focusTrap:focus {
+ outline: 0;
+}
+.oo-ui-tagMultiselectWidget-handle {
+ background-color: #fff;
+ cursor: text;
+ min-height: 2.4em;
+ margin-right: 0.5em;
+ padding: 0.15em 0.25em;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ border-radius: 0.25em;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-tagMultiselectWidget-handle:last-child {
+ margin-right: 0;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input {
+ border: 0;
+ line-height: 1.675em;
+ margin: 0;
+ margin-left: 0.2em;
+ padding: 0;
+ font-size: inherit;
+ font-family: inherit;
+ background-color: transparent;
+ color: #000;
+ vertical-align: middle;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input::-webkit-input-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input:-ms-input-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input::-moz-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input:-moz-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input::placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input:focus {
+ outline: 0;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-iconElement .oo-ui-tagMultiselectWidget-handle {
+ padding-left: 2.475em;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-iconElement .oo-ui-tagMultiselectWidget-handle > .oo-ui-iconElement-icon {
+ left: 0;
+ margin: 0 0.3em;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-indicatorElement .oo-ui-tagMultiselectWidget-handle {
+ padding-right: 2.4875em;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-indicatorElement .oo-ui-tagMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ right: 0;
+ margin: 0 0.775em;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-enabled.oo-ui-tagMultiselectWidget-inlined:hover .oo-ui-tagMultiselectWidget.oo-ui-widget-enabled.oo-ui-tagMultiselectWidget-inlined-handle {
+ border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-enabled.oo-ui-tagMultiselectWidget-inlined.oo-ui-tagMultiselectWidget-focus .oo-ui-tagMultiselectWidget-handle {
+ border-color: #ace;
+ outline: 0;
+ box-shadow: 0 0 2px 2px #ace;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-disabled .oo-ui-tagMultiselectWidget-handle {
+ color: #ccc;
+ text-shadow: 0 1px 1px #fff;
+ border-color: #ddd;
+ background-color: #f3f3f3;
+ cursor: default;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-disabled .oo-ui-tagMultiselectWidget-handle > .oo-ui-iconElement-icon,
+.oo-ui-tagMultiselectWidget.oo-ui-widget-disabled .oo-ui-tagMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-tagMultiselectWidget-popup > .oo-ui-popupWidget-popup {
+ border: 0;
+}
+.oo-ui-tagItemWidget {
+ position: relative;
+ display: inline-block;
+ cursor: default;
+ white-space: nowrap;
+ width: auto;
+ max-width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ vertical-align: middle;
+ padding: 0 0.4em;
+ margin: 0.1em;
+ height: 1.7em;
+ line-height: 1.7em;
+ background-color: #eeeeee;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #fff), color-stop(100%, #ddd));
+ background-image: -webkit-linear-gradient(top, #fff 0, #ddd 100%);
+ background-image: -moz-linear-gradient(top, #fff 0, #ddd 100%);
+ background-image: linear-gradient(to bottom, #fff 0, #ddd 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffffff', endColorstr='#ffdddddd' )";
+ border: 1px solid #ccc;
+ color: #333;
+ border-radius: 0.25em;
+}
+.oo-ui-tagItemWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: inline-block;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ cursor: text;
+}
+.oo-ui-tagItemWidget:focus {
+ outline: 0;
+ border-color: #087ecc;
+}
+.oo-ui-tagItemWidget > .oo-ui-buttonElement {
+ margin-top: -1.25em;
+ padding-left: 0.3em;
+}
+.oo-ui-tagItemWidget > .oo-ui-buttonElement > .oo-ui-buttonElement-button {
+ padding: 0;
+}
+.oo-ui-tagItemWidget > .oo-ui-buttonElement > .oo-ui-buttonElement-button .oo-ui-iconElement-icon {
+ min-width: 20px;
+ width: 1.5625em;
+ margin-right: -0.3em;
+}
+.oo-ui-tagItemWidget > .oo-ui-buttonElement > .oo-ui-buttonElement-button .oo-ui-labelElement-label,
+.oo-ui-tagItemWidget > .oo-ui-buttonElement > .oo-ui-buttonElement-button .oo-ui-indicatorElement-indicator {
+ display: none;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-disabled {
+ opacity: 0.5;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
+ box-shadow: none;
+ color: #333;
+ background: #eee;
+ border-color: #ccc;
+}
+.oo-ui-capsuleMultiselectWidget {
+ display: inline-block;
+ position: relative;
+ width: 100%;
+ max-width: 50em;
+}
+.oo-ui-capsuleMultiselectWidget-handle {
+ width: 100%;
+ display: block;
+ position: relative;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-iconElement-icon,
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ position: absolute;
+ top: 0;
+ height: 100%;
+}
+.oo-ui-capsuleMultiselectWidget-content {
+ position: relative;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiselectWidget-content > input {
+ display: none;
+}
+.oo-ui-capsuleMultiselectWidget-group {
+ display: inline;
+}
+.oo-ui-capsuleMultiselectWidget-popup > .oo-ui-popupWidget-popup > .oo-ui-popupWidget-body > * {
+ display: block;
+}
+.oo-ui-capsuleMultiselectWidget-focusTrap {
+ display: inline-block;
+ height: 1px;
+ width: 1px;
+}
+.oo-ui-capsuleMultiselectWidget-focusTrap:focus {
+ outline: 0;
+}
+.oo-ui-capsuleMultiselectWidget-handle {
+ background-color: #fff;
+ cursor: text;
+ min-height: 2.4em;
+ margin-right: 0.5em;
+ padding: 0.15em 0.25em;
+ border: 1px solid rgba(0, 0, 0, 0.1);
+ border-radius: 0.25em;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-capsuleMultiselectWidget-handle:last-child {
+ margin-right: 0;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input {
+ border: 0;
+ line-height: 1.675em;
+ margin: 0;
+ margin-left: 0.2em;
+ padding: 0;
+ font-size: inherit;
+ font-family: inherit;
+ background-color: transparent;
+ color: #000;
+ vertical-align: middle;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input::-webkit-input-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input:-ms-input-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input::-moz-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input:-moz-placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input::placeholder {
+ color: #767676;
+ opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input:focus {
+ outline: 0;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-iconElement .oo-ui-capsuleMultiselectWidget-handle {
+ padding-left: 2.475em;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-iconElement .oo-ui-capsuleMultiselectWidget-handle > .oo-ui-iconElement-icon {
+ left: 0;
+ margin: 0 0.3em;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-indicatorElement .oo-ui-capsuleMultiselectWidget-handle {
+ padding-right: 2.4875em;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-indicatorElement .oo-ui-capsuleMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ right: 0;
+ margin: 0 0.775em;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-enabled:hover .oo-ui-capsuleMultiselectWidget-handle {
+ border-color: rgba(0, 0, 0, 0.2);
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-enabled.oo-ui-capsuleMultiselectWidget-open .oo-ui-capsuleMultiselectWidget-handle {
+ border-color: #ace;
+ outline: 0;
+ box-shadow: 0 0 2px 2px #ace;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiselectWidget-handle {
+ color: #ccc;
+ text-shadow: 0 1px 1px #fff;
+ border-color: #ddd;
+ background-color: #f3f3f3;
+ cursor: default;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiselectWidget-handle > .oo-ui-iconElement-icon,
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-capsuleMultiselectWidget-popup > .oo-ui-popupWidget-popup {
+ border: 0;
+}
+.oo-ui-capsuleItemWidget {
+ position: relative;
+ display: inline-block;
+ cursor: default;
+ white-space: nowrap;
+ width: auto;
+ max-width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ vertical-align: middle;
+ padding: 0 0.4em;
+ margin: 0.1em;
+ height: 1.7em;
+ line-height: 1.7em;
+ background-color: #eeeeee;
+ background-image: -webkit-gradient(linear, right top, right bottom, color-stop(0, #fff), color-stop(100%, #ddd));
+ background-image: -webkit-linear-gradient(top, #fff 0, #ddd 100%);
+ background-image: -moz-linear-gradient(top, #fff 0, #ddd 100%);
+ background-image: linear-gradient(to bottom, #fff 0, #ddd 100%);
+ -ms-filter: "progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffffffff', endColorstr='#ffdddddd' )";
+ border: 1px solid #ccc;
+ color: #333;
+ border-radius: 0.25em;
+}
+.oo-ui-capsuleItemWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: inline-block;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ cursor: text;
+}
+.oo-ui-capsuleItemWidget:focus {
+ outline: 0;
+ border-color: #087ecc;
+}
+.oo-ui-capsuleItemWidget > .oo-ui-buttonElement {
+ margin-top: -1.25em;
+ padding-left: 0.3em;
+}
+.oo-ui-capsuleItemWidget > .oo-ui-buttonElement > .oo-ui-buttonElement-button {
+ padding: 0;
+}
+.oo-ui-capsuleItemWidget > .oo-ui-buttonElement > .oo-ui-buttonElement-button .oo-ui-iconElement-icon {
+ min-width: 20px;
+ width: 1.5625em;
+ margin-right: -0.3em;
+}
+.oo-ui-capsuleItemWidget > .oo-ui-buttonElement > .oo-ui-buttonElement-button .oo-ui-labelElement-label,
+.oo-ui-capsuleItemWidget > .oo-ui-buttonElement > .oo-ui-buttonElement-button .oo-ui-indicatorElement-indicator {
+ display: none;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-disabled {
+ opacity: 0.5;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
+ box-shadow: none;
+ color: #333;
+ background: #eee;
+ border-color: #ccc;
+}
+.oo-ui-searchWidget-query {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+ width: 100%;
+}
+.oo-ui-searchWidget-results {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.oo-ui-searchWidget-query {
+ height: 4em;
+ padding: 0 1em;
+ box-shadow: 0 0 0.5em rgba(0, 0, 0, 0.2);
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+ margin: 0.75em 0;
+}
+.oo-ui-searchWidget-results {
+ top: 4em;
+ padding: 1em;
+ line-height: 0;
+}
+.oo-ui-numberInputWidget {
+ display: inline-block;
+ position: relative;
+ max-width: 50em;
+}
+.oo-ui-numberInputWidget-buttoned .oo-ui-buttonWidget,
+.oo-ui-numberInputWidget-buttoned .oo-ui-inputWidget-input {
+ display: table-cell;
+ height: 100%;
+}
+.oo-ui-numberInputWidget-field {
+ display: table;
+ table-layout: fixed;
+ width: 100%;
+}
+.oo-ui-numberInputWidget-field > .oo-ui-buttonWidget {
+ width: 2.25em;
+}
+.oo-ui-numberInputWidget-buttoned .oo-ui-buttonElement-button .oo-ui-iconElement-icon {
+ min-width: 20px;
+ width: 1.5625em;
+}
+.oo-ui-numberInputWidget-buttoned .oo-ui-inputWidget-input {
+ border-radius: 0;
+}
+.oo-ui-numberInputWidget-minusButton > .oo-ui-buttonElement-button {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ border-right-width: 0;
+}
+.oo-ui-numberInputWidget-plusButton > .oo-ui-buttonElement-button {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ border-left-width: 0;
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-mediawiki.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-mediawiki.css
new file mode 100644
index 00000000..5c48ea52
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-mediawiki.css
@@ -0,0 +1,1017 @@
+/*!
+ * OOjs UI v0.17.1
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2016 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2016-05-03T22:58:06Z
+ */
+.oo-ui-draggableElement-handle,
+.oo-ui-draggableElement-handle.oo-ui-widget {
+ cursor: move;
+ cursor: url(images/grab.cur );
+ cursor: -webkit-grab;
+ cursor: -moz-grab;
+ cursor: grab;
+}
+.oo-ui-draggableElement-handle:active {
+ cursor: move;
+ cursor: url(images/grabbing.cur );
+ cursor: -webkit-grabbing;
+ cursor: -moz-grabbing;
+ cursor: grabbing;
+}
+.oo-ui-draggableElement-handle.oo-ui-widget-disabled,
+.oo-ui-widget-disabled .oo-ui-draggableElement-handle {
+ cursor: default;
+}
+.oo-ui-draggableElement-placeholder {
+ opacity: 0.2;
+}
+.oo-ui-draggableGroupElement-horizontal .oo-ui-draggableElement {
+ display: inline-block;
+}
+.oo-ui-lookupElement > .oo-ui-menuSelectWidget {
+ z-index: 1;
+ width: 100%;
+}
+.oo-ui-bookletLayout-stackLayout.oo-ui-stackLayout-continuous > .oo-ui-panelLayout-scrollable {
+ overflow-y: hidden;
+}
+.oo-ui-bookletLayout-stackLayout > .oo-ui-panelLayout {
+ width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-bookletLayout-stackLayout > .oo-ui-panelLayout-scrollable {
+ overflow-y: auto;
+}
+.oo-ui-bookletLayout-stackLayout > .oo-ui-panelLayout-padded {
+ padding: 2em;
+}
+.oo-ui-bookletLayout-outlinePanel-editable > .oo-ui-outlineSelectWidget {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 3em;
+ overflow-y: auto;
+}
+.oo-ui-bookletLayout-outlinePanel > .oo-ui-outlineControlsWidget {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+.oo-ui-bookletLayout-stackLayout > .oo-ui-panelLayout {
+ padding: 1.5em;
+}
+.oo-ui-bookletLayout-outlinePanel {
+ border-right: 1px solid #dddddd;
+}
+.oo-ui-bookletLayout-outlinePanel > .oo-ui-outlineControlsWidget {
+ box-shadow: 0 0.15em 0 0 rgba(0, 0, 0, 0.15);
+}
+.oo-ui-indexLayout > .oo-ui-menuLayout-menu {
+ height: 3em;
+}
+.oo-ui-indexLayout > .oo-ui-menuLayout-content {
+ top: 3em;
+}
+.oo-ui-indexLayout-stackLayout > .oo-ui-panelLayout {
+ padding: 1.5em;
+}
+.oo-ui-indexLayout > .oo-ui-menuLayout-menu {
+ height: 2.75em;
+}
+.oo-ui-indexLayout > .oo-ui-menuLayout-content {
+ top: 2.75em;
+}
+.oo-ui-menuLayout {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-menuLayout-menu,
+.oo-ui-menuLayout-content {
+ position: absolute;
+ -webkit-transition: all 200ms ease;
+ -moz-transition: all 200ms ease;
+ transition: all 200ms ease;
+}
+.oo-ui-menuLayout-menu {
+ height: 18em;
+ width: 18em;
+}
+.oo-ui-menuLayout-content {
+ top: 18em;
+ left: 18em;
+ right: 18em;
+ bottom: 18em;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu > .oo-ui-menuLayout-menu {
+ width: 0 !important;
+ height: 0 !important;
+ overflow: hidden;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu > .oo-ui-menuLayout-content {
+ top: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ bottom: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top > .oo-ui-menuLayout-menu {
+ width: auto !important;
+ left: 0;
+ top: 0;
+ right: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top > .oo-ui-menuLayout-content {
+ right: 0 !important;
+ bottom: 0 !important;
+ left: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after > .oo-ui-menuLayout-menu {
+ height: auto !important;
+ top: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after > .oo-ui-menuLayout-content {
+ bottom: 0 !important;
+ left: 0 !important;
+ top: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom > .oo-ui-menuLayout-menu {
+ width: auto !important;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom > .oo-ui-menuLayout-content {
+ left: 0 !important;
+ top: 0 !important;
+ right: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before > .oo-ui-menuLayout-menu {
+ height: auto !important;
+ bottom: 0;
+ left: 0;
+ top: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before > .oo-ui-menuLayout-content {
+ top: 0 !important;
+ right: 0 !important;
+ bottom: 0 !important;
+}
+.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
+ display: block;
+ position: relative;
+}
+.oo-ui-buttonSelectWidget {
+ display: inline-block;
+ white-space: nowrap;
+ border-radius: 2px;
+ margin-right: 0.5em;
+}
+.oo-ui-buttonSelectWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonSelectWidget:focus {
+ outline: 0;
+}
+.oo-ui-buttonSelectWidget:focus .oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected .oo-ui-buttonElement-button {
+ border-color: #347bff;
+ box-shadow: inset 0 0 0 1px #347bff;
+ z-index: 2;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+ border-radius: 0;
+ margin-left: -1px;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonElement-button {
+ border-bottom-left-radius: 2px;
+ border-top-left-radius: 2px;
+ margin-left: 0;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonElement-button {
+ border-bottom-right-radius: 2px;
+ border-top-right-radius: 2px;
+}
+.oo-ui-buttonOptionWidget {
+ display: inline-block;
+ padding: 0;
+ background-color: transparent;
+}
+.oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+ position: relative;
+}
+.oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ position: static;
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected,
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+.oo-ui-buttonOptionWidget.oo-ui-optionWidget-highlighted {
+ background-color: transparent;
+}
+.oo-ui-toggleButtonWidget {
+ display: inline-block;
+ vertical-align: middle;
+ margin-right: 0.5em;
+}
+.oo-ui-toggleButtonWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-toggleSwitchWidget {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+ overflow: hidden;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ -webkit-transform: translateZ(0);
+ -moz-transform: translateZ(0);
+ -ms-transform: translateZ(0);
+ transform: translateZ(0);
+ height: 2em;
+ width: 3.5em;
+ border: 1px solid #777777;
+ border-radius: 1em;
+ background-color: #ffffff;
+ margin-right: 0.5em;
+ -webkit-transition: background-color 100ms, border-color 100ms;
+ -moz-transition: background-color 100ms, border-color 100ms;
+ transition: background-color 100ms, border-color 100ms;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled {
+ cursor: pointer;
+}
+.oo-ui-toggleSwitchWidget-grip {
+ position: absolute;
+ display: block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-toggleSwitchWidget .oo-ui-toggleSwitchWidget-glow {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ right: 0;
+ left: 0;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-glow {
+ display: none;
+}
+.oo-ui-toggleSwitchWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-toggleSwitchWidget:before {
+ content: "";
+ display: block;
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ border: 1px solid transparent;
+ border-radius: 1em;
+ z-index: 1;
+}
+.oo-ui-toggleSwitchWidget-grip {
+ top: 0.35em;
+ width: 1.2em;
+ height: 1.2em;
+ border-radius: 1.2em;
+ background-color: #555555;
+ -webkit-transition: left 100ms, margin-left 100ms;
+ -moz-transition: left 100ms, margin-left 100ms;
+ transition: left 100ms, margin-left 100ms;
+}
+.oo-ui-toggleSwitchWidget-glow {
+ display: none;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+ left: 1.9em;
+ margin-left: -2px;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
+ left: 0.4em;
+ margin-left: 0;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on {
+ background-color: #347bff;
+ border-color: #347bff;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+ background-color: #ffffff;
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover {
+ border-color: #2962cc;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover.oo-ui-toggleWidget-on {
+ background-color: #2962cc;
+ border-color: #2962cc;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus {
+ border-color: #347bff;
+ outline: 0;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus.oo-ui-toggleWidget-on {
+ border-color: #347bff;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus.oo-ui-toggleWidget-on:before {
+ border-color: #ffffff;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active:hover {
+ background-color: #347bff;
+ border-color: #347bff;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active .oo-ui-toggleSwitchWidget-grip,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active:hover .oo-ui-toggleSwitchWidget-grip {
+ background-color: #ffffff;
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+ background-color: #dddddd;
+ border-color: #dddddd;
+ outline: 0;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled .oo-ui-toggleSwitchWidget-grip {
+ background-color: #ffffff;
+}
+.oo-ui-progressBarWidget {
+ max-width: 50em;
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+ border-radius: 2px;
+ overflow: hidden;
+}
+.oo-ui-progressBarWidget-bar {
+ background-color: #dddddd;
+ height: 1em;
+ -webkit-transition: width 200ms, margin-left 200ms;
+ -moz-transition: width 200ms, margin-left 200ms;
+ transition: width 200ms, margin-left 200ms;
+}
+.oo-ui-progressBarWidget-indeterminate .oo-ui-progressBarWidget-bar {
+ -webkit-animation: oo-ui-progressBarWidget-slide 2s infinite linear;
+ -moz-animation: oo-ui-progressBarWidget-slide 2s infinite linear;
+ animation: oo-ui-progressBarWidget-slide 2s infinite linear;
+ width: 40%;
+ margin-left: -10%;
+ border-left-width: 1px;
+}
+.oo-ui-progressBarWidget.oo-ui-widget-disabled {
+ opacity: 0.6;
+}
+@-webkit-keyframes oo-ui-progressBarWidget-slide {
+ from {
+ margin-left: -40%;
+ }
+ to {
+ margin-left: 100%;
+ }
+}
+@-moz-keyframes oo-ui-progressBarWidget-slide {
+ from {
+ margin-left: -40%;
+ }
+ to {
+ margin-left: 100%;
+ }
+}
+@keyframes oo-ui-progressBarWidget-slide {
+ from {
+ margin-left: -40%;
+ }
+ to {
+ margin-left: 100%;
+ }
+}
+.oo-ui-selectFileWidget {
+ display: inline-block;
+ vertical-align: middle;
+ width: 100%;
+ max-width: 50em;
+ margin-right: 0.5em;
+}
+.oo-ui-selectFileWidget-selectButton {
+ display: table-cell;
+ vertical-align: middle;
+}
+.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
+ position: relative;
+ overflow: hidden;
+}
+.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button > [type="file"] {
+ position: absolute;
+ margin: 0;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ z-index: 1;
+ cursor: pointer;
+ padding-top: 100px;
+}
+.oo-ui-selectFileWidget-selectButton.oo-ui-widget-disabled > .oo-ui-buttonElement-button > [type="file"] {
+ display: none;
+}
+.oo-ui-selectFileWidget-info {
+ width: 100%;
+ display: table-cell;
+ vertical-align: middle;
+ position: relative;
+ overflow: hidden;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-overflow: ellipsis;
+}
+.oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-fileType {
+ float: right;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator,
+.oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon,
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton {
+ position: absolute;
+}
+.oo-ui-selectFileWidget .oo-ui-selectFileWidget-clearButton {
+ z-index: 2;
+}
+.oo-ui-selectFileWidget-dropTarget {
+ cursor: default;
+ height: 5.5em;
+ padding: 0;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel,
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
+ display: none;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail {
+ height: 5.5em;
+ width: 5.5em;
+ position: absolute;
+ background-size: cover;
+ background-position: center center;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail.oo-ui-pendingElement-pending {
+ background-size: auto;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail > .oo-ui-selectFileWidget-noThumbnail-icon {
+ opacity: 0.4;
+ background-color: #cccccc;
+ height: 5.5em;
+ width: 5.5em;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+ border: 0;
+ background: none;
+ display: block;
+ height: 100%;
+ width: auto;
+ margin-left: 5.5em;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label {
+ position: relative;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-fileName {
+ display: block;
+ padding-right: 2.375em;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-fileType {
+ display: block;
+ float: none;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton {
+ position: absolute;
+ right: 0.5em;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel {
+ display: block;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail,
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+ display: none;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
+ display: block;
+ margin: 0.7em;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget {
+ text-align: center;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+ margin: 0;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-clearButton,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-clearButton {
+ display: none;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button {
+ cursor: no-drop;
+}
+.oo-ui-selectFileWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
+ margin-left: 0.5em;
+}
+.oo-ui-selectFileWidget-info {
+ height: 2.4em;
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+ border-radius: 2px;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon {
+ left: 0;
+ top: 0;
+ height: 2.3em;
+ margin-left: 0.5em;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ display: block;
+ line-height: 2.3em;
+ margin: 0;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ left: 0;
+ right: 0;
+ padding-left: 0.5em;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-label > .oo-ui-selectFileWidget-fileType {
+ color: #888888;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator {
+ top: 0;
+ right: 0;
+ height: 2.3em;
+ margin-right: 0.775em;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton {
+ top: 0;
+ min-width: 24px;
+ width: 1.875em;
+ margin-right: 0;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-selectFileWidget-clearButton .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ height: 2.3em;
+}
+.oo-ui-selectFileWidget.oo-ui-widget-disabled .oo-ui-selectFileWidget-info {
+ background-color: #f3f3f3;
+ color: #cccccc;
+ text-shadow: 0 1px 1px #ffffff;
+ border-color: #dddddd;
+ cursor: default;
+}
+.oo-ui-selectFileWidget.oo-ui-widget-disabled .oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon,
+.oo-ui-selectFileWidget.oo-ui-widget-disabled .oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-label {
+ color: #cccccc;
+}
+.oo-ui-selectFileWidget.oo-ui-iconElement .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label {
+ left: 2.875em;
+}
+.oo-ui-selectFileWidget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label {
+ right: 2.375em;
+}
+.oo-ui-selectFileWidget .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-clearButton {
+ right: 0;
+}
+.oo-ui-selectFileWidget.oo-ui-indicatorElement .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label {
+ right: 4.4625em;
+ padding-left: 0;
+}
+.oo-ui-selectFileWidget.oo-ui-indicatorElement .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-clearButton {
+ right: 2.0875em;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label {
+ right: 0.5em;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-indicatorElement .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label,
+.oo-ui-selectFileWidget-notsupported.oo-ui-indicatorElement .oo-ui-selectFileWidget-info .oo-ui-selectFileWidget-label {
+ right: 2em;
+ padding-left: 0;
+}
+.oo-ui-selectFileWidget-supported.oo-ui-widget-enabled.oo-ui-selectFileWidget-canDrop .oo-ui-selectFileWidget-dropTarget {
+ background-color: #ebf2ff;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget {
+ border-color: #dddddd;
+ background-color: #f3f3f3;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel {
+ color: #cccccc;
+ text-shadow: 0 1px 1px #ffffff;
+}
+.oo-ui-selectFileWidget-dropTarget {
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+ margin-bottom: 0.5em;
+ vertical-align: middle;
+ overflow: hidden;
+ border-radius: 2px;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-dropTarget {
+ background-color: #eeeeee;
+ border-style: dashed;
+}
+.oo-ui-outlineOptionWidget {
+ position: relative;
+ cursor: pointer;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ font-size: 1.1em;
+ padding: 0.75em;
+}
+.oo-ui-outlineOptionWidget .oo-ui-iconElement-icon {
+ font-size: 90.90909%;
+}
+.oo-ui-outlineOptionWidget.oo-ui-indicatorElement .oo-ui-labelElement-label {
+ padding-right: 1.5em;
+}
+.oo-ui-outlineOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ opacity: 0.5;
+}
+.oo-ui-outlineOptionWidget-level-0 {
+ padding-left: 3.5em;
+}
+.oo-ui-outlineOptionWidget-level-0 .oo-ui-iconElement-icon {
+ left: 1em;
+}
+.oo-ui-outlineOptionWidget-level-1 {
+ padding-left: 5em;
+}
+.oo-ui-outlineOptionWidget-level-1 .oo-ui-iconElement-icon {
+ left: 2.5em;
+}
+.oo-ui-outlineOptionWidget-level-2 {
+ padding-left: 6.5em;
+}
+.oo-ui-outlineOptionWidget-level-2 .oo-ui-iconElement-icon {
+ left: 4em;
+}
+.oo-ui-selectWidget-depressed .oo-ui-outlineOptionWidget.oo-ui-optionWidget-selected {
+ background-color: #d0d0d0;
+ text-shadow: 0 1px 1px #ffffff;
+}
+.oo-ui-outlineOptionWidget.oo-ui-flaggedElement-important {
+ font-weight: bold;
+}
+.oo-ui-outlineOptionWidget.oo-ui-flaggedElement-empty .oo-ui-iconElement-icon {
+ opacity: 0.5;
+}
+.oo-ui-outlineOptionWidget.oo-ui-flaggedElement-empty .oo-ui-labelElement-label {
+ color: #777777;
+}
+.oo-ui-outlineControlsWidget {
+ height: 3em;
+ background-color: #ffffff;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+ float: left;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+ float: left;
+ background-position: right center;
+}
+.oo-ui-outlineControlsWidget-items {
+ float: left;
+}
+.oo-ui-outlineControlsWidget-items .oo-ui-buttonWidget {
+ float: left;
+}
+.oo-ui-outlineControlsWidget-movers {
+ float: right;
+}
+.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
+ float: right;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+ height: 2em;
+ margin: 0.5em 0.5em 0.5em 0;
+ padding: 0;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+ width: 1.5em;
+ height: 2em;
+ margin: 0.5em 0 0.5em 0.5em;
+ opacity: 0.2;
+}
+.oo-ui-tabSelectWidget {
+ text-align: left;
+ white-space: nowrap;
+ overflow: hidden;
+ background-color: #dddddd;
+}
+.oo-ui-tabOptionWidget {
+ display: inline-block;
+ vertical-align: bottom;
+ padding: 0.35em 1em;
+ margin: 0.5em 0 0 0.75em;
+ border: 1px solid transparent;
+ border-bottom: none;
+ border-top-left-radius: 2px;
+ border-top-right-radius: 2px;
+ color: #555555;
+ font-weight: bold;
+}
+.oo-ui-tabOptionWidget.oo-ui-widget-enabled:hover {
+ background-color: rgba(255, 255, 255, 0.3);
+}
+.oo-ui-tabOptionWidget.oo-ui-widget-enabled:active {
+ background-color: rgba(255, 255, 255, 0.8);
+}
+.oo-ui-tabOptionWidget.oo-ui-indicatorElement .oo-ui-labelElement-label {
+ padding-right: 1.5em;
+}
+.oo-ui-tabOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ opacity: 0.5;
+}
+.oo-ui-selectWidget-pressed .oo-ui-tabOptionWidget.oo-ui-optionWidget-selected,
+.oo-ui-selectWidget-depressed .oo-ui-tabOptionWidget.oo-ui-optionWidget-selected,
+.oo-ui-tabOptionWidget.oo-ui-optionWidget-selected:hover {
+ background-color: #ffffff;
+ color: #333333;
+}
+.oo-ui-capsuleMultiSelectWidget {
+ display: inline-block;
+ position: relative;
+ width: 100%;
+ max-width: 50em;
+}
+.oo-ui-capsuleMultiSelectWidget-handle {
+ width: 100%;
+ display: block;
+ position: relative;
+}
+.oo-ui-capsuleMultiSelectWidget-content {
+ position: relative;
+}
+.oo-ui-capsuleMultiSelectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiSelectWidget-content > input {
+ display: none;
+}
+.oo-ui-capsuleMultiSelectWidget-group {
+ display: inline;
+}
+.oo-ui-capsuleMultiSelectWidget > .oo-ui-menuSelectWidget {
+ z-index: 1;
+ width: 100%;
+}
+.oo-ui-capsuleMultiSelectWidget-handle {
+ background-color: #ffffff;
+ cursor: text;
+ min-height: 2.4em;
+ margin-right: 0.5em;
+ padding: 0.15em 0.25em;
+ border: 1px solid #cccccc;
+ border-radius: 2px;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-capsuleMultiSelectWidget-handle:last-child {
+ margin-right: 0;
+}
+.oo-ui-capsuleMultiSelectWidget-handle > .oo-ui-indicatorElement-indicator,
+.oo-ui-capsuleMultiSelectWidget-handle > .oo-ui-iconElement-icon {
+ position: absolute;
+}
+.oo-ui-capsuleMultiSelectWidget-handle > .oo-ui-capsuleMultiSelectWidget-content > input {
+ border: 0;
+ line-height: 1.675em;
+ margin: 0 0 0 0.2em;
+ padding: 0;
+ font-size: inherit;
+ font-family: inherit;
+ background-color: transparent;
+ color: #000000;
+ vertical-align: middle;
+}
+.oo-ui-capsuleMultiSelectWidget-handle > .oo-ui-capsuleMultiSelectWidget-content > input:focus {
+ outline: 0;
+}
+.oo-ui-capsuleMultiSelectWidget.oo-ui-indicatorElement .oo-ui-capsuleMultiSelectWidget-handle {
+ padding-right: 2.4875em;
+}
+.oo-ui-capsuleMultiSelectWidget.oo-ui-indicatorElement .oo-ui-capsuleMultiSelectWidget-handle > .oo-ui-indicatorElement-indicator {
+ right: 0;
+ top: 0;
+ margin: 0.775em;
+}
+.oo-ui-capsuleMultiSelectWidget.oo-ui-iconElement .oo-ui-capsuleMultiSelectWidget-handle {
+ padding-left: 2.475em;
+}
+.oo-ui-capsuleMultiSelectWidget.oo-ui-iconElement .oo-ui-capsuleMultiSelectWidget-handle > .oo-ui-iconElement-icon {
+ left: 0;
+ top: 0;
+ margin: 0.3em;
+}
+.oo-ui-capsuleMultiSelectWidget:hover .oo-ui-capsuleMultiSelectWidget-handle {
+ border-color: #aaaaaa;
+}
+.oo-ui-capsuleMultiSelectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiSelectWidget-handle {
+ color: #cccccc;
+ text-shadow: 0 1px 1px #ffffff;
+ border-color: #dddddd;
+ background-color: #f3f3f3;
+ cursor: default;
+}
+.oo-ui-capsuleMultiSelectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiSelectWidget-handle > .oo-ui-iconElement-icon,
+.oo-ui-capsuleMultiSelectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiSelectWidget-handle > .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+}
+.oo-ui-capsuleItemWidget {
+ position: relative;
+ display: inline-block;
+ cursor: default;
+ white-space: nowrap;
+ width: auto;
+ max-width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ vertical-align: middle;
+ height: 1.7em;
+ line-height: 1.7em;
+ background-color: #eeeeee;
+ color: #555555;
+ margin: 0.1em;
+ border: 1px solid #cccccc;
+ border-radius: 2px;
+ padding: 0 0.4em;
+}
+.oo-ui-capsuleItemWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: inline-block;
+ text-overflow: ellipsis;
+ overflow: hidden;
+}
+.oo-ui-capsuleItemWidget:focus {
+ outline: 0;
+ border-color: #347bff;
+ box-shadow: inset 0 0 0 1px #347bff;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-disabled {
+ background-color: #f3f3f3;
+ color: #cccccc;
+ border-color: #dddddd;
+ text-shadow: 0 1px 1px #ffffff;
+}
+.oo-ui-capsuleItemWidget > .oo-ui-buttonElement {
+ display: none;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled {
+ padding-right: 1.5375em;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled > .oo-ui-buttonElement {
+ display: block;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button {
+ display: block;
+ width: 1.5375em;
+ height: 100%;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button .oo-ui-indicator-clear {
+ position: absolute;
+ top: 0;
+ right: 0.3em;
+ bottom: 0;
+ height: auto;
+}
+.oo-ui-searchWidget-query {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+ width: 100%;
+}
+.oo-ui-searchWidget-results {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.oo-ui-searchWidget-query {
+ height: 4em;
+ padding: 0 1em;
+ border-bottom: 1px solid #cccccc;
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+ margin: 0.75em 0;
+}
+.oo-ui-searchWidget-results {
+ top: 4em;
+ padding: 1em;
+ line-height: 0;
+}
+.oo-ui-numberInputWidget {
+ display: inline-block;
+ position: relative;
+ max-width: 50em;
+}
+.oo-ui-numberInputWidget-field {
+ display: table;
+ table-layout: fixed;
+ width: 100%;
+}
+.oo-ui-numberInputWidget-field > .oo-ui-buttonWidget,
+.oo-ui-numberInputWidget-field > .oo-ui-textInputWidget {
+ display: table-cell;
+ vertical-align: middle;
+}
+.oo-ui-numberInputWidget-field > .oo-ui-textInputWidget {
+ width: 100%;
+}
+.oo-ui-numberInputWidget-field > .oo-ui-textInputWidget [type="number"]::-webkit-outer-spin-button,
+.oo-ui-numberInputWidget-field > .oo-ui-textInputWidget [type="number"]::-webkit-inner-spin-button {
+ -webkit-appearance: none;
+ margin: 0;
+}
+.oo-ui-numberInputWidget-field > .oo-ui-textInputWidget [type="number"] {
+ -moz-appearance: textfield;
+}
+.oo-ui-numberInputWidget-field > .oo-ui-buttonWidget {
+ white-space: nowrap;
+}
+.oo-ui-numberInputWidget-field > .oo-ui-buttonWidget > .oo-ui-buttonElement-button {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-numberInputWidget-field > .oo-ui-buttonWidget {
+ width: 2.5em;
+}
+.oo-ui-numberInputWidget-minusButton.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ border-right-width: 0;
+}
+.oo-ui-numberInputWidget-plusButton.oo-ui-buttonElement-framed.oo-ui-widget-enabled > .oo-ui-buttonElement-button {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ border-left-width: 0;
+}
+.oo-ui-numberInputWidget-buttoned .oo-ui-textInputWidget input {
+ border-radius: 0;
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-wikimediaui.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-wikimediaui.css
new file mode 100644
index 00000000..19b1aeed
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets-wikimediaui.css
@@ -0,0 +1,1324 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:24:03Z
+ */
+/**
+ * WikimediaUI Base v0.9.2
+ * Wikimedia Foundation user interface base variables
+ */
+/* Colors */
+/* Positioning */
+/* Box Model properties */
+/* Max Widths */
+/* Typography incl. print properties */
+/* Other Properties */
+/* Animation & Transition */
+.oo-ui-draggableElement-handle:not( .oo-ui-draggableElement-undraggable ).oo-ui-widget {
+ cursor: move;
+ cursor: url(images/grab.cur );
+ cursor: -webkit-grab;
+ cursor: -moz-grab;
+ cursor: grab;
+}
+.oo-ui-draggableElement-handle:not( .oo-ui-draggableElement-undraggable ):active {
+ cursor: url(images/grabbing.cur );
+ cursor: -webkit-grabbing;
+ cursor: -moz-grabbing;
+ cursor: grabbing;
+}
+.oo-ui-draggableElement-handle.oo-ui-widget-disabled,
+.oo-ui-widget-disabled .oo-ui-draggableElement-handle {
+ cursor: default;
+}
+.oo-ui-draggableElement-placeholder {
+ opacity: 0.2;
+}
+.oo-ui-draggableGroupElement-horizontal .oo-ui-draggableElement {
+ display: inline-block;
+}
+.oo-ui-bookletLayout-stackLayout.oo-ui-stackLayout-continuous > .oo-ui-panelLayout-scrollable {
+ overflow: hidden;
+}
+.oo-ui-bookletLayout-stackLayout > .oo-ui-panelLayout {
+ width: 100%;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-bookletLayout-outlinePanel-editable > .oo-ui-outlineSelectWidget {
+ height: auto;
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 2.5em;
+ overflow: auto;
+}
+.oo-ui-bookletLayout-outlinePanel > .oo-ui-outlineControlsWidget {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ height: 2.5em;
+}
+.oo-ui-bookletLayout-stackLayout > .oo-ui-panelLayout {
+ padding: 1.5em;
+}
+.oo-ui-bookletLayout-outlinePanel {
+ border-right: 1px solid #ddd;
+}
+.oo-ui-bookletLayout-outlinePanel > .oo-ui-outlineControlsWidget {
+ border-top: 1px solid #c8ccd1;
+}
+.oo-ui-indexLayout > .oo-ui-menuLayout-menu {
+ height: 3em;
+}
+.oo-ui-indexLayout > .oo-ui-menuLayout-content {
+ top: 3em;
+}
+.oo-ui-indexLayout-stackLayout > .oo-ui-panelLayout {
+ padding: 1.5em;
+}
+.oo-ui-indexLayout > .oo-ui-menuLayout-menu {
+ height: 2.75em;
+}
+.oo-ui-indexLayout > .oo-ui-menuLayout-content {
+ top: 2.75em;
+}
+.oo-ui-menuLayout {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-menuLayout-menu,
+.oo-ui-menuLayout-content {
+ position: absolute;
+ -webkit-transition: all 200ms ease;
+ -moz-transition: all 200ms ease;
+ transition: all 200ms ease;
+}
+.oo-ui-menuLayout-menu {
+ height: 18em;
+ width: 18em;
+}
+.oo-ui-menuLayout-content {
+ top: 18em;
+ left: 18em;
+ right: 18em;
+ bottom: 18em;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu > .oo-ui-menuLayout-menu {
+ width: 0 !important;
+ height: 0 !important;
+ overflow: hidden;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-hideMenu > .oo-ui-menuLayout-content {
+ top: 0 !important;
+ left: 0 !important;
+ right: 0 !important;
+ bottom: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top > .oo-ui-menuLayout-menu {
+ width: auto !important;
+ left: 0;
+ top: 0;
+ right: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-top > .oo-ui-menuLayout-content {
+ right: 0 !important;
+ bottom: 0 !important;
+ left: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after > .oo-ui-menuLayout-menu {
+ height: auto !important;
+ top: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-after > .oo-ui-menuLayout-content {
+ bottom: 0 !important;
+ left: 0 !important;
+ top: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom > .oo-ui-menuLayout-menu {
+ width: auto !important;
+ right: 0;
+ bottom: 0;
+ left: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-bottom > .oo-ui-menuLayout-content {
+ left: 0 !important;
+ top: 0 !important;
+ right: 0 !important;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before > .oo-ui-menuLayout-menu {
+ height: auto !important;
+ bottom: 0;
+ left: 0;
+ top: 0;
+}
+.oo-ui-menuLayout.oo-ui-menuLayout-showMenu.oo-ui-menuLayout-before > .oo-ui-menuLayout-content {
+ top: 0 !important;
+ right: 0 !important;
+ bottom: 0 !important;
+}
+.oo-ui-stackLayout-continuous > .oo-ui-panelLayout {
+ display: block;
+ position: relative;
+}
+.oo-ui-buttonSelectWidget {
+ display: inline-block;
+ white-space: nowrap;
+ border-radius: 2px;
+ margin-right: 0.5em;
+ z-index: 0;
+ position: relative;
+}
+.oo-ui-buttonSelectWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-buttonSelectWidget:focus {
+ outline: 0;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget .oo-ui-buttonElement-button {
+ margin-left: -1px;
+ border-radius: 0;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:first-child .oo-ui-buttonElement-button {
+ margin-left: 0;
+ border-bottom-left-radius: 2px;
+ border-top-left-radius: 2px;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget:last-child .oo-ui-buttonElement-button {
+ border-bottom-right-radius: 2px;
+ border-top-right-radius: 2px;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ position: absolute;
+}
+.oo-ui-buttonSelectWidget .oo-ui-buttonOptionWidget.oo-ui-widget-disabled + .oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ border-left-color: #fff;
+}
+.oo-ui-buttonSelectWidget.oo-ui-widget-enabled:focus .oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected .oo-ui-buttonElement-button {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c, inset 0 0 0 2px #fff;
+}
+.oo-ui-buttonSelectWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:hover,
+.oo-ui-buttonSelectWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-enabled > .oo-ui-buttonElement-button:active {
+ z-index: 1;
+}
+.oo-ui-buttonSelectWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-buttonElement-active > .oo-ui-buttonElement-button {
+ z-index: 3;
+}
+.oo-ui-buttonSelectWidget.oo-ui-widget-enabled .oo-ui-buttonElement.oo-ui-widget-disabled > .oo-ui-buttonElement-button {
+ z-index: -1;
+}
+.oo-ui-buttonOptionWidget {
+ display: inline-block;
+}
+.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active .oo-ui-buttonElement-button {
+ cursor: default;
+}
+.oo-ui-buttonOptionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-buttonOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ position: static;
+ display: inline-block;
+ vertical-align: middle;
+}
+.oo-ui-toggleButtonWidget {
+ margin-right: 0.5em;
+}
+.oo-ui-toggleButtonWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-toggleSwitchWidget {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+ overflow: hidden;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ -webkit-transform: translateZ(0);
+ transform: translateZ(0);
+ background-color: #f8f9fa;
+ width: 3.5em;
+ min-height: 26px;
+ height: 2em;
+ border: 1px solid #72777d;
+ border-radius: 1em;
+ margin-right: 0.5em;
+ -webkit-transition: background-color 250ms, border-color 250ms;
+ -moz-transition: background-color 250ms, border-color 250ms;
+ transition: background-color 250ms, border-color 250ms;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled {
+ cursor: pointer;
+}
+.oo-ui-toggleSwitchWidget-grip {
+ position: absolute;
+ display: block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-toggleSwitchWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-toggleSwitchWidget:before {
+ content: '';
+ display: block;
+ position: absolute;
+ top: 1px;
+ left: 1px;
+ bottom: 1px;
+ right: 1px;
+ border: 1px solid transparent;
+ border-radius: 1em;
+ z-index: 1;
+ -webkit-transition: border-color 250ms;
+ -moz-transition: border-color 250ms;
+ transition: border-color 250ms;
+}
+.oo-ui-toggleSwitchWidget-grip {
+ top: 0.3125em;
+ min-width: 16px;
+ width: 1.25em;
+ min-height: 16px;
+ height: 1.25em;
+ border-radius: 1.25em;
+ -webkit-transition: background-color 250ms, left 100ms, margin-left 100ms;
+ -moz-transition: background-color 250ms, left 100ms, margin-left 100ms;
+ transition: background-color 250ms, left 100ms, margin-left 100ms;
+}
+.oo-ui-toggleSwitchWidget-glow {
+ display: none;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
+ left: 0.4em;
+ margin-left: 0;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+ left: 1.9em;
+ margin-left: -2px;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled .oo-ui-toggleSwitchWidget-grip {
+ background-color: #f8f9fa;
+ border: 1px solid #72777d;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover {
+ background-color: #fff;
+ border-color: #447ff5;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:hover .oo-ui-toggleSwitchWidget-grip {
+ background-color: #fff;
+ border-color: #447ff5;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active:hover,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active:focus {
+ background-color: #2a4b8d;
+ border-color: #2a4b8d;
+ box-shadow: inset 0 0 0 1px #2a4b8d;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active .oo-ui-toggleSwitchWidget-grip,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active:hover .oo-ui-toggleSwitchWidget-grip,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:active:focus .oo-ui-toggleSwitchWidget-grip {
+ background-color: #fff;
+ border-color: #fff;
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c;
+ outline: 0;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled:focus .oo-ui-toggleSwitchWidget-grip {
+ border-color: #36c;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on {
+ background-color: #36c;
+ border-color: #36c;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+ background-color: #fff;
+ border-color: #fff;
+ box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.1);
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on:hover {
+ background-color: #447ff5;
+ border-color: #447ff5;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on:active,
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on:active:hover {
+ background-color: #2a4b8d;
+ border-color: #2a4b8d;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on:focus {
+ border-color: #36c;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-enabled.oo-ui-toggleWidget-on:focus:before {
+ border-color: #fff;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled {
+ background-color: #c8ccd1;
+ border-color: #c8ccd1;
+ outline: 0;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled.oo-ui-toggleWidget-off .oo-ui-toggleSwitchWidget-grip {
+ border: 1px solid #fff;
+ box-shadow: inset 0 0 0 1px #fff;
+}
+.oo-ui-toggleSwitchWidget.oo-ui-widget-disabled.oo-ui-toggleWidget-on .oo-ui-toggleSwitchWidget-grip {
+ background-color: #fff;
+}
+.oo-ui-selectFileWidget {
+ display: inline-block;
+ vertical-align: middle;
+ width: 100%;
+ max-width: 50em;
+ margin-right: 0.5em;
+}
+.oo-ui-selectFileWidget-selectButton {
+ display: table-cell;
+}
+.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
+ position: relative;
+ overflow: hidden;
+}
+.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button > [type='file'] {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ width: 100%;
+ height: 100%;
+ opacity: 0;
+ z-index: 1;
+ cursor: pointer;
+ padding-top: 100px;
+}
+.oo-ui-selectFileWidget-selectButton.oo-ui-widget-disabled > .oo-ui-buttonElement-button > [type='file'] {
+ display: none;
+}
+.oo-ui-selectFileWidget-info {
+ width: 100%;
+ display: table-cell;
+ vertical-align: middle;
+ position: relative;
+ overflow: hidden;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator,
+.oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon {
+ position: absolute;
+ top: 0;
+ height: 100%;
+}
+.oo-ui-widget-disabled .oo-ui-selectFileWidget-info {
+ cursor: default;
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-selectFileWidget-label {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ text-overflow: ellipsis;
+}
+.oo-ui-selectFileWidget-clearButton {
+ position: absolute;
+ z-index: 2;
+}
+.oo-ui-selectFileWidget-dropTarget {
+ position: relative;
+ cursor: default;
+ height: 8.815em;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-dropLabel,
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton,
+.oo-ui-selectFileWidget-dropTarget .oo-ui-iconElement-icon {
+ display: none;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail {
+ width: 7.815em;
+ position: absolute;
+ top: 0.5em;
+ bottom: 0.5em;
+ left: 0.5em;
+ background-position: center center;
+ background-repeat: no-repeat;
+ background-size: contain;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail.oo-ui-pendingElement-pending {
+ background-repeat: repeat;
+ background-size: auto;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail > .oo-ui-selectFileWidget-noThumbnail-icon {
+ opacity: 0.4;
+ height: 7.815em;
+ width: 7.815em;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+ display: block;
+ height: 100%;
+ width: auto;
+ margin-left: 8.815em;
+ border: 0;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-label {
+ display: block;
+ position: relative;
+ top: inherit;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-fileName {
+ display: block;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-thumbnail,
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+ display: none;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton {
+ display: block;
+ margin: 2.2em 1em 1em;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
+ text-align: center;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-info {
+ margin: 0;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-clearButton,
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-clearButton {
+ display: none;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-enabled .oo-ui-selectFileWidget-label {
+ cursor: default;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-enabled .oo-ui-selectFileWidget-dropLabel {
+ display: block;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button,
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget .oo-ui-buttonElement-button {
+ cursor: no-drop;
+}
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
+ height: auto;
+}
+.oo-ui-selectFileWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
+ border-radius: 0 2px 2px 0;
+}
+.oo-ui-selectFileWidget-info {
+ background-color: #fff;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px 0 0 2px;
+ border-right-width: 0;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon {
+ top: -1px;
+ left: 0.46875em;
+ min-height: 2.5em;
+ margin-left: -1px;
+}
+.oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator {
+ top: -1px;
+ right: 0.9375em;
+ min-height: 2.5em;
+}
+.oo-ui-selectFileWidget-label {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ display: block;
+ right: 2.375em;
+ padding-top: 0.625em;
+ padding-left: 0.625em;
+ padding-bottom: 0.546875em;
+ line-height: 1.172em;
+ white-space: nowrap;
+}
+.oo-ui-selectFileWidget-fileName {
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.oo-ui-selectFileWidget-clearButton {
+ top: -1px;
+ right: 0.46875em;
+ min-width: 24px;
+ width: 1.875em;
+ margin-right: 0;
+}
+.oo-ui-selectFileWidget-clearButton .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ height: 2.5em;
+}
+.oo-ui-selectFileWidget-empty .oo-ui-selectFileWidget-label {
+ color: #72777d;
+}
+.oo-ui-selectFileWidget.oo-ui-iconElement .oo-ui-selectFileWidget-label {
+ left: 2.5em;
+}
+.oo-ui-selectFileWidget.oo-ui-indicatorElement .oo-ui-selectFileWidget-label {
+ right: 3.75em;
+ padding-left: 0;
+}
+.oo-ui-selectFileWidget.oo-ui-indicatorElement .oo-ui-selectFileWidget-clearButton {
+ right: 2.0875em;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-indicatorElement .oo-ui-selectFileWidget-label,
+.oo-ui-selectFileWidget-notsupported.oo-ui-indicatorElement .oo-ui-selectFileWidget-label {
+ right: 2em;
+}
+.oo-ui-selectFileWidget-dropTarget {
+ background-color: #fff;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ vertical-align: middle;
+ overflow: hidden;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-selectButton > .oo-ui-buttonElement-button {
+ border-radius: 2px;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-label {
+ line-height: 1.4;
+ overflow: inherit;
+ white-space: normal;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-fileName {
+ padding-right: 2.5em;
+}
+.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-clearButton {
+ top: 0;
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-enabled.oo-ui-selectFileWidget-dropTarget {
+ background-color: #fff;
+ border-style: dashed;
+ -webkit-transition: background-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+ -moz-transition: background-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+ transition: background-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+}
+.oo-ui-selectFileWidget-empty.oo-ui-widget-enabled.oo-ui-selectFileWidget-dropTarget:hover {
+ border-color: #72777d;
+}
+.oo-ui-selectFileWidget-supported.oo-ui-widget-enabled.oo-ui-selectFileWidget-canDrop.oo-ui-selectFileWidget-dropTarget {
+ background-color: #eaf3ff;
+ color: #36c;
+}
+.oo-ui-selectFileWidget.oo-ui-widget-disabled .oo-ui-selectFileWidget-info,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-info {
+ background-color: #eaecf0;
+ color: #72777d;
+ border-color: #c8ccd1;
+ text-shadow: 0 1px 1px #fff;
+}
+.oo-ui-selectFileWidget.oo-ui-widget-disabled .oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-info > .oo-ui-iconElement-icon {
+ opacity: 0.51;
+}
+.oo-ui-selectFileWidget.oo-ui-widget-disabled .oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled .oo-ui-selectFileWidget-info > .oo-ui-indicatorElement-indicator {
+ opacity: 0.15;
+}
+.oo-ui-selectFileWidget.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget,
+.oo-ui-selectFileWidget-empty.oo-ui-widget-disabled.oo-ui-selectFileWidget-dropTarget {
+ background-color: #eaecf0;
+ border-color: #c8ccd1;
+}
+.oo-ui-selectFileWidget-notsupported .oo-ui-selectFileWidget-info {
+ background-color: #eaecf0;
+ color: #222;
+ border-color: #c8ccd1;
+}
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget {
+ background-color: #eaecf0;
+ border-color: #c8ccd1;
+}
+.oo-ui-selectFileWidget-notsupported.oo-ui-selectFileWidget-dropTarget .oo-ui-selectFileWidget-label {
+ padding: 1em 0.9375em;
+}
+.oo-ui-widget-disabled .oo-ui-selectFileWidget-dropLabel {
+ display: none;
+}
+.oo-ui-outlineSelectWidget {
+ height: 100%;
+}
+.oo-ui-outlineSelectWidget:focus {
+ box-shadow: inset 0 0 0 2px #36c;
+}
+.oo-ui-outlineOptionWidget {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+ padding: 1.0546875em 0.9375em 0.9375em;
+ -webkit-transition: background-color 100ms, color 100ms;
+ -moz-transition: background-color 100ms, color 100ms;
+ transition: background-color 100ms, color 100ms;
+}
+.oo-ui-outlineOptionWidget.oo-ui-optionWidget-highlighted {
+ background-color: #eaecf0;
+ color: #000;
+}
+.oo-ui-outlineOptionWidget.oo-ui-optionWidget-selected {
+ background-color: #eaf3ff;
+ color: #36c;
+}
+.oo-ui-outlineOptionWidget.oo-ui-optionWidget-pressed {
+ background-color: rgba(41, 98, 204, 0.1);
+ color: #36c;
+}
+.oo-ui-outlineOptionWidget.oo-ui-indicatorElement .oo-ui-labelElement-label {
+ padding-right: 1.5em;
+}
+.oo-ui-outlineOptionWidget.oo-ui-indicatorElement .oo-ui-indicatorElement-indicator {
+ opacity: 0.5;
+}
+.oo-ui-outlineOptionWidget .oo-ui-labelElement-label {
+ font-size: 1.1em;
+}
+.oo-ui-outlineOptionWidget-level-1 {
+ padding-left: 2.571em;
+}
+.oo-ui-outlineOptionWidget-level-1.oo-ui-iconElement {
+ padding-left: 4.429em;
+}
+.oo-ui-outlineOptionWidget-level-1.oo-ui-iconElement .oo-ui-iconElement-icon {
+ left: 2.571em;
+}
+.oo-ui-outlineOptionWidget-level-2 {
+ padding-left: 5.142em;
+}
+.oo-ui-outlineOptionWidget-level-2.oo-ui-iconElement {
+ padding-left: 6.857em;
+}
+.oo-ui-outlineOptionWidget-level-2.oo-ui-iconElement .oo-ui-iconElement-icon {
+ left: 4.429em;
+}
+.oo-ui-outlineControlsWidget {
+ overflow: hidden;
+ background-color: #fff;
+}
+.oo-ui-outlineControlsWidget-items,
+.oo-ui-outlineControlsWidget-movers {
+ float: left;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+ float: left;
+ background-position: right center;
+}
+.oo-ui-outlineControlsWidget-items {
+ float: left;
+}
+.oo-ui-outlineControlsWidget-items .oo-ui-buttonWidget {
+ float: left;
+}
+.oo-ui-outlineControlsWidget-movers {
+ float: right;
+}
+.oo-ui-outlineControlsWidget-movers .oo-ui-buttonWidget {
+ float: right;
+}
+.oo-ui-outlineControlsWidget-items > .oo-ui-buttonWidget,
+.oo-ui-outlineControlsWidget-movers > .oo-ui-buttonWidget {
+ height: 2.5em;
+ width: 2.5em;
+ margin: 0 !important;
+ /* stylelint-disable-line declaration-no-important */
+}
+.oo-ui-outlineControlsWidget > .oo-ui-iconElement-icon {
+ height: 2.5em;
+ opacity: 0.2;
+}
+.oo-ui-tabSelectWidget {
+ text-align: left;
+ white-space: nowrap;
+ overflow: hidden;
+ background-color: #eaecf0;
+}
+.oo-ui-tabOptionWidget {
+ display: inline-block;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ vertical-align: bottom;
+ color: #222;
+ margin: 0.46875em 0 0 0.46875em;
+ border-color: transparent;
+ border-style: solid;
+ border-width: 1px 1px 0 1px;
+ border-top-left-radius: 2px;
+ border-top-right-radius: 2px;
+ padding: 0.625em 1.015625em 0.546875em;
+ font-weight: bold;
+ line-height: 1;
+ -webkit-transition: background-color 100ms, color 100ms;
+ -moz-transition: background-color 100ms, color 100ms;
+ transition: background-color 100ms, color 100ms;
+}
+.oo-ui-tabOptionWidget.oo-ui-optionWidget-selected {
+ background-color: #fff;
+ color: #000;
+}
+.oo-ui-tabOptionWidget .oo-ui-labelElement-label {
+ line-height: 1.172em;
+}
+.oo-ui-tabOptionWidget.oo-ui-widget-enabled:hover {
+ background-color: rgba(255, 255, 255, 0.3);
+}
+.oo-ui-tabOptionWidget.oo-ui-widget-enabled:active {
+ background-color: rgba(255, 255, 255, 0.8);
+}
+.oo-ui-tabOptionWidget.oo-ui-widget-enabled.oo-ui-optionWidget-selected:hover {
+ background-color: #fff;
+}
+.oo-ui-tagMultiselectWidget {
+ display: inline-block;
+ position: relative;
+ width: 100%;
+ max-width: 50em;
+}
+.oo-ui-tagMultiselectWidget-handle {
+ width: 100%;
+ display: block;
+ position: relative;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-iconElement-icon,
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ position: absolute;
+ top: 0;
+ height: 100%;
+}
+.oo-ui-tagMultiselectWidget-content {
+ position: relative;
+}
+.oo-ui-tagMultiselectWidget-group {
+ display: inline;
+}
+.oo-ui-tagMultiselectWidget-outlined {
+ width: 100%;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-enabled.oo-ui-tagMultiselectWidget-inlined .oo-ui-tagMultiselectWidget-handle {
+ cursor: text;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-disabled .oo-ui-tagMultiselectWidget-content > input {
+ display: none;
+}
+.oo-ui-tagMultiselectWidget-focusTrap {
+ display: inline-block;
+ height: 1px;
+ width: 1px;
+}
+.oo-ui-tagMultiselectWidget-focusTrap:focus {
+ outline: 0;
+}
+.oo-ui-tagMultiselectWidget-handle {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ min-height: 2.5em;
+ margin-right: 0.5em;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ padding: 0 0.625em 0.3125em;
+ line-height: 1;
+}
+.oo-ui-tagMultiselectWidget-handle:last-child {
+ margin-right: 0;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input {
+ background-color: transparent;
+ color: #000;
+ margin: 0.46875em 0 0 0.390625em;
+ border: 0;
+ padding: 0;
+ font-family: inherit;
+ font-size: inherit;
+ line-height: 1.563em;
+ vertical-align: middle;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input::-webkit-input-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input:-ms-input-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input::-moz-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input:-moz-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input::placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content > input:focus {
+ outline: 0;
+}
+.oo-ui-tagMultiselectWidget-handle > .oo-ui-tagMultiselectWidget-content .oo-ui-tagMultiselectWidget-group:empty + input {
+ margin-left: 0;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-iconElement .oo-ui-tagMultiselectWidget-handle {
+ padding-left: 2.475em;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-iconElement .oo-ui-tagMultiselectWidget-handle > .oo-ui-iconElement-icon {
+ left: 0;
+ margin: 0 0.3em;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-indicatorElement .oo-ui-tagMultiselectWidget-handle {
+ padding-right: 2.4875em;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-indicatorElement .oo-ui-tagMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ right: 0;
+ margin: 0 0.775em;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-enabled .oo-ui-tagMultiselectWidget-handle {
+ background-color: #fff;
+ -webkit-transition: border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), box-shadow 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+ -moz-transition: border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), box-shadow 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+ transition: border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), box-shadow 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-enabled.oo-ui-tagMultiselectWidget-inlined:hover .oo-ui-tagMultiselectWidget-handle {
+ border-color: #72777d;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-enabled.oo-ui-tagMultiselectWidget-inlined.oo-ui-tagMultiselectWidget-focus .oo-ui-tagMultiselectWidget-handle {
+ border-color: #36c;
+ outline: 0;
+ box-shadow: inset 0 0 0 1px #36c;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-enabled.oo-ui-tagMultiselectWidget-outlined .oo-ui-tagMultiselectWidget-handle {
+ background-color: #f8f9fa;
+ border-bottom: 0;
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-enabled.oo-ui-tagMultiselectWidget-outlined .oo-ui-tagItemWidget.oo-ui-widget-enabled {
+ background-color: #fff;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-enabled.oo-ui-tagMultiselectWidget-outlined .oo-ui-inputWidget-input {
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-disabled .oo-ui-tagMultiselectWidget-handle {
+ color: #72777d;
+ text-shadow: 0 1px 1px #fff;
+ border-color: #c8ccd1;
+ background-color: #eaecf0;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-disabled .oo-ui-tagMultiselectWidget-handle > .oo-ui-iconElement-icon {
+ opacity: 0.51;
+}
+.oo-ui-tagMultiselectWidget.oo-ui-widget-disabled .oo-ui-tagMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ opacity: 0.15;
+}
+.oo-ui-tagItemWidget {
+ position: relative;
+ display: inline-block;
+ cursor: default;
+ white-space: nowrap;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: auto;
+ max-width: 100%;
+ height: 1.71875em;
+ margin: 0.3125em 0.3125em 0 0;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ padding: 0 0.3125em;
+ line-height: 1.71875em;
+ vertical-align: middle;
+}
+.oo-ui-tagItemWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: inline-block;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ cursor: text;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-enabled {
+ background-color: #f8f9fa;
+ color: #222;
+ padding-right: 1.640625em;
+ -webkit-transition: background-color 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+ -moz-transition: background-color 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+ transition: background-color 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-enabled:hover {
+ background-color: #fff;
+ color: #444;
+ border-color: #a2a9b1;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-enabled:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c;
+ outline: 0;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid {
+ border-color: #d33;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid:hover {
+ border-color: #d33;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-invalid:focus {
+ border-color: #d33;
+ box-shadow: inset 0 0 0 1px #d33;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-enabled > .oo-ui-buttonElement {
+ display: block;
+ position: absolute;
+ top: 0;
+ right: 0;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button {
+ min-width: 0;
+ min-height: 0;
+ border: 0;
+ padding-top: 1.5625em;
+ padding-left: 1.5625em;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button .oo-ui-icon-close {
+ left: 0;
+ min-width: 20px;
+ min-height: 20px;
+ width: 1.5625em;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button .oo-ui-labelElement-label,
+.oo-ui-tagItemWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button .oo-ui-indicatorElement-indicator {
+ display: none;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-disabled {
+ background-color: #eaecf0;
+ color: #72777d;
+ border-color: #c8ccd1;
+ text-shadow: 0 1px 1px #fff;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-disabled:focus {
+ outline: 0;
+}
+.oo-ui-tagItemWidget.oo-ui-widget-disabled > .oo-ui-buttonElement {
+ display: none;
+}
+.oo-ui-capsuleMultiselectWidget {
+ display: inline-block;
+ position: relative;
+ width: 100%;
+ max-width: 50em;
+}
+.oo-ui-capsuleMultiselectWidget-handle {
+ width: 100%;
+ display: block;
+ position: relative;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-iconElement-icon,
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ position: absolute;
+ top: 0;
+ height: 100%;
+}
+.oo-ui-capsuleMultiselectWidget-content {
+ position: relative;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiselectWidget-content > input {
+ display: none;
+}
+.oo-ui-capsuleMultiselectWidget-group {
+ display: inline;
+}
+.oo-ui-capsuleMultiselectWidget-popup > .oo-ui-popupWidget-popup > .oo-ui-popupWidget-body > * {
+ display: block;
+}
+.oo-ui-capsuleMultiselectWidget-focusTrap {
+ display: inline-block;
+ height: 1px;
+ width: 1px;
+}
+.oo-ui-capsuleMultiselectWidget-focusTrap:focus {
+ outline: 0;
+}
+.oo-ui-capsuleMultiselectWidget-handle {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ min-height: 2.5em;
+ margin-right: 0.5em;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ padding: 0 0.625em 0.3125em;
+ line-height: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle:last-child {
+ margin-right: 0;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input {
+ background-color: transparent;
+ color: #000;
+ border: 0;
+ margin: 0.46875em 0 0 0.390625em;
+ padding: 0;
+ font-family: inherit;
+ font-size: inherit;
+ line-height: 1.563em;
+ vertical-align: middle;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input::-webkit-input-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input:-ms-input-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input::-moz-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input:-moz-placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input::placeholder {
+ color: #72777d;
+ opacity: 1;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content > input:focus {
+ outline: 0;
+}
+.oo-ui-capsuleMultiselectWidget-handle > .oo-ui-capsuleMultiselectWidget-content .oo-ui-capsuleMultiselectWidget-group:empty + input {
+ margin-left: 0;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-iconElement .oo-ui-capsuleMultiselectWidget-handle {
+ padding-left: 2.5em;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-iconElement .oo-ui-capsuleMultiselectWidget-handle > .oo-ui-iconElement-icon {
+ left: 0.46875em;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-indicatorElement .oo-ui-capsuleMultiselectWidget-handle {
+ padding-right: 2.8125em;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-indicatorElement .oo-ui-capsuleMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ right: 0.9375em;
+}
+.oo-ui-capsuleMultiselectWidget-popup {
+ margin-top: -1px;
+}
+.oo-ui-capsuleMultiselectWidget-popup > .oo-ui-popupWidget-popup {
+ border: 0;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-enabled .oo-ui-capsuleMultiselectWidget-handle {
+ background-color: #fff;
+ cursor: text;
+ -webkit-transition: border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), box-shadow 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+ -moz-transition: border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), box-shadow 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+ transition: border-color 200ms cubic-bezier(0.4, 0.55, 0.55, 1), box-shadow 200ms cubic-bezier(0.4, 0.55, 0.55, 1);
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-enabled:hover .oo-ui-capsuleMultiselectWidget-handle {
+ border-color: #72777d;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-enabled.oo-ui-capsuleMultiselectWidget-open .oo-ui-capsuleMultiselectWidget-handle {
+ border-color: #36c;
+ outline: 0;
+ box-shadow: inset 0 0 0 1px #36c;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiselectWidget-handle {
+ color: #72777d;
+ text-shadow: 0 1px 1px #fff;
+ border-color: #c8ccd1;
+ background-color: #eaecf0;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiselectWidget-handle > .oo-ui-iconElement-icon {
+ opacity: 0.51;
+}
+.oo-ui-capsuleMultiselectWidget.oo-ui-widget-disabled .oo-ui-capsuleMultiselectWidget-handle > .oo-ui-indicatorElement-indicator {
+ opacity: 0.15;
+}
+.oo-ui-capsuleItemWidget {
+ position: relative;
+ display: inline-block;
+ cursor: default;
+ white-space: nowrap;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ width: auto;
+ max-width: 100%;
+ height: 1.71875em;
+ margin: 0.3125em 0.3125em 0 0;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ padding: 0 0.3125em;
+ line-height: 1.71875em;
+ vertical-align: middle;
+}
+.oo-ui-capsuleItemWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ display: inline-block;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ cursor: text;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled {
+ background-color: #f8f9fa;
+ color: #222;
+ padding-right: 1.640625em;
+ -webkit-transition: background-color 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+ -moz-transition: background-color 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+ transition: background-color 100ms, color 100ms, border-color 100ms, box-shadow 100ms;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled:hover {
+ background-color: #fff;
+ color: #444;
+ border-color: #a2a9b1;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c;
+ outline: 0;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled > .oo-ui-buttonElement {
+ display: block;
+ position: absolute;
+ top: 0;
+ right: 0;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button {
+ min-width: 0;
+ min-height: 0;
+ border: 0;
+ padding-top: 1.5625em;
+ padding-left: 1.5625em;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button .oo-ui-icon-close {
+ left: 0;
+ min-width: 20px;
+ min-height: 20px;
+ width: 1.5625em;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button .oo-ui-labelElement-label,
+.oo-ui-capsuleItemWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button .oo-ui-indicatorElement-indicator {
+ display: none;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-disabled {
+ background-color: #eaecf0;
+ color: #72777d;
+ border-color: #c8ccd1;
+ text-shadow: 0 1px 1px #fff;
+}
+.oo-ui-capsuleItemWidget.oo-ui-widget-disabled > .oo-ui-buttonElement {
+ display: none;
+}
+.oo-ui-searchWidget-query {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+ width: 100%;
+}
+.oo-ui-searchWidget-results {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.oo-ui-searchWidget-query {
+ height: 4.375em;
+ padding: 0 1.25em;
+ border-bottom: 1px solid #c8ccd1;
+ box-shadow: 0 1px 1px 0 rgba(0, 0, 0, 0.1);
+}
+.oo-ui-searchWidget-query .oo-ui-textInputWidget {
+ margin: 0.9375em 0;
+}
+.oo-ui-searchWidget-results {
+ top: 4.375em;
+ padding: 1.25em;
+ line-height: 0;
+}
+.oo-ui-numberInputWidget {
+ display: inline-block;
+ position: relative;
+ max-width: 50em;
+}
+.oo-ui-numberInputWidget-buttoned .oo-ui-buttonWidget,
+.oo-ui-numberInputWidget-buttoned .oo-ui-inputWidget-input {
+ display: table-cell;
+ height: 100%;
+}
+.oo-ui-numberInputWidget-field {
+ display: table;
+ table-layout: fixed;
+ width: 100%;
+}
+.oo-ui-numberInputWidget-buttoned .oo-ui-buttonWidget {
+ width: 2.5em;
+}
+.oo-ui-numberInputWidget-buttoned .oo-ui-buttonWidget .oo-ui-buttonElement-button {
+ display: block;
+ min-width: 2.5em;
+ min-height: 2.5em;
+ padding-left: 0;
+ padding-right: 0;
+}
+.oo-ui-numberInputWidget-buttoned .oo-ui-buttonWidget .oo-ui-buttonElement-button .oo-ui-iconElement-icon {
+ left: 0.46875em;
+ min-width: 20px;
+ width: 1.5625em;
+}
+.oo-ui-numberInputWidget-buttoned .oo-ui-inputWidget-input {
+ border-radius: 0;
+}
+.oo-ui-numberInputWidget-minusButton > .oo-ui-buttonElement-button {
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+ border-right-width: 0;
+}
+.oo-ui-numberInputWidget-plusButton > .oo-ui-buttonElement-button {
+ border-top-left-radius: 0;
+ border-bottom-left-radius: 0;
+ border-left-width: 0;
+}
+.oo-ui-numberInputWidget.oo-ui-widget-disabled.oo-ui-numberInputWidget-buttoned .oo-ui-iconElement-icon {
+ opacity: 1;
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets.js b/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets.js
new file mode 100644
index 00000000..37c05402
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets.js
@@ -0,0 +1,6932 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:23:58Z
+ */
+( function ( OO ) {
+
+'use strict';
+
+/**
+ * DraggableElement is a mixin class used to create elements that can be clicked
+ * and dragged by a mouse to a new position within a group. This class must be used
+ * in conjunction with OO.ui.mixin.DraggableGroupElement, which provides a container for
+ * the draggable elements.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$handle] The part of the element which can be used for dragging, defaults to the whole element
+ * @cfg {boolean} [draggable] The items are draggable. This can change with #toggleDraggable
+ * but the draggable state should be called from the DraggableGroupElement, which updates
+ * the whole group
+ */
+OO.ui.mixin.DraggableElement = function OoUiMixinDraggableElement( config ) {
+ config = config || {};
+
+ // Properties
+ this.index = null;
+ this.$handle = config.$handle || this.$element;
+ this.wasHandleUsed = null;
+
+ // Initialize and events
+ this.$element
+ .addClass( 'oo-ui-draggableElement' )
+ .on( {
+ mousedown: this.onDragMouseDown.bind( this ),
+ dragstart: this.onDragStart.bind( this ),
+ dragover: this.onDragOver.bind( this ),
+ dragend: this.onDragEnd.bind( this ),
+ drop: this.onDrop.bind( this )
+ } );
+ this.$handle.addClass( 'oo-ui-draggableElement-handle' );
+ this.toggleDraggable( config.draggable === undefined ? true : !!config.draggable );
+};
+
+OO.initClass( OO.ui.mixin.DraggableElement );
+
+/* Events */
+
+/**
+ * @event dragstart
+ *
+ * A dragstart event is emitted when the user clicks and begins dragging an item.
+ * @param {OO.ui.mixin.DraggableElement} item The item the user has clicked and is dragging with the mouse.
+ */
+
+/**
+ * @event dragend
+ * A dragend event is emitted when the user drags an item and releases the mouse,
+ * thus terminating the drag operation.
+ */
+
+/**
+ * @event drop
+ * A drop event is emitted when the user drags an item and then releases the mouse button
+ * over a valid target.
+ */
+
+/* Static Properties */
+
+/**
+ * @inheritdoc OO.ui.mixin.ButtonElement
+ */
+OO.ui.mixin.DraggableElement.static.cancelButtonMouseDownEvents = false;
+
+/* Methods */
+
+/**
+ * Change the draggable state of this widget.
+ * This allows users to temporarily halt the dragging operations.
+ *
+ * @param {boolean} isDraggable Widget supports draggable operations
+ * @fires draggable
+ */
+OO.ui.mixin.DraggableElement.prototype.toggleDraggable = function ( isDraggable ) {
+ isDraggable = isDraggable !== undefined ? !!isDraggable : !this.draggable;
+
+ if ( this.draggable !== isDraggable ) {
+ this.draggable = isDraggable;
+
+ this.$handle.toggleClass( 'oo-ui-draggableElement-undraggable', !this.draggable );
+
+ // We make the entire element draggable, not just the handle, so that
+ // the whole element appears to move. wasHandleUsed prevents drags from
+ // starting outside the handle
+ this.$element.prop( 'draggable', this.draggable );
+ }
+};
+
+/**
+ * Check the draggable state of this widget
+ *
+ * @return {boolean} Widget supports draggable operations
+ */
+OO.ui.mixin.DraggableElement.prototype.isDraggable = function () {
+ return this.draggable;
+};
+
+/**
+ * Respond to mousedown event.
+ *
+ * @private
+ * @param {jQuery.Event} e Drag event
+ */
+OO.ui.mixin.DraggableElement.prototype.onDragMouseDown = function ( e ) {
+ if ( !this.isDraggable() ) {
+ return;
+ }
+
+ this.wasHandleUsed =
+ // Optimization: if the handle is the whole element this is always true
+ this.$handle[ 0 ] === this.$element[ 0 ] ||
+ // Check the mousedown occurred inside the handle
+ OO.ui.contains( this.$handle[ 0 ], e.target, true );
+};
+
+/**
+ * Respond to dragstart event.
+ *
+ * @private
+ * @param {jQuery.Event} e Drag event
+ * @return {boolean} False if the event is cancelled
+ * @fires dragstart
+ */
+OO.ui.mixin.DraggableElement.prototype.onDragStart = function ( e ) {
+ var element = this,
+ dataTransfer = e.originalEvent.dataTransfer;
+
+ if ( !this.wasHandleUsed || !this.isDraggable() ) {
+ return false;
+ }
+
+ // Define drop effect
+ dataTransfer.dropEffect = 'none';
+ dataTransfer.effectAllowed = 'move';
+ // Support: Firefox
+ // We must set up a dataTransfer data property or Firefox seems to
+ // ignore the fact the element is draggable.
+ try {
+ dataTransfer.setData( 'application-x/OOjs-UI-draggable', this.getIndex() );
+ } catch ( err ) {
+ // The above is only for Firefox. Move on if it fails.
+ }
+ // Briefly add a 'clone' class to style the browser's native drag image
+ this.$element.addClass( 'oo-ui-draggableElement-clone' );
+ // Add placeholder class after the browser has rendered the clone
+ setTimeout( function () {
+ element.$element
+ .removeClass( 'oo-ui-draggableElement-clone' )
+ .addClass( 'oo-ui-draggableElement-placeholder' );
+ } );
+ // Emit event
+ this.emit( 'dragstart', this );
+ return true;
+};
+
+/**
+ * Respond to dragend event.
+ *
+ * @private
+ * @fires dragend
+ */
+OO.ui.mixin.DraggableElement.prototype.onDragEnd = function () {
+ this.$element.removeClass( 'oo-ui-draggableElement-placeholder' );
+ this.emit( 'dragend' );
+};
+
+/**
+ * Handle drop event.
+ *
+ * @private
+ * @param {jQuery.Event} e Drop event
+ * @fires drop
+ */
+OO.ui.mixin.DraggableElement.prototype.onDrop = function ( e ) {
+ e.preventDefault();
+ this.emit( 'drop', e );
+};
+
+/**
+ * In order for drag/drop to work, the dragover event must
+ * return false and stop propogation.
+ *
+ * @param {jQuery.Event} e Drag event
+ * @private
+ */
+OO.ui.mixin.DraggableElement.prototype.onDragOver = function ( e ) {
+ e.preventDefault();
+};
+
+/**
+ * Set item index.
+ * Store it in the DOM so we can access from the widget drag event
+ *
+ * @private
+ * @param {number} index Item index
+ */
+OO.ui.mixin.DraggableElement.prototype.setIndex = function ( index ) {
+ if ( this.index !== index ) {
+ this.index = index;
+ this.$element.data( 'index', index );
+ }
+};
+
+/**
+ * Get item index
+ *
+ * @private
+ * @return {number} Item index
+ */
+OO.ui.mixin.DraggableElement.prototype.getIndex = function () {
+ return this.index;
+};
+
+/**
+ * DraggableGroupElement is a mixin class used to create a group element to
+ * contain draggable elements, which are items that can be clicked and dragged by a mouse.
+ * The class is used with OO.ui.mixin.DraggableElement.
+ *
+ * @abstract
+ * @class
+ * @mixins OO.ui.mixin.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [orientation] Item orientation: 'horizontal' or 'vertical'. The orientation
+ * should match the layout of the items. Items displayed in a single row
+ * or in several rows should use horizontal orientation. The vertical orientation should only be
+ * used when the items are displayed in a single column. Defaults to 'vertical'
+ * @cfg {boolean} [draggable] The items are draggable. This can change with #toggleDraggable
+ */
+OO.ui.mixin.DraggableGroupElement = function OoUiMixinDraggableGroupElement( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.mixin.GroupElement.call( this, config );
+
+ // Properties
+ this.orientation = config.orientation || 'vertical';
+ this.dragItem = null;
+ this.itemKeys = {};
+ this.dir = null;
+ this.itemsOrder = null;
+ this.draggable = config.draggable === undefined ? true : !!config.draggable;
+
+ // Events
+ this.aggregate( {
+ dragstart: 'itemDragStart',
+ dragend: 'itemDragEnd',
+ drop: 'itemDrop'
+ } );
+ this.connect( this, {
+ itemDragStart: 'onItemDragStart',
+ itemDrop: 'onItemDropOrDragEnd',
+ itemDragEnd: 'onItemDropOrDragEnd'
+ } );
+
+ // Initialize
+ if ( Array.isArray( config.items ) ) {
+ this.addItems( config.items );
+ }
+ this.$element
+ .addClass( 'oo-ui-draggableGroupElement' )
+ .append( this.$status )
+ .toggleClass( 'oo-ui-draggableGroupElement-horizontal', this.orientation === 'horizontal' );
+};
+
+/* Setup */
+OO.mixinClass( OO.ui.mixin.DraggableGroupElement, OO.ui.mixin.GroupElement );
+
+/* Events */
+
+/**
+ * An item has been dragged to a new position, but not yet dropped.
+ *
+ * @event drag
+ * @param {OO.ui.mixin.DraggableElement} item Dragged item
+ * @param {number} [newIndex] New index for the item
+ */
+
+/**
+ * An item has been dropped at a new position.
+ *
+ * @event reorder
+ * @param {OO.ui.mixin.DraggableElement} item Reordered item
+ * @param {number} [newIndex] New index for the item
+ */
+
+/**
+ * Draggable state of this widget has changed.
+ *
+ * @event draggable
+ * @param {boolean} [draggable] Widget is draggable
+ */
+
+/* Methods */
+
+/**
+ * Change the draggable state of this widget.
+ * This allows users to temporarily halt the dragging operations.
+ *
+ * @param {boolean} isDraggable Widget supports draggable operations
+ * @fires draggable
+ */
+OO.ui.mixin.DraggableGroupElement.prototype.toggleDraggable = function ( isDraggable ) {
+ isDraggable = isDraggable !== undefined ? !!isDraggable : !this.draggable;
+
+ if ( this.draggable !== isDraggable ) {
+ this.draggable = isDraggable;
+
+ // Tell the items their draggable state changed
+ this.getItems().forEach( function ( item ) {
+ item.toggleDraggable( this.draggable );
+ }.bind( this ) );
+
+ // Emit event
+ this.emit( 'draggable', this.draggable );
+ }
+};
+
+/**
+ * Check the draggable state of this widget
+ *
+ * @return {boolean} Widget supports draggable operations
+ */
+OO.ui.mixin.DraggableGroupElement.prototype.isDraggable = function () {
+ return this.draggable;
+};
+
+/**
+ * Respond to item drag start event
+ *
+ * @private
+ * @param {OO.ui.mixin.DraggableElement} item Dragged item
+ */
+OO.ui.mixin.DraggableGroupElement.prototype.onItemDragStart = function ( item ) {
+ if ( !this.isDraggable() ) {
+ return;
+ }
+ // Make a shallow copy of this.items so we can re-order it during previews
+ // without affecting the original array.
+ this.itemsOrder = this.items.slice();
+ this.updateIndexes();
+ if ( this.orientation === 'horizontal' ) {
+ // Calculate and cache directionality on drag start - it's a little
+ // expensive and it shouldn't change while dragging.
+ this.dir = this.$element.css( 'direction' );
+ }
+ this.setDragItem( item );
+};
+
+/**
+ * Update the index properties of the items
+ */
+OO.ui.mixin.DraggableGroupElement.prototype.updateIndexes = function () {
+ var i, len;
+
+ // Map the index of each object
+ for ( i = 0, len = this.itemsOrder.length; i < len; i++ ) {
+ this.itemsOrder[ i ].setIndex( i );
+ }
+};
+
+/**
+ * Handle drop or dragend event and switch the order of the items accordingly
+ *
+ * @private
+ * @param {OO.ui.mixin.DraggableElement} item Dropped item
+ */
+OO.ui.mixin.DraggableGroupElement.prototype.onItemDropOrDragEnd = function () {
+ var targetIndex, originalIndex,
+ item = this.getDragItem();
+
+ // TODO: Figure out a way to configure a list of legally droppable
+ // elements even if they are not yet in the list
+ if ( item ) {
+ originalIndex = this.items.indexOf( item );
+ // If the item has moved forward, add one to the index to account for the left shift
+ targetIndex = item.getIndex() + ( item.getIndex() > originalIndex ? 1 : 0 );
+ if ( targetIndex !== originalIndex ) {
+ this.reorder( this.getDragItem(), targetIndex );
+ this.emit( 'reorder', this.getDragItem(), targetIndex );
+ }
+ this.updateIndexes();
+ }
+ this.unsetDragItem();
+ // Return false to prevent propogation
+ return false;
+};
+
+/**
+ * Respond to dragover event
+ *
+ * @private
+ * @param {jQuery.Event} e Dragover event
+ * @fires reorder
+ */
+OO.ui.mixin.DraggableGroupElement.prototype.onDragOver = function ( e ) {
+ var overIndex, targetIndex,
+ item = this.getDragItem(),
+ dragItemIndex = item.getIndex();
+
+ // Get the OptionWidget item we are dragging over
+ overIndex = $( e.target ).closest( '.oo-ui-draggableElement' ).data( 'index' );
+
+ if ( overIndex !== undefined && overIndex !== dragItemIndex ) {
+ targetIndex = overIndex + ( overIndex > dragItemIndex ? 1 : 0 );
+
+ if ( targetIndex > 0 ) {
+ this.$group.children().eq( targetIndex - 1 ).after( item.$element );
+ } else {
+ this.$group.prepend( item.$element );
+ }
+ // Move item in itemsOrder array
+ this.itemsOrder.splice( overIndex, 0,
+ this.itemsOrder.splice( dragItemIndex, 1 )[ 0 ]
+ );
+ this.updateIndexes();
+ this.emit( 'drag', item, targetIndex );
+ }
+ // Prevent default
+ e.preventDefault();
+};
+
+/**
+ * Reorder the items in the group
+ *
+ * @param {OO.ui.mixin.DraggableElement} item Reordered item
+ * @param {number} newIndex New index
+ */
+OO.ui.mixin.DraggableGroupElement.prototype.reorder = function ( item, newIndex ) {
+ this.addItems( [ item ], newIndex );
+};
+
+/**
+ * Set a dragged item
+ *
+ * @param {OO.ui.mixin.DraggableElement} item Dragged item
+ */
+OO.ui.mixin.DraggableGroupElement.prototype.setDragItem = function ( item ) {
+ if ( this.dragItem !== item ) {
+ this.dragItem = item;
+ this.$element.on( 'dragover', this.onDragOver.bind( this ) );
+ this.$element.addClass( 'oo-ui-draggableGroupElement-dragging' );
+ }
+};
+
+/**
+ * Unset the current dragged item
+ */
+OO.ui.mixin.DraggableGroupElement.prototype.unsetDragItem = function () {
+ if ( this.dragItem ) {
+ this.dragItem = null;
+ this.$element.off( 'dragover' );
+ this.$element.removeClass( 'oo-ui-draggableGroupElement-dragging' );
+ }
+};
+
+/**
+ * Get the item that is currently being dragged.
+ *
+ * @return {OO.ui.mixin.DraggableElement|null} The currently dragged item, or `null` if no item is being dragged
+ */
+OO.ui.mixin.DraggableGroupElement.prototype.getDragItem = function () {
+ return this.dragItem;
+};
+
+/**
+ * RequestManager is a mixin that manages the lifecycle of a promise-backed request for a widget, such as
+ * the {@link OO.ui.mixin.LookupElement}.
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ */
+OO.ui.mixin.RequestManager = function OoUiMixinRequestManager() {
+ this.requestCache = {};
+ this.requestQuery = null;
+ this.requestRequest = null;
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.mixin.RequestManager );
+
+/**
+ * Get request results for the current query.
+ *
+ * @return {jQuery.Promise} Promise object which will be passed response data as the first argument of
+ * the done event. If the request was aborted to make way for a subsequent request, this promise
+ * may not be rejected, depending on what jQuery feels like doing.
+ */
+OO.ui.mixin.RequestManager.prototype.getRequestData = function () {
+ var widget = this,
+ value = this.getRequestQuery(),
+ deferred = $.Deferred(),
+ ourRequest;
+
+ this.abortRequest();
+ if ( Object.prototype.hasOwnProperty.call( this.requestCache, value ) ) {
+ deferred.resolve( this.requestCache[ value ] );
+ } else {
+ if ( this.pushPending ) {
+ this.pushPending();
+ }
+ this.requestQuery = value;
+ ourRequest = this.requestRequest = this.getRequest();
+ ourRequest
+ .always( function () {
+ // We need to pop pending even if this is an old request, otherwise
+ // the widget will remain pending forever.
+ // TODO: this assumes that an aborted request will fail or succeed soon after
+ // being aborted, or at least eventually. It would be nice if we could popPending()
+ // at abort time, but only if we knew that we hadn't already called popPending()
+ // for that request.
+ if ( widget.popPending ) {
+ widget.popPending();
+ }
+ } )
+ .done( function ( response ) {
+ // If this is an old request (and aborting it somehow caused it to still succeed),
+ // ignore its success completely
+ if ( ourRequest === widget.requestRequest ) {
+ widget.requestQuery = null;
+ widget.requestRequest = null;
+ widget.requestCache[ value ] = widget.getRequestCacheDataFromResponse( response );
+ deferred.resolve( widget.requestCache[ value ] );
+ }
+ } )
+ .fail( function () {
+ // If this is an old request (or a request failing because it's being aborted),
+ // ignore its failure completely
+ if ( ourRequest === widget.requestRequest ) {
+ widget.requestQuery = null;
+ widget.requestRequest = null;
+ deferred.reject();
+ }
+ } );
+ }
+ return deferred.promise();
+};
+
+/**
+ * Abort the currently pending request, if any.
+ *
+ * @private
+ */
+OO.ui.mixin.RequestManager.prototype.abortRequest = function () {
+ var oldRequest = this.requestRequest;
+ if ( oldRequest ) {
+ // First unset this.requestRequest to the fail handler will notice
+ // that the request is no longer current
+ this.requestRequest = null;
+ this.requestQuery = null;
+ oldRequest.abort();
+ }
+};
+
+/**
+ * Get the query to be made.
+ *
+ * @protected
+ * @method
+ * @abstract
+ * @return {string} query to be used
+ */
+OO.ui.mixin.RequestManager.prototype.getRequestQuery = null;
+
+/**
+ * Get a new request object of the current query value.
+ *
+ * @protected
+ * @method
+ * @abstract
+ * @return {jQuery.Promise} jQuery AJAX object, or promise object with an .abort() method
+ */
+OO.ui.mixin.RequestManager.prototype.getRequest = null;
+
+/**
+ * Pre-process data returned by the request from #getRequest.
+ *
+ * The return value of this function will be cached, and any further queries for the given value
+ * will use the cache rather than doing API requests.
+ *
+ * @protected
+ * @method
+ * @abstract
+ * @param {Mixed} response Response from server
+ * @return {Mixed} Cached result data
+ */
+OO.ui.mixin.RequestManager.prototype.getRequestCacheDataFromResponse = null;
+
+/**
+ * LookupElement is a mixin that creates a {@link OO.ui.MenuSelectWidget menu} of suggested values for
+ * a {@link OO.ui.TextInputWidget text input widget}. Suggested values are based on the characters the user types
+ * into the text input field and, in general, the menu is only displayed when the user types. If a suggested value is chosen
+ * from the lookup menu, that value becomes the value of the input field.
+ *
+ * Note that a new menu of suggested items is displayed when a value is chosen from the lookup menu. If this is
+ * not the desired behavior, disable lookup menus with the #setLookupsDisabled method, then set the value, then
+ * re-enable lookups.
+ *
+ * See the [OOjs UI demos][1] for an example.
+ *
+ * [1]: https://tools.wmflabs.org/oojs-ui/oojs-ui/demos/index.html#widgets-apex-vector-ltr
+ *
+ * @class
+ * @abstract
+ * @mixins OO.ui.mixin.RequestManager
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery} [$overlay] Overlay for the lookup menu; defaults to relative positioning.
+ * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.
+ * @cfg {jQuery} [$container=this.$element] The container element. The lookup menu is rendered beneath the specified element.
+ * @cfg {boolean} [allowSuggestionsWhenEmpty=false] Request and display a lookup menu when the text input is empty.
+ * By default, the lookup menu is not generated and displayed until the user begins to type.
+ * @cfg {boolean} [highlightFirst=true] Whether the first lookup result should be highlighted (so, that the user can
+ * take it over into the input with simply pressing return) automatically or not.
+ */
+OO.ui.mixin.LookupElement = function OoUiMixinLookupElement( config ) {
+ // Configuration initialization
+ config = $.extend( { highlightFirst: true }, config );
+
+ // Mixin constructors
+ OO.ui.mixin.RequestManager.call( this, config );
+
+ // Properties
+ this.$overlay = config.$overlay || this.$element;
+ this.lookupMenu = new OO.ui.MenuSelectWidget( {
+ widget: this,
+ input: this,
+ $floatableContainer: config.$container || this.$element
+ } );
+
+ this.allowSuggestionsWhenEmpty = config.allowSuggestionsWhenEmpty || false;
+
+ this.lookupsDisabled = false;
+ this.lookupInputFocused = false;
+ this.lookupHighlightFirstItem = config.highlightFirst;
+
+ // Events
+ this.$input.on( {
+ focus: this.onLookupInputFocus.bind( this ),
+ blur: this.onLookupInputBlur.bind( this ),
+ mousedown: this.onLookupInputMouseDown.bind( this )
+ } );
+ this.connect( this, { change: 'onLookupInputChange' } );
+ this.lookupMenu.connect( this, {
+ toggle: 'onLookupMenuToggle',
+ choose: 'onLookupMenuItemChoose'
+ } );
+
+ // Initialization
+ this.$input.attr( {
+ role: 'combobox',
+ 'aria-owns': this.lookupMenu.getElementId(),
+ 'aria-autocomplete': 'list'
+ } );
+ this.$element.addClass( 'oo-ui-lookupElement' );
+ this.lookupMenu.$element.addClass( 'oo-ui-lookupElement-menu' );
+ this.$overlay.append( this.lookupMenu.$element );
+};
+
+/* Setup */
+
+OO.mixinClass( OO.ui.mixin.LookupElement, OO.ui.mixin.RequestManager );
+
+/* Methods */
+
+/**
+ * Handle input focus event.
+ *
+ * @protected
+ * @param {jQuery.Event} e Input focus event
+ */
+OO.ui.mixin.LookupElement.prototype.onLookupInputFocus = function () {
+ this.lookupInputFocused = true;
+ this.populateLookupMenu();
+};
+
+/**
+ * Handle input blur event.
+ *
+ * @protected
+ * @param {jQuery.Event} e Input blur event
+ */
+OO.ui.mixin.LookupElement.prototype.onLookupInputBlur = function () {
+ this.closeLookupMenu();
+ this.lookupInputFocused = false;
+};
+
+/**
+ * Handle input mouse down event.
+ *
+ * @protected
+ * @param {jQuery.Event} e Input mouse down event
+ */
+OO.ui.mixin.LookupElement.prototype.onLookupInputMouseDown = function () {
+ // Only open the menu if the input was already focused.
+ // This way we allow the user to open the menu again after closing it with Esc
+ // by clicking in the input. Opening (and populating) the menu when initially
+ // clicking into the input is handled by the focus handler.
+ if ( this.lookupInputFocused && !this.lookupMenu.isVisible() ) {
+ this.populateLookupMenu();
+ }
+};
+
+/**
+ * Handle input change event.
+ *
+ * @protected
+ * @param {string} value New input value
+ */
+OO.ui.mixin.LookupElement.prototype.onLookupInputChange = function () {
+ if ( this.lookupInputFocused ) {
+ this.populateLookupMenu();
+ }
+};
+
+/**
+ * Handle the lookup menu being shown/hidden.
+ *
+ * @protected
+ * @param {boolean} visible Whether the lookup menu is now visible.
+ */
+OO.ui.mixin.LookupElement.prototype.onLookupMenuToggle = function ( visible ) {
+ if ( !visible ) {
+ // When the menu is hidden, abort any active request and clear the menu.
+ // This has to be done here in addition to closeLookupMenu(), because
+ // MenuSelectWidget will close itself when the user presses Esc.
+ this.abortLookupRequest();
+ this.lookupMenu.clearItems();
+ }
+};
+
+/**
+ * Handle menu item 'choose' event, updating the text input value to the value of the clicked item.
+ *
+ * @protected
+ * @param {OO.ui.MenuOptionWidget} item Selected item
+ */
+OO.ui.mixin.LookupElement.prototype.onLookupMenuItemChoose = function ( item ) {
+ this.setValue( item.getData() );
+};
+
+/**
+ * Get lookup menu.
+ *
+ * @private
+ * @return {OO.ui.MenuSelectWidget}
+ */
+OO.ui.mixin.LookupElement.prototype.getLookupMenu = function () {
+ return this.lookupMenu;
+};
+
+/**
+ * Disable or re-enable lookups.
+ *
+ * When lookups are disabled, calls to #populateLookupMenu will be ignored.
+ *
+ * @param {boolean} disabled Disable lookups
+ */
+OO.ui.mixin.LookupElement.prototype.setLookupsDisabled = function ( disabled ) {
+ this.lookupsDisabled = !!disabled;
+};
+
+/**
+ * Open the menu. If there are no entries in the menu, this does nothing.
+ *
+ * @private
+ * @chainable
+ */
+OO.ui.mixin.LookupElement.prototype.openLookupMenu = function () {
+ if ( !this.lookupMenu.isEmpty() ) {
+ this.lookupMenu.toggle( true );
+ }
+ return this;
+};
+
+/**
+ * Close the menu, empty it, and abort any pending request.
+ *
+ * @private
+ * @chainable
+ */
+OO.ui.mixin.LookupElement.prototype.closeLookupMenu = function () {
+ this.lookupMenu.toggle( false );
+ this.abortLookupRequest();
+ this.lookupMenu.clearItems();
+ return this;
+};
+
+/**
+ * Request menu items based on the input's current value, and when they arrive,
+ * populate the menu with these items and show the menu.
+ *
+ * If lookups have been disabled with #setLookupsDisabled, this function does nothing.
+ *
+ * @private
+ * @chainable
+ */
+OO.ui.mixin.LookupElement.prototype.populateLookupMenu = function () {
+ var widget = this,
+ value = this.getValue();
+
+ if ( this.lookupsDisabled || this.isReadOnly() ) {
+ return;
+ }
+
+ // If the input is empty, clear the menu, unless suggestions when empty are allowed.
+ if ( !this.allowSuggestionsWhenEmpty && value === '' ) {
+ this.closeLookupMenu();
+ // Skip population if there is already a request pending for the current value
+ } else if ( value !== this.lookupQuery ) {
+ this.getLookupMenuItems()
+ .done( function ( items ) {
+ widget.lookupMenu.clearItems();
+ if ( items.length ) {
+ widget.lookupMenu
+ .addItems( items )
+ .toggle( true );
+ widget.initializeLookupMenuSelection();
+ } else {
+ widget.lookupMenu.toggle( false );
+ }
+ } )
+ .fail( function () {
+ widget.lookupMenu.clearItems();
+ } );
+ }
+
+ return this;
+};
+
+/**
+ * Highlight the first selectable item in the menu, if configured.
+ *
+ * @private
+ * @chainable
+ */
+OO.ui.mixin.LookupElement.prototype.initializeLookupMenuSelection = function () {
+ if ( this.lookupHighlightFirstItem && !this.lookupMenu.getSelectedItem() ) {
+ this.lookupMenu.highlightItem( this.lookupMenu.getFirstSelectableItem() );
+ }
+};
+
+/**
+ * Get lookup menu items for the current query.
+ *
+ * @private
+ * @return {jQuery.Promise} Promise object which will be passed menu items as the first argument of
+ * the done event. If the request was aborted to make way for a subsequent request, this promise
+ * will not be rejected: it will remain pending forever.
+ */
+OO.ui.mixin.LookupElement.prototype.getLookupMenuItems = function () {
+ return this.getRequestData().then( function ( data ) {
+ return this.getLookupMenuOptionsFromData( data );
+ }.bind( this ) );
+};
+
+/**
+ * Abort the currently pending lookup request, if any.
+ *
+ * @private
+ */
+OO.ui.mixin.LookupElement.prototype.abortLookupRequest = function () {
+ this.abortRequest();
+};
+
+/**
+ * Get a new request object of the current lookup query value.
+ *
+ * @protected
+ * @method
+ * @abstract
+ * @return {jQuery.Promise} jQuery AJAX object, or promise object with an .abort() method
+ */
+OO.ui.mixin.LookupElement.prototype.getLookupRequest = null;
+
+/**
+ * Pre-process data returned by the request from #getLookupRequest.
+ *
+ * The return value of this function will be cached, and any further queries for the given value
+ * will use the cache rather than doing API requests.
+ *
+ * @protected
+ * @method
+ * @abstract
+ * @param {Mixed} response Response from server
+ * @return {Mixed} Cached result data
+ */
+OO.ui.mixin.LookupElement.prototype.getLookupCacheDataFromResponse = null;
+
+/**
+ * Get a list of menu option widgets from the (possibly cached) data returned by
+ * #getLookupCacheDataFromResponse.
+ *
+ * @protected
+ * @method
+ * @abstract
+ * @param {Mixed} data Cached result data, usually an array
+ * @return {OO.ui.MenuOptionWidget[]} Menu items
+ */
+OO.ui.mixin.LookupElement.prototype.getLookupMenuOptionsFromData = null;
+
+/**
+ * Set the read-only state of the widget.
+ *
+ * This will also disable/enable the lookups functionality.
+ *
+ * @param {boolean} readOnly Make input read-only
+ * @chainable
+ */
+OO.ui.mixin.LookupElement.prototype.setReadOnly = function ( readOnly ) {
+ // Parent method
+ // Note: Calling #setReadOnly this way assumes this is mixed into an OO.ui.TextInputWidget
+ OO.ui.TextInputWidget.prototype.setReadOnly.call( this, readOnly );
+
+ // During construction, #setReadOnly is called before the OO.ui.mixin.LookupElement constructor
+ if ( this.isReadOnly() && this.lookupMenu ) {
+ this.closeLookupMenu();
+ }
+
+ return this;
+};
+
+/**
+ * @inheritdoc OO.ui.mixin.RequestManager
+ */
+OO.ui.mixin.LookupElement.prototype.getRequestQuery = function () {
+ return this.getValue();
+};
+
+/**
+ * @inheritdoc OO.ui.mixin.RequestManager
+ */
+OO.ui.mixin.LookupElement.prototype.getRequest = function () {
+ return this.getLookupRequest();
+};
+
+/**
+ * @inheritdoc OO.ui.mixin.RequestManager
+ */
+OO.ui.mixin.LookupElement.prototype.getRequestCacheDataFromResponse = function ( response ) {
+ return this.getLookupCacheDataFromResponse( response );
+};
+
+/**
+ * TabPanelLayouts are used within {@link OO.ui.IndexLayout index layouts} to create tab panels that
+ * users can select and display from the index's optional {@link OO.ui.TabSelectWidget tab}
+ * navigation. TabPanels are usually not instantiated directly, rather extended to include the
+ * required content and functionality.
+ *
+ * Each tab panel must have a unique symbolic name, which is passed to the constructor. In addition,
+ * the tab panel's tab item is customized (with a label) using the #setupTabItem method. See
+ * {@link OO.ui.IndexLayout IndexLayout} for an example.
+ *
+ * @class
+ * @extends OO.ui.PanelLayout
+ *
+ * @constructor
+ * @param {string} name Unique symbolic name of tab panel
+ * @param {Object} [config] Configuration options
+ * @cfg {jQuery|string|Function|OO.ui.HtmlSnippet} [label] Label for tab panel's tab
+ */
+OO.ui.TabPanelLayout = function OoUiTabPanelLayout( name, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( name ) && config === undefined ) {
+ config = name;
+ name = config.name;
+ }
+
+ // Configuration initialization
+ config = $.extend( { scrollable: true }, config );
+
+ // Parent constructor
+ OO.ui.TabPanelLayout.parent.call( this, config );
+
+ // Properties
+ this.name = name;
+ this.label = config.label;
+ this.tabItem = null;
+ this.active = false;
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-tabPanelLayout' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.TabPanelLayout, OO.ui.PanelLayout );
+
+/* Events */
+
+/**
+ * An 'active' event is emitted when the tab panel becomes active. Tab panels become active when they are
+ * shown in a index layout that is configured to display only one tab panel at a time.
+ *
+ * @event active
+ * @param {boolean} active Tab panel is active
+ */
+
+/* Methods */
+
+/**
+ * Get the symbolic name of the tab panel.
+ *
+ * @return {string} Symbolic name of tab panel
+ */
+OO.ui.TabPanelLayout.prototype.getName = function () {
+ return this.name;
+};
+
+/**
+ * Check if tab panel is active.
+ *
+ * Tab panels become active when they are shown in a {@link OO.ui.IndexLayout index layout} that is configured to
+ * display only one tab panel at a time. Additional CSS is applied to the tab panel's tab item to reflect the
+ * active state.
+ *
+ * @return {boolean} Tab panel is active
+ */
+OO.ui.TabPanelLayout.prototype.isActive = function () {
+ return this.active;
+};
+
+/**
+ * Get tab item.
+ *
+ * The tab item allows users to access the tab panel from the index's tab
+ * navigation. The tab item itself can be customized (with a label, level, etc.) using the #setupTabItem method.
+ *
+ * @return {OO.ui.TabOptionWidget|null} Tab option widget
+ */
+OO.ui.TabPanelLayout.prototype.getTabItem = function () {
+ return this.tabItem;
+};
+
+/**
+ * Set or unset the tab item.
+ *
+ * Specify a {@link OO.ui.TabOptionWidget tab option} to set it,
+ * or `null` to clear the tab item. To customize the tab item itself (e.g., to set a label or tab
+ * level), use #setupTabItem instead of this method.
+ *
+ * @param {OO.ui.TabOptionWidget|null} tabItem Tab option widget, null to clear
+ * @chainable
+ */
+OO.ui.TabPanelLayout.prototype.setTabItem = function ( tabItem ) {
+ this.tabItem = tabItem || null;
+ if ( tabItem ) {
+ this.setupTabItem();
+ }
+ return this;
+};
+
+/**
+ * Set up the tab item.
+ *
+ * Use this method to customize the tab item (e.g., to add a label or tab level). To set or unset
+ * the tab item itself (with a {@link OO.ui.TabOptionWidget tab option} or `null`), use
+ * the #setTabItem method instead.
+ *
+ * @param {OO.ui.TabOptionWidget} tabItem Tab option widget to set up
+ * @chainable
+ */
+OO.ui.TabPanelLayout.prototype.setupTabItem = function () {
+ if ( this.label ) {
+ this.tabItem.setLabel( this.label );
+ }
+ return this;
+};
+
+/**
+ * Set the tab panel to its 'active' state.
+ *
+ * Tab panels become active when they are shown in a index layout that is configured to display only
+ * one tab panel at a time. Additional CSS is applied to the tab item to reflect the tab panel's
+ * active state. Outside of the index context, setting the active state on a tab panel does nothing.
+ *
+ * @param {boolean} active Tab panel is active
+ * @fires active
+ */
+OO.ui.TabPanelLayout.prototype.setActive = function ( active ) {
+ active = !!active;
+
+ if ( active !== this.active ) {
+ this.active = active;
+ this.$element.toggleClass( 'oo-ui-tabPanelLayout-active', this.active );
+ this.emit( 'active', this.active );
+ }
+};
+
+/**
+ * PageLayouts are used within {@link OO.ui.BookletLayout booklet layouts} to create pages that users can select and display
+ * from the booklet's optional {@link OO.ui.OutlineSelectWidget outline} navigation. Pages are usually not instantiated directly,
+ * rather extended to include the required content and functionality.
+ *
+ * Each page must have a unique symbolic name, which is passed to the constructor. In addition, the page's outline
+ * item is customized (with a label, outline level, etc.) using the #setupOutlineItem method. See
+ * {@link OO.ui.BookletLayout BookletLayout} for an example.
+ *
+ * @class
+ * @extends OO.ui.PanelLayout
+ *
+ * @constructor
+ * @param {string} name Unique symbolic name of page
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.PageLayout = function OoUiPageLayout( name, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( name ) && config === undefined ) {
+ config = name;
+ name = config.name;
+ }
+
+ // Configuration initialization
+ config = $.extend( { scrollable: true }, config );
+
+ // Parent constructor
+ OO.ui.PageLayout.parent.call( this, config );
+
+ // Properties
+ this.name = name;
+ this.outlineItem = null;
+ this.active = false;
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-pageLayout' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.PageLayout, OO.ui.PanelLayout );
+
+/* Events */
+
+/**
+ * An 'active' event is emitted when the page becomes active. Pages become active when they are
+ * shown in a booklet layout that is configured to display only one page at a time.
+ *
+ * @event active
+ * @param {boolean} active Page is active
+ */
+
+/* Methods */
+
+/**
+ * Get the symbolic name of the page.
+ *
+ * @return {string} Symbolic name of page
+ */
+OO.ui.PageLayout.prototype.getName = function () {
+ return this.name;
+};
+
+/**
+ * Check if page is active.
+ *
+ * Pages become active when they are shown in a {@link OO.ui.BookletLayout booklet layout} that is configured to display
+ * only one page at a time. Additional CSS is applied to the page's outline item to reflect the active state.
+ *
+ * @return {boolean} Page is active
+ */
+OO.ui.PageLayout.prototype.isActive = function () {
+ return this.active;
+};
+
+/**
+ * Get outline item.
+ *
+ * The outline item allows users to access the page from the booklet's outline
+ * navigation. The outline item itself can be customized (with a label, level, etc.) using the #setupOutlineItem method.
+ *
+ * @return {OO.ui.OutlineOptionWidget|null} Outline option widget
+ */
+OO.ui.PageLayout.prototype.getOutlineItem = function () {
+ return this.outlineItem;
+};
+
+/**
+ * Set or unset the outline item.
+ *
+ * Specify an {@link OO.ui.OutlineOptionWidget outline option} to set it,
+ * or `null` to clear the outline item. To customize the outline item itself (e.g., to set a label or outline
+ * level), use #setupOutlineItem instead of this method.
+ *
+ * @param {OO.ui.OutlineOptionWidget|null} outlineItem Outline option widget, null to clear
+ * @chainable
+ */
+OO.ui.PageLayout.prototype.setOutlineItem = function ( outlineItem ) {
+ this.outlineItem = outlineItem || null;
+ if ( outlineItem ) {
+ this.setupOutlineItem();
+ }
+ return this;
+};
+
+/**
+ * Set up the outline item.
+ *
+ * Use this method to customize the outline item (e.g., to add a label or outline level). To set or unset
+ * the outline item itself (with an {@link OO.ui.OutlineOptionWidget outline option} or `null`), use
+ * the #setOutlineItem method instead.
+ *
+ * @param {OO.ui.OutlineOptionWidget} outlineItem Outline option widget to set up
+ * @chainable
+ */
+OO.ui.PageLayout.prototype.setupOutlineItem = function () {
+ return this;
+};
+
+/**
+ * Set the page to its 'active' state.
+ *
+ * Pages become active when they are shown in a booklet layout that is configured to display only one page at a time. Additional
+ * CSS is applied to the outline item to reflect the page's active state. Outside of the booklet
+ * context, setting the active state on a page does nothing.
+ *
+ * @param {boolean} active Page is active
+ * @fires active
+ */
+OO.ui.PageLayout.prototype.setActive = function ( active ) {
+ active = !!active;
+
+ if ( active !== this.active ) {
+ this.active = active;
+ this.$element.toggleClass( 'oo-ui-pageLayout-active', active );
+ this.emit( 'active', this.active );
+ }
+};
+
+/**
+ * StackLayouts contain a series of {@link OO.ui.PanelLayout panel layouts}. By default, only one panel is displayed
+ * at a time, though the stack layout can also be configured to show all contained panels, one after another,
+ * by setting the #continuous option to 'true'.
+ *
+ * @example
+ * // A stack layout with two panels, configured to be displayed continously
+ * var myStack = new OO.ui.StackLayout( {
+ * items: [
+ * new OO.ui.PanelLayout( {
+ * $content: $( '<p>Panel One</p>' ),
+ * padded: true,
+ * framed: true
+ * } ),
+ * new OO.ui.PanelLayout( {
+ * $content: $( '<p>Panel Two</p>' ),
+ * padded: true,
+ * framed: true
+ * } )
+ * ],
+ * continuous: true
+ * } );
+ * $( 'body' ).append( myStack.$element );
+ *
+ * @class
+ * @extends OO.ui.PanelLayout
+ * @mixins OO.ui.mixin.GroupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [continuous=false] Show all panels, one after another. By default, only one panel is displayed at a time.
+ * @cfg {OO.ui.Layout[]} [items] Panel layouts to add to the stack layout.
+ */
+OO.ui.StackLayout = function OoUiStackLayout( config ) {
+ // Configuration initialization
+ config = $.extend( { scrollable: true }, config );
+
+ // Parent constructor
+ OO.ui.StackLayout.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.GroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );
+
+ // Properties
+ this.currentItem = null;
+ this.continuous = !!config.continuous;
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-stackLayout' );
+ if ( this.continuous ) {
+ this.$element.addClass( 'oo-ui-stackLayout-continuous' );
+ this.$element.on( 'scroll', OO.ui.debounce( this.onScroll.bind( this ), 250 ) );
+ }
+ if ( Array.isArray( config.items ) ) {
+ this.addItems( config.items );
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.StackLayout, OO.ui.PanelLayout );
+OO.mixinClass( OO.ui.StackLayout, OO.ui.mixin.GroupElement );
+
+/* Events */
+
+/**
+ * A 'set' event is emitted when panels are {@link #addItems added}, {@link #removeItems removed},
+ * {@link #clearItems cleared} or {@link #setItem displayed}.
+ *
+ * @event set
+ * @param {OO.ui.Layout|null} item Current panel or `null` if no panel is shown
+ */
+
+/**
+ * When used in continuous mode, this event is emitted when the user scrolls down
+ * far enough such that currentItem is no longer visible.
+ *
+ * @event visibleItemChange
+ * @param {OO.ui.PanelLayout} panel The next visible item in the layout
+ */
+
+/* Methods */
+
+/**
+ * Handle scroll events from the layout element
+ *
+ * @param {jQuery.Event} e
+ * @fires visibleItemChange
+ */
+OO.ui.StackLayout.prototype.onScroll = function () {
+ var currentRect,
+ len = this.items.length,
+ currentIndex = this.items.indexOf( this.currentItem ),
+ newIndex = currentIndex,
+ containerRect = this.$element[ 0 ].getBoundingClientRect();
+
+ if ( !containerRect || ( !containerRect.top && !containerRect.bottom ) ) {
+ // Can't get bounding rect, possibly not attached.
+ return;
+ }
+
+ function getRect( item ) {
+ return item.$element[ 0 ].getBoundingClientRect();
+ }
+
+ function isVisible( item ) {
+ var rect = getRect( item );
+ return rect.bottom > containerRect.top && rect.top < containerRect.bottom;
+ }
+
+ currentRect = getRect( this.currentItem );
+
+ if ( currentRect.bottom < containerRect.top ) {
+ // Scrolled down past current item
+ while ( ++newIndex < len ) {
+ if ( isVisible( this.items[ newIndex ] ) ) {
+ break;
+ }
+ }
+ } else if ( currentRect.top > containerRect.bottom ) {
+ // Scrolled up past current item
+ while ( --newIndex >= 0 ) {
+ if ( isVisible( this.items[ newIndex ] ) ) {
+ break;
+ }
+ }
+ }
+
+ if ( newIndex !== currentIndex ) {
+ this.emit( 'visibleItemChange', this.items[ newIndex ] );
+ }
+};
+
+/**
+ * Get the current panel.
+ *
+ * @return {OO.ui.Layout|null}
+ */
+OO.ui.StackLayout.prototype.getCurrentItem = function () {
+ return this.currentItem;
+};
+
+/**
+ * Unset the current item.
+ *
+ * @private
+ * @param {OO.ui.StackLayout} layout
+ * @fires set
+ */
+OO.ui.StackLayout.prototype.unsetCurrentItem = function () {
+ var prevItem = this.currentItem;
+ if ( prevItem === null ) {
+ return;
+ }
+
+ this.currentItem = null;
+ this.emit( 'set', null );
+};
+
+/**
+ * Add panel layouts to the stack layout.
+ *
+ * Panels will be added to the end of the stack layout array unless the optional index parameter specifies a different
+ * insertion point. Adding a panel that is already in the stack will move it to the end of the array or the point specified
+ * by the index.
+ *
+ * @param {OO.ui.Layout[]} items Panels to add
+ * @param {number} [index] Index of the insertion point
+ * @chainable
+ */
+OO.ui.StackLayout.prototype.addItems = function ( items, index ) {
+ // Update the visibility
+ this.updateHiddenState( items, this.currentItem );
+
+ // Mixin method
+ OO.ui.mixin.GroupElement.prototype.addItems.call( this, items, index );
+
+ if ( !this.currentItem && items.length ) {
+ this.setItem( items[ 0 ] );
+ }
+
+ return this;
+};
+
+/**
+ * Remove the specified panels from the stack layout.
+ *
+ * Removed panels are detached from the DOM, not removed, so that they may be reused. To remove all panels,
+ * you may wish to use the #clearItems method instead.
+ *
+ * @param {OO.ui.Layout[]} items Panels to remove
+ * @chainable
+ * @fires set
+ */
+OO.ui.StackLayout.prototype.removeItems = function ( items ) {
+ // Mixin method
+ OO.ui.mixin.GroupElement.prototype.removeItems.call( this, items );
+
+ if ( items.indexOf( this.currentItem ) !== -1 ) {
+ if ( this.items.length ) {
+ this.setItem( this.items[ 0 ] );
+ } else {
+ this.unsetCurrentItem();
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Clear all panels from the stack layout.
+ *
+ * Cleared panels are detached from the DOM, not removed, so that they may be reused. To remove only
+ * a subset of panels, use the #removeItems method.
+ *
+ * @chainable
+ * @fires set
+ */
+OO.ui.StackLayout.prototype.clearItems = function () {
+ this.unsetCurrentItem();
+ OO.ui.mixin.GroupElement.prototype.clearItems.call( this );
+
+ return this;
+};
+
+/**
+ * Show the specified panel.
+ *
+ * If another panel is currently displayed, it will be hidden.
+ *
+ * @param {OO.ui.Layout} item Panel to show
+ * @chainable
+ * @fires set
+ */
+OO.ui.StackLayout.prototype.setItem = function ( item ) {
+ if ( item !== this.currentItem ) {
+ this.updateHiddenState( this.items, item );
+
+ if ( this.items.indexOf( item ) !== -1 ) {
+ this.currentItem = item;
+ this.emit( 'set', item );
+ } else {
+ this.unsetCurrentItem();
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Update the visibility of all items in case of non-continuous view.
+ *
+ * Ensure all items are hidden except for the selected one.
+ * This method does nothing when the stack is continuous.
+ *
+ * @private
+ * @param {OO.ui.Layout[]} items Item list iterate over
+ * @param {OO.ui.Layout} [selectedItem] Selected item to show
+ */
+OO.ui.StackLayout.prototype.updateHiddenState = function ( items, selectedItem ) {
+ var i, len;
+
+ if ( !this.continuous ) {
+ for ( i = 0, len = items.length; i < len; i++ ) {
+ if ( !selectedItem || selectedItem !== items[ i ] ) {
+ items[ i ].$element.addClass( 'oo-ui-element-hidden' );
+ items[ i ].$element.attr( 'aria-hidden', 'true' );
+ }
+ }
+ if ( selectedItem ) {
+ selectedItem.$element.removeClass( 'oo-ui-element-hidden' );
+ selectedItem.$element.removeAttr( 'aria-hidden' );
+ }
+ }
+};
+
+/**
+ * MenuLayouts combine a menu and a content {@link OO.ui.PanelLayout panel}. The menu is positioned relative to the content (after, before, top, or bottom)
+ * and its size is customized with the #menuSize config. The content area will fill all remaining space.
+ *
+ * @example
+ * var menuLayout = new OO.ui.MenuLayout( {
+ * position: 'top'
+ * } ),
+ * menuPanel = new OO.ui.PanelLayout( { padded: true, expanded: true, scrollable: true } ),
+ * contentPanel = new OO.ui.PanelLayout( { padded: true, expanded: true, scrollable: true } ),
+ * select = new OO.ui.SelectWidget( {
+ * items: [
+ * new OO.ui.OptionWidget( {
+ * data: 'before',
+ * label: 'Before',
+ * } ),
+ * new OO.ui.OptionWidget( {
+ * data: 'after',
+ * label: 'After',
+ * } ),
+ * new OO.ui.OptionWidget( {
+ * data: 'top',
+ * label: 'Top',
+ * } ),
+ * new OO.ui.OptionWidget( {
+ * data: 'bottom',
+ * label: 'Bottom',
+ * } )
+ * ]
+ * } ).on( 'select', function ( item ) {
+ * menuLayout.setMenuPosition( item.getData() );
+ * } );
+ *
+ * menuLayout.$menu.append(
+ * menuPanel.$element.append( '<b>Menu panel</b>', select.$element )
+ * );
+ * menuLayout.$content.append(
+ * contentPanel.$element.append( '<b>Content panel</b>', '<p>Note that the menu is positioned relative to the content panel: top, bottom, after, before.</p>')
+ * );
+ * $( 'body' ).append( menuLayout.$element );
+ *
+ * If menu size needs to be overridden, it can be accomplished using CSS similar to the snippet
+ * below. MenuLayout's CSS will override the appropriate values with 'auto' or '0' to display the
+ * menu correctly. If `menuPosition` is known beforehand, CSS rules corresponding to other positions
+ * may be omitted.
+ *
+ * .oo-ui-menuLayout-menu {
+ * height: 200px;
+ * width: 200px;
+ * }
+ * .oo-ui-menuLayout-content {
+ * top: 200px;
+ * left: 200px;
+ * right: 200px;
+ * bottom: 200px;
+ * }
+ *
+ * @class
+ * @extends OO.ui.Layout
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [showMenu=true] Show menu
+ * @cfg {string} [menuPosition='before'] Position of menu: `top`, `after`, `bottom` or `before`
+ */
+OO.ui.MenuLayout = function OoUiMenuLayout( config ) {
+ // Configuration initialization
+ config = $.extend( {
+ showMenu: true,
+ menuPosition: 'before'
+ }, config );
+
+ // Parent constructor
+ OO.ui.MenuLayout.parent.call( this, config );
+
+ /**
+ * Menu DOM node
+ *
+ * @property {jQuery}
+ */
+ this.$menu = $( '<div>' );
+ /**
+ * Content DOM node
+ *
+ * @property {jQuery}
+ */
+ this.$content = $( '<div>' );
+
+ // Initialization
+ this.$menu
+ .addClass( 'oo-ui-menuLayout-menu' );
+ this.$content.addClass( 'oo-ui-menuLayout-content' );
+ this.$element
+ .addClass( 'oo-ui-menuLayout' )
+ .append( this.$content, this.$menu );
+ this.setMenuPosition( config.menuPosition );
+ this.toggleMenu( config.showMenu );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MenuLayout, OO.ui.Layout );
+
+/* Methods */
+
+/**
+ * Toggle menu.
+ *
+ * @param {boolean} showMenu Show menu, omit to toggle
+ * @chainable
+ */
+OO.ui.MenuLayout.prototype.toggleMenu = function ( showMenu ) {
+ showMenu = showMenu === undefined ? !this.showMenu : !!showMenu;
+
+ if ( this.showMenu !== showMenu ) {
+ this.showMenu = showMenu;
+ this.$element
+ .toggleClass( 'oo-ui-menuLayout-showMenu', this.showMenu )
+ .toggleClass( 'oo-ui-menuLayout-hideMenu', !this.showMenu );
+ this.$menu.attr( 'aria-hidden', this.showMenu ? 'false' : 'true' );
+ }
+
+ return this;
+};
+
+/**
+ * Check if menu is visible
+ *
+ * @return {boolean} Menu is visible
+ */
+OO.ui.MenuLayout.prototype.isMenuVisible = function () {
+ return this.showMenu;
+};
+
+/**
+ * Set menu position.
+ *
+ * @param {string} position Position of menu, either `top`, `after`, `bottom` or `before`
+ * @throws {Error} If position value is not supported
+ * @chainable
+ */
+OO.ui.MenuLayout.prototype.setMenuPosition = function ( position ) {
+ this.$element.removeClass( 'oo-ui-menuLayout-' + this.menuPosition );
+ this.menuPosition = position;
+ this.$element.addClass( 'oo-ui-menuLayout-' + position );
+
+ return this;
+};
+
+/**
+ * Get menu position.
+ *
+ * @return {string} Menu position
+ */
+OO.ui.MenuLayout.prototype.getMenuPosition = function () {
+ return this.menuPosition;
+};
+
+/**
+ * BookletLayouts contain {@link OO.ui.PageLayout page layouts} as well as
+ * an {@link OO.ui.OutlineSelectWidget outline} that allows users to easily navigate
+ * through the pages and select which one to display. By default, only one page is
+ * displayed at a time and the outline is hidden. When a user navigates to a new page,
+ * the booklet layout automatically focuses on the first focusable element, unless the
+ * default setting is changed. Optionally, booklets can be configured to show
+ * {@link OO.ui.OutlineControlsWidget controls} for adding, moving, and removing items.
+ *
+ * @example
+ * // Example of a BookletLayout that contains two PageLayouts.
+ *
+ * function PageOneLayout( name, config ) {
+ * PageOneLayout.parent.call( this, name, config );
+ * this.$element.append( '<p>First page</p><p>(This booklet has an outline, displayed on the left)</p>' );
+ * }
+ * OO.inheritClass( PageOneLayout, OO.ui.PageLayout );
+ * PageOneLayout.prototype.setupOutlineItem = function () {
+ * this.outlineItem.setLabel( 'Page One' );
+ * };
+ *
+ * function PageTwoLayout( name, config ) {
+ * PageTwoLayout.parent.call( this, name, config );
+ * this.$element.append( '<p>Second page</p>' );
+ * }
+ * OO.inheritClass( PageTwoLayout, OO.ui.PageLayout );
+ * PageTwoLayout.prototype.setupOutlineItem = function () {
+ * this.outlineItem.setLabel( 'Page Two' );
+ * };
+ *
+ * var page1 = new PageOneLayout( 'one' ),
+ * page2 = new PageTwoLayout( 'two' );
+ *
+ * var booklet = new OO.ui.BookletLayout( {
+ * outlined: true
+ * } );
+ *
+ * booklet.addPages ( [ page1, page2 ] );
+ * $( 'body' ).append( booklet.$element );
+ *
+ * @class
+ * @extends OO.ui.MenuLayout
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [continuous=false] Show all pages, one after another
+ * @cfg {boolean} [autoFocus=true] Focus on the first focusable element when a new page is displayed. Disabled on mobile.
+ * @cfg {boolean} [outlined=false] Show the outline. The outline is used to navigate through the pages of the booklet.
+ * @cfg {boolean} [editable=false] Show controls for adding, removing and reordering pages
+ */
+OO.ui.BookletLayout = function OoUiBookletLayout( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.BookletLayout.parent.call( this, config );
+
+ // Properties
+ this.currentPageName = null;
+ this.pages = {};
+ this.ignoreFocus = false;
+ this.stackLayout = new OO.ui.StackLayout( { continuous: !!config.continuous } );
+ this.$content.append( this.stackLayout.$element );
+ this.autoFocus = config.autoFocus === undefined || !!config.autoFocus;
+ this.outlineVisible = false;
+ this.outlined = !!config.outlined;
+ if ( this.outlined ) {
+ this.editable = !!config.editable;
+ this.outlineControlsWidget = null;
+ this.outlineSelectWidget = new OO.ui.OutlineSelectWidget();
+ this.outlinePanel = new OO.ui.PanelLayout( { scrollable: true } );
+ this.$menu.append( this.outlinePanel.$element );
+ this.outlineVisible = true;
+ if ( this.editable ) {
+ this.outlineControlsWidget = new OO.ui.OutlineControlsWidget(
+ this.outlineSelectWidget
+ );
+ }
+ }
+ this.toggleMenu( this.outlined );
+
+ // Events
+ this.stackLayout.connect( this, { set: 'onStackLayoutSet' } );
+ if ( this.outlined ) {
+ this.outlineSelectWidget.connect( this, { select: 'onOutlineSelectWidgetSelect' } );
+ this.scrolling = false;
+ this.stackLayout.connect( this, { visibleItemChange: 'onStackLayoutVisibleItemChange' } );
+ }
+ if ( this.autoFocus ) {
+ // Event 'focus' does not bubble, but 'focusin' does
+ this.stackLayout.$element.on( 'focusin', this.onStackLayoutFocus.bind( this ) );
+ }
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-bookletLayout' );
+ this.stackLayout.$element.addClass( 'oo-ui-bookletLayout-stackLayout' );
+ if ( this.outlined ) {
+ this.outlinePanel.$element
+ .addClass( 'oo-ui-bookletLayout-outlinePanel' )
+ .append( this.outlineSelectWidget.$element );
+ if ( this.editable ) {
+ this.outlinePanel.$element
+ .addClass( 'oo-ui-bookletLayout-outlinePanel-editable' )
+ .append( this.outlineControlsWidget.$element );
+ }
+ }
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.BookletLayout, OO.ui.MenuLayout );
+
+/* Events */
+
+/**
+ * A 'set' event is emitted when a page is {@link #setPage set} to be displayed by the booklet layout.
+ * @event set
+ * @param {OO.ui.PageLayout} page Current page
+ */
+
+/**
+ * An 'add' event is emitted when pages are {@link #addPages added} to the booklet layout.
+ *
+ * @event add
+ * @param {OO.ui.PageLayout[]} page Added pages
+ * @param {number} index Index pages were added at
+ */
+
+/**
+ * A 'remove' event is emitted when pages are {@link #clearPages cleared} or
+ * {@link #removePages removed} from the booklet.
+ *
+ * @event remove
+ * @param {OO.ui.PageLayout[]} pages Removed pages
+ */
+
+/* Methods */
+
+/**
+ * Handle stack layout focus.
+ *
+ * @private
+ * @param {jQuery.Event} e Focusin event
+ */
+OO.ui.BookletLayout.prototype.onStackLayoutFocus = function ( e ) {
+ var name, $target;
+
+ // Find the page that an element was focused within
+ $target = $( e.target ).closest( '.oo-ui-pageLayout' );
+ for ( name in this.pages ) {
+ // Check for page match, exclude current page to find only page changes
+ if ( this.pages[ name ].$element[ 0 ] === $target[ 0 ] && name !== this.currentPageName ) {
+ this.setPage( name );
+ break;
+ }
+ }
+};
+
+/**
+ * Handle visibleItemChange events from the stackLayout
+ *
+ * The next visible page is set as the current page by selecting it
+ * in the outline
+ *
+ * @param {OO.ui.PageLayout} page The next visible page in the layout
+ */
+OO.ui.BookletLayout.prototype.onStackLayoutVisibleItemChange = function ( page ) {
+ // Set a flag to so that the resulting call to #onStackLayoutSet doesn't
+ // try and scroll the item into view again.
+ this.scrolling = true;
+ this.outlineSelectWidget.selectItemByData( page.getName() );
+ this.scrolling = false;
+};
+
+/**
+ * Handle stack layout set events.
+ *
+ * @private
+ * @param {OO.ui.PanelLayout|null} page The page panel that is now the current panel
+ */
+OO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) {
+ var layout = this;
+ if ( !this.scrolling && page ) {
+ page.scrollElementIntoView().done( function () {
+ if ( layout.autoFocus && !OO.ui.isMobile() ) {
+ layout.focus();
+ }
+ } );
+ }
+};
+
+/**
+ * Focus the first input in the current page.
+ *
+ * If no page is selected, the first selectable page will be selected.
+ * If the focus is already in an element on the current page, nothing will happen.
+ *
+ * @param {number} [itemIndex] A specific item to focus on
+ */
+OO.ui.BookletLayout.prototype.focus = function ( itemIndex ) {
+ var page,
+ items = this.stackLayout.getItems();
+
+ if ( itemIndex !== undefined && items[ itemIndex ] ) {
+ page = items[ itemIndex ];
+ } else {
+ page = this.stackLayout.getCurrentItem();
+ }
+
+ if ( !page && this.outlined ) {
+ this.selectFirstSelectablePage();
+ page = this.stackLayout.getCurrentItem();
+ }
+ if ( !page ) {
+ return;
+ }
+ // Only change the focus if is not already in the current page
+ if ( !OO.ui.contains( page.$element[ 0 ], this.getElementDocument().activeElement, true ) ) {
+ page.focus();
+ }
+};
+
+/**
+ * Find the first focusable input in the booklet layout and focus
+ * on it.
+ */
+OO.ui.BookletLayout.prototype.focusFirstFocusable = function () {
+ OO.ui.findFocusable( this.stackLayout.$element ).focus();
+};
+
+/**
+ * Handle outline widget select events.
+ *
+ * @private
+ * @param {OO.ui.OptionWidget|null} item Selected item
+ */
+OO.ui.BookletLayout.prototype.onOutlineSelectWidgetSelect = function ( item ) {
+ if ( item ) {
+ this.setPage( item.getData() );
+ }
+};
+
+/**
+ * Check if booklet has an outline.
+ *
+ * @return {boolean} Booklet has an outline
+ */
+OO.ui.BookletLayout.prototype.isOutlined = function () {
+ return this.outlined;
+};
+
+/**
+ * Check if booklet has editing controls.
+ *
+ * @return {boolean} Booklet is editable
+ */
+OO.ui.BookletLayout.prototype.isEditable = function () {
+ return this.editable;
+};
+
+/**
+ * Check if booklet has a visible outline.
+ *
+ * @return {boolean} Outline is visible
+ */
+OO.ui.BookletLayout.prototype.isOutlineVisible = function () {
+ return this.outlined && this.outlineVisible;
+};
+
+/**
+ * Hide or show the outline.
+ *
+ * @param {boolean} [show] Show outline, omit to invert current state
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.toggleOutline = function ( show ) {
+ var booklet = this;
+
+ if ( this.outlined ) {
+ show = show === undefined ? !this.outlineVisible : !!show;
+ this.outlineVisible = show;
+ this.toggleMenu( show );
+ if ( show && this.editable ) {
+ // HACK: Kill dumb scrollbars when the sidebar stops animating, see T161798. Only necessary when
+ // outline controls are present, delay matches transition on `.oo-ui-menuLayout-menu`.
+ setTimeout( function () {
+ OO.ui.Element.static.reconsiderScrollbars( booklet.outlinePanel.$element[ 0 ] );
+ }, 200 );
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Find the page closest to the specified page.
+ *
+ * @param {OO.ui.PageLayout} page Page to use as a reference point
+ * @return {OO.ui.PageLayout|null} Page closest to the specified page
+ */
+OO.ui.BookletLayout.prototype.findClosestPage = function ( page ) {
+ var next, prev, level,
+ pages = this.stackLayout.getItems(),
+ index = pages.indexOf( page );
+
+ if ( index !== -1 ) {
+ next = pages[ index + 1 ];
+ prev = pages[ index - 1 ];
+ // Prefer adjacent pages at the same level
+ if ( this.outlined ) {
+ level = this.outlineSelectWidget.getItemFromData( page.getName() ).getLevel();
+ if (
+ prev &&
+ level === this.outlineSelectWidget.getItemFromData( prev.getName() ).getLevel()
+ ) {
+ return prev;
+ }
+ if (
+ next &&
+ level === this.outlineSelectWidget.getItemFromData( next.getName() ).getLevel()
+ ) {
+ return next;
+ }
+ }
+ }
+ return prev || next || null;
+};
+
+/**
+ * Get the page closest to the specified page.
+ *
+ * @deprecated 0.22.6 Use {@link OO.ui.BookletLayout#findClosestPage} instead.
+ * @param {OO.ui.PageLayout} page Page to use as a reference point
+ * @return {OO.ui.PageLayout|null} Page closest to the specified page
+ */
+OO.ui.BookletLayout.prototype.getClosestPage = function ( page ) {
+ OO.ui.warnDeprecation( 'BookletLayout#getClosestPage: Deprecated function. Use findClosestPage instead. See T76630.' );
+ return this.findClosestPage( page );
+};
+
+/**
+ * Get the outline widget.
+ *
+ * If the booklet is not outlined, the method will return `null`.
+ *
+ * @return {OO.ui.OutlineSelectWidget|null} Outline widget, or null if the booklet is not outlined
+ */
+OO.ui.BookletLayout.prototype.getOutline = function () {
+ return this.outlineSelectWidget;
+};
+
+/**
+ * Get the outline controls widget.
+ *
+ * If the outline is not editable, the method will return `null`.
+ *
+ * @return {OO.ui.OutlineControlsWidget|null} The outline controls widget.
+ */
+OO.ui.BookletLayout.prototype.getOutlineControls = function () {
+ return this.outlineControlsWidget;
+};
+
+/**
+ * Get a page by its symbolic name.
+ *
+ * @param {string} name Symbolic name of page
+ * @return {OO.ui.PageLayout|undefined} Page, if found
+ */
+OO.ui.BookletLayout.prototype.getPage = function ( name ) {
+ return this.pages[ name ];
+};
+
+/**
+ * Get the current page.
+ *
+ * @return {OO.ui.PageLayout|undefined} Current page, if found
+ */
+OO.ui.BookletLayout.prototype.getCurrentPage = function () {
+ var name = this.getCurrentPageName();
+ return name ? this.getPage( name ) : undefined;
+};
+
+/**
+ * Get the symbolic name of the current page.
+ *
+ * @return {string|null} Symbolic name of the current page
+ */
+OO.ui.BookletLayout.prototype.getCurrentPageName = function () {
+ return this.currentPageName;
+};
+
+/**
+ * Add pages to the booklet layout
+ *
+ * When pages are added with the same names as existing pages, the existing pages will be
+ * automatically removed before the new pages are added.
+ *
+ * @param {OO.ui.PageLayout[]} pages Pages to add
+ * @param {number} index Index of the insertion point
+ * @fires add
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.addPages = function ( pages, index ) {
+ var i, len, name, page, item, currentIndex,
+ stackLayoutPages = this.stackLayout.getItems(),
+ remove = [],
+ items = [];
+
+ // Remove pages with same names
+ for ( i = 0, len = pages.length; i < len; i++ ) {
+ page = pages[ i ];
+ name = page.getName();
+
+ if ( Object.prototype.hasOwnProperty.call( this.pages, name ) ) {
+ // Correct the insertion index
+ currentIndex = stackLayoutPages.indexOf( this.pages[ name ] );
+ if ( currentIndex !== -1 && currentIndex + 1 < index ) {
+ index--;
+ }
+ remove.push( this.pages[ name ] );
+ }
+ }
+ if ( remove.length ) {
+ this.removePages( remove );
+ }
+
+ // Add new pages
+ for ( i = 0, len = pages.length; i < len; i++ ) {
+ page = pages[ i ];
+ name = page.getName();
+ this.pages[ page.getName() ] = page;
+ if ( this.outlined ) {
+ item = new OO.ui.OutlineOptionWidget( { data: name } );
+ page.setOutlineItem( item );
+ items.push( item );
+ }
+ }
+
+ if ( this.outlined && items.length ) {
+ this.outlineSelectWidget.addItems( items, index );
+ this.selectFirstSelectablePage();
+ }
+ this.stackLayout.addItems( pages, index );
+ this.emit( 'add', pages, index );
+
+ return this;
+};
+
+/**
+ * Remove the specified pages from the booklet layout.
+ *
+ * To remove all pages from the booklet, you may wish to use the #clearPages method instead.
+ *
+ * @param {OO.ui.PageLayout[]} pages An array of pages to remove
+ * @fires remove
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.removePages = function ( pages ) {
+ var i, len, name, page,
+ items = [];
+
+ for ( i = 0, len = pages.length; i < len; i++ ) {
+ page = pages[ i ];
+ name = page.getName();
+ delete this.pages[ name ];
+ if ( this.outlined ) {
+ items.push( this.outlineSelectWidget.getItemFromData( name ) );
+ page.setOutlineItem( null );
+ }
+ }
+ if ( this.outlined && items.length ) {
+ this.outlineSelectWidget.removeItems( items );
+ this.selectFirstSelectablePage();
+ }
+ this.stackLayout.removeItems( pages );
+ this.emit( 'remove', pages );
+
+ return this;
+};
+
+/**
+ * Clear all pages from the booklet layout.
+ *
+ * To remove only a subset of pages from the booklet, use the #removePages method.
+ *
+ * @fires remove
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.clearPages = function () {
+ var i, len,
+ pages = this.stackLayout.getItems();
+
+ this.pages = {};
+ this.currentPageName = null;
+ if ( this.outlined ) {
+ this.outlineSelectWidget.clearItems();
+ for ( i = 0, len = pages.length; i < len; i++ ) {
+ pages[ i ].setOutlineItem( null );
+ }
+ }
+ this.stackLayout.clearItems();
+
+ this.emit( 'remove', pages );
+
+ return this;
+};
+
+/**
+ * Set the current page by symbolic name.
+ *
+ * @fires set
+ * @param {string} name Symbolic name of page
+ */
+OO.ui.BookletLayout.prototype.setPage = function ( name ) {
+ var selectedItem,
+ $focused,
+ page = this.pages[ name ],
+ previousPage = this.currentPageName && this.pages[ this.currentPageName ];
+
+ if ( name !== this.currentPageName ) {
+ if ( this.outlined ) {
+ selectedItem = this.outlineSelectWidget.getSelectedItem();
+ if ( selectedItem && selectedItem.getData() !== name ) {
+ this.outlineSelectWidget.selectItemByData( name );
+ }
+ }
+ if ( page ) {
+ if ( previousPage ) {
+ previousPage.setActive( false );
+ // Blur anything focused if the next page doesn't have anything focusable.
+ // This is not needed if the next page has something focusable (because once it is focused
+ // this blur happens automatically). If the layout is non-continuous, this check is
+ // meaningless because the next page is not visible yet and thus can't hold focus.
+ if (
+ this.autoFocus &&
+ !OO.ui.isMobile() &&
+ this.stackLayout.continuous &&
+ OO.ui.findFocusable( page.$element ).length !== 0
+ ) {
+ $focused = previousPage.$element.find( ':focus' );
+ if ( $focused.length ) {
+ $focused[ 0 ].blur();
+ }
+ }
+ }
+ this.currentPageName = name;
+ page.setActive( true );
+ this.stackLayout.setItem( page );
+ if ( !this.stackLayout.continuous && previousPage ) {
+ // This should not be necessary, since any inputs on the previous page should have been
+ // blurred when it was hidden, but browsers are not very consistent about this.
+ $focused = previousPage.$element.find( ':focus' );
+ if ( $focused.length ) {
+ $focused[ 0 ].blur();
+ }
+ }
+ this.emit( 'set', page );
+ }
+ }
+};
+
+/**
+ * Select the first selectable page.
+ *
+ * @chainable
+ */
+OO.ui.BookletLayout.prototype.selectFirstSelectablePage = function () {
+ if ( !this.outlineSelectWidget.getSelectedItem() ) {
+ this.outlineSelectWidget.selectItem( this.outlineSelectWidget.getFirstSelectableItem() );
+ }
+
+ return this;
+};
+
+/**
+ * IndexLayouts contain {@link OO.ui.TabPanelLayout tab panel layouts} as well as
+ * {@link OO.ui.TabSelectWidget tabs} that allow users to easily navigate through the tab panels and
+ * select which one to display. By default, only one tab panel is displayed at a time. When a user
+ * navigates to a new tab panel, the index layout automatically focuses on the first focusable element,
+ * unless the default setting is changed.
+ *
+ * TODO: This class is similar to BookletLayout, we may want to refactor to reduce duplication
+ *
+ * @example
+ * // Example of a IndexLayout that contains two TabPanelLayouts.
+ *
+ * function TabPanelOneLayout( name, config ) {
+ * TabPanelOneLayout.parent.call( this, name, config );
+ * this.$element.append( '<p>First tab panel</p>' );
+ * }
+ * OO.inheritClass( TabPanelOneLayout, OO.ui.TabPanelLayout );
+ * TabPanelOneLayout.prototype.setupTabItem = function () {
+ * this.tabItem.setLabel( 'Tab panel one' );
+ * };
+ *
+ * var tabPanel1 = new TabPanelOneLayout( 'one' ),
+ * tabPanel2 = new OO.ui.TabPanelLayout( 'two', { label: 'Tab panel two' } );
+ *
+ * tabPanel2.$element.append( '<p>Second tab panel</p>' );
+ *
+ * var index = new OO.ui.IndexLayout();
+ *
+ * index.addTabPanels ( [ tabPanel1, tabPanel2 ] );
+ * $( 'body' ).append( index.$element );
+ *
+ * @class
+ * @extends OO.ui.MenuLayout
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [continuous=false] Show all tab panels, one after another
+ * @cfg {boolean} [expanded=true] Expand the content panel to fill the entire parent element.
+ * @cfg {boolean} [autoFocus=true] Focus on the first focusable element when a new tab panel is displayed. Disabled on mobile.
+ */
+OO.ui.IndexLayout = function OoUiIndexLayout( config ) {
+ // Configuration initialization
+ config = $.extend( {}, config, { menuPosition: 'top' } );
+
+ // Parent constructor
+ OO.ui.IndexLayout.parent.call( this, config );
+
+ // Properties
+ this.currentTabPanelName = null;
+ this.tabPanels = {};
+
+ this.ignoreFocus = false;
+ this.stackLayout = new OO.ui.StackLayout( {
+ continuous: !!config.continuous,
+ expanded: config.expanded
+ } );
+ this.$content.append( this.stackLayout.$element );
+ this.autoFocus = config.autoFocus === undefined || !!config.autoFocus;
+
+ this.tabSelectWidget = new OO.ui.TabSelectWidget();
+ this.tabPanel = new OO.ui.PanelLayout();
+ this.$menu.append( this.tabPanel.$element );
+
+ this.toggleMenu( true );
+
+ // Events
+ this.stackLayout.connect( this, { set: 'onStackLayoutSet' } );
+ this.tabSelectWidget.connect( this, { select: 'onTabSelectWidgetSelect' } );
+ if ( this.autoFocus ) {
+ // Event 'focus' does not bubble, but 'focusin' does
+ this.stackLayout.$element.on( 'focusin', this.onStackLayoutFocus.bind( this ) );
+ }
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-indexLayout' );
+ this.stackLayout.$element.addClass( 'oo-ui-indexLayout-stackLayout' );
+ this.tabPanel.$element
+ .addClass( 'oo-ui-indexLayout-tabPanel' )
+ .append( this.tabSelectWidget.$element );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.IndexLayout, OO.ui.MenuLayout );
+
+/* Events */
+
+/**
+ * A 'set' event is emitted when a tab panel is {@link #setTabPanel set} to be displayed by the index layout.
+ * @event set
+ * @param {OO.ui.TabPanelLayout} tabPanel Current tab panel
+ */
+
+/**
+ * An 'add' event is emitted when tab panels are {@link #addTabPanels added} to the index layout.
+ *
+ * @event add
+ * @param {OO.ui.TabPanelLayout[]} tabPanel Added tab panels
+ * @param {number} index Index tab panels were added at
+ */
+
+/**
+ * A 'remove' event is emitted when tab panels are {@link #clearTabPanels cleared} or
+ * {@link #removeTabPanels removed} from the index.
+ *
+ * @event remove
+ * @param {OO.ui.TabPanelLayout[]} tabPanel Removed tab panels
+ */
+
+/* Methods */
+
+/**
+ * Handle stack layout focus.
+ *
+ * @private
+ * @param {jQuery.Event} e Focusing event
+ */
+OO.ui.IndexLayout.prototype.onStackLayoutFocus = function ( e ) {
+ var name, $target;
+
+ // Find the tab panel that an element was focused within
+ $target = $( e.target ).closest( '.oo-ui-tabPanelLayout' );
+ for ( name in this.tabPanels ) {
+ // Check for tab panel match, exclude current tab panel to find only tab panel changes
+ if ( this.tabPanels[ name ].$element[ 0 ] === $target[ 0 ] && name !== this.currentTabPanelName ) {
+ this.setTabPanel( name );
+ break;
+ }
+ }
+};
+
+/**
+ * Handle stack layout set events.
+ *
+ * @private
+ * @param {OO.ui.PanelLayout|null} tabPanel The tab panel that is now the current panel
+ */
+OO.ui.IndexLayout.prototype.onStackLayoutSet = function ( tabPanel ) {
+ var layout = this;
+ if ( tabPanel ) {
+ tabPanel.scrollElementIntoView().done( function () {
+ if ( layout.autoFocus && !OO.ui.isMobile() ) {
+ layout.focus();
+ }
+ } );
+ }
+};
+
+/**
+ * Focus the first input in the current tab panel.
+ *
+ * If no tab panel is selected, the first selectable tab panel will be selected.
+ * If the focus is already in an element on the current tab panel, nothing will happen.
+ *
+ * @param {number} [itemIndex] A specific item to focus on
+ */
+OO.ui.IndexLayout.prototype.focus = function ( itemIndex ) {
+ var tabPanel,
+ items = this.stackLayout.getItems();
+
+ if ( itemIndex !== undefined && items[ itemIndex ] ) {
+ tabPanel = items[ itemIndex ];
+ } else {
+ tabPanel = this.stackLayout.getCurrentItem();
+ }
+
+ if ( !tabPanel ) {
+ this.selectFirstSelectableTabPanel();
+ tabPanel = this.stackLayout.getCurrentItem();
+ }
+ if ( !tabPanel ) {
+ return;
+ }
+ // Only change the focus if is not already in the current page
+ if ( !OO.ui.contains( tabPanel.$element[ 0 ], this.getElementDocument().activeElement, true ) ) {
+ tabPanel.focus();
+ }
+};
+
+/**
+ * Find the first focusable input in the index layout and focus
+ * on it.
+ */
+OO.ui.IndexLayout.prototype.focusFirstFocusable = function () {
+ OO.ui.findFocusable( this.stackLayout.$element ).focus();
+};
+
+/**
+ * Handle tab widget select events.
+ *
+ * @private
+ * @param {OO.ui.OptionWidget|null} item Selected item
+ */
+OO.ui.IndexLayout.prototype.onTabSelectWidgetSelect = function ( item ) {
+ if ( item ) {
+ this.setTabPanel( item.getData() );
+ }
+};
+
+/**
+ * Get the tab panel closest to the specified tab panel.
+ *
+ * @param {OO.ui.TabPanelLayout} tabPanel Tab panel to use as a reference point
+ * @return {OO.ui.TabPanelLayout|null} Tab panel closest to the specified
+ */
+OO.ui.IndexLayout.prototype.getClosestTabPanel = function ( tabPanel ) {
+ var next, prev, level,
+ tabPanels = this.stackLayout.getItems(),
+ index = tabPanels.indexOf( tabPanel );
+
+ if ( index !== -1 ) {
+ next = tabPanels[ index + 1 ];
+ prev = tabPanels[ index - 1 ];
+ // Prefer adjacent tab panels at the same level
+ level = this.tabSelectWidget.getItemFromData( tabPanel.getName() ).getLevel();
+ if (
+ prev &&
+ level === this.tabSelectWidget.getItemFromData( prev.getName() ).getLevel()
+ ) {
+ return prev;
+ }
+ if (
+ next &&
+ level === this.tabSelectWidget.getItemFromData( next.getName() ).getLevel()
+ ) {
+ return next;
+ }
+ }
+ return prev || next || null;
+};
+
+/**
+ * Get the tabs widget.
+ *
+ * @return {OO.ui.TabSelectWidget} Tabs widget
+ */
+OO.ui.IndexLayout.prototype.getTabs = function () {
+ return this.tabSelectWidget;
+};
+
+/**
+ * Get a tab panel by its symbolic name.
+ *
+ * @param {string} name Symbolic name of tab panel
+ * @return {OO.ui.TabPanelLayout|undefined} Tab panel, if found
+ */
+OO.ui.IndexLayout.prototype.getTabPanel = function ( name ) {
+ return this.tabPanels[ name ];
+};
+
+/**
+ * Get the current tab panel.
+ *
+ * @return {OO.ui.TabPanelLayout|undefined} Current tab panel, if found
+ */
+OO.ui.IndexLayout.prototype.getCurrentTabPanel = function () {
+ var name = this.getCurrentTabPanelName();
+ return name ? this.getTabPanel( name ) : undefined;
+};
+
+/**
+ * Get the symbolic name of the current tab panel.
+ *
+ * @return {string|null} Symbolic name of the current tab panel
+ */
+OO.ui.IndexLayout.prototype.getCurrentTabPanelName = function () {
+ return this.currentTabPanelName;
+};
+
+/**
+ * Add tab panels to the index layout
+ *
+ * When tab panels are added with the same names as existing tab panels, the existing tab panels
+ * will be automatically removed before the new tab panels are added.
+ *
+ * @param {OO.ui.TabPanelLayout[]} tabPanels Tab panels to add
+ * @param {number} index Index of the insertion point
+ * @fires add
+ * @chainable
+ */
+OO.ui.IndexLayout.prototype.addTabPanels = function ( tabPanels, index ) {
+ var i, len, name, tabPanel, item, currentIndex,
+ stackLayoutTabPanels = this.stackLayout.getItems(),
+ remove = [],
+ items = [];
+
+ // Remove tab panels with same names
+ for ( i = 0, len = tabPanels.length; i < len; i++ ) {
+ tabPanel = tabPanels[ i ];
+ name = tabPanel.getName();
+
+ if ( Object.prototype.hasOwnProperty.call( this.tabPanels, name ) ) {
+ // Correct the insertion index
+ currentIndex = stackLayoutTabPanels.indexOf( this.tabPanels[ name ] );
+ if ( currentIndex !== -1 && currentIndex + 1 < index ) {
+ index--;
+ }
+ remove.push( this.tabPanels[ name ] );
+ }
+ }
+ if ( remove.length ) {
+ this.removeTabPanels( remove );
+ }
+
+ // Add new tab panels
+ for ( i = 0, len = tabPanels.length; i < len; i++ ) {
+ tabPanel = tabPanels[ i ];
+ name = tabPanel.getName();
+ this.tabPanels[ tabPanel.getName() ] = tabPanel;
+ item = new OO.ui.TabOptionWidget( { data: name } );
+ tabPanel.setTabItem( item );
+ items.push( item );
+ }
+
+ if ( items.length ) {
+ this.tabSelectWidget.addItems( items, index );
+ this.selectFirstSelectableTabPanel();
+ }
+ this.stackLayout.addItems( tabPanels, index );
+ this.emit( 'add', tabPanels, index );
+
+ return this;
+};
+
+/**
+ * Remove the specified tab panels from the index layout.
+ *
+ * To remove all tab panels from the index, you may wish to use the #clearTabPanels method instead.
+ *
+ * @param {OO.ui.TabPanelLayout[]} tabPanels An array of tab panels to remove
+ * @fires remove
+ * @chainable
+ */
+OO.ui.IndexLayout.prototype.removeTabPanels = function ( tabPanels ) {
+ var i, len, name, tabPanel,
+ items = [];
+
+ for ( i = 0, len = tabPanels.length; i < len; i++ ) {
+ tabPanel = tabPanels[ i ];
+ name = tabPanel.getName();
+ delete this.tabPanels[ name ];
+ items.push( this.tabSelectWidget.getItemFromData( name ) );
+ tabPanel.setTabItem( null );
+ }
+ if ( items.length ) {
+ this.tabSelectWidget.removeItems( items );
+ this.selectFirstSelectableTabPanel();
+ }
+ this.stackLayout.removeItems( tabPanels );
+ this.emit( 'remove', tabPanels );
+
+ return this;
+};
+
+/**
+ * Clear all tab panels from the index layout.
+ *
+ * To remove only a subset of tab panels from the index, use the #removeTabPanels method.
+ *
+ * @fires remove
+ * @chainable
+ */
+OO.ui.IndexLayout.prototype.clearTabPanels = function () {
+ var i, len,
+ tabPanels = this.stackLayout.getItems();
+
+ this.tabPanels = {};
+ this.currentTabPanelName = null;
+ this.tabSelectWidget.clearItems();
+ for ( i = 0, len = tabPanels.length; i < len; i++ ) {
+ tabPanels[ i ].setTabItem( null );
+ }
+ this.stackLayout.clearItems();
+
+ this.emit( 'remove', tabPanels );
+
+ return this;
+};
+
+/**
+ * Set the current tab panel by symbolic name.
+ *
+ * @fires set
+ * @param {string} name Symbolic name of tab panel
+ */
+OO.ui.IndexLayout.prototype.setTabPanel = function ( name ) {
+ var selectedItem,
+ $focused,
+ tabPanel = this.tabPanels[ name ],
+ previousTabPanel = this.currentTabPanelName && this.tabPanels[ this.currentTabPanelName ];
+
+ if ( name !== this.currentTabPanelName ) {
+ selectedItem = this.tabSelectWidget.getSelectedItem();
+ if ( selectedItem && selectedItem.getData() !== name ) {
+ this.tabSelectWidget.selectItemByData( name );
+ }
+ if ( tabPanel ) {
+ if ( previousTabPanel ) {
+ previousTabPanel.setActive( false );
+ // Blur anything focused if the next tab panel doesn't have anything focusable.
+ // This is not needed if the next tab panel has something focusable (because once it is focused
+ // this blur happens automatically). If the layout is non-continuous, this check is
+ // meaningless because the next tab panel is not visible yet and thus can't hold focus.
+ if (
+ this.autoFocus &&
+ !OO.ui.isMobile() &&
+ this.stackLayout.continuous &&
+ OO.ui.findFocusable( tabPanel.$element ).length !== 0
+ ) {
+ $focused = previousTabPanel.$element.find( ':focus' );
+ if ( $focused.length ) {
+ $focused[ 0 ].blur();
+ }
+ }
+ }
+ this.currentTabPanelName = name;
+ tabPanel.setActive( true );
+ this.stackLayout.setItem( tabPanel );
+ if ( !this.stackLayout.continuous && previousTabPanel ) {
+ // This should not be necessary, since any inputs on the previous tab panel should have been
+ // blurred when it was hidden, but browsers are not very consistent about this.
+ $focused = previousTabPanel.$element.find( ':focus' );
+ if ( $focused.length ) {
+ $focused[ 0 ].blur();
+ }
+ }
+ this.emit( 'set', tabPanel );
+ }
+ }
+};
+
+/**
+ * Select the first selectable tab panel.
+ *
+ * @chainable
+ */
+OO.ui.IndexLayout.prototype.selectFirstSelectableTabPanel = function () {
+ if ( !this.tabSelectWidget.getSelectedItem() ) {
+ this.tabSelectWidget.selectItem( this.tabSelectWidget.getFirstSelectableItem() );
+ }
+
+ return this;
+};
+
+/**
+ * ToggleWidget implements basic behavior of widgets with an on/off state.
+ * Please see OO.ui.ToggleButtonWidget and OO.ui.ToggleSwitchWidget for examples.
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [value=false] The toggle’s initial on/off state.
+ * By default, the toggle is in the 'off' state.
+ */
+OO.ui.ToggleWidget = function OoUiToggleWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.ToggleWidget.parent.call( this, config );
+
+ // Properties
+ this.value = null;
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-toggleWidget' );
+ this.setValue( !!config.value );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToggleWidget, OO.ui.Widget );
+
+/* Events */
+
+/**
+ * @event change
+ *
+ * A change event is emitted when the on/off state of the toggle changes.
+ *
+ * @param {boolean} value Value representing the new state of the toggle
+ */
+
+/* Methods */
+
+/**
+ * Get the value representing the toggle’s state.
+ *
+ * @return {boolean} The on/off state of the toggle
+ */
+OO.ui.ToggleWidget.prototype.getValue = function () {
+ return this.value;
+};
+
+/**
+ * Set the state of the toggle: `true` for 'on', `false` for 'off'.
+ *
+ * @param {boolean} value The state of the toggle
+ * @fires change
+ * @chainable
+ */
+OO.ui.ToggleWidget.prototype.setValue = function ( value ) {
+ value = !!value;
+ if ( this.value !== value ) {
+ this.value = value;
+ this.emit( 'change', value );
+ this.$element.toggleClass( 'oo-ui-toggleWidget-on', value );
+ this.$element.toggleClass( 'oo-ui-toggleWidget-off', !value );
+ }
+ return this;
+};
+
+/**
+ * ToggleButtons are buttons that have a state (‘on’ or ‘off’) that is represented by a
+ * Boolean value. Like other {@link OO.ui.ButtonWidget buttons}, toggle buttons can be
+ * configured with {@link OO.ui.mixin.IconElement icons}, {@link OO.ui.mixin.IndicatorElement indicators},
+ * {@link OO.ui.mixin.TitledElement titles}, {@link OO.ui.mixin.FlaggedElement styling flags},
+ * and {@link OO.ui.mixin.LabelElement labels}. Please see
+ * the [OOjs UI documentation][1] on MediaWiki for more information.
+ *
+ * @example
+ * // Toggle buttons in the 'off' and 'on' state.
+ * var toggleButton1 = new OO.ui.ToggleButtonWidget( {
+ * label: 'Toggle Button off'
+ * } );
+ * var toggleButton2 = new OO.ui.ToggleButtonWidget( {
+ * label: 'Toggle Button on',
+ * value: true
+ * } );
+ * // Append the buttons to the DOM.
+ * $( 'body' ).append( toggleButton1.$element, toggleButton2.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches#Toggle_buttons
+ *
+ * @class
+ * @extends OO.ui.ToggleWidget
+ * @mixins OO.ui.mixin.ButtonElement
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.TitledElement
+ * @mixins OO.ui.mixin.FlaggedElement
+ * @mixins OO.ui.mixin.TabIndexedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [value=false] The toggle button’s initial on/off
+ * state. By default, the button is in the 'off' state.
+ */
+OO.ui.ToggleButtonWidget = function OoUiToggleButtonWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.ToggleButtonWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.ButtonElement.call( this, $.extend( {}, config, { active: this.active } ) );
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.IndicatorElement.call( this, config );
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$button } ) );
+ OO.ui.mixin.FlaggedElement.call( this, config );
+ OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$button } ) );
+
+ // Events
+ this.connect( this, { click: 'onAction' } );
+
+ // Initialization
+ this.$button.append( this.$icon, this.$label, this.$indicator );
+ this.$element
+ .addClass( 'oo-ui-toggleButtonWidget' )
+ .append( this.$button );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToggleButtonWidget, OO.ui.ToggleWidget );
+OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.ButtonElement );
+OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.IndicatorElement );
+OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.TitledElement );
+OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.FlaggedElement );
+OO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.TabIndexedElement );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.ToggleButtonWidget.static.tagName = 'span';
+
+/* Methods */
+
+/**
+ * Handle the button action being triggered.
+ *
+ * @private
+ */
+OO.ui.ToggleButtonWidget.prototype.onAction = function () {
+ this.setValue( !this.value );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToggleButtonWidget.prototype.setValue = function ( value ) {
+ value = !!value;
+ if ( value !== this.value ) {
+ // Might be called from parent constructor before ButtonElement constructor
+ if ( this.$button ) {
+ this.$button.attr( 'aria-pressed', value.toString() );
+ }
+ this.setActive( value );
+ }
+
+ // Parent method
+ OO.ui.ToggleButtonWidget.parent.prototype.setValue.call( this, value );
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToggleButtonWidget.prototype.setButtonElement = function ( $button ) {
+ if ( this.$button ) {
+ this.$button.removeAttr( 'aria-pressed' );
+ }
+ OO.ui.mixin.ButtonElement.prototype.setButtonElement.call( this, $button );
+ this.$button.attr( 'aria-pressed', this.value.toString() );
+};
+
+/**
+ * ToggleSwitches are switches that slide on and off. Their state is represented by a Boolean
+ * value (`true` for ‘on’, and `false` otherwise, the default). The ‘off’ state is represented
+ * visually by a slider in the leftmost position.
+ *
+ * @example
+ * // Toggle switches in the 'off' and 'on' position.
+ * var toggleSwitch1 = new OO.ui.ToggleSwitchWidget();
+ * var toggleSwitch2 = new OO.ui.ToggleSwitchWidget( {
+ * value: true
+ * } );
+ *
+ * // Create a FieldsetLayout to layout and label switches
+ * var fieldset = new OO.ui.FieldsetLayout( {
+ * label: 'Toggle switches'
+ * } );
+ * fieldset.addItems( [
+ * new OO.ui.FieldLayout( toggleSwitch1, { label: 'Off', align: 'top' } ),
+ * new OO.ui.FieldLayout( toggleSwitch2, { label: 'On', align: 'top' } )
+ * ] );
+ * $( 'body' ).append( fieldset.$element );
+ *
+ * @class
+ * @extends OO.ui.ToggleWidget
+ * @mixins OO.ui.mixin.TabIndexedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [value=false] The toggle switch’s initial on/off state.
+ * By default, the toggle switch is in the 'off' position.
+ */
+OO.ui.ToggleSwitchWidget = function OoUiToggleSwitchWidget( config ) {
+ // Parent constructor
+ OO.ui.ToggleSwitchWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.TabIndexedElement.call( this, config );
+
+ // Properties
+ this.dragging = false;
+ this.dragStart = null;
+ this.sliding = false;
+ this.$glow = $( '<span>' );
+ this.$grip = $( '<span>' );
+
+ // Events
+ this.$element.on( {
+ click: this.onClick.bind( this ),
+ keypress: this.onKeyPress.bind( this )
+ } );
+
+ // Initialization
+ this.$glow.addClass( 'oo-ui-toggleSwitchWidget-glow' );
+ this.$grip.addClass( 'oo-ui-toggleSwitchWidget-grip' );
+ this.$element
+ .addClass( 'oo-ui-toggleSwitchWidget' )
+ .attr( 'role', 'checkbox' )
+ .append( this.$glow, this.$grip );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ToggleSwitchWidget, OO.ui.ToggleWidget );
+OO.mixinClass( OO.ui.ToggleSwitchWidget, OO.ui.mixin.TabIndexedElement );
+
+/* Methods */
+
+/**
+ * Handle mouse click events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse click event
+ */
+OO.ui.ToggleSwitchWidget.prototype.onClick = function ( e ) {
+ if ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {
+ this.setValue( !this.value );
+ }
+ return false;
+};
+
+/**
+ * Handle key press events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key press event
+ */
+OO.ui.ToggleSwitchWidget.prototype.onKeyPress = function ( e ) {
+ if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) {
+ this.setValue( !this.value );
+ return false;
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToggleSwitchWidget.prototype.setValue = function ( value ) {
+ OO.ui.ToggleSwitchWidget.parent.prototype.setValue.call( this, value );
+ this.$element.attr( 'aria-checked', this.value.toString() );
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ToggleSwitchWidget.prototype.simulateLabelClick = function () {
+ if ( !this.isDisabled() ) {
+ this.setValue( !this.value );
+ }
+ this.focus();
+};
+
+/**
+ * OutlineControlsWidget is a set of controls for an {@link OO.ui.OutlineSelectWidget outline select widget}.
+ * Controls include moving items up and down, removing items, and adding different kinds of items.
+ *
+ * **Currently, this class is only used by {@link OO.ui.BookletLayout booklet layouts}.**
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.GroupElement
+ * @mixins OO.ui.mixin.IconElement
+ *
+ * @constructor
+ * @param {OO.ui.OutlineSelectWidget} outline Outline to control
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} [abilities] List of abilties
+ * @cfg {boolean} [abilities.move=true] Allow moving movable items
+ * @cfg {boolean} [abilities.remove=true] Allow removing removable items
+ */
+OO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( outline ) && config === undefined ) {
+ config = outline;
+ outline = config.outline;
+ }
+
+ // Configuration initialization
+ config = $.extend( { icon: 'add' }, config );
+
+ // Parent constructor
+ OO.ui.OutlineControlsWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.GroupElement.call( this, config );
+ OO.ui.mixin.IconElement.call( this, config );
+
+ // Properties
+ this.outline = outline;
+ this.$movers = $( '<div>' );
+ this.upButton = new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'collapse',
+ title: OO.ui.msg( 'ooui-outline-control-move-up' )
+ } );
+ this.downButton = new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'expand',
+ title: OO.ui.msg( 'ooui-outline-control-move-down' )
+ } );
+ this.removeButton = new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'trash',
+ title: OO.ui.msg( 'ooui-outline-control-remove' )
+ } );
+ this.abilities = { move: true, remove: true };
+
+ // Events
+ outline.connect( this, {
+ select: 'onOutlineChange',
+ add: 'onOutlineChange',
+ remove: 'onOutlineChange'
+ } );
+ this.upButton.connect( this, { click: [ 'emit', 'move', -1 ] } );
+ this.downButton.connect( this, { click: [ 'emit', 'move', 1 ] } );
+ this.removeButton.connect( this, { click: [ 'emit', 'remove' ] } );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-outlineControlsWidget' );
+ this.$group.addClass( 'oo-ui-outlineControlsWidget-items' );
+ this.$movers
+ .addClass( 'oo-ui-outlineControlsWidget-movers' )
+ .append( this.removeButton.$element, this.upButton.$element, this.downButton.$element );
+ this.$element.append( this.$icon, this.$group, this.$movers );
+ this.setAbilities( config.abilities || {} );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.mixin.GroupElement );
+OO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.mixin.IconElement );
+
+/* Events */
+
+/**
+ * @event move
+ * @param {number} places Number of places to move
+ */
+
+/**
+ * @event remove
+ */
+
+/* Methods */
+
+/**
+ * Set abilities.
+ *
+ * @param {Object} abilities List of abilties
+ * @param {boolean} [abilities.move] Allow moving movable items
+ * @param {boolean} [abilities.remove] Allow removing removable items
+ */
+OO.ui.OutlineControlsWidget.prototype.setAbilities = function ( abilities ) {
+ var ability;
+
+ for ( ability in this.abilities ) {
+ if ( abilities[ ability ] !== undefined ) {
+ this.abilities[ ability ] = !!abilities[ ability ];
+ }
+ }
+
+ this.onOutlineChange();
+};
+
+/**
+ * Handle outline change events.
+ *
+ * @private
+ */
+OO.ui.OutlineControlsWidget.prototype.onOutlineChange = function () {
+ var i, len, firstMovable, lastMovable,
+ items = this.outline.getItems(),
+ selectedItem = this.outline.getSelectedItem(),
+ movable = this.abilities.move && selectedItem && selectedItem.isMovable(),
+ removable = this.abilities.remove && selectedItem && selectedItem.isRemovable();
+
+ if ( movable ) {
+ i = -1;
+ len = items.length;
+ while ( ++i < len ) {
+ if ( items[ i ].isMovable() ) {
+ firstMovable = items[ i ];
+ break;
+ }
+ }
+ i = len;
+ while ( i-- ) {
+ if ( items[ i ].isMovable() ) {
+ lastMovable = items[ i ];
+ break;
+ }
+ }
+ }
+ this.upButton.setDisabled( !movable || selectedItem === firstMovable );
+ this.downButton.setDisabled( !movable || selectedItem === lastMovable );
+ this.removeButton.setDisabled( !removable );
+};
+
+/**
+ * OutlineOptionWidget is an item in an {@link OO.ui.OutlineSelectWidget OutlineSelectWidget}.
+ *
+ * Currently, this class is only used by {@link OO.ui.BookletLayout booklet layouts}, which contain
+ * {@link OO.ui.PageLayout page layouts}. See {@link OO.ui.BookletLayout BookletLayout}
+ * for an example.
+ *
+ * @class
+ * @extends OO.ui.DecoratedOptionWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [level] Indentation level
+ * @cfg {boolean} [movable] Allow modification from {@link OO.ui.OutlineControlsWidget outline controls}.
+ */
+OO.ui.OutlineOptionWidget = function OoUiOutlineOptionWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.OutlineOptionWidget.parent.call( this, config );
+
+ // Properties
+ this.level = 0;
+ this.movable = !!config.movable;
+ this.removable = !!config.removable;
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-outlineOptionWidget' );
+ this.setLevel( config.level );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.OutlineOptionWidget, OO.ui.DecoratedOptionWidget );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.OutlineOptionWidget.static.highlightable = true;
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.OutlineOptionWidget.static.scrollIntoViewOnSelect = true;
+
+/**
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.OutlineOptionWidget.static.levelClass = 'oo-ui-outlineOptionWidget-level-';
+
+/**
+ * @static
+ * @inheritable
+ * @property {number}
+ */
+OO.ui.OutlineOptionWidget.static.levels = 3;
+
+/* Methods */
+
+/**
+ * Check if item is movable.
+ *
+ * Movability is used by {@link OO.ui.OutlineControlsWidget outline controls}.
+ *
+ * @return {boolean} Item is movable
+ */
+OO.ui.OutlineOptionWidget.prototype.isMovable = function () {
+ return this.movable;
+};
+
+/**
+ * Check if item is removable.
+ *
+ * Removability is used by {@link OO.ui.OutlineControlsWidget outline controls}.
+ *
+ * @return {boolean} Item is removable
+ */
+OO.ui.OutlineOptionWidget.prototype.isRemovable = function () {
+ return this.removable;
+};
+
+/**
+ * Get indentation level.
+ *
+ * @return {number} Indentation level
+ */
+OO.ui.OutlineOptionWidget.prototype.getLevel = function () {
+ return this.level;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.OutlineOptionWidget.prototype.setPressed = function ( state ) {
+ OO.ui.OutlineOptionWidget.parent.prototype.setPressed.call( this, state );
+ if ( this.pressed ) {
+ this.setFlags( { progressive: true } );
+ } else if ( !this.selected ) {
+ this.setFlags( { progressive: false } );
+ }
+ return this;
+};
+
+/**
+ * Set movability.
+ *
+ * Movability is used by {@link OO.ui.OutlineControlsWidget outline controls}.
+ *
+ * @param {boolean} movable Item is movable
+ * @chainable
+ */
+OO.ui.OutlineOptionWidget.prototype.setMovable = function ( movable ) {
+ this.movable = !!movable;
+ this.updateThemeClasses();
+ return this;
+};
+
+/**
+ * Set removability.
+ *
+ * Removability is used by {@link OO.ui.OutlineControlsWidget outline controls}.
+ *
+ * @param {boolean} removable Item is removable
+ * @chainable
+ */
+OO.ui.OutlineOptionWidget.prototype.setRemovable = function ( removable ) {
+ this.removable = !!removable;
+ this.updateThemeClasses();
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.OutlineOptionWidget.prototype.setSelected = function ( state ) {
+ OO.ui.OutlineOptionWidget.parent.prototype.setSelected.call( this, state );
+ if ( this.selected ) {
+ this.setFlags( { progressive: true } );
+ } else {
+ this.setFlags( { progressive: false } );
+ }
+ return this;
+};
+
+/**
+ * Set indentation level.
+ *
+ * @param {number} [level=0] Indentation level, in the range of [0,#maxLevel]
+ * @chainable
+ */
+OO.ui.OutlineOptionWidget.prototype.setLevel = function ( level ) {
+ var levels = this.constructor.static.levels,
+ levelClass = this.constructor.static.levelClass,
+ i = levels;
+
+ this.level = level ? Math.max( 0, Math.min( levels - 1, level ) ) : 0;
+ while ( i-- ) {
+ if ( this.level === i ) {
+ this.$element.addClass( levelClass + i );
+ } else {
+ this.$element.removeClass( levelClass + i );
+ }
+ }
+ this.updateThemeClasses();
+
+ return this;
+};
+
+/**
+ * OutlineSelectWidget is a structured list that contains {@link OO.ui.OutlineOptionWidget outline options}
+ * A set of controls can be provided with an {@link OO.ui.OutlineControlsWidget outline controls} widget.
+ *
+ * **Currently, this class is only used by {@link OO.ui.BookletLayout booklet layouts}.**
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ * @mixins OO.ui.mixin.TabIndexedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.OutlineSelectWidget = function OoUiOutlineSelectWidget( config ) {
+ // Parent constructor
+ OO.ui.OutlineSelectWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.TabIndexedElement.call( this, config );
+
+ // Events
+ this.$element.on( {
+ focus: this.bindKeyDownListener.bind( this ),
+ blur: this.unbindKeyDownListener.bind( this )
+ } );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-outlineSelectWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.OutlineSelectWidget, OO.ui.SelectWidget );
+OO.mixinClass( OO.ui.OutlineSelectWidget, OO.ui.mixin.TabIndexedElement );
+
+/**
+ * ButtonOptionWidget is a special type of {@link OO.ui.mixin.ButtonElement button element} that
+ * can be selected and configured with data. The class is
+ * used with OO.ui.ButtonSelectWidget to create a selection of button options. Please see the
+ * [OOjs UI documentation on MediaWiki] [1] for more information.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Button_selects_and_options
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ * @mixins OO.ui.mixin.ButtonElement
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.TitledElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ButtonOptionWidget = function OoUiButtonOptionWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.ButtonOptionWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.ButtonElement.call( this, config );
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.IndicatorElement.call( this, config );
+ OO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$button } ) );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-buttonOptionWidget' );
+ this.$button.append( this.$icon, this.$label, this.$indicator );
+ this.$element.append( this.$button );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ButtonOptionWidget, OO.ui.OptionWidget );
+OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.ButtonElement );
+OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.IndicatorElement );
+OO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.TitledElement );
+
+/* Static Properties */
+
+/**
+ * Allow button mouse down events to pass through so they can be handled by the parent select widget
+ *
+ * @static
+ * @inheritdoc
+ */
+OO.ui.ButtonOptionWidget.static.cancelButtonMouseDownEvents = false;
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.ButtonOptionWidget.static.highlightable = false;
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {
+ OO.ui.ButtonOptionWidget.parent.prototype.setSelected.call( this, state );
+
+ if ( this.constructor.static.selectable ) {
+ this.setActive( state );
+ }
+
+ return this;
+};
+
+/**
+ * ButtonSelectWidget is a {@link OO.ui.SelectWidget select widget} that contains
+ * button options and is used together with
+ * OO.ui.ButtonOptionWidget. The ButtonSelectWidget provides an interface for
+ * highlighting, choosing, and selecting mutually exclusive options. Please see
+ * the [OOjs UI documentation on MediaWiki] [1] for more information.
+ *
+ * @example
+ * // Example: A ButtonSelectWidget that contains three ButtonOptionWidgets
+ * var option1 = new OO.ui.ButtonOptionWidget( {
+ * data: 1,
+ * label: 'Option 1',
+ * title: 'Button option 1'
+ * } );
+ *
+ * var option2 = new OO.ui.ButtonOptionWidget( {
+ * data: 2,
+ * label: 'Option 2',
+ * title: 'Button option 2'
+ * } );
+ *
+ * var option3 = new OO.ui.ButtonOptionWidget( {
+ * data: 3,
+ * label: 'Option 3',
+ * title: 'Button option 3'
+ * } );
+ *
+ * var buttonSelect=new OO.ui.ButtonSelectWidget( {
+ * items: [ option1, option2, option3 ]
+ * } );
+ * $( 'body' ).append( buttonSelect.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ * @mixins OO.ui.mixin.TabIndexedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ButtonSelectWidget = function OoUiButtonSelectWidget( config ) {
+ // Parent constructor
+ OO.ui.ButtonSelectWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.TabIndexedElement.call( this, config );
+
+ // Events
+ this.$element.on( {
+ focus: this.bindKeyDownListener.bind( this ),
+ blur: this.unbindKeyDownListener.bind( this )
+ } );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-buttonSelectWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ButtonSelectWidget, OO.ui.SelectWidget );
+OO.mixinClass( OO.ui.ButtonSelectWidget, OO.ui.mixin.TabIndexedElement );
+
+/**
+ * TabOptionWidget is an item in a {@link OO.ui.TabSelectWidget TabSelectWidget}.
+ *
+ * Currently, this class is only used by {@link OO.ui.IndexLayout index layouts}, which contain
+ * {@link OO.ui.TabPanelLayout tab panel layouts}. See {@link OO.ui.IndexLayout IndexLayout}
+ * for an example.
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.TabOptionWidget = function OoUiTabOptionWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.TabOptionWidget.parent.call( this, config );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-tabOptionWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.TabOptionWidget, OO.ui.OptionWidget );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.TabOptionWidget.static.highlightable = false;
+
+/**
+ * TabSelectWidget is a list that contains {@link OO.ui.TabOptionWidget tab options}
+ *
+ * **Currently, this class is only used by {@link OO.ui.IndexLayout index layouts}.**
+ *
+ * @class
+ * @extends OO.ui.SelectWidget
+ * @mixins OO.ui.mixin.TabIndexedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.TabSelectWidget = function OoUiTabSelectWidget( config ) {
+ // Parent constructor
+ OO.ui.TabSelectWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.TabIndexedElement.call( this, config );
+
+ // Events
+ this.$element.on( {
+ focus: this.bindKeyDownListener.bind( this ),
+ blur: this.unbindKeyDownListener.bind( this )
+ } );
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-tabSelectWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.TabSelectWidget, OO.ui.SelectWidget );
+OO.mixinClass( OO.ui.TabSelectWidget, OO.ui.mixin.TabIndexedElement );
+
+/**
+ * CapsuleItemWidgets are used within a {@link OO.ui.CapsuleMultiselectWidget
+ * CapsuleMultiselectWidget} to display the selected items.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.ItemWidget
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.FlaggedElement
+ * @mixins OO.ui.mixin.TabIndexedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.CapsuleItemWidget = function OoUiCapsuleItemWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.CapsuleItemWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.ItemWidget.call( this );
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.FlaggedElement.call( this, config );
+ OO.ui.mixin.TabIndexedElement.call( this, config );
+
+ // Events
+ this.closeButton = new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'close',
+ tabIndex: -1,
+ title: OO.ui.msg( 'ooui-item-remove' )
+ } ).on( 'click', this.onCloseClick.bind( this ) );
+
+ this.on( 'disable', function ( disabled ) {
+ this.closeButton.setDisabled( disabled );
+ }.bind( this ) );
+
+ // Initialization
+ this.$element
+ .on( {
+ click: this.onClick.bind( this ),
+ keydown: this.onKeyDown.bind( this )
+ } )
+ .addClass( 'oo-ui-capsuleItemWidget' )
+ .append( this.$label, this.closeButton.$element );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.CapsuleItemWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.CapsuleItemWidget, OO.ui.mixin.ItemWidget );
+OO.mixinClass( OO.ui.CapsuleItemWidget, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.CapsuleItemWidget, OO.ui.mixin.FlaggedElement );
+OO.mixinClass( OO.ui.CapsuleItemWidget, OO.ui.mixin.TabIndexedElement );
+
+/* Methods */
+
+/**
+ * Handle close icon clicks
+ */
+OO.ui.CapsuleItemWidget.prototype.onCloseClick = function () {
+ var element = this.getElementGroup();
+
+ if ( element && $.isFunction( element.removeItems ) ) {
+ element.removeItems( [ this ] );
+ element.focus();
+ }
+};
+
+/**
+ * Handle click event for the entire capsule
+ */
+OO.ui.CapsuleItemWidget.prototype.onClick = function () {
+ var element = this.getElementGroup();
+
+ if ( !this.isDisabled() && element && $.isFunction( element.editItem ) ) {
+ element.editItem( this );
+ }
+};
+
+/**
+ * Handle keyDown event for the entire capsule
+ *
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.CapsuleItemWidget.prototype.onKeyDown = function ( e ) {
+ var element = this.getElementGroup();
+
+ if ( e.keyCode === OO.ui.Keys.BACKSPACE || e.keyCode === OO.ui.Keys.DELETE ) {
+ element.removeItems( [ this ] );
+ element.focus();
+ return false;
+ } else if ( e.keyCode === OO.ui.Keys.ENTER ) {
+ element.editItem( this );
+ return false;
+ } else if ( e.keyCode === OO.ui.Keys.LEFT ) {
+ element.getPreviousItem( this ).focus();
+ } else if ( e.keyCode === OO.ui.Keys.RIGHT ) {
+ element.getNextItem( this ).focus();
+ }
+};
+
+/**
+ * CapsuleMultiselectWidgets are something like a {@link OO.ui.ComboBoxInputWidget combo box widget}
+ * that allows for selecting multiple values.
+ *
+ * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * @example
+ * // Example: A CapsuleMultiselectWidget.
+ * var capsule = new OO.ui.CapsuleMultiselectWidget( {
+ * label: 'CapsuleMultiselectWidget',
+ * selected: [ 'Option 1', 'Option 3' ],
+ * menu: {
+ * items: [
+ * new OO.ui.MenuOptionWidget( {
+ * data: 'Option 1',
+ * label: 'Option One'
+ * } ),
+ * new OO.ui.MenuOptionWidget( {
+ * data: 'Option 2',
+ * label: 'Option Two'
+ * } ),
+ * new OO.ui.MenuOptionWidget( {
+ * data: 'Option 3',
+ * label: 'Option Three'
+ * } ),
+ * new OO.ui.MenuOptionWidget( {
+ * data: 'Option 4',
+ * label: 'Option Four'
+ * } ),
+ * new OO.ui.MenuOptionWidget( {
+ * data: 'Option 5',
+ * label: 'Option Five'
+ * } )
+ * ]
+ * }
+ * } );
+ * $( 'body' ).append( capsule.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.GroupElement
+ * @mixins OO.ui.mixin.PopupElement
+ * @mixins OO.ui.mixin.TabIndexedElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.IconElement
+ * @uses OO.ui.CapsuleItemWidget
+ * @uses OO.ui.MenuSelectWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [placeholder] Placeholder text
+ * @cfg {boolean} [allowArbitrary=false] Allow data items to be added even if not present in the menu.
+ * @cfg {boolean} [allowDuplicates=false] Allow duplicate items to be added.
+ * @cfg {Object} [menu] (required) Configuration options to pass to the
+ * {@link OO.ui.MenuSelectWidget menu select widget}.
+ * @cfg {Object} [popup] Configuration options to pass to the {@link OO.ui.PopupWidget popup widget}.
+ * If specified, this popup will be shown instead of the menu (but the menu
+ * will still be used for item labels and allowArbitrary=false). The widgets
+ * in the popup should use {@link #addItemsFromData} or {@link #addItems} as necessary.
+ * @cfg {jQuery} [$overlay=this.$element] Render the menu or popup into a separate layer.
+ * This configuration is useful in cases where the expanded menu is larger than
+ * its containing `<div>`. The specified overlay layer is usually on top of
+ * the containing `<div>` and has a larger area. By default, the menu uses
+ * relative positioning.
+ * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.
+ */
+OO.ui.CapsuleMultiselectWidget = function OoUiCapsuleMultiselectWidget( config ) {
+ var $tabFocus;
+
+ // Parent constructor
+ OO.ui.CapsuleMultiselectWidget.parent.call( this, config );
+
+ // Configuration initialization
+ config = $.extend( {
+ allowArbitrary: false,
+ allowDuplicates: false,
+ $overlay: this.$element
+ }, config );
+
+ // Properties (must be set before mixin constructor calls)
+ this.$handle = $( '<div>' );
+ this.$input = config.popup ? null : $( '<input>' );
+ if ( config.placeholder !== undefined && config.placeholder !== '' ) {
+ this.$input.attr( 'placeholder', config.placeholder );
+ }
+
+ // Mixin constructors
+ OO.ui.mixin.GroupElement.call( this, config );
+ if ( config.popup ) {
+ config.popup = $.extend( {}, config.popup, {
+ align: 'forwards',
+ anchor: false
+ } );
+ OO.ui.mixin.PopupElement.call( this, config );
+ $tabFocus = $( '<span>' );
+ OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: $tabFocus } ) );
+ } else {
+ this.popup = null;
+ $tabFocus = null;
+ OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$input } ) );
+ }
+ OO.ui.mixin.IndicatorElement.call( this, config );
+ OO.ui.mixin.IconElement.call( this, config );
+
+ // Properties
+ this.$content = $( '<div>' );
+ this.allowArbitrary = config.allowArbitrary;
+ this.allowDuplicates = config.allowDuplicates;
+ this.$overlay = config.$overlay;
+ this.menu = new OO.ui.MenuSelectWidget( $.extend(
+ {
+ widget: this,
+ $input: this.$input,
+ $floatableContainer: this.$element,
+ filterFromInput: true,
+ disabled: this.isDisabled()
+ },
+ config.menu
+ ) );
+
+ // Events
+ if ( this.popup ) {
+ $tabFocus.on( {
+ focus: this.focus.bind( this )
+ } );
+ this.popup.$element.on( 'focusout', this.onPopupFocusOut.bind( this ) );
+ if ( this.popup.$autoCloseIgnore ) {
+ this.popup.$autoCloseIgnore.on( 'focusout', this.onPopupFocusOut.bind( this ) );
+ }
+ this.popup.connect( this, {
+ toggle: function ( visible ) {
+ $tabFocus.toggle( !visible );
+ }
+ } );
+ } else {
+ this.$input.on( {
+ focus: this.onInputFocus.bind( this ),
+ blur: this.onInputBlur.bind( this ),
+ 'propertychange change click mouseup keydown keyup input cut paste select focus':
+ OO.ui.debounce( this.updateInputSize.bind( this ) ),
+ keydown: this.onKeyDown.bind( this ),
+ keypress: this.onKeyPress.bind( this )
+ } );
+ }
+ this.menu.connect( this, {
+ choose: 'onMenuChoose',
+ toggle: 'onMenuToggle',
+ add: 'onMenuItemsChange',
+ remove: 'onMenuItemsChange'
+ } );
+ this.$handle.on( {
+ mousedown: this.onMouseDown.bind( this )
+ } );
+
+ // Initialization
+ if ( this.$input ) {
+ this.$input.prop( 'disabled', this.isDisabled() );
+ this.$input.attr( {
+ role: 'combobox',
+ 'aria-owns': this.menu.getElementId(),
+ 'aria-autocomplete': 'list'
+ } );
+ }
+ if ( config.data ) {
+ this.setItemsFromData( config.data );
+ }
+ this.$content.addClass( 'oo-ui-capsuleMultiselectWidget-content' )
+ .append( this.$group );
+ this.$group.addClass( 'oo-ui-capsuleMultiselectWidget-group' );
+ this.$handle.addClass( 'oo-ui-capsuleMultiselectWidget-handle' )
+ .append( this.$indicator, this.$icon, this.$content );
+ this.$element.addClass( 'oo-ui-capsuleMultiselectWidget' )
+ .append( this.$handle );
+ if ( this.popup ) {
+ this.popup.$element.addClass( 'oo-ui-capsuleMultiselectWidget-popup' );
+ this.$content.append( $tabFocus );
+ this.$overlay.append( this.popup.$element );
+ } else {
+ this.$content.append( this.$input );
+ this.$overlay.append( this.menu.$element );
+ }
+ if ( $tabFocus ) {
+ $tabFocus.addClass( 'oo-ui-capsuleMultiselectWidget-focusTrap' );
+ }
+
+ // Input size needs to be calculated after everything else is rendered
+ setTimeout( function () {
+ if ( this.$input ) {
+ this.updateInputSize();
+ }
+ }.bind( this ) );
+
+ this.onMenuItemsChange();
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.CapsuleMultiselectWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.CapsuleMultiselectWidget, OO.ui.mixin.GroupElement );
+OO.mixinClass( OO.ui.CapsuleMultiselectWidget, OO.ui.mixin.PopupElement );
+OO.mixinClass( OO.ui.CapsuleMultiselectWidget, OO.ui.mixin.TabIndexedElement );
+OO.mixinClass( OO.ui.CapsuleMultiselectWidget, OO.ui.mixin.IndicatorElement );
+OO.mixinClass( OO.ui.CapsuleMultiselectWidget, OO.ui.mixin.IconElement );
+
+/* Events */
+
+/**
+ * @event change
+ *
+ * A change event is emitted when the set of selected items changes.
+ *
+ * @param {Mixed[]} datas Data of the now-selected items
+ */
+
+/**
+ * @event resize
+ *
+ * A resize event is emitted when the widget's dimensions change to accomodate newly added items or
+ * current user input.
+ */
+
+/* Methods */
+
+/**
+ * Construct a OO.ui.CapsuleItemWidget (or a subclass thereof) from given label and data.
+ * May return `null` if the given label and data are not valid.
+ *
+ * @protected
+ * @param {Mixed} data Custom data of any type.
+ * @param {string} label The label text.
+ * @return {OO.ui.CapsuleItemWidget|null}
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.createItemWidget = function ( data, label ) {
+ if ( label === '' ) {
+ return null;
+ }
+ return new OO.ui.CapsuleItemWidget( { data: data, label: label } );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.getInputId = function () {
+ if ( !this.$input ) {
+ return null;
+ }
+ return OO.ui.mixin.TabIndexedElement.prototype.getInputId.call( this );
+};
+
+/**
+ * Get the data of the items in the capsule
+ *
+ * @return {Mixed[]}
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.getItemsData = function () {
+ return this.getItems().map( function ( item ) {
+ return item.data;
+ } );
+};
+
+/**
+ * Set the items in the capsule by providing data
+ *
+ * @chainable
+ * @param {Mixed[]} datas
+ * @return {OO.ui.CapsuleMultiselectWidget}
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.setItemsFromData = function ( datas ) {
+ var widget = this,
+ menu = this.menu,
+ items = this.getItems();
+
+ $.each( datas, function ( i, data ) {
+ var j, label,
+ item = menu.getItemFromData( data );
+
+ if ( item ) {
+ label = item.label;
+ } else if ( widget.allowArbitrary ) {
+ label = String( data );
+ } else {
+ return;
+ }
+
+ item = null;
+ for ( j = 0; j < items.length; j++ ) {
+ if ( items[ j ].data === data && items[ j ].label === label ) {
+ item = items[ j ];
+ items.splice( j, 1 );
+ break;
+ }
+ }
+ if ( !item ) {
+ item = widget.createItemWidget( data, label );
+ }
+ if ( item ) {
+ widget.addItems( [ item ], i );
+ }
+ } );
+
+ if ( items.length ) {
+ widget.removeItems( items );
+ }
+
+ return this;
+};
+
+/**
+ * Add items to the capsule by providing their data
+ *
+ * @chainable
+ * @param {Mixed[]} datas
+ * @return {OO.ui.CapsuleMultiselectWidget}
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.addItemsFromData = function ( datas ) {
+ var widget = this,
+ menu = this.menu,
+ items = [];
+
+ $.each( datas, function ( i, data ) {
+ var item;
+
+ if ( !widget.getItemFromData( data ) || widget.allowDuplicates ) {
+ item = menu.getItemFromData( data );
+ if ( item ) {
+ item = widget.createItemWidget( data, item.label );
+ } else if ( widget.allowArbitrary ) {
+ item = widget.createItemWidget( data, String( data ) );
+ }
+ if ( item ) {
+ items.push( item );
+ }
+ }
+ } );
+
+ if ( items.length ) {
+ this.addItems( items );
+ }
+
+ return this;
+};
+
+/**
+ * Add items to the capsule by providing a label
+ *
+ * @param {string} label
+ * @return {boolean} Whether the item was added or not
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.addItemFromLabel = function ( label ) {
+ var item, items;
+ item = this.menu.getItemFromLabel( label, true );
+ if ( item ) {
+ this.addItemsFromData( [ item.data ] );
+ return true;
+ } else if ( this.allowArbitrary ) {
+ items = this.getItems();
+ this.addItemsFromData( [ label ] );
+ return !OO.compare( this.getItems(), items );
+ }
+ return false;
+};
+
+/**
+ * Remove items by data
+ *
+ * @chainable
+ * @param {Mixed[]} datas
+ * @return {OO.ui.CapsuleMultiselectWidget}
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.removeItemsFromData = function ( datas ) {
+ var widget = this,
+ items = [];
+
+ $.each( datas, function ( i, data ) {
+ var item = widget.getItemFromData( data );
+ if ( item ) {
+ items.push( item );
+ }
+ } );
+
+ if ( items.length ) {
+ this.removeItems( items );
+ }
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.addItems = function ( items ) {
+ var same, i, l,
+ oldItems = this.items.slice();
+
+ OO.ui.mixin.GroupElement.prototype.addItems.call( this, items );
+
+ if ( this.items.length !== oldItems.length ) {
+ same = false;
+ } else {
+ same = true;
+ for ( i = 0, l = oldItems.length; same && i < l; i++ ) {
+ same = same && this.items[ i ] === oldItems[ i ];
+ }
+ }
+ if ( !same ) {
+ this.emit( 'change', this.getItemsData() );
+ this.updateInputSize();
+ }
+
+ return this;
+};
+
+/**
+ * Removes the item from the list and copies its label to `this.$input`.
+ *
+ * @param {Object} item
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.editItem = function ( item ) {
+ this.addItemFromLabel( this.$input.val() );
+ this.clearInput();
+ this.$input.val( item.label );
+ this.updateInputSize();
+ this.focus();
+ this.menu.updateItemVisibility(); // Hack, we shouldn't be calling this method directly
+ this.removeItems( [ item ] );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.removeItems = function ( items ) {
+ var same, i, l,
+ oldItems = this.items.slice();
+
+ OO.ui.mixin.GroupElement.prototype.removeItems.call( this, items );
+
+ if ( this.items.length !== oldItems.length ) {
+ same = false;
+ } else {
+ same = true;
+ for ( i = 0, l = oldItems.length; same && i < l; i++ ) {
+ same = same && this.items[ i ] === oldItems[ i ];
+ }
+ }
+ if ( !same ) {
+ this.emit( 'change', this.getItemsData() );
+ this.updateInputSize();
+ }
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.clearItems = function () {
+ if ( this.items.length ) {
+ OO.ui.mixin.GroupElement.prototype.clearItems.call( this );
+ this.emit( 'change', this.getItemsData() );
+ this.updateInputSize();
+ }
+ return this;
+};
+
+/**
+ * Given an item, returns the item after it. If its the last item,
+ * returns `this.$input`. If no item is passed, returns the very first
+ * item.
+ *
+ * @param {OO.ui.CapsuleItemWidget} [item]
+ * @return {OO.ui.CapsuleItemWidget|jQuery|boolean}
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.getNextItem = function ( item ) {
+ var itemIndex;
+
+ if ( item === undefined ) {
+ return this.items[ 0 ];
+ }
+
+ itemIndex = this.items.indexOf( item );
+ if ( itemIndex < 0 ) { // Item not in list
+ return false;
+ } else if ( itemIndex === this.items.length - 1 ) { // Last item
+ return this.$input;
+ } else {
+ return this.items[ itemIndex + 1 ];
+ }
+};
+
+/**
+ * Given an item, returns the item before it. If its the first item,
+ * returns `this.$input`. If no item is passed, returns the very last
+ * item.
+ *
+ * @param {OO.ui.CapsuleItemWidget} [item]
+ * @return {OO.ui.CapsuleItemWidget|jQuery|boolean}
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.getPreviousItem = function ( item ) {
+ var itemIndex;
+
+ if ( item === undefined ) {
+ return this.items[ this.items.length - 1 ];
+ }
+
+ itemIndex = this.items.indexOf( item );
+ if ( itemIndex < 0 ) { // Item not in list
+ return false;
+ } else if ( itemIndex === 0 ) { // First item
+ return this.$input;
+ } else {
+ return this.items[ itemIndex - 1 ];
+ }
+};
+
+/**
+ * Get the capsule widget's menu.
+ *
+ * @return {OO.ui.MenuSelectWidget} Menu widget
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.getMenu = function () {
+ return this.menu;
+};
+
+/**
+ * Handle focus events
+ *
+ * @private
+ * @param {jQuery.Event} event
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.onInputFocus = function () {
+ if ( !this.isDisabled() ) {
+ this.updateInputSize();
+ this.menu.toggle( true );
+ }
+};
+
+/**
+ * Handle blur events
+ *
+ * @private
+ * @param {jQuery.Event} event
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.onInputBlur = function () {
+ this.addItemFromLabel( this.$input.val() );
+ this.clearInput();
+};
+
+/**
+ * Handles popup focus out events.
+ *
+ * @private
+ * @param {jQuery.Event} e Focus out event
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.onPopupFocusOut = function () {
+ var widget = this.popup;
+
+ setTimeout( function () {
+ if (
+ widget.isVisible() &&
+ !OO.ui.contains( widget.$element.add( widget.$autoCloseIgnore ).get(), document.activeElement, true )
+ ) {
+ widget.toggle( false );
+ }
+ } );
+};
+
+/**
+ * Handle mouse down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.onMouseDown = function ( e ) {
+ if ( e.which === OO.ui.MouseButtons.LEFT ) {
+ this.focus();
+ return false;
+ } else {
+ this.updateInputSize();
+ }
+};
+
+/**
+ * Handle key press events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key press event
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.onKeyPress = function ( e ) {
+ if ( !this.isDisabled() ) {
+ if ( e.which === OO.ui.Keys.ESCAPE ) {
+ this.clearInput();
+ return false;
+ }
+
+ if ( !this.popup ) {
+ this.menu.toggle( true );
+ if ( e.which === OO.ui.Keys.ENTER ) {
+ if ( this.addItemFromLabel( this.$input.val() ) ) {
+ this.clearInput();
+ }
+ return false;
+ }
+
+ // Make sure the input gets resized.
+ setTimeout( this.updateInputSize.bind( this ), 0 );
+ }
+ }
+};
+
+/**
+ * Handle key down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.onKeyDown = function ( e ) {
+ if (
+ !this.isDisabled() &&
+ this.$input.val() === '' &&
+ this.items.length
+ ) {
+ // 'keypress' event is not triggered for Backspace
+ if ( e.keyCode === OO.ui.Keys.BACKSPACE ) {
+ if ( e.metaKey || e.ctrlKey ) {
+ this.removeItems( this.items.slice( -1 ) );
+ } else {
+ this.editItem( this.items[ this.items.length - 1 ] );
+ }
+ return false;
+ } else if ( e.keyCode === OO.ui.Keys.LEFT ) {
+ this.getPreviousItem().focus();
+ } else if ( e.keyCode === OO.ui.Keys.RIGHT ) {
+ this.getNextItem().focus();
+ }
+ }
+};
+
+/**
+ * Update the dimensions of the text input field to encompass all available area.
+ *
+ * @private
+ * @param {jQuery.Event} e Event of some sort
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.updateInputSize = function () {
+ var $lastItem, direction, contentWidth, currentWidth, bestWidth;
+ if ( this.$input && !this.isDisabled() ) {
+ this.$input.css( 'width', '1em' );
+ $lastItem = this.$group.children().last();
+ direction = OO.ui.Element.static.getDir( this.$handle );
+
+ // Get the width of the input with the placeholder text as
+ // the value and save it so that we don't keep recalculating
+ if (
+ this.contentWidthWithPlaceholder === undefined &&
+ this.$input.val() === '' &&
+ this.$input.attr( 'placeholder' ) !== undefined
+ ) {
+ this.$input.val( this.$input.attr( 'placeholder' ) );
+ this.contentWidthWithPlaceholder = this.$input[ 0 ].scrollWidth;
+ this.$input.val( '' );
+
+ }
+
+ // Always keep the input wide enough for the placeholder text
+ contentWidth = Math.max(
+ this.$input[ 0 ].scrollWidth,
+ // undefined arguments in Math.max lead to NaN
+ ( this.contentWidthWithPlaceholder === undefined ) ?
+ 0 : this.contentWidthWithPlaceholder
+ );
+ currentWidth = this.$input.width();
+
+ if ( contentWidth < currentWidth ) {
+ this.updateIfHeightChanged();
+ // All is fine, don't perform expensive calculations
+ return;
+ }
+
+ if ( $lastItem.length === 0 ) {
+ bestWidth = this.$content.innerWidth();
+ } else {
+ bestWidth = direction === 'ltr' ?
+ this.$content.innerWidth() - $lastItem.position().left - $lastItem.outerWidth() :
+ $lastItem.position().left;
+ }
+
+ // Some safety margin for sanity, because I *really* don't feel like finding out where the few
+ // pixels this is off by are coming from.
+ bestWidth -= 10;
+ if ( contentWidth > bestWidth ) {
+ // This will result in the input getting shifted to the next line
+ bestWidth = this.$content.innerWidth() - 10;
+ }
+ this.$input.width( Math.floor( bestWidth ) );
+ this.updateIfHeightChanged();
+ } else {
+ this.updateIfHeightChanged();
+ }
+};
+
+/**
+ * Determine if widget height changed, and if so, update menu position and emit 'resize' event.
+ *
+ * @private
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.updateIfHeightChanged = function () {
+ var height = this.$element.height();
+ if ( height !== this.height ) {
+ this.height = height;
+ this.menu.position();
+ if ( this.popup ) {
+ this.popup.updateDimensions();
+ }
+ this.emit( 'resize' );
+ }
+};
+
+/**
+ * Handle menu choose events.
+ *
+ * @private
+ * @param {OO.ui.OptionWidget} item Chosen item
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.onMenuChoose = function ( item ) {
+ if ( item && item.isVisible() ) {
+ this.addItemsFromData( [ item.getData() ] );
+ this.clearInput();
+ }
+};
+
+/**
+ * Handle menu toggle events.
+ *
+ * @private
+ * @param {boolean} isVisible Menu toggle event
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.onMenuToggle = function ( isVisible ) {
+ this.$element.toggleClass( 'oo-ui-capsuleMultiselectWidget-open', isVisible );
+};
+
+/**
+ * Handle menu item change events.
+ *
+ * @private
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.onMenuItemsChange = function () {
+ this.setItemsFromData( this.getItemsData() );
+ this.$element.toggleClass( 'oo-ui-capsuleMultiselectWidget-empty', this.menu.isEmpty() );
+};
+
+/**
+ * Clear the input field
+ *
+ * @private
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.clearInput = function () {
+ if ( this.$input ) {
+ this.$input.val( '' );
+ this.updateInputSize();
+ }
+ if ( this.popup ) {
+ this.popup.toggle( false );
+ }
+ this.menu.toggle( false );
+ this.menu.selectItem();
+ this.menu.highlightItem();
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.setDisabled = function ( disabled ) {
+ var i, len;
+
+ // Parent method
+ OO.ui.CapsuleMultiselectWidget.parent.prototype.setDisabled.call( this, disabled );
+
+ if ( this.$input ) {
+ this.$input.prop( 'disabled', this.isDisabled() );
+ }
+ if ( this.menu ) {
+ this.menu.setDisabled( this.isDisabled() );
+ }
+ if ( this.popup ) {
+ this.popup.setDisabled( this.isDisabled() );
+ }
+
+ if ( this.items ) {
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ this.items[ i ].updateDisabled();
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Focus the widget
+ *
+ * @chainable
+ */
+OO.ui.CapsuleMultiselectWidget.prototype.focus = function () {
+ if ( !this.isDisabled() ) {
+ if ( this.popup ) {
+ this.popup.setSize( this.$handle.outerWidth() );
+ this.popup.toggle( true );
+ OO.ui.findFocusable( this.popup.$element ).focus();
+ } else {
+ OO.ui.mixin.TabIndexedElement.prototype.focus.call( this );
+ }
+ }
+ return this;
+};
+
+/**
+ * TagItemWidgets are used within a {@link OO.ui.TagMultiselectWidget
+ * TagMultiselectWidget} to display the selected items.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.ItemWidget
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.FlaggedElement
+ * @mixins OO.ui.mixin.TabIndexedElement
+ * @mixins OO.ui.mixin.DraggableElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration object
+ * @cfg {boolean} [valid=true] Item is valid
+ */
+OO.ui.TagItemWidget = function OoUiTagItemWidget( config ) {
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.TagItemWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.ItemWidget.call( this );
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.FlaggedElement.call( this, config );
+ OO.ui.mixin.TabIndexedElement.call( this, config );
+ OO.ui.mixin.DraggableElement.call( this, config );
+
+ this.valid = config.valid === undefined ? true : !!config.valid;
+
+ this.closeButton = new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'close',
+ tabIndex: -1,
+ title: OO.ui.msg( 'ooui-item-remove' )
+ } );
+ this.closeButton.setDisabled( this.isDisabled() );
+
+ // Events
+ this.closeButton
+ .connect( this, { click: 'remove' } );
+ this.$element
+ .on( 'click', this.select.bind( this ) )
+ .on( 'keydown', this.onKeyDown.bind( this ) )
+ // Prevent propagation of mousedown; the tag item "lives" in the
+ // clickable area of the TagMultiselectWidget, which listens to
+ // mousedown to open the menu or popup. We want to prevent that
+ // for clicks specifically on the tag itself, so the actions taken
+ // are more deliberate. When the tag is clicked, it will emit the
+ // selection event (similar to how #OO.ui.MultioptionWidget emits 'change')
+ // and can be handled separately.
+ .on( 'mousedown', function ( e ) { e.stopPropagation(); } );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-tagItemWidget' )
+ .append( this.$label, this.closeButton.$element );
+};
+
+/* Initialization */
+
+OO.inheritClass( OO.ui.TagItemWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.TagItemWidget, OO.ui.mixin.ItemWidget );
+OO.mixinClass( OO.ui.TagItemWidget, OO.ui.mixin.LabelElement );
+OO.mixinClass( OO.ui.TagItemWidget, OO.ui.mixin.FlaggedElement );
+OO.mixinClass( OO.ui.TagItemWidget, OO.ui.mixin.TabIndexedElement );
+OO.mixinClass( OO.ui.TagItemWidget, OO.ui.mixin.DraggableElement );
+
+/* Events */
+
+/**
+ * @event remove
+ *
+ * A remove action was performed on the item
+ */
+
+/**
+ * @event navigate
+ * @param {string} direction Direction of the movement, forward or backwards
+ *
+ * A navigate action was performed on the item
+ */
+
+/**
+ * @event select
+ *
+ * The tag widget was selected. This can occur when the widget
+ * is either clicked or enter was pressed on it.
+ */
+
+/**
+ * @event valid
+ * @param {boolean} isValid Item is valid
+ *
+ * Item validity has changed
+ */
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.TagItemWidget.prototype.setDisabled = function ( state ) {
+ // Parent method
+ OO.ui.TagItemWidget.parent.prototype.setDisabled.call( this, state );
+
+ if ( this.closeButton ) {
+ this.closeButton.setDisabled( state );
+ }
+ return this;
+};
+
+/**
+ * Handle removal of the item
+ *
+ * This is mainly for extensibility concerns, so other children
+ * of this class can change the behavior if they need to. This
+ * is called by both clicking the 'remove' button but also
+ * on keypress, which is harder to override if needed.
+ *
+ * @fires remove
+ */
+OO.ui.TagItemWidget.prototype.remove = function () {
+ if ( !this.isDisabled() ) {
+ this.emit( 'remove' );
+ }
+};
+
+/**
+ * Handle a keydown event on the widget
+ *
+ * @fires navigate
+ * @fires remove
+ * @param {jQuery.Event} e Key down event
+ * @return {boolean|undefined} false to stop the operation
+ */
+OO.ui.TagItemWidget.prototype.onKeyDown = function ( e ) {
+ var movement;
+
+ if ( e.keyCode === OO.ui.Keys.BACKSPACE || e.keyCode === OO.ui.Keys.DELETE ) {
+ this.remove();
+ return false;
+ } else if ( e.keyCode === OO.ui.Keys.ENTER ) {
+ this.select();
+ return false;
+ } else if (
+ e.keyCode === OO.ui.Keys.LEFT ||
+ e.keyCode === OO.ui.Keys.RIGHT
+ ) {
+ if ( OO.ui.Element.static.getDir( this.$element ) === 'rtl' ) {
+ movement = {
+ left: 'forwards',
+ right: 'backwards'
+ };
+ } else {
+ movement = {
+ left: 'backwards',
+ right: 'forwards'
+ };
+ }
+
+ this.emit(
+ 'navigate',
+ e.keyCode === OO.ui.Keys.LEFT ?
+ movement.left : movement.right
+ );
+ }
+};
+
+/**
+ * Select this item
+ *
+ * @fires select
+ */
+OO.ui.TagItemWidget.prototype.select = function () {
+ if ( !this.isDisabled() ) {
+ this.emit( 'select' );
+ }
+};
+
+/**
+ * Set the valid state of this item
+ *
+ * @param {boolean} [valid] Item is valid
+ * @fires valid
+ */
+OO.ui.TagItemWidget.prototype.toggleValid = function ( valid ) {
+ valid = valid === undefined ? !this.valid : !!valid;
+
+ if ( this.valid !== valid ) {
+ this.valid = valid;
+
+ this.setFlags( { invalid: !this.valid } );
+
+ this.emit( 'valid', this.valid );
+ }
+};
+
+/**
+ * Check whether the item is valid
+ *
+ * @return {boolean} Item is valid
+ */
+OO.ui.TagItemWidget.prototype.isValid = function () {
+ return this.valid;
+};
+
+/**
+ * A basic tag multiselect widget, similar in concept to {@link OO.ui.ComboBoxInputWidget combo box widget}
+ * that allows the user to add multiple values that are displayed in a tag area.
+ *
+ * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * This widget is a base widget; see {@link OO.ui.MenuTagMultiselectWidget MenuTagMultiselectWidget} and
+ * {@link OO.ui.PopupTagMultiselectWidget PopupTagMultiselectWidget} for the implementations that use
+ * a menu and a popup respectively.
+ *
+ * @example
+ * // Example: A basic TagMultiselectWidget.
+ * var widget = new OO.ui.TagMultiselectWidget( {
+ * inputPosition: 'outline',
+ * allowedValues: [ 'Option 1', 'Option 2', 'Option 3' ],
+ * selected: [ 'Option 1' ]
+ * } );
+ * $( 'body' ).append( widget.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.GroupWidget
+ * @mixins OO.ui.mixin.DraggableGroupElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.TabIndexedElement
+ * @mixins OO.ui.mixin.FlaggedElement
+ *
+ * @constructor
+ * @param {Object} config Configuration object
+ * @cfg {Object} [input] Configuration options for the input widget
+ * @cfg {OO.ui.InputWidget} [inputWidget] An optional input widget. If given, it will
+ * replace the input widget used in the TagMultiselectWidget. If not given,
+ * TagMultiselectWidget creates its own.
+ * @cfg {boolean} [inputPosition='inline'] Position of the input. Options are:
+ * - inline: The input is invisible, but exists inside the tag list, so
+ * the user types into the tag groups to add tags.
+ * - outline: The input is underneath the tag area.
+ * - none: No input supplied
+ * @cfg {boolean} [allowEditTags=true] Allow editing of the tags by clicking them
+ * @cfg {boolean} [allowArbitrary=false] Allow data items to be added even if
+ * not present in the menu.
+ * @cfg {Object[]} [allowedValues] An array representing the allowed items
+ * by their datas.
+ * @cfg {boolean} [allowDuplicates=false] Allow duplicate items to be added
+ * @cfg {boolean} [allowDisplayInvalidTags=false] Allow the display of
+ * invalid tags. These tags will display with an invalid state, and
+ * the widget as a whole will have an invalid state if any invalid tags
+ * are present.
+ * @cfg {boolean} [allowReordering=true] Allow reordering of the items
+ * @cfg {Object[]|String[]} [selected] A set of selected tags. If given,
+ * these will appear in the tag list on initialization, as long as they
+ * pass the validity tests.
+ */
+OO.ui.TagMultiselectWidget = function OoUiTagMultiselectWidget( config ) {
+ var inputEvents,
+ rAF = window.requestAnimationFrame || setTimeout,
+ widget = this,
+ $tabFocus = $( '<span>' )
+ .addClass( 'oo-ui-tagMultiselectWidget-focusTrap' );
+
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.TagMultiselectWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.GroupWidget.call( this, config );
+ OO.ui.mixin.IndicatorElement.call( this, config );
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.TabIndexedElement.call( this, config );
+ OO.ui.mixin.FlaggedElement.call( this, config );
+ OO.ui.mixin.DraggableGroupElement.call( this, config );
+
+ this.toggleDraggable(
+ config.allowReordering === undefined ?
+ true : !!config.allowReordering
+ );
+
+ this.inputPosition =
+ this.constructor.static.allowedInputPositions.indexOf( config.inputPosition ) > -1 ?
+ config.inputPosition : 'inline';
+ this.allowEditTags = config.allowEditTags === undefined ? true : !!config.allowEditTags;
+ this.allowArbitrary = !!config.allowArbitrary;
+ this.allowDuplicates = !!config.allowDuplicates;
+ this.allowedValues = config.allowedValues || [];
+ this.allowDisplayInvalidTags = config.allowDisplayInvalidTags;
+ this.hasInput = this.inputPosition !== 'none';
+ this.height = null;
+ this.valid = true;
+
+ this.$content = $( '<div>' )
+ .addClass( 'oo-ui-tagMultiselectWidget-content' );
+ this.$handle = $( '<div>' )
+ .addClass( 'oo-ui-tagMultiselectWidget-handle' )
+ .append(
+ this.$indicator,
+ this.$icon,
+ this.$content
+ .append(
+ this.$group
+ .addClass( 'oo-ui-tagMultiselectWidget-group' )
+ )
+ );
+
+ // Events
+ this.aggregate( {
+ remove: 'itemRemove',
+ navigate: 'itemNavigate',
+ select: 'itemSelect'
+ } );
+ this.connect( this, {
+ itemRemove: 'onTagRemove',
+ itemSelect: 'onTagSelect',
+ itemNavigate: 'onTagNavigate',
+ change: 'onChangeTags'
+ } );
+ this.$handle.on( {
+ mousedown: this.onMouseDown.bind( this )
+ } );
+
+ // Initialize
+ this.$element
+ .addClass( 'oo-ui-tagMultiselectWidget' )
+ .append( this.$handle );
+
+ if ( this.hasInput ) {
+ if ( config.inputWidget ) {
+ this.input = config.inputWidget;
+ } else {
+ this.input = new OO.ui.TextInputWidget( $.extend( {
+ placeholder: config.placeholder,
+ classes: [ 'oo-ui-tagMultiselectWidget-input' ]
+ }, config.input ) );
+ }
+ this.input.setDisabled( this.isDisabled() );
+
+ inputEvents = {
+ focus: this.onInputFocus.bind( this ),
+ blur: this.onInputBlur.bind( this ),
+ 'propertychange change click mouseup keydown keyup input cut paste select focus':
+ OO.ui.debounce( this.updateInputSize.bind( this ) ),
+ keydown: this.onInputKeyDown.bind( this ),
+ keypress: this.onInputKeyPress.bind( this )
+ };
+
+ this.input.$input.on( inputEvents );
+
+ if ( this.inputPosition === 'outline' ) {
+ // Override max-height for the input widget
+ // in the case the widget is outline so it can
+ // stretch all the way if the widet is wide
+ this.input.$element.css( 'max-width', 'inherit' );
+ this.$element
+ .addClass( 'oo-ui-tagMultiselectWidget-outlined' )
+ .append( this.input.$element );
+ } else {
+ this.$element.addClass( 'oo-ui-tagMultiselectWidget-inlined' );
+ // HACK: When the widget is using 'inline' input, the
+ // behavior needs to only use the $input itself
+ // so we style and size it accordingly (otherwise
+ // the styling and sizing can get very convoluted
+ // when the wrapping divs and other elements)
+ // We are taking advantage of still being able to
+ // call the widget itself for operations like
+ // .getValue() and setDisabled() and .focus() but
+ // having only the $input attached to the DOM
+ this.$content.append( this.input.$input );
+ }
+ } else {
+ this.$content.append( $tabFocus );
+ }
+
+ this.setTabIndexedElement(
+ this.hasInput ?
+ this.input.$input :
+ $tabFocus
+ );
+
+ if ( config.selected ) {
+ this.setValue( config.selected );
+ }
+
+ // HACK: Input size needs to be calculated after everything
+ // else is rendered
+ rAF( function () {
+ if ( widget.hasInput ) {
+ widget.updateInputSize();
+ }
+ } );
+};
+
+/* Initialization */
+
+OO.inheritClass( OO.ui.TagMultiselectWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.GroupWidget );
+OO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.DraggableGroupElement );
+OO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.IndicatorElement );
+OO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.TabIndexedElement );
+OO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.FlaggedElement );
+
+/* Static properties */
+
+/**
+ * Allowed input positions.
+ * - inline: The input is inside the tag list
+ * - outline: The input is under the tag list
+ * - none: There is no input
+ *
+ * @property {Array}
+ */
+OO.ui.TagMultiselectWidget.static.allowedInputPositions = [ 'inline', 'outline', 'none' ];
+
+/* Methods */
+
+/**
+ * Handle mouse down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse down event
+ * @return {boolean} False to prevent defaults
+ */
+OO.ui.TagMultiselectWidget.prototype.onMouseDown = function ( e ) {
+ if ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {
+ this.focus();
+ return false;
+ }
+};
+
+/**
+ * Handle key press events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key press event
+ * @return {boolean} Whether to prevent defaults
+ */
+OO.ui.TagMultiselectWidget.prototype.onInputKeyPress = function ( e ) {
+ var stopOrContinue,
+ withMetaKey = e.metaKey || e.ctrlKey;
+
+ if ( !this.isDisabled() ) {
+ if ( e.which === OO.ui.Keys.ENTER ) {
+ stopOrContinue = this.doInputEnter( e, withMetaKey );
+ }
+
+ // Make sure the input gets resized.
+ setTimeout( this.updateInputSize.bind( this ), 0 );
+ return stopOrContinue;
+ }
+};
+
+/**
+ * Handle key down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key down event
+ * @return {boolean}
+ */
+OO.ui.TagMultiselectWidget.prototype.onInputKeyDown = function ( e ) {
+ var movement, direction,
+ withMetaKey = e.metaKey || e.ctrlKey;
+
+ if ( !this.isDisabled() ) {
+ // 'keypress' event is not triggered for Backspace
+ if ( e.keyCode === OO.ui.Keys.BACKSPACE ) {
+ return this.doInputBackspace( e, withMetaKey );
+ } else if ( e.keyCode === OO.ui.Keys.ESCAPE ) {
+ return this.doInputEscape( e );
+ } else if (
+ e.keyCode === OO.ui.Keys.LEFT ||
+ e.keyCode === OO.ui.Keys.RIGHT
+ ) {
+ if ( OO.ui.Element.static.getDir( this.$element ) === 'rtl' ) {
+ movement = {
+ left: 'forwards',
+ right: 'backwards'
+ };
+ } else {
+ movement = {
+ left: 'backwards',
+ right: 'forwards'
+ };
+ }
+ direction = e.keyCode === OO.ui.Keys.LEFT ?
+ movement.left : movement.right;
+
+ return this.doInputArrow( e, direction, withMetaKey );
+ }
+ }
+};
+
+/**
+ * Respond to input focus event
+ */
+OO.ui.TagMultiselectWidget.prototype.onInputFocus = function () {
+ this.$element.addClass( 'oo-ui-tagMultiselectWidget-focus' );
+};
+
+/**
+ * Respond to input blur event
+ */
+OO.ui.TagMultiselectWidget.prototype.onInputBlur = function () {
+ this.$element.removeClass( 'oo-ui-tagMultiselectWidget-focus' );
+};
+
+/**
+ * Perform an action after the enter key on the input
+ *
+ * @param {jQuery.Event} e Event data
+ * @param {boolean} [withMetaKey] Whether this key was pressed with
+ * a meta key like 'ctrl'
+ * @return {boolean} Whether to prevent defaults
+ */
+OO.ui.TagMultiselectWidget.prototype.doInputEnter = function () {
+ this.addTagFromInput();
+ return false;
+};
+
+/**
+ * Perform an action responding to the enter key on the input
+ *
+ * @param {jQuery.Event} e Event data
+ * @param {boolean} [withMetaKey] Whether this key was pressed with
+ * a meta key like 'ctrl'
+ * @return {boolean} Whether to prevent defaults
+ */
+OO.ui.TagMultiselectWidget.prototype.doInputBackspace = function ( e, withMetaKey ) {
+ var items, item;
+
+ if (
+ this.inputPosition === 'inline' &&
+ this.input.getValue() === '' &&
+ !this.isEmpty()
+ ) {
+ // Delete the last item
+ items = this.getItems();
+ item = items[ items.length - 1 ];
+ this.removeItems( [ item ] );
+ // If Ctrl/Cmd was pressed, delete item entirely.
+ // Otherwise put it into the text field for editing.
+ if ( !withMetaKey ) {
+ this.input.setValue( item.getData() );
+ }
+
+ return false;
+ }
+};
+
+/**
+ * Perform an action after the escape key on the input
+ *
+ * @param {jQuery.Event} e Event data
+ */
+OO.ui.TagMultiselectWidget.prototype.doInputEscape = function () {
+ this.clearInput();
+};
+
+/**
+ * Perform an action after the arrow key on the input, select the previous
+ * or next item from the input.
+ * See #getPreviousItem and #getNextItem
+ *
+ * @param {jQuery.Event} e Event data
+ * @param {string} direction Direction of the movement; forwards or backwards
+ * @param {boolean} [withMetaKey] Whether this key was pressed with
+ * a meta key like 'ctrl'
+ */
+OO.ui.TagMultiselectWidget.prototype.doInputArrow = function ( e, direction ) {
+ if (
+ this.inputPosition === 'inline' &&
+ !this.isEmpty()
+ ) {
+ if ( direction === 'backwards' ) {
+ // Get previous item
+ this.getPreviousItem().focus();
+ } else {
+ // Get next item
+ this.getNextItem().focus();
+ }
+ }
+};
+
+/**
+ * Respond to item select event
+ *
+ * @param {OO.ui.TagItemWidget} item Selected item
+ */
+OO.ui.TagMultiselectWidget.prototype.onTagSelect = function ( item ) {
+ if ( this.hasInput && this.allowEditTags ) {
+ if ( this.input.getValue() ) {
+ this.addTagFromInput();
+ }
+ // 1. Get the label of the tag into the input
+ this.input.setValue( item.getData() );
+ // 2. Remove the tag
+ this.removeItems( [ item ] );
+ // 3. Focus the input
+ this.focus();
+ }
+};
+
+/**
+ * Respond to change event, where items were added, removed, or cleared.
+ */
+OO.ui.TagMultiselectWidget.prototype.onChangeTags = function () {
+ this.toggleValid( this.checkValidity() );
+ if ( this.hasInput ) {
+ this.updateInputSize();
+ }
+ this.updateIfHeightChanged();
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.TagMultiselectWidget.prototype.setDisabled = function ( isDisabled ) {
+ // Parent method
+ OO.ui.TagMultiselectWidget.parent.prototype.setDisabled.call( this, isDisabled );
+
+ if ( this.hasInput && this.input ) {
+ this.input.setDisabled( !!isDisabled );
+ }
+
+ if ( this.items ) {
+ this.getItems().forEach( function ( item ) {
+ item.setDisabled( !!isDisabled );
+ } );
+ }
+};
+
+/**
+ * Respond to tag remove event
+ * @param {OO.ui.TagItemWidget} item Removed tag
+ */
+OO.ui.TagMultiselectWidget.prototype.onTagRemove = function ( item ) {
+ this.removeTagByData( item.getData() );
+};
+
+/**
+ * Respond to navigate event on the tag
+ *
+ * @param {OO.ui.TagItemWidget} item Removed tag
+ * @param {string} direction Direction of movement; 'forwards' or 'backwards'
+ */
+OO.ui.TagMultiselectWidget.prototype.onTagNavigate = function ( item, direction ) {
+ if ( direction === 'forwards' ) {
+ this.getNextItem( item ).focus();
+ } else {
+ this.getPreviousItem( item ).focus();
+ }
+};
+
+/**
+ * Add tag from input value
+ */
+OO.ui.TagMultiselectWidget.prototype.addTagFromInput = function () {
+ var val = this.input.getValue(),
+ isValid = this.isAllowedData( val );
+
+ if ( !val ) {
+ return;
+ }
+
+ if ( isValid || this.allowDisplayInvalidTags ) {
+ this.addTag( val );
+ this.clearInput();
+ this.focus();
+ }
+};
+
+/**
+ * Clear the input
+ */
+OO.ui.TagMultiselectWidget.prototype.clearInput = function () {
+ this.input.setValue( '' );
+};
+
+/**
+ * Check whether the given value is a duplicate of an existing
+ * tag already in the list.
+ *
+ * @param {string|Object} data Requested value
+ * @return {boolean} Value is duplicate
+ */
+OO.ui.TagMultiselectWidget.prototype.isDuplicateData = function ( data ) {
+ return !!this.getItemFromData( data );
+};
+
+/**
+ * Check whether a given value is allowed to be added
+ *
+ * @param {string|Object} data Requested value
+ * @return {boolean} Value is allowed
+ */
+OO.ui.TagMultiselectWidget.prototype.isAllowedData = function ( data ) {
+ if (
+ !this.allowDuplicates &&
+ this.isDuplicateData( data )
+ ) {
+ return false;
+ }
+
+ if ( this.allowArbitrary ) {
+ return true;
+ }
+
+ // Check with allowed values
+ if (
+ this.getAllowedValues().some( function ( value ) {
+ return data === value;
+ } )
+ ) {
+ return true;
+ }
+
+ return false;
+};
+
+/**
+ * Get the allowed values list
+ *
+ * @return {string[]} Allowed data values
+ */
+OO.ui.TagMultiselectWidget.prototype.getAllowedValues = function () {
+ return this.allowedValues;
+};
+
+/**
+ * Add a value to the allowed values list
+ *
+ * @param {string} value Allowed data value
+ */
+OO.ui.TagMultiselectWidget.prototype.addAllowedValue = function ( value ) {
+ if ( this.allowedValues.indexOf( value ) === -1 ) {
+ this.allowedValues.push( value );
+ }
+};
+
+/**
+ * Get the datas of the currently selected items
+ *
+ * @return {string[]|Object[]} Datas of currently selected items
+ */
+OO.ui.TagMultiselectWidget.prototype.getValue = function () {
+ return this.getItems()
+ .filter( function ( item ) {
+ return item.isValid();
+ } )
+ .map( function ( item ) {
+ return item.getData();
+ } );
+};
+
+/**
+ * Set the value of this widget by datas.
+ *
+ * @param {string|string[]|Object|Object[]} valueObject An object representing the data
+ * and label of the value. If the widget allows arbitrary values,
+ * the items will be added as-is. Otherwise, the data value will
+ * be checked against allowedValues.
+ * This object must contain at least a data key. Example:
+ * { data: 'foo', label: 'Foo item' }
+ * For multiple items, use an array of objects. For example:
+ * [
+ * { data: 'foo', label: 'Foo item' },
+ * { data: 'bar', label: 'Bar item' }
+ * ]
+ * Value can also be added with plaintext array, for example:
+ * [ 'foo', 'bar', 'bla' ] or a single string, like 'foo'
+ */
+OO.ui.TagMultiselectWidget.prototype.setValue = function ( valueObject ) {
+ valueObject = Array.isArray( valueObject ) ? valueObject : [ valueObject ];
+
+ this.clearItems();
+ valueObject.forEach( function ( obj ) {
+ if ( typeof obj === 'string' ) {
+ this.addTag( obj );
+ } else {
+ this.addTag( obj.data, obj.label );
+ }
+ }.bind( this ) );
+};
+
+/**
+ * Add tag to the display area
+ *
+ * @param {string|Object} data Tag data
+ * @param {string} [label] Tag label. If no label is provided, the
+ * stringified version of the data will be used instead.
+ * @return {boolean} Item was added successfully
+ */
+OO.ui.TagMultiselectWidget.prototype.addTag = function ( data, label ) {
+ var newItemWidget,
+ isValid = this.isAllowedData( data );
+
+ if ( isValid || this.allowDisplayInvalidTags ) {
+ newItemWidget = this.createTagItemWidget( data, label );
+ newItemWidget.toggleValid( isValid );
+ this.addItems( [ newItemWidget ] );
+ return true;
+ }
+ return false;
+};
+
+/**
+ * Remove tag by its data property.
+ *
+ * @param {string|Object} data Tag data
+ */
+OO.ui.TagMultiselectWidget.prototype.removeTagByData = function ( data ) {
+ var item = this.getItemFromData( data );
+
+ this.removeItems( [ item ] );
+};
+
+/**
+ * Construct a OO.ui.TagItemWidget (or a subclass thereof) from given label and data.
+ *
+ * @protected
+ * @param {string} data Item data
+ * @param {string} label The label text.
+ * @return {OO.ui.TagItemWidget}
+ */
+OO.ui.TagMultiselectWidget.prototype.createTagItemWidget = function ( data, label ) {
+ label = label || data;
+
+ return new OO.ui.TagItemWidget( { data: data, label: label } );
+};
+
+/**
+ * Given an item, returns the item after it. If the item is already the
+ * last item, return `this.input`. If no item is passed, returns the
+ * very first item.
+ *
+ * @protected
+ * @param {OO.ui.TagItemWidget} [item] Tag item
+ * @return {OO.ui.Widget} The next widget available.
+ */
+OO.ui.TagMultiselectWidget.prototype.getNextItem = function ( item ) {
+ var itemIndex = this.items.indexOf( item );
+
+ if ( item === undefined || itemIndex === -1 ) {
+ return this.items[ 0 ];
+ }
+
+ if ( itemIndex === this.items.length - 1 ) { // Last item
+ if ( this.hasInput ) {
+ return this.input;
+ } else {
+ // Return first item
+ return this.items[ 0 ];
+ }
+ } else {
+ return this.items[ itemIndex + 1 ];
+ }
+};
+
+/**
+ * Given an item, returns the item before it. If the item is already the
+ * first item, return `this.input`. If no item is passed, returns the
+ * very last item.
+ *
+ * @protected
+ * @param {OO.ui.TagItemWidget} [item] Tag item
+ * @return {OO.ui.Widget} The previous widget available.
+ */
+OO.ui.TagMultiselectWidget.prototype.getPreviousItem = function ( item ) {
+ var itemIndex = this.items.indexOf( item );
+
+ if ( item === undefined || itemIndex === -1 ) {
+ return this.items[ this.items.length - 1 ];
+ }
+
+ if ( itemIndex === 0 ) {
+ if ( this.hasInput ) {
+ return this.input;
+ } else {
+ // Return the last item
+ return this.items[ this.items.length - 1 ];
+ }
+ } else {
+ return this.items[ itemIndex - 1 ];
+ }
+};
+
+/**
+ * Update the dimensions of the text input field to encompass all available area.
+ * This is especially relevant for when the input is at the edge of a line
+ * and should get smaller. The usual operation (as an inline-block with min-width)
+ * does not work in that case, pushing the input downwards to the next line.
+ *
+ * @private
+ */
+OO.ui.TagMultiselectWidget.prototype.updateInputSize = function () {
+ var $lastItem, direction, contentWidth, currentWidth, bestWidth;
+ if ( this.inputPosition === 'inline' && !this.isDisabled() ) {
+ if ( this.input.$input[ 0 ].scrollWidth === 0 ) {
+ // Input appears to be attached but not visible.
+ // Don't attempt to adjust its size, because our measurements
+ // are going to fail anyway.
+ return;
+ }
+ this.input.$input.css( 'width', '1em' );
+ $lastItem = this.$group.children().last();
+ direction = OO.ui.Element.static.getDir( this.$handle );
+
+ // Get the width of the input with the placeholder text as
+ // the value and save it so that we don't keep recalculating
+ if (
+ this.contentWidthWithPlaceholder === undefined &&
+ this.input.getValue() === '' &&
+ this.input.$input.attr( 'placeholder' ) !== undefined
+ ) {
+ this.input.setValue( this.input.$input.attr( 'placeholder' ) );
+ this.contentWidthWithPlaceholder = this.input.$input[ 0 ].scrollWidth;
+ this.input.setValue( '' );
+
+ }
+
+ // Always keep the input wide enough for the placeholder text
+ contentWidth = Math.max(
+ this.input.$input[ 0 ].scrollWidth,
+ // undefined arguments in Math.max lead to NaN
+ ( this.contentWidthWithPlaceholder === undefined ) ?
+ 0 : this.contentWidthWithPlaceholder
+ );
+ currentWidth = this.input.$input.width();
+
+ if ( contentWidth < currentWidth ) {
+ this.updateIfHeightChanged();
+ // All is fine, don't perform expensive calculations
+ return;
+ }
+
+ if ( $lastItem.length === 0 ) {
+ bestWidth = this.$content.innerWidth();
+ } else {
+ bestWidth = direction === 'ltr' ?
+ this.$content.innerWidth() - $lastItem.position().left - $lastItem.outerWidth() :
+ $lastItem.position().left;
+ }
+
+ // Some safety margin for sanity, because I *really* don't feel like finding out where the few
+ // pixels this is off by are coming from.
+ bestWidth -= 10;
+ if ( contentWidth > bestWidth ) {
+ // This will result in the input getting shifted to the next line
+ bestWidth = this.$content.innerWidth() - 10;
+ }
+ this.input.$input.width( Math.floor( bestWidth ) );
+ this.updateIfHeightChanged();
+ } else {
+ this.updateIfHeightChanged();
+ }
+};
+
+/**
+ * Determine if widget height changed, and if so,
+ * emit the resize event. This is useful for when there are either
+ * menus or popups attached to the bottom of the widget, to allow
+ * them to change their positioning in case the widget moved down
+ * or up.
+ *
+ * @private
+ */
+OO.ui.TagMultiselectWidget.prototype.updateIfHeightChanged = function () {
+ var height = this.$element.height();
+ if ( height !== this.height ) {
+ this.height = height;
+ this.emit( 'resize' );
+ }
+};
+
+/**
+ * Check whether all items in the widget are valid
+ *
+ * @return {boolean} Widget is valid
+ */
+OO.ui.TagMultiselectWidget.prototype.checkValidity = function () {
+ return this.getItems().every( function ( item ) {
+ return item.isValid();
+ } );
+};
+
+/**
+ * Set the valid state of this item
+ *
+ * @param {boolean} [valid] Item is valid
+ * @fires valid
+ */
+OO.ui.TagMultiselectWidget.prototype.toggleValid = function ( valid ) {
+ valid = valid === undefined ? !this.valid : !!valid;
+
+ if ( this.valid !== valid ) {
+ this.valid = valid;
+
+ this.setFlags( { invalid: !this.valid } );
+
+ this.emit( 'valid', this.valid );
+ }
+};
+
+/**
+ * Get the current valid state of the widget
+ *
+ * @return {boolean} Widget is valid
+ */
+OO.ui.TagMultiselectWidget.prototype.isValid = function () {
+ return this.valid;
+};
+
+/**
+ * PopupTagMultiselectWidget is a {@link OO.ui.TagMultiselectWidget OO.ui.TagMultiselectWidget} intended
+ * to use a popup. The popup can be configured to have a default input to insert values into the widget.
+ *
+ * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * @example
+ * // Example: A basic PopupTagMultiselectWidget.
+ * var widget = new OO.ui.PopupTagMultiselectWidget();
+ * $( 'body' ).append( widget.$element );
+ *
+ * // Example: A PopupTagMultiselectWidget with an external popup.
+ * var popupInput = new OO.ui.TextInputWidget(),
+ * widget = new OO.ui.PopupTagMultiselectWidget( {
+ * popupInput: popupInput,
+ * popup: {
+ * $content: popupInput.$element
+ * }
+ * } );
+ * $( 'body' ).append( widget.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options
+ *
+ * @class
+ * @extends OO.ui.TagMultiselectWidget
+ * @mixins OO.ui.mixin.PopupElement
+ *
+ * @param {Object} config Configuration object
+ * @cfg {jQuery} [$overlay] An overlay for the popup.
+ * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.
+ * @cfg {Object} [popup] Configuration options for the popup
+ * @cfg {OO.ui.InputWidget} [popupInput] An input widget inside the popup that will be
+ * focused when the popup is opened and will be used as replacement for the
+ * general input in the widget.
+ */
+OO.ui.PopupTagMultiselectWidget = function OoUiPopupTagMultiselectWidget( config ) {
+ var defaultInput,
+ defaultConfig = { popup: {} };
+
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.PopupTagMultiselectWidget.parent.call( this, $.extend( { inputPosition: 'none' }, config ) );
+
+ this.$overlay = config.$overlay || this.$element;
+
+ if ( !config.popup ) {
+ // For the default base implementation, we give a popup
+ // with an input widget inside it. For any other use cases
+ // the popup needs to be populated externally and the
+ // event handled to add tags separately and manually
+ defaultInput = new OO.ui.TextInputWidget();
+
+ defaultConfig.popupInput = defaultInput;
+ defaultConfig.popup.$content = defaultInput.$element;
+
+ this.$element.addClass( 'oo-ui-popupTagMultiselectWidget-defaultPopup' );
+ }
+
+ // Add overlay, and add that to the autoCloseIgnore
+ defaultConfig.popup.$overlay = this.$overlay;
+ defaultConfig.popup.$autoCloseIgnore = this.hasInput ?
+ this.input.$element.add( this.$overlay ) : this.$overlay;
+
+ // Allow extending any of the above
+ config = $.extend( defaultConfig, config );
+
+ // Mixin constructors
+ OO.ui.mixin.PopupElement.call( this, config );
+
+ if ( this.hasInput ) {
+ this.input.$input.on( 'focus', this.popup.toggle.bind( this.popup, true ) );
+ }
+
+ // Configuration options
+ this.popupInput = config.popupInput;
+ if ( this.popupInput ) {
+ this.popupInput.connect( this, {
+ enter: 'onPopupInputEnter'
+ } );
+ }
+
+ // Events
+ this.on( 'resize', this.popup.updateDimensions.bind( this.popup ) );
+ this.popup.connect( this, { toggle: 'onPopupToggle' } );
+ this.$tabIndexed
+ .on( 'focus', this.onFocus.bind( this ) );
+
+ // Initialize
+ this.$element
+ .append( this.popup.$element )
+ .addClass( 'oo-ui-popupTagMultiselectWidget' );
+};
+
+/* Initialization */
+
+OO.inheritClass( OO.ui.PopupTagMultiselectWidget, OO.ui.TagMultiselectWidget );
+OO.mixinClass( OO.ui.PopupTagMultiselectWidget, OO.ui.mixin.PopupElement );
+
+/* Methods */
+
+/**
+ * Focus event handler.
+ *
+ * @private
+ */
+OO.ui.PopupTagMultiselectWidget.prototype.onFocus = function () {
+ this.popup.toggle( true );
+};
+
+/**
+ * Respond to popup toggle event
+ *
+ * @param {boolean} isVisible Popup is visible
+ */
+OO.ui.PopupTagMultiselectWidget.prototype.onPopupToggle = function ( isVisible ) {
+ if ( isVisible && this.popupInput ) {
+ this.popupInput.focus();
+ }
+};
+
+/**
+ * Respond to popup input enter event
+ */
+OO.ui.PopupTagMultiselectWidget.prototype.onPopupInputEnter = function () {
+ if ( this.popupInput ) {
+ this.addTagByPopupValue( this.popupInput.getValue() );
+ this.popupInput.setValue( '' );
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.PopupTagMultiselectWidget.prototype.onTagSelect = function ( item ) {
+ if ( this.popupInput && this.allowEditTags ) {
+ this.popupInput.setValue( item.getData() );
+ this.removeItems( [ item ] );
+
+ this.popup.toggle( true );
+ this.popupInput.focus();
+ } else {
+ // Parent
+ OO.ui.PopupTagMultiselectWidget.parent.prototype.onTagSelect.call( this, item );
+ }
+};
+
+/**
+ * Add a tag by the popup value.
+ * Whatever is responsible for setting the value in the popup should call
+ * this method to add a tag, or use the regular methods like #addTag or
+ * #setValue directly.
+ *
+ * @param {string} data The value of item
+ * @param {string} [label] The label of the tag. If not given, the data is used.
+ */
+OO.ui.PopupTagMultiselectWidget.prototype.addTagByPopupValue = function ( data, label ) {
+ this.addTag( data, label );
+};
+
+/**
+ * MenuTagMultiselectWidget is a {@link OO.ui.TagMultiselectWidget OO.ui.TagMultiselectWidget} intended
+ * to use a menu of selectable options.
+ *
+ * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * @example
+ * // Example: A basic MenuTagMultiselectWidget.
+ * var widget = new OO.ui.MenuTagMultiselectWidget( {
+ * inputPosition: 'outline',
+ * options: [
+ * { data: 'option1', label: 'Option 1' },
+ * { data: 'option2', label: 'Option 2' },
+ * { data: 'option3', label: 'Option 3' },
+ * ],
+ * selected: [ 'option1', 'option2' ]
+ * } );
+ * $( 'body' ).append( widget.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options
+ *
+ * @class
+ * @extends OO.ui.TagMultiselectWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration object
+ * @cfg {Object} [menu] Configuration object for the menu widget
+ * @cfg {jQuery} [$overlay] An overlay for the menu.
+ * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.
+ * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`
+ */
+OO.ui.MenuTagMultiselectWidget = function OoUiMenuTagMultiselectWidget( config ) {
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.MenuTagMultiselectWidget.parent.call( this, config );
+
+ this.$overlay = config.$overlay || this.$element;
+
+ this.menu = this.createMenuWidget( $.extend( {
+ widget: this,
+ input: this.hasInput ? this.input : null,
+ $input: this.hasInput ? this.input.$input : null,
+ filterFromInput: !!this.hasInput,
+ $autoCloseIgnore: this.hasInput ?
+ this.input.$element.add( this.$overlay ) : this.$overlay,
+ $floatableContainer: this.hasInput && this.inputPosition === 'outline' ?
+ this.input.$element : this.$element,
+ $overlay: this.$overlay,
+ disabled: this.isDisabled()
+ }, config.menu ) );
+ this.addOptions( config.options || [] );
+
+ // Events
+ this.menu.connect( this, {
+ choose: 'onMenuChoose',
+ toggle: 'onMenuToggle'
+ } );
+ if ( this.hasInput ) {
+ this.input.connect( this, { change: 'onInputChange' } );
+ }
+ this.connect( this, { resize: 'onResize' } );
+
+ // Initialization
+ this.$overlay
+ .append( this.menu.$element );
+ this.$element
+ .addClass( 'oo-ui-menuTagMultiselectWidget' );
+ // TagMultiselectWidget already does this, but it doesn't work right because this.menu is not yet
+ // set up while the parent constructor runs, and #getAllowedValues rejects everything.
+ if ( config.selected ) {
+ this.setValue( config.selected );
+ }
+};
+
+/* Initialization */
+
+OO.inheritClass( OO.ui.MenuTagMultiselectWidget, OO.ui.TagMultiselectWidget );
+
+/* Methods */
+
+/**
+ * Respond to resize event
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.onResize = function () {
+ // Reposition the menu
+ this.menu.position();
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.onInputFocus = function () {
+ // Parent method
+ OO.ui.MenuTagMultiselectWidget.parent.prototype.onInputFocus.call( this );
+
+ this.menu.toggle( true );
+};
+
+/**
+ * Respond to input change event
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.onInputChange = function () {
+ this.menu.toggle( true );
+};
+
+/**
+ * Respond to menu choose event
+ *
+ * @param {OO.ui.OptionWidget} menuItem Chosen menu item
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.onMenuChoose = function ( menuItem ) {
+ // Add tag
+ this.addTag( menuItem.getData(), menuItem.getLabel() );
+};
+
+/**
+ * Respond to menu toggle event. Reset item highlights on hide.
+ *
+ * @param {boolean} isVisible The menu is visible
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.onMenuToggle = function ( isVisible ) {
+ if ( !isVisible ) {
+ this.menu.selectItem( null );
+ this.menu.highlightItem( null );
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.onTagSelect = function ( tagItem ) {
+ var menuItem = this.menu.getItemFromData( tagItem.getData() );
+ // Override the base behavior from TagMultiselectWidget; the base behavior
+ // in TagMultiselectWidget is to remove the tag to edit it in the input,
+ // but in our case, we want to utilize the menu selection behavior, and
+ // definitely not remove the item.
+
+ // Select the menu item
+ this.menu.selectItem( menuItem );
+
+ this.focus();
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.addTagFromInput = function () {
+ var inputValue = this.input.getValue(),
+ validated = false,
+ highlightedItem = this.menu.getHighlightedItem(),
+ item = this.menu.getItemFromData( inputValue );
+
+ // Override the parent method so we add from the menu
+ // rather than directly from the input
+
+ // Look for a highlighted item first
+ if ( highlightedItem ) {
+ validated = this.addTag( highlightedItem.getData(), highlightedItem.getLabel() );
+ } else if ( item ) {
+ // Look for the element that fits the data
+ validated = this.addTag( item.getData(), item.getLabel() );
+ } else {
+ // Otherwise, add the tag - the method will only add if the
+ // tag is valid or if invalid tags are allowed
+ validated = this.addTag( inputValue );
+ }
+
+ if ( validated ) {
+ this.clearInput();
+ this.focus();
+ }
+};
+
+/**
+ * Return the visible items in the menu. This is mainly used for when
+ * the menu is filtering results.
+ *
+ * @return {OO.ui.MenuOptionWidget[]} Visible results
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.getMenuVisibleItems = function () {
+ return this.menu.getItems().filter( function ( menuItem ) {
+ return menuItem.isVisible();
+ } );
+};
+
+/**
+ * Create the menu for this widget. This is in a separate method so that
+ * child classes can override this without polluting the constructor with
+ * unnecessary extra objects that will be overidden.
+ *
+ * @param {Object} menuConfig Configuration options
+ * @return {OO.ui.MenuSelectWidget} Menu widget
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.createMenuWidget = function ( menuConfig ) {
+ return new OO.ui.MenuSelectWidget( menuConfig );
+};
+
+/**
+ * Add options to the menu
+ *
+ * @param {Object[]} menuOptions Object defining options
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.addOptions = function ( menuOptions ) {
+ var widget = this,
+ items = menuOptions.map( function ( obj ) {
+ return widget.createMenuOptionWidget( obj.data, obj.label );
+ } );
+
+ this.menu.addItems( items );
+};
+
+/**
+ * Create a menu option widget.
+ *
+ * @param {string} data Item data
+ * @param {string} [label] Item label
+ * @return {OO.ui.OptionWidget} Option widget
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.createMenuOptionWidget = function ( data, label ) {
+ return new OO.ui.MenuOptionWidget( {
+ data: data,
+ label: label || data
+ } );
+};
+
+/**
+ * Get the menu
+ *
+ * @return {OO.ui.MenuSelectWidget} Menu
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.getMenu = function () {
+ return this.menu;
+};
+
+/**
+ * Get the allowed values list
+ *
+ * @return {string[]} Allowed data values
+ */
+OO.ui.MenuTagMultiselectWidget.prototype.getAllowedValues = function () {
+ var menuDatas = [];
+ if ( this.menu ) {
+ // If the parent constructor is calling us, we're not ready yet, this.menu is not set up.
+ menuDatas = this.menu.getItems().map( function ( menuItem ) {
+ return menuItem.getData();
+ } );
+ }
+ return this.allowedValues.concat( menuDatas );
+};
+
+/**
+ * SelectFileWidgets allow for selecting files, using the HTML5 File API. These
+ * widgets can be configured with {@link OO.ui.mixin.IconElement icons} and {@link
+ * OO.ui.mixin.IndicatorElement indicators}.
+ * Please see the [OOjs UI documentation on MediaWiki] [1] for more information and examples.
+ *
+ * @example
+ * // Example of a file select widget
+ * var selectFile = new OO.ui.SelectFileWidget();
+ * $( 'body' ).append( selectFile.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.PendingElement
+ * @mixins OO.ui.mixin.LabelElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string[]|null} [accept=null] MIME types to accept. null accepts all types.
+ * @cfg {string} [placeholder] Text to display when no file is selected.
+ * @cfg {string} [notsupported] Text to display when file support is missing in the browser.
+ * @cfg {boolean} [droppable=true] Whether to accept files by drag and drop.
+ * @cfg {boolean} [showDropTarget=false] Whether to show a drop target. Requires droppable to be true.
+ * @cfg {number} [thumbnailSizeLimit=20] File size limit in MiB above which to not try and show a
+ * preview (for performance)
+ */
+OO.ui.SelectFileWidget = function OoUiSelectFileWidget( config ) {
+ var dragHandler;
+
+ // Configuration initialization
+ config = $.extend( {
+ accept: null,
+ placeholder: OO.ui.msg( 'ooui-selectfile-placeholder' ),
+ notsupported: OO.ui.msg( 'ooui-selectfile-not-supported' ),
+ droppable: true,
+ showDropTarget: false,
+ thumbnailSizeLimit: 20
+ }, config );
+
+ // Parent constructor
+ OO.ui.SelectFileWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.IndicatorElement.call( this, config );
+ OO.ui.mixin.PendingElement.call( this, $.extend( {}, config, { $pending: this.$info } ) );
+ OO.ui.mixin.LabelElement.call( this, config );
+
+ // Properties
+ this.$info = $( '<span>' );
+ this.showDropTarget = config.showDropTarget;
+ this.thumbnailSizeLimit = config.thumbnailSizeLimit;
+ this.isSupported = this.constructor.static.isSupported();
+ this.currentFile = null;
+ if ( Array.isArray( config.accept ) ) {
+ this.accept = config.accept;
+ } else {
+ this.accept = null;
+ }
+ this.placeholder = config.placeholder;
+ this.notsupported = config.notsupported;
+ this.onFileSelectedHandler = this.onFileSelected.bind( this );
+
+ this.selectButton = new OO.ui.ButtonWidget( {
+ classes: [ 'oo-ui-selectFileWidget-selectButton' ],
+ label: OO.ui.msg( 'ooui-selectfile-button-select' ),
+ disabled: this.disabled || !this.isSupported
+ } );
+
+ this.clearButton = new OO.ui.ButtonWidget( {
+ classes: [ 'oo-ui-selectFileWidget-clearButton' ],
+ framed: false,
+ icon: 'close',
+ disabled: this.disabled
+ } );
+
+ // Events
+ this.selectButton.$button.on( {
+ keypress: this.onKeyPress.bind( this )
+ } );
+ this.clearButton.connect( this, {
+ click: 'onClearClick'
+ } );
+ if ( config.droppable ) {
+ dragHandler = this.onDragEnterOrOver.bind( this );
+ this.$element.on( {
+ dragenter: dragHandler,
+ dragover: dragHandler,
+ dragleave: this.onDragLeave.bind( this ),
+ drop: this.onDrop.bind( this )
+ } );
+ }
+
+ // Initialization
+ this.addInput();
+ this.$label.addClass( 'oo-ui-selectFileWidget-label' );
+ this.$info
+ .addClass( 'oo-ui-selectFileWidget-info' )
+ .append( this.$icon, this.$label, this.clearButton.$element, this.$indicator );
+
+ if ( config.droppable && config.showDropTarget ) {
+ this.selectButton.setIcon( 'upload' );
+ this.$thumbnail = $( '<div>' ).addClass( 'oo-ui-selectFileWidget-thumbnail' );
+ this.setPendingElement( this.$thumbnail );
+ this.$element
+ .addClass( 'oo-ui-selectFileWidget-dropTarget oo-ui-selectFileWidget' )
+ .on( {
+ click: this.onDropTargetClick.bind( this )
+ } )
+ .append(
+ this.$thumbnail,
+ this.$info,
+ this.selectButton.$element,
+ $( '<span>' )
+ .addClass( 'oo-ui-selectFileWidget-dropLabel' )
+ .text( OO.ui.msg( 'ooui-selectfile-dragdrop-placeholder' ) )
+ );
+ } else {
+ this.$element
+ .addClass( 'oo-ui-selectFileWidget' )
+ .append( this.$info, this.selectButton.$element );
+ }
+ this.updateUI();
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.SelectFileWidget, OO.ui.Widget );
+OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.IconElement );
+OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.IndicatorElement );
+OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.PendingElement );
+OO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.LabelElement );
+
+/* Static Properties */
+
+/**
+ * Check if this widget is supported
+ *
+ * @static
+ * @return {boolean}
+ */
+OO.ui.SelectFileWidget.static.isSupported = function () {
+ var $input;
+ if ( OO.ui.SelectFileWidget.static.isSupportedCache === null ) {
+ $input = $( '<input>' ).attr( 'type', 'file' );
+ OO.ui.SelectFileWidget.static.isSupportedCache = $input[ 0 ].files !== undefined;
+ }
+ return OO.ui.SelectFileWidget.static.isSupportedCache;
+};
+
+OO.ui.SelectFileWidget.static.isSupportedCache = null;
+
+/* Events */
+
+/**
+ * @event change
+ *
+ * A change event is emitted when the on/off state of the toggle changes.
+ *
+ * @param {File|null} value New value
+ */
+
+/* Methods */
+
+/**
+ * Get the current value of the field
+ *
+ * @return {File|null}
+ */
+OO.ui.SelectFileWidget.prototype.getValue = function () {
+ return this.currentFile;
+};
+
+/**
+ * Set the current value of the field
+ *
+ * @param {File|null} file File to select
+ */
+OO.ui.SelectFileWidget.prototype.setValue = function ( file ) {
+ if ( this.currentFile !== file ) {
+ this.currentFile = file;
+ this.updateUI();
+ this.emit( 'change', this.currentFile );
+ }
+};
+
+/**
+ * Focus the widget.
+ *
+ * Focusses the select file button.
+ *
+ * @chainable
+ */
+OO.ui.SelectFileWidget.prototype.focus = function () {
+ this.selectButton.focus();
+ return this;
+};
+
+/**
+ * Blur the widget.
+ *
+ * @chainable
+ */
+OO.ui.SelectFileWidget.prototype.blur = function () {
+ this.selectButton.blur();
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.SelectFileWidget.prototype.simulateLabelClick = function () {
+ this.focus();
+};
+
+/**
+ * Update the user interface when a file is selected or unselected
+ *
+ * @protected
+ */
+OO.ui.SelectFileWidget.prototype.updateUI = function () {
+ var $label;
+ if ( !this.isSupported ) {
+ this.$element.addClass( 'oo-ui-selectFileWidget-notsupported' );
+ this.$element.removeClass( 'oo-ui-selectFileWidget-empty' );
+ this.setLabel( this.notsupported );
+ } else {
+ this.$element.addClass( 'oo-ui-selectFileWidget-supported' );
+ if ( this.currentFile ) {
+ this.$element.removeClass( 'oo-ui-selectFileWidget-empty' );
+ $label = $( [] );
+ $label = $label.add(
+ $( '<span>' )
+ .addClass( 'oo-ui-selectFileWidget-fileName' )
+ .text( this.currentFile.name )
+ );
+ this.setLabel( $label );
+
+ if ( this.showDropTarget ) {
+ this.pushPending();
+ this.loadAndGetImageUrl().done( function ( url ) {
+ this.$thumbnail.css( 'background-image', 'url( ' + url + ' )' );
+ }.bind( this ) ).fail( function () {
+ this.$thumbnail.append(
+ new OO.ui.IconWidget( {
+ icon: 'attachment',
+ classes: [ 'oo-ui-selectFileWidget-noThumbnail-icon' ]
+ } ).$element
+ );
+ }.bind( this ) ).always( function () {
+ this.popPending();
+ }.bind( this ) );
+ this.$element.off( 'click' );
+ }
+ } else {
+ if ( this.showDropTarget ) {
+ this.$element.off( 'click' );
+ this.$element.on( {
+ click: this.onDropTargetClick.bind( this )
+ } );
+ this.$thumbnail
+ .empty()
+ .css( 'background-image', '' );
+ }
+ this.$element.addClass( 'oo-ui-selectFileWidget-empty' );
+ this.setLabel( this.placeholder );
+ }
+ }
+};
+
+/**
+ * If the selected file is an image, get its URL and load it.
+ *
+ * @return {jQuery.Promise} Promise resolves with the image URL after it has loaded
+ */
+OO.ui.SelectFileWidget.prototype.loadAndGetImageUrl = function () {
+ var deferred = $.Deferred(),
+ file = this.currentFile,
+ reader = new FileReader();
+
+ if (
+ file &&
+ ( OO.getProp( file, 'type' ) || '' ).indexOf( 'image/' ) === 0 &&
+ file.size < this.thumbnailSizeLimit * 1024 * 1024
+ ) {
+ reader.onload = function ( event ) {
+ var img = document.createElement( 'img' );
+ img.addEventListener( 'load', function () {
+ if (
+ img.naturalWidth === 0 ||
+ img.naturalHeight === 0 ||
+ img.complete === false
+ ) {
+ deferred.reject();
+ } else {
+ deferred.resolve( event.target.result );
+ }
+ } );
+ img.src = event.target.result;
+ };
+ reader.readAsDataURL( file );
+ } else {
+ deferred.reject();
+ }
+
+ return deferred.promise();
+};
+
+/**
+ * Add the input to the widget
+ *
+ * @private
+ */
+OO.ui.SelectFileWidget.prototype.addInput = function () {
+ if ( this.$input ) {
+ this.$input.remove();
+ }
+
+ if ( !this.isSupported ) {
+ this.$input = null;
+ return;
+ }
+
+ this.$input = $( '<input>' ).attr( 'type', 'file' );
+ this.$input.on( 'change', this.onFileSelectedHandler );
+ this.$input.on( 'click', function ( e ) {
+ // Prevents dropTarget to get clicked which calls
+ // a click on this input
+ e.stopPropagation();
+ } );
+ this.$input.attr( {
+ tabindex: -1
+ } );
+ if ( this.accept ) {
+ this.$input.attr( 'accept', this.accept.join( ', ' ) );
+ }
+ this.selectButton.$button.append( this.$input );
+};
+
+/**
+ * Determine if we should accept this file
+ *
+ * @private
+ * @param {string} mimeType File MIME type
+ * @return {boolean}
+ */
+OO.ui.SelectFileWidget.prototype.isAllowedType = function ( mimeType ) {
+ var i, mimeTest;
+
+ if ( !this.accept || !mimeType ) {
+ return true;
+ }
+
+ for ( i = 0; i < this.accept.length; i++ ) {
+ mimeTest = this.accept[ i ];
+ if ( mimeTest === mimeType ) {
+ return true;
+ } else if ( mimeTest.substr( -2 ) === '/*' ) {
+ mimeTest = mimeTest.substr( 0, mimeTest.length - 1 );
+ if ( mimeType.substr( 0, mimeTest.length ) === mimeTest ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+};
+
+/**
+ * Handle file selection from the input
+ *
+ * @private
+ * @param {jQuery.Event} e
+ */
+OO.ui.SelectFileWidget.prototype.onFileSelected = function ( e ) {
+ var file = OO.getProp( e.target, 'files', 0 ) || null;
+
+ if ( file && !this.isAllowedType( file.type ) ) {
+ file = null;
+ }
+
+ this.setValue( file );
+ this.addInput();
+};
+
+/**
+ * Handle clear button click events.
+ *
+ * @private
+ */
+OO.ui.SelectFileWidget.prototype.onClearClick = function () {
+ this.setValue( null );
+ return false;
+};
+
+/**
+ * Handle key press events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key press event
+ */
+OO.ui.SelectFileWidget.prototype.onKeyPress = function ( e ) {
+ if ( this.isSupported && !this.isDisabled() && this.$input &&
+ ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
+ ) {
+ this.$input.click();
+ return false;
+ }
+};
+
+/**
+ * Handle drop target click events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key press event
+ */
+OO.ui.SelectFileWidget.prototype.onDropTargetClick = function () {
+ if ( this.isSupported && !this.isDisabled() && this.$input ) {
+ this.$input.click();
+ return false;
+ }
+};
+
+/**
+ * Handle drag enter and over events
+ *
+ * @private
+ * @param {jQuery.Event} e Drag event
+ */
+OO.ui.SelectFileWidget.prototype.onDragEnterOrOver = function ( e ) {
+ var itemOrFile,
+ droppableFile = false,
+ dt = e.originalEvent.dataTransfer;
+
+ e.preventDefault();
+ e.stopPropagation();
+
+ if ( this.isDisabled() || !this.isSupported ) {
+ this.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' );
+ dt.dropEffect = 'none';
+ return false;
+ }
+
+ // DataTransferItem and File both have a type property, but in Chrome files
+ // have no information at this point.
+ itemOrFile = OO.getProp( dt, 'items', 0 ) || OO.getProp( dt, 'files', 0 );
+ if ( itemOrFile ) {
+ if ( this.isAllowedType( itemOrFile.type ) ) {
+ droppableFile = true;
+ }
+ // dt.types is Array-like, but not an Array
+ } else if ( Array.prototype.indexOf.call( OO.getProp( dt, 'types' ) || [], 'Files' ) !== -1 ) {
+ // File information is not available at this point for security so just assume
+ // it is acceptable for now.
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=640534
+ droppableFile = true;
+ }
+
+ this.$element.toggleClass( 'oo-ui-selectFileWidget-canDrop', droppableFile );
+ if ( !droppableFile ) {
+ dt.dropEffect = 'none';
+ }
+
+ return false;
+};
+
+/**
+ * Handle drag leave events
+ *
+ * @private
+ * @param {jQuery.Event} e Drag event
+ */
+OO.ui.SelectFileWidget.prototype.onDragLeave = function () {
+ this.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' );
+};
+
+/**
+ * Handle drop events
+ *
+ * @private
+ * @param {jQuery.Event} e Drop event
+ */
+OO.ui.SelectFileWidget.prototype.onDrop = function ( e ) {
+ var file = null,
+ dt = e.originalEvent.dataTransfer;
+
+ e.preventDefault();
+ e.stopPropagation();
+ this.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' );
+
+ if ( this.isDisabled() || !this.isSupported ) {
+ return false;
+ }
+
+ file = OO.getProp( dt, 'files', 0 );
+ if ( file && !this.isAllowedType( file.type ) ) {
+ file = null;
+ }
+ if ( file ) {
+ this.setValue( file );
+ }
+
+ return false;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.SelectFileWidget.prototype.setDisabled = function ( disabled ) {
+ OO.ui.SelectFileWidget.parent.prototype.setDisabled.call( this, disabled );
+ if ( this.selectButton ) {
+ this.selectButton.setDisabled( disabled );
+ }
+ if ( this.clearButton ) {
+ this.clearButton.setDisabled( disabled );
+ }
+ return this;
+};
+
+/**
+ * SearchWidgets combine a {@link OO.ui.TextInputWidget text input field}, where users can type a search query,
+ * and a menu of search results, which is displayed beneath the query
+ * field. Unlike {@link OO.ui.mixin.LookupElement lookup menus}, search result menus are always visible to the user.
+ * Users can choose an item from the menu or type a query into the text field to search for a matching result item.
+ * In general, search widgets are used inside a separate {@link OO.ui.Dialog dialog} window.
+ *
+ * Each time the query is changed, the search result menu is cleared and repopulated. Please see
+ * the [OOjs UI demos][1] for an example.
+ *
+ * [1]: https://tools.wmflabs.org/oojs-ui/oojs-ui/demos/#dialogs-mediawiki-vector-ltr
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string|jQuery} [placeholder] Placeholder text for query input
+ * @cfg {string} [value] Initial query value
+ */
+OO.ui.SearchWidget = function OoUiSearchWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.SearchWidget.parent.call( this, config );
+
+ // Properties
+ this.query = new OO.ui.TextInputWidget( {
+ icon: 'search',
+ placeholder: config.placeholder,
+ value: config.value
+ } );
+ this.results = new OO.ui.SelectWidget();
+ this.$query = $( '<div>' );
+ this.$results = $( '<div>' );
+
+ // Events
+ this.query.connect( this, {
+ change: 'onQueryChange',
+ enter: 'onQueryEnter'
+ } );
+ this.query.$input.on( 'keydown', this.onQueryKeydown.bind( this ) );
+
+ // Initialization
+ this.$query
+ .addClass( 'oo-ui-searchWidget-query' )
+ .append( this.query.$element );
+ this.$results
+ .addClass( 'oo-ui-searchWidget-results' )
+ .append( this.results.$element );
+ this.$element
+ .addClass( 'oo-ui-searchWidget' )
+ .append( this.$results, this.$query );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.SearchWidget, OO.ui.Widget );
+
+/* Methods */
+
+/**
+ * Handle query key down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.SearchWidget.prototype.onQueryKeydown = function ( e ) {
+ var highlightedItem, nextItem,
+ dir = e.which === OO.ui.Keys.DOWN ? 1 : ( e.which === OO.ui.Keys.UP ? -1 : 0 );
+
+ if ( dir ) {
+ highlightedItem = this.results.getHighlightedItem();
+ if ( !highlightedItem ) {
+ highlightedItem = this.results.getSelectedItem();
+ }
+ nextItem = this.results.getRelativeSelectableItem( highlightedItem, dir );
+ this.results.highlightItem( nextItem );
+ nextItem.scrollElementIntoView();
+ }
+};
+
+/**
+ * Handle select widget select events.
+ *
+ * Clears existing results. Subclasses should repopulate items according to new query.
+ *
+ * @private
+ * @param {string} value New value
+ */
+OO.ui.SearchWidget.prototype.onQueryChange = function () {
+ // Reset
+ this.results.clearItems();
+};
+
+/**
+ * Handle select widget enter key events.
+ *
+ * Chooses highlighted item.
+ *
+ * @private
+ * @param {string} value New value
+ */
+OO.ui.SearchWidget.prototype.onQueryEnter = function () {
+ var highlightedItem = this.results.getHighlightedItem();
+ if ( highlightedItem ) {
+ this.results.chooseItem( highlightedItem );
+ }
+};
+
+/**
+ * Get the query input.
+ *
+ * @return {OO.ui.TextInputWidget} Query input
+ */
+OO.ui.SearchWidget.prototype.getQuery = function () {
+ return this.query;
+};
+
+/**
+ * Get the search results menu.
+ *
+ * @return {OO.ui.SelectWidget} Menu of search results
+ */
+OO.ui.SearchWidget.prototype.getResults = function () {
+ return this.results;
+};
+
+/**
+ * NumberInputWidgets combine a {@link OO.ui.TextInputWidget text input} (where a value
+ * can be entered manually) and two {@link OO.ui.ButtonWidget button widgets}
+ * (to adjust the value in increments) to allow the user to enter a number.
+ *
+ * @example
+ * // Example: A NumberInputWidget.
+ * var numberInput = new OO.ui.NumberInputWidget( {
+ * label: 'NumberInputWidget',
+ * input: { value: 5 },
+ * min: 1,
+ * max: 10
+ * } );
+ * $( 'body' ).append( numberInput.$element );
+ *
+ * @class
+ * @extends OO.ui.TextInputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} [minusButton] Configuration options to pass to the {@link OO.ui.ButtonWidget decrementing button widget}.
+ * @cfg {Object} [plusButton] Configuration options to pass to the {@link OO.ui.ButtonWidget incrementing button widget}.
+ * @cfg {boolean} [allowInteger=false] Whether the field accepts only integer values.
+ * @cfg {number} [min=-Infinity] Minimum allowed value
+ * @cfg {number} [max=Infinity] Maximum allowed value
+ * @cfg {number} [step=1] Delta when using the buttons or up/down arrow keys
+ * @cfg {number|null} [pageStep] Delta when using the page-up/page-down keys. Defaults to 10 times #step.
+ * @cfg {boolean} [showButtons=true] Whether to show the plus and minus buttons.
+ */
+OO.ui.NumberInputWidget = function OoUiNumberInputWidget( config ) {
+ var $field = $( '<div>' )
+ .addClass( 'oo-ui-numberInputWidget-field' );
+
+ // Configuration initialization
+ config = $.extend( {
+ allowInteger: false,
+ min: -Infinity,
+ max: Infinity,
+ step: 1,
+ pageStep: null,
+ showButtons: true
+ }, config );
+
+ // For backward compatibility
+ $.extend( config, config.input );
+ this.input = this;
+
+ // Parent constructor
+ OO.ui.NumberInputWidget.parent.call( this, $.extend( config, {
+ type: 'number'
+ } ) );
+
+ if ( config.showButtons ) {
+ this.minusButton = new OO.ui.ButtonWidget( $.extend(
+ {
+ disabled: this.isDisabled(),
+ tabIndex: -1,
+ classes: [ 'oo-ui-numberInputWidget-minusButton' ],
+ icon: 'subtract'
+ },
+ config.minusButton
+ ) );
+ this.plusButton = new OO.ui.ButtonWidget( $.extend(
+ {
+ disabled: this.isDisabled(),
+ tabIndex: -1,
+ classes: [ 'oo-ui-numberInputWidget-plusButton' ],
+ icon: 'add'
+ },
+ config.plusButton
+ ) );
+ }
+
+ // Events
+ this.$input.on( {
+ keydown: this.onKeyDown.bind( this ),
+ 'wheel mousewheel DOMMouseScroll': this.onWheel.bind( this )
+ } );
+ if ( config.showButtons ) {
+ this.plusButton.connect( this, {
+ click: [ 'onButtonClick', +1 ]
+ } );
+ this.minusButton.connect( this, {
+ click: [ 'onButtonClick', -1 ]
+ } );
+ }
+
+ // Build the field
+ $field.append( this.$input );
+ if ( config.showButtons ) {
+ $field
+ .prepend( this.minusButton.$element )
+ .append( this.plusButton.$element );
+ }
+
+ // Initialization
+ this.setAllowInteger( config.allowInteger || config.isInteger );
+ this.setRange( config.min, config.max );
+ this.setStep( config.step, config.pageStep );
+ // Set the validation method after we set allowInteger and range
+ // so that it doesn't immediately call setValidityFlag
+ this.setValidation( this.validateNumber.bind( this ) );
+
+ this.$element
+ .addClass( 'oo-ui-numberInputWidget' )
+ .toggleClass( 'oo-ui-numberInputWidget-buttoned', config.showButtons )
+ .append( $field );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.NumberInputWidget, OO.ui.TextInputWidget );
+
+/* Methods */
+
+/**
+ * Set whether only integers are allowed
+ *
+ * @param {boolean} flag
+ */
+OO.ui.NumberInputWidget.prototype.setAllowInteger = function ( flag ) {
+ this.allowInteger = !!flag;
+ this.setValidityFlag();
+};
+// Backward compatibility
+OO.ui.NumberInputWidget.prototype.setIsInteger = OO.ui.NumberInputWidget.prototype.setAllowInteger;
+
+/**
+ * Get whether only integers are allowed
+ *
+ * @return {boolean} Flag value
+ */
+OO.ui.NumberInputWidget.prototype.getAllowInteger = function () {
+ return this.allowInteger;
+};
+// Backward compatibility
+OO.ui.NumberInputWidget.prototype.getIsInteger = OO.ui.NumberInputWidget.prototype.getAllowInteger;
+
+/**
+ * Set the range of allowed values
+ *
+ * @param {number} min Minimum allowed value
+ * @param {number} max Maximum allowed value
+ */
+OO.ui.NumberInputWidget.prototype.setRange = function ( min, max ) {
+ if ( min > max ) {
+ throw new Error( 'Minimum (' + min + ') must not be greater than maximum (' + max + ')' );
+ }
+ this.min = min;
+ this.max = max;
+ this.setValidityFlag();
+};
+
+/**
+ * Get the current range
+ *
+ * @return {number[]} Minimum and maximum values
+ */
+OO.ui.NumberInputWidget.prototype.getRange = function () {
+ return [ this.min, this.max ];
+};
+
+/**
+ * Set the stepping deltas
+ *
+ * @param {number} step Normal step
+ * @param {number|null} pageStep Page step. If null, 10 * step will be used.
+ */
+OO.ui.NumberInputWidget.prototype.setStep = function ( step, pageStep ) {
+ if ( step <= 0 ) {
+ throw new Error( 'Step value must be positive' );
+ }
+ if ( pageStep === null ) {
+ pageStep = step * 10;
+ } else if ( pageStep <= 0 ) {
+ throw new Error( 'Page step value must be positive' );
+ }
+ this.step = step;
+ this.pageStep = pageStep;
+};
+
+/**
+ * Get the current stepping values
+ *
+ * @return {number[]} Step and page step
+ */
+OO.ui.NumberInputWidget.prototype.getStep = function () {
+ return [ this.step, this.pageStep ];
+};
+
+/**
+ * Get the current value of the widget as a number
+ *
+ * @return {number} May be NaN, or an invalid number
+ */
+OO.ui.NumberInputWidget.prototype.getNumericValue = function () {
+ return +this.getValue();
+};
+
+/**
+ * Adjust the value of the widget
+ *
+ * @param {number} delta Adjustment amount
+ */
+OO.ui.NumberInputWidget.prototype.adjustValue = function ( delta ) {
+ var n, v = this.getNumericValue();
+
+ delta = +delta;
+ if ( isNaN( delta ) || !isFinite( delta ) ) {
+ throw new Error( 'Delta must be a finite number' );
+ }
+
+ if ( isNaN( v ) ) {
+ n = 0;
+ } else {
+ n = v + delta;
+ n = Math.max( Math.min( n, this.max ), this.min );
+ if ( this.allowInteger ) {
+ n = Math.round( n );
+ }
+ }
+
+ if ( n !== v ) {
+ this.setValue( n );
+ }
+};
+/**
+ * Validate input
+ *
+ * @private
+ * @param {string} value Field value
+ * @return {boolean}
+ */
+OO.ui.NumberInputWidget.prototype.validateNumber = function ( value ) {
+ var n = +value;
+ if ( value === '' ) {
+ return !this.isRequired();
+ }
+
+ if ( isNaN( n ) || !isFinite( n ) ) {
+ return false;
+ }
+
+ if ( this.allowInteger && Math.floor( n ) !== n ) {
+ return false;
+ }
+
+ if ( n < this.min || n > this.max ) {
+ return false;
+ }
+
+ return true;
+};
+
+/**
+ * Handle mouse click events.
+ *
+ * @private
+ * @param {number} dir +1 or -1
+ */
+OO.ui.NumberInputWidget.prototype.onButtonClick = function ( dir ) {
+ this.adjustValue( dir * this.step );
+};
+
+/**
+ * Handle mouse wheel events.
+ *
+ * @private
+ * @param {jQuery.Event} event
+ */
+OO.ui.NumberInputWidget.prototype.onWheel = function ( event ) {
+ var delta = 0;
+
+ if ( !this.isDisabled() && this.$input.is( ':focus' ) ) {
+ // Standard 'wheel' event
+ if ( event.originalEvent.deltaMode !== undefined ) {
+ this.sawWheelEvent = true;
+ }
+ if ( event.originalEvent.deltaY ) {
+ delta = -event.originalEvent.deltaY;
+ } else if ( event.originalEvent.deltaX ) {
+ delta = event.originalEvent.deltaX;
+ }
+
+ // Non-standard events
+ if ( !this.sawWheelEvent ) {
+ if ( event.originalEvent.wheelDeltaX ) {
+ delta = -event.originalEvent.wheelDeltaX;
+ } else if ( event.originalEvent.wheelDeltaY ) {
+ delta = event.originalEvent.wheelDeltaY;
+ } else if ( event.originalEvent.wheelDelta ) {
+ delta = event.originalEvent.wheelDelta;
+ } else if ( event.originalEvent.detail ) {
+ delta = -event.originalEvent.detail;
+ }
+ }
+
+ if ( delta ) {
+ delta = delta < 0 ? -1 : 1;
+ this.adjustValue( delta * this.step );
+ }
+
+ return false;
+ }
+};
+
+/**
+ * Handle key down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.NumberInputWidget.prototype.onKeyDown = function ( e ) {
+ if ( !this.isDisabled() ) {
+ switch ( e.which ) {
+ case OO.ui.Keys.UP:
+ this.adjustValue( this.step );
+ return false;
+ case OO.ui.Keys.DOWN:
+ this.adjustValue( -this.step );
+ return false;
+ case OO.ui.Keys.PAGEUP:
+ this.adjustValue( this.pageStep );
+ return false;
+ case OO.ui.Keys.PAGEDOWN:
+ this.adjustValue( -this.pageStep );
+ return false;
+ }
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.NumberInputWidget.prototype.setDisabled = function ( disabled ) {
+ // Parent method
+ OO.ui.NumberInputWidget.parent.prototype.setDisabled.call( this, disabled );
+
+ if ( this.minusButton ) {
+ this.minusButton.setDisabled( this.isDisabled() );
+ }
+ if ( this.plusButton ) {
+ this.plusButton.setDisabled( this.isDisabled() );
+ }
+
+ return this;
+};
+
+}( OO ) );
+
+//# sourceMappingURL=oojs-ui-widgets.js.map \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets.js.map b/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets.js.map
new file mode 100644
index 00000000..5eed7ca3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-widgets.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/intro.js.txt","../src/mixins/DraggableElement.js","../src/mixins/DraggableGroupElement.js","../src/mixins/RequestManager.js","../src/mixins/LookupElement.js","../src/layouts/TabPanelLayout.js","../src/layouts/PageLayout.js","../src/layouts/StackLayout.js","../src/layouts/MenuLayout.js","../src/layouts/BookletLayout.js","../src/layouts/IndexLayout.js","../src/widgets/ToggleWidget.js","../src/widgets/ToggleButtonWidget.js","../src/widgets/ToggleSwitchWidget.js","../src/widgets/OutlineControlsWidget.js","../src/widgets/OutlineOptionWidget.js","../src/widgets/OutlineSelectWidget.js","../src/widgets/ButtonOptionWidget.js","../src/widgets/ButtonSelectWidget.js","../src/widgets/TabOptionWidget.js","../src/widgets/TabSelectWidget.js","../src/widgets/CapsuleItemWidget.js","../src/widgets/CapsuleMultiselectWidget.js","../src/widgets/TagItemWidget.js","../src/widgets/TagMultiselectWidget.js","../src/widgets/PopupTagMultiselectWidget.js","../src/widgets/MenuTagMultiselectWidget.js","../src/widgets/SelectFileWidget.js","../src/widgets/SearchWidget.js","../src/widgets/NumberInputWidget.js","../src/outro.js.txt"],"names":[],"mappings":";;;;;;;;;;AAAA,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACnB;AACA,CAAC,GAAG,CAAC,MAAM,EAAE;;ACFb,GAAG;AACH,CAAC,CAAC,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO;AAChF,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI;AACnF,CAAC,CAAC,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG;AACxF,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC;AAC1B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,QAAQ;AACZ,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO;AAChH,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,eAAe;AAC5F,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,KAAK,CAAC,OAAO;AAC1F,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,KAAK;AACnB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC;AAChD,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3B;AACA,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM;AACzB,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;AACvC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACR,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAChD,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5C,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC1C,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACxC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACjC,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,EAAE;AAC1D,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC,EAAE;AACpF,EAAE;AACF;AACA,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE;AAC7C;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS;AACnB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC;AACjF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AAC3G,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO;AACjB,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC;AACjF,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;AACvC,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;AACd,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM;AACzF,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;AACvB,CAAC,EAAE;AACH;AACA,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;AACvB;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa;AACxC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC,KAAK,CAAC;AACxE;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;AAC7C,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC;AACjE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU;AACpE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS;AACnB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AACnF,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;AAC3E;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AACxC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;AAC/B;AACA,EAAE,IAAI,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,WAAW,EAAE,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;AACpF;AACA,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI;AACvE,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI;AACzE,EAAE,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM;AAChC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;AACpD,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM;AAC3C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU;AACzD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;AACvB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;AAC9B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK;AACrC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;AAC7B,EAAE,MAAM,CAAC;AACT,CAAC,CAAC;AACF;AACA,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACrB,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI;AACzE,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC7C,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM;AACnD,EAAE,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AACtD,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC;AAC9B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK;AACrC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS;AACpD,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS;AACnB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACpB,EAAE,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC;AAC9C;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;AACpD,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM;AACtB,CAAC,YAAY,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;AAClC,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;AACrC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,OAAO;AACpB,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;AACnE,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC;AAC7C,CAAC,GAAG,CAAC,CAAC;AACN,EAAE,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE;AAC7E,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAClB,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;AACxD,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK;AACxE,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE;AAC1D,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK;AAClE,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1B,EAAE,OAAO,EAAE,OAAO;AAClB,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC;AACjD,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,EAAE;AACrD,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK;AACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE;AAChC,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO;AACjB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAChE,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,EAAE;AACnE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE;AACxB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACrB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK;AACrC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC,CAAC,CAAC,cAAc,GAAG;AACpB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE;AACxB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI;AAC1D,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;AACrC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK;AACrC,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC,CAAC,CAAC,cAAc,GAAG;AACpB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;AAClB,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK;AAClE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;AACnC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9B,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;AACrB,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,EAAE;AACvC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AACjB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK;AAC9B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/D,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACnB,EAAE;;ACvNF,GAAG;AACH,CAAC,CAAC,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;AAC3E,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC;AAC1F,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC;AACvD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,QAAQ;AACZ,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,WAAW;AAC5F,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG;AACzE,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;AACjG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC;AAChF,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,eAAe;AAC5F,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,QAAQ,CAAC,8BAA8B,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACvF,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC/C;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE;AACrD,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACtB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG;AACpB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACjB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;AACxB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC;AAC7E;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;AAClB,EAAE,SAAS,CAAC,CAAC,CAAC,aAAa,EAAE;AAC7B,EAAE,OAAO,CAAC,CAAC,CAAC,WAAW,EAAE;AACzB,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;AAClB,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACtB,EAAE,aAAa,CAAC,CAAC,CAAC,eAAe,EAAE;AACnC,EAAE,QAAQ,CAAC,CAAC,CAAC,mBAAmB,EAAE;AAClC,EAAE,WAAW,CAAC,CAAC,CAAC,mBAAmB,CAAC;AACpC,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;AAChC,CAAC,CAAC;AACF,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC;AAC5C,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACzB,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,UAAU,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE;AAC9F,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;AAC7E;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC;AACnE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;AACd,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;AAC1D,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;AACpD,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC9C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO;AACjB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI;AAC5D,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;AACpD,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC;AAC9C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS;AACnB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS;AACnD,CAAC,EAAE;AACH;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;AAC7C,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,UAAU,CAAC;AACjE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU;AACpE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS;AACnB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AACxF,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;AAC3E;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AACxC,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC;AAC/B;AACA,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO;AACjD,EAAE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9C,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;AAC1C,EAAE,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACnB;AACA,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK;AACf,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE;AAC3C,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM;AAC3C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,UAAU;AACzD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACvE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;AACvB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;AAC1D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjF,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC;AAC7B,EAAE,MAAM,CAAC;AACT,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ;AAC3E,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;AACzC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG;AACtC,CAAC,IAAI,CAAC,aAAa,GAAG;AACtB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3C,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM;AACrE,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC;AACtD,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE;AAC9C,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE;AAC1B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AAC3C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACZ;AACA,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM;AAChC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5D,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;AACrC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,WAAW;AAC7E,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;AAC1D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/E,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,aAAa,CAAC;AAChC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG;AAC5B;AACA,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS;AACnE,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI;AACjD,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACd,EAAE,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE;AAC7C,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AACtF,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC9E,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AACxC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,WAAW,CAAC,EAAE;AACnD,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,WAAW,GAAG,CAAC,WAAW,CAAC,EAAE;AAC3D,EAAE,CAAC;AACH,EAAE,IAAI,CAAC,aAAa,GAAG;AACvB,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,aAAa,GAAG;AACtB,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,WAAW;AACvC,CAAC,MAAM,CAAC,KAAK,CAAC;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK;AACzC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO;AACjB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC;AAC5B,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,GAAG;AAC5B,EAAE,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG;AAClC;AACA,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI;AAClD,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AAChF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AAChE,EAAE,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAClE;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1B,GAAG,IAAI,EAAE,KAAK,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;AACvE,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,IAAI,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;AACxC,EAAE,CAAC;AACH,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK;AAClC,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACvC,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAClD,EAAE,EAAE;AACJ,EAAE,IAAI,CAAC,aAAa,GAAG;AACvB,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,EAAE;AACzC,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO;AACnB,CAAC,CAAC,CAAC,cAAc,GAAG;AACpB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AACjC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI;AAC5D,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK;AACrC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACnF,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE;AACrC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI;AACrB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;AAC1D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACvB,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC/D,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,EAAE;AACnE,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI;AACjC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACvB,EAAE,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE;AAClC,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,EAAE;AACtE,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;AAChD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO;AAChH,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACvE,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;AACtB,EAAE;;AC5PF,GAAG;AACH,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AACzG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,EAAE;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,QAAQ;AACZ,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,uBAAuB,EAAE,CAAC,CAAC;AACjE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG;AACxB,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1B,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5B,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE;AAC3C;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC;AAC7C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE;AACtG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO;AAClG,CAAC,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;AACpE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,GAAG;AACjC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,GAAG;AAC1B,EAAE,UAAU,CAAC;AACb;AACA,CAAC,IAAI,CAAC,YAAY,GAAG;AACrB,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1E,EAAE,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AACjD,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC3B,GAAG,IAAI,CAAC,WAAW,GAAG;AACtB,EAAE,CAAC;AACH,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC;AAC5B,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG;AACvD,EAAE,UAAU;AACZ,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzB,IAAI,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,SAAS;AACvE,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;AAC9C,IAAI,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK;AACjF,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE;AACvF,IAAI,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE;AACpF,IAAI,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC;AACxB,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAC9B,KAAK,MAAM,CAAC,UAAU,GAAG;AACzB,IAAI,CAAC;AACL,GAAG,CAAC,CAAC,CAAC;AACN,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACjC,IAAI,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE;AACtF,IAAI,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU;AACpC,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACjD,KAAK,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC;AAChC,KAAK,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC;AAClC,KAAK,MAAM,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,+BAA+B,CAAC,CAAC,QAAQ,CAAC,EAAE;AACvF,KAAK,QAAQ,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AACtD,IAAI,CAAC;AACL,GAAG,CAAC,CAAC,CAAC;AACN,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACvB,IAAI,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE;AACnF,IAAI,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,UAAU;AACpC,IAAI,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACjD,KAAK,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC;AAChC,KAAK,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC;AAClC,KAAK,QAAQ,CAAC,MAAM,GAAG;AACvB,IAAI,CAAC;AACL,GAAG,CAAC,CAAC,EAAE;AACP,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAG;AAC3B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC;AAC/C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC;AACtC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACpB,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM;AACpE,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO;AAC1C,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7B,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3B,EAAE,UAAU,CAAC,KAAK,GAAG;AACrB,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,QAAQ;AACZ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI;AACpC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5D;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;AACvD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,QAAQ;AACZ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM;AACzF,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC;AAC7D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK;AAChG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;AACrD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,QAAQ;AACZ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM;AAC/C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI;AACrC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAC,CAAC,IAAI,CAAC;;AC5H5E,GAAG;AACH,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG;AACtG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AACjH,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM;AAC5H,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;AACzE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;AAC/G,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI;AAC/G,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;AACrB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC;AAC7C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG;AAC1F,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,QAAQ;AACZ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc;AACrC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,WAAW,CAAC;AAC1F,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE;AACnE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC;AAC7H,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,yBAAyB,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;AACnH,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC;AAC7F,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG;AACpH,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG,CAAC;AAClF,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACvD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACjD;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC;AAClD,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAChD,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC;AACf,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC;AACd,EAAE,CAAC,kBAAkB,CAAC,CAAC,MAAM,EAAE,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO;AACzD,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC,CAAC,MAAM,CAAC,yBAAyB,CAAC,EAAE,CAAC,KAAK,CAAC;AAC5E;AACA,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC;AAC9B,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC;AACjC,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC;AACvD;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AAClB,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC9C,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5C,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACrD,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,EAAE;AACzD,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACjC,EAAE,MAAM,CAAC,CAAC,CAAC,kBAAkB,EAAE;AAC/B,EAAE,MAAM,CAAC,CAAC,CAAC,sBAAsB,CAAC;AAClC,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACpB,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE;AACnB,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,YAAY,GAAG;AAC9C,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC;AAC7B,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE;AACjD,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,EAAE;AACjE,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE;AAClD,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE;AACvE;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK;AAC5C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACtE,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC;AAChC,CAAC,IAAI,CAAC,kBAAkB,GAAG;AAC3B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;AAC3B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;AAC3C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrE,CAAC,IAAI,CAAC,eAAe,GAAG;AACxB,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC;AACjC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;AACjC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;AACjD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1E,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;AACxD,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG;AAC/E,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS;AAC9E,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;AAC5D,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;AACjE,EAAE,IAAI,CAAC,kBAAkB,GAAG;AAC5B,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK;AACxC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACvE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;AACjC,EAAE,IAAI,CAAC,kBAAkB,GAAG;AAC5B,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;AAC7C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC;AACnE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC/E,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClB,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;AAC1E,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,eAAe,GAAG,CAAC,OAAO;AACvE,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;AAClE,EAAE,IAAI,CAAC,kBAAkB,GAAG;AAC5B,EAAE,IAAI,CAAC,UAAU,CAAC,UAAU,GAAG;AAC/B,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;AACnG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI;AACrD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;AACjC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;AACnB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC;AACnC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;AACxB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;AAChC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;AAC3E,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO;AAC5C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;AACnC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;AACzE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC;AACpC,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AACjC,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC;AAC3D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnE,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE;AACjC,CAAC,IAAI,CAAC,kBAAkB,GAAG;AAC3B,CAAC,IAAI,CAAC,UAAU,CAAC,UAAU,GAAG;AAC9B,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;AAC/E,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;AACxD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;AACtF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACtE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG;AAC1B;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AACnD,EAAE,MAAM,CAAC;AACT,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;AACrF,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,yBAAyB,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACzD,EAAE,IAAI,CAAC,eAAe,GAAG;AACzB,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK;AAC/E,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC3C,EAAE,IAAI,CAAC,kBAAkB,EAAE;AAC3B,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9B,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,GAAG;AACnC,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACzB,KAAK,MAAM,CAAC,UAAU;AACtB,MAAM,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC;AACxB,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AACtB,KAAK,MAAM,CAAC,6BAA6B,GAAG;AAC5C,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACZ,KAAK,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE;AACvC,IAAI,CAAC;AACL,GAAG,CAAC,CAAC,CAAC;AACN,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACvB,IAAI,MAAM,CAAC,UAAU,CAAC,UAAU,GAAG;AACnC,GAAG,CAAC,CAAC,EAAE;AACP,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC;AAClE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjF,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC;AAC7E,EAAE,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,sBAAsB,EAAE,CAAC,EAAE;AAC5E,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC;AAC/C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE;AACnG,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO;AAClG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;AAC1D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACtE,CAAC,MAAM,CAAC,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACvD,EAAE,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC,IAAI,CAAC,EAAE;AACnD,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAClB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC;AACtD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACtE,CAAC,IAAI,CAAC,YAAY,GAAG;AACrB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC;AAC9D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,QAAQ;AACZ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM;AACzF,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5D;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,gBAAgB,CAAC;AACnE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK;AAChG,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;AACrD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,QAAQ;AACZ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM;AAC/C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI;AACrC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1E;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AAChF,CAAC,CAAC,CAAC,CAAC,8BAA8B,CAAC;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,QAAQ;AACZ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK;AAC3D,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,GAAG,CAAC,IAAI,CAAC,KAAK;AAChD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,4BAA4B,CAAC,CAAC,CAAC,IAAI,CAAC;AACxE;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC;AAC3D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI;AACjD,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM;AACjB,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe;AAC3F,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE;AACpE;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW;AAChG,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAC9C,EAAE,IAAI,CAAC,eAAe,GAAG;AACzB,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnE,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,GAAG;AACxB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9D,CAAC,MAAM,CAAC,IAAI,CAAC,gBAAgB,GAAG;AAChC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,+BAA+B,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC7F,CAAC,MAAM,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC,QAAQ,CAAC,EAAE;AACxD,EAAE;;AClWF,GAAG;AACH,CAAC,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI;AACpG,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC;AAC3F,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG;AAC9F,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;AACtC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC;AACpG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG;AAC5F,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC;AACxD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AACzD,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG;AACpF,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM;AAChE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC1D,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAChB,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACnD;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAClD;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAClB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AAC3B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACrB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;AACrB;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE;AAClD,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE;AAC3D;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;AACzG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACtF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM;AAC9C,CAAC,EAAE;AACH;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AAC9C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACtD,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AAClB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC;AAChC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE;AACjH,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG;AAC7G,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AAChB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM;AACxC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACvD,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;AACpB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;AAChB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG;AACzE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC;AAChH,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM;AACzD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;AACrB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;AAChE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG;AACjG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;AACpD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK;AAC/E,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC;AAChC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACjB,EAAE,IAAI,CAAC,YAAY,GAAG;AACtB,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;AACvB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK;AACjG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG;AACvF,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC;AAClC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE;AACrE,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC3D,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpB,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACtC,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC;AAC3C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI;AACpG,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAChG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;AACpG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM;AAC9C,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;AACnB;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAChC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AACvB,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;AAC1E,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;AACrC,CAAC,CAAC;AACF,EAAE;;AChJF,GAAG;AACH,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO;AAC5H,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,QAAQ,CAAC;AACjI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC;AACrE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO;AAClH,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,GAAG;AACjG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC;AAC5D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI;AACpD,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM;AAChE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC1D,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAChB,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACnD;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC9C;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAClB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AACzB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;AACrB;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE;AAC9C,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE;AACvD;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;AAC/F,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AACnF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM;AACzC,CAAC,EAAE;AACH;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;AACrC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClD,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AAClB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;AAC3B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO;AACxH,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC;AAC7G,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM;AACnC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnD,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;AACpB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;AACpB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO;AAC9E,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,gBAAgB,CAAC,MAAM,CAAC;AACxH,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM;AACjE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;AACzB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;AACjC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;AACzE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO;AAC7G,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;AACxD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK;AAC3F,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC;AACxC,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AACrB,EAAE,IAAI,CAAC,gBAAgB,GAAG;AAC1B,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;AAC3B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK;AACzG,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG;AACpG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC;AACtC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE;AACjF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC3D,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC;AACtC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU;AAChI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO;AAChG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;AAC5D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM;AACzC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC;AACnB;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAChC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AACvB,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,EAAE;AACjE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE;AACrC,CAAC,CAAC;AACF,EAAE;;ACzIF,GAAG;AACH,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS;AACpH,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;AAC7G,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE;AAC/C,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,WAAW;AAChF,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;AAC7C,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC;AACnB,CAAC,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;AACvC,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE;AACrD,CAAC,CAAC,iBAAiB,MAAM,CAAC,CAAC,IAAI,CAAC;AAChC,CAAC,CAAC,iBAAiB,MAAM,CAAC,CAAC,IAAI;AAC/B,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE;AACnB,CAAC,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;AACvC,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE;AACrD,CAAC,CAAC,iBAAiB,MAAM,CAAC,CAAC,IAAI,CAAC;AAChC,CAAC,CAAC,iBAAiB,MAAM,CAAC,CAAC,IAAI;AAC/B,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,SAAS,EAAE;AACb,CAAC,CAAC,SAAS,UAAU,CAAC,CAAC,IAAI;AAC3B,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE;AAC9C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW;AAC7B,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3H,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AAC1E,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACnD;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC/C;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC1F;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AACzB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;AACvC;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE;AAC/C,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACzB,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,EAAE;AAC3D,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;AAClF,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;AAChC,CAAC,CAAC;AACF,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE;AACxD,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;AAC7D;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,WAAW,CAAC,OAAO,EAAE;AAClG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE;AAC7D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK;AAC/E,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;AACjF,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;AACzD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,iBAAiB;AAC3B,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM;AACvE,CAAC,EAAE;AACH;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO;AAC/C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAC1B,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,iBAAiB;AAC3B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACpD,CAAC,GAAG,CAAC,WAAW,CAAC;AACjB,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;AAC1B,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;AACxD,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,CAAC;AAC1B,EAAE,aAAa,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,qBAAqB,GAAG;AAC7D;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3E,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC;AACpD,EAAE,MAAM,CAAC;AACT,CAAC,CAAC;AACF;AACA,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3B,EAAE,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,qBAAqB,GAAG;AACpD,CAAC,CAAC;AACF;AACA,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC7B,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE;AAC7B,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC;AAC5E,CAAC,CAAC;AACF;AACA,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;AAC3C;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAChD,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;AACpC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC9B,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,IAAI,KAAK,CAAC;AACV,GAAG,CAAC;AACJ,EAAE,CAAC;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACvD,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;AAClC,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7B,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC/C,IAAI,KAAK,CAAC;AACV,GAAG,CAAC;AACJ,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACnC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,iBAAiB,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE;AAC3D,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC;AACzB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC;AAC9B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1D,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;AACzB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;AAC1B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,MAAM;AACpC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC5D,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;AACjC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3B,EAAE,MAAM,CAAC;AACT,CAAC,CAAC;AACF;AACA,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AACzB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE;AAC1B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS;AACtH,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS;AAC3H,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;AAChB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AAC9C,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK;AACvD,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU;AACzB,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;AACnD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE;AACxE;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC3C,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC7B,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AACrD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;AAC3G,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC;AACtD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM;AACjD,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AACpE;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5B,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACnC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,IAAI,CAAC,gBAAgB,GAAG;AAC3B,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AAC1C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI;AACpG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC;AACnD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACtD,CAAC,IAAI,CAAC,gBAAgB,GAAG;AACzB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5D;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC;AAC9D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI;AAC3C,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACzD,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AACnC,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE;AAC7C;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5C,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3B,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE;AAC5B,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,IAAI,CAAC,gBAAgB,GAAG;AAC3B,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC;AACrE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC;AAC3D,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC;AACzD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;AACvD,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI;AAC7D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACZ;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAC1B,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACnD,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE;AAC3D,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE;AACtD,GAAG,CAAC;AACJ,EAAE,CAAC;AACH,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACvB,GAAG,YAAY,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE;AAC/D,GAAG,YAAY,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,EAAE;AACrD,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;;AClRF,GAAG;AACH,CAAC,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC;AAC3J,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC;AACxG,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;AAC/C,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;AAC1B,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC,SAAS,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACnG,CAAC,CAAC,SAAS,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACtG,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC7C,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC;AACvB,CAAC,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC5C,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE;AACtC,CAAC,CAAC,qBAAqB,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE;AACvC,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE;AACvB,CAAC,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC5C,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;AACrC,CAAC,CAAC,qBAAqB,KAAK,CAAC,CAAC,CAAC,KAAK,EAAE;AACtC,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE;AACvB,CAAC,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC5C,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE;AACnC,CAAC,CAAC,qBAAqB,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE;AACpC,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE;AACvB,CAAC,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC5C,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE;AACtC,CAAC,CAAC,qBAAqB,KAAK,CAAC,CAAC,CAAC,MAAM,EAAE;AACvC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;AACtB,CAAC,CAAC,cAAc,CAAC;AACjB,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC,YAAY,UAAU,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;AAC3D,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE;AACf,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,UAAU,EAAE,IAAI,CAAC,MAAM,CAAC;AAC/B,CAAC,CAAC,SAAS,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC5E,CAAC,CAAC,KAAK,EAAE;AACT,CAAC,CAAC,KAAK,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC;AAClC,CAAC,CAAC,SAAS,YAAY,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,GAAG;AACtK,CAAC,CAAC,KAAK,EAAE;AACT,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE;AACjD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO;AAC/F,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG;AACjG,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS;AACpG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC;AAClB,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AAC/B,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,KAAK,CAAC;AACzB,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,KAAK,CAAC;AACxB,CAAC,CAAC,KAAK,CAAC;AACR,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC;AACtB,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,KAAK,CAAC;AACvB,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,KAAK,CAAC;AACxB,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,KAAK,CAAC;AACzB,CAAC,CAAC,KAAK,CAAC;AACR,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM;AACxB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI;AAC3C,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;AAC/F,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtD,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACrB,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC;AACjB,EAAE,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC;AACxB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACb;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC9C;AACA,CAAC,GAAG;AACJ,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI;AACjB,EAAE,CAAC;AACH,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;AACtB,EAAE,EAAE;AACJ,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;AAC3B,CAAC,GAAG;AACJ,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI;AACpB,EAAE,CAAC;AACH,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;AACtB,EAAE,EAAE;AACJ,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;AAC9B;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,IAAI;AACX,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,EAAE;AACvC,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE;AACtD,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;AACjC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE;AACvC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE;AAC7C,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE;AACpC,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AAClD;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;AACf,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM;AACtD,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;AACjE;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACpC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC3B,EAAE,IAAI,EAAE,OAAO;AACf,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC7D,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AAC/D,EAAE,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE;AACrE,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO;AAC3B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO;AACpC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;AACtB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;AACrB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC;AACzF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS;AACrD,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE;AACtE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC9B,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE;AAC1D;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;AACrB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ;AACjC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1D,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;AAC1B,EAAE;;AC5JF,GAAG;AACH,CAAC,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;AAC1E,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ;AACpF,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE;AAClF,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;AACtF,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG;AACtF,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI;AAC7E,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;AACvF,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,WAAW,CAAC;AACnE,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,QAAQ,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC3D,CAAC,CAAC,SAAS,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC,EAAE;AAClH,CAAC,CAAC,KAAK,CAAC;AACR,CAAC,CAAC,KAAK,EAAE,CAAC,YAAY,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE;AAC1D,CAAC,CAAC,KAAK,aAAa,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/D,CAAC,CAAC,SAAS,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE;AACnD,CAAC,CAAC,KAAK,EAAE;AACT,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,QAAQ,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC/C,CAAC,CAAC,SAAS,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC3D,CAAC,CAAC,SAAS,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,EAAE;AACxD,CAAC,CAAC,KAAK,CAAC;AACR,CAAC,CAAC,KAAK,EAAE,CAAC,YAAY,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE;AAC1D,CAAC,CAAC,KAAK,aAAa,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/D,CAAC,CAAC,SAAS,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE;AACnD,CAAC,CAAC,KAAK,EAAE;AACT,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;AAC9C,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;AAC9C,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;AAC/C,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,IAAI;AACzB,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AAC7C,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE;AAC9C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO;AACtE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC;AACzH,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC;AACtH,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK;AAC1F,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACjD;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG;AACjB,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC;AAC1B,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE;AACjF,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE;AACnD,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC;AACvE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC;AAC7B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;AACnC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,QAAQ,CAAC;AACpC,EAAE,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC;AACpC,EAAE,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,GAAG;AAC7D,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACpE,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE;AAClD,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7B,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxB,GAAG,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC;AAChE,IAAI,IAAI,CAAC,mBAAmB;AAC5B,GAAG,EAAE;AACL,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AAClC;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE;AAC/D,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC,EAAE;AACtF,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;AACzB,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,8BAA8B,CAAC,CAAC,CAAC,CAAC,EAAE;AAC5F,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACxB,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI;AACtD,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAClF,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE;AACjD,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,EAAE;AACzE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,YAAY,EAAE,OAAO;AAC5B,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,YAAY,CAAC,CAAC,CAAC;AAClD,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,mBAAmB,EAAE,OAAO,CAAC,EAAE;AAChD,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxB,GAAG,IAAI,CAAC,YAAY,EAAE,OAAO;AAC7B,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC5D,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,qBAAqB,EAAE,OAAO,CAAC,EAAE;AACnD,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE;AACzD;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;AACtG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI;AAC9C,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;AAC1F,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK;AAC/C,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAClD,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,EAAE;AAC5E,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;AACjD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK;AAClD,CAAC,EAAE;AACH;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK;AACxC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AACnB;AACA,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM;AACpD,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE;AACxD,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC7B,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO;AACzE,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AAC7F,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE;AACxB,GAAG,KAAK,CAAC;AACT,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW;AACvD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE;AACnE,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO;AACjB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM;AACrE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,8BAA8B,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC;AACzE,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC;AAC5C,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AACvB,CAAC,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;AAC7D,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;AACxB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;AAClC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK;AACpF,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjC,EAAE,IAAI,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClD,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;AACjD,IAAI,MAAM,CAAC,KAAK,GAAG;AACnB,GAAG,CAAC;AACJ,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;AAC7C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC;AACtE,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;AAClF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE;AAC1D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC,GAAG,CAAC,IAAI,CAAC;AACV,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG;AACtC;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,EAAE;AAC5B,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,GAAG;AAC3C,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChC,EAAE,IAAI,CAAC,yBAAyB,GAAG;AACnC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,GAAG;AAC3C,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACf,EAAE,MAAM,CAAC;AACT,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI;AAC/D,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,kBAAkB,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9F,EAAE,IAAI,CAAC,KAAK,GAAG;AACf,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK;AACjE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACT,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,KAAK,GAAG;AAC1D,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;AACvC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI;AACtD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,2BAA2B,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC/E,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACd,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;AACjC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO;AAC3C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;AACtB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ;AACxC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;AACtB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC;AAC1C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO;AACvC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9D,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC;AAC7C,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK;AACrE,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AACpB;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;AAC5D,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7B,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE;AAC1B,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChC,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI;AACnG,GAAG,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE;AACzF,GAAG,UAAU,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC5B,IAAI,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,OAAO,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACpF,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE;AACZ,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;AAC/C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK;AAClE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI;AACrE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;AACvB,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG;AACtC,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE;AAChC;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC5B,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC5B,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AAC5C,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxB,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,GAAG;AACjF,GAAG,EAAE,CAAC,CAAC;AACP,IAAI,IAAI,CAAC,EAAE;AACX,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE;AACnF,GAAG,CAAC,CAAC,CAAC;AACN,IAAI,MAAM,CAAC,IAAI,CAAC;AAChB,GAAG,CAAC;AACJ,GAAG,EAAE,CAAC,CAAC;AACP,IAAI,IAAI,CAAC,EAAE;AACX,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE;AACnF,GAAG,CAAC,CAAC,CAAC;AACN,IAAI,MAAM,CAAC,IAAI,CAAC;AAChB,GAAG,CAAC;AACJ,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;AAC7B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;AAC9C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC;AAC9E,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK;AAClE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI;AACrE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,aAAa,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,EAAE;AACxH,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE;AACrC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;AAC1B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;AACjE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ;AAClG,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC;AACjC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE;AACjE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC;AAC1E,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAChE,CAAC,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC;AACnC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI;AAC7C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK;AACtD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE;AAC3B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;AACxB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK;AAC9D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC5D,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,GAAG;AACtC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AAChD,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;AAC7C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI;AAC1D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAChE,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC;AAC7B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM;AAClC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;AACzF,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC;AACxD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG;AACjD,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK;AACrD,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC;AAC5C,EAAE,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG;AACjD,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG;AACd,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG;AACb;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;AAChC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAClD,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AACpB,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG;AACxB;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK;AACjC,GAAG,YAAY,CAAC,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACjE,GAAG,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC3D,IAAI,KAAK,GAAG;AACZ,GAAG,CAAC;AACJ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACrC,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,EAAE;AAC7B,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK;AACjB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAClD,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AACpB,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG;AACxB,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxB,GAAG,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC1D,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE;AAC/B,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACtB,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACvC,EAAE,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE;AACpD,EAAE,IAAI,CAAC,yBAAyB,GAAG;AACnC,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE;AAC3C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE;AAClC;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;AACtD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,CAAC;AAC5F,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM;AAChE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;AACxB,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG;AACb;AACA,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAClD,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AACpB,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG;AACxB,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5B,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxB,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAClE,GAAG,IAAI,CAAC,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE;AAC/B,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACvC,EAAE,IAAI,CAAC,mBAAmB,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,EAAE;AAChD,EAAE,IAAI,CAAC,yBAAyB,GAAG;AACnC,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,EAAE;AACvC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE;AAC9B;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC;AAC3C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC;AAClF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACxD,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACZ,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG;AACtC;AACA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG;AACjB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7B,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,mBAAmB,CAAC,UAAU,GAAG;AACxC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACnD,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,EAAE;AACrC,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,GAAG;AAC/B;AACA,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE;AAC9B;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI;AAC7C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC,GAAG,CAAC,YAAY,CAAC;AAClB,EAAE,CAAC,OAAO,CAAC;AACX,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5B,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE;AAC5E;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AACvC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxB,GAAG,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,eAAe,GAAG;AAC7D,GAAG,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3D,IAAI,IAAI,CAAC,mBAAmB,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,EAAE;AACtD,GAAG,CAAC;AACJ,EAAE,CAAC;AACH,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACf,GAAG,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACxB,IAAI,YAAY,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,EAAE;AACpC,IAAI,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;AAC9E,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO;AAC9F,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACvF,IAAI,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;AACtF,IAAI,EAAE,CAAC,CAAC;AACR,KAAK,IAAI,CAAC,SAAS,CAAC,EAAE;AACtB,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE;AACzB,KAAK,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE;AACnC,KAAK,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;AACtD,IAAI,CAAC,CAAC,CAAC;AACP,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE;AACvD,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC7B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG;AAC3B,KAAK,CAAC;AACN,IAAI,CAAC;AACL,GAAG,CAAC;AACJ,GAAG,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/B,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE;AAC1B,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE;AACpC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACxD,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;AAC3F,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;AACnF,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE;AACtD,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG;AAC1B,IAAI,CAAC;AACL,GAAG,CAAC;AACJ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE;AAC5B,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;AACpC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,yBAAyB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACvE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC;AACrD,EAAE,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,sBAAsB,EAAE,CAAC,EAAE;AAC3F,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;;AC5jBF,GAAG;AACH,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE;AACjF,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG;AACpG,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;AAClG,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC;AACvG,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AAC9F,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,eAAe,CAAC;AACrE,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,QAAQ,CAAC,iBAAiB,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACnD,CAAC,CAAC,SAAS,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC/D,CAAC,CAAC,SAAS,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE;AAC5D,CAAC,CAAC,KAAK,CAAC;AACR,CAAC,CAAC,KAAK,EAAE,CAAC,YAAY,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,EAAE;AAClE,CAAC,CAAC,KAAK,iBAAiB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/D,CAAC,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE;AACpD,CAAC,CAAC,KAAK,EAAE;AACT,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;AACtD,CAAC,CAAC,SAAS,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;AACrF,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE;AAC9D,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,GAAG;AAC3C,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;AACvD,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE;AAC5C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO;AAC3E,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;AAC7F,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC;AAC9H,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACxD,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;AAC1D;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC/C;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG;AACrB;AACA,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC;AAC1B,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;AAC5C,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;AAClC,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ;AAC3B,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE;AACnD,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC;AACvE;AACA,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,GAAG;AACpD,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,GAAG;AACzC,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE;AAC7C;AACA,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE;AACzB;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,EAAE;AAC/D,CAAC,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC,EAAE;AAC7E,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACxB,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI;AACtD,EAAE,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAClF,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE;AAC/C,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,EAAE;AACvE,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO;AACvB,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC3C,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,EAAE;AAC3C,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE;AACvD;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AAC7G,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK;AAC3D,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AACjG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM;AAC5D,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACvD,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC,EAAE;AACrF,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AACnD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,GAAG,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM;AAC9D,CAAC,EAAE;AACH;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AACnB;AACA,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM;AACzD,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE;AAC5D,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACjC,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO;AACxF,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;AACrG,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5B,GAAG,KAAK,CAAC;AACT,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC;AAClC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK;AACvF,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAClB,EAAE,QAAQ,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACtD,GAAG,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;AACjD,IAAI,MAAM,CAAC,KAAK,GAAG;AACnB,GAAG,CAAC;AACJ,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AAClD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC;AAChF,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;AACvF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE;AAC1D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC,GAAG,CAAC,QAAQ,CAAC;AACd,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG;AACtC;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,EAAE,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,EAAE;AAChC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,GAAG;AAC/C,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACnB,EAAE,IAAI,CAAC,6BAA6B,GAAG;AACvC,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,cAAc,GAAG;AAC/C,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACnB,EAAE,MAAM,CAAC;AACT,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI;AAC/D,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,kBAAkB,GAAG,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClG,EAAE,QAAQ,CAAC,KAAK,GAAG;AACnB,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK;AAC/D,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACT,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/D,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE,KAAK,GAAG;AAC1D,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI;AACtD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,uBAAuB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACd,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;AACrC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC;AACxD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK;AAC/E,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS;AACzE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;AACvB,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG;AAC1C,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE;AACxC;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAChC,EAAE,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAChC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AACjD,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,GAAG;AAChF,EAAE,EAAE,CAAC,CAAC;AACN,GAAG,IAAI,CAAC,EAAE;AACV,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE;AAC9E,EAAE,CAAC,CAAC,CAAC;AACL,GAAG,MAAM,CAAC,IAAI,CAAC;AACf,EAAE,CAAC;AACH,EAAE,EAAE,CAAC,CAAC;AACN,GAAG,IAAI,CAAC,EAAE;AACV,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE;AAC9E,EAAE,CAAC,CAAC,CAAC;AACL,GAAG,MAAM,CAAC,IAAI,CAAC;AACf,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;AAC7B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;AACvB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,MAAM;AAC9C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnD,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC;AAC7B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC;AACxC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AAClD,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK;AAC/D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE;AAC/B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,KAAK;AACvE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9D,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,sBAAsB,GAAG;AAC1C,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACpD,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AAClD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK;AAC/D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC,MAAM,CAAC,IAAI,CAAC,mBAAmB,CAAC;AACjC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM;AACrC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM;AAChG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC;AACrE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AAC9D,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK;AACrD,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC;AAChD,EAAE,oBAAoB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG;AACrD,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG;AACd,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG;AACb;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK;AACrC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACtD,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;AAC5B,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,GAAG;AAC5B;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK;AACjC,GAAG,YAAY,CAAC,CAAC,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACzE,GAAG,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC3D,IAAI,KAAK,GAAG;AACZ,GAAG,CAAC;AACJ,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACzC,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,EAAE;AACjC,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM;AACtB,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACtD,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;AAC5B,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,GAAG;AAC5B,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AAClD,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACrD,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE;AAC9B,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACrB,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE;AAChD,EAAE,IAAI,CAAC,6BAA6B,GAAG;AACvC,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,EAAE;AAC/C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,EAAE;AACtC;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AACzD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,cAAc,CAAC,MAAM,CAAC,OAAO,CAAC;AACnG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM;AAC7E,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC;AAC5B,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG;AACb;AACA,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACtD,EAAE,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE;AAC5B,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,GAAG;AAC5B,EAAE,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE;AAChC,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC7D,EAAE,QAAQ,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE;AAC9B,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,IAAI,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,EAAE;AAC5C,EAAE,IAAI,CAAC,6BAA6B,GAAG;AACvC,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,SAAS,CAAC,EAAE;AAC3C,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE;AAClC;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AAC9C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC;AACzF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1D,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACZ,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,QAAQ,GAAG;AAC1C;AACA,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG;AACrB,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC,IAAI,CAAC,eAAe,CAAC,UAAU,GAAG;AACnC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACtD,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE;AACpC,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,GAAG;AAC/B;AACA,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,SAAS,CAAC,EAAE;AAClC;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;AAC9C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AAClD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC,GAAG,CAAC,YAAY,CAAC;AAClB,EAAE,CAAC,OAAO,CAAC;AACX,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE;AACpC,EAAE,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAAE;AAC5F;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAC3C,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,eAAe,GAAG;AACxD,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1D,GAAG,IAAI,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,EAAE;AACjD,EAAE,CAAC;AACH,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACnB,GAAG,EAAE,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;AAC5B,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,EAAE;AACxC,IAAI,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC;AACnF,IAAI,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO;AACnG,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACvF,IAAI,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;AAC3F,IAAI,EAAE,CAAC,CAAC;AACR,KAAK,IAAI,CAAC,SAAS,CAAC,EAAE;AACtB,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,EAAE,CAAC,EAAE;AACzB,KAAK,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE;AACnC,KAAK,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC;AAC1D,IAAI,CAAC,CAAC,CAAC;AACP,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE;AAC3D,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC7B,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG;AAC3B,KAAK,CAAC;AACN,IAAI,CAAC;AACL,GAAG,CAAC;AACJ,GAAG,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC,IAAI,CAAC;AACnC,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE;AAC9B,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE;AACxC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC;AAC5D,IAAI,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;AAChG,IAAI,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC;AACnF,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE;AAC1D,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5B,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,GAAG;AAC1B,IAAI,CAAC;AACL,GAAG,CAAC;AACJ,GAAG,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE;AAChC,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,SAAS,CAAC,6BAA6B,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,eAAe,EAAE,CAAC,CAAC,CAAC,CAAC;AACjD,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,sBAAsB,EAAE,CAAC,EAAE;AACnF,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;;AC1bF,GAAG;AACH,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;AAC1E,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,GAAG,CAAC,QAAQ,CAAC;AACjF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,QAAQ;AACZ,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM;AACxB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;AAClE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;AACjD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAChD;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE;AAChD,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE;AACjC,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACpD;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;AACzE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM;AACxE,CAAC,EAAE;AACH;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;AACjD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM;AACnD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrD,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACnB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE;AACnE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM;AACjD,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;AACjB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9B,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;AACrB,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE;AAC/B,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE;AAC9D,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE;AAChE,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;;ACrEF,GAAG;AACH,CAAC,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AACvF,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;AACtF,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,EAAE;AAC1G,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,CAAC,KAAK,EAAE;AAC9F,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG;AAC1D,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;AACpE,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC;AACrD,CAAC,CAAC,KAAK,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAC1D,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC;AACrC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC,KAAK,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAC1D,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE;AACrC,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,IAAI;AACtB,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC;AACxC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,aAAa,EAAE,OAAO,CAAC,EAAE;AAC5E,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,oBAAoB,CAAC,cAAc;AAC1F,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY;AAC9B,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa;AACpC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW;AAClC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB;AACvC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACnC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa;AACpC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc;AACrC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB;AACxC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG;AAClE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;AACxD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACtD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACzF,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC9C,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACnD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC/C,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC3F,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACjD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACnG;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;AAC7C;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE;AACjE,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;AACzC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AAC1B,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE;AAChE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE;AACrE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;AACnE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE;AACxE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;AACpE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE;AACrE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE;AACtE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;AACzE;AACA,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;AACvB;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;AACjD;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC;AAC5C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC3D,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC9B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;AACjB,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9B,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,aAAa,CAAC,WAAW;AAC7E,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AACvB,GAAG,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE;AACzD,EAAE,CAAC;AACH,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,EAAE;AAC1B,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM;AACjB,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AACxE;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5E,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,IAAI,EAAE,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE;AAC5C,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE;AAC5E,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE;AAC5D,EAAE;;ACzHF,GAAG;AACH,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO;AAC7F,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,WAAW;AAC9F,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,QAAQ,CAAC;AACjD,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC;AACzD,CAAC,CAAC,KAAK,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,GAAG;AAC1D,CAAC,CAAC,KAAK,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;AAC1D,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,IAAI;AACtB,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,cAAc,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ;AAC9D,CAAC,CAAC,KAAK,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;AACjD,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC;AAClC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC,KAAK,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC3B,CAAC,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE;AAClF,CAAC,CAAC,SAAS,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,QAAQ,EAAE,OAAO,CAAC,EAAE;AAC/C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY;AAC9B,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB;AACxC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;AACzE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;AAC3D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACtD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACpD;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC;AACvB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AACvB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;AACtB,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;AAC5B,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;AAC5B;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AACpB,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACnC,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE;AACxD,CAAC,IAAI,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,EAAE;AACxD,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;AACzC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC7B,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE;AACpC,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE;AAChE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;AACzE;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK;AAC5C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7D,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACnE,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC/B,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,KAAK,CAAC;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AAC3B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK;AAC1C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC/B,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AACxE,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,EAAE;AAC7D,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC/B,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,KAAK,GAAG;AACd,EAAE;;AC9GF,GAAG;AACH,CAAC,CAAC,CAAC,qBAAqB,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE;AAC7G,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC;AAClG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,IAAI;AACzF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM;AACxB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACnC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW;AAClC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO;AAChE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ;AAC7C,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK;AAClE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK;AACxE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACrF,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM;AAChE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC7D,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;AACnB,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC;AAC3B,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AAC9C;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACzD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC/C,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC9C;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;AACxB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;AAC7B,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC1C,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC;AAChB,EAAE,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE;AACnB,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC5C,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC;AAChB,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE;AACjB,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACtD,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC9C,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC;AAChB,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;AAChB,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AACnD,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AAC/C;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACzB,EAAE,MAAM,CAAC,CAAC,CAAC,eAAe,EAAE;AAC5B,EAAE,GAAG,CAAC,CAAC,CAAC,eAAe,EAAE;AACzB,EAAE,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC;AAC3B,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAClE,CAAC,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACnE,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACpE;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,EAAE;AACzD,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,KAAK,CAAC,CAAC,EAAE;AAC7D,CAAC,IAAI,EAAE,MAAM;AACb,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,MAAM,CAAC,CAAC,CAAC;AACnD,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE;AAC1F,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AAC/D,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AAC7C,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AAC7D,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;AACvE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;AACtE;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;AACd,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI;AAClD,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,EAAE;AACH;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC;AACjB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ;AAC7C,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK;AAC/D,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK;AACrE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC,GAAG,CAAC,OAAO,CAAC;AACb;AACA,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACpC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC7C,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,EAAE;AACtD,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,IAAI,CAAC,eAAe,GAAG;AACxB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC;AAChC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,YAAY,CAAC,CAAC,WAAW,CAAC;AACvC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,GAAG;AAClC,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,GAAG;AAChD,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,GAAG;AAC5E,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC,YAAY,CAAC,WAAW,GAAG;AAClF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACjB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACT,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;AACrB,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACvB,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;AAClC,IAAI,YAAY,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AAC9B,IAAI,KAAK,CAAC;AACV,GAAG,CAAC;AACJ,EAAE,CAAC;AACH,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACV,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACjB,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;AAClC,IAAI,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AAC7B,IAAI,KAAK,CAAC;AACV,GAAG,CAAC;AACJ,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE;AACxE,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE;AACzE,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE;AAC7C,EAAE;;ACjJF,GAAG;AACH,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,mBAAmB,EAAE;AAC9F,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO;AACnG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,aAAa,CAAC;AACvF,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC;AAClB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB;AACvC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,WAAW,CAAC,KAAK;AAC1C,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,QAAQ,EAAE;AACzG,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACvD;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AAChB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC;AACjC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,SAAS,CAAC;AACrC;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,EAAE;AACvD,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;AAC/B,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,EAAE;AAC1E;AACA,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;AACvB;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/D;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;AACrB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,KAAK,GAAG;AACjF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;AACrB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAC5C;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,QAAQ,EAAE;AAC9E,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO;AACpC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC7D,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;AACrB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC;AAC9B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,QAAQ,EAAE;AAChF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS;AACtC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/D,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC;AACvB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC;AACzB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,KAAK;AACrC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC5D,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACnB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AAC3E,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACzC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC/B,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AAC1C,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,CAAC;AAClB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,QAAQ,EAAE;AAC9E,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO;AAC3C,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;AAC1B,CAAC,IAAI,CAAC,kBAAkB,GAAG;AAC3B,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC;AACpB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,QAAQ,EAAE;AAChF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS;AAC/C,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;AAC9B,CAAC,IAAI,CAAC,kBAAkB,GAAG;AAC3B,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AAC5E,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACzC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AAC1C,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC;AACzB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC;AAC7E,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC;AAC7C,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC;AAClD,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;AACb;AACA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAChB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3B,GAAG,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC5C,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC/C,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,kBAAkB,GAAG;AAC3B;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;;AC7KF,GAAG;AACH,CAAC,CAAC,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,CAAC,OAAO,CAAC;AAC3G,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,qBAAqB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC;AACzG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,OAAO,IAAI;AACzF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY;AAC9B,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB;AACxC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,uBAAuB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACvD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACpD;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AACpB,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC/C,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,EAAE;AACvD,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE;AACjE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;;ACjC1E,GAAG;AACH,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI;AAChG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;AACzD,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG;AAC7F,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;AACjE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,0BAA0B;AACrG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY;AAC9B,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa;AACpC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW;AAClC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB;AACvC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa;AACpC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACtD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAChD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC9C,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACnD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC3F;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE;AACtD,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE;AACjE,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AACtC,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE;AAChE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE;AACrE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;AACnE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE;AACxE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE;AACrE;AACA,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;AACvB;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM;AACpG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,2BAA2B,CAAC,CAAC,CAAC,KAAK,CAAC;AACpE;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC;AACtD;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AAC3E;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAC5C,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,EAAE;AAC1B,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;;AC1EF,GAAG;AACH,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ;AACjF,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI;AAC3C,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,GAAG,CAAC,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG;AAC7E,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG;AAC/E,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC;AACrE,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,mBAAmB;AAC/E,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AAC7B,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AACnC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AAC7B,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AACnC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;AACpD,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC;AACnB,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AAC7B,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;AACnC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC;AACvD,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,CAAC;AAC/C,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE;AACnD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB;AAC1E,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY;AAC9B,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB;AACxC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACtD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACpD;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AACpB,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC/C,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE;AACtD,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE;AAChE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,kBAAkB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;;AC7DzE,GAAG;AACH,CAAC,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,eAAe,EAAE;AACjF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,OAAO;AAC/F,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,cAAc,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,WAAW,CAAC;AAC5F,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC;AAClB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY;AAC9B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACnD;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE;AACnD,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE;AAC7D;AACA,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;AACvB;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC;;AClCnD,GAAG;AACH,CAAC,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,OAAO,CAAC;AACpF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,IAAI;AACrF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY;AAC9B,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB;AACxC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACnD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACpD;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AACpB,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC/C,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE;AACnD,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,EAAE;AAC7D,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;;AChCtE,GAAG;AACH,CAAC,CAAC,CAAC,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB;AAC7E,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC3D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM;AACxB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU;AACjC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACnC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc;AACrC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB;AACxC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACrD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACrC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC/C,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACjD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACpD;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC7C,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC;AAChB,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;AAChB,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACf,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AACxC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACnD;AACA,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC5C,EAAE,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,EAAE;AAC3C,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAClB;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AACR,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACpC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACvC,EAAE,CAAC,CAAC,CAAC;AACL,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC;AACxC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE;AACpD,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACzD,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE;AACjE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;AACnE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE;AACrE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;AACxE;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM;AAC3B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9D,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,GAAG;AACtC;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxD,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAClC,EAAE,OAAO,CAAC,KAAK,GAAG;AAClB,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO;AAC5C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,GAAG;AACtC;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3E,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE;AAC3B,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO;AAC9C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,GAAG;AACtC;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC/E,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAClC,EAAE,OAAO,CAAC,KAAK,GAAG;AAClB,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC/C,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE;AAC3B,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9C,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG;AAC1C,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC/C,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG;AACtC,CAAC,CAAC;AACF,EAAE;;ACtGF,GAAG;AACH,CAAC,CAAC,CAAC,yBAAyB,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;AACpG,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,MAAM,CAAC;AAC7C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE;AACxG,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,wBAAwB,CAAC;AAC9C,CAAC,CAAC,KAAK,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC;AAC1D,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,wBAAwB,EAAE;AAC7C,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AAChD,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,aAAa,KAAK,CAAC,CAAC,CAAC;AACvB,CAAC,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACxC,CAAC,CAAC,qBAAqB,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;AAC1C,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE;AACvB,CAAC,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACxC,CAAC,CAAC,qBAAqB,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;AAC1C,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE;AACvB,CAAC,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACxC,CAAC,CAAC,qBAAqB,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AAC5C,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE;AACvB,CAAC,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACxC,CAAC,CAAC,qBAAqB,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;AAC3C,CAAC,CAAC,iBAAiB,CAAC,CAAC,EAAE;AACvB,CAAC,CAAC,iBAAiB,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAChD,CAAC,CAAC,qBAAqB,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACxC,CAAC,CAAC,qBAAqB,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;AAC3C,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC;AACtB,CAAC,CAAC,aAAa,CAAC;AAChB,CAAC,CAAC,SAAS,CAAC;AACZ,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE;AAC9C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,wBAAwB;AACnG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM;AACxB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACnC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACnC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB;AACxC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB;AACvC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW;AAClC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB;AAChC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB;AAC/B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,IAAI;AAC/C,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;AACtG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC;AAC5E,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG;AACvE,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;AACtD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,MAAM,EAAE;AACrG,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;AAC5E,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,OAAO;AAC7E,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC;AACxF,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;AACzF,CAAC,CAAC,EAAE,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI;AAChF,CAAC,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,EAAE,GAAG,GAAG,CAAC,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE;AAC5E,CAAC,CAAC,EAAE,GAAG,CAAC,UAAU,CAAC,EAAE,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;AAC3E,CAAC,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC;AACzB,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE;AACnE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;AACf;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC5D;AACA,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACrB,EAAE,cAAc,CAAC,CAAC,KAAK,CAAC;AACxB,EAAE,eAAe,CAAC,CAAC,KAAK,CAAC;AACzB,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,OAAO;AACzB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACb;AACA,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC;AAC3D,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;AAC7B,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE;AACpD,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACvE,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE;AACxD,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC/C,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAC9C,GAAG,KAAK,CAAC,CAAC,CAAC,QAAQ,EAAE;AACrB,GAAG,MAAM,CAAC,CAAC,KAAK;AAChB,EAAE,CAAC,CAAC,EAAE;AACN,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAChD,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;AAC5B,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACjG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACpB,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACnG,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACnD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC9C;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;AAC9B,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC;AAC7C,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC;AAC/C,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC;AACjC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC;AAClD,EAAE,CAAC;AACH,GAAG,MAAM,CAAC,CAAC,IAAI,CAAC;AAChB,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC;AACvB,GAAG,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC;AACtC,GAAG,eAAe,CAAC,CAAC,IAAI,CAAC;AACzB,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE;AAC9B,EAAE,EAAE;AACJ,EAAE,MAAM,CAAC,IAAI;AACb,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpB,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;AACjB,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACjC,EAAE,CAAC,CAAC,EAAE;AACN,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC1E,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC;AACtC,GAAG,IAAI,CAAC,KAAK,EAAE,eAAe,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACnF,EAAE,CAAC;AACH,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7B,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AACjC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE;AACjC,GAAG,CAAC;AACJ,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AACnB,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACzC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACvC,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE;AACpF,IAAI,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACxD,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACxC,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACzC,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3B,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,EAAE;AACzB,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,EAAE;AACzB,EAAE,GAAG,CAAC,CAAC,CAAC,iBAAiB,EAAE;AAC3B,EAAE,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC;AAC7B,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AACnB,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AACrB,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;AACpD,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACrB,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE;AACpB,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,GAAG;AACzC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC;AAC9B,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACrB,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;AACvC,CAAC,CAAC;AACF,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,OAAO,CAAC,CAAC,CAAC;AACnE,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;AACzB,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC,EAAE;AAChE,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,MAAM,CAAC,CAAC,CAAC;AACjE,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;AACxD,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC;AAC3D,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AAC1B,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpB,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC,EAAE;AACzE,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE;AACpC,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE;AAC9C,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;AACtC,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;AAC7C,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACnB,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,CAAC,EAAE;AACnE,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ;AACvE,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1B,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AACtB,GAAG,IAAI,CAAC,eAAe,GAAG;AAC1B,EAAE,CAAC;AACH,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAClB;AACA,CAAC,IAAI,CAAC,iBAAiB,GAAG;AAC1B,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AAChE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;AAC1E,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;AAC1E,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;AAC/E,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE;AAC9E,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;AACzE;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,OAAO,CAAC;AACpE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK;AACxD,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;AACnG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;AACtB,CAAC,EAAE;AACH;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;AACzF,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC;AAC/D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;AAC/C,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;AACxC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,IAAI,CAAC;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtF,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,MAAM,CAAC,IAAI,CAAC;AACd,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AACpE,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,MAAM,CAAC,IAAI,CAAC;AACd,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACxE,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO;AAC3C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,GAAG;AACpB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrE,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChD,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AACnB,CAAC,CAAC,CAAC,EAAE;AACL,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI;AACjD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK;AACzB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC;AAC3C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;AACnB,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG;AAC1B;AACA,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACtC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AACf,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE;AACvC;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACf,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;AACtB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACvC,GAAG,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AAC1B,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,MAAM,CAAC;AACV,EAAE,CAAC;AACH;AACA,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACd,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACxC,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAClE,IAAI,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AACtB,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACzB,IAAI,KAAK,CAAC;AACV,GAAG,CAAC;AACJ,EAAE,CAAC;AACH,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChB,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AACjD,EAAE,CAAC;AACH,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACf,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;AAClC,EAAE,CAAC;AACH,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,EAAE;AAC9B,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI;AACnD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK;AACzB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC;AAC3C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;AACnB,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG;AACb;AACA,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACtC,EAAE,GAAG,CAAC,IAAI,CAAC;AACX;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AACpE,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE;AACvC,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChB,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACvD,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACxC,IAAI,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC3D,GAAG,CAAC;AACJ,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChB,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACvB,GAAG,CAAC;AACJ,EAAE,CAAC;AACH,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE;AACzB,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK;AAChD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK;AACxB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG;AACtD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;AACjB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE;AAClD,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACd,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACzC,EAAE,MAAM,CAAC,IAAI,CAAC;AACd,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACpC,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG;AAC1B,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AACrC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG,CAAC,KAAK,CAAC,EAAE;AAC/C,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,KAAK,CAAC;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI;AACvB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,GAAG,CAAC,KAAK;AACzB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC;AAC3C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACnF,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG;AACb;AACA,CAAC,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACtC,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5C,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACf,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACtB,EAAE,CAAC;AACH,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,EAAE;AAC5B,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChB,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG;AAChC;AACA,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AACjE;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC/C,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AACf,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACd,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1D,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;AACpD,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACf,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE;AAC7C,EAAE,IAAI,CAAC,eAAe,GAAG;AACzB,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE;AACxE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI;AACvB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE;AAC5C,CAAC,IAAI,CAAC,UAAU,GAAG;AACnB,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AAC/B,CAAC,IAAI,CAAC,eAAe,GAAG;AACxB,CAAC,IAAI,CAAC,KAAK,GAAG;AACd,CAAC,IAAI,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ;AACxF,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC9B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChB,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,GAAG;AAChC;AACA,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AACpE;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC/C,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AACf,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACd,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1D,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;AACpD,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACf,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE;AAC7C,EAAE,IAAI,CAAC,eAAe,GAAG;AACzB,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC3B,EAAE,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC7D,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE;AAC7C,EAAE,IAAI,CAAC,eAAe,GAAG;AACzB,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;AAClE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AACtE,CAAC,CAAC,CAAC,IAAI,CAAC;AACR,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC;AACnD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC,GAAG,CAAC,SAAS,CAAC;AACf;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AACzB,CAAC,CAAC;AACF;AACA,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE;AACxC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI;AAC3C,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI;AACjE,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;AACrB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACrC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;AACpE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;AACrE,CAAC,CAAC,CAAC,IAAI,CAAC;AACR,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,CAAC;AACnD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC,GAAG,CAAC,SAAS,CAAC;AACf;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC7C,CAAC,CAAC;AACF;AACA,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE;AACxC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI;AAC3C,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI;AAC9C,EAAE,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC;AACrB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACrC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACjC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,MAAM;AAC/C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAChE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AAClB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM;AACtB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK;AAC9B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,IAAI,CAAC,eAAe,GAAG;AACzB,EAAE,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AAC3B,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM;AACrB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK;AAC9B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACpE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,EAAE;AAC5C,CAAC,IAAI,CAAC,UAAU,GAAG;AACnB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;AAClC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK;AAC1C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC;AACzB;AACA,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1B,EAAE,EAAE,CAAC,CAAC;AACN,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,EAAE;AACxB,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,EAAE,GAAG,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,CAAC;AACxG,EAAE,CAAC,CAAC,CAAC;AACL,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE;AAC1B,EAAE,CAAC;AACH,CAAC,CAAC,CAAC,EAAE;AACL,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;AAC3C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC7C,EAAE,IAAI,CAAC,KAAK,GAAG;AACf,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,CAAC,eAAe,GAAG;AACzB,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AAC3B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK;AAC1C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACxC,GAAG,IAAI,CAAC,UAAU,GAAG;AACrB,GAAG,MAAM,CAAC,KAAK,CAAC;AAChB,EAAE,CAAC;AACH;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtB,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5B,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACxC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvD,KAAK,IAAI,CAAC,UAAU,GAAG;AACvB,IAAI,CAAC;AACL,IAAI,MAAM,CAAC,KAAK,CAAC;AACjB,GAAG,CAAC;AACJ;AACA,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;AACvC,GAAG,UAAU,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;AACtD,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;AAC1B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC,EAAE,CAAC,CAAC;AACL,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;AACvB,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;AAC7B,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM;AACnB,CAAC,CAAC,CAAC,CAAC;AACJ,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS;AACpD,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC7C,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAClC,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC/C,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AACX,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACzD,GAAG,CAAC;AACJ,GAAG,MAAM,CAAC,KAAK,CAAC;AAChB,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC/C,GAAG,IAAI,CAAC,eAAe,GAAG,KAAK,GAAG;AAClC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChD,GAAG,IAAI,CAAC,WAAW,GAAG,KAAK,GAAG;AAC9B,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;AACjF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI;AAC7C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC;AACjE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAC3C,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;AACpC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,GAAG;AAC5C,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AAC1D;AACA,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;AAC5D,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa;AAC9D,EAAE,EAAE,CAAC,CAAC;AACN,GAAG,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;AACpD,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;AAC9B,GAAG,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS;AAClD,EAAE,CAAC,CAAC,CAAC;AACL,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE;AACxD,GAAG,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC;AACnE,GAAG,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE;AACzB;AACA,EAAE,CAAC;AACH;AACA,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI;AAC/D,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AAC1B,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC;AAChC,GAAG,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG;AACjD,GAAG,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACvD,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,2BAA2B;AACxC,EAAE,EAAE;AACJ,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,GAAG;AACrC;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACtC,GAAG,IAAI,CAAC,qBAAqB,GAAG;AAChC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,YAAY;AACvD,GAAG,MAAM,CAAC;AACV,EAAE,CAAC;AACH;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,GAAG;AAC1C,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACpC,IAAI,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;AACrF,IAAI,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC9B,EAAE,CAAC;AACH;AACA,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG;AAChG,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;AAC3C,EAAE,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;AAClB,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACnC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;AACpE,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,EAAE,CAAC;AACH,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;AAC/C,EAAE,IAAI,CAAC,qBAAqB,GAAG;AAC/B,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,CAAC,qBAAqB,GAAG;AAC/B,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC;AAC/F,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9E,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,GAAG;AACrC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAChC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AACvB,EAAE,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG;AACvB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACrB,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,GAAG;AACjC,EAAE,CAAC;AACH,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACxB,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI;AAC/C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;AAClC,EAAE,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE;AAC9C,EAAE,IAAI,CAAC,UAAU,GAAG;AACpB,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK;AAC/C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,IAAI,EAAE,CAAC,SAAS,CAAC,EAAE;AAC/E,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;AAClC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1E,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,EAAE;AAC9C,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;AAC1F,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK;AACxB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AACrB,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE;AACxB,EAAE,IAAI,CAAC,eAAe,GAAG;AACzB,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpB,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE;AAC7B,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,EAAE;AAC3B,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,GAAG;AACxB,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,GAAG;AAC3B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AACZ;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM;AACjB,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE;AACpF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AACrB,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;AACpD,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACnB,EAAE,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;AAC7C,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpB,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;AAC9C,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpB,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACxD,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc,GAAG;AACpC,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM;AACnB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9D,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACrB,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,EAAE;AACnD,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AAC7B,GAAG,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,KAAK,GAAG;AACtD,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC9D,EAAE,CAAC;AACH,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;;AC9yBF,GAAG;AACH,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB;AACrE,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;AACvD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM;AACxB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU;AACjC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACnC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc;AACrC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB;AACxC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB;AACvC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,MAAM;AAChD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK;AAC5C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5D,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACjD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACrC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC/C,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACjD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACpD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACnD;AACA,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,KAAK,CAAC;AACjE;AACA,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC7C,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC;AAChB,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;AAChB,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACf,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AACxC,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;AACnD;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,CAAC,WAAW;AACjB,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AACxC,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1C,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC/C,EAAE,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG;AAClE,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE;AACjE,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI;AACjE,EAAE,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK;AACpE,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG;AACnE,EAAE,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE;AAC7E,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC;AACnC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,GAAG,CAAC,CAAC,CAAC,EAAE;AAC9D;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;AACpC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE;AACpD,EAAE;AACF;AACA,EAAE,CAAC,cAAc,CAAC,EAAE;AACpB;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACrD,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE;AAC7D,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;AAC/D,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE;AACjE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;AACpE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE;AACnE;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI;AAC5C,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ;AAClB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,SAAS;AAC5E,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI;AAC9C,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM;AAC9D,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC;AAChD,CAAC,EAAE;AACH;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO;AAC5B,CAAC,EAAE;AACH;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM;AACjB,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AACtE;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC1B,EAAE,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,EAAE;AACxC,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ;AAC/D,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI;AAC9D,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI;AAC1D,CAAC,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC;AACtD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACpD,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACxB,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM;AACvC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ;AAClB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AACzC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS;AAC1D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC,GAAG,CAAC,QAAQ,CAAC;AACd;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC/E,EAAE,IAAI,CAAC,MAAM,GAAG;AAChB,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC/C,EAAE,IAAI,CAAC,MAAM,GAAG;AAChB,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACZ,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AAClC,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK;AAChC,CAAC,CAAC,CAAC,CAAC;AACJ,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AACf,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE;AACrB,IAAI,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACtB,GAAG,EAAE;AACL,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;AACf,IAAI,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE;AACtB,IAAI,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AACrB,GAAG,EAAE;AACL,EAAE,CAAC;AACH;AACA,EAAE,IAAI,CAAC,IAAI,CAAC;AACZ,GAAG,CAAC,QAAQ,EAAE;AACd,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAClC,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK;AAClC,EAAE,EAAE;AACJ,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;AACnB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACpD,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACxB,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK;AACzC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK;AACf,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;AACrD;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9B,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;AACrB;AACA,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AAC5C;AACA,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACnC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK;AAClC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK;AAClC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrD,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACnB,EAAE;;AC9MF,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,mBAAmB,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;AAC3G,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;AAChF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE;AACxG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,wBAAwB,CAAC,CAAC,GAAG;AACxG,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,yBAAyB,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,eAAe,CAAC,IAAI,CAAC,GAAG;AACrG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY,CAAC;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC;AAChD,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;AACrD,CAAC,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,OAAO,EAAE;AACpC,CAAC,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AACjE,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AACnC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;AAC7C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,wBAAwB;AACnG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM;AACxB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW;AAClC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB;AAC5C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB;AACvC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW;AAClC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB;AACxC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc;AACrC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM;AAC9C,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM;AACnE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,IAAI;AACrF,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;AAC5E,CAAC,CAAC,EAAE,oBAAoB,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;AACzC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC;AAC9E,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE;AACxE,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;AACpD,CAAC,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;AACpD,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,QAAQ;AAC7B,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI;AACjF,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;AAC7E,CAAC,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;AAC5B,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK;AAC1E,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC;AACnB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK;AAC3E,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,uBAAuB,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;AACtE,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG;AACpE,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI;AACxE,CAAC,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC;AAChB,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AACtE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,MAAM,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC;AACxE,CAAC,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI;AACxE,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;AAC5B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC,QAAQ,CAAC,wBAAwB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC,GAAG,CAAC,WAAW,CAAC;AACjB,EAAE,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,qBAAqB,CAAC,EAAE,CAAC,UAAU,CAAC;AACnD,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AAChB,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AAC3B,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,EAAE;AACvD;AACA,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACxD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC9C,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACnD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC9C,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACpD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACjD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACxD;AACA,CAAC,IAAI,CAAC,eAAe,CAAC;AACtB,EAAE,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACxC,GAAG,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,eAAe;AAClC,CAAC,EAAE;AACH;AACA,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;AACrB,EAAE,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,qBAAqB,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtF,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE;AACnC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,aAAa,CAAC;AACzF,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,cAAc,CAAC;AAC/C,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,eAAe,CAAC;AACjD,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC,GAAG;AACjD,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,MAAM,CAAC,uBAAuB,CAAC;AAC/D,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE;AAC/C,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACpB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB;AACA,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;AAC7B,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,EAAE;AACpD,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;AAC5B,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC,CAAC;AAClD,EAAE,CAAC,MAAM,CAAC;AACV,GAAG,IAAI,EAAE,SAAS,CAAC;AACnB,GAAG,IAAI,EAAE,IAAI,CAAC;AACd,GAAG,IAAI,EAAE,OAAO;AAChB,IAAI,CAAC,MAAM,CAAC;AACZ,KAAK,IAAI,EAAE,KAAK;AAChB,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC;AACrD,IAAI,CAAC;AACL,EAAE,EAAE;AACJ;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;AAClB,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,EAAE;AACvB,EAAE,QAAQ,CAAC,CAAC,CAAC,YAAY,EAAE;AAC3B,EAAE,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC;AACtB,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACtB,EAAE,UAAU,CAAC,CAAC,CAAC,WAAW,EAAE;AAC5B,EAAE,UAAU,CAAC,CAAC,CAAC,WAAW,EAAE;AAC5B,EAAE,YAAY,CAAC,CAAC,CAAC,aAAa,EAAE;AAChC,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;AACxB,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AACnB,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,CAAC;AAC3C,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AAC1B;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC7B,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;AACnC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACtD,IAAI,WAAW,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;AACpC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,CAAC;AACnD,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AACvB,EAAE,CAAC;AACH,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;AAC9C;AACA,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC;AACjB,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACzC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACvC,GAAG,CAAC,cAAc,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE;AACpF,IAAI,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACxD,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC7C,GAAG,QAAQ,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AAC9C,EAAE,EAAE;AACJ;AACA,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,WAAW,CAAC,EAAE;AACtC;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3C,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM;AAC9C,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG;AACjD,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI;AAC9C,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE;AACrD,GAAG,IAAI,EAAE,OAAO;AAChB,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,QAAQ,CAAC,CAAC,CAAC;AACtD,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE;AACnC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,CAAC,EAAE;AAClE,GAAG,EAAE,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG;AACxD,GAAG,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM;AAClD,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,SAAS;AACpD,GAAG,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU;AACpD,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC;AAChD,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;AACpD,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI;AAChD,GAAG,EAAE,CAAC,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,GAAG;AACpD,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG;AAChD,GAAG,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE;AAC7C,EAAE,CAAC;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE;AACpC,CAAC,CAAC;AACF;AACA,CAAC,IAAI,CAAC,oBAAoB,CAAC;AAC3B,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AACjB,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AACtB,GAAG,CAAC,QAAQ;AACZ,CAAC,EAAE;AACH;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACzB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE;AACnC,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,KAAK,CAAC,UAAU;AAC5D,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ;AACpB,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnB,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC1B,GAAG,MAAM,CAAC,eAAe,GAAG;AAC5B,EAAE,CAAC;AACH,CAAC,CAAC,CAAC,EAAE;AACL,EAAE;AACF;AACA,EAAE,CAAC,cAAc,CAAC,EAAE;AACpB;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AAC5D,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;AACrE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,qBAAqB,CAAC,EAAE;AAC/E,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE;AAC1E,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;AACrE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,EAAE;AAC3E,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE;AACxE;AACA,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;AACvB;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC;AAC3B,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;AAC7C,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;AAC7C,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC;AACpB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE;AAC1F;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;AAC3C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ;AAC9C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACnE,EAAE,IAAI,CAAC,KAAK,GAAG;AACf,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AAC3B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK;AAC1C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ;AAChD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC,GAAG,CAAC,cAAc,CAAC;AACpB,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AACvC;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvC,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE;AACxD,EAAE,CAAC;AACH;AACA,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC;AACtC,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE;AACrD,EAAE,MAAM,CAAC,cAAc,CAAC;AACxB,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;AAC1B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AACzC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;AACpB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC;AACzB,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;AACvC;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS;AACpD,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC7C,GAAG,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE;AAClD,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACjD,GAAG,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE;AAClC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AACb,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AACnC,GAAG,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK;AACjC,EAAE,CAAC,CAAC,CAAC;AACL,GAAG,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAClE,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChB,KAAK,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE;AACtB,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;AACvB,IAAI,EAAE;AACN,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC;AACX,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChB,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,EAAE;AACvB,KAAK,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC;AACtB,IAAI,EAAE;AACN,GAAG,CAAC;AACJ,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC9C,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;AACnC;AACA,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,WAAW,CAAC,EAAE;AACzD,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK;AAC/B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,EAAE;AAC9D,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK;AAC9B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAChE,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,KAAK,CAAC,CAAC,EAAE;AACjE,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AACrD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;AACrC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI;AACnE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;AACzB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ;AAChD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,IAAI,CAAC,eAAe,GAAG;AACxB,CAAC,MAAM,CAAC,KAAK,CAAC;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AAC7D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;AACrC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI;AACnE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;AACzB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ;AAChD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AACrF,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;AACjB;AACA,CAAC,EAAE,CAAC,CAAC;AACL,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACpC,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;AACjC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE;AACjB,CAAC,CAAC,CAAC,CAAC;AACJ,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;AACzB,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG;AAC1B,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACnC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC/B,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC;AACnD,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC;AACtD,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AACvB,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;AACzC,EAAE,CAAC;AACH;AACA,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AACtD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;AACrC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC,IAAI,CAAC,UAAU,GAAG;AACnB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ;AAC1E,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AAC/B,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,WAAW;AACxC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI;AACrC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,SAAS;AAC7E,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI;AACnE,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC;AAC1B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC/E,CAAC,EAAE,CAAC,CAAC;AACL,EAAE,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACpC,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE;AACjB,CAAC,CAAC,CAAC,CAAC;AACJ,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;AACpC,GAAG,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI;AACvB,GAAG,IAAI,CAAC,eAAe,GAAG,KAAK,GAAG;AAClC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;AACnB,GAAG,IAAI,CAAC,WAAW,GAAG,KAAK,GAAG;AAC9B,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK;AAC/B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI;AAClD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AAC7C,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;AAChC,GAAG,IAAI,CAAC,eAAe,GAAG;AAC1B,EAAE,CAAC;AACH,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK;AAC/C,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;AACxC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG;AACtB,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC/B,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK;AACvB,EAAE,IAAI,CAAC,KAAK,GAAG;AACf,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC;AACxE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,EAAE;AAC1C,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,eAAe,GAAG;AACzB,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,qBAAqB,GAAG;AAC9B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAC5E,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM;AACjB,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,UAAU,CAAC,EAAE;AAClF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACrC,EAAE,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE;AACzC,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpB,EAAE,IAAI,CAAC,QAAQ,GAAG,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9C,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE;AACpC,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK;AAC9B,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG;AAChD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;AACxC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG;AACvC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG;AAChD,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC;AAC7E,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACnF,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AAClC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG;AACnC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG;AACvC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK;AAC3B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACpE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG;AACjC,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,GAAG,CAAC,EAAE;AACtC;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACd,EAAE,MAAM,CAAC;AACT,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;AACjD,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE;AACrB,EAAE,IAAI,CAAC,UAAU,GAAG;AACpB,EAAE,IAAI,CAAC,KAAK,GAAG;AACf,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK;AAClB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC/D,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE;AAC3B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ;AAC9D,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;AAC3B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK;AAC9C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS;AACvC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE;AACvC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK;AACrD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK;AAC9C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO;AACrC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC,EAAE,CAAC,CAAC;AACL,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE;AAC1B,EAAE,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC,CAAC,CAAC,CAAC;AACJ,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AAC7B,EAAE,MAAM,CAAC,IAAI,CAAC;AACd,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM;AAC7B,CAAC,EAAE,CAAC,CAAC;AACL,EAAE,IAAI,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpD,GAAG,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AACzB,EAAE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC,CAAC;AACJ,EAAE,MAAM,CAAC,IAAI,CAAC;AACd,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,KAAK,CAAC;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI;AAC9B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrE,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC;AAC3B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK;AAC3C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,EAAE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AACnC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK;AAChD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK;AAChE,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC7D,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE;AACvB,EAAE,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC9B,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,GAAG;AACzB,EAAE,CAAC,CAAC,CAAC;AACL,EAAE,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3B,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,GAAG;AACzB,EAAE,CAAC,CAAC,EAAE;AACN,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI;AACvF,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,MAAM,CAAC;AAClE,CAAC,CAAC,EAAE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI;AACjE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC;AACrC,CAAC,CAAC,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;AAC1D,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AACtC,CAAC,CAAC,EAAE,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;AAC7D,CAAC,CAAC,GAAG,CAAC;AACN,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE;AAC3C,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1C,CAAC,CAAC,GAAG,CAAC;AACN,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;AAC9D,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC;AAC1D,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE;AAC5E;AACA,CAAC,IAAI,CAAC,UAAU,GAAG;AACnB,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACxC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;AAClC,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE;AACtB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;AACtC,EAAE,CAAC;AACH,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAClB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI;AAC9B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI;AACvC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,GAAG;AAClE,CAAC,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC;AACzD,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,YAAY;AAChD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC,GAAG,CAAC,aAAa,CAAC;AACnB,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,EAAE;AACvC;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC,CAAC;AACjD,EAAE,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AAC1D,EAAE,aAAa,CAAC,WAAW,CAAC,CAAC,OAAO,CAAC,EAAE;AACvC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE;AACrC,EAAE,MAAM,CAAC,IAAI,CAAC;AACd,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,KAAK,CAAC;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI;AACvC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE;AACzC;AACA,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC9B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;AACrF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;AACjC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC;AACxC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC;AAChC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACrF,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC;AACvB;AACA,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AAChE,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG;AACvE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG;AACpE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC;AACnB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI;AAC/C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC;AACpD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5C;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AACzB,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI;AAC1D,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxB,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACrB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI;AACvB,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AAC1B,EAAE,CAAC;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACrC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG;AACxE,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,GAAG;AACrE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;AAClB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,IAAI;AAC/C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC;AACxD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5C;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC7C,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACzB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxB,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACrB,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;AAC1B,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC9C,EAAE,CAAC;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACrC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;AACjF,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI;AAC1E,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC;AAClF,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;AAC5E,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACpE,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC,YAAY,CAAC,CAAC,SAAS,CAAC;AACjE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAC/D,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnD,GAAG,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC;AACnD,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY;AAChE,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;AAC/B,GAAG,MAAM,CAAC;AACV,EAAE,CAAC;AACH,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;AAC1C,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,GAAG,IAAI,GAAG;AAC5C,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE;AAC1D;AACA,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE;AAC5D,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa;AAC9D,EAAE,EAAE,CAAC,CAAC;AACN,GAAG,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;AACpD,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE;AAClC,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS;AACxD,EAAE,CAAC,CAAC,CAAC;AACL,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,EAAE;AAClE,GAAG,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC;AACzE,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE;AAC7B;AACA,EAAE,CAAC;AACH;AACA,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI;AAC/D,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;AAC1B,GAAG,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC;AACtC,GAAG,EAAE,CAAC,SAAS,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG;AACjD,GAAG,CAAC,CAAC,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACvD,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,2BAA2B;AACxC,EAAE,EAAE;AACJ,EAAE,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,GAAG;AAC3C;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AACtC,GAAG,IAAI,CAAC,qBAAqB,GAAG;AAChC,GAAG,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,SAAS,CAAC,YAAY;AACvD,GAAG,MAAM,CAAC;AACV,EAAE,CAAC;AACH;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,GAAG;AAC1C,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACpC,IAAI,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC,CAAC;AACrF,IAAI,CAAC,QAAQ,CAAC,QAAQ,GAAG,IAAI,CAAC;AAC9B,EAAE,CAAC;AACH;AACA,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG;AAChG,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;AAC3C,EAAE,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC;AAClB,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACnC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;AACpE,GAAG,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,EAAE,CAAC;AACH,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;AACrD,EAAE,IAAI,CAAC,qBAAqB,GAAG;AAC/B,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,CAAC,qBAAqB,GAAG;AAC/B,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;AACjD,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM;AAClE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,KAAK;AACjE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI;AACjE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AACT,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,qBAAqB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1E,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,GAAG;AACrC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAChC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AACvB,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACxB,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK;AAClD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK;AACpC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClD,EAAE,MAAM,CAAC,IAAI,CAAC,OAAO,GAAG;AACxB,CAAC,CAAC,CAAC,EAAE;AACL,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK;AACzC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK;AACf,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC;AACrD;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC9B,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;AACrB;AACA,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AAC5C;AACA,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE;AACnC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM;AAC5C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK;AACpC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC5D,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACnB,EAAE;;AC5yBF,GAAG;AACH,CAAC,CAAC,CAAC,yBAAyB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,QAAQ;AACxG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;AACxG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE;AACxG,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,yBAAyB,CAAC;AACrD,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,yBAAyB,GAAG;AAC1D,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;AAC7C,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC;AACtE,CAAC,CAAC,KAAK,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,GAAG;AACpD,CAAC,CAAC,SAAS,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,CAAC;AAC1D,CAAC,CAAC,YAAY,UAAU,CAAC,CAAC,UAAU,CAAC;AACrC,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC;AACtB,CAAC,CAAC,eAAe,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,OAAO;AAC9C,CAAC,CAAC,YAAY,CAAC;AACf,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;AAC7C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,wBAAwB;AACnG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB;AACtC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM;AAC9C,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC;AACrD,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE;AACnE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK;AAC5D,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AACtF,CAAC,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG;AAC5E,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC;AAChC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,CAAC,QAAQ,CAAC,6BAA6B,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACpF,CAAC,GAAG,CAAC,YAAY,CAAC;AAClB,EAAE,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE;AAChC;AACA,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE;AACpG;AACA,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC;AAClD;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;AACzD,EAAE,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK;AAC5D,EAAE,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG;AACvD,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,QAAQ;AACtD,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,GAAG;AAC7C;AACA,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC;AAC1C,EAAE,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,YAAY,EAAE,OAAO,CAAC;AACvD;AACA,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,YAAY,CAAC,CAAC,EAAE;AAC3E,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,eAAe;AACpD,CAAC,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC;AAC9C,CAAC,aAAa,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACvD,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC;AAC3D;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AACpC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,EAAE;AAC5C;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC/C;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC9E,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,aAAa,CAAC,OAAO;AACzB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;AACrC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACzB,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClC,GAAG,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC;AAC7B,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;AACrE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE;AACzD,CAAC,IAAI,EAAE,UAAU;AACjB,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC5C;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;AAChC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,EAAE;AACjD,EAAE;AACF;AACA,EAAE,CAAC,cAAc,CAAC,EAAE;AACpB;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,EAAE;AAC/E,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;AAC3E;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;AACvB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AAC3B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK;AAChC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO;AAC9C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACtC,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG;AAC1B,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK;AACrC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC3E,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACzB,EAAE,IAAI,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAC,EAAE;AACxD,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,EAAE;AACjC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3E,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AAC/C,EAAE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,EAAE;AAC7C,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AAC/B;AACA,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5B,EAAE,IAAI,CAAC,UAAU,CAAC,KAAK,GAAG;AAC1B,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,EAAE,CAAC,MAAM;AACX,EAAE,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAClF,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;AAChC,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI;AACzE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACvE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC;AACtB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI;AACzC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;AAChF,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,yBAAyB,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACzF,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,EAAE;AAC5B,EAAE;;AC9JF,GAAG;AACH,CAAC,CAAC,CAAC,wBAAwB,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,CAAC,QAAQ;AACvG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;AACvC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,CAAC,EAAE;AACxG,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,wBAAwB,CAAC;AACpD,CAAC,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC;AACzD,CAAC,CAAC,SAAS,aAAa,CAAC,CAAC,CAAC,OAAO,EAAE;AACpC,CAAC,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC;AACrB,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AACrD,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AACrD,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AACrD,CAAC,CAAC,SAAS,EAAE;AACb,CAAC,CAAC,SAAS,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAC7C,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE;AAC7C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,mBAAmB,CAAC,wBAAwB;AACnG,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB;AACtC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,MAAM;AAChD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM;AAChE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC;AACpD,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE;AACnE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AAC3F,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,CAAC,QAAQ,CAAC,4BAA4B,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAClF,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC5D;AACA,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,CAAC;AAClD;AACA,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AAC/C,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC;AACf,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAC3C,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACnD,EAAE,eAAe,CAAC,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC;AACnC,EAAE,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACnC,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC;AAC5D,EAAE,CAAC,kBAAkB,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AAC1E,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC;AACvC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC;AAC1B,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE;AAC7B,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACpB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACzC;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC3B,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,EAAE;AACzB,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC;AACxB,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvB,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE;AAC1D,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;AAC9C;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE;AAChC,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,EAAE;AAChD,CAAC,EAAE,CAAC,oBAAoB,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG;AAClG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,gBAAgB,CAAC,OAAO,CAAC,UAAU,CAAC;AACvF,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACzB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE;AACnC,CAAC,CAAC;AACF,EAAE;AACF;AACA,EAAE,CAAC,cAAc,CAAC,EAAE;AACpB;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,EAAE;AAC9E;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK;AAC1B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI;AACvB,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG;AACtB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrE,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM;AACjB,CAAC,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,MAAM,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC3E;AACA,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AAC1B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK;AAChC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACtE,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE;AAC1B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK;AAC/B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;AACxD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC/E,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG;AACX,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,OAAO,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC,EAAE;AACxD,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,CAAC;AAC/D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO;AACjD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACpB,EAAE,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,EAAE;AAC/B,EAAE,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,EAAE;AAClC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,EAAE;AAC/D,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAQ;AAC3E,CAAC,EAAE,CAAC,EAAE,CAAC,oBAAoB,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;AACzE,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,GAAG;AACxE,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC;AACnC;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;AACxB,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,EAAE;AAClC;AACA,CAAC,IAAI,CAAC,KAAK,GAAG;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACxE,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,GAAG;AACxC,EAAE,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;AACpB,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,kBAAkB,GAAG;AACnD,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,UAAU,CAAC,EAAE;AACjD;AACA,CAAC,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI;AACtD,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK;AACvC;AACA,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK;AACrC,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AACzB,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,OAAO,GAAG,CAAC,eAAe,CAAC,QAAQ,EAAE,CAAC,EAAE;AACnF,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACrB,EAAE,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI;AAC5C,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,GAAG,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,EAAE;AAC7D,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,EAAE,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG;AAC7D,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,OAAO;AAChD,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,EAAE;AACxC,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACnB,EAAE,IAAI,CAAC,UAAU,GAAG;AACpB,EAAE,IAAI,CAAC,KAAK,GAAG;AACf,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI;AACrE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC;AACjC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,GAAG,CAAC,OAAO,CAAC,OAAO;AACrD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC5E,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC5D,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,GAAG;AAC9B,CAAC,CAAC,CAAC,EAAE;AACL,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI;AACxE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI;AACzE,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,SAAS,CAAC;AACpD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,UAAU,CAAC,aAAa,CAAC,OAAO;AACnD,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,MAAM;AAC/C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACrF,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,UAAU,CAAC,EAAE;AACjD,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI;AAC1B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO;AACxD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAChF,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB,EAAE,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AAC7C,GAAG,MAAM,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;AAC/D,EAAE,CAAC,CAAC,EAAE;AACN;AACA,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,EAAE;AAC7B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC;AAC/B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;AACjC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,KAAK;AACrC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,MAAM;AAC7C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,sBAAsB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAC5F,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;AACrC,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC;AACb,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI;AACtB,CAAC,CAAC,CAAC,EAAE;AACL,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI;AACf,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,IAAI;AACxC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAChE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;AAClB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI;AAC9B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,wBAAwB,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG;AACpB,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACnB,EAAE,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;AAC3F,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,GAAG,GAAG,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC/D,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAG;AAC7B,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,SAAS,CAAC,EAAE;AAC/C,EAAE;;ACzPF,GAAG;AACH,CAAC,CAAC,CAAC,iBAAiB,CAAC,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK;AAC/E,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,EAAE,IAAI;AAClF,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,UAAU,EAAE;AAC5C,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;AAC7F,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM;AACzC,CAAC,CAAC,KAAK,GAAG,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,GAAG;AACrD,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE;AACjD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO;AACtD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM;AACxB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW;AAClC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB;AACvC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc;AACrC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC;AACnF,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC;AACxE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC;AAC5F,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;AAC5E,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC;AACtG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,kBAAkB,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACjG,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,GAAG,CAAC,WAAW,CAAC;AAC7B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC,GAAG,CAAC,WAAW,CAAC;AACjB;AACA,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACrB,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC;AACf,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,EAAE;AAC1D,EAAE,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,EAAE;AAC7D,EAAE,SAAS,CAAC,CAAC,IAAI,CAAC;AAClB,EAAE,cAAc,CAAC,CAAC,KAAK,CAAC;AACxB,EAAE,kBAAkB,CAAC,CAAC,EAAE;AACxB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACb;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACpD;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC9C,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AACnD,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AAC3F,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAC/C;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE;AAC5B,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC;AAC7C,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,MAAM,CAAC,kBAAkB,CAAC;AACrD,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,WAAW,GAAG;AAC1D,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AACzB,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACxC,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;AAC9B,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACrB,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;AACvC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC;AACzC,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC/D;AACA,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC9C,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,EAAE;AACrD,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE;AACtD,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW;AAC9C,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AAC7C,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAC,EAAE;AACpD,EAAE,MAAM,CAAC,CAAC,KAAK,CAAC;AAChB,EAAE,IAAI,CAAC,CAAC,CAAC,KAAK,EAAE;AAChB,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ;AACzB,CAAC,CAAC,CAAC,EAAE;AACL;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;AAChC,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACxC,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClC,EAAE,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC;AACvB,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AAC1B,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACpD,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AACrB,GAAG,SAAS,CAAC,CAAC,WAAW,CAAC;AAC1B,GAAG,QAAQ,CAAC,CAAC,WAAW,CAAC;AACzB,GAAG,SAAS,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AAC5C,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACjC,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,CAAC,QAAQ,GAAG;AACjB,CAAC,IAAI,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE;AACxD,CAAC,IAAI,EAAE,IAAI;AACX,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5C,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE;AACjF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AACnD,EAAE,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE;AACxC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,EAAE;AAChF,EAAE,IAAI,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE;AAC5C,EAAE,IAAI,EAAE,OAAO;AACf,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,UAAU,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;AAC1E,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;AACT,IAAI,KAAK,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AAC9C,GAAG,CAAC,CAAC,CAAC;AACN,GAAG,CAAC,MAAM,CAAC;AACX,IAAI,IAAI,EAAE,SAAS,CAAC;AACpB,IAAI,IAAI,EAAE,IAAI,CAAC;AACf,IAAI,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC;AAC/B,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACjB,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;AACpD,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AACjE,GAAG,EAAE;AACL,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,EAAE,OAAO;AACf,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,CAAC;AACxC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,EAAE;AACrD,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,QAAQ,GAAG;AACjB,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACxD,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,WAAW,CAAC,EAAE;AACjE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE;AACtE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,cAAc,CAAC,EAAE;AACpE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE;AAClE;AACA,EAAE,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE;AACvB;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,SAAS;AACpC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM;AACV,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;AACpB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;AACZ,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACjE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE;AACjD,EAAE,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,SAAS,CAAC;AACnF,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,gBAAgB,CAAC;AACvD,EAAE;AACF;AACA,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;AACtD;AACA,EAAE,CAAC,MAAM,CAAC,EAAE;AACZ;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM;AAChB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC;AACzE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK;AACrC,CAAC,EAAE;AACH;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AACrC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;AACtB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC;AACzB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK;AACrC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC/D,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACnC,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;AAC1B,EAAE,IAAI,CAAC,QAAQ,GAAG;AAClB,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;AAC1C,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;AACpB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACtD,CAAC,IAAI,CAAC,YAAY,CAAC,KAAK,GAAG;AAC3B,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC;AACnB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrD,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,GAAG;AAC1B,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnE,CAAC,IAAI,CAAC,KAAK,GAAG;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,UAAU;AAClE,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,SAAS;AACb,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC;AACZ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC3B,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,YAAY,CAAC,CAAC,EAAE;AAClE,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE;AAC9D,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE;AACrC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,EAAE;AAC/D,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC3B,GAAG,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE;AAC/D,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE;AACpB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;AACvB,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACjB,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;AACnD,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;AACnC,GAAG,EAAE;AACL,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;AAC3B;AACA,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AAC/B,IAAI,IAAI,CAAC,WAAW,GAAG;AACvB,IAAI,IAAI,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACtD,KAAK,IAAI,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE;AACrE,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACxC,KAAK,IAAI,EAAE,SAAS,CAAC,MAAM,CAAC;AAC5B,MAAM,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;AAC7B,OAAO,IAAI,CAAC,CAAC,CAAC,UAAU,EAAE;AAC1B,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;AAC7D,MAAM,CAAC,CAAC,GAAG,OAAO;AAClB,KAAK,EAAE;AACP,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1C,KAAK,IAAI,CAAC,UAAU,GAAG;AACvB,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACrB,IAAI,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACjC,GAAG,CAAC;AACJ,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;AACV,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC;AAC/B,IAAI,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACjC,IAAI,IAAI,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;AACvB,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AAC/C,IAAI,CAAC,CAAC,EAAE;AACR,IAAI,IAAI,EAAE,SAAS;AACnB,KAAK,CAAC,KAAK,EAAE;AACb,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE;AACpC,GAAG,CAAC;AACJ,GAAG,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,EAAE;AAC5D,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE;AACrC,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;AAC7D,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM;AACnF,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACnE,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,QAAQ,GAAG;AAC7B,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC;AAC1B,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,UAAU,GAAG;AAC5B;AACA,CAAC,EAAE,CAAC,CAAC;AACL,EAAE,IAAI,CAAC,EAAE;AACT,EAAE,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;AACnE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI;AACnD,CAAC,CAAC,CAAC,CAAC;AACJ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtC,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE;AAC7C,GAAG,GAAG,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC9C,IAAI,EAAE,CAAC,CAAC;AACR,KAAK,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;AAC9B,KAAK,GAAG,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE;AAC/B,KAAK,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK;AAC3B,IAAI,CAAC,CAAC,CAAC;AACP,KAAK,QAAQ,CAAC,MAAM,GAAG;AACvB,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AACZ,KAAK,QAAQ,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE;AAC7C,IAAI,CAAC;AACL,GAAG,CAAC,CAAC,EAAE;AACP,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;AACjC,EAAE,EAAE;AACJ,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,EAAE;AAC/B,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,QAAQ,CAAC,MAAM,GAAG;AACpB,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAG;AAC3B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM;AAC9B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AACrB,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG;AACvB,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC3B,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACrB,EAAE,MAAM,CAAC;AACT,CAAC,CAAC;AACF;AACA,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE;AACrD,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,EAAE;AACxD,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1C,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;AACnD,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK;AAC1B,EAAE,CAAC,CAAC,eAAe,GAAG;AACtB,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;AACpB,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC;AACd,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACrB,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACzD,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;AACjD,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI;AAC1C,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI;AAC1C,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;AACpB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACxE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AACjB;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACnC,EAAE,MAAM,CAAC,IAAI,CAAC;AACd,CAAC,CAAC;AACF;AACA,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAC7C,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AAC9B,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAChC,GAAG,MAAM,CAAC,IAAI,CAAC;AACf,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChD,GAAG,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACxD,GAAG,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAC9D,IAAI,MAAM,CAAC,IAAI,CAAC;AAChB,GAAG,CAAC;AACJ,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,KAAK,CAAC;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK;AACvC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;AAC1B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClE,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC;AACvD;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACd,CAAC,CAAC;AACF;AACA,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE;AACvB,CAAC,IAAI,CAAC,QAAQ,GAAG;AACjB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;AACpC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC7D,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE;AACvB,CAAC,MAAM,CAAC,KAAK,CAAC;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC;AAC3B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK;AAC1C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;AAC9D,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAClE,CAAC,CAAC,CAAC,CAAC;AACJ,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,GAAG;AACtB,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC;AACnC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK;AAC1C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;AAC/D,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,GAAG;AACtB,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM;AACpC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK;AACrC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACrE,CAAC,GAAG,CAAC,UAAU,CAAC;AAChB,EAAE,aAAa,CAAC,CAAC,CAAC,KAAK,CAAC;AACxB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC;AACpC;AACA,CAAC,CAAC,CAAC,cAAc,GAAG;AACpB,CAAC,CAAC,CAAC,eAAe,GAAG;AACrB;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAChD,EAAE,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,EAAE;AAChE,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;AACzB,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,gBAAgB,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK;AAC5E,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;AACtC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;AAC3E,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACpB,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChD,GAAG,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;AACxB,EAAE,CAAC;AACH,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK;AAC5C,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAChG,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM;AAChF,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC;AAC9B,EAAE,EAAE,CAAC,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM;AACxD,EAAE,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;AACvB,CAAC,CAAC;AACF;AACA,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,OAAO,EAAE,CAAC,aAAa,CAAC,EAAE;AAC9E,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AACxB,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;AACzB,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,KAAK,CAAC;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM;AAC3B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK;AACrC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC5D,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,EAAE;AAC/D,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM;AACrB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK;AACrC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACjB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,YAAY,CAAC;AACpC;AACA,CAAC,CAAC,CAAC,cAAc,GAAG;AACpB,CAAC,CAAC,CAAC,eAAe,GAAG;AACrB,CAAC,IAAI,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,EAAE;AAC/D;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAChD,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF;AACA,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE;AACrC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAClD,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AACd,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACd,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE;AACxB,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,KAAK,CAAC;AACd,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC,EAAE,CAAC,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE;AAC5E,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAC3B,EAAE,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,EAAE;AAC5C,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC1B,EAAE,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,EAAE;AAC3C,CAAC,CAAC;AACF,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;;ACzgBF,GAAG;AACH,CAAC,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AAC/G,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK;AACrE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC;AACpH,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC;AACnH,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;AAC5F,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,MAAM,CAAC,GAAG;AAChG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG;AACrF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM;AACxB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK;AACtE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK;AAC5C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC1D,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG;AACvB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,EAAE;AAChD;AACA,CAAC,EAAE,CAAC,UAAU;AACd,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC;AAC1C,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE;AACjB,EAAE,WAAW,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC;AAClC,EAAE,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK;AACrB,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,GAAG;AACzC,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;AAC5B,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE;AAC9B;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAC5B,EAAE,MAAM,CAAC,CAAC,CAAC,aAAa,EAAE;AAC1B,EAAE,KAAK,CAAC,CAAC,CAAC,YAAY,CAAC;AACvB,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACrE;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,EAAE,KAAK;AACZ,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AACzC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE;AACjC,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC;AAC3C,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,EAAE;AACnC,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC;AACnC,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;AACxC,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACpD;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;AAChC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,QAAQ,CAAC;AAC/B,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACjF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACb,EAAE,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,GAAG;AACtD,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AAC3B,GAAG,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,eAAe,GAAG;AACpD,EAAE,CAAC;AACH,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,EAAE;AAC5E,EAAE,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,QAAQ,CAAC,EAAE;AACzC,EAAE,QAAQ,CAAC,qBAAqB,GAAG;AACnC,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC;AACtC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC;AACtF,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK;AAClC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1D,CAAC,EAAE,CAAC,KAAK;AACT,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,GAAG;AAC3B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC;AACzC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC;AAC5B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK;AAClC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,kBAAkB,GAAG;AACzD,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;AACzB,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,eAAe,CAAC,EAAE;AAC7C,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC;AACvB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,KAAK,CAAC,KAAK;AAC9C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACrD,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;AACnB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;AAC/B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO;AACtD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACvD,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC;AACrB,EAAE;;AC/HF,GAAG;AACH,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK;AACvF,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC;AAC7E,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3E,CAAC,CAAC;AACF,CAAC,CAAC,KAAK,CAAC,OAAO;AACf,CAAC,CAAC,KAAK,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC;AACvC,CAAC,CAAC,KAAK,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC;AACvD,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,iBAAiB,EAAE;AACtC,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AAC/B,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,EAAE;AAClB,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE;AACX,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,WAAW,EAAE,OAAO,CAAC,EAAE;AAClD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK;AACT,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe;AACjC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,WAAW;AACf,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,aAAa,CAAC,OAAO;AACjD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE;AAC1H,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,YAAY,CAAC,MAAM,CAAC,MAAM,EAAE;AACzH,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;AACrF,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK;AACtD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK;AACrD,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI;AAC5E,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC;AACzG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC;AAChF,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;AAC1B,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,EAAE;AAC/C;AACA,CAAC,EAAE,CAAC,aAAa,CAAC,cAAc;AAChC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;AACrB,EAAE,YAAY,CAAC,CAAC,KAAK,CAAC;AACtB,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC;AACjB,EAAE,GAAG,CAAC,CAAC,QAAQ,CAAC;AAChB,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC;AACV,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC;AACjB,EAAE,WAAW,CAAC,CAAC,IAAI;AACnB,CAAC,EAAE,CAAC,MAAM,CAAC,EAAE;AACb;AACA,CAAC,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa;AAC9B,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE;AAClC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACnB;AACA,CAAC,EAAE,CAAC,MAAM,CAAC,WAAW;AACtB,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/D,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC;AAChB,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACP;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC;AACtD,GAAG,CAAC;AACJ,IAAI,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG;AAChC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACjB,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC,EAAE;AACvD,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC;AACpB,GAAG,EAAE;AACL,GAAG,MAAM,CAAC,WAAW;AACrB,EAAE,CAAC,CAAC,EAAE;AACN,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC;AACrD,GAAG,CAAC;AACJ,IAAI,QAAQ,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG;AAChC,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;AACjB,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC,EAAE;AACtD,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC;AACf,GAAG,EAAE;AACL,GAAG,MAAM,CAAC,UAAU;AACpB,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,MAAM;AACV,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC;AAClB,EAAE,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE;AACvC,EAAE,CAAC,KAAK,CAAC,UAAU,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC;AAC9D,CAAC,CAAC,CAAC,EAAE;AACL,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,EAAE,CAAC,CAAC,EAAE;AACN,EAAE,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACnC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,EAAE,CAAC,CAAC,EAAE;AACN,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK;AACnB,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE;AAC9B,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,CAAC,KAAK;AACR,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AACxC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE;AACvC,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,cAAc;AAClB,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE;AACjE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;AACzC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE;AAC9C,CAAC,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK;AACjE,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,eAAe;AACvD,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE;AACxD;AACA,CAAC,IAAI,EAAE,OAAO;AACd,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC;AACxC,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,QAAQ,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;AACxE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE;AACpB,EAAE;AACF;AACA,EAAE,CAAC,KAAK,CAAC,EAAE;AACX;AACA,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,eAAe,CAAC,EAAE;AAClE;AACA,EAAE,CAAC,OAAO,CAAC,EAAE;AACb;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO;AACxC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI;AACxB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,IAAI,CAAC;AAC5B,CAAC,IAAI,CAAC,eAAe,GAAG;AACxB,EAAE;AACF,EAAE,CAAC,QAAQ,CAAC,aAAa;AACzB,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,eAAe,CAAC;AACnG;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO;AACxC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,KAAK;AAC/B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC;AAC1B,EAAE;AACF,EAAE,CAAC,QAAQ,CAAC,aAAa;AACzB,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,eAAe,CAAC;AACnG;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM;AAClC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK;AAC5C,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK;AAC5C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACnB,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE;AAC5F,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AAChB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;AAChB,CAAC,IAAI,CAAC,eAAe,GAAG;AACxB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK;AACxB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM;AAChD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AAC1D,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;AAC/B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM;AAC1B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI;AACnC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;AAC5E,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACzE,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACnB,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE;AACnD,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3B,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;AACvB,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9B,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,EAAE;AACxD,CAAC,CAAC;AACF,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC;AAClB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1B,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM;AAClC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI;AACxC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACzD,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AACrC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM;AAClD,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,MAAM;AACpD,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,QAAQ,GAAG;AACzB,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG,CAAC,MAAM;AACjC,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,MAAM;AAC1C,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,eAAe,GAAG;AACnC;AACA,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAChB,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9C,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE;AACrD,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpB,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACR,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACT,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAChB,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;AACpD,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;AAC5B,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;AACvB,EAAE,CAAC;AACH,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACjB,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE;AACrB,CAAC,CAAC;AACF,EAAE;AACF,GAAG;AACH,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK;AACjB,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK;AACpC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC;AACpB,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;AAChB,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACtB,EAAE,MAAM,CAAC,CAAC,IAAI,CAAC,UAAU,GAAG;AAC5B,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACtC,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AACpD,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACtC,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;AAC/B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AACrC,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC;AAC7B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK;AAC9B,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChE,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;AACf;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC1D,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,KAAK;AAC3B,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC;AACtD,GAAG,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7B,EAAE,CAAC;AACH,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AACrC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC;AACvC,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC5C,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC;AACtC,EAAE,CAAC;AACH;AACA,EAAE,EAAE,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM;AACxB,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;AAC9B,GAAG,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC3C,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC;AAC7C,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAClD,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC;AAC5C,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACjD,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,UAAU,CAAC;AAC3C,GAAG,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;AAC7C,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC;AACxC,GAAG,CAAC;AACJ,EAAE,CAAC;AACH;AACA,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAChB,GAAG,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9B,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AACzC,EAAE,CAAC;AACH;AACA,EAAE,MAAM,CAAC,KAAK,CAAC;AACf,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;AAC1B,CAAC,CAAC;AACF,CAAC,CAAC,CAAC,CAAC,OAAO;AACX,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK;AACzC,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC9D,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5B,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AACtB,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;AACtB,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AAClC,IAAI,MAAM,CAAC,KAAK,CAAC;AACjB,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC;AACxB,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE;AACnC,IAAI,MAAM,CAAC,KAAK,CAAC;AACjB,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC;AAC1B,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AACtC,IAAI,MAAM,CAAC,KAAK,CAAC;AACjB,GAAG,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC;AAC5B,IAAI,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE;AACvC,IAAI,MAAM,CAAC,KAAK,CAAC;AACjB,EAAE,CAAC;AACH,CAAC,CAAC;AACF,EAAE;AACF;AACA,GAAG;AACH,CAAC,CAAC,CAAC,CAAC,UAAU;AACd,CAAC,EAAE;AACH,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AACvE,CAAC,EAAE,CAAC,MAAM,CAAC,MAAM;AACjB,CAAC,EAAE,CAAC,EAAE,CAAC,iBAAiB,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,EAAE;AAC7E;AACA,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;AAC1B,EAAE,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;AACpD,CAAC,CAAC;AACF,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AACzB,EAAE,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,EAAE;AACnD,CAAC,CAAC;AACF;AACA,CAAC,MAAM,CAAC,IAAI,CAAC;AACb,EAAE;;AC1VF,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE","file":"oojs-ui-widgets.js","sourcesContent":["( function ( OO ) {\n\n'use strict';\n","/**\n * DraggableElement is a mixin class used to create elements that can be clicked\n * and dragged by a mouse to a new position within a group. This class must be used\n * in conjunction with OO.ui.mixin.DraggableGroupElement, which provides a container for\n * the draggable elements.\n *\n * @abstract\n * @class\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$handle] The part of the element which can be used for dragging, defaults to the whole element\n * @cfg {boolean} [draggable] The items are draggable. This can change with #toggleDraggable\n * but the draggable state should be called from the DraggableGroupElement, which updates\n * the whole group\n */\nOO.ui.mixin.DraggableElement = function OoUiMixinDraggableElement( config ) {\n\tconfig = config || {};\n\n\t// Properties\n\tthis.index = null;\n\tthis.$handle = config.$handle || this.$element;\n\tthis.wasHandleUsed = null;\n\n\t// Initialize and events\n\tthis.$element\n\t\t.addClass( 'oo-ui-draggableElement' )\n\t\t.on( {\n\t\t\tmousedown: this.onDragMouseDown.bind( this ),\n\t\t\tdragstart: this.onDragStart.bind( this ),\n\t\t\tdragover: this.onDragOver.bind( this ),\n\t\t\tdragend: this.onDragEnd.bind( this ),\n\t\t\tdrop: this.onDrop.bind( this )\n\t\t} );\n\tthis.$handle.addClass( 'oo-ui-draggableElement-handle' );\n\tthis.toggleDraggable( config.draggable === undefined ? true : !!config.draggable );\n};\n\nOO.initClass( OO.ui.mixin.DraggableElement );\n\n/* Events */\n\n/**\n * @event dragstart\n *\n * A dragstart event is emitted when the user clicks and begins dragging an item.\n * @param {OO.ui.mixin.DraggableElement} item The item the user has clicked and is dragging with the mouse.\n */\n\n/**\n * @event dragend\n * A dragend event is emitted when the user drags an item and releases the mouse,\n * thus terminating the drag operation.\n */\n\n/**\n * @event drop\n * A drop event is emitted when the user drags an item and then releases the mouse button\n * over a valid target.\n */\n\n/* Static Properties */\n\n/**\n * @inheritdoc OO.ui.mixin.ButtonElement\n */\nOO.ui.mixin.DraggableElement.static.cancelButtonMouseDownEvents = false;\n\n/* Methods */\n\n/**\n * Change the draggable state of this widget.\n * This allows users to temporarily halt the dragging operations.\n *\n * @param {boolean} isDraggable Widget supports draggable operations\n * @fires draggable\n */\nOO.ui.mixin.DraggableElement.prototype.toggleDraggable = function ( isDraggable ) {\n\tisDraggable = isDraggable !== undefined ? !!isDraggable : !this.draggable;\n\n\tif ( this.draggable !== isDraggable ) {\n\t\tthis.draggable = isDraggable;\n\n\t\tthis.$handle.toggleClass( 'oo-ui-draggableElement-undraggable', !this.draggable );\n\n\t\t// We make the entire element draggable, not just the handle, so that\n\t\t// the whole element appears to move. wasHandleUsed prevents drags from\n\t\t// starting outside the handle\n\t\tthis.$element.prop( 'draggable', this.draggable );\n\t}\n};\n\n/**\n * Check the draggable state of this widget\n *\n * @return {boolean} Widget supports draggable operations\n */\nOO.ui.mixin.DraggableElement.prototype.isDraggable = function () {\n\treturn this.draggable;\n};\n\n/**\n * Respond to mousedown event.\n *\n * @private\n * @param {jQuery.Event} e Drag event\n */\nOO.ui.mixin.DraggableElement.prototype.onDragMouseDown = function ( e ) {\n\tif ( !this.isDraggable() ) {\n\t\treturn;\n\t}\n\n\tthis.wasHandleUsed =\n\t\t// Optimization: if the handle is the whole element this is always true\n\t\tthis.$handle[ 0 ] === this.$element[ 0 ] ||\n\t\t// Check the mousedown occurred inside the handle\n\t\tOO.ui.contains( this.$handle[ 0 ], e.target, true );\n};\n\n/**\n * Respond to dragstart event.\n *\n * @private\n * @param {jQuery.Event} e Drag event\n * @return {boolean} False if the event is cancelled\n * @fires dragstart\n */\nOO.ui.mixin.DraggableElement.prototype.onDragStart = function ( e ) {\n\tvar element = this,\n\t\tdataTransfer = e.originalEvent.dataTransfer;\n\n\tif ( !this.wasHandleUsed || !this.isDraggable() ) {\n\t\treturn false;\n\t}\n\n\t// Define drop effect\n\tdataTransfer.dropEffect = 'none';\n\tdataTransfer.effectAllowed = 'move';\n\t// Support: Firefox\n\t// We must set up a dataTransfer data property or Firefox seems to\n\t// ignore the fact the element is draggable.\n\ttry {\n\t\tdataTransfer.setData( 'application-x/OOjs-UI-draggable', this.getIndex() );\n\t} catch ( err ) {\n\t\t// The above is only for Firefox. Move on if it fails.\n\t}\n\t// Briefly add a 'clone' class to style the browser's native drag image\n\tthis.$element.addClass( 'oo-ui-draggableElement-clone' );\n\t// Add placeholder class after the browser has rendered the clone\n\tsetTimeout( function () {\n\t\telement.$element\n\t\t\t.removeClass( 'oo-ui-draggableElement-clone' )\n\t\t\t.addClass( 'oo-ui-draggableElement-placeholder' );\n\t} );\n\t// Emit event\n\tthis.emit( 'dragstart', this );\n\treturn true;\n};\n\n/**\n * Respond to dragend event.\n *\n * @private\n * @fires dragend\n */\nOO.ui.mixin.DraggableElement.prototype.onDragEnd = function () {\n\tthis.$element.removeClass( 'oo-ui-draggableElement-placeholder' );\n\tthis.emit( 'dragend' );\n};\n\n/**\n * Handle drop event.\n *\n * @private\n * @param {jQuery.Event} e Drop event\n * @fires drop\n */\nOO.ui.mixin.DraggableElement.prototype.onDrop = function ( e ) {\n\te.preventDefault();\n\tthis.emit( 'drop', e );\n};\n\n/**\n * In order for drag/drop to work, the dragover event must\n * return false and stop propogation.\n *\n * @param {jQuery.Event} e Drag event\n * @private\n */\nOO.ui.mixin.DraggableElement.prototype.onDragOver = function ( e ) {\n\te.preventDefault();\n};\n\n/**\n * Set item index.\n * Store it in the DOM so we can access from the widget drag event\n *\n * @private\n * @param {number} index Item index\n */\nOO.ui.mixin.DraggableElement.prototype.setIndex = function ( index ) {\n\tif ( this.index !== index ) {\n\t\tthis.index = index;\n\t\tthis.$element.data( 'index', index );\n\t}\n};\n\n/**\n * Get item index\n *\n * @private\n * @return {number} Item index\n */\nOO.ui.mixin.DraggableElement.prototype.getIndex = function () {\n\treturn this.index;\n};\n","/**\n * DraggableGroupElement is a mixin class used to create a group element to\n * contain draggable elements, which are items that can be clicked and dragged by a mouse.\n * The class is used with OO.ui.mixin.DraggableElement.\n *\n * @abstract\n * @class\n * @mixins OO.ui.mixin.GroupElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string} [orientation] Item orientation: 'horizontal' or 'vertical'. The orientation\n * should match the layout of the items. Items displayed in a single row\n * or in several rows should use horizontal orientation. The vertical orientation should only be\n * used when the items are displayed in a single column. Defaults to 'vertical'\n * @cfg {boolean} [draggable] The items are draggable. This can change with #toggleDraggable\n */\nOO.ui.mixin.DraggableGroupElement = function OoUiMixinDraggableGroupElement( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.mixin.GroupElement.call( this, config );\n\n\t// Properties\n\tthis.orientation = config.orientation || 'vertical';\n\tthis.dragItem = null;\n\tthis.itemKeys = {};\n\tthis.dir = null;\n\tthis.itemsOrder = null;\n\tthis.draggable = config.draggable === undefined ? true : !!config.draggable;\n\n\t// Events\n\tthis.aggregate( {\n\t\tdragstart: 'itemDragStart',\n\t\tdragend: 'itemDragEnd',\n\t\tdrop: 'itemDrop'\n\t} );\n\tthis.connect( this, {\n\t\titemDragStart: 'onItemDragStart',\n\t\titemDrop: 'onItemDropOrDragEnd',\n\t\titemDragEnd: 'onItemDropOrDragEnd'\n\t} );\n\n\t// Initialize\n\tif ( Array.isArray( config.items ) ) {\n\t\tthis.addItems( config.items );\n\t}\n\tthis.$element\n\t\t.addClass( 'oo-ui-draggableGroupElement' )\n\t\t.append( this.$status )\n\t\t.toggleClass( 'oo-ui-draggableGroupElement-horizontal', this.orientation === 'horizontal' );\n};\n\n/* Setup */\nOO.mixinClass( OO.ui.mixin.DraggableGroupElement, OO.ui.mixin.GroupElement );\n\n/* Events */\n\n/**\n * An item has been dragged to a new position, but not yet dropped.\n *\n * @event drag\n * @param {OO.ui.mixin.DraggableElement} item Dragged item\n * @param {number} [newIndex] New index for the item\n */\n\n/**\n * An item has been dropped at a new position.\n *\n * @event reorder\n * @param {OO.ui.mixin.DraggableElement} item Reordered item\n * @param {number} [newIndex] New index for the item\n */\n\n/**\n * Draggable state of this widget has changed.\n *\n * @event draggable\n * @param {boolean} [draggable] Widget is draggable\n */\n\n/* Methods */\n\n/**\n * Change the draggable state of this widget.\n * This allows users to temporarily halt the dragging operations.\n *\n * @param {boolean} isDraggable Widget supports draggable operations\n * @fires draggable\n */\nOO.ui.mixin.DraggableGroupElement.prototype.toggleDraggable = function ( isDraggable ) {\n\tisDraggable = isDraggable !== undefined ? !!isDraggable : !this.draggable;\n\n\tif ( this.draggable !== isDraggable ) {\n\t\tthis.draggable = isDraggable;\n\n\t\t// Tell the items their draggable state changed\n\t\tthis.getItems().forEach( function ( item ) {\n\t\t\titem.toggleDraggable( this.draggable );\n\t\t}.bind( this ) );\n\n\t\t// Emit event\n\t\tthis.emit( 'draggable', this.draggable );\n\t}\n};\n\n/**\n * Check the draggable state of this widget\n *\n * @return {boolean} Widget supports draggable operations\n */\nOO.ui.mixin.DraggableGroupElement.prototype.isDraggable = function () {\n\treturn this.draggable;\n};\n\n/**\n * Respond to item drag start event\n *\n * @private\n * @param {OO.ui.mixin.DraggableElement} item Dragged item\n */\nOO.ui.mixin.DraggableGroupElement.prototype.onItemDragStart = function ( item ) {\n\tif ( !this.isDraggable() ) {\n\t\treturn;\n\t}\n\t// Make a shallow copy of this.items so we can re-order it during previews\n\t// without affecting the original array.\n\tthis.itemsOrder = this.items.slice();\n\tthis.updateIndexes();\n\tif ( this.orientation === 'horizontal' ) {\n\t\t// Calculate and cache directionality on drag start - it's a little\n\t\t// expensive and it shouldn't change while dragging.\n\t\tthis.dir = this.$element.css( 'direction' );\n\t}\n\tthis.setDragItem( item );\n};\n\n/**\n * Update the index properties of the items\n */\nOO.ui.mixin.DraggableGroupElement.prototype.updateIndexes = function () {\n\tvar i, len;\n\n\t// Map the index of each object\n\tfor ( i = 0, len = this.itemsOrder.length; i < len; i++ ) {\n\t\tthis.itemsOrder[ i ].setIndex( i );\n\t}\n};\n\n/**\n * Handle drop or dragend event and switch the order of the items accordingly\n *\n * @private\n * @param {OO.ui.mixin.DraggableElement} item Dropped item\n */\nOO.ui.mixin.DraggableGroupElement.prototype.onItemDropOrDragEnd = function () {\n\tvar targetIndex, originalIndex,\n\t\titem = this.getDragItem();\n\n\t// TODO: Figure out a way to configure a list of legally droppable\n\t// elements even if they are not yet in the list\n\tif ( item ) {\n\t\toriginalIndex = this.items.indexOf( item );\n\t\t// If the item has moved forward, add one to the index to account for the left shift\n\t\ttargetIndex = item.getIndex() + ( item.getIndex() > originalIndex ? 1 : 0 );\n\t\tif ( targetIndex !== originalIndex ) {\n\t\t\tthis.reorder( this.getDragItem(), targetIndex );\n\t\t\tthis.emit( 'reorder', this.getDragItem(), targetIndex );\n\t\t}\n\t\tthis.updateIndexes();\n\t}\n\tthis.unsetDragItem();\n\t// Return false to prevent propogation\n\treturn false;\n};\n\n/**\n * Respond to dragover event\n *\n * @private\n * @param {jQuery.Event} e Dragover event\n * @fires reorder\n */\nOO.ui.mixin.DraggableGroupElement.prototype.onDragOver = function ( e ) {\n\tvar overIndex, targetIndex,\n\t\titem = this.getDragItem(),\n\t\tdragItemIndex = item.getIndex();\n\n\t// Get the OptionWidget item we are dragging over\n\toverIndex = $( e.target ).closest( '.oo-ui-draggableElement' ).data( 'index' );\n\n\tif ( overIndex !== undefined && overIndex !== dragItemIndex ) {\n\t\ttargetIndex = overIndex + ( overIndex > dragItemIndex ? 1 : 0 );\n\n\t\tif ( targetIndex > 0 ) {\n\t\t\tthis.$group.children().eq( targetIndex - 1 ).after( item.$element );\n\t\t} else {\n\t\t\tthis.$group.prepend( item.$element );\n\t\t}\n\t\t// Move item in itemsOrder array\n\t\tthis.itemsOrder.splice( overIndex, 0,\n\t\t\tthis.itemsOrder.splice( dragItemIndex, 1 )[ 0 ]\n\t\t);\n\t\tthis.updateIndexes();\n\t\tthis.emit( 'drag', item, targetIndex );\n\t}\n\t// Prevent default\n\te.preventDefault();\n};\n\n/**\n * Reorder the items in the group\n *\n * @param {OO.ui.mixin.DraggableElement} item Reordered item\n * @param {number} newIndex New index\n */\nOO.ui.mixin.DraggableGroupElement.prototype.reorder = function ( item, newIndex ) {\n\tthis.addItems( [ item ], newIndex );\n};\n\n/**\n * Set a dragged item\n *\n * @param {OO.ui.mixin.DraggableElement} item Dragged item\n */\nOO.ui.mixin.DraggableGroupElement.prototype.setDragItem = function ( item ) {\n\tif ( this.dragItem !== item ) {\n\t\tthis.dragItem = item;\n\t\tthis.$element.on( 'dragover', this.onDragOver.bind( this ) );\n\t\tthis.$element.addClass( 'oo-ui-draggableGroupElement-dragging' );\n\t}\n};\n\n/**\n * Unset the current dragged item\n */\nOO.ui.mixin.DraggableGroupElement.prototype.unsetDragItem = function () {\n\tif ( this.dragItem ) {\n\t\tthis.dragItem = null;\n\t\tthis.$element.off( 'dragover' );\n\t\tthis.$element.removeClass( 'oo-ui-draggableGroupElement-dragging' );\n\t}\n};\n\n/**\n * Get the item that is currently being dragged.\n *\n * @return {OO.ui.mixin.DraggableElement|null} The currently dragged item, or `null` if no item is being dragged\n */\nOO.ui.mixin.DraggableGroupElement.prototype.getDragItem = function () {\n\treturn this.dragItem;\n};\n","/**\n * RequestManager is a mixin that manages the lifecycle of a promise-backed request for a widget, such as\n * the {@link OO.ui.mixin.LookupElement}.\n *\n * @class\n * @abstract\n *\n * @constructor\n */\nOO.ui.mixin.RequestManager = function OoUiMixinRequestManager() {\n\tthis.requestCache = {};\n\tthis.requestQuery = null;\n\tthis.requestRequest = null;\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.mixin.RequestManager );\n\n/**\n * Get request results for the current query.\n *\n * @return {jQuery.Promise} Promise object which will be passed response data as the first argument of\n * the done event. If the request was aborted to make way for a subsequent request, this promise\n * may not be rejected, depending on what jQuery feels like doing.\n */\nOO.ui.mixin.RequestManager.prototype.getRequestData = function () {\n\tvar widget = this,\n\t\tvalue = this.getRequestQuery(),\n\t\tdeferred = $.Deferred(),\n\t\tourRequest;\n\n\tthis.abortRequest();\n\tif ( Object.prototype.hasOwnProperty.call( this.requestCache, value ) ) {\n\t\tdeferred.resolve( this.requestCache[ value ] );\n\t} else {\n\t\tif ( this.pushPending ) {\n\t\t\tthis.pushPending();\n\t\t}\n\t\tthis.requestQuery = value;\n\t\tourRequest = this.requestRequest = this.getRequest();\n\t\tourRequest\n\t\t\t.always( function () {\n\t\t\t\t// We need to pop pending even if this is an old request, otherwise\n\t\t\t\t// the widget will remain pending forever.\n\t\t\t\t// TODO: this assumes that an aborted request will fail or succeed soon after\n\t\t\t\t// being aborted, or at least eventually. It would be nice if we could popPending()\n\t\t\t\t// at abort time, but only if we knew that we hadn't already called popPending()\n\t\t\t\t// for that request.\n\t\t\t\tif ( widget.popPending ) {\n\t\t\t\t\twidget.popPending();\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.done( function ( response ) {\n\t\t\t\t// If this is an old request (and aborting it somehow caused it to still succeed),\n\t\t\t\t// ignore its success completely\n\t\t\t\tif ( ourRequest === widget.requestRequest ) {\n\t\t\t\t\twidget.requestQuery = null;\n\t\t\t\t\twidget.requestRequest = null;\n\t\t\t\t\twidget.requestCache[ value ] = widget.getRequestCacheDataFromResponse( response );\n\t\t\t\t\tdeferred.resolve( widget.requestCache[ value ] );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.fail( function () {\n\t\t\t\t// If this is an old request (or a request failing because it's being aborted),\n\t\t\t\t// ignore its failure completely\n\t\t\t\tif ( ourRequest === widget.requestRequest ) {\n\t\t\t\t\twidget.requestQuery = null;\n\t\t\t\t\twidget.requestRequest = null;\n\t\t\t\t\tdeferred.reject();\n\t\t\t\t}\n\t\t\t} );\n\t}\n\treturn deferred.promise();\n};\n\n/**\n * Abort the currently pending request, if any.\n *\n * @private\n */\nOO.ui.mixin.RequestManager.prototype.abortRequest = function () {\n\tvar oldRequest = this.requestRequest;\n\tif ( oldRequest ) {\n\t\t// First unset this.requestRequest to the fail handler will notice\n\t\t// that the request is no longer current\n\t\tthis.requestRequest = null;\n\t\tthis.requestQuery = null;\n\t\toldRequest.abort();\n\t}\n};\n\n/**\n * Get the query to be made.\n *\n * @protected\n * @method\n * @abstract\n * @return {string} query to be used\n */\nOO.ui.mixin.RequestManager.prototype.getRequestQuery = null;\n\n/**\n * Get a new request object of the current query value.\n *\n * @protected\n * @method\n * @abstract\n * @return {jQuery.Promise} jQuery AJAX object, or promise object with an .abort() method\n */\nOO.ui.mixin.RequestManager.prototype.getRequest = null;\n\n/**\n * Pre-process data returned by the request from #getRequest.\n *\n * The return value of this function will be cached, and any further queries for the given value\n * will use the cache rather than doing API requests.\n *\n * @protected\n * @method\n * @abstract\n * @param {Mixed} response Response from server\n * @return {Mixed} Cached result data\n */\nOO.ui.mixin.RequestManager.prototype.getRequestCacheDataFromResponse = null;\n","/**\n * LookupElement is a mixin that creates a {@link OO.ui.MenuSelectWidget menu} of suggested values for\n * a {@link OO.ui.TextInputWidget text input widget}. Suggested values are based on the characters the user types\n * into the text input field and, in general, the menu is only displayed when the user types. If a suggested value is chosen\n * from the lookup menu, that value becomes the value of the input field.\n *\n * Note that a new menu of suggested items is displayed when a value is chosen from the lookup menu. If this is\n * not the desired behavior, disable lookup menus with the #setLookupsDisabled method, then set the value, then\n * re-enable lookups.\n *\n * See the [OOjs UI demos][1] for an example.\n *\n * [1]: https://tools.wmflabs.org/oojs-ui/oojs-ui/demos/index.html#widgets-apex-vector-ltr\n *\n * @class\n * @abstract\n * @mixins OO.ui.mixin.RequestManager\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {jQuery} [$overlay] Overlay for the lookup menu; defaults to relative positioning.\n * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.\n * @cfg {jQuery} [$container=this.$element] The container element. The lookup menu is rendered beneath the specified element.\n * @cfg {boolean} [allowSuggestionsWhenEmpty=false] Request and display a lookup menu when the text input is empty.\n * By default, the lookup menu is not generated and displayed until the user begins to type.\n * @cfg {boolean} [highlightFirst=true] Whether the first lookup result should be highlighted (so, that the user can\n * take it over into the input with simply pressing return) automatically or not.\n */\nOO.ui.mixin.LookupElement = function OoUiMixinLookupElement( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( { highlightFirst: true }, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.RequestManager.call( this, config );\n\n\t// Properties\n\tthis.$overlay = config.$overlay || this.$element;\n\tthis.lookupMenu = new OO.ui.MenuSelectWidget( {\n\t\twidget: this,\n\t\tinput: this,\n\t\t$floatableContainer: config.$container || this.$element\n\t} );\n\n\tthis.allowSuggestionsWhenEmpty = config.allowSuggestionsWhenEmpty || false;\n\n\tthis.lookupsDisabled = false;\n\tthis.lookupInputFocused = false;\n\tthis.lookupHighlightFirstItem = config.highlightFirst;\n\n\t// Events\n\tthis.$input.on( {\n\t\tfocus: this.onLookupInputFocus.bind( this ),\n\t\tblur: this.onLookupInputBlur.bind( this ),\n\t\tmousedown: this.onLookupInputMouseDown.bind( this )\n\t} );\n\tthis.connect( this, { change: 'onLookupInputChange' } );\n\tthis.lookupMenu.connect( this, {\n\t\ttoggle: 'onLookupMenuToggle',\n\t\tchoose: 'onLookupMenuItemChoose'\n\t} );\n\n\t// Initialization\n\tthis.$input.attr( {\n\t\trole: 'combobox',\n\t\t'aria-owns': this.lookupMenu.getElementId(),\n\t\t'aria-autocomplete': 'list'\n\t} );\n\tthis.$element.addClass( 'oo-ui-lookupElement' );\n\tthis.lookupMenu.$element.addClass( 'oo-ui-lookupElement-menu' );\n\tthis.$overlay.append( this.lookupMenu.$element );\n};\n\n/* Setup */\n\nOO.mixinClass( OO.ui.mixin.LookupElement, OO.ui.mixin.RequestManager );\n\n/* Methods */\n\n/**\n * Handle input focus event.\n *\n * @protected\n * @param {jQuery.Event} e Input focus event\n */\nOO.ui.mixin.LookupElement.prototype.onLookupInputFocus = function () {\n\tthis.lookupInputFocused = true;\n\tthis.populateLookupMenu();\n};\n\n/**\n * Handle input blur event.\n *\n * @protected\n * @param {jQuery.Event} e Input blur event\n */\nOO.ui.mixin.LookupElement.prototype.onLookupInputBlur = function () {\n\tthis.closeLookupMenu();\n\tthis.lookupInputFocused = false;\n};\n\n/**\n * Handle input mouse down event.\n *\n * @protected\n * @param {jQuery.Event} e Input mouse down event\n */\nOO.ui.mixin.LookupElement.prototype.onLookupInputMouseDown = function () {\n\t// Only open the menu if the input was already focused.\n\t// This way we allow the user to open the menu again after closing it with Esc\n\t// by clicking in the input. Opening (and populating) the menu when initially\n\t// clicking into the input is handled by the focus handler.\n\tif ( this.lookupInputFocused && !this.lookupMenu.isVisible() ) {\n\t\tthis.populateLookupMenu();\n\t}\n};\n\n/**\n * Handle input change event.\n *\n * @protected\n * @param {string} value New input value\n */\nOO.ui.mixin.LookupElement.prototype.onLookupInputChange = function () {\n\tif ( this.lookupInputFocused ) {\n\t\tthis.populateLookupMenu();\n\t}\n};\n\n/**\n * Handle the lookup menu being shown/hidden.\n *\n * @protected\n * @param {boolean} visible Whether the lookup menu is now visible.\n */\nOO.ui.mixin.LookupElement.prototype.onLookupMenuToggle = function ( visible ) {\n\tif ( !visible ) {\n\t\t// When the menu is hidden, abort any active request and clear the menu.\n\t\t// This has to be done here in addition to closeLookupMenu(), because\n\t\t// MenuSelectWidget will close itself when the user presses Esc.\n\t\tthis.abortLookupRequest();\n\t\tthis.lookupMenu.clearItems();\n\t}\n};\n\n/**\n * Handle menu item 'choose' event, updating the text input value to the value of the clicked item.\n *\n * @protected\n * @param {OO.ui.MenuOptionWidget} item Selected item\n */\nOO.ui.mixin.LookupElement.prototype.onLookupMenuItemChoose = function ( item ) {\n\tthis.setValue( item.getData() );\n};\n\n/**\n * Get lookup menu.\n *\n * @private\n * @return {OO.ui.MenuSelectWidget}\n */\nOO.ui.mixin.LookupElement.prototype.getLookupMenu = function () {\n\treturn this.lookupMenu;\n};\n\n/**\n * Disable or re-enable lookups.\n *\n * When lookups are disabled, calls to #populateLookupMenu will be ignored.\n *\n * @param {boolean} disabled Disable lookups\n */\nOO.ui.mixin.LookupElement.prototype.setLookupsDisabled = function ( disabled ) {\n\tthis.lookupsDisabled = !!disabled;\n};\n\n/**\n * Open the menu. If there are no entries in the menu, this does nothing.\n *\n * @private\n * @chainable\n */\nOO.ui.mixin.LookupElement.prototype.openLookupMenu = function () {\n\tif ( !this.lookupMenu.isEmpty() ) {\n\t\tthis.lookupMenu.toggle( true );\n\t}\n\treturn this;\n};\n\n/**\n * Close the menu, empty it, and abort any pending request.\n *\n * @private\n * @chainable\n */\nOO.ui.mixin.LookupElement.prototype.closeLookupMenu = function () {\n\tthis.lookupMenu.toggle( false );\n\tthis.abortLookupRequest();\n\tthis.lookupMenu.clearItems();\n\treturn this;\n};\n\n/**\n * Request menu items based on the input's current value, and when they arrive,\n * populate the menu with these items and show the menu.\n *\n * If lookups have been disabled with #setLookupsDisabled, this function does nothing.\n *\n * @private\n * @chainable\n */\nOO.ui.mixin.LookupElement.prototype.populateLookupMenu = function () {\n\tvar widget = this,\n\t\tvalue = this.getValue();\n\n\tif ( this.lookupsDisabled || this.isReadOnly() ) {\n\t\treturn;\n\t}\n\n\t// If the input is empty, clear the menu, unless suggestions when empty are allowed.\n\tif ( !this.allowSuggestionsWhenEmpty && value === '' ) {\n\t\tthis.closeLookupMenu();\n\t// Skip population if there is already a request pending for the current value\n\t} else if ( value !== this.lookupQuery ) {\n\t\tthis.getLookupMenuItems()\n\t\t\t.done( function ( items ) {\n\t\t\t\twidget.lookupMenu.clearItems();\n\t\t\t\tif ( items.length ) {\n\t\t\t\t\twidget.lookupMenu\n\t\t\t\t\t\t.addItems( items )\n\t\t\t\t\t\t.toggle( true );\n\t\t\t\t\twidget.initializeLookupMenuSelection();\n\t\t\t\t} else {\n\t\t\t\t\twidget.lookupMenu.toggle( false );\n\t\t\t\t}\n\t\t\t} )\n\t\t\t.fail( function () {\n\t\t\t\twidget.lookupMenu.clearItems();\n\t\t\t} );\n\t}\n\n\treturn this;\n};\n\n/**\n * Highlight the first selectable item in the menu, if configured.\n *\n * @private\n * @chainable\n */\nOO.ui.mixin.LookupElement.prototype.initializeLookupMenuSelection = function () {\n\tif ( this.lookupHighlightFirstItem && !this.lookupMenu.getSelectedItem() ) {\n\t\tthis.lookupMenu.highlightItem( this.lookupMenu.getFirstSelectableItem() );\n\t}\n};\n\n/**\n * Get lookup menu items for the current query.\n *\n * @private\n * @return {jQuery.Promise} Promise object which will be passed menu items as the first argument of\n * the done event. If the request was aborted to make way for a subsequent request, this promise\n * will not be rejected: it will remain pending forever.\n */\nOO.ui.mixin.LookupElement.prototype.getLookupMenuItems = function () {\n\treturn this.getRequestData().then( function ( data ) {\n\t\treturn this.getLookupMenuOptionsFromData( data );\n\t}.bind( this ) );\n};\n\n/**\n * Abort the currently pending lookup request, if any.\n *\n * @private\n */\nOO.ui.mixin.LookupElement.prototype.abortLookupRequest = function () {\n\tthis.abortRequest();\n};\n\n/**\n * Get a new request object of the current lookup query value.\n *\n * @protected\n * @method\n * @abstract\n * @return {jQuery.Promise} jQuery AJAX object, or promise object with an .abort() method\n */\nOO.ui.mixin.LookupElement.prototype.getLookupRequest = null;\n\n/**\n * Pre-process data returned by the request from #getLookupRequest.\n *\n * The return value of this function will be cached, and any further queries for the given value\n * will use the cache rather than doing API requests.\n *\n * @protected\n * @method\n * @abstract\n * @param {Mixed} response Response from server\n * @return {Mixed} Cached result data\n */\nOO.ui.mixin.LookupElement.prototype.getLookupCacheDataFromResponse = null;\n\n/**\n * Get a list of menu option widgets from the (possibly cached) data returned by\n * #getLookupCacheDataFromResponse.\n *\n * @protected\n * @method\n * @abstract\n * @param {Mixed} data Cached result data, usually an array\n * @return {OO.ui.MenuOptionWidget[]} Menu items\n */\nOO.ui.mixin.LookupElement.prototype.getLookupMenuOptionsFromData = null;\n\n/**\n * Set the read-only state of the widget.\n *\n * This will also disable/enable the lookups functionality.\n *\n * @param {boolean} readOnly Make input read-only\n * @chainable\n */\nOO.ui.mixin.LookupElement.prototype.setReadOnly = function ( readOnly ) {\n\t// Parent method\n\t// Note: Calling #setReadOnly this way assumes this is mixed into an OO.ui.TextInputWidget\n\tOO.ui.TextInputWidget.prototype.setReadOnly.call( this, readOnly );\n\n\t// During construction, #setReadOnly is called before the OO.ui.mixin.LookupElement constructor\n\tif ( this.isReadOnly() && this.lookupMenu ) {\n\t\tthis.closeLookupMenu();\n\t}\n\n\treturn this;\n};\n\n/**\n * @inheritdoc OO.ui.mixin.RequestManager\n */\nOO.ui.mixin.LookupElement.prototype.getRequestQuery = function () {\n\treturn this.getValue();\n};\n\n/**\n * @inheritdoc OO.ui.mixin.RequestManager\n */\nOO.ui.mixin.LookupElement.prototype.getRequest = function () {\n\treturn this.getLookupRequest();\n};\n\n/**\n * @inheritdoc OO.ui.mixin.RequestManager\n */\nOO.ui.mixin.LookupElement.prototype.getRequestCacheDataFromResponse = function ( response ) {\n\treturn this.getLookupCacheDataFromResponse( response );\n};\n","/**\n * TabPanelLayouts are used within {@link OO.ui.IndexLayout index layouts} to create tab panels that\n * users can select and display from the index's optional {@link OO.ui.TabSelectWidget tab}\n * navigation. TabPanels are usually not instantiated directly, rather extended to include the\n * required content and functionality.\n *\n * Each tab panel must have a unique symbolic name, which is passed to the constructor. In addition,\n * the tab panel's tab item is customized (with a label) using the #setupTabItem method. See\n * {@link OO.ui.IndexLayout IndexLayout} for an example.\n *\n * @class\n * @extends OO.ui.PanelLayout\n *\n * @constructor\n * @param {string} name Unique symbolic name of tab panel\n * @param {Object} [config] Configuration options\n * @cfg {jQuery|string|Function|OO.ui.HtmlSnippet} [label] Label for tab panel's tab\n */\nOO.ui.TabPanelLayout = function OoUiTabPanelLayout( name, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( name ) && config === undefined ) {\n\t\tconfig = name;\n\t\tname = config.name;\n\t}\n\n\t// Configuration initialization\n\tconfig = $.extend( { scrollable: true }, config );\n\n\t// Parent constructor\n\tOO.ui.TabPanelLayout.parent.call( this, config );\n\n\t// Properties\n\tthis.name = name;\n\tthis.label = config.label;\n\tthis.tabItem = null;\n\tthis.active = false;\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-tabPanelLayout' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.TabPanelLayout, OO.ui.PanelLayout );\n\n/* Events */\n\n/**\n * An 'active' event is emitted when the tab panel becomes active. Tab panels become active when they are\n * shown in a index layout that is configured to display only one tab panel at a time.\n *\n * @event active\n * @param {boolean} active Tab panel is active\n */\n\n/* Methods */\n\n/**\n * Get the symbolic name of the tab panel.\n *\n * @return {string} Symbolic name of tab panel\n */\nOO.ui.TabPanelLayout.prototype.getName = function () {\n\treturn this.name;\n};\n\n/**\n * Check if tab panel is active.\n *\n * Tab panels become active when they are shown in a {@link OO.ui.IndexLayout index layout} that is configured to\n * display only one tab panel at a time. Additional CSS is applied to the tab panel's tab item to reflect the\n * active state.\n *\n * @return {boolean} Tab panel is active\n */\nOO.ui.TabPanelLayout.prototype.isActive = function () {\n\treturn this.active;\n};\n\n/**\n * Get tab item.\n *\n * The tab item allows users to access the tab panel from the index's tab\n * navigation. The tab item itself can be customized (with a label, level, etc.) using the #setupTabItem method.\n *\n * @return {OO.ui.TabOptionWidget|null} Tab option widget\n */\nOO.ui.TabPanelLayout.prototype.getTabItem = function () {\n\treturn this.tabItem;\n};\n\n/**\n * Set or unset the tab item.\n *\n * Specify a {@link OO.ui.TabOptionWidget tab option} to set it,\n * or `null` to clear the tab item. To customize the tab item itself (e.g., to set a label or tab\n * level), use #setupTabItem instead of this method.\n *\n * @param {OO.ui.TabOptionWidget|null} tabItem Tab option widget, null to clear\n * @chainable\n */\nOO.ui.TabPanelLayout.prototype.setTabItem = function ( tabItem ) {\n\tthis.tabItem = tabItem || null;\n\tif ( tabItem ) {\n\t\tthis.setupTabItem();\n\t}\n\treturn this;\n};\n\n/**\n * Set up the tab item.\n *\n * Use this method to customize the tab item (e.g., to add a label or tab level). To set or unset\n * the tab item itself (with a {@link OO.ui.TabOptionWidget tab option} or `null`), use\n * the #setTabItem method instead.\n *\n * @param {OO.ui.TabOptionWidget} tabItem Tab option widget to set up\n * @chainable\n */\nOO.ui.TabPanelLayout.prototype.setupTabItem = function () {\n\tif ( this.label ) {\n\t\tthis.tabItem.setLabel( this.label );\n\t}\n\treturn this;\n};\n\n/**\n * Set the tab panel to its 'active' state.\n *\n * Tab panels become active when they are shown in a index layout that is configured to display only\n * one tab panel at a time. Additional CSS is applied to the tab item to reflect the tab panel's\n * active state. Outside of the index context, setting the active state on a tab panel does nothing.\n *\n * @param {boolean} active Tab panel is active\n * @fires active\n */\nOO.ui.TabPanelLayout.prototype.setActive = function ( active ) {\n\tactive = !!active;\n\n\tif ( active !== this.active ) {\n\t\tthis.active = active;\n\t\tthis.$element.toggleClass( 'oo-ui-tabPanelLayout-active', this.active );\n\t\tthis.emit( 'active', this.active );\n\t}\n};\n","/**\n * PageLayouts are used within {@link OO.ui.BookletLayout booklet layouts} to create pages that users can select and display\n * from the booklet's optional {@link OO.ui.OutlineSelectWidget outline} navigation. Pages are usually not instantiated directly,\n * rather extended to include the required content and functionality.\n *\n * Each page must have a unique symbolic name, which is passed to the constructor. In addition, the page's outline\n * item is customized (with a label, outline level, etc.) using the #setupOutlineItem method. See\n * {@link OO.ui.BookletLayout BookletLayout} for an example.\n *\n * @class\n * @extends OO.ui.PanelLayout\n *\n * @constructor\n * @param {string} name Unique symbolic name of page\n * @param {Object} [config] Configuration options\n */\nOO.ui.PageLayout = function OoUiPageLayout( name, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( name ) && config === undefined ) {\n\t\tconfig = name;\n\t\tname = config.name;\n\t}\n\n\t// Configuration initialization\n\tconfig = $.extend( { scrollable: true }, config );\n\n\t// Parent constructor\n\tOO.ui.PageLayout.parent.call( this, config );\n\n\t// Properties\n\tthis.name = name;\n\tthis.outlineItem = null;\n\tthis.active = false;\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-pageLayout' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.PageLayout, OO.ui.PanelLayout );\n\n/* Events */\n\n/**\n * An 'active' event is emitted when the page becomes active. Pages become active when they are\n * shown in a booklet layout that is configured to display only one page at a time.\n *\n * @event active\n * @param {boolean} active Page is active\n */\n\n/* Methods */\n\n/**\n * Get the symbolic name of the page.\n *\n * @return {string} Symbolic name of page\n */\nOO.ui.PageLayout.prototype.getName = function () {\n\treturn this.name;\n};\n\n/**\n * Check if page is active.\n *\n * Pages become active when they are shown in a {@link OO.ui.BookletLayout booklet layout} that is configured to display\n * only one page at a time. Additional CSS is applied to the page's outline item to reflect the active state.\n *\n * @return {boolean} Page is active\n */\nOO.ui.PageLayout.prototype.isActive = function () {\n\treturn this.active;\n};\n\n/**\n * Get outline item.\n *\n * The outline item allows users to access the page from the booklet's outline\n * navigation. The outline item itself can be customized (with a label, level, etc.) using the #setupOutlineItem method.\n *\n * @return {OO.ui.OutlineOptionWidget|null} Outline option widget\n */\nOO.ui.PageLayout.prototype.getOutlineItem = function () {\n\treturn this.outlineItem;\n};\n\n/**\n * Set or unset the outline item.\n *\n * Specify an {@link OO.ui.OutlineOptionWidget outline option} to set it,\n * or `null` to clear the outline item. To customize the outline item itself (e.g., to set a label or outline\n * level), use #setupOutlineItem instead of this method.\n *\n * @param {OO.ui.OutlineOptionWidget|null} outlineItem Outline option widget, null to clear\n * @chainable\n */\nOO.ui.PageLayout.prototype.setOutlineItem = function ( outlineItem ) {\n\tthis.outlineItem = outlineItem || null;\n\tif ( outlineItem ) {\n\t\tthis.setupOutlineItem();\n\t}\n\treturn this;\n};\n\n/**\n * Set up the outline item.\n *\n * Use this method to customize the outline item (e.g., to add a label or outline level). To set or unset\n * the outline item itself (with an {@link OO.ui.OutlineOptionWidget outline option} or `null`), use\n * the #setOutlineItem method instead.\n *\n * @param {OO.ui.OutlineOptionWidget} outlineItem Outline option widget to set up\n * @chainable\n */\nOO.ui.PageLayout.prototype.setupOutlineItem = function () {\n\treturn this;\n};\n\n/**\n * Set the page to its 'active' state.\n *\n * Pages become active when they are shown in a booklet layout that is configured to display only one page at a time. Additional\n * CSS is applied to the outline item to reflect the page's active state. Outside of the booklet\n * context, setting the active state on a page does nothing.\n *\n * @param {boolean} active Page is active\n * @fires active\n */\nOO.ui.PageLayout.prototype.setActive = function ( active ) {\n\tactive = !!active;\n\n\tif ( active !== this.active ) {\n\t\tthis.active = active;\n\t\tthis.$element.toggleClass( 'oo-ui-pageLayout-active', active );\n\t\tthis.emit( 'active', this.active );\n\t}\n};\n","/**\n * StackLayouts contain a series of {@link OO.ui.PanelLayout panel layouts}. By default, only one panel is displayed\n * at a time, though the stack layout can also be configured to show all contained panels, one after another,\n * by setting the #continuous option to 'true'.\n *\n * @example\n * // A stack layout with two panels, configured to be displayed continously\n * var myStack = new OO.ui.StackLayout( {\n * items: [\n * new OO.ui.PanelLayout( {\n * $content: $( '<p>Panel One</p>' ),\n * padded: true,\n * framed: true\n * } ),\n * new OO.ui.PanelLayout( {\n * $content: $( '<p>Panel Two</p>' ),\n * padded: true,\n * framed: true\n * } )\n * ],\n * continuous: true\n * } );\n * $( 'body' ).append( myStack.$element );\n *\n * @class\n * @extends OO.ui.PanelLayout\n * @mixins OO.ui.mixin.GroupElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [continuous=false] Show all panels, one after another. By default, only one panel is displayed at a time.\n * @cfg {OO.ui.Layout[]} [items] Panel layouts to add to the stack layout.\n */\nOO.ui.StackLayout = function OoUiStackLayout( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( { scrollable: true }, config );\n\n\t// Parent constructor\n\tOO.ui.StackLayout.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.GroupElement.call( this, $.extend( {}, config, { $group: this.$element } ) );\n\n\t// Properties\n\tthis.currentItem = null;\n\tthis.continuous = !!config.continuous;\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-stackLayout' );\n\tif ( this.continuous ) {\n\t\tthis.$element.addClass( 'oo-ui-stackLayout-continuous' );\n\t\tthis.$element.on( 'scroll', OO.ui.debounce( this.onScroll.bind( this ), 250 ) );\n\t}\n\tif ( Array.isArray( config.items ) ) {\n\t\tthis.addItems( config.items );\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.StackLayout, OO.ui.PanelLayout );\nOO.mixinClass( OO.ui.StackLayout, OO.ui.mixin.GroupElement );\n\n/* Events */\n\n/**\n * A 'set' event is emitted when panels are {@link #addItems added}, {@link #removeItems removed},\n * {@link #clearItems cleared} or {@link #setItem displayed}.\n *\n * @event set\n * @param {OO.ui.Layout|null} item Current panel or `null` if no panel is shown\n */\n\n/**\n * When used in continuous mode, this event is emitted when the user scrolls down\n * far enough such that currentItem is no longer visible.\n *\n * @event visibleItemChange\n * @param {OO.ui.PanelLayout} panel The next visible item in the layout\n */\n\n/* Methods */\n\n/**\n * Handle scroll events from the layout element\n *\n * @param {jQuery.Event} e\n * @fires visibleItemChange\n */\nOO.ui.StackLayout.prototype.onScroll = function () {\n\tvar currentRect,\n\t\tlen = this.items.length,\n\t\tcurrentIndex = this.items.indexOf( this.currentItem ),\n\t\tnewIndex = currentIndex,\n\t\tcontainerRect = this.$element[ 0 ].getBoundingClientRect();\n\n\tif ( !containerRect || ( !containerRect.top && !containerRect.bottom ) ) {\n\t\t// Can't get bounding rect, possibly not attached.\n\t\treturn;\n\t}\n\n\tfunction getRect( item ) {\n\t\treturn item.$element[ 0 ].getBoundingClientRect();\n\t}\n\n\tfunction isVisible( item ) {\n\t\tvar rect = getRect( item );\n\t\treturn rect.bottom > containerRect.top && rect.top < containerRect.bottom;\n\t}\n\n\tcurrentRect = getRect( this.currentItem );\n\n\tif ( currentRect.bottom < containerRect.top ) {\n\t\t// Scrolled down past current item\n\t\twhile ( ++newIndex < len ) {\n\t\t\tif ( isVisible( this.items[ newIndex ] ) ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t} else if ( currentRect.top > containerRect.bottom ) {\n\t\t// Scrolled up past current item\n\t\twhile ( --newIndex >= 0 ) {\n\t\t\tif ( isVisible( this.items[ newIndex ] ) ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif ( newIndex !== currentIndex ) {\n\t\tthis.emit( 'visibleItemChange', this.items[ newIndex ] );\n\t}\n};\n\n/**\n * Get the current panel.\n *\n * @return {OO.ui.Layout|null}\n */\nOO.ui.StackLayout.prototype.getCurrentItem = function () {\n\treturn this.currentItem;\n};\n\n/**\n * Unset the current item.\n *\n * @private\n * @param {OO.ui.StackLayout} layout\n * @fires set\n */\nOO.ui.StackLayout.prototype.unsetCurrentItem = function () {\n\tvar prevItem = this.currentItem;\n\tif ( prevItem === null ) {\n\t\treturn;\n\t}\n\n\tthis.currentItem = null;\n\tthis.emit( 'set', null );\n};\n\n/**\n * Add panel layouts to the stack layout.\n *\n * Panels will be added to the end of the stack layout array unless the optional index parameter specifies a different\n * insertion point. Adding a panel that is already in the stack will move it to the end of the array or the point specified\n * by the index.\n *\n * @param {OO.ui.Layout[]} items Panels to add\n * @param {number} [index] Index of the insertion point\n * @chainable\n */\nOO.ui.StackLayout.prototype.addItems = function ( items, index ) {\n\t// Update the visibility\n\tthis.updateHiddenState( items, this.currentItem );\n\n\t// Mixin method\n\tOO.ui.mixin.GroupElement.prototype.addItems.call( this, items, index );\n\n\tif ( !this.currentItem && items.length ) {\n\t\tthis.setItem( items[ 0 ] );\n\t}\n\n\treturn this;\n};\n\n/**\n * Remove the specified panels from the stack layout.\n *\n * Removed panels are detached from the DOM, not removed, so that they may be reused. To remove all panels,\n * you may wish to use the #clearItems method instead.\n *\n * @param {OO.ui.Layout[]} items Panels to remove\n * @chainable\n * @fires set\n */\nOO.ui.StackLayout.prototype.removeItems = function ( items ) {\n\t// Mixin method\n\tOO.ui.mixin.GroupElement.prototype.removeItems.call( this, items );\n\n\tif ( items.indexOf( this.currentItem ) !== -1 ) {\n\t\tif ( this.items.length ) {\n\t\t\tthis.setItem( this.items[ 0 ] );\n\t\t} else {\n\t\t\tthis.unsetCurrentItem();\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Clear all panels from the stack layout.\n *\n * Cleared panels are detached from the DOM, not removed, so that they may be reused. To remove only\n * a subset of panels, use the #removeItems method.\n *\n * @chainable\n * @fires set\n */\nOO.ui.StackLayout.prototype.clearItems = function () {\n\tthis.unsetCurrentItem();\n\tOO.ui.mixin.GroupElement.prototype.clearItems.call( this );\n\n\treturn this;\n};\n\n/**\n * Show the specified panel.\n *\n * If another panel is currently displayed, it will be hidden.\n *\n * @param {OO.ui.Layout} item Panel to show\n * @chainable\n * @fires set\n */\nOO.ui.StackLayout.prototype.setItem = function ( item ) {\n\tif ( item !== this.currentItem ) {\n\t\tthis.updateHiddenState( this.items, item );\n\n\t\tif ( this.items.indexOf( item ) !== -1 ) {\n\t\t\tthis.currentItem = item;\n\t\t\tthis.emit( 'set', item );\n\t\t} else {\n\t\t\tthis.unsetCurrentItem();\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Update the visibility of all items in case of non-continuous view.\n *\n * Ensure all items are hidden except for the selected one.\n * This method does nothing when the stack is continuous.\n *\n * @private\n * @param {OO.ui.Layout[]} items Item list iterate over\n * @param {OO.ui.Layout} [selectedItem] Selected item to show\n */\nOO.ui.StackLayout.prototype.updateHiddenState = function ( items, selectedItem ) {\n\tvar i, len;\n\n\tif ( !this.continuous ) {\n\t\tfor ( i = 0, len = items.length; i < len; i++ ) {\n\t\t\tif ( !selectedItem || selectedItem !== items[ i ] ) {\n\t\t\t\titems[ i ].$element.addClass( 'oo-ui-element-hidden' );\n\t\t\t\titems[ i ].$element.attr( 'aria-hidden', 'true' );\n\t\t\t}\n\t\t}\n\t\tif ( selectedItem ) {\n\t\t\tselectedItem.$element.removeClass( 'oo-ui-element-hidden' );\n\t\t\tselectedItem.$element.removeAttr( 'aria-hidden' );\n\t\t}\n\t}\n};\n","/**\n * MenuLayouts combine a menu and a content {@link OO.ui.PanelLayout panel}. The menu is positioned relative to the content (after, before, top, or bottom)\n * and its size is customized with the #menuSize config. The content area will fill all remaining space.\n *\n * @example\n * var menuLayout = new OO.ui.MenuLayout( {\n * position: 'top'\n * } ),\n * menuPanel = new OO.ui.PanelLayout( { padded: true, expanded: true, scrollable: true } ),\n * contentPanel = new OO.ui.PanelLayout( { padded: true, expanded: true, scrollable: true } ),\n * select = new OO.ui.SelectWidget( {\n * items: [\n * new OO.ui.OptionWidget( {\n * data: 'before',\n * label: 'Before',\n * } ),\n * new OO.ui.OptionWidget( {\n * data: 'after',\n * label: 'After',\n * } ),\n * new OO.ui.OptionWidget( {\n * data: 'top',\n * label: 'Top',\n * } ),\n * new OO.ui.OptionWidget( {\n * data: 'bottom',\n * label: 'Bottom',\n * } )\n * ]\n * } ).on( 'select', function ( item ) {\n * menuLayout.setMenuPosition( item.getData() );\n * } );\n *\n * menuLayout.$menu.append(\n * menuPanel.$element.append( '<b>Menu panel</b>', select.$element )\n * );\n * menuLayout.$content.append(\n * contentPanel.$element.append( '<b>Content panel</b>', '<p>Note that the menu is positioned relative to the content panel: top, bottom, after, before.</p>')\n * );\n * $( 'body' ).append( menuLayout.$element );\n *\n * If menu size needs to be overridden, it can be accomplished using CSS similar to the snippet\n * below. MenuLayout's CSS will override the appropriate values with 'auto' or '0' to display the\n * menu correctly. If `menuPosition` is known beforehand, CSS rules corresponding to other positions\n * may be omitted.\n *\n * .oo-ui-menuLayout-menu {\n * height: 200px;\n * width: 200px;\n * }\n * .oo-ui-menuLayout-content {\n * top: 200px;\n * left: 200px;\n * right: 200px;\n * bottom: 200px;\n * }\n *\n * @class\n * @extends OO.ui.Layout\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [showMenu=true] Show menu\n * @cfg {string} [menuPosition='before'] Position of menu: `top`, `after`, `bottom` or `before`\n */\nOO.ui.MenuLayout = function OoUiMenuLayout( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( {\n\t\tshowMenu: true,\n\t\tmenuPosition: 'before'\n\t}, config );\n\n\t// Parent constructor\n\tOO.ui.MenuLayout.parent.call( this, config );\n\n\t/**\n\t * Menu DOM node\n\t *\n\t * @property {jQuery}\n\t */\n\tthis.$menu = $( '<div>' );\n\t/**\n\t * Content DOM node\n\t *\n\t * @property {jQuery}\n\t */\n\tthis.$content = $( '<div>' );\n\n\t// Initialization\n\tthis.$menu\n\t\t.addClass( 'oo-ui-menuLayout-menu' );\n\tthis.$content.addClass( 'oo-ui-menuLayout-content' );\n\tthis.$element\n\t\t.addClass( 'oo-ui-menuLayout' )\n\t\t.append( this.$content, this.$menu );\n\tthis.setMenuPosition( config.menuPosition );\n\tthis.toggleMenu( config.showMenu );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.MenuLayout, OO.ui.Layout );\n\n/* Methods */\n\n/**\n * Toggle menu.\n *\n * @param {boolean} showMenu Show menu, omit to toggle\n * @chainable\n */\nOO.ui.MenuLayout.prototype.toggleMenu = function ( showMenu ) {\n\tshowMenu = showMenu === undefined ? !this.showMenu : !!showMenu;\n\n\tif ( this.showMenu !== showMenu ) {\n\t\tthis.showMenu = showMenu;\n\t\tthis.$element\n\t\t\t.toggleClass( 'oo-ui-menuLayout-showMenu', this.showMenu )\n\t\t\t.toggleClass( 'oo-ui-menuLayout-hideMenu', !this.showMenu );\n\t\tthis.$menu.attr( 'aria-hidden', this.showMenu ? 'false' : 'true' );\n\t}\n\n\treturn this;\n};\n\n/**\n * Check if menu is visible\n *\n * @return {boolean} Menu is visible\n */\nOO.ui.MenuLayout.prototype.isMenuVisible = function () {\n\treturn this.showMenu;\n};\n\n/**\n * Set menu position.\n *\n * @param {string} position Position of menu, either `top`, `after`, `bottom` or `before`\n * @throws {Error} If position value is not supported\n * @chainable\n */\nOO.ui.MenuLayout.prototype.setMenuPosition = function ( position ) {\n\tthis.$element.removeClass( 'oo-ui-menuLayout-' + this.menuPosition );\n\tthis.menuPosition = position;\n\tthis.$element.addClass( 'oo-ui-menuLayout-' + position );\n\n\treturn this;\n};\n\n/**\n * Get menu position.\n *\n * @return {string} Menu position\n */\nOO.ui.MenuLayout.prototype.getMenuPosition = function () {\n\treturn this.menuPosition;\n};\n","/**\n * BookletLayouts contain {@link OO.ui.PageLayout page layouts} as well as\n * an {@link OO.ui.OutlineSelectWidget outline} that allows users to easily navigate\n * through the pages and select which one to display. By default, only one page is\n * displayed at a time and the outline is hidden. When a user navigates to a new page,\n * the booklet layout automatically focuses on the first focusable element, unless the\n * default setting is changed. Optionally, booklets can be configured to show\n * {@link OO.ui.OutlineControlsWidget controls} for adding, moving, and removing items.\n *\n * @example\n * // Example of a BookletLayout that contains two PageLayouts.\n *\n * function PageOneLayout( name, config ) {\n * PageOneLayout.parent.call( this, name, config );\n * this.$element.append( '<p>First page</p><p>(This booklet has an outline, displayed on the left)</p>' );\n * }\n * OO.inheritClass( PageOneLayout, OO.ui.PageLayout );\n * PageOneLayout.prototype.setupOutlineItem = function () {\n * this.outlineItem.setLabel( 'Page One' );\n * };\n *\n * function PageTwoLayout( name, config ) {\n * PageTwoLayout.parent.call( this, name, config );\n * this.$element.append( '<p>Second page</p>' );\n * }\n * OO.inheritClass( PageTwoLayout, OO.ui.PageLayout );\n * PageTwoLayout.prototype.setupOutlineItem = function () {\n * this.outlineItem.setLabel( 'Page Two' );\n * };\n *\n * var page1 = new PageOneLayout( 'one' ),\n * page2 = new PageTwoLayout( 'two' );\n *\n * var booklet = new OO.ui.BookletLayout( {\n * outlined: true\n * } );\n *\n * booklet.addPages ( [ page1, page2 ] );\n * $( 'body' ).append( booklet.$element );\n *\n * @class\n * @extends OO.ui.MenuLayout\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [continuous=false] Show all pages, one after another\n * @cfg {boolean} [autoFocus=true] Focus on the first focusable element when a new page is displayed. Disabled on mobile.\n * @cfg {boolean} [outlined=false] Show the outline. The outline is used to navigate through the pages of the booklet.\n * @cfg {boolean} [editable=false] Show controls for adding, removing and reordering pages\n */\nOO.ui.BookletLayout = function OoUiBookletLayout( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.BookletLayout.parent.call( this, config );\n\n\t// Properties\n\tthis.currentPageName = null;\n\tthis.pages = {};\n\tthis.ignoreFocus = false;\n\tthis.stackLayout = new OO.ui.StackLayout( { continuous: !!config.continuous } );\n\tthis.$content.append( this.stackLayout.$element );\n\tthis.autoFocus = config.autoFocus === undefined || !!config.autoFocus;\n\tthis.outlineVisible = false;\n\tthis.outlined = !!config.outlined;\n\tif ( this.outlined ) {\n\t\tthis.editable = !!config.editable;\n\t\tthis.outlineControlsWidget = null;\n\t\tthis.outlineSelectWidget = new OO.ui.OutlineSelectWidget();\n\t\tthis.outlinePanel = new OO.ui.PanelLayout( { scrollable: true } );\n\t\tthis.$menu.append( this.outlinePanel.$element );\n\t\tthis.outlineVisible = true;\n\t\tif ( this.editable ) {\n\t\t\tthis.outlineControlsWidget = new OO.ui.OutlineControlsWidget(\n\t\t\t\tthis.outlineSelectWidget\n\t\t\t);\n\t\t}\n\t}\n\tthis.toggleMenu( this.outlined );\n\n\t// Events\n\tthis.stackLayout.connect( this, { set: 'onStackLayoutSet' } );\n\tif ( this.outlined ) {\n\t\tthis.outlineSelectWidget.connect( this, { select: 'onOutlineSelectWidgetSelect' } );\n\t\tthis.scrolling = false;\n\t\tthis.stackLayout.connect( this, { visibleItemChange: 'onStackLayoutVisibleItemChange' } );\n\t}\n\tif ( this.autoFocus ) {\n\t\t// Event 'focus' does not bubble, but 'focusin' does\n\t\tthis.stackLayout.$element.on( 'focusin', this.onStackLayoutFocus.bind( this ) );\n\t}\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-bookletLayout' );\n\tthis.stackLayout.$element.addClass( 'oo-ui-bookletLayout-stackLayout' );\n\tif ( this.outlined ) {\n\t\tthis.outlinePanel.$element\n\t\t\t.addClass( 'oo-ui-bookletLayout-outlinePanel' )\n\t\t\t.append( this.outlineSelectWidget.$element );\n\t\tif ( this.editable ) {\n\t\t\tthis.outlinePanel.$element\n\t\t\t\t.addClass( 'oo-ui-bookletLayout-outlinePanel-editable' )\n\t\t\t\t.append( this.outlineControlsWidget.$element );\n\t\t}\n\t}\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.BookletLayout, OO.ui.MenuLayout );\n\n/* Events */\n\n/**\n * A 'set' event is emitted when a page is {@link #setPage set} to be displayed by the booklet layout.\n * @event set\n * @param {OO.ui.PageLayout} page Current page\n */\n\n/**\n * An 'add' event is emitted when pages are {@link #addPages added} to the booklet layout.\n *\n * @event add\n * @param {OO.ui.PageLayout[]} page Added pages\n * @param {number} index Index pages were added at\n */\n\n/**\n * A 'remove' event is emitted when pages are {@link #clearPages cleared} or\n * {@link #removePages removed} from the booklet.\n *\n * @event remove\n * @param {OO.ui.PageLayout[]} pages Removed pages\n */\n\n/* Methods */\n\n/**\n * Handle stack layout focus.\n *\n * @private\n * @param {jQuery.Event} e Focusin event\n */\nOO.ui.BookletLayout.prototype.onStackLayoutFocus = function ( e ) {\n\tvar name, $target;\n\n\t// Find the page that an element was focused within\n\t$target = $( e.target ).closest( '.oo-ui-pageLayout' );\n\tfor ( name in this.pages ) {\n\t\t// Check for page match, exclude current page to find only page changes\n\t\tif ( this.pages[ name ].$element[ 0 ] === $target[ 0 ] && name !== this.currentPageName ) {\n\t\t\tthis.setPage( name );\n\t\t\tbreak;\n\t\t}\n\t}\n};\n\n/**\n * Handle visibleItemChange events from the stackLayout\n *\n * The next visible page is set as the current page by selecting it\n * in the outline\n *\n * @param {OO.ui.PageLayout} page The next visible page in the layout\n */\nOO.ui.BookletLayout.prototype.onStackLayoutVisibleItemChange = function ( page ) {\n\t// Set a flag to so that the resulting call to #onStackLayoutSet doesn't\n\t// try and scroll the item into view again.\n\tthis.scrolling = true;\n\tthis.outlineSelectWidget.selectItemByData( page.getName() );\n\tthis.scrolling = false;\n};\n\n/**\n * Handle stack layout set events.\n *\n * @private\n * @param {OO.ui.PanelLayout|null} page The page panel that is now the current panel\n */\nOO.ui.BookletLayout.prototype.onStackLayoutSet = function ( page ) {\n\tvar layout = this;\n\tif ( !this.scrolling && page ) {\n\t\tpage.scrollElementIntoView().done( function () {\n\t\t\tif ( layout.autoFocus && !OO.ui.isMobile() ) {\n\t\t\t\tlayout.focus();\n\t\t\t}\n\t\t} );\n\t}\n};\n\n/**\n * Focus the first input in the current page.\n *\n * If no page is selected, the first selectable page will be selected.\n * If the focus is already in an element on the current page, nothing will happen.\n *\n * @param {number} [itemIndex] A specific item to focus on\n */\nOO.ui.BookletLayout.prototype.focus = function ( itemIndex ) {\n\tvar page,\n\t\titems = this.stackLayout.getItems();\n\n\tif ( itemIndex !== undefined && items[ itemIndex ] ) {\n\t\tpage = items[ itemIndex ];\n\t} else {\n\t\tpage = this.stackLayout.getCurrentItem();\n\t}\n\n\tif ( !page && this.outlined ) {\n\t\tthis.selectFirstSelectablePage();\n\t\tpage = this.stackLayout.getCurrentItem();\n\t}\n\tif ( !page ) {\n\t\treturn;\n\t}\n\t// Only change the focus if is not already in the current page\n\tif ( !OO.ui.contains( page.$element[ 0 ], this.getElementDocument().activeElement, true ) ) {\n\t\tpage.focus();\n\t}\n};\n\n/**\n * Find the first focusable input in the booklet layout and focus\n * on it.\n */\nOO.ui.BookletLayout.prototype.focusFirstFocusable = function () {\n\tOO.ui.findFocusable( this.stackLayout.$element ).focus();\n};\n\n/**\n * Handle outline widget select events.\n *\n * @private\n * @param {OO.ui.OptionWidget|null} item Selected item\n */\nOO.ui.BookletLayout.prototype.onOutlineSelectWidgetSelect = function ( item ) {\n\tif ( item ) {\n\t\tthis.setPage( item.getData() );\n\t}\n};\n\n/**\n * Check if booklet has an outline.\n *\n * @return {boolean} Booklet has an outline\n */\nOO.ui.BookletLayout.prototype.isOutlined = function () {\n\treturn this.outlined;\n};\n\n/**\n * Check if booklet has editing controls.\n *\n * @return {boolean} Booklet is editable\n */\nOO.ui.BookletLayout.prototype.isEditable = function () {\n\treturn this.editable;\n};\n\n/**\n * Check if booklet has a visible outline.\n *\n * @return {boolean} Outline is visible\n */\nOO.ui.BookletLayout.prototype.isOutlineVisible = function () {\n\treturn this.outlined && this.outlineVisible;\n};\n\n/**\n * Hide or show the outline.\n *\n * @param {boolean} [show] Show outline, omit to invert current state\n * @chainable\n */\nOO.ui.BookletLayout.prototype.toggleOutline = function ( show ) {\n\tvar booklet = this;\n\n\tif ( this.outlined ) {\n\t\tshow = show === undefined ? !this.outlineVisible : !!show;\n\t\tthis.outlineVisible = show;\n\t\tthis.toggleMenu( show );\n\t\tif ( show && this.editable ) {\n\t\t\t// HACK: Kill dumb scrollbars when the sidebar stops animating, see T161798. Only necessary when\n\t\t\t// outline controls are present, delay matches transition on `.oo-ui-menuLayout-menu`.\n\t\t\tsetTimeout( function () {\n\t\t\t\tOO.ui.Element.static.reconsiderScrollbars( booklet.outlinePanel.$element[ 0 ] );\n\t\t\t}, 200 );\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Find the page closest to the specified page.\n *\n * @param {OO.ui.PageLayout} page Page to use as a reference point\n * @return {OO.ui.PageLayout|null} Page closest to the specified page\n */\nOO.ui.BookletLayout.prototype.findClosestPage = function ( page ) {\n\tvar next, prev, level,\n\t\tpages = this.stackLayout.getItems(),\n\t\tindex = pages.indexOf( page );\n\n\tif ( index !== -1 ) {\n\t\tnext = pages[ index + 1 ];\n\t\tprev = pages[ index - 1 ];\n\t\t// Prefer adjacent pages at the same level\n\t\tif ( this.outlined ) {\n\t\t\tlevel = this.outlineSelectWidget.getItemFromData( page.getName() ).getLevel();\n\t\t\tif (\n\t\t\t\tprev &&\n\t\t\t\tlevel === this.outlineSelectWidget.getItemFromData( prev.getName() ).getLevel()\n\t\t\t) {\n\t\t\t\treturn prev;\n\t\t\t}\n\t\t\tif (\n\t\t\t\tnext &&\n\t\t\t\tlevel === this.outlineSelectWidget.getItemFromData( next.getName() ).getLevel()\n\t\t\t) {\n\t\t\t\treturn next;\n\t\t\t}\n\t\t}\n\t}\n\treturn prev || next || null;\n};\n\n/**\n * Get the page closest to the specified page.\n *\n * @deprecated 0.22.6 Use {@link OO.ui.BookletLayout#findClosestPage} instead.\n * @param {OO.ui.PageLayout} page Page to use as a reference point\n * @return {OO.ui.PageLayout|null} Page closest to the specified page\n */\nOO.ui.BookletLayout.prototype.getClosestPage = function ( page ) {\n\tOO.ui.warnDeprecation( 'BookletLayout#getClosestPage: Deprecated function. Use findClosestPage instead. See T76630.' );\n\treturn this.findClosestPage( page );\n};\n\n/**\n * Get the outline widget.\n *\n * If the booklet is not outlined, the method will return `null`.\n *\n * @return {OO.ui.OutlineSelectWidget|null} Outline widget, or null if the booklet is not outlined\n */\nOO.ui.BookletLayout.prototype.getOutline = function () {\n\treturn this.outlineSelectWidget;\n};\n\n/**\n * Get the outline controls widget.\n *\n * If the outline is not editable, the method will return `null`.\n *\n * @return {OO.ui.OutlineControlsWidget|null} The outline controls widget.\n */\nOO.ui.BookletLayout.prototype.getOutlineControls = function () {\n\treturn this.outlineControlsWidget;\n};\n\n/**\n * Get a page by its symbolic name.\n *\n * @param {string} name Symbolic name of page\n * @return {OO.ui.PageLayout|undefined} Page, if found\n */\nOO.ui.BookletLayout.prototype.getPage = function ( name ) {\n\treturn this.pages[ name ];\n};\n\n/**\n * Get the current page.\n *\n * @return {OO.ui.PageLayout|undefined} Current page, if found\n */\nOO.ui.BookletLayout.prototype.getCurrentPage = function () {\n\tvar name = this.getCurrentPageName();\n\treturn name ? this.getPage( name ) : undefined;\n};\n\n/**\n * Get the symbolic name of the current page.\n *\n * @return {string|null} Symbolic name of the current page\n */\nOO.ui.BookletLayout.prototype.getCurrentPageName = function () {\n\treturn this.currentPageName;\n};\n\n/**\n * Add pages to the booklet layout\n *\n * When pages are added with the same names as existing pages, the existing pages will be\n * automatically removed before the new pages are added.\n *\n * @param {OO.ui.PageLayout[]} pages Pages to add\n * @param {number} index Index of the insertion point\n * @fires add\n * @chainable\n */\nOO.ui.BookletLayout.prototype.addPages = function ( pages, index ) {\n\tvar i, len, name, page, item, currentIndex,\n\t\tstackLayoutPages = this.stackLayout.getItems(),\n\t\tremove = [],\n\t\titems = [];\n\n\t// Remove pages with same names\n\tfor ( i = 0, len = pages.length; i < len; i++ ) {\n\t\tpage = pages[ i ];\n\t\tname = page.getName();\n\n\t\tif ( Object.prototype.hasOwnProperty.call( this.pages, name ) ) {\n\t\t\t// Correct the insertion index\n\t\t\tcurrentIndex = stackLayoutPages.indexOf( this.pages[ name ] );\n\t\t\tif ( currentIndex !== -1 && currentIndex + 1 < index ) {\n\t\t\t\tindex--;\n\t\t\t}\n\t\t\tremove.push( this.pages[ name ] );\n\t\t}\n\t}\n\tif ( remove.length ) {\n\t\tthis.removePages( remove );\n\t}\n\n\t// Add new pages\n\tfor ( i = 0, len = pages.length; i < len; i++ ) {\n\t\tpage = pages[ i ];\n\t\tname = page.getName();\n\t\tthis.pages[ page.getName() ] = page;\n\t\tif ( this.outlined ) {\n\t\t\titem = new OO.ui.OutlineOptionWidget( { data: name } );\n\t\t\tpage.setOutlineItem( item );\n\t\t\titems.push( item );\n\t\t}\n\t}\n\n\tif ( this.outlined && items.length ) {\n\t\tthis.outlineSelectWidget.addItems( items, index );\n\t\tthis.selectFirstSelectablePage();\n\t}\n\tthis.stackLayout.addItems( pages, index );\n\tthis.emit( 'add', pages, index );\n\n\treturn this;\n};\n\n/**\n * Remove the specified pages from the booklet layout.\n *\n * To remove all pages from the booklet, you may wish to use the #clearPages method instead.\n *\n * @param {OO.ui.PageLayout[]} pages An array of pages to remove\n * @fires remove\n * @chainable\n */\nOO.ui.BookletLayout.prototype.removePages = function ( pages ) {\n\tvar i, len, name, page,\n\t\titems = [];\n\n\tfor ( i = 0, len = pages.length; i < len; i++ ) {\n\t\tpage = pages[ i ];\n\t\tname = page.getName();\n\t\tdelete this.pages[ name ];\n\t\tif ( this.outlined ) {\n\t\t\titems.push( this.outlineSelectWidget.getItemFromData( name ) );\n\t\t\tpage.setOutlineItem( null );\n\t\t}\n\t}\n\tif ( this.outlined && items.length ) {\n\t\tthis.outlineSelectWidget.removeItems( items );\n\t\tthis.selectFirstSelectablePage();\n\t}\n\tthis.stackLayout.removeItems( pages );\n\tthis.emit( 'remove', pages );\n\n\treturn this;\n};\n\n/**\n * Clear all pages from the booklet layout.\n *\n * To remove only a subset of pages from the booklet, use the #removePages method.\n *\n * @fires remove\n * @chainable\n */\nOO.ui.BookletLayout.prototype.clearPages = function () {\n\tvar i, len,\n\t\tpages = this.stackLayout.getItems();\n\n\tthis.pages = {};\n\tthis.currentPageName = null;\n\tif ( this.outlined ) {\n\t\tthis.outlineSelectWidget.clearItems();\n\t\tfor ( i = 0, len = pages.length; i < len; i++ ) {\n\t\t\tpages[ i ].setOutlineItem( null );\n\t\t}\n\t}\n\tthis.stackLayout.clearItems();\n\n\tthis.emit( 'remove', pages );\n\n\treturn this;\n};\n\n/**\n * Set the current page by symbolic name.\n *\n * @fires set\n * @param {string} name Symbolic name of page\n */\nOO.ui.BookletLayout.prototype.setPage = function ( name ) {\n\tvar selectedItem,\n\t\t$focused,\n\t\tpage = this.pages[ name ],\n\t\tpreviousPage = this.currentPageName && this.pages[ this.currentPageName ];\n\n\tif ( name !== this.currentPageName ) {\n\t\tif ( this.outlined ) {\n\t\t\tselectedItem = this.outlineSelectWidget.getSelectedItem();\n\t\t\tif ( selectedItem && selectedItem.getData() !== name ) {\n\t\t\t\tthis.outlineSelectWidget.selectItemByData( name );\n\t\t\t}\n\t\t}\n\t\tif ( page ) {\n\t\t\tif ( previousPage ) {\n\t\t\t\tpreviousPage.setActive( false );\n\t\t\t\t// Blur anything focused if the next page doesn't have anything focusable.\n\t\t\t\t// This is not needed if the next page has something focusable (because once it is focused\n\t\t\t\t// this blur happens automatically). If the layout is non-continuous, this check is\n\t\t\t\t// meaningless because the next page is not visible yet and thus can't hold focus.\n\t\t\t\tif (\n\t\t\t\t\tthis.autoFocus &&\n\t\t\t\t\t!OO.ui.isMobile() &&\n\t\t\t\t\tthis.stackLayout.continuous &&\n\t\t\t\t\tOO.ui.findFocusable( page.$element ).length !== 0\n\t\t\t\t) {\n\t\t\t\t\t$focused = previousPage.$element.find( ':focus' );\n\t\t\t\t\tif ( $focused.length ) {\n\t\t\t\t\t\t$focused[ 0 ].blur();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.currentPageName = name;\n\t\t\tpage.setActive( true );\n\t\t\tthis.stackLayout.setItem( page );\n\t\t\tif ( !this.stackLayout.continuous && previousPage ) {\n\t\t\t\t// This should not be necessary, since any inputs on the previous page should have been\n\t\t\t\t// blurred when it was hidden, but browsers are not very consistent about this.\n\t\t\t\t$focused = previousPage.$element.find( ':focus' );\n\t\t\t\tif ( $focused.length ) {\n\t\t\t\t\t$focused[ 0 ].blur();\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.emit( 'set', page );\n\t\t}\n\t}\n};\n\n/**\n * Select the first selectable page.\n *\n * @chainable\n */\nOO.ui.BookletLayout.prototype.selectFirstSelectablePage = function () {\n\tif ( !this.outlineSelectWidget.getSelectedItem() ) {\n\t\tthis.outlineSelectWidget.selectItem( this.outlineSelectWidget.getFirstSelectableItem() );\n\t}\n\n\treturn this;\n};\n","/**\n * IndexLayouts contain {@link OO.ui.TabPanelLayout tab panel layouts} as well as\n * {@link OO.ui.TabSelectWidget tabs} that allow users to easily navigate through the tab panels and\n * select which one to display. By default, only one tab panel is displayed at a time. When a user\n * navigates to a new tab panel, the index layout automatically focuses on the first focusable element,\n * unless the default setting is changed.\n *\n * TODO: This class is similar to BookletLayout, we may want to refactor to reduce duplication\n *\n * @example\n * // Example of a IndexLayout that contains two TabPanelLayouts.\n *\n * function TabPanelOneLayout( name, config ) {\n * TabPanelOneLayout.parent.call( this, name, config );\n * this.$element.append( '<p>First tab panel</p>' );\n * }\n * OO.inheritClass( TabPanelOneLayout, OO.ui.TabPanelLayout );\n * TabPanelOneLayout.prototype.setupTabItem = function () {\n * this.tabItem.setLabel( 'Tab panel one' );\n * };\n *\n * var tabPanel1 = new TabPanelOneLayout( 'one' ),\n * tabPanel2 = new OO.ui.TabPanelLayout( 'two', { label: 'Tab panel two' } );\n *\n * tabPanel2.$element.append( '<p>Second tab panel</p>' );\n *\n * var index = new OO.ui.IndexLayout();\n *\n * index.addTabPanels ( [ tabPanel1, tabPanel2 ] );\n * $( 'body' ).append( index.$element );\n *\n * @class\n * @extends OO.ui.MenuLayout\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [continuous=false] Show all tab panels, one after another\n * @cfg {boolean} [expanded=true] Expand the content panel to fill the entire parent element.\n * @cfg {boolean} [autoFocus=true] Focus on the first focusable element when a new tab panel is displayed. Disabled on mobile.\n */\nOO.ui.IndexLayout = function OoUiIndexLayout( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( {}, config, { menuPosition: 'top' } );\n\n\t// Parent constructor\n\tOO.ui.IndexLayout.parent.call( this, config );\n\n\t// Properties\n\tthis.currentTabPanelName = null;\n\tthis.tabPanels = {};\n\n\tthis.ignoreFocus = false;\n\tthis.stackLayout = new OO.ui.StackLayout( {\n\t\tcontinuous: !!config.continuous,\n\t\texpanded: config.expanded\n\t} );\n\tthis.$content.append( this.stackLayout.$element );\n\tthis.autoFocus = config.autoFocus === undefined || !!config.autoFocus;\n\n\tthis.tabSelectWidget = new OO.ui.TabSelectWidget();\n\tthis.tabPanel = new OO.ui.PanelLayout();\n\tthis.$menu.append( this.tabPanel.$element );\n\n\tthis.toggleMenu( true );\n\n\t// Events\n\tthis.stackLayout.connect( this, { set: 'onStackLayoutSet' } );\n\tthis.tabSelectWidget.connect( this, { select: 'onTabSelectWidgetSelect' } );\n\tif ( this.autoFocus ) {\n\t\t// Event 'focus' does not bubble, but 'focusin' does\n\t\tthis.stackLayout.$element.on( 'focusin', this.onStackLayoutFocus.bind( this ) );\n\t}\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-indexLayout' );\n\tthis.stackLayout.$element.addClass( 'oo-ui-indexLayout-stackLayout' );\n\tthis.tabPanel.$element\n\t\t.addClass( 'oo-ui-indexLayout-tabPanel' )\n\t\t.append( this.tabSelectWidget.$element );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.IndexLayout, OO.ui.MenuLayout );\n\n/* Events */\n\n/**\n * A 'set' event is emitted when a tab panel is {@link #setTabPanel set} to be displayed by the index layout.\n * @event set\n * @param {OO.ui.TabPanelLayout} tabPanel Current tab panel\n */\n\n/**\n * An 'add' event is emitted when tab panels are {@link #addTabPanels added} to the index layout.\n *\n * @event add\n * @param {OO.ui.TabPanelLayout[]} tabPanel Added tab panels\n * @param {number} index Index tab panels were added at\n */\n\n/**\n * A 'remove' event is emitted when tab panels are {@link #clearTabPanels cleared} or\n * {@link #removeTabPanels removed} from the index.\n *\n * @event remove\n * @param {OO.ui.TabPanelLayout[]} tabPanel Removed tab panels\n */\n\n/* Methods */\n\n/**\n * Handle stack layout focus.\n *\n * @private\n * @param {jQuery.Event} e Focusing event\n */\nOO.ui.IndexLayout.prototype.onStackLayoutFocus = function ( e ) {\n\tvar name, $target;\n\n\t// Find the tab panel that an element was focused within\n\t$target = $( e.target ).closest( '.oo-ui-tabPanelLayout' );\n\tfor ( name in this.tabPanels ) {\n\t\t// Check for tab panel match, exclude current tab panel to find only tab panel changes\n\t\tif ( this.tabPanels[ name ].$element[ 0 ] === $target[ 0 ] && name !== this.currentTabPanelName ) {\n\t\t\tthis.setTabPanel( name );\n\t\t\tbreak;\n\t\t}\n\t}\n};\n\n/**\n * Handle stack layout set events.\n *\n * @private\n * @param {OO.ui.PanelLayout|null} tabPanel The tab panel that is now the current panel\n */\nOO.ui.IndexLayout.prototype.onStackLayoutSet = function ( tabPanel ) {\n\tvar layout = this;\n\tif ( tabPanel ) {\n\t\ttabPanel.scrollElementIntoView().done( function () {\n\t\t\tif ( layout.autoFocus && !OO.ui.isMobile() ) {\n\t\t\t\tlayout.focus();\n\t\t\t}\n\t\t} );\n\t}\n};\n\n/**\n * Focus the first input in the current tab panel.\n *\n * If no tab panel is selected, the first selectable tab panel will be selected.\n * If the focus is already in an element on the current tab panel, nothing will happen.\n *\n * @param {number} [itemIndex] A specific item to focus on\n */\nOO.ui.IndexLayout.prototype.focus = function ( itemIndex ) {\n\tvar tabPanel,\n\t\titems = this.stackLayout.getItems();\n\n\tif ( itemIndex !== undefined && items[ itemIndex ] ) {\n\t\ttabPanel = items[ itemIndex ];\n\t} else {\n\t\ttabPanel = this.stackLayout.getCurrentItem();\n\t}\n\n\tif ( !tabPanel ) {\n\t\tthis.selectFirstSelectableTabPanel();\n\t\ttabPanel = this.stackLayout.getCurrentItem();\n\t}\n\tif ( !tabPanel ) {\n\t\treturn;\n\t}\n\t// Only change the focus if is not already in the current page\n\tif ( !OO.ui.contains( tabPanel.$element[ 0 ], this.getElementDocument().activeElement, true ) ) {\n\t\ttabPanel.focus();\n\t}\n};\n\n/**\n * Find the first focusable input in the index layout and focus\n * on it.\n */\nOO.ui.IndexLayout.prototype.focusFirstFocusable = function () {\n\tOO.ui.findFocusable( this.stackLayout.$element ).focus();\n};\n\n/**\n * Handle tab widget select events.\n *\n * @private\n * @param {OO.ui.OptionWidget|null} item Selected item\n */\nOO.ui.IndexLayout.prototype.onTabSelectWidgetSelect = function ( item ) {\n\tif ( item ) {\n\t\tthis.setTabPanel( item.getData() );\n\t}\n};\n\n/**\n * Get the tab panel closest to the specified tab panel.\n *\n * @param {OO.ui.TabPanelLayout} tabPanel Tab panel to use as a reference point\n * @return {OO.ui.TabPanelLayout|null} Tab panel closest to the specified\n */\nOO.ui.IndexLayout.prototype.getClosestTabPanel = function ( tabPanel ) {\n\tvar next, prev, level,\n\t\ttabPanels = this.stackLayout.getItems(),\n\t\tindex = tabPanels.indexOf( tabPanel );\n\n\tif ( index !== -1 ) {\n\t\tnext = tabPanels[ index + 1 ];\n\t\tprev = tabPanels[ index - 1 ];\n\t\t// Prefer adjacent tab panels at the same level\n\t\tlevel = this.tabSelectWidget.getItemFromData( tabPanel.getName() ).getLevel();\n\t\tif (\n\t\t\tprev &&\n\t\t\tlevel === this.tabSelectWidget.getItemFromData( prev.getName() ).getLevel()\n\t\t) {\n\t\t\treturn prev;\n\t\t}\n\t\tif (\n\t\t\tnext &&\n\t\t\tlevel === this.tabSelectWidget.getItemFromData( next.getName() ).getLevel()\n\t\t) {\n\t\t\treturn next;\n\t\t}\n\t}\n\treturn prev || next || null;\n};\n\n/**\n * Get the tabs widget.\n *\n * @return {OO.ui.TabSelectWidget} Tabs widget\n */\nOO.ui.IndexLayout.prototype.getTabs = function () {\n\treturn this.tabSelectWidget;\n};\n\n/**\n * Get a tab panel by its symbolic name.\n *\n * @param {string} name Symbolic name of tab panel\n * @return {OO.ui.TabPanelLayout|undefined} Tab panel, if found\n */\nOO.ui.IndexLayout.prototype.getTabPanel = function ( name ) {\n\treturn this.tabPanels[ name ];\n};\n\n/**\n * Get the current tab panel.\n *\n * @return {OO.ui.TabPanelLayout|undefined} Current tab panel, if found\n */\nOO.ui.IndexLayout.prototype.getCurrentTabPanel = function () {\n\tvar name = this.getCurrentTabPanelName();\n\treturn name ? this.getTabPanel( name ) : undefined;\n};\n\n/**\n * Get the symbolic name of the current tab panel.\n *\n * @return {string|null} Symbolic name of the current tab panel\n */\nOO.ui.IndexLayout.prototype.getCurrentTabPanelName = function () {\n\treturn this.currentTabPanelName;\n};\n\n/**\n * Add tab panels to the index layout\n *\n * When tab panels are added with the same names as existing tab panels, the existing tab panels\n * will be automatically removed before the new tab panels are added.\n *\n * @param {OO.ui.TabPanelLayout[]} tabPanels Tab panels to add\n * @param {number} index Index of the insertion point\n * @fires add\n * @chainable\n */\nOO.ui.IndexLayout.prototype.addTabPanels = function ( tabPanels, index ) {\n\tvar i, len, name, tabPanel, item, currentIndex,\n\t\tstackLayoutTabPanels = this.stackLayout.getItems(),\n\t\tremove = [],\n\t\titems = [];\n\n\t// Remove tab panels with same names\n\tfor ( i = 0, len = tabPanels.length; i < len; i++ ) {\n\t\ttabPanel = tabPanels[ i ];\n\t\tname = tabPanel.getName();\n\n\t\tif ( Object.prototype.hasOwnProperty.call( this.tabPanels, name ) ) {\n\t\t\t// Correct the insertion index\n\t\t\tcurrentIndex = stackLayoutTabPanels.indexOf( this.tabPanels[ name ] );\n\t\t\tif ( currentIndex !== -1 && currentIndex + 1 < index ) {\n\t\t\t\tindex--;\n\t\t\t}\n\t\t\tremove.push( this.tabPanels[ name ] );\n\t\t}\n\t}\n\tif ( remove.length ) {\n\t\tthis.removeTabPanels( remove );\n\t}\n\n\t// Add new tab panels\n\tfor ( i = 0, len = tabPanels.length; i < len; i++ ) {\n\t\ttabPanel = tabPanels[ i ];\n\t\tname = tabPanel.getName();\n\t\tthis.tabPanels[ tabPanel.getName() ] = tabPanel;\n\t\titem = new OO.ui.TabOptionWidget( { data: name } );\n\t\ttabPanel.setTabItem( item );\n\t\titems.push( item );\n\t}\n\n\tif ( items.length ) {\n\t\tthis.tabSelectWidget.addItems( items, index );\n\t\tthis.selectFirstSelectableTabPanel();\n\t}\n\tthis.stackLayout.addItems( tabPanels, index );\n\tthis.emit( 'add', tabPanels, index );\n\n\treturn this;\n};\n\n/**\n * Remove the specified tab panels from the index layout.\n *\n * To remove all tab panels from the index, you may wish to use the #clearTabPanels method instead.\n *\n * @param {OO.ui.TabPanelLayout[]} tabPanels An array of tab panels to remove\n * @fires remove\n * @chainable\n */\nOO.ui.IndexLayout.prototype.removeTabPanels = function ( tabPanels ) {\n\tvar i, len, name, tabPanel,\n\t\titems = [];\n\n\tfor ( i = 0, len = tabPanels.length; i < len; i++ ) {\n\t\ttabPanel = tabPanels[ i ];\n\t\tname = tabPanel.getName();\n\t\tdelete this.tabPanels[ name ];\n\t\titems.push( this.tabSelectWidget.getItemFromData( name ) );\n\t\ttabPanel.setTabItem( null );\n\t}\n\tif ( items.length ) {\n\t\tthis.tabSelectWidget.removeItems( items );\n\t\tthis.selectFirstSelectableTabPanel();\n\t}\n\tthis.stackLayout.removeItems( tabPanels );\n\tthis.emit( 'remove', tabPanels );\n\n\treturn this;\n};\n\n/**\n * Clear all tab panels from the index layout.\n *\n * To remove only a subset of tab panels from the index, use the #removeTabPanels method.\n *\n * @fires remove\n * @chainable\n */\nOO.ui.IndexLayout.prototype.clearTabPanels = function () {\n\tvar i, len,\n\t\ttabPanels = this.stackLayout.getItems();\n\n\tthis.tabPanels = {};\n\tthis.currentTabPanelName = null;\n\tthis.tabSelectWidget.clearItems();\n\tfor ( i = 0, len = tabPanels.length; i < len; i++ ) {\n\t\ttabPanels[ i ].setTabItem( null );\n\t}\n\tthis.stackLayout.clearItems();\n\n\tthis.emit( 'remove', tabPanels );\n\n\treturn this;\n};\n\n/**\n * Set the current tab panel by symbolic name.\n *\n * @fires set\n * @param {string} name Symbolic name of tab panel\n */\nOO.ui.IndexLayout.prototype.setTabPanel = function ( name ) {\n\tvar selectedItem,\n\t\t$focused,\n\t\ttabPanel = this.tabPanels[ name ],\n\t\tpreviousTabPanel = this.currentTabPanelName && this.tabPanels[ this.currentTabPanelName ];\n\n\tif ( name !== this.currentTabPanelName ) {\n\t\tselectedItem = this.tabSelectWidget.getSelectedItem();\n\t\tif ( selectedItem && selectedItem.getData() !== name ) {\n\t\t\tthis.tabSelectWidget.selectItemByData( name );\n\t\t}\n\t\tif ( tabPanel ) {\n\t\t\tif ( previousTabPanel ) {\n\t\t\t\tpreviousTabPanel.setActive( false );\n\t\t\t\t// Blur anything focused if the next tab panel doesn't have anything focusable.\n\t\t\t\t// This is not needed if the next tab panel has something focusable (because once it is focused\n\t\t\t\t// this blur happens automatically). If the layout is non-continuous, this check is\n\t\t\t\t// meaningless because the next tab panel is not visible yet and thus can't hold focus.\n\t\t\t\tif (\n\t\t\t\t\tthis.autoFocus &&\n\t\t\t\t\t!OO.ui.isMobile() &&\n\t\t\t\t\tthis.stackLayout.continuous &&\n\t\t\t\t\tOO.ui.findFocusable( tabPanel.$element ).length !== 0\n\t\t\t\t) {\n\t\t\t\t\t$focused = previousTabPanel.$element.find( ':focus' );\n\t\t\t\t\tif ( $focused.length ) {\n\t\t\t\t\t\t$focused[ 0 ].blur();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.currentTabPanelName = name;\n\t\t\ttabPanel.setActive( true );\n\t\t\tthis.stackLayout.setItem( tabPanel );\n\t\t\tif ( !this.stackLayout.continuous && previousTabPanel ) {\n\t\t\t\t// This should not be necessary, since any inputs on the previous tab panel should have been\n\t\t\t\t// blurred when it was hidden, but browsers are not very consistent about this.\n\t\t\t\t$focused = previousTabPanel.$element.find( ':focus' );\n\t\t\t\tif ( $focused.length ) {\n\t\t\t\t\t$focused[ 0 ].blur();\n\t\t\t\t}\n\t\t\t}\n\t\t\tthis.emit( 'set', tabPanel );\n\t\t}\n\t}\n};\n\n/**\n * Select the first selectable tab panel.\n *\n * @chainable\n */\nOO.ui.IndexLayout.prototype.selectFirstSelectableTabPanel = function () {\n\tif ( !this.tabSelectWidget.getSelectedItem() ) {\n\t\tthis.tabSelectWidget.selectItem( this.tabSelectWidget.getFirstSelectableItem() );\n\t}\n\n\treturn this;\n};\n","/**\n * ToggleWidget implements basic behavior of widgets with an on/off state.\n * Please see OO.ui.ToggleButtonWidget and OO.ui.ToggleSwitchWidget for examples.\n *\n * @abstract\n * @class\n * @extends OO.ui.Widget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [value=false] The toggle’s initial on/off state.\n * By default, the toggle is in the 'off' state.\n */\nOO.ui.ToggleWidget = function OoUiToggleWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.ToggleWidget.parent.call( this, config );\n\n\t// Properties\n\tthis.value = null;\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-toggleWidget' );\n\tthis.setValue( !!config.value );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ToggleWidget, OO.ui.Widget );\n\n/* Events */\n\n/**\n * @event change\n *\n * A change event is emitted when the on/off state of the toggle changes.\n *\n * @param {boolean} value Value representing the new state of the toggle\n */\n\n/* Methods */\n\n/**\n * Get the value representing the toggle’s state.\n *\n * @return {boolean} The on/off state of the toggle\n */\nOO.ui.ToggleWidget.prototype.getValue = function () {\n\treturn this.value;\n};\n\n/**\n * Set the state of the toggle: `true` for 'on', `false` for 'off'.\n *\n * @param {boolean} value The state of the toggle\n * @fires change\n * @chainable\n */\nOO.ui.ToggleWidget.prototype.setValue = function ( value ) {\n\tvalue = !!value;\n\tif ( this.value !== value ) {\n\t\tthis.value = value;\n\t\tthis.emit( 'change', value );\n\t\tthis.$element.toggleClass( 'oo-ui-toggleWidget-on', value );\n\t\tthis.$element.toggleClass( 'oo-ui-toggleWidget-off', !value );\n\t}\n\treturn this;\n};\n","/**\n * ToggleButtons are buttons that have a state (‘on’ or ‘off’) that is represented by a\n * Boolean value. Like other {@link OO.ui.ButtonWidget buttons}, toggle buttons can be\n * configured with {@link OO.ui.mixin.IconElement icons}, {@link OO.ui.mixin.IndicatorElement indicators},\n * {@link OO.ui.mixin.TitledElement titles}, {@link OO.ui.mixin.FlaggedElement styling flags},\n * and {@link OO.ui.mixin.LabelElement labels}. Please see\n * the [OOjs UI documentation][1] on MediaWiki for more information.\n *\n * @example\n * // Toggle buttons in the 'off' and 'on' state.\n * var toggleButton1 = new OO.ui.ToggleButtonWidget( {\n * label: 'Toggle Button off'\n * } );\n * var toggleButton2 = new OO.ui.ToggleButtonWidget( {\n * label: 'Toggle Button on',\n * value: true\n * } );\n * // Append the buttons to the DOM.\n * $( 'body' ).append( toggleButton1.$element, toggleButton2.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Buttons_and_Switches#Toggle_buttons\n *\n * @class\n * @extends OO.ui.ToggleWidget\n * @mixins OO.ui.mixin.ButtonElement\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.IndicatorElement\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.TitledElement\n * @mixins OO.ui.mixin.FlaggedElement\n * @mixins OO.ui.mixin.TabIndexedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [value=false] The toggle button’s initial on/off\n * state. By default, the button is in the 'off' state.\n */\nOO.ui.ToggleButtonWidget = function OoUiToggleButtonWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.ToggleButtonWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.ButtonElement.call( this, $.extend( {}, config, { active: this.active } ) );\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.IndicatorElement.call( this, config );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\tOO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$button } ) );\n\tOO.ui.mixin.FlaggedElement.call( this, config );\n\tOO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$button } ) );\n\n\t// Events\n\tthis.connect( this, { click: 'onAction' } );\n\n\t// Initialization\n\tthis.$button.append( this.$icon, this.$label, this.$indicator );\n\tthis.$element\n\t\t.addClass( 'oo-ui-toggleButtonWidget' )\n\t\t.append( this.$button );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ToggleButtonWidget, OO.ui.ToggleWidget );\nOO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.ButtonElement );\nOO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.IndicatorElement );\nOO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.TitledElement );\nOO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.FlaggedElement );\nOO.mixinClass( OO.ui.ToggleButtonWidget, OO.ui.mixin.TabIndexedElement );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.ToggleButtonWidget.static.tagName = 'span';\n\n/* Methods */\n\n/**\n * Handle the button action being triggered.\n *\n * @private\n */\nOO.ui.ToggleButtonWidget.prototype.onAction = function () {\n\tthis.setValue( !this.value );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ToggleButtonWidget.prototype.setValue = function ( value ) {\n\tvalue = !!value;\n\tif ( value !== this.value ) {\n\t\t// Might be called from parent constructor before ButtonElement constructor\n\t\tif ( this.$button ) {\n\t\t\tthis.$button.attr( 'aria-pressed', value.toString() );\n\t\t}\n\t\tthis.setActive( value );\n\t}\n\n\t// Parent method\n\tOO.ui.ToggleButtonWidget.parent.prototype.setValue.call( this, value );\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ToggleButtonWidget.prototype.setButtonElement = function ( $button ) {\n\tif ( this.$button ) {\n\t\tthis.$button.removeAttr( 'aria-pressed' );\n\t}\n\tOO.ui.mixin.ButtonElement.prototype.setButtonElement.call( this, $button );\n\tthis.$button.attr( 'aria-pressed', this.value.toString() );\n};\n","/**\n * ToggleSwitches are switches that slide on and off. Their state is represented by a Boolean\n * value (`true` for ‘on’, and `false` otherwise, the default). The ‘off’ state is represented\n * visually by a slider in the leftmost position.\n *\n * @example\n * // Toggle switches in the 'off' and 'on' position.\n * var toggleSwitch1 = new OO.ui.ToggleSwitchWidget();\n * var toggleSwitch2 = new OO.ui.ToggleSwitchWidget( {\n * value: true\n * } );\n *\n * // Create a FieldsetLayout to layout and label switches\n * var fieldset = new OO.ui.FieldsetLayout( {\n * label: 'Toggle switches'\n * } );\n * fieldset.addItems( [\n * new OO.ui.FieldLayout( toggleSwitch1, { label: 'Off', align: 'top' } ),\n * new OO.ui.FieldLayout( toggleSwitch2, { label: 'On', align: 'top' } )\n * ] );\n * $( 'body' ).append( fieldset.$element );\n *\n * @class\n * @extends OO.ui.ToggleWidget\n * @mixins OO.ui.mixin.TabIndexedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [value=false] The toggle switch’s initial on/off state.\n * By default, the toggle switch is in the 'off' position.\n */\nOO.ui.ToggleSwitchWidget = function OoUiToggleSwitchWidget( config ) {\n\t// Parent constructor\n\tOO.ui.ToggleSwitchWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.TabIndexedElement.call( this, config );\n\n\t// Properties\n\tthis.dragging = false;\n\tthis.dragStart = null;\n\tthis.sliding = false;\n\tthis.$glow = $( '<span>' );\n\tthis.$grip = $( '<span>' );\n\n\t// Events\n\tthis.$element.on( {\n\t\tclick: this.onClick.bind( this ),\n\t\tkeypress: this.onKeyPress.bind( this )\n\t} );\n\n\t// Initialization\n\tthis.$glow.addClass( 'oo-ui-toggleSwitchWidget-glow' );\n\tthis.$grip.addClass( 'oo-ui-toggleSwitchWidget-grip' );\n\tthis.$element\n\t\t.addClass( 'oo-ui-toggleSwitchWidget' )\n\t\t.attr( 'role', 'checkbox' )\n\t\t.append( this.$glow, this.$grip );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ToggleSwitchWidget, OO.ui.ToggleWidget );\nOO.mixinClass( OO.ui.ToggleSwitchWidget, OO.ui.mixin.TabIndexedElement );\n\n/* Methods */\n\n/**\n * Handle mouse click events.\n *\n * @private\n * @param {jQuery.Event} e Mouse click event\n */\nOO.ui.ToggleSwitchWidget.prototype.onClick = function ( e ) {\n\tif ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {\n\t\tthis.setValue( !this.value );\n\t}\n\treturn false;\n};\n\n/**\n * Handle key press events.\n *\n * @private\n * @param {jQuery.Event} e Key press event\n */\nOO.ui.ToggleSwitchWidget.prototype.onKeyPress = function ( e ) {\n\tif ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) {\n\t\tthis.setValue( !this.value );\n\t\treturn false;\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ToggleSwitchWidget.prototype.setValue = function ( value ) {\n\tOO.ui.ToggleSwitchWidget.parent.prototype.setValue.call( this, value );\n\tthis.$element.attr( 'aria-checked', this.value.toString() );\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ToggleSwitchWidget.prototype.simulateLabelClick = function () {\n\tif ( !this.isDisabled() ) {\n\t\tthis.setValue( !this.value );\n\t}\n\tthis.focus();\n};\n","/**\n * OutlineControlsWidget is a set of controls for an {@link OO.ui.OutlineSelectWidget outline select widget}.\n * Controls include moving items up and down, removing items, and adding different kinds of items.\n *\n * **Currently, this class is only used by {@link OO.ui.BookletLayout booklet layouts}.**\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.GroupElement\n * @mixins OO.ui.mixin.IconElement\n *\n * @constructor\n * @param {OO.ui.OutlineSelectWidget} outline Outline to control\n * @param {Object} [config] Configuration options\n * @cfg {Object} [abilities] List of abilties\n * @cfg {boolean} [abilities.move=true] Allow moving movable items\n * @cfg {boolean} [abilities.remove=true] Allow removing removable items\n */\nOO.ui.OutlineControlsWidget = function OoUiOutlineControlsWidget( outline, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( outline ) && config === undefined ) {\n\t\tconfig = outline;\n\t\toutline = config.outline;\n\t}\n\n\t// Configuration initialization\n\tconfig = $.extend( { icon: 'add' }, config );\n\n\t// Parent constructor\n\tOO.ui.OutlineControlsWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.GroupElement.call( this, config );\n\tOO.ui.mixin.IconElement.call( this, config );\n\n\t// Properties\n\tthis.outline = outline;\n\tthis.$movers = $( '<div>' );\n\tthis.upButton = new OO.ui.ButtonWidget( {\n\t\tframed: false,\n\t\ticon: 'collapse',\n\t\ttitle: OO.ui.msg( 'ooui-outline-control-move-up' )\n\t} );\n\tthis.downButton = new OO.ui.ButtonWidget( {\n\t\tframed: false,\n\t\ticon: 'expand',\n\t\ttitle: OO.ui.msg( 'ooui-outline-control-move-down' )\n\t} );\n\tthis.removeButton = new OO.ui.ButtonWidget( {\n\t\tframed: false,\n\t\ticon: 'trash',\n\t\ttitle: OO.ui.msg( 'ooui-outline-control-remove' )\n\t} );\n\tthis.abilities = { move: true, remove: true };\n\n\t// Events\n\toutline.connect( this, {\n\t\tselect: 'onOutlineChange',\n\t\tadd: 'onOutlineChange',\n\t\tremove: 'onOutlineChange'\n\t} );\n\tthis.upButton.connect( this, { click: [ 'emit', 'move', -1 ] } );\n\tthis.downButton.connect( this, { click: [ 'emit', 'move', 1 ] } );\n\tthis.removeButton.connect( this, { click: [ 'emit', 'remove' ] } );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-outlineControlsWidget' );\n\tthis.$group.addClass( 'oo-ui-outlineControlsWidget-items' );\n\tthis.$movers\n\t\t.addClass( 'oo-ui-outlineControlsWidget-movers' )\n\t\t.append( this.removeButton.$element, this.upButton.$element, this.downButton.$element );\n\tthis.$element.append( this.$icon, this.$group, this.$movers );\n\tthis.setAbilities( config.abilities || {} );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.OutlineControlsWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.mixin.GroupElement );\nOO.mixinClass( OO.ui.OutlineControlsWidget, OO.ui.mixin.IconElement );\n\n/* Events */\n\n/**\n * @event move\n * @param {number} places Number of places to move\n */\n\n/**\n * @event remove\n */\n\n/* Methods */\n\n/**\n * Set abilities.\n *\n * @param {Object} abilities List of abilties\n * @param {boolean} [abilities.move] Allow moving movable items\n * @param {boolean} [abilities.remove] Allow removing removable items\n */\nOO.ui.OutlineControlsWidget.prototype.setAbilities = function ( abilities ) {\n\tvar ability;\n\n\tfor ( ability in this.abilities ) {\n\t\tif ( abilities[ ability ] !== undefined ) {\n\t\t\tthis.abilities[ ability ] = !!abilities[ ability ];\n\t\t}\n\t}\n\n\tthis.onOutlineChange();\n};\n\n/**\n * Handle outline change events.\n *\n * @private\n */\nOO.ui.OutlineControlsWidget.prototype.onOutlineChange = function () {\n\tvar i, len, firstMovable, lastMovable,\n\t\titems = this.outline.getItems(),\n\t\tselectedItem = this.outline.getSelectedItem(),\n\t\tmovable = this.abilities.move && selectedItem && selectedItem.isMovable(),\n\t\tremovable = this.abilities.remove && selectedItem && selectedItem.isRemovable();\n\n\tif ( movable ) {\n\t\ti = -1;\n\t\tlen = items.length;\n\t\twhile ( ++i < len ) {\n\t\t\tif ( items[ i ].isMovable() ) {\n\t\t\t\tfirstMovable = items[ i ];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\ti = len;\n\t\twhile ( i-- ) {\n\t\t\tif ( items[ i ].isMovable() ) {\n\t\t\t\tlastMovable = items[ i ];\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\tthis.upButton.setDisabled( !movable || selectedItem === firstMovable );\n\tthis.downButton.setDisabled( !movable || selectedItem === lastMovable );\n\tthis.removeButton.setDisabled( !removable );\n};\n","/**\n * OutlineOptionWidget is an item in an {@link OO.ui.OutlineSelectWidget OutlineSelectWidget}.\n *\n * Currently, this class is only used by {@link OO.ui.BookletLayout booklet layouts}, which contain\n * {@link OO.ui.PageLayout page layouts}. See {@link OO.ui.BookletLayout BookletLayout}\n * for an example.\n *\n * @class\n * @extends OO.ui.DecoratedOptionWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {number} [level] Indentation level\n * @cfg {boolean} [movable] Allow modification from {@link OO.ui.OutlineControlsWidget outline controls}.\n */\nOO.ui.OutlineOptionWidget = function OoUiOutlineOptionWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.OutlineOptionWidget.parent.call( this, config );\n\n\t// Properties\n\tthis.level = 0;\n\tthis.movable = !!config.movable;\n\tthis.removable = !!config.removable;\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-outlineOptionWidget' );\n\tthis.setLevel( config.level );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.OutlineOptionWidget, OO.ui.DecoratedOptionWidget );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.OutlineOptionWidget.static.highlightable = true;\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.OutlineOptionWidget.static.scrollIntoViewOnSelect = true;\n\n/**\n * @static\n * @inheritable\n * @property {string}\n */\nOO.ui.OutlineOptionWidget.static.levelClass = 'oo-ui-outlineOptionWidget-level-';\n\n/**\n * @static\n * @inheritable\n * @property {number}\n */\nOO.ui.OutlineOptionWidget.static.levels = 3;\n\n/* Methods */\n\n/**\n * Check if item is movable.\n *\n * Movability is used by {@link OO.ui.OutlineControlsWidget outline controls}.\n *\n * @return {boolean} Item is movable\n */\nOO.ui.OutlineOptionWidget.prototype.isMovable = function () {\n\treturn this.movable;\n};\n\n/**\n * Check if item is removable.\n *\n * Removability is used by {@link OO.ui.OutlineControlsWidget outline controls}.\n *\n * @return {boolean} Item is removable\n */\nOO.ui.OutlineOptionWidget.prototype.isRemovable = function () {\n\treturn this.removable;\n};\n\n/**\n * Get indentation level.\n *\n * @return {number} Indentation level\n */\nOO.ui.OutlineOptionWidget.prototype.getLevel = function () {\n\treturn this.level;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.OutlineOptionWidget.prototype.setPressed = function ( state ) {\n\tOO.ui.OutlineOptionWidget.parent.prototype.setPressed.call( this, state );\n\tif ( this.pressed ) {\n\t\tthis.setFlags( { progressive: true } );\n\t} else if ( !this.selected ) {\n\t\tthis.setFlags( { progressive: false } );\n\t}\n\treturn this;\n};\n\n/**\n * Set movability.\n *\n * Movability is used by {@link OO.ui.OutlineControlsWidget outline controls}.\n *\n * @param {boolean} movable Item is movable\n * @chainable\n */\nOO.ui.OutlineOptionWidget.prototype.setMovable = function ( movable ) {\n\tthis.movable = !!movable;\n\tthis.updateThemeClasses();\n\treturn this;\n};\n\n/**\n * Set removability.\n *\n * Removability is used by {@link OO.ui.OutlineControlsWidget outline controls}.\n *\n * @param {boolean} removable Item is removable\n * @chainable\n */\nOO.ui.OutlineOptionWidget.prototype.setRemovable = function ( removable ) {\n\tthis.removable = !!removable;\n\tthis.updateThemeClasses();\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.OutlineOptionWidget.prototype.setSelected = function ( state ) {\n\tOO.ui.OutlineOptionWidget.parent.prototype.setSelected.call( this, state );\n\tif ( this.selected ) {\n\t\tthis.setFlags( { progressive: true } );\n\t} else {\n\t\tthis.setFlags( { progressive: false } );\n\t}\n\treturn this;\n};\n\n/**\n * Set indentation level.\n *\n * @param {number} [level=0] Indentation level, in the range of [0,#maxLevel]\n * @chainable\n */\nOO.ui.OutlineOptionWidget.prototype.setLevel = function ( level ) {\n\tvar levels = this.constructor.static.levels,\n\t\tlevelClass = this.constructor.static.levelClass,\n\t\ti = levels;\n\n\tthis.level = level ? Math.max( 0, Math.min( levels - 1, level ) ) : 0;\n\twhile ( i-- ) {\n\t\tif ( this.level === i ) {\n\t\t\tthis.$element.addClass( levelClass + i );\n\t\t} else {\n\t\t\tthis.$element.removeClass( levelClass + i );\n\t\t}\n\t}\n\tthis.updateThemeClasses();\n\n\treturn this;\n};\n","/**\n * OutlineSelectWidget is a structured list that contains {@link OO.ui.OutlineOptionWidget outline options}\n * A set of controls can be provided with an {@link OO.ui.OutlineControlsWidget outline controls} widget.\n *\n * **Currently, this class is only used by {@link OO.ui.BookletLayout booklet layouts}.**\n *\n * @class\n * @extends OO.ui.SelectWidget\n * @mixins OO.ui.mixin.TabIndexedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.OutlineSelectWidget = function OoUiOutlineSelectWidget( config ) {\n\t// Parent constructor\n\tOO.ui.OutlineSelectWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.TabIndexedElement.call( this, config );\n\n\t// Events\n\tthis.$element.on( {\n\t\tfocus: this.bindKeyDownListener.bind( this ),\n\t\tblur: this.unbindKeyDownListener.bind( this )\n\t} );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-outlineSelectWidget' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.OutlineSelectWidget, OO.ui.SelectWidget );\nOO.mixinClass( OO.ui.OutlineSelectWidget, OO.ui.mixin.TabIndexedElement );\n","/**\n * ButtonOptionWidget is a special type of {@link OO.ui.mixin.ButtonElement button element} that\n * can be selected and configured with data. The class is\n * used with OO.ui.ButtonSelectWidget to create a selection of button options. Please see the\n * [OOjs UI documentation on MediaWiki] [1] for more information.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Button_selects_and_options\n *\n * @class\n * @extends OO.ui.OptionWidget\n * @mixins OO.ui.mixin.ButtonElement\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.IndicatorElement\n * @mixins OO.ui.mixin.TitledElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.ButtonOptionWidget = function OoUiButtonOptionWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.ButtonOptionWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.ButtonElement.call( this, config );\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.IndicatorElement.call( this, config );\n\tOO.ui.mixin.TitledElement.call( this, $.extend( {}, config, { $titled: this.$button } ) );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-buttonOptionWidget' );\n\tthis.$button.append( this.$icon, this.$label, this.$indicator );\n\tthis.$element.append( this.$button );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ButtonOptionWidget, OO.ui.OptionWidget );\nOO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.ButtonElement );\nOO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.IndicatorElement );\nOO.mixinClass( OO.ui.ButtonOptionWidget, OO.ui.mixin.TitledElement );\n\n/* Static Properties */\n\n/**\n * Allow button mouse down events to pass through so they can be handled by the parent select widget\n *\n * @static\n * @inheritdoc\n */\nOO.ui.ButtonOptionWidget.static.cancelButtonMouseDownEvents = false;\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.ButtonOptionWidget.static.highlightable = false;\n\n/* Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.ButtonOptionWidget.prototype.setSelected = function ( state ) {\n\tOO.ui.ButtonOptionWidget.parent.prototype.setSelected.call( this, state );\n\n\tif ( this.constructor.static.selectable ) {\n\t\tthis.setActive( state );\n\t}\n\n\treturn this;\n};\n","/**\n * ButtonSelectWidget is a {@link OO.ui.SelectWidget select widget} that contains\n * button options and is used together with\n * OO.ui.ButtonOptionWidget. The ButtonSelectWidget provides an interface for\n * highlighting, choosing, and selecting mutually exclusive options. Please see\n * the [OOjs UI documentation on MediaWiki] [1] for more information.\n *\n * @example\n * // Example: A ButtonSelectWidget that contains three ButtonOptionWidgets\n * var option1 = new OO.ui.ButtonOptionWidget( {\n * data: 1,\n * label: 'Option 1',\n * title: 'Button option 1'\n * } );\n *\n * var option2 = new OO.ui.ButtonOptionWidget( {\n * data: 2,\n * label: 'Option 2',\n * title: 'Button option 2'\n * } );\n *\n * var option3 = new OO.ui.ButtonOptionWidget( {\n * data: 3,\n * label: 'Option 3',\n * title: 'Button option 3'\n * } );\n *\n * var buttonSelect=new OO.ui.ButtonSelectWidget( {\n * items: [ option1, option2, option3 ]\n * } );\n * $( 'body' ).append( buttonSelect.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options\n *\n * @class\n * @extends OO.ui.SelectWidget\n * @mixins OO.ui.mixin.TabIndexedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.ButtonSelectWidget = function OoUiButtonSelectWidget( config ) {\n\t// Parent constructor\n\tOO.ui.ButtonSelectWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.TabIndexedElement.call( this, config );\n\n\t// Events\n\tthis.$element.on( {\n\t\tfocus: this.bindKeyDownListener.bind( this ),\n\t\tblur: this.unbindKeyDownListener.bind( this )\n\t} );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-buttonSelectWidget' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ButtonSelectWidget, OO.ui.SelectWidget );\nOO.mixinClass( OO.ui.ButtonSelectWidget, OO.ui.mixin.TabIndexedElement );\n","/**\n * TabOptionWidget is an item in a {@link OO.ui.TabSelectWidget TabSelectWidget}.\n *\n * Currently, this class is only used by {@link OO.ui.IndexLayout index layouts}, which contain\n * {@link OO.ui.TabPanelLayout tab panel layouts}. See {@link OO.ui.IndexLayout IndexLayout}\n * for an example.\n *\n * @class\n * @extends OO.ui.OptionWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.TabOptionWidget = function OoUiTabOptionWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.TabOptionWidget.parent.call( this, config );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-tabOptionWidget' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.TabOptionWidget, OO.ui.OptionWidget );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.TabOptionWidget.static.highlightable = false;\n","/**\n * TabSelectWidget is a list that contains {@link OO.ui.TabOptionWidget tab options}\n *\n * **Currently, this class is only used by {@link OO.ui.IndexLayout index layouts}.**\n *\n * @class\n * @extends OO.ui.SelectWidget\n * @mixins OO.ui.mixin.TabIndexedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.TabSelectWidget = function OoUiTabSelectWidget( config ) {\n\t// Parent constructor\n\tOO.ui.TabSelectWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.TabIndexedElement.call( this, config );\n\n\t// Events\n\tthis.$element.on( {\n\t\tfocus: this.bindKeyDownListener.bind( this ),\n\t\tblur: this.unbindKeyDownListener.bind( this )\n\t} );\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-tabSelectWidget' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.TabSelectWidget, OO.ui.SelectWidget );\nOO.mixinClass( OO.ui.TabSelectWidget, OO.ui.mixin.TabIndexedElement );\n","/**\n * CapsuleItemWidgets are used within a {@link OO.ui.CapsuleMultiselectWidget\n * CapsuleMultiselectWidget} to display the selected items.\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.ItemWidget\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.FlaggedElement\n * @mixins OO.ui.mixin.TabIndexedElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.CapsuleItemWidget = function OoUiCapsuleItemWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.CapsuleItemWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.ItemWidget.call( this );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\tOO.ui.mixin.FlaggedElement.call( this, config );\n\tOO.ui.mixin.TabIndexedElement.call( this, config );\n\n\t// Events\n\tthis.closeButton = new OO.ui.ButtonWidget( {\n\t\tframed: false,\n\t\ticon: 'close',\n\t\ttabIndex: -1,\n\t\ttitle: OO.ui.msg( 'ooui-item-remove' )\n\t} ).on( 'click', this.onCloseClick.bind( this ) );\n\n\tthis.on( 'disable', function ( disabled ) {\n\t\tthis.closeButton.setDisabled( disabled );\n\t}.bind( this ) );\n\n\t// Initialization\n\tthis.$element\n\t\t.on( {\n\t\t\tclick: this.onClick.bind( this ),\n\t\t\tkeydown: this.onKeyDown.bind( this )\n\t\t} )\n\t\t.addClass( 'oo-ui-capsuleItemWidget' )\n\t\t.append( this.$label, this.closeButton.$element );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.CapsuleItemWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.CapsuleItemWidget, OO.ui.mixin.ItemWidget );\nOO.mixinClass( OO.ui.CapsuleItemWidget, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.CapsuleItemWidget, OO.ui.mixin.FlaggedElement );\nOO.mixinClass( OO.ui.CapsuleItemWidget, OO.ui.mixin.TabIndexedElement );\n\n/* Methods */\n\n/**\n * Handle close icon clicks\n */\nOO.ui.CapsuleItemWidget.prototype.onCloseClick = function () {\n\tvar element = this.getElementGroup();\n\n\tif ( element && $.isFunction( element.removeItems ) ) {\n\t\telement.removeItems( [ this ] );\n\t\telement.focus();\n\t}\n};\n\n/**\n * Handle click event for the entire capsule\n */\nOO.ui.CapsuleItemWidget.prototype.onClick = function () {\n\tvar element = this.getElementGroup();\n\n\tif ( !this.isDisabled() && element && $.isFunction( element.editItem ) ) {\n\t\telement.editItem( this );\n\t}\n};\n\n/**\n * Handle keyDown event for the entire capsule\n *\n * @param {jQuery.Event} e Key down event\n */\nOO.ui.CapsuleItemWidget.prototype.onKeyDown = function ( e ) {\n\tvar element = this.getElementGroup();\n\n\tif ( e.keyCode === OO.ui.Keys.BACKSPACE || e.keyCode === OO.ui.Keys.DELETE ) {\n\t\telement.removeItems( [ this ] );\n\t\telement.focus();\n\t\treturn false;\n\t} else if ( e.keyCode === OO.ui.Keys.ENTER ) {\n\t\telement.editItem( this );\n\t\treturn false;\n\t} else if ( e.keyCode === OO.ui.Keys.LEFT ) {\n\t\telement.getPreviousItem( this ).focus();\n\t} else if ( e.keyCode === OO.ui.Keys.RIGHT ) {\n\t\telement.getNextItem( this ).focus();\n\t}\n};\n","/**\n * CapsuleMultiselectWidgets are something like a {@link OO.ui.ComboBoxInputWidget combo box widget}\n * that allows for selecting multiple values.\n *\n * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * @example\n * // Example: A CapsuleMultiselectWidget.\n * var capsule = new OO.ui.CapsuleMultiselectWidget( {\n * label: 'CapsuleMultiselectWidget',\n * selected: [ 'Option 1', 'Option 3' ],\n * menu: {\n * items: [\n * new OO.ui.MenuOptionWidget( {\n * data: 'Option 1',\n * label: 'Option One'\n * } ),\n * new OO.ui.MenuOptionWidget( {\n * data: 'Option 2',\n * label: 'Option Two'\n * } ),\n * new OO.ui.MenuOptionWidget( {\n * data: 'Option 3',\n * label: 'Option Three'\n * } ),\n * new OO.ui.MenuOptionWidget( {\n * data: 'Option 4',\n * label: 'Option Four'\n * } ),\n * new OO.ui.MenuOptionWidget( {\n * data: 'Option 5',\n * label: 'Option Five'\n * } )\n * ]\n * }\n * } );\n * $( 'body' ).append( capsule.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.GroupElement\n * @mixins OO.ui.mixin.PopupElement\n * @mixins OO.ui.mixin.TabIndexedElement\n * @mixins OO.ui.mixin.IndicatorElement\n * @mixins OO.ui.mixin.IconElement\n * @uses OO.ui.CapsuleItemWidget\n * @uses OO.ui.MenuSelectWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string} [placeholder] Placeholder text\n * @cfg {boolean} [allowArbitrary=false] Allow data items to be added even if not present in the menu.\n * @cfg {boolean} [allowDuplicates=false] Allow duplicate items to be added.\n * @cfg {Object} [menu] (required) Configuration options to pass to the\n * {@link OO.ui.MenuSelectWidget menu select widget}.\n * @cfg {Object} [popup] Configuration options to pass to the {@link OO.ui.PopupWidget popup widget}.\n * If specified, this popup will be shown instead of the menu (but the menu\n * will still be used for item labels and allowArbitrary=false). The widgets\n * in the popup should use {@link #addItemsFromData} or {@link #addItems} as necessary.\n * @cfg {jQuery} [$overlay=this.$element] Render the menu or popup into a separate layer.\n * This configuration is useful in cases where the expanded menu is larger than\n * its containing `<div>`. The specified overlay layer is usually on top of\n * the containing `<div>` and has a larger area. By default, the menu uses\n * relative positioning.\n * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.\n */\nOO.ui.CapsuleMultiselectWidget = function OoUiCapsuleMultiselectWidget( config ) {\n\tvar $tabFocus;\n\n\t// Parent constructor\n\tOO.ui.CapsuleMultiselectWidget.parent.call( this, config );\n\n\t// Configuration initialization\n\tconfig = $.extend( {\n\t\tallowArbitrary: false,\n\t\tallowDuplicates: false,\n\t\t$overlay: this.$element\n\t}, config );\n\n\t// Properties (must be set before mixin constructor calls)\n\tthis.$handle = $( '<div>' );\n\tthis.$input = config.popup ? null : $( '<input>' );\n\tif ( config.placeholder !== undefined && config.placeholder !== '' ) {\n\t\tthis.$input.attr( 'placeholder', config.placeholder );\n\t}\n\n\t// Mixin constructors\n\tOO.ui.mixin.GroupElement.call( this, config );\n\tif ( config.popup ) {\n\t\tconfig.popup = $.extend( {}, config.popup, {\n\t\t\talign: 'forwards',\n\t\t\tanchor: false\n\t\t} );\n\t\tOO.ui.mixin.PopupElement.call( this, config );\n\t\t$tabFocus = $( '<span>' );\n\t\tOO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: $tabFocus } ) );\n\t} else {\n\t\tthis.popup = null;\n\t\t$tabFocus = null;\n\t\tOO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$input } ) );\n\t}\n\tOO.ui.mixin.IndicatorElement.call( this, config );\n\tOO.ui.mixin.IconElement.call( this, config );\n\n\t// Properties\n\tthis.$content = $( '<div>' );\n\tthis.allowArbitrary = config.allowArbitrary;\n\tthis.allowDuplicates = config.allowDuplicates;\n\tthis.$overlay = config.$overlay;\n\tthis.menu = new OO.ui.MenuSelectWidget( $.extend(\n\t\t{\n\t\t\twidget: this,\n\t\t\t$input: this.$input,\n\t\t\t$floatableContainer: this.$element,\n\t\t\tfilterFromInput: true,\n\t\t\tdisabled: this.isDisabled()\n\t\t},\n\t\tconfig.menu\n\t) );\n\n\t// Events\n\tif ( this.popup ) {\n\t\t$tabFocus.on( {\n\t\t\tfocus: this.focus.bind( this )\n\t\t} );\n\t\tthis.popup.$element.on( 'focusout', this.onPopupFocusOut.bind( this ) );\n\t\tif ( this.popup.$autoCloseIgnore ) {\n\t\t\tthis.popup.$autoCloseIgnore.on( 'focusout', this.onPopupFocusOut.bind( this ) );\n\t\t}\n\t\tthis.popup.connect( this, {\n\t\t\ttoggle: function ( visible ) {\n\t\t\t\t$tabFocus.toggle( !visible );\n\t\t\t}\n\t\t} );\n\t} else {\n\t\tthis.$input.on( {\n\t\t\tfocus: this.onInputFocus.bind( this ),\n\t\t\tblur: this.onInputBlur.bind( this ),\n\t\t\t'propertychange change click mouseup keydown keyup input cut paste select focus':\n\t\t\t\tOO.ui.debounce( this.updateInputSize.bind( this ) ),\n\t\t\tkeydown: this.onKeyDown.bind( this ),\n\t\t\tkeypress: this.onKeyPress.bind( this )\n\t\t} );\n\t}\n\tthis.menu.connect( this, {\n\t\tchoose: 'onMenuChoose',\n\t\ttoggle: 'onMenuToggle',\n\t\tadd: 'onMenuItemsChange',\n\t\tremove: 'onMenuItemsChange'\n\t} );\n\tthis.$handle.on( {\n\t\tmousedown: this.onMouseDown.bind( this )\n\t} );\n\n\t// Initialization\n\tif ( this.$input ) {\n\t\tthis.$input.prop( 'disabled', this.isDisabled() );\n\t\tthis.$input.attr( {\n\t\t\trole: 'combobox',\n\t\t\t'aria-owns': this.menu.getElementId(),\n\t\t\t'aria-autocomplete': 'list'\n\t\t} );\n\t}\n\tif ( config.data ) {\n\t\tthis.setItemsFromData( config.data );\n\t}\n\tthis.$content.addClass( 'oo-ui-capsuleMultiselectWidget-content' )\n\t\t.append( this.$group );\n\tthis.$group.addClass( 'oo-ui-capsuleMultiselectWidget-group' );\n\tthis.$handle.addClass( 'oo-ui-capsuleMultiselectWidget-handle' )\n\t\t.append( this.$indicator, this.$icon, this.$content );\n\tthis.$element.addClass( 'oo-ui-capsuleMultiselectWidget' )\n\t\t.append( this.$handle );\n\tif ( this.popup ) {\n\t\tthis.popup.$element.addClass( 'oo-ui-capsuleMultiselectWidget-popup' );\n\t\tthis.$content.append( $tabFocus );\n\t\tthis.$overlay.append( this.popup.$element );\n\t} else {\n\t\tthis.$content.append( this.$input );\n\t\tthis.$overlay.append( this.menu.$element );\n\t}\n\tif ( $tabFocus ) {\n\t\t$tabFocus.addClass( 'oo-ui-capsuleMultiselectWidget-focusTrap' );\n\t}\n\n\t// Input size needs to be calculated after everything else is rendered\n\tsetTimeout( function () {\n\t\tif ( this.$input ) {\n\t\t\tthis.updateInputSize();\n\t\t}\n\t}.bind( this ) );\n\n\tthis.onMenuItemsChange();\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.CapsuleMultiselectWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.CapsuleMultiselectWidget, OO.ui.mixin.GroupElement );\nOO.mixinClass( OO.ui.CapsuleMultiselectWidget, OO.ui.mixin.PopupElement );\nOO.mixinClass( OO.ui.CapsuleMultiselectWidget, OO.ui.mixin.TabIndexedElement );\nOO.mixinClass( OO.ui.CapsuleMultiselectWidget, OO.ui.mixin.IndicatorElement );\nOO.mixinClass( OO.ui.CapsuleMultiselectWidget, OO.ui.mixin.IconElement );\n\n/* Events */\n\n/**\n * @event change\n *\n * A change event is emitted when the set of selected items changes.\n *\n * @param {Mixed[]} datas Data of the now-selected items\n */\n\n/**\n * @event resize\n *\n * A resize event is emitted when the widget's dimensions change to accomodate newly added items or\n * current user input.\n */\n\n/* Methods */\n\n/**\n * Construct a OO.ui.CapsuleItemWidget (or a subclass thereof) from given label and data.\n * May return `null` if the given label and data are not valid.\n *\n * @protected\n * @param {Mixed} data Custom data of any type.\n * @param {string} label The label text.\n * @return {OO.ui.CapsuleItemWidget|null}\n */\nOO.ui.CapsuleMultiselectWidget.prototype.createItemWidget = function ( data, label ) {\n\tif ( label === '' ) {\n\t\treturn null;\n\t}\n\treturn new OO.ui.CapsuleItemWidget( { data: data, label: label } );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CapsuleMultiselectWidget.prototype.getInputId = function () {\n\tif ( !this.$input ) {\n\t\treturn null;\n\t}\n\treturn OO.ui.mixin.TabIndexedElement.prototype.getInputId.call( this );\n};\n\n/**\n * Get the data of the items in the capsule\n *\n * @return {Mixed[]}\n */\nOO.ui.CapsuleMultiselectWidget.prototype.getItemsData = function () {\n\treturn this.getItems().map( function ( item ) {\n\t\treturn item.data;\n\t} );\n};\n\n/**\n * Set the items in the capsule by providing data\n *\n * @chainable\n * @param {Mixed[]} datas\n * @return {OO.ui.CapsuleMultiselectWidget}\n */\nOO.ui.CapsuleMultiselectWidget.prototype.setItemsFromData = function ( datas ) {\n\tvar widget = this,\n\t\tmenu = this.menu,\n\t\titems = this.getItems();\n\n\t$.each( datas, function ( i, data ) {\n\t\tvar j, label,\n\t\t\titem = menu.getItemFromData( data );\n\n\t\tif ( item ) {\n\t\t\tlabel = item.label;\n\t\t} else if ( widget.allowArbitrary ) {\n\t\t\tlabel = String( data );\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\n\t\titem = null;\n\t\tfor ( j = 0; j < items.length; j++ ) {\n\t\t\tif ( items[ j ].data === data && items[ j ].label === label ) {\n\t\t\t\titem = items[ j ];\n\t\t\t\titems.splice( j, 1 );\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif ( !item ) {\n\t\t\titem = widget.createItemWidget( data, label );\n\t\t}\n\t\tif ( item ) {\n\t\t\twidget.addItems( [ item ], i );\n\t\t}\n\t} );\n\n\tif ( items.length ) {\n\t\twidget.removeItems( items );\n\t}\n\n\treturn this;\n};\n\n/**\n * Add items to the capsule by providing their data\n *\n * @chainable\n * @param {Mixed[]} datas\n * @return {OO.ui.CapsuleMultiselectWidget}\n */\nOO.ui.CapsuleMultiselectWidget.prototype.addItemsFromData = function ( datas ) {\n\tvar widget = this,\n\t\tmenu = this.menu,\n\t\titems = [];\n\n\t$.each( datas, function ( i, data ) {\n\t\tvar item;\n\n\t\tif ( !widget.getItemFromData( data ) || widget.allowDuplicates ) {\n\t\t\titem = menu.getItemFromData( data );\n\t\t\tif ( item ) {\n\t\t\t\titem = widget.createItemWidget( data, item.label );\n\t\t\t} else if ( widget.allowArbitrary ) {\n\t\t\t\titem = widget.createItemWidget( data, String( data ) );\n\t\t\t}\n\t\t\tif ( item ) {\n\t\t\t\titems.push( item );\n\t\t\t}\n\t\t}\n\t} );\n\n\tif ( items.length ) {\n\t\tthis.addItems( items );\n\t}\n\n\treturn this;\n};\n\n/**\n * Add items to the capsule by providing a label\n *\n * @param {string} label\n * @return {boolean} Whether the item was added or not\n */\nOO.ui.CapsuleMultiselectWidget.prototype.addItemFromLabel = function ( label ) {\n\tvar item, items;\n\titem = this.menu.getItemFromLabel( label, true );\n\tif ( item ) {\n\t\tthis.addItemsFromData( [ item.data ] );\n\t\treturn true;\n\t} else if ( this.allowArbitrary ) {\n\t\titems = this.getItems();\n\t\tthis.addItemsFromData( [ label ] );\n\t\treturn !OO.compare( this.getItems(), items );\n\t}\n\treturn false;\n};\n\n/**\n * Remove items by data\n *\n * @chainable\n * @param {Mixed[]} datas\n * @return {OO.ui.CapsuleMultiselectWidget}\n */\nOO.ui.CapsuleMultiselectWidget.prototype.removeItemsFromData = function ( datas ) {\n\tvar widget = this,\n\t\titems = [];\n\n\t$.each( datas, function ( i, data ) {\n\t\tvar item = widget.getItemFromData( data );\n\t\tif ( item ) {\n\t\t\titems.push( item );\n\t\t}\n\t} );\n\n\tif ( items.length ) {\n\t\tthis.removeItems( items );\n\t}\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CapsuleMultiselectWidget.prototype.addItems = function ( items ) {\n\tvar same, i, l,\n\t\toldItems = this.items.slice();\n\n\tOO.ui.mixin.GroupElement.prototype.addItems.call( this, items );\n\n\tif ( this.items.length !== oldItems.length ) {\n\t\tsame = false;\n\t} else {\n\t\tsame = true;\n\t\tfor ( i = 0, l = oldItems.length; same && i < l; i++ ) {\n\t\t\tsame = same && this.items[ i ] === oldItems[ i ];\n\t\t}\n\t}\n\tif ( !same ) {\n\t\tthis.emit( 'change', this.getItemsData() );\n\t\tthis.updateInputSize();\n\t}\n\n\treturn this;\n};\n\n/**\n * Removes the item from the list and copies its label to `this.$input`.\n *\n * @param {Object} item\n */\nOO.ui.CapsuleMultiselectWidget.prototype.editItem = function ( item ) {\n\tthis.addItemFromLabel( this.$input.val() );\n\tthis.clearInput();\n\tthis.$input.val( item.label );\n\tthis.updateInputSize();\n\tthis.focus();\n\tthis.menu.updateItemVisibility(); // Hack, we shouldn't be calling this method directly\n\tthis.removeItems( [ item ] );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CapsuleMultiselectWidget.prototype.removeItems = function ( items ) {\n\tvar same, i, l,\n\t\toldItems = this.items.slice();\n\n\tOO.ui.mixin.GroupElement.prototype.removeItems.call( this, items );\n\n\tif ( this.items.length !== oldItems.length ) {\n\t\tsame = false;\n\t} else {\n\t\tsame = true;\n\t\tfor ( i = 0, l = oldItems.length; same && i < l; i++ ) {\n\t\t\tsame = same && this.items[ i ] === oldItems[ i ];\n\t\t}\n\t}\n\tif ( !same ) {\n\t\tthis.emit( 'change', this.getItemsData() );\n\t\tthis.updateInputSize();\n\t}\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CapsuleMultiselectWidget.prototype.clearItems = function () {\n\tif ( this.items.length ) {\n\t\tOO.ui.mixin.GroupElement.prototype.clearItems.call( this );\n\t\tthis.emit( 'change', this.getItemsData() );\n\t\tthis.updateInputSize();\n\t}\n\treturn this;\n};\n\n/**\n * Given an item, returns the item after it. If its the last item,\n * returns `this.$input`. If no item is passed, returns the very first\n * item.\n *\n * @param {OO.ui.CapsuleItemWidget} [item]\n * @return {OO.ui.CapsuleItemWidget|jQuery|boolean}\n */\nOO.ui.CapsuleMultiselectWidget.prototype.getNextItem = function ( item ) {\n\tvar itemIndex;\n\n\tif ( item === undefined ) {\n\t\treturn this.items[ 0 ];\n\t}\n\n\titemIndex = this.items.indexOf( item );\n\tif ( itemIndex < 0 ) { // Item not in list\n\t\treturn false;\n\t} else if ( itemIndex === this.items.length - 1 ) { // Last item\n\t\treturn this.$input;\n\t} else {\n\t\treturn this.items[ itemIndex + 1 ];\n\t}\n};\n\n/**\n * Given an item, returns the item before it. If its the first item,\n * returns `this.$input`. If no item is passed, returns the very last\n * item.\n *\n * @param {OO.ui.CapsuleItemWidget} [item]\n * @return {OO.ui.CapsuleItemWidget|jQuery|boolean}\n */\nOO.ui.CapsuleMultiselectWidget.prototype.getPreviousItem = function ( item ) {\n\tvar itemIndex;\n\n\tif ( item === undefined ) {\n\t\treturn this.items[ this.items.length - 1 ];\n\t}\n\n\titemIndex = this.items.indexOf( item );\n\tif ( itemIndex < 0 ) { // Item not in list\n\t\treturn false;\n\t} else if ( itemIndex === 0 ) { // First item\n\t\treturn this.$input;\n\t} else {\n\t\treturn this.items[ itemIndex - 1 ];\n\t}\n};\n\n/**\n * Get the capsule widget's menu.\n *\n * @return {OO.ui.MenuSelectWidget} Menu widget\n */\nOO.ui.CapsuleMultiselectWidget.prototype.getMenu = function () {\n\treturn this.menu;\n};\n\n/**\n * Handle focus events\n *\n * @private\n * @param {jQuery.Event} event\n */\nOO.ui.CapsuleMultiselectWidget.prototype.onInputFocus = function () {\n\tif ( !this.isDisabled() ) {\n\t\tthis.updateInputSize();\n\t\tthis.menu.toggle( true );\n\t}\n};\n\n/**\n * Handle blur events\n *\n * @private\n * @param {jQuery.Event} event\n */\nOO.ui.CapsuleMultiselectWidget.prototype.onInputBlur = function () {\n\tthis.addItemFromLabel( this.$input.val() );\n\tthis.clearInput();\n};\n\n/**\n * Handles popup focus out events.\n *\n * @private\n * @param {jQuery.Event} e Focus out event\n */\nOO.ui.CapsuleMultiselectWidget.prototype.onPopupFocusOut = function () {\n\tvar widget = this.popup;\n\n\tsetTimeout( function () {\n\t\tif (\n\t\t\twidget.isVisible() &&\n\t\t\t!OO.ui.contains( widget.$element.add( widget.$autoCloseIgnore ).get(), document.activeElement, true )\n\t\t) {\n\t\t\twidget.toggle( false );\n\t\t}\n\t} );\n};\n\n/**\n * Handle mouse down events.\n *\n * @private\n * @param {jQuery.Event} e Mouse down event\n */\nOO.ui.CapsuleMultiselectWidget.prototype.onMouseDown = function ( e ) {\n\tif ( e.which === OO.ui.MouseButtons.LEFT ) {\n\t\tthis.focus();\n\t\treturn false;\n\t} else {\n\t\tthis.updateInputSize();\n\t}\n};\n\n/**\n * Handle key press events.\n *\n * @private\n * @param {jQuery.Event} e Key press event\n */\nOO.ui.CapsuleMultiselectWidget.prototype.onKeyPress = function ( e ) {\n\tif ( !this.isDisabled() ) {\n\t\tif ( e.which === OO.ui.Keys.ESCAPE ) {\n\t\t\tthis.clearInput();\n\t\t\treturn false;\n\t\t}\n\n\t\tif ( !this.popup ) {\n\t\t\tthis.menu.toggle( true );\n\t\t\tif ( e.which === OO.ui.Keys.ENTER ) {\n\t\t\t\tif ( this.addItemFromLabel( this.$input.val() ) ) {\n\t\t\t\t\tthis.clearInput();\n\t\t\t\t}\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\t// Make sure the input gets resized.\n\t\t\tsetTimeout( this.updateInputSize.bind( this ), 0 );\n\t\t}\n\t}\n};\n\n/**\n * Handle key down events.\n *\n * @private\n * @param {jQuery.Event} e Key down event\n */\nOO.ui.CapsuleMultiselectWidget.prototype.onKeyDown = function ( e ) {\n\tif (\n\t\t!this.isDisabled() &&\n\t\tthis.$input.val() === '' &&\n\t\tthis.items.length\n\t) {\n\t\t// 'keypress' event is not triggered for Backspace\n\t\tif ( e.keyCode === OO.ui.Keys.BACKSPACE ) {\n\t\t\tif ( e.metaKey || e.ctrlKey ) {\n\t\t\t\tthis.removeItems( this.items.slice( -1 ) );\n\t\t\t} else {\n\t\t\t\tthis.editItem( this.items[ this.items.length - 1 ] );\n\t\t\t}\n\t\t\treturn false;\n\t\t} else if ( e.keyCode === OO.ui.Keys.LEFT ) {\n\t\t\tthis.getPreviousItem().focus();\n\t\t} else if ( e.keyCode === OO.ui.Keys.RIGHT ) {\n\t\t\tthis.getNextItem().focus();\n\t\t}\n\t}\n};\n\n/**\n * Update the dimensions of the text input field to encompass all available area.\n *\n * @private\n * @param {jQuery.Event} e Event of some sort\n */\nOO.ui.CapsuleMultiselectWidget.prototype.updateInputSize = function () {\n\tvar $lastItem, direction, contentWidth, currentWidth, bestWidth;\n\tif ( this.$input && !this.isDisabled() ) {\n\t\tthis.$input.css( 'width', '1em' );\n\t\t$lastItem = this.$group.children().last();\n\t\tdirection = OO.ui.Element.static.getDir( this.$handle );\n\n\t\t// Get the width of the input with the placeholder text as\n\t\t// the value and save it so that we don't keep recalculating\n\t\tif (\n\t\t\tthis.contentWidthWithPlaceholder === undefined &&\n\t\t\tthis.$input.val() === '' &&\n\t\t\tthis.$input.attr( 'placeholder' ) !== undefined\n\t\t) {\n\t\t\tthis.$input.val( this.$input.attr( 'placeholder' ) );\n\t\t\tthis.contentWidthWithPlaceholder = this.$input[ 0 ].scrollWidth;\n\t\t\tthis.$input.val( '' );\n\n\t\t}\n\n\t\t// Always keep the input wide enough for the placeholder text\n\t\tcontentWidth = Math.max(\n\t\t\tthis.$input[ 0 ].scrollWidth,\n\t\t\t// undefined arguments in Math.max lead to NaN\n\t\t\t( this.contentWidthWithPlaceholder === undefined ) ?\n\t\t\t\t0 : this.contentWidthWithPlaceholder\n\t\t);\n\t\tcurrentWidth = this.$input.width();\n\n\t\tif ( contentWidth < currentWidth ) {\n\t\t\tthis.updateIfHeightChanged();\n\t\t\t// All is fine, don't perform expensive calculations\n\t\t\treturn;\n\t\t}\n\n\t\tif ( $lastItem.length === 0 ) {\n\t\t\tbestWidth = this.$content.innerWidth();\n\t\t} else {\n\t\t\tbestWidth = direction === 'ltr' ?\n\t\t\t\tthis.$content.innerWidth() - $lastItem.position().left - $lastItem.outerWidth() :\n\t\t\t\t$lastItem.position().left;\n\t\t}\n\n\t\t// Some safety margin for sanity, because I *really* don't feel like finding out where the few\n\t\t// pixels this is off by are coming from.\n\t\tbestWidth -= 10;\n\t\tif ( contentWidth > bestWidth ) {\n\t\t\t// This will result in the input getting shifted to the next line\n\t\t\tbestWidth = this.$content.innerWidth() - 10;\n\t\t}\n\t\tthis.$input.width( Math.floor( bestWidth ) );\n\t\tthis.updateIfHeightChanged();\n\t} else {\n\t\tthis.updateIfHeightChanged();\n\t}\n};\n\n/**\n * Determine if widget height changed, and if so, update menu position and emit 'resize' event.\n *\n * @private\n */\nOO.ui.CapsuleMultiselectWidget.prototype.updateIfHeightChanged = function () {\n\tvar height = this.$element.height();\n\tif ( height !== this.height ) {\n\t\tthis.height = height;\n\t\tthis.menu.position();\n\t\tif ( this.popup ) {\n\t\t\tthis.popup.updateDimensions();\n\t\t}\n\t\tthis.emit( 'resize' );\n\t}\n};\n\n/**\n * Handle menu choose events.\n *\n * @private\n * @param {OO.ui.OptionWidget} item Chosen item\n */\nOO.ui.CapsuleMultiselectWidget.prototype.onMenuChoose = function ( item ) {\n\tif ( item && item.isVisible() ) {\n\t\tthis.addItemsFromData( [ item.getData() ] );\n\t\tthis.clearInput();\n\t}\n};\n\n/**\n * Handle menu toggle events.\n *\n * @private\n * @param {boolean} isVisible Menu toggle event\n */\nOO.ui.CapsuleMultiselectWidget.prototype.onMenuToggle = function ( isVisible ) {\n\tthis.$element.toggleClass( 'oo-ui-capsuleMultiselectWidget-open', isVisible );\n};\n\n/**\n * Handle menu item change events.\n *\n * @private\n */\nOO.ui.CapsuleMultiselectWidget.prototype.onMenuItemsChange = function () {\n\tthis.setItemsFromData( this.getItemsData() );\n\tthis.$element.toggleClass( 'oo-ui-capsuleMultiselectWidget-empty', this.menu.isEmpty() );\n};\n\n/**\n * Clear the input field\n *\n * @private\n */\nOO.ui.CapsuleMultiselectWidget.prototype.clearInput = function () {\n\tif ( this.$input ) {\n\t\tthis.$input.val( '' );\n\t\tthis.updateInputSize();\n\t}\n\tif ( this.popup ) {\n\t\tthis.popup.toggle( false );\n\t}\n\tthis.menu.toggle( false );\n\tthis.menu.selectItem();\n\tthis.menu.highlightItem();\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.CapsuleMultiselectWidget.prototype.setDisabled = function ( disabled ) {\n\tvar i, len;\n\n\t// Parent method\n\tOO.ui.CapsuleMultiselectWidget.parent.prototype.setDisabled.call( this, disabled );\n\n\tif ( this.$input ) {\n\t\tthis.$input.prop( 'disabled', this.isDisabled() );\n\t}\n\tif ( this.menu ) {\n\t\tthis.menu.setDisabled( this.isDisabled() );\n\t}\n\tif ( this.popup ) {\n\t\tthis.popup.setDisabled( this.isDisabled() );\n\t}\n\n\tif ( this.items ) {\n\t\tfor ( i = 0, len = this.items.length; i < len; i++ ) {\n\t\t\tthis.items[ i ].updateDisabled();\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Focus the widget\n *\n * @chainable\n */\nOO.ui.CapsuleMultiselectWidget.prototype.focus = function () {\n\tif ( !this.isDisabled() ) {\n\t\tif ( this.popup ) {\n\t\t\tthis.popup.setSize( this.$handle.outerWidth() );\n\t\t\tthis.popup.toggle( true );\n\t\t\tOO.ui.findFocusable( this.popup.$element ).focus();\n\t\t} else {\n\t\t\tOO.ui.mixin.TabIndexedElement.prototype.focus.call( this );\n\t\t}\n\t}\n\treturn this;\n};\n","/**\n * TagItemWidgets are used within a {@link OO.ui.TagMultiselectWidget\n * TagMultiselectWidget} to display the selected items.\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.ItemWidget\n * @mixins OO.ui.mixin.LabelElement\n * @mixins OO.ui.mixin.FlaggedElement\n * @mixins OO.ui.mixin.TabIndexedElement\n * @mixins OO.ui.mixin.DraggableElement\n *\n * @constructor\n * @param {Object} [config] Configuration object\n * @cfg {boolean} [valid=true] Item is valid\n */\nOO.ui.TagItemWidget = function OoUiTagItemWidget( config ) {\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.TagItemWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.ItemWidget.call( this );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\tOO.ui.mixin.FlaggedElement.call( this, config );\n\tOO.ui.mixin.TabIndexedElement.call( this, config );\n\tOO.ui.mixin.DraggableElement.call( this, config );\n\n\tthis.valid = config.valid === undefined ? true : !!config.valid;\n\n\tthis.closeButton = new OO.ui.ButtonWidget( {\n\t\tframed: false,\n\t\ticon: 'close',\n\t\ttabIndex: -1,\n\t\ttitle: OO.ui.msg( 'ooui-item-remove' )\n\t} );\n\tthis.closeButton.setDisabled( this.isDisabled() );\n\n\t// Events\n\tthis.closeButton\n\t\t.connect( this, { click: 'remove' } );\n\tthis.$element\n\t\t.on( 'click', this.select.bind( this ) )\n\t\t.on( 'keydown', this.onKeyDown.bind( this ) )\n\t\t// Prevent propagation of mousedown; the tag item \"lives\" in the\n\t\t// clickable area of the TagMultiselectWidget, which listens to\n\t\t// mousedown to open the menu or popup. We want to prevent that\n\t\t// for clicks specifically on the tag itself, so the actions taken\n\t\t// are more deliberate. When the tag is clicked, it will emit the\n\t\t// selection event (similar to how #OO.ui.MultioptionWidget emits 'change')\n\t\t// and can be handled separately.\n\t\t.on( 'mousedown', function ( e ) { e.stopPropagation(); } );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-tagItemWidget' )\n\t\t.append( this.$label, this.closeButton.$element );\n};\n\n/* Initialization */\n\nOO.inheritClass( OO.ui.TagItemWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.TagItemWidget, OO.ui.mixin.ItemWidget );\nOO.mixinClass( OO.ui.TagItemWidget, OO.ui.mixin.LabelElement );\nOO.mixinClass( OO.ui.TagItemWidget, OO.ui.mixin.FlaggedElement );\nOO.mixinClass( OO.ui.TagItemWidget, OO.ui.mixin.TabIndexedElement );\nOO.mixinClass( OO.ui.TagItemWidget, OO.ui.mixin.DraggableElement );\n\n/* Events */\n\n/**\n * @event remove\n *\n * A remove action was performed on the item\n */\n\n/**\n * @event navigate\n * @param {string} direction Direction of the movement, forward or backwards\n *\n * A navigate action was performed on the item\n */\n\n/**\n * @event select\n *\n * The tag widget was selected. This can occur when the widget\n * is either clicked or enter was pressed on it.\n */\n\n/**\n * @event valid\n * @param {boolean} isValid Item is valid\n *\n * Item validity has changed\n */\n\n/* Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.TagItemWidget.prototype.setDisabled = function ( state ) {\n\t// Parent method\n\tOO.ui.TagItemWidget.parent.prototype.setDisabled.call( this, state );\n\n\tif ( this.closeButton ) {\n\t\tthis.closeButton.setDisabled( state );\n\t}\n\treturn this;\n};\n\n/**\n * Handle removal of the item\n *\n * This is mainly for extensibility concerns, so other children\n * of this class can change the behavior if they need to. This\n * is called by both clicking the 'remove' button but also\n * on keypress, which is harder to override if needed.\n *\n * @fires remove\n */\nOO.ui.TagItemWidget.prototype.remove = function () {\n\tif ( !this.isDisabled() ) {\n\t\tthis.emit( 'remove' );\n\t}\n};\n\n/**\n * Handle a keydown event on the widget\n *\n * @fires navigate\n * @fires remove\n * @param {jQuery.Event} e Key down event\n * @return {boolean|undefined} false to stop the operation\n */\nOO.ui.TagItemWidget.prototype.onKeyDown = function ( e ) {\n\tvar movement;\n\n\tif ( e.keyCode === OO.ui.Keys.BACKSPACE || e.keyCode === OO.ui.Keys.DELETE ) {\n\t\tthis.remove();\n\t\treturn false;\n\t} else if ( e.keyCode === OO.ui.Keys.ENTER ) {\n\t\tthis.select();\n\t\treturn false;\n\t} else if (\n\t\te.keyCode === OO.ui.Keys.LEFT ||\n\t\te.keyCode === OO.ui.Keys.RIGHT\n\t) {\n\t\tif ( OO.ui.Element.static.getDir( this.$element ) === 'rtl' ) {\n\t\t\tmovement = {\n\t\t\t\tleft: 'forwards',\n\t\t\t\tright: 'backwards'\n\t\t\t};\n\t\t} else {\n\t\t\tmovement = {\n\t\t\t\tleft: 'backwards',\n\t\t\t\tright: 'forwards'\n\t\t\t};\n\t\t}\n\n\t\tthis.emit(\n\t\t\t'navigate',\n\t\t\te.keyCode === OO.ui.Keys.LEFT ?\n\t\t\t\tmovement.left : movement.right\n\t\t);\n\t}\n};\n\n/**\n * Select this item\n *\n * @fires select\n */\nOO.ui.TagItemWidget.prototype.select = function () {\n\tif ( !this.isDisabled() ) {\n\t\tthis.emit( 'select' );\n\t}\n};\n\n/**\n * Set the valid state of this item\n *\n * @param {boolean} [valid] Item is valid\n * @fires valid\n */\nOO.ui.TagItemWidget.prototype.toggleValid = function ( valid ) {\n\tvalid = valid === undefined ? !this.valid : !!valid;\n\n\tif ( this.valid !== valid ) {\n\t\tthis.valid = valid;\n\n\t\tthis.setFlags( { invalid: !this.valid } );\n\n\t\tthis.emit( 'valid', this.valid );\n\t}\n};\n\n/**\n * Check whether the item is valid\n *\n * @return {boolean} Item is valid\n */\nOO.ui.TagItemWidget.prototype.isValid = function () {\n\treturn this.valid;\n};\n","/**\n * A basic tag multiselect widget, similar in concept to {@link OO.ui.ComboBoxInputWidget combo box widget}\n * that allows the user to add multiple values that are displayed in a tag area.\n *\n * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * This widget is a base widget; see {@link OO.ui.MenuTagMultiselectWidget MenuTagMultiselectWidget} and\n * {@link OO.ui.PopupTagMultiselectWidget PopupTagMultiselectWidget} for the implementations that use\n * a menu and a popup respectively.\n *\n * @example\n * // Example: A basic TagMultiselectWidget.\n * var widget = new OO.ui.TagMultiselectWidget( {\n * inputPosition: 'outline',\n * allowedValues: [ 'Option 1', 'Option 2', 'Option 3' ],\n * selected: [ 'Option 1' ]\n * } );\n * $( 'body' ).append( widget.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.GroupWidget\n * @mixins OO.ui.mixin.DraggableGroupElement\n * @mixins OO.ui.mixin.IndicatorElement\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.TabIndexedElement\n * @mixins OO.ui.mixin.FlaggedElement\n *\n * @constructor\n * @param {Object} config Configuration object\n * @cfg {Object} [input] Configuration options for the input widget\n * @cfg {OO.ui.InputWidget} [inputWidget] An optional input widget. If given, it will\n * replace the input widget used in the TagMultiselectWidget. If not given,\n * TagMultiselectWidget creates its own.\n * @cfg {boolean} [inputPosition='inline'] Position of the input. Options are:\n * \t- inline: The input is invisible, but exists inside the tag list, so\n * \t\tthe user types into the tag groups to add tags.\n * \t- outline: The input is underneath the tag area.\n * \t- none: No input supplied\n * @cfg {boolean} [allowEditTags=true] Allow editing of the tags by clicking them\n * @cfg {boolean} [allowArbitrary=false] Allow data items to be added even if\n * not present in the menu.\n * @cfg {Object[]} [allowedValues] An array representing the allowed items\n * by their datas.\n * @cfg {boolean} [allowDuplicates=false] Allow duplicate items to be added\n * @cfg {boolean} [allowDisplayInvalidTags=false] Allow the display of\n * invalid tags. These tags will display with an invalid state, and\n * the widget as a whole will have an invalid state if any invalid tags\n * are present.\n * @cfg {boolean} [allowReordering=true] Allow reordering of the items\n * @cfg {Object[]|String[]} [selected] A set of selected tags. If given,\n * these will appear in the tag list on initialization, as long as they\n * pass the validity tests.\n */\nOO.ui.TagMultiselectWidget = function OoUiTagMultiselectWidget( config ) {\n\tvar inputEvents,\n\t\trAF = window.requestAnimationFrame || setTimeout,\n\t\twidget = this,\n\t\t$tabFocus = $( '<span>' )\n\t\t\t.addClass( 'oo-ui-tagMultiselectWidget-focusTrap' );\n\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.TagMultiselectWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.GroupWidget.call( this, config );\n\tOO.ui.mixin.IndicatorElement.call( this, config );\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.TabIndexedElement.call( this, config );\n\tOO.ui.mixin.FlaggedElement.call( this, config );\n\tOO.ui.mixin.DraggableGroupElement.call( this, config );\n\n\tthis.toggleDraggable(\n\t\tconfig.allowReordering === undefined ?\n\t\t\ttrue : !!config.allowReordering\n\t);\n\n\tthis.inputPosition =\n\t\tthis.constructor.static.allowedInputPositions.indexOf( config.inputPosition ) > -1 ?\n\t\t\tconfig.inputPosition : 'inline';\n\tthis.allowEditTags = config.allowEditTags === undefined ? true : !!config.allowEditTags;\n\tthis.allowArbitrary = !!config.allowArbitrary;\n\tthis.allowDuplicates = !!config.allowDuplicates;\n\tthis.allowedValues = config.allowedValues || [];\n\tthis.allowDisplayInvalidTags = config.allowDisplayInvalidTags;\n\tthis.hasInput = this.inputPosition !== 'none';\n\tthis.height = null;\n\tthis.valid = true;\n\n\tthis.$content = $( '<div>' )\n\t\t.addClass( 'oo-ui-tagMultiselectWidget-content' );\n\tthis.$handle = $( '<div>' )\n\t\t.addClass( 'oo-ui-tagMultiselectWidget-handle' )\n\t\t.append(\n\t\t\tthis.$indicator,\n\t\t\tthis.$icon,\n\t\t\tthis.$content\n\t\t\t\t.append(\n\t\t\t\t\tthis.$group\n\t\t\t\t\t\t.addClass( 'oo-ui-tagMultiselectWidget-group' )\n\t\t\t\t)\n\t\t);\n\n\t// Events\n\tthis.aggregate( {\n\t\tremove: 'itemRemove',\n\t\tnavigate: 'itemNavigate',\n\t\tselect: 'itemSelect'\n\t} );\n\tthis.connect( this, {\n\t\titemRemove: 'onTagRemove',\n\t\titemSelect: 'onTagSelect',\n\t\titemNavigate: 'onTagNavigate',\n\t\tchange: 'onChangeTags'\n\t} );\n\tthis.$handle.on( {\n\t\tmousedown: this.onMouseDown.bind( this )\n\t} );\n\n\t// Initialize\n\tthis.$element\n\t\t.addClass( 'oo-ui-tagMultiselectWidget' )\n\t\t.append( this.$handle );\n\n\tif ( this.hasInput ) {\n\t\tif ( config.inputWidget ) {\n\t\t\tthis.input = config.inputWidget;\n\t\t} else {\n\t\t\tthis.input = new OO.ui.TextInputWidget( $.extend( {\n\t\t\t\tplaceholder: config.placeholder,\n\t\t\t\tclasses: [ 'oo-ui-tagMultiselectWidget-input' ]\n\t\t\t}, config.input ) );\n\t\t}\n\t\tthis.input.setDisabled( this.isDisabled() );\n\n\t\tinputEvents = {\n\t\t\tfocus: this.onInputFocus.bind( this ),\n\t\t\tblur: this.onInputBlur.bind( this ),\n\t\t\t'propertychange change click mouseup keydown keyup input cut paste select focus':\n\t\t\t\tOO.ui.debounce( this.updateInputSize.bind( this ) ),\n\t\t\tkeydown: this.onInputKeyDown.bind( this ),\n\t\t\tkeypress: this.onInputKeyPress.bind( this )\n\t\t};\n\n\t\tthis.input.$input.on( inputEvents );\n\n\t\tif ( this.inputPosition === 'outline' ) {\n\t\t\t// Override max-height for the input widget\n\t\t\t// in the case the widget is outline so it can\n\t\t\t// stretch all the way if the widet is wide\n\t\t\tthis.input.$element.css( 'max-width', 'inherit' );\n\t\t\tthis.$element\n\t\t\t\t.addClass( 'oo-ui-tagMultiselectWidget-outlined' )\n\t\t\t\t.append( this.input.$element );\n\t\t} else {\n\t\t\tthis.$element.addClass( 'oo-ui-tagMultiselectWidget-inlined' );\n\t\t\t// HACK: When the widget is using 'inline' input, the\n\t\t\t// behavior needs to only use the $input itself\n\t\t\t// so we style and size it accordingly (otherwise\n\t\t\t// the styling and sizing can get very convoluted\n\t\t\t// when the wrapping divs and other elements)\n\t\t\t// We are taking advantage of still being able to\n\t\t\t// call the widget itself for operations like\n\t\t\t// .getValue() and setDisabled() and .focus() but\n\t\t\t// having only the $input attached to the DOM\n\t\t\tthis.$content.append( this.input.$input );\n\t\t}\n\t} else {\n\t\tthis.$content.append( $tabFocus );\n\t}\n\n\tthis.setTabIndexedElement(\n\t\tthis.hasInput ?\n\t\t\tthis.input.$input :\n\t\t\t$tabFocus\n\t);\n\n\tif ( config.selected ) {\n\t\tthis.setValue( config.selected );\n\t}\n\n\t// HACK: Input size needs to be calculated after everything\n\t// else is rendered\n\trAF( function () {\n\t\tif ( widget.hasInput ) {\n\t\t\twidget.updateInputSize();\n\t\t}\n\t} );\n};\n\n/* Initialization */\n\nOO.inheritClass( OO.ui.TagMultiselectWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.GroupWidget );\nOO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.DraggableGroupElement );\nOO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.IndicatorElement );\nOO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.TabIndexedElement );\nOO.mixinClass( OO.ui.TagMultiselectWidget, OO.ui.mixin.FlaggedElement );\n\n/* Static properties */\n\n/**\n * Allowed input positions.\n * - inline: The input is inside the tag list\n * - outline: The input is under the tag list\n * - none: There is no input\n *\n * @property {Array}\n */\nOO.ui.TagMultiselectWidget.static.allowedInputPositions = [ 'inline', 'outline', 'none' ];\n\n/* Methods */\n\n/**\n * Handle mouse down events.\n *\n * @private\n * @param {jQuery.Event} e Mouse down event\n * @return {boolean} False to prevent defaults\n */\nOO.ui.TagMultiselectWidget.prototype.onMouseDown = function ( e ) {\n\tif ( !this.isDisabled() && e.which === OO.ui.MouseButtons.LEFT ) {\n\t\tthis.focus();\n\t\treturn false;\n\t}\n};\n\n/**\n * Handle key press events.\n *\n * @private\n * @param {jQuery.Event} e Key press event\n * @return {boolean} Whether to prevent defaults\n */\nOO.ui.TagMultiselectWidget.prototype.onInputKeyPress = function ( e ) {\n\tvar stopOrContinue,\n\t\twithMetaKey = e.metaKey || e.ctrlKey;\n\n\tif ( !this.isDisabled() ) {\n\t\tif ( e.which === OO.ui.Keys.ENTER ) {\n\t\t\tstopOrContinue = this.doInputEnter( e, withMetaKey );\n\t\t}\n\n\t\t// Make sure the input gets resized.\n\t\tsetTimeout( this.updateInputSize.bind( this ), 0 );\n\t\treturn stopOrContinue;\n\t}\n};\n\n/**\n * Handle key down events.\n *\n * @private\n * @param {jQuery.Event} e Key down event\n * @return {boolean}\n */\nOO.ui.TagMultiselectWidget.prototype.onInputKeyDown = function ( e ) {\n\tvar movement, direction,\n\t\twithMetaKey = e.metaKey || e.ctrlKey;\n\n\tif ( !this.isDisabled() ) {\n\t\t// 'keypress' event is not triggered for Backspace\n\t\tif ( e.keyCode === OO.ui.Keys.BACKSPACE ) {\n\t\t\treturn this.doInputBackspace( e, withMetaKey );\n\t\t} else if ( e.keyCode === OO.ui.Keys.ESCAPE ) {\n\t\t\treturn this.doInputEscape( e );\n\t\t} else if (\n\t\t\te.keyCode === OO.ui.Keys.LEFT ||\n\t\t\te.keyCode === OO.ui.Keys.RIGHT\n\t\t) {\n\t\t\tif ( OO.ui.Element.static.getDir( this.$element ) === 'rtl' ) {\n\t\t\t\tmovement = {\n\t\t\t\t\tleft: 'forwards',\n\t\t\t\t\tright: 'backwards'\n\t\t\t\t};\n\t\t\t} else {\n\t\t\t\tmovement = {\n\t\t\t\t\tleft: 'backwards',\n\t\t\t\t\tright: 'forwards'\n\t\t\t\t};\n\t\t\t}\n\t\t\tdirection = e.keyCode === OO.ui.Keys.LEFT ?\n\t\t\t\tmovement.left : movement.right;\n\n\t\t\treturn this.doInputArrow( e, direction, withMetaKey );\n\t\t}\n\t}\n};\n\n/**\n * Respond to input focus event\n */\nOO.ui.TagMultiselectWidget.prototype.onInputFocus = function () {\n\tthis.$element.addClass( 'oo-ui-tagMultiselectWidget-focus' );\n};\n\n/**\n * Respond to input blur event\n */\nOO.ui.TagMultiselectWidget.prototype.onInputBlur = function () {\n\tthis.$element.removeClass( 'oo-ui-tagMultiselectWidget-focus' );\n};\n\n/**\n * Perform an action after the enter key on the input\n *\n * @param {jQuery.Event} e Event data\n * @param {boolean} [withMetaKey] Whether this key was pressed with\n * a meta key like 'ctrl'\n * @return {boolean} Whether to prevent defaults\n */\nOO.ui.TagMultiselectWidget.prototype.doInputEnter = function () {\n\tthis.addTagFromInput();\n\treturn false;\n};\n\n/**\n * Perform an action responding to the enter key on the input\n *\n * @param {jQuery.Event} e Event data\n * @param {boolean} [withMetaKey] Whether this key was pressed with\n * a meta key like 'ctrl'\n * @return {boolean} Whether to prevent defaults\n */\nOO.ui.TagMultiselectWidget.prototype.doInputBackspace = function ( e, withMetaKey ) {\n\tvar items, item;\n\n\tif (\n\t\tthis.inputPosition === 'inline' &&\n\t\tthis.input.getValue() === '' &&\n\t\t!this.isEmpty()\n\t) {\n\t\t// Delete the last item\n\t\titems = this.getItems();\n\t\titem = items[ items.length - 1 ];\n\t\tthis.removeItems( [ item ] );\n\t\t// If Ctrl/Cmd was pressed, delete item entirely.\n\t\t// Otherwise put it into the text field for editing.\n\t\tif ( !withMetaKey ) {\n\t\t\tthis.input.setValue( item.getData() );\n\t\t}\n\n\t\treturn false;\n\t}\n};\n\n/**\n * Perform an action after the escape key on the input\n *\n * @param {jQuery.Event} e Event data\n */\nOO.ui.TagMultiselectWidget.prototype.doInputEscape = function () {\n\tthis.clearInput();\n};\n\n/**\n * Perform an action after the arrow key on the input, select the previous\n * or next item from the input.\n * See #getPreviousItem and #getNextItem\n *\n * @param {jQuery.Event} e Event data\n * @param {string} direction Direction of the movement; forwards or backwards\n * @param {boolean} [withMetaKey] Whether this key was pressed with\n * a meta key like 'ctrl'\n */\nOO.ui.TagMultiselectWidget.prototype.doInputArrow = function ( e, direction ) {\n\tif (\n\t\tthis.inputPosition === 'inline' &&\n\t\t!this.isEmpty()\n\t) {\n\t\tif ( direction === 'backwards' ) {\n\t\t\t// Get previous item\n\t\t\tthis.getPreviousItem().focus();\n\t\t} else {\n\t\t\t// Get next item\n\t\t\tthis.getNextItem().focus();\n\t\t}\n\t}\n};\n\n/**\n * Respond to item select event\n *\n * @param {OO.ui.TagItemWidget} item Selected item\n */\nOO.ui.TagMultiselectWidget.prototype.onTagSelect = function ( item ) {\n\tif ( this.hasInput && this.allowEditTags ) {\n\t\tif ( this.input.getValue() ) {\n\t\t\tthis.addTagFromInput();\n\t\t}\n\t\t// 1. Get the label of the tag into the input\n\t\tthis.input.setValue( item.getData() );\n\t\t// 2. Remove the tag\n\t\tthis.removeItems( [ item ] );\n\t\t// 3. Focus the input\n\t\tthis.focus();\n\t}\n};\n\n/**\n * Respond to change event, where items were added, removed, or cleared.\n */\nOO.ui.TagMultiselectWidget.prototype.onChangeTags = function () {\n\tthis.toggleValid( this.checkValidity() );\n\tif ( this.hasInput ) {\n\t\tthis.updateInputSize();\n\t}\n\tthis.updateIfHeightChanged();\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.TagMultiselectWidget.prototype.setDisabled = function ( isDisabled ) {\n\t// Parent method\n\tOO.ui.TagMultiselectWidget.parent.prototype.setDisabled.call( this, isDisabled );\n\n\tif ( this.hasInput && this.input ) {\n\t\tthis.input.setDisabled( !!isDisabled );\n\t}\n\n\tif ( this.items ) {\n\t\tthis.getItems().forEach( function ( item ) {\n\t\t\titem.setDisabled( !!isDisabled );\n\t\t} );\n\t}\n};\n\n/**\n * Respond to tag remove event\n * @param {OO.ui.TagItemWidget} item Removed tag\n */\nOO.ui.TagMultiselectWidget.prototype.onTagRemove = function ( item ) {\n\tthis.removeTagByData( item.getData() );\n};\n\n/**\n * Respond to navigate event on the tag\n *\n * @param {OO.ui.TagItemWidget} item Removed tag\n * @param {string} direction Direction of movement; 'forwards' or 'backwards'\n */\nOO.ui.TagMultiselectWidget.prototype.onTagNavigate = function ( item, direction ) {\n\tif ( direction === 'forwards' ) {\n\t\tthis.getNextItem( item ).focus();\n\t} else {\n\t\tthis.getPreviousItem( item ).focus();\n\t}\n};\n\n/**\n * Add tag from input value\n */\nOO.ui.TagMultiselectWidget.prototype.addTagFromInput = function () {\n\tvar val = this.input.getValue(),\n\t\tisValid = this.isAllowedData( val );\n\n\tif ( !val ) {\n\t\treturn;\n\t}\n\n\tif ( isValid || this.allowDisplayInvalidTags ) {\n\t\tthis.addTag( val );\n\t\tthis.clearInput();\n\t\tthis.focus();\n\t}\n};\n\n/**\n * Clear the input\n */\nOO.ui.TagMultiselectWidget.prototype.clearInput = function () {\n\tthis.input.setValue( '' );\n};\n\n/**\n * Check whether the given value is a duplicate of an existing\n * tag already in the list.\n *\n * @param {string|Object} data Requested value\n * @return {boolean} Value is duplicate\n */\nOO.ui.TagMultiselectWidget.prototype.isDuplicateData = function ( data ) {\n\treturn !!this.getItemFromData( data );\n};\n\n/**\n * Check whether a given value is allowed to be added\n *\n * @param {string|Object} data Requested value\n * @return {boolean} Value is allowed\n */\nOO.ui.TagMultiselectWidget.prototype.isAllowedData = function ( data ) {\n\tif (\n\t\t!this.allowDuplicates &&\n\t\tthis.isDuplicateData( data )\n\t) {\n\t\treturn false;\n\t}\n\n\tif ( this.allowArbitrary ) {\n\t\treturn true;\n\t}\n\n\t// Check with allowed values\n\tif (\n\t\tthis.getAllowedValues().some( function ( value ) {\n\t\t\treturn data === value;\n\t\t} )\n\t) {\n\t\treturn true;\n\t}\n\n\treturn false;\n};\n\n/**\n * Get the allowed values list\n *\n * @return {string[]} Allowed data values\n */\nOO.ui.TagMultiselectWidget.prototype.getAllowedValues = function () {\n\treturn this.allowedValues;\n};\n\n/**\n * Add a value to the allowed values list\n *\n * @param {string} value Allowed data value\n */\nOO.ui.TagMultiselectWidget.prototype.addAllowedValue = function ( value ) {\n\tif ( this.allowedValues.indexOf( value ) === -1 ) {\n\t\tthis.allowedValues.push( value );\n\t}\n};\n\n/**\n * Get the datas of the currently selected items\n *\n * @return {string[]|Object[]} Datas of currently selected items\n */\nOO.ui.TagMultiselectWidget.prototype.getValue = function () {\n\treturn this.getItems()\n\t\t.filter( function ( item ) {\n\t\t\treturn item.isValid();\n\t\t} )\n\t\t.map( function ( item ) {\n\t\t\treturn item.getData();\n\t\t} );\n};\n\n/**\n * Set the value of this widget by datas.\n *\n * @param {string|string[]|Object|Object[]} valueObject An object representing the data\n * and label of the value. If the widget allows arbitrary values,\n * the items will be added as-is. Otherwise, the data value will\n * be checked against allowedValues.\n * This object must contain at least a data key. Example:\n * { data: 'foo', label: 'Foo item' }\n * For multiple items, use an array of objects. For example:\n * [\n * { data: 'foo', label: 'Foo item' },\n * { data: 'bar', label: 'Bar item' }\n * \t ]\n * Value can also be added with plaintext array, for example:\n * [ 'foo', 'bar', 'bla' ] or a single string, like 'foo'\n */\nOO.ui.TagMultiselectWidget.prototype.setValue = function ( valueObject ) {\n\tvalueObject = Array.isArray( valueObject ) ? valueObject : [ valueObject ];\n\n\tthis.clearItems();\n\tvalueObject.forEach( function ( obj ) {\n\t\tif ( typeof obj === 'string' ) {\n\t\t\tthis.addTag( obj );\n\t\t} else {\n\t\t\tthis.addTag( obj.data, obj.label );\n\t\t}\n\t}.bind( this ) );\n};\n\n/**\n * Add tag to the display area\n *\n * @param {string|Object} data Tag data\n * @param {string} [label] Tag label. If no label is provided, the\n * stringified version of the data will be used instead.\n * @return {boolean} Item was added successfully\n */\nOO.ui.TagMultiselectWidget.prototype.addTag = function ( data, label ) {\n\tvar newItemWidget,\n\t\tisValid = this.isAllowedData( data );\n\n\tif ( isValid || this.allowDisplayInvalidTags ) {\n\t\tnewItemWidget = this.createTagItemWidget( data, label );\n\t\tnewItemWidget.toggleValid( isValid );\n\t\tthis.addItems( [ newItemWidget ] );\n\t\treturn true;\n\t}\n\treturn false;\n};\n\n/**\n * Remove tag by its data property.\n *\n * @param {string|Object} data Tag data\n */\nOO.ui.TagMultiselectWidget.prototype.removeTagByData = function ( data ) {\n\tvar item = this.getItemFromData( data );\n\n\tthis.removeItems( [ item ] );\n};\n\n/**\n * Construct a OO.ui.TagItemWidget (or a subclass thereof) from given label and data.\n *\n * @protected\n * @param {string} data Item data\n * @param {string} label The label text.\n * @return {OO.ui.TagItemWidget}\n */\nOO.ui.TagMultiselectWidget.prototype.createTagItemWidget = function ( data, label ) {\n\tlabel = label || data;\n\n\treturn new OO.ui.TagItemWidget( { data: data, label: label } );\n};\n\n/**\n * Given an item, returns the item after it. If the item is already the\n * last item, return `this.input`. If no item is passed, returns the\n * very first item.\n *\n * @protected\n * @param {OO.ui.TagItemWidget} [item] Tag item\n * @return {OO.ui.Widget} The next widget available.\n */\nOO.ui.TagMultiselectWidget.prototype.getNextItem = function ( item ) {\n\tvar itemIndex = this.items.indexOf( item );\n\n\tif ( item === undefined || itemIndex === -1 ) {\n\t\treturn this.items[ 0 ];\n\t}\n\n\tif ( itemIndex === this.items.length - 1 ) { // Last item\n\t\tif ( this.hasInput ) {\n\t\t\treturn this.input;\n\t\t} else {\n\t\t\t// Return first item\n\t\t\treturn this.items[ 0 ];\n\t\t}\n\t} else {\n\t\treturn this.items[ itemIndex + 1 ];\n\t}\n};\n\n/**\n * Given an item, returns the item before it. If the item is already the\n * first item, return `this.input`. If no item is passed, returns the\n * very last item.\n *\n * @protected\n * @param {OO.ui.TagItemWidget} [item] Tag item\n * @return {OO.ui.Widget} The previous widget available.\n */\nOO.ui.TagMultiselectWidget.prototype.getPreviousItem = function ( item ) {\n\tvar itemIndex = this.items.indexOf( item );\n\n\tif ( item === undefined || itemIndex === -1 ) {\n\t\treturn this.items[ this.items.length - 1 ];\n\t}\n\n\tif ( itemIndex === 0 ) {\n\t\tif ( this.hasInput ) {\n\t\t\treturn this.input;\n\t\t} else {\n\t\t\t// Return the last item\n\t\t\treturn this.items[ this.items.length - 1 ];\n\t\t}\n\t} else {\n\t\treturn this.items[ itemIndex - 1 ];\n\t}\n};\n\n/**\n * Update the dimensions of the text input field to encompass all available area.\n * This is especially relevant for when the input is at the edge of a line\n * and should get smaller. The usual operation (as an inline-block with min-width)\n * does not work in that case, pushing the input downwards to the next line.\n *\n * @private\n */\nOO.ui.TagMultiselectWidget.prototype.updateInputSize = function () {\n\tvar $lastItem, direction, contentWidth, currentWidth, bestWidth;\n\tif ( this.inputPosition === 'inline' && !this.isDisabled() ) {\n\t\tif ( this.input.$input[ 0 ].scrollWidth === 0 ) {\n\t\t\t// Input appears to be attached but not visible.\n\t\t\t// Don't attempt to adjust its size, because our measurements\n\t\t\t// are going to fail anyway.\n\t\t\treturn;\n\t\t}\n\t\tthis.input.$input.css( 'width', '1em' );\n\t\t$lastItem = this.$group.children().last();\n\t\tdirection = OO.ui.Element.static.getDir( this.$handle );\n\n\t\t// Get the width of the input with the placeholder text as\n\t\t// the value and save it so that we don't keep recalculating\n\t\tif (\n\t\t\tthis.contentWidthWithPlaceholder === undefined &&\n\t\t\tthis.input.getValue() === '' &&\n\t\t\tthis.input.$input.attr( 'placeholder' ) !== undefined\n\t\t) {\n\t\t\tthis.input.setValue( this.input.$input.attr( 'placeholder' ) );\n\t\t\tthis.contentWidthWithPlaceholder = this.input.$input[ 0 ].scrollWidth;\n\t\t\tthis.input.setValue( '' );\n\n\t\t}\n\n\t\t// Always keep the input wide enough for the placeholder text\n\t\tcontentWidth = Math.max(\n\t\t\tthis.input.$input[ 0 ].scrollWidth,\n\t\t\t// undefined arguments in Math.max lead to NaN\n\t\t\t( this.contentWidthWithPlaceholder === undefined ) ?\n\t\t\t\t0 : this.contentWidthWithPlaceholder\n\t\t);\n\t\tcurrentWidth = this.input.$input.width();\n\n\t\tif ( contentWidth < currentWidth ) {\n\t\t\tthis.updateIfHeightChanged();\n\t\t\t// All is fine, don't perform expensive calculations\n\t\t\treturn;\n\t\t}\n\n\t\tif ( $lastItem.length === 0 ) {\n\t\t\tbestWidth = this.$content.innerWidth();\n\t\t} else {\n\t\t\tbestWidth = direction === 'ltr' ?\n\t\t\t\tthis.$content.innerWidth() - $lastItem.position().left - $lastItem.outerWidth() :\n\t\t\t\t$lastItem.position().left;\n\t\t}\n\n\t\t// Some safety margin for sanity, because I *really* don't feel like finding out where the few\n\t\t// pixels this is off by are coming from.\n\t\tbestWidth -= 10;\n\t\tif ( contentWidth > bestWidth ) {\n\t\t\t// This will result in the input getting shifted to the next line\n\t\t\tbestWidth = this.$content.innerWidth() - 10;\n\t\t}\n\t\tthis.input.$input.width( Math.floor( bestWidth ) );\n\t\tthis.updateIfHeightChanged();\n\t} else {\n\t\tthis.updateIfHeightChanged();\n\t}\n};\n\n/**\n * Determine if widget height changed, and if so,\n * emit the resize event. This is useful for when there are either\n * menus or popups attached to the bottom of the widget, to allow\n * them to change their positioning in case the widget moved down\n * or up.\n *\n * @private\n */\nOO.ui.TagMultiselectWidget.prototype.updateIfHeightChanged = function () {\n\tvar height = this.$element.height();\n\tif ( height !== this.height ) {\n\t\tthis.height = height;\n\t\tthis.emit( 'resize' );\n\t}\n};\n\n/**\n * Check whether all items in the widget are valid\n *\n * @return {boolean} Widget is valid\n */\nOO.ui.TagMultiselectWidget.prototype.checkValidity = function () {\n\treturn this.getItems().every( function ( item ) {\n\t\treturn item.isValid();\n\t} );\n};\n\n/**\n * Set the valid state of this item\n *\n * @param {boolean} [valid] Item is valid\n * @fires valid\n */\nOO.ui.TagMultiselectWidget.prototype.toggleValid = function ( valid ) {\n\tvalid = valid === undefined ? !this.valid : !!valid;\n\n\tif ( this.valid !== valid ) {\n\t\tthis.valid = valid;\n\n\t\tthis.setFlags( { invalid: !this.valid } );\n\n\t\tthis.emit( 'valid', this.valid );\n\t}\n};\n\n/**\n * Get the current valid state of the widget\n *\n * @return {boolean} Widget is valid\n */\nOO.ui.TagMultiselectWidget.prototype.isValid = function () {\n\treturn this.valid;\n};\n","/**\n * PopupTagMultiselectWidget is a {@link OO.ui.TagMultiselectWidget OO.ui.TagMultiselectWidget} intended\n * to use a popup. The popup can be configured to have a default input to insert values into the widget.\n *\n * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * @example\n * // Example: A basic PopupTagMultiselectWidget.\n * var widget = new OO.ui.PopupTagMultiselectWidget();\n * $( 'body' ).append( widget.$element );\n *\n * // Example: A PopupTagMultiselectWidget with an external popup.\n * var popupInput = new OO.ui.TextInputWidget(),\n * widget = new OO.ui.PopupTagMultiselectWidget( {\n * popupInput: popupInput,\n * popup: {\n * $content: popupInput.$element\n * }\n * } );\n * $( 'body' ).append( widget.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options\n *\n * @class\n * @extends OO.ui.TagMultiselectWidget\n * @mixins OO.ui.mixin.PopupElement\n *\n * @param {Object} config Configuration object\n * @cfg {jQuery} [$overlay] An overlay for the popup.\n * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.\n * @cfg {Object} [popup] Configuration options for the popup\n * @cfg {OO.ui.InputWidget} [popupInput] An input widget inside the popup that will be\n * focused when the popup is opened and will be used as replacement for the\n * general input in the widget.\n */\nOO.ui.PopupTagMultiselectWidget = function OoUiPopupTagMultiselectWidget( config ) {\n\tvar defaultInput,\n\t\tdefaultConfig = { popup: {} };\n\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.PopupTagMultiselectWidget.parent.call( this, $.extend( { inputPosition: 'none' }, config ) );\n\n\tthis.$overlay = config.$overlay || this.$element;\n\n\tif ( !config.popup ) {\n\t\t// For the default base implementation, we give a popup\n\t\t// with an input widget inside it. For any other use cases\n\t\t// the popup needs to be populated externally and the\n\t\t// event handled to add tags separately and manually\n\t\tdefaultInput = new OO.ui.TextInputWidget();\n\n\t\tdefaultConfig.popupInput = defaultInput;\n\t\tdefaultConfig.popup.$content = defaultInput.$element;\n\n\t\tthis.$element.addClass( 'oo-ui-popupTagMultiselectWidget-defaultPopup' );\n\t}\n\n\t// Add overlay, and add that to the autoCloseIgnore\n\tdefaultConfig.popup.$overlay = this.$overlay;\n\tdefaultConfig.popup.$autoCloseIgnore = this.hasInput ?\n\t\tthis.input.$element.add( this.$overlay ) : this.$overlay;\n\n\t// Allow extending any of the above\n\tconfig = $.extend( defaultConfig, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.PopupElement.call( this, config );\n\n\tif ( this.hasInput ) {\n\t\tthis.input.$input.on( 'focus', this.popup.toggle.bind( this.popup, true ) );\n\t}\n\n\t// Configuration options\n\tthis.popupInput = config.popupInput;\n\tif ( this.popupInput ) {\n\t\tthis.popupInput.connect( this, {\n\t\t\tenter: 'onPopupInputEnter'\n\t\t} );\n\t}\n\n\t// Events\n\tthis.on( 'resize', this.popup.updateDimensions.bind( this.popup ) );\n\tthis.popup.connect( this, { toggle: 'onPopupToggle' } );\n\tthis.$tabIndexed\n\t\t.on( 'focus', this.onFocus.bind( this ) );\n\n\t// Initialize\n\tthis.$element\n\t\t.append( this.popup.$element )\n\t\t.addClass( 'oo-ui-popupTagMultiselectWidget' );\n};\n\n/* Initialization */\n\nOO.inheritClass( OO.ui.PopupTagMultiselectWidget, OO.ui.TagMultiselectWidget );\nOO.mixinClass( OO.ui.PopupTagMultiselectWidget, OO.ui.mixin.PopupElement );\n\n/* Methods */\n\n/**\n * Focus event handler.\n *\n * @private\n */\nOO.ui.PopupTagMultiselectWidget.prototype.onFocus = function () {\n\tthis.popup.toggle( true );\n};\n\n/**\n * Respond to popup toggle event\n *\n * @param {boolean} isVisible Popup is visible\n */\nOO.ui.PopupTagMultiselectWidget.prototype.onPopupToggle = function ( isVisible ) {\n\tif ( isVisible && this.popupInput ) {\n\t\tthis.popupInput.focus();\n\t}\n};\n\n/**\n * Respond to popup input enter event\n */\nOO.ui.PopupTagMultiselectWidget.prototype.onPopupInputEnter = function () {\n\tif ( this.popupInput ) {\n\t\tthis.addTagByPopupValue( this.popupInput.getValue() );\n\t\tthis.popupInput.setValue( '' );\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.PopupTagMultiselectWidget.prototype.onTagSelect = function ( item ) {\n\tif ( this.popupInput && this.allowEditTags ) {\n\t\tthis.popupInput.setValue( item.getData() );\n\t\tthis.removeItems( [ item ] );\n\n\t\tthis.popup.toggle( true );\n\t\tthis.popupInput.focus();\n\t} else {\n\t\t// Parent\n\t\tOO.ui.PopupTagMultiselectWidget.parent.prototype.onTagSelect.call( this, item );\n\t}\n};\n\n/**\n * Add a tag by the popup value.\n * Whatever is responsible for setting the value in the popup should call\n * this method to add a tag, or use the regular methods like #addTag or\n * #setValue directly.\n *\n * @param {string} data The value of item\n * @param {string} [label] The label of the tag. If not given, the data is used.\n */\nOO.ui.PopupTagMultiselectWidget.prototype.addTagByPopupValue = function ( data, label ) {\n\tthis.addTag( data, label );\n};\n","/**\n * MenuTagMultiselectWidget is a {@link OO.ui.TagMultiselectWidget OO.ui.TagMultiselectWidget} intended\n * to use a menu of selectable options.\n *\n * For more information about menus and options, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * @example\n * // Example: A basic MenuTagMultiselectWidget.\n * var widget = new OO.ui.MenuTagMultiselectWidget( {\n * inputPosition: 'outline',\n * options: [\n * { data: 'option1', label: 'Option 1' },\n * { data: 'option2', label: 'Option 2' },\n * { data: 'option3', label: 'Option 3' },\n * ],\n * selected: [ 'option1', 'option2' ]\n * } );\n * $( 'body' ).append( widget.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Selects_and_Options#Menu_selects_and_options\n *\n * @class\n * @extends OO.ui.TagMultiselectWidget\n *\n * @constructor\n * @param {Object} [config] Configuration object\n * @cfg {Object} [menu] Configuration object for the menu widget\n * @cfg {jQuery} [$overlay] An overlay for the menu.\n * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.\n * @cfg {Object[]} [options=[]] Array of menu options in the format `{ data: …, label: … }`\n */\nOO.ui.MenuTagMultiselectWidget = function OoUiMenuTagMultiselectWidget( config ) {\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.MenuTagMultiselectWidget.parent.call( this, config );\n\n\tthis.$overlay = config.$overlay || this.$element;\n\n\tthis.menu = this.createMenuWidget( $.extend( {\n\t\twidget: this,\n\t\tinput: this.hasInput ? this.input : null,\n\t\t$input: this.hasInput ? this.input.$input : null,\n\t\tfilterFromInput: !!this.hasInput,\n\t\t$autoCloseIgnore: this.hasInput ?\n\t\t\tthis.input.$element.add( this.$overlay ) : this.$overlay,\n\t\t$floatableContainer: this.hasInput && this.inputPosition === 'outline' ?\n\t\t\tthis.input.$element : this.$element,\n\t\t$overlay: this.$overlay,\n\t\tdisabled: this.isDisabled()\n\t}, config.menu ) );\n\tthis.addOptions( config.options || [] );\n\n\t// Events\n\tthis.menu.connect( this, {\n\t\tchoose: 'onMenuChoose',\n\t\ttoggle: 'onMenuToggle'\n\t} );\n\tif ( this.hasInput ) {\n\t\tthis.input.connect( this, { change: 'onInputChange' } );\n\t}\n\tthis.connect( this, { resize: 'onResize' } );\n\n\t// Initialization\n\tthis.$overlay\n\t\t.append( this.menu.$element );\n\tthis.$element\n\t\t.addClass( 'oo-ui-menuTagMultiselectWidget' );\n\t// TagMultiselectWidget already does this, but it doesn't work right because this.menu is not yet\n\t// set up while the parent constructor runs, and #getAllowedValues rejects everything.\n\tif ( config.selected ) {\n\t\tthis.setValue( config.selected );\n\t}\n};\n\n/* Initialization */\n\nOO.inheritClass( OO.ui.MenuTagMultiselectWidget, OO.ui.TagMultiselectWidget );\n\n/* Methods */\n\n/**\n * Respond to resize event\n */\nOO.ui.MenuTagMultiselectWidget.prototype.onResize = function () {\n\t// Reposition the menu\n\tthis.menu.position();\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MenuTagMultiselectWidget.prototype.onInputFocus = function () {\n\t// Parent method\n\tOO.ui.MenuTagMultiselectWidget.parent.prototype.onInputFocus.call( this );\n\n\tthis.menu.toggle( true );\n};\n\n/**\n * Respond to input change event\n */\nOO.ui.MenuTagMultiselectWidget.prototype.onInputChange = function () {\n\tthis.menu.toggle( true );\n};\n\n/**\n * Respond to menu choose event\n *\n * @param {OO.ui.OptionWidget} menuItem Chosen menu item\n */\nOO.ui.MenuTagMultiselectWidget.prototype.onMenuChoose = function ( menuItem ) {\n\t// Add tag\n\tthis.addTag( menuItem.getData(), menuItem.getLabel() );\n};\n\n/**\n * Respond to menu toggle event. Reset item highlights on hide.\n *\n * @param {boolean} isVisible The menu is visible\n */\nOO.ui.MenuTagMultiselectWidget.prototype.onMenuToggle = function ( isVisible ) {\n\tif ( !isVisible ) {\n\t\tthis.menu.selectItem( null );\n\t\tthis.menu.highlightItem( null );\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MenuTagMultiselectWidget.prototype.onTagSelect = function ( tagItem ) {\n\tvar menuItem = this.menu.getItemFromData( tagItem.getData() );\n\t// Override the base behavior from TagMultiselectWidget; the base behavior\n\t// in TagMultiselectWidget is to remove the tag to edit it in the input,\n\t// but in our case, we want to utilize the menu selection behavior, and\n\t// definitely not remove the item.\n\n\t// Select the menu item\n\tthis.menu.selectItem( menuItem );\n\n\tthis.focus();\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MenuTagMultiselectWidget.prototype.addTagFromInput = function () {\n\tvar inputValue = this.input.getValue(),\n\t\tvalidated = false,\n\t\thighlightedItem = this.menu.getHighlightedItem(),\n\t\titem = this.menu.getItemFromData( inputValue );\n\n\t// Override the parent method so we add from the menu\n\t// rather than directly from the input\n\n\t// Look for a highlighted item first\n\tif ( highlightedItem ) {\n\t\tvalidated = this.addTag( highlightedItem.getData(), highlightedItem.getLabel() );\n\t} else if ( item ) {\n\t\t// Look for the element that fits the data\n\t\tvalidated = this.addTag( item.getData(), item.getLabel() );\n\t} else {\n\t\t// Otherwise, add the tag - the method will only add if the\n\t\t// tag is valid or if invalid tags are allowed\n\t\tvalidated = this.addTag( inputValue );\n\t}\n\n\tif ( validated ) {\n\t\tthis.clearInput();\n\t\tthis.focus();\n\t}\n};\n\n/**\n * Return the visible items in the menu. This is mainly used for when\n * the menu is filtering results.\n *\n * @return {OO.ui.MenuOptionWidget[]} Visible results\n */\nOO.ui.MenuTagMultiselectWidget.prototype.getMenuVisibleItems = function () {\n\treturn this.menu.getItems().filter( function ( menuItem ) {\n\t\treturn menuItem.isVisible();\n\t} );\n};\n\n/**\n * Create the menu for this widget. This is in a separate method so that\n * child classes can override this without polluting the constructor with\n * unnecessary extra objects that will be overidden.\n *\n * @param {Object} menuConfig Configuration options\n * @return {OO.ui.MenuSelectWidget} Menu widget\n */\nOO.ui.MenuTagMultiselectWidget.prototype.createMenuWidget = function ( menuConfig ) {\n\treturn new OO.ui.MenuSelectWidget( menuConfig );\n};\n\n/**\n * Add options to the menu\n *\n * @param {Object[]} menuOptions Object defining options\n */\nOO.ui.MenuTagMultiselectWidget.prototype.addOptions = function ( menuOptions ) {\n\tvar widget = this,\n\t\titems = menuOptions.map( function ( obj ) {\n\t\t\treturn widget.createMenuOptionWidget( obj.data, obj.label );\n\t\t} );\n\n\tthis.menu.addItems( items );\n};\n\n/**\n * Create a menu option widget.\n *\n * @param {string} data Item data\n * @param {string} [label] Item label\n * @return {OO.ui.OptionWidget} Option widget\n */\nOO.ui.MenuTagMultiselectWidget.prototype.createMenuOptionWidget = function ( data, label ) {\n\treturn new OO.ui.MenuOptionWidget( {\n\t\tdata: data,\n\t\tlabel: label || data\n\t} );\n};\n\n/**\n * Get the menu\n *\n * @return {OO.ui.MenuSelectWidget} Menu\n */\nOO.ui.MenuTagMultiselectWidget.prototype.getMenu = function () {\n\treturn this.menu;\n};\n\n/**\n * Get the allowed values list\n *\n * @return {string[]} Allowed data values\n */\nOO.ui.MenuTagMultiselectWidget.prototype.getAllowedValues = function () {\n\tvar menuDatas = [];\n\tif ( this.menu ) {\n\t\t// If the parent constructor is calling us, we're not ready yet, this.menu is not set up.\n\t\tmenuDatas = this.menu.getItems().map( function ( menuItem ) {\n\t\t\treturn menuItem.getData();\n\t\t} );\n\t}\n\treturn this.allowedValues.concat( menuDatas );\n};\n","/**\n * SelectFileWidgets allow for selecting files, using the HTML5 File API. These\n * widgets can be configured with {@link OO.ui.mixin.IconElement icons} and {@link\n * OO.ui.mixin.IndicatorElement indicators}.\n * Please see the [OOjs UI documentation on MediaWiki] [1] for more information and examples.\n *\n * @example\n * // Example of a file select widget\n * var selectFile = new OO.ui.SelectFileWidget();\n * $( 'body' ).append( selectFile.$element );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets\n *\n * @class\n * @extends OO.ui.Widget\n * @mixins OO.ui.mixin.IconElement\n * @mixins OO.ui.mixin.IndicatorElement\n * @mixins OO.ui.mixin.PendingElement\n * @mixins OO.ui.mixin.LabelElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string[]|null} [accept=null] MIME types to accept. null accepts all types.\n * @cfg {string} [placeholder] Text to display when no file is selected.\n * @cfg {string} [notsupported] Text to display when file support is missing in the browser.\n * @cfg {boolean} [droppable=true] Whether to accept files by drag and drop.\n * @cfg {boolean} [showDropTarget=false] Whether to show a drop target. Requires droppable to be true.\n * @cfg {number} [thumbnailSizeLimit=20] File size limit in MiB above which to not try and show a\n * preview (for performance)\n */\nOO.ui.SelectFileWidget = function OoUiSelectFileWidget( config ) {\n\tvar dragHandler;\n\n\t// Configuration initialization\n\tconfig = $.extend( {\n\t\taccept: null,\n\t\tplaceholder: OO.ui.msg( 'ooui-selectfile-placeholder' ),\n\t\tnotsupported: OO.ui.msg( 'ooui-selectfile-not-supported' ),\n\t\tdroppable: true,\n\t\tshowDropTarget: false,\n\t\tthumbnailSizeLimit: 20\n\t}, config );\n\n\t// Parent constructor\n\tOO.ui.SelectFileWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.IconElement.call( this, config );\n\tOO.ui.mixin.IndicatorElement.call( this, config );\n\tOO.ui.mixin.PendingElement.call( this, $.extend( {}, config, { $pending: this.$info } ) );\n\tOO.ui.mixin.LabelElement.call( this, config );\n\n\t// Properties\n\tthis.$info = $( '<span>' );\n\tthis.showDropTarget = config.showDropTarget;\n\tthis.thumbnailSizeLimit = config.thumbnailSizeLimit;\n\tthis.isSupported = this.constructor.static.isSupported();\n\tthis.currentFile = null;\n\tif ( Array.isArray( config.accept ) ) {\n\t\tthis.accept = config.accept;\n\t} else {\n\t\tthis.accept = null;\n\t}\n\tthis.placeholder = config.placeholder;\n\tthis.notsupported = config.notsupported;\n\tthis.onFileSelectedHandler = this.onFileSelected.bind( this );\n\n\tthis.selectButton = new OO.ui.ButtonWidget( {\n\t\tclasses: [ 'oo-ui-selectFileWidget-selectButton' ],\n\t\tlabel: OO.ui.msg( 'ooui-selectfile-button-select' ),\n\t\tdisabled: this.disabled || !this.isSupported\n\t} );\n\n\tthis.clearButton = new OO.ui.ButtonWidget( {\n\t\tclasses: [ 'oo-ui-selectFileWidget-clearButton' ],\n\t\tframed: false,\n\t\ticon: 'close',\n\t\tdisabled: this.disabled\n\t} );\n\n\t// Events\n\tthis.selectButton.$button.on( {\n\t\tkeypress: this.onKeyPress.bind( this )\n\t} );\n\tthis.clearButton.connect( this, {\n\t\tclick: 'onClearClick'\n\t} );\n\tif ( config.droppable ) {\n\t\tdragHandler = this.onDragEnterOrOver.bind( this );\n\t\tthis.$element.on( {\n\t\t\tdragenter: dragHandler,\n\t\t\tdragover: dragHandler,\n\t\t\tdragleave: this.onDragLeave.bind( this ),\n\t\t\tdrop: this.onDrop.bind( this )\n\t\t} );\n\t}\n\n\t// Initialization\n\tthis.addInput();\n\tthis.$label.addClass( 'oo-ui-selectFileWidget-label' );\n\tthis.$info\n\t\t.addClass( 'oo-ui-selectFileWidget-info' )\n\t\t.append( this.$icon, this.$label, this.clearButton.$element, this.$indicator );\n\n\tif ( config.droppable && config.showDropTarget ) {\n\t\tthis.selectButton.setIcon( 'upload' );\n\t\tthis.$thumbnail = $( '<div>' ).addClass( 'oo-ui-selectFileWidget-thumbnail' );\n\t\tthis.setPendingElement( this.$thumbnail );\n\t\tthis.$element\n\t\t\t.addClass( 'oo-ui-selectFileWidget-dropTarget oo-ui-selectFileWidget' )\n\t\t\t.on( {\n\t\t\t\tclick: this.onDropTargetClick.bind( this )\n\t\t\t} )\n\t\t\t.append(\n\t\t\t\tthis.$thumbnail,\n\t\t\t\tthis.$info,\n\t\t\t\tthis.selectButton.$element,\n\t\t\t\t$( '<span>' )\n\t\t\t\t\t.addClass( 'oo-ui-selectFileWidget-dropLabel' )\n\t\t\t\t\t.text( OO.ui.msg( 'ooui-selectfile-dragdrop-placeholder' ) )\n\t\t\t);\n\t} else {\n\t\tthis.$element\n\t\t\t.addClass( 'oo-ui-selectFileWidget' )\n\t\t\t.append( this.$info, this.selectButton.$element );\n\t}\n\tthis.updateUI();\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.SelectFileWidget, OO.ui.Widget );\nOO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.IconElement );\nOO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.IndicatorElement );\nOO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.PendingElement );\nOO.mixinClass( OO.ui.SelectFileWidget, OO.ui.mixin.LabelElement );\n\n/* Static Properties */\n\n/**\n * Check if this widget is supported\n *\n * @static\n * @return {boolean}\n */\nOO.ui.SelectFileWidget.static.isSupported = function () {\n\tvar $input;\n\tif ( OO.ui.SelectFileWidget.static.isSupportedCache === null ) {\n\t\t$input = $( '<input>' ).attr( 'type', 'file' );\n\t\tOO.ui.SelectFileWidget.static.isSupportedCache = $input[ 0 ].files !== undefined;\n\t}\n\treturn OO.ui.SelectFileWidget.static.isSupportedCache;\n};\n\nOO.ui.SelectFileWidget.static.isSupportedCache = null;\n\n/* Events */\n\n/**\n * @event change\n *\n * A change event is emitted when the on/off state of the toggle changes.\n *\n * @param {File|null} value New value\n */\n\n/* Methods */\n\n/**\n * Get the current value of the field\n *\n * @return {File|null}\n */\nOO.ui.SelectFileWidget.prototype.getValue = function () {\n\treturn this.currentFile;\n};\n\n/**\n * Set the current value of the field\n *\n * @param {File|null} file File to select\n */\nOO.ui.SelectFileWidget.prototype.setValue = function ( file ) {\n\tif ( this.currentFile !== file ) {\n\t\tthis.currentFile = file;\n\t\tthis.updateUI();\n\t\tthis.emit( 'change', this.currentFile );\n\t}\n};\n\n/**\n * Focus the widget.\n *\n * Focusses the select file button.\n *\n * @chainable\n */\nOO.ui.SelectFileWidget.prototype.focus = function () {\n\tthis.selectButton.focus();\n\treturn this;\n};\n\n/**\n * Blur the widget.\n *\n * @chainable\n */\nOO.ui.SelectFileWidget.prototype.blur = function () {\n\tthis.selectButton.blur();\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.SelectFileWidget.prototype.simulateLabelClick = function () {\n\tthis.focus();\n};\n\n/**\n * Update the user interface when a file is selected or unselected\n *\n * @protected\n */\nOO.ui.SelectFileWidget.prototype.updateUI = function () {\n\tvar $label;\n\tif ( !this.isSupported ) {\n\t\tthis.$element.addClass( 'oo-ui-selectFileWidget-notsupported' );\n\t\tthis.$element.removeClass( 'oo-ui-selectFileWidget-empty' );\n\t\tthis.setLabel( this.notsupported );\n\t} else {\n\t\tthis.$element.addClass( 'oo-ui-selectFileWidget-supported' );\n\t\tif ( this.currentFile ) {\n\t\t\tthis.$element.removeClass( 'oo-ui-selectFileWidget-empty' );\n\t\t\t$label = $( [] );\n\t\t\t$label = $label.add(\n\t\t\t\t$( '<span>' )\n\t\t\t\t\t.addClass( 'oo-ui-selectFileWidget-fileName' )\n\t\t\t\t\t.text( this.currentFile.name )\n\t\t\t);\n\t\t\tthis.setLabel( $label );\n\n\t\t\tif ( this.showDropTarget ) {\n\t\t\t\tthis.pushPending();\n\t\t\t\tthis.loadAndGetImageUrl().done( function ( url ) {\n\t\t\t\t\tthis.$thumbnail.css( 'background-image', 'url( ' + url + ' )' );\n\t\t\t\t}.bind( this ) ).fail( function () {\n\t\t\t\t\tthis.$thumbnail.append(\n\t\t\t\t\t\tnew OO.ui.IconWidget( {\n\t\t\t\t\t\t\ticon: 'attachment',\n\t\t\t\t\t\t\tclasses: [ 'oo-ui-selectFileWidget-noThumbnail-icon' ]\n\t\t\t\t\t\t} ).$element\n\t\t\t\t\t);\n\t\t\t\t}.bind( this ) ).always( function () {\n\t\t\t\t\tthis.popPending();\n\t\t\t\t}.bind( this ) );\n\t\t\t\tthis.$element.off( 'click' );\n\t\t\t}\n\t\t} else {\n\t\t\tif ( this.showDropTarget ) {\n\t\t\t\tthis.$element.off( 'click' );\n\t\t\t\tthis.$element.on( {\n\t\t\t\t\tclick: this.onDropTargetClick.bind( this )\n\t\t\t\t} );\n\t\t\t\tthis.$thumbnail\n\t\t\t\t\t.empty()\n\t\t\t\t\t.css( 'background-image', '' );\n\t\t\t}\n\t\t\tthis.$element.addClass( 'oo-ui-selectFileWidget-empty' );\n\t\t\tthis.setLabel( this.placeholder );\n\t\t}\n\t}\n};\n\n/**\n * If the selected file is an image, get its URL and load it.\n *\n * @return {jQuery.Promise} Promise resolves with the image URL after it has loaded\n */\nOO.ui.SelectFileWidget.prototype.loadAndGetImageUrl = function () {\n\tvar deferred = $.Deferred(),\n\t\tfile = this.currentFile,\n\t\treader = new FileReader();\n\n\tif (\n\t\tfile &&\n\t\t( OO.getProp( file, 'type' ) || '' ).indexOf( 'image/' ) === 0 &&\n\t\tfile.size < this.thumbnailSizeLimit * 1024 * 1024\n\t) {\n\t\treader.onload = function ( event ) {\n\t\t\tvar img = document.createElement( 'img' );\n\t\t\timg.addEventListener( 'load', function () {\n\t\t\t\tif (\n\t\t\t\t\timg.naturalWidth === 0 ||\n\t\t\t\t\timg.naturalHeight === 0 ||\n\t\t\t\t\timg.complete === false\n\t\t\t\t) {\n\t\t\t\t\tdeferred.reject();\n\t\t\t\t} else {\n\t\t\t\t\tdeferred.resolve( event.target.result );\n\t\t\t\t}\n\t\t\t} );\n\t\t\timg.src = event.target.result;\n\t\t};\n\t\treader.readAsDataURL( file );\n\t} else {\n\t\tdeferred.reject();\n\t}\n\n\treturn deferred.promise();\n};\n\n/**\n * Add the input to the widget\n *\n * @private\n */\nOO.ui.SelectFileWidget.prototype.addInput = function () {\n\tif ( this.$input ) {\n\t\tthis.$input.remove();\n\t}\n\n\tif ( !this.isSupported ) {\n\t\tthis.$input = null;\n\t\treturn;\n\t}\n\n\tthis.$input = $( '<input>' ).attr( 'type', 'file' );\n\tthis.$input.on( 'change', this.onFileSelectedHandler );\n\tthis.$input.on( 'click', function ( e ) {\n\t\t// Prevents dropTarget to get clicked which calls\n\t\t// a click on this input\n\t\te.stopPropagation();\n\t} );\n\tthis.$input.attr( {\n\t\ttabindex: -1\n\t} );\n\tif ( this.accept ) {\n\t\tthis.$input.attr( 'accept', this.accept.join( ', ' ) );\n\t}\n\tthis.selectButton.$button.append( this.$input );\n};\n\n/**\n * Determine if we should accept this file\n *\n * @private\n * @param {string} mimeType File MIME type\n * @return {boolean}\n */\nOO.ui.SelectFileWidget.prototype.isAllowedType = function ( mimeType ) {\n\tvar i, mimeTest;\n\n\tif ( !this.accept || !mimeType ) {\n\t\treturn true;\n\t}\n\n\tfor ( i = 0; i < this.accept.length; i++ ) {\n\t\tmimeTest = this.accept[ i ];\n\t\tif ( mimeTest === mimeType ) {\n\t\t\treturn true;\n\t\t} else if ( mimeTest.substr( -2 ) === '/*' ) {\n\t\t\tmimeTest = mimeTest.substr( 0, mimeTest.length - 1 );\n\t\t\tif ( mimeType.substr( 0, mimeTest.length ) === mimeTest ) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn false;\n};\n\n/**\n * Handle file selection from the input\n *\n * @private\n * @param {jQuery.Event} e\n */\nOO.ui.SelectFileWidget.prototype.onFileSelected = function ( e ) {\n\tvar file = OO.getProp( e.target, 'files', 0 ) || null;\n\n\tif ( file && !this.isAllowedType( file.type ) ) {\n\t\tfile = null;\n\t}\n\n\tthis.setValue( file );\n\tthis.addInput();\n};\n\n/**\n * Handle clear button click events.\n *\n * @private\n */\nOO.ui.SelectFileWidget.prototype.onClearClick = function () {\n\tthis.setValue( null );\n\treturn false;\n};\n\n/**\n * Handle key press events.\n *\n * @private\n * @param {jQuery.Event} e Key press event\n */\nOO.ui.SelectFileWidget.prototype.onKeyPress = function ( e ) {\n\tif ( this.isSupported && !this.isDisabled() && this.$input &&\n\t\t( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )\n\t) {\n\t\tthis.$input.click();\n\t\treturn false;\n\t}\n};\n\n/**\n * Handle drop target click events.\n *\n * @private\n * @param {jQuery.Event} e Key press event\n */\nOO.ui.SelectFileWidget.prototype.onDropTargetClick = function () {\n\tif ( this.isSupported && !this.isDisabled() && this.$input ) {\n\t\tthis.$input.click();\n\t\treturn false;\n\t}\n};\n\n/**\n * Handle drag enter and over events\n *\n * @private\n * @param {jQuery.Event} e Drag event\n */\nOO.ui.SelectFileWidget.prototype.onDragEnterOrOver = function ( e ) {\n\tvar itemOrFile,\n\t\tdroppableFile = false,\n\t\tdt = e.originalEvent.dataTransfer;\n\n\te.preventDefault();\n\te.stopPropagation();\n\n\tif ( this.isDisabled() || !this.isSupported ) {\n\t\tthis.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' );\n\t\tdt.dropEffect = 'none';\n\t\treturn false;\n\t}\n\n\t// DataTransferItem and File both have a type property, but in Chrome files\n\t// have no information at this point.\n\titemOrFile = OO.getProp( dt, 'items', 0 ) || OO.getProp( dt, 'files', 0 );\n\tif ( itemOrFile ) {\n\t\tif ( this.isAllowedType( itemOrFile.type ) ) {\n\t\t\tdroppableFile = true;\n\t\t}\n\t// dt.types is Array-like, but not an Array\n\t} else if ( Array.prototype.indexOf.call( OO.getProp( dt, 'types' ) || [], 'Files' ) !== -1 ) {\n\t\t// File information is not available at this point for security so just assume\n\t\t// it is acceptable for now.\n\t\t// https://bugzilla.mozilla.org/show_bug.cgi?id=640534\n\t\tdroppableFile = true;\n\t}\n\n\tthis.$element.toggleClass( 'oo-ui-selectFileWidget-canDrop', droppableFile );\n\tif ( !droppableFile ) {\n\t\tdt.dropEffect = 'none';\n\t}\n\n\treturn false;\n};\n\n/**\n * Handle drag leave events\n *\n * @private\n * @param {jQuery.Event} e Drag event\n */\nOO.ui.SelectFileWidget.prototype.onDragLeave = function () {\n\tthis.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' );\n};\n\n/**\n * Handle drop events\n *\n * @private\n * @param {jQuery.Event} e Drop event\n */\nOO.ui.SelectFileWidget.prototype.onDrop = function ( e ) {\n\tvar file = null,\n\t\tdt = e.originalEvent.dataTransfer;\n\n\te.preventDefault();\n\te.stopPropagation();\n\tthis.$element.removeClass( 'oo-ui-selectFileWidget-canDrop' );\n\n\tif ( this.isDisabled() || !this.isSupported ) {\n\t\treturn false;\n\t}\n\n\tfile = OO.getProp( dt, 'files', 0 );\n\tif ( file && !this.isAllowedType( file.type ) ) {\n\t\tfile = null;\n\t}\n\tif ( file ) {\n\t\tthis.setValue( file );\n\t}\n\n\treturn false;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.SelectFileWidget.prototype.setDisabled = function ( disabled ) {\n\tOO.ui.SelectFileWidget.parent.prototype.setDisabled.call( this, disabled );\n\tif ( this.selectButton ) {\n\t\tthis.selectButton.setDisabled( disabled );\n\t}\n\tif ( this.clearButton ) {\n\t\tthis.clearButton.setDisabled( disabled );\n\t}\n\treturn this;\n};\n","/**\n * SearchWidgets combine a {@link OO.ui.TextInputWidget text input field}, where users can type a search query,\n * and a menu of search results, which is displayed beneath the query\n * field. Unlike {@link OO.ui.mixin.LookupElement lookup menus}, search result menus are always visible to the user.\n * Users can choose an item from the menu or type a query into the text field to search for a matching result item.\n * In general, search widgets are used inside a separate {@link OO.ui.Dialog dialog} window.\n *\n * Each time the query is changed, the search result menu is cleared and repopulated. Please see\n * the [OOjs UI demos][1] for an example.\n *\n * [1]: https://tools.wmflabs.org/oojs-ui/oojs-ui/demos/#dialogs-mediawiki-vector-ltr\n *\n * @class\n * @extends OO.ui.Widget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string|jQuery} [placeholder] Placeholder text for query input\n * @cfg {string} [value] Initial query value\n */\nOO.ui.SearchWidget = function OoUiSearchWidget( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.SearchWidget.parent.call( this, config );\n\n\t// Properties\n\tthis.query = new OO.ui.TextInputWidget( {\n\t\ticon: 'search',\n\t\tplaceholder: config.placeholder,\n\t\tvalue: config.value\n\t} );\n\tthis.results = new OO.ui.SelectWidget();\n\tthis.$query = $( '<div>' );\n\tthis.$results = $( '<div>' );\n\n\t// Events\n\tthis.query.connect( this, {\n\t\tchange: 'onQueryChange',\n\t\tenter: 'onQueryEnter'\n\t} );\n\tthis.query.$input.on( 'keydown', this.onQueryKeydown.bind( this ) );\n\n\t// Initialization\n\tthis.$query\n\t\t.addClass( 'oo-ui-searchWidget-query' )\n\t\t.append( this.query.$element );\n\tthis.$results\n\t\t.addClass( 'oo-ui-searchWidget-results' )\n\t\t.append( this.results.$element );\n\tthis.$element\n\t\t.addClass( 'oo-ui-searchWidget' )\n\t\t.append( this.$results, this.$query );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.SearchWidget, OO.ui.Widget );\n\n/* Methods */\n\n/**\n * Handle query key down events.\n *\n * @private\n * @param {jQuery.Event} e Key down event\n */\nOO.ui.SearchWidget.prototype.onQueryKeydown = function ( e ) {\n\tvar highlightedItem, nextItem,\n\t\tdir = e.which === OO.ui.Keys.DOWN ? 1 : ( e.which === OO.ui.Keys.UP ? -1 : 0 );\n\n\tif ( dir ) {\n\t\thighlightedItem = this.results.getHighlightedItem();\n\t\tif ( !highlightedItem ) {\n\t\t\thighlightedItem = this.results.getSelectedItem();\n\t\t}\n\t\tnextItem = this.results.getRelativeSelectableItem( highlightedItem, dir );\n\t\tthis.results.highlightItem( nextItem );\n\t\tnextItem.scrollElementIntoView();\n\t}\n};\n\n/**\n * Handle select widget select events.\n *\n * Clears existing results. Subclasses should repopulate items according to new query.\n *\n * @private\n * @param {string} value New value\n */\nOO.ui.SearchWidget.prototype.onQueryChange = function () {\n\t// Reset\n\tthis.results.clearItems();\n};\n\n/**\n * Handle select widget enter key events.\n *\n * Chooses highlighted item.\n *\n * @private\n * @param {string} value New value\n */\nOO.ui.SearchWidget.prototype.onQueryEnter = function () {\n\tvar highlightedItem = this.results.getHighlightedItem();\n\tif ( highlightedItem ) {\n\t\tthis.results.chooseItem( highlightedItem );\n\t}\n};\n\n/**\n * Get the query input.\n *\n * @return {OO.ui.TextInputWidget} Query input\n */\nOO.ui.SearchWidget.prototype.getQuery = function () {\n\treturn this.query;\n};\n\n/**\n * Get the search results menu.\n *\n * @return {OO.ui.SelectWidget} Menu of search results\n */\nOO.ui.SearchWidget.prototype.getResults = function () {\n\treturn this.results;\n};\n","/**\n * NumberInputWidgets combine a {@link OO.ui.TextInputWidget text input} (where a value\n * can be entered manually) and two {@link OO.ui.ButtonWidget button widgets}\n * (to adjust the value in increments) to allow the user to enter a number.\n *\n * @example\n * // Example: A NumberInputWidget.\n * var numberInput = new OO.ui.NumberInputWidget( {\n * label: 'NumberInputWidget',\n * input: { value: 5 },\n * min: 1,\n * max: 10\n * } );\n * $( 'body' ).append( numberInput.$element );\n *\n * @class\n * @extends OO.ui.TextInputWidget\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {Object} [minusButton] Configuration options to pass to the {@link OO.ui.ButtonWidget decrementing button widget}.\n * @cfg {Object} [plusButton] Configuration options to pass to the {@link OO.ui.ButtonWidget incrementing button widget}.\n * @cfg {boolean} [allowInteger=false] Whether the field accepts only integer values.\n * @cfg {number} [min=-Infinity] Minimum allowed value\n * @cfg {number} [max=Infinity] Maximum allowed value\n * @cfg {number} [step=1] Delta when using the buttons or up/down arrow keys\n * @cfg {number|null} [pageStep] Delta when using the page-up/page-down keys. Defaults to 10 times #step.\n * @cfg {boolean} [showButtons=true] Whether to show the plus and minus buttons.\n */\nOO.ui.NumberInputWidget = function OoUiNumberInputWidget( config ) {\n\tvar $field = $( '<div>' )\n\t\t.addClass( 'oo-ui-numberInputWidget-field' );\n\n\t// Configuration initialization\n\tconfig = $.extend( {\n\t\tallowInteger: false,\n\t\tmin: -Infinity,\n\t\tmax: Infinity,\n\t\tstep: 1,\n\t\tpageStep: null,\n\t\tshowButtons: true\n\t}, config );\n\n\t// For backward compatibility\n\t$.extend( config, config.input );\n\tthis.input = this;\n\n\t// Parent constructor\n\tOO.ui.NumberInputWidget.parent.call( this, $.extend( config, {\n\t\ttype: 'number'\n\t} ) );\n\n\tif ( config.showButtons ) {\n\t\tthis.minusButton = new OO.ui.ButtonWidget( $.extend(\n\t\t\t{\n\t\t\t\tdisabled: this.isDisabled(),\n\t\t\t\ttabIndex: -1,\n\t\t\t\tclasses: [ 'oo-ui-numberInputWidget-minusButton' ],\n\t\t\t\ticon: 'subtract'\n\t\t\t},\n\t\t\tconfig.minusButton\n\t\t) );\n\t\tthis.plusButton = new OO.ui.ButtonWidget( $.extend(\n\t\t\t{\n\t\t\t\tdisabled: this.isDisabled(),\n\t\t\t\ttabIndex: -1,\n\t\t\t\tclasses: [ 'oo-ui-numberInputWidget-plusButton' ],\n\t\t\t\ticon: 'add'\n\t\t\t},\n\t\t\tconfig.plusButton\n\t\t) );\n\t}\n\n\t// Events\n\tthis.$input.on( {\n\t\tkeydown: this.onKeyDown.bind( this ),\n\t\t'wheel mousewheel DOMMouseScroll': this.onWheel.bind( this )\n\t} );\n\tif ( config.showButtons ) {\n\t\tthis.plusButton.connect( this, {\n\t\t\tclick: [ 'onButtonClick', +1 ]\n\t\t} );\n\t\tthis.minusButton.connect( this, {\n\t\t\tclick: [ 'onButtonClick', -1 ]\n\t\t} );\n\t}\n\n\t// Build the field\n\t$field.append( this.$input );\n\tif ( config.showButtons ) {\n\t\t$field\n\t\t\t.prepend( this.minusButton.$element )\n\t\t\t.append( this.plusButton.$element );\n\t}\n\n\t// Initialization\n\tthis.setAllowInteger( config.allowInteger || config.isInteger );\n\tthis.setRange( config.min, config.max );\n\tthis.setStep( config.step, config.pageStep );\n\t// Set the validation method after we set allowInteger and range\n\t// so that it doesn't immediately call setValidityFlag\n\tthis.setValidation( this.validateNumber.bind( this ) );\n\n\tthis.$element\n\t\t.addClass( 'oo-ui-numberInputWidget' )\n\t\t.toggleClass( 'oo-ui-numberInputWidget-buttoned', config.showButtons )\n\t\t.append( $field );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.NumberInputWidget, OO.ui.TextInputWidget );\n\n/* Methods */\n\n/**\n * Set whether only integers are allowed\n *\n * @param {boolean} flag\n */\nOO.ui.NumberInputWidget.prototype.setAllowInteger = function ( flag ) {\n\tthis.allowInteger = !!flag;\n\tthis.setValidityFlag();\n};\n// Backward compatibility\nOO.ui.NumberInputWidget.prototype.setIsInteger = OO.ui.NumberInputWidget.prototype.setAllowInteger;\n\n/**\n * Get whether only integers are allowed\n *\n * @return {boolean} Flag value\n */\nOO.ui.NumberInputWidget.prototype.getAllowInteger = function () {\n\treturn this.allowInteger;\n};\n// Backward compatibility\nOO.ui.NumberInputWidget.prototype.getIsInteger = OO.ui.NumberInputWidget.prototype.getAllowInteger;\n\n/**\n * Set the range of allowed values\n *\n * @param {number} min Minimum allowed value\n * @param {number} max Maximum allowed value\n */\nOO.ui.NumberInputWidget.prototype.setRange = function ( min, max ) {\n\tif ( min > max ) {\n\t\tthrow new Error( 'Minimum (' + min + ') must not be greater than maximum (' + max + ')' );\n\t}\n\tthis.min = min;\n\tthis.max = max;\n\tthis.setValidityFlag();\n};\n\n/**\n * Get the current range\n *\n * @return {number[]} Minimum and maximum values\n */\nOO.ui.NumberInputWidget.prototype.getRange = function () {\n\treturn [ this.min, this.max ];\n};\n\n/**\n * Set the stepping deltas\n *\n * @param {number} step Normal step\n * @param {number|null} pageStep Page step. If null, 10 * step will be used.\n */\nOO.ui.NumberInputWidget.prototype.setStep = function ( step, pageStep ) {\n\tif ( step <= 0 ) {\n\t\tthrow new Error( 'Step value must be positive' );\n\t}\n\tif ( pageStep === null ) {\n\t\tpageStep = step * 10;\n\t} else if ( pageStep <= 0 ) {\n\t\tthrow new Error( 'Page step value must be positive' );\n\t}\n\tthis.step = step;\n\tthis.pageStep = pageStep;\n};\n\n/**\n * Get the current stepping values\n *\n * @return {number[]} Step and page step\n */\nOO.ui.NumberInputWidget.prototype.getStep = function () {\n\treturn [ this.step, this.pageStep ];\n};\n\n/**\n * Get the current value of the widget as a number\n *\n * @return {number} May be NaN, or an invalid number\n */\nOO.ui.NumberInputWidget.prototype.getNumericValue = function () {\n\treturn +this.getValue();\n};\n\n/**\n * Adjust the value of the widget\n *\n * @param {number} delta Adjustment amount\n */\nOO.ui.NumberInputWidget.prototype.adjustValue = function ( delta ) {\n\tvar n, v = this.getNumericValue();\n\n\tdelta = +delta;\n\tif ( isNaN( delta ) || !isFinite( delta ) ) {\n\t\tthrow new Error( 'Delta must be a finite number' );\n\t}\n\n\tif ( isNaN( v ) ) {\n\t\tn = 0;\n\t} else {\n\t\tn = v + delta;\n\t\tn = Math.max( Math.min( n, this.max ), this.min );\n\t\tif ( this.allowInteger ) {\n\t\t\tn = Math.round( n );\n\t\t}\n\t}\n\n\tif ( n !== v ) {\n\t\tthis.setValue( n );\n\t}\n};\n/**\n * Validate input\n *\n * @private\n * @param {string} value Field value\n * @return {boolean}\n */\nOO.ui.NumberInputWidget.prototype.validateNumber = function ( value ) {\n\tvar n = +value;\n\tif ( value === '' ) {\n\t\treturn !this.isRequired();\n\t}\n\n\tif ( isNaN( n ) || !isFinite( n ) ) {\n\t\treturn false;\n\t}\n\n\tif ( this.allowInteger && Math.floor( n ) !== n ) {\n\t\treturn false;\n\t}\n\n\tif ( n < this.min || n > this.max ) {\n\t\treturn false;\n\t}\n\n\treturn true;\n};\n\n/**\n * Handle mouse click events.\n *\n * @private\n * @param {number} dir +1 or -1\n */\nOO.ui.NumberInputWidget.prototype.onButtonClick = function ( dir ) {\n\tthis.adjustValue( dir * this.step );\n};\n\n/**\n * Handle mouse wheel events.\n *\n * @private\n * @param {jQuery.Event} event\n */\nOO.ui.NumberInputWidget.prototype.onWheel = function ( event ) {\n\tvar delta = 0;\n\n\tif ( !this.isDisabled() && this.$input.is( ':focus' ) ) {\n\t\t// Standard 'wheel' event\n\t\tif ( event.originalEvent.deltaMode !== undefined ) {\n\t\t\tthis.sawWheelEvent = true;\n\t\t}\n\t\tif ( event.originalEvent.deltaY ) {\n\t\t\tdelta = -event.originalEvent.deltaY;\n\t\t} else if ( event.originalEvent.deltaX ) {\n\t\t\tdelta = event.originalEvent.deltaX;\n\t\t}\n\n\t\t// Non-standard events\n\t\tif ( !this.sawWheelEvent ) {\n\t\t\tif ( event.originalEvent.wheelDeltaX ) {\n\t\t\t\tdelta = -event.originalEvent.wheelDeltaX;\n\t\t\t} else if ( event.originalEvent.wheelDeltaY ) {\n\t\t\t\tdelta = event.originalEvent.wheelDeltaY;\n\t\t\t} else if ( event.originalEvent.wheelDelta ) {\n\t\t\t\tdelta = event.originalEvent.wheelDelta;\n\t\t\t} else if ( event.originalEvent.detail ) {\n\t\t\t\tdelta = -event.originalEvent.detail;\n\t\t\t}\n\t\t}\n\n\t\tif ( delta ) {\n\t\t\tdelta = delta < 0 ? -1 : 1;\n\t\t\tthis.adjustValue( delta * this.step );\n\t\t}\n\n\t\treturn false;\n\t}\n};\n\n/**\n * Handle key down events.\n *\n * @private\n * @param {jQuery.Event} e Key down event\n */\nOO.ui.NumberInputWidget.prototype.onKeyDown = function ( e ) {\n\tif ( !this.isDisabled() ) {\n\t\tswitch ( e.which ) {\n\t\t\tcase OO.ui.Keys.UP:\n\t\t\t\tthis.adjustValue( this.step );\n\t\t\t\treturn false;\n\t\t\tcase OO.ui.Keys.DOWN:\n\t\t\t\tthis.adjustValue( -this.step );\n\t\t\t\treturn false;\n\t\t\tcase OO.ui.Keys.PAGEUP:\n\t\t\t\tthis.adjustValue( this.pageStep );\n\t\t\t\treturn false;\n\t\t\tcase OO.ui.Keys.PAGEDOWN:\n\t\t\t\tthis.adjustValue( -this.pageStep );\n\t\t\t\treturn false;\n\t\t}\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.NumberInputWidget.prototype.setDisabled = function ( disabled ) {\n\t// Parent method\n\tOO.ui.NumberInputWidget.parent.prototype.setDisabled.call( this, disabled );\n\n\tif ( this.minusButton ) {\n\t\tthis.minusButton.setDisabled( this.isDisabled() );\n\t}\n\tif ( this.plusButton ) {\n\t\tthis.plusButton.setDisabled( this.isDisabled() );\n\t}\n\n\treturn this;\n};\n","}( OO ) );\n"]} \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-wikimediaui.js b/www/wiki/resources/lib/oojs-ui/oojs-ui-wikimediaui.js
new file mode 100644
index 00000000..54313562
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-wikimediaui.js
@@ -0,0 +1,91 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:23:58Z
+ */
+( function ( OO ) {
+
+'use strict';
+
+/**
+ * @class
+ * @extends OO.ui.Theme
+ *
+ * @constructor
+ */
+OO.ui.WikimediaUITheme = function OoUiWikimediaUITheme() {
+ // Parent constructor
+ OO.ui.WikimediaUITheme.parent.call( this );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.WikimediaUITheme, OO.ui.Theme );
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.WikimediaUITheme.prototype.getElementClasses = function ( element ) {
+ // Parent method
+ var variant, isFramed, isActive,
+ variants = {
+ warning: false,
+ invert: false,
+ progressive: false,
+ constructive: false,
+ destructive: false
+ },
+ // Parent method
+ classes = OO.ui.WikimediaUITheme.parent.prototype.getElementClasses.call( this, element );
+
+ if ( element.supports( [ 'hasFlag' ] ) ) {
+ isFramed = element.supports( [ 'isFramed' ] ) && element.isFramed();
+ isActive = element.supports( [ 'isActive' ] ) && element.isActive();
+ if (
+ // Button with a dark background
+ isFramed && ( isActive || element.isDisabled() || element.hasFlag( 'primary' ) ) ||
+ // Toolbar with a dark background
+ OO.ui.ToolGroup && element instanceof OO.ui.ToolGroup && ( isActive || element.hasFlag( 'primary' ) )
+ ) {
+ // … use white icon / indicator, regardless of other flags
+ variants.invert = true;
+ } else if ( !isFramed && element.isDisabled() ) {
+ // Frameless disabled button, always use black icon / indicator regardless of other flags
+ variants.invert = false;
+ } else if ( !element.isDisabled() ) {
+ // Any other kind of button, use the right colored icon / indicator if available
+ variants.progressive = element.hasFlag( 'progressive' );
+ variants.constructive = element.hasFlag( 'constructive' );
+ variants.destructive = element.hasFlag( 'destructive' );
+ variants.warning = element.hasFlag( 'warning' );
+ }
+ }
+
+ for ( variant in variants ) {
+ classes[ variants[ variant ] ? 'on' : 'off' ].push( 'oo-ui-image-' + variant );
+ }
+
+ return classes;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.WikimediaUITheme.prototype.getDialogTransitionDuration = function () {
+ return 250;
+};
+
+/* Instantiation */
+
+OO.ui.theme = new OO.ui.WikimediaUITheme();
+
+}( OO ) );
+
+//# sourceMappingURL=oojs-ui-wikimediaui.js.map \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-wikimediaui.js.map b/www/wiki/resources/lib/oojs-ui/oojs-ui-wikimediaui.js.map
new file mode 100644
index 00000000..a27b8e70
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-wikimediaui.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/intro.js.txt","../src/themes/wikimediaui/WikimediaUITheme.js","../src/outro.js.txt"],"names":[],"mappings":"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","file":"oojs-ui-wikimediaui.js","sourcesContent":["( function ( OO ) {\n\n'use strict';\n","/**\n * @class\n * @extends OO.ui.Theme\n *\n * @constructor\n */\nOO.ui.WikimediaUITheme = function OoUiWikimediaUITheme() {\n\t// Parent constructor\n\tOO.ui.WikimediaUITheme.parent.call( this );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.WikimediaUITheme, OO.ui.Theme );\n\n/* Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.WikimediaUITheme.prototype.getElementClasses = function ( element ) {\n\t// Parent method\n\tvar variant, isFramed, isActive,\n\t\tvariants = {\n\t\t\twarning: false,\n\t\t\tinvert: false,\n\t\t\tprogressive: false,\n\t\t\tconstructive: false,\n\t\t\tdestructive: false\n\t\t},\n\t\t// Parent method\n\t\tclasses = OO.ui.WikimediaUITheme.parent.prototype.getElementClasses.call( this, element );\n\n\tif ( element.supports( [ 'hasFlag' ] ) ) {\n\t\tisFramed = element.supports( [ 'isFramed' ] ) && element.isFramed();\n\t\tisActive = element.supports( [ 'isActive' ] ) && element.isActive();\n\t\tif (\n\t\t\t// Button with a dark background\n\t\t\tisFramed && ( isActive || element.isDisabled() || element.hasFlag( 'primary' ) ) ||\n\t\t\t// Toolbar with a dark background\n\t\t\tOO.ui.ToolGroup && element instanceof OO.ui.ToolGroup && ( isActive || element.hasFlag( 'primary' ) )\n\t\t) {\n\t\t\t// … use white icon / indicator, regardless of other flags\n\t\t\tvariants.invert = true;\n\t\t} else if ( !isFramed && element.isDisabled() ) {\n\t\t\t// Frameless disabled button, always use black icon / indicator regardless of other flags\n\t\t\tvariants.invert = false;\n\t\t} else if ( !element.isDisabled() ) {\n\t\t\t// Any other kind of button, use the right colored icon / indicator if available\n\t\t\tvariants.progressive = element.hasFlag( 'progressive' );\n\t\t\tvariants.constructive = element.hasFlag( 'constructive' );\n\t\t\tvariants.destructive = element.hasFlag( 'destructive' );\n\t\t\tvariants.warning = element.hasFlag( 'warning' );\n\t\t}\n\t}\n\n\tfor ( variant in variants ) {\n\t\tclasses[ variants[ variant ] ? 'on' : 'off' ].push( 'oo-ui-image-' + variant );\n\t}\n\n\treturn classes;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.WikimediaUITheme.prototype.getDialogTransitionDuration = function () {\n\treturn 250;\n};\n\n/* Instantiation */\n\nOO.ui.theme = new OO.ui.WikimediaUITheme();\n","}( OO ) );\n"]} \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-windows-apex.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-windows-apex.css
new file mode 100644
index 00000000..f9fa6c32
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-windows-apex.css
@@ -0,0 +1,414 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:24:03Z
+ */
+.oo-ui-actionWidget.oo-ui-pendingElement-pending {
+ background-image: /* @embed */ url(themes/apex/images/textures/pending.gif);
+}
+.oo-ui-window {
+ background-color: transparent;
+ background-image: none;
+}
+.oo-ui-window-frame {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-window-content {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-window-content:focus {
+ outline: 0;
+}
+.oo-ui-window-head,
+.oo-ui-window-foot {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-window-body {
+ margin: 0;
+ padding: 0;
+ background: none;
+}
+.oo-ui-window-overlay {
+ position: absolute;
+ top: 0;
+ /* @noflip */
+ left: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-head,
+.oo-ui-dialog-content > .oo-ui-window-body,
+.oo-ui-dialog-content > .oo-ui-window-foot {
+ position: absolute;
+ left: 0;
+ right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-dialog-content > .oo-ui-window-head {
+ overflow: hidden;
+ z-index: 1;
+ top: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-body {
+ overflow: auto;
+ z-index: 2;
+ top: 0;
+ bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-foot {
+ z-index: 3;
+ bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-body {
+ box-shadow: 0 0 0.66em rgba(0, 0, 0, 0.25);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget {
+ position: relative;
+ text-align: center;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-buttonElement-button {
+ display: block;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-labelElement-label {
+ position: relative;
+ top: auto;
+ bottom: auto;
+}
+.oo-ui-messageDialog-actions-horizontal {
+ display: table;
+ table-layout: fixed;
+ width: 100%;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+ display: table-cell;
+ width: 1%;
+}
+.oo-ui-messageDialog-actions-vertical {
+ display: block;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.oo-ui-messageDialog-content .oo-ui-window-body {
+ box-shadow: 0 0 0.33em rgba(0, 0, 0, 0.33);
+}
+.oo-ui-messageDialog-title,
+.oo-ui-messageDialog-message {
+ display: block;
+ text-align: center;
+}
+.oo-ui-messageDialog-title.oo-ui-labelElement,
+.oo-ui-messageDialog-message.oo-ui-labelElement {
+ padding-top: 0.5em;
+}
+.oo-ui-messageDialog-title {
+ font-size: 1.5em;
+ line-height: 1em;
+ color: #000;
+}
+.oo-ui-messageDialog-message {
+ font-size: 1.1em;
+ line-height: 1.5em;
+ color: #666;
+ text-align: left;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+ border-right: 1px solid #e5e5e5;
+ margin: 0;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget:last-child {
+ border-right-width: 0;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+ border-bottom: 1px solid #e5e5e5;
+ margin: 0;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget:last-child {
+ border-bottom-width: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget {
+ min-height: 3.4em;
+ margin-right: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:active {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-buttonElement-button {
+ padding: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ text-align: center;
+ line-height: 3.4em;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:hover {
+ background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:active {
+ background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label {
+ font-weight: bold;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover {
+ background-color: rgba(118, 171, 54, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active {
+ background-color: rgba(118, 171, 54, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover {
+ background-color: rgba(212, 83, 83, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active {
+ background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-location {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.oo-ui-processDialog-title {
+ display: inline;
+ padding: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget {
+ white-space: nowrap;
+}
+.oo-ui-processDialog-actions-safe,
+.oo-ui-processDialog-actions-primary {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+}
+.oo-ui-processDialog-actions-safe {
+ left: 0;
+}
+.oo-ui-processDialog-actions-primary {
+ right: 0;
+}
+.oo-ui-processDialog-errors {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 4;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.oo-ui-processDialog-content .oo-ui-window-head {
+ height: 3.4em;
+}
+.oo-ui-processDialog-content .oo-ui-window-body {
+ top: 3.4em;
+ box-shadow: 0 0 0.33em rgba(0, 0, 0, 0.33);
+}
+.oo-ui-processDialog-navigation {
+ position: relative;
+ height: 3.4em;
+ padding: 0 1em;
+}
+.oo-ui-processDialog-location {
+ padding: 0.75em 0;
+ height: 1.875em;
+ cursor: default;
+ text-align: center;
+}
+.oo-ui-processDialog-title {
+ font-weight: bold;
+ line-height: 1.875em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-buttonElement-button {
+ min-width: 1.875em;
+ min-height: 1.875em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget .oo-ui-labelElement-label {
+ line-height: 1.875em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-iconElement .oo-ui-iconElement-icon {
+ margin-top: -0.125em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed {
+ margin: 0.75em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed .oo-ui-buttonElement-button {
+ padding: 0 1em;
+ vertical-align: middle;
+ margin: -1px;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless {
+ margin: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-buttonElement-button {
+ padding: 0.75em 1em;
+ vertical-align: middle;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget:active {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:hover {
+ background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:active {
+ background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label {
+ font-weight: bold;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover {
+ background-color: rgba(118, 171, 54, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active {
+ background-color: rgba(118, 171, 54, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover {
+ background-color: rgba(212, 83, 83, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active {
+ background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement {
+ margin-right: 0;
+}
+.oo-ui-processDialog > .oo-ui-window-frame {
+ min-height: 5em;
+}
+.oo-ui-processDialog-errors {
+ background-color: rgba(255, 255, 255, 0.9);
+ padding: 3em 3em 1.5em 3em;
+ text-align: center;
+}
+.oo-ui-processDialog-errors .oo-ui-buttonWidget {
+ margin: 2em 1em 2em 1em;
+}
+.oo-ui-processDialog-errors-title {
+ font-size: 1.5em;
+ color: #000;
+ margin-bottom: 2em;
+}
+.oo-ui-processDialog-error {
+ text-align: left;
+ margin: 1em;
+ padding: 1em;
+ border: 1px solid #ff9e9e;
+ background-color: #fff7f7;
+ border-radius: 0.25em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+ position: fixed;
+ width: 0;
+ height: 0;
+ overflow: hidden;
+ z-index: 4;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-active {
+ width: auto;
+ height: auto;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: 1em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame {
+ position: absolute;
+ right: 0;
+ left: 0;
+ margin: auto;
+ overflow: hidden;
+ max-width: 100%;
+ max-height: 100%;
+}
+.oo-ui-windowManager-fullscreen > .oo-ui-dialog > .oo-ui-window-frame {
+ width: 100%;
+ height: 100%;
+ top: 0;
+ bottom: 0;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+ background-color: rgba(255, 255, 255, 0.5);
+ opacity: 0;
+ -webkit-transition: opacity 250ms ease;
+ -moz-transition: opacity 250ms ease;
+ transition: opacity 250ms ease;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog > .oo-ui-window-frame {
+ background-color: #fff;
+ opacity: 0;
+ -webkit-transform: scale(0.5);
+ -moz-transform: scale(0.5);
+ -ms-transform: scale(0.5);
+ transform: scale(0.5);
+ -webkit-transition: all 250ms ease;
+ -moz-transition: all 250ms ease;
+ transition: all 250ms ease;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup {
+ opacity: 1;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-ready > .oo-ui-window-frame {
+ opacity: 1;
+ -webkit-transform: scale(1);
+ -moz-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+}
+.oo-ui-windowManager-modal.oo-ui-windowManager-floating > .oo-ui-dialog > .oo-ui-window-frame {
+ top: 1em;
+ bottom: 1em;
+ max-height: 100%;
+ max-height: calc( 100% - 2em );
+ border: 1px solid #ccc;
+ border-radius: 0.5em;
+ box-shadow: 0 0.2em 1em rgba(0, 0, 0, 0.3);
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-windows-mediawiki.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-windows-mediawiki.css
new file mode 100644
index 00000000..deda1d0c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-windows-mediawiki.css
@@ -0,0 +1,385 @@
+/*!
+ * OOjs UI v0.17.1
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2016 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2016-05-03T22:58:06Z
+ */
+.oo-ui-window {
+ background: transparent;
+}
+.oo-ui-window-frame {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-window-content:focus {
+ outline: 0;
+}
+.oo-ui-window-head,
+.oo-ui-window-foot {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-window-body {
+ margin: 0;
+ padding: 0;
+ background: none;
+}
+.oo-ui-window-overlay {
+ position: absolute;
+ top: 0;
+ /* @noflip */
+ left: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-head,
+.oo-ui-dialog-content > .oo-ui-window-body,
+.oo-ui-dialog-content > .oo-ui-window-foot {
+ position: absolute;
+ left: 0;
+ right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-dialog-content > .oo-ui-window-head {
+ overflow: hidden;
+ z-index: 1;
+ top: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-body {
+ overflow: auto;
+ z-index: 2;
+ top: 0;
+ bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-foot {
+ overflow: hidden;
+ z-index: 1;
+ bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-body {
+ outline: 1px solid #aaaaaa;
+}
+.oo-ui-messageDialog-actions-horizontal {
+ display: table;
+ table-layout: fixed;
+ width: 100%;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+ display: table-cell;
+ width: 1%;
+}
+.oo-ui-messageDialog-actions-vertical {
+ display: block;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget {
+ position: relative;
+ text-align: center;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-buttonElement-button {
+ display: block;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-labelElement-label {
+ position: relative;
+ top: auto;
+ bottom: auto;
+ display: inline;
+ white-space: nowrap;
+}
+.oo-ui-messageDialog-title,
+.oo-ui-messageDialog-message {
+ display: block;
+ text-align: center;
+}
+.oo-ui-messageDialog-title.oo-ui-labelElement,
+.oo-ui-messageDialog-message.oo-ui-labelElement {
+ padding-top: 0.5em;
+}
+.oo-ui-messageDialog-title {
+ font-size: 1.5em;
+ line-height: 1em;
+ color: #000000;
+}
+.oo-ui-messageDialog-message {
+ font-size: 0.9em;
+ line-height: 1.25em;
+ color: #555555;
+}
+.oo-ui-messageDialog-message-verbose {
+ font-size: 1.1em;
+ line-height: 1.5em;
+ text-align: left;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+ border-right: 1px solid #e5e5e5;
+ margin: 0;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget:last-child {
+ border-right-width: 0;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+ border-bottom: 1px solid #e5e5e5;
+ margin: 0;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget:last-child {
+ border-bottom-width: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget {
+ height: 3.4em;
+ margin-right: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ text-align: center;
+ line-height: 3.4em;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:active {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:hover {
+ background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-progressive:active {
+ background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label {
+ font-weight: bold;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:hover {
+ background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-constructive:active {
+ background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:hover {
+ background-color: rgba(212, 83, 83, 0.05);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-flaggedElement-destructive:active {
+ background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-location {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.oo-ui-processDialog-title {
+ display: inline;
+ padding: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget {
+ white-space: nowrap;
+}
+.oo-ui-processDialog-actions-safe,
+.oo-ui-processDialog-actions-primary {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+}
+.oo-ui-processDialog-actions-safe {
+ left: 0;
+}
+.oo-ui-processDialog-actions-primary {
+ right: 0;
+}
+.oo-ui-processDialog-errors {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 2;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.oo-ui-processDialog-content .oo-ui-window-head {
+ height: 3.4em;
+}
+.oo-ui-processDialog-content .oo-ui-window-body {
+ top: 3.4em;
+ outline: 1px solid rgba(0, 0, 0, 0.2);
+}
+.oo-ui-processDialog-navigation {
+ position: relative;
+ height: 3.4em;
+ padding: 0 1em;
+}
+.oo-ui-processDialog-location {
+ padding: 0.75em 0;
+ height: 1.875em;
+ cursor: default;
+ text-align: center;
+}
+.oo-ui-processDialog-title {
+ font-weight: bold;
+ line-height: 1.875em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed {
+ margin: 0.5em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless {
+ margin: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-buttonElement-button {
+ padding: 0.75em 1em;
+ vertical-align: middle;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-labelElement-label {
+ line-height: 1.875em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless:active {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:hover {
+ background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:active {
+ background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label {
+ font-weight: bold;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:hover {
+ background-color: rgba(118, 171, 54, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:active {
+ background-color: rgba(118, 171, 54, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:hover {
+ background-color: rgba(212, 83, 83, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:active {
+ background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement {
+ margin-right: 0;
+}
+.oo-ui-processDialog > .oo-ui-window-frame {
+ min-height: 5em;
+}
+.oo-ui-processDialog-errors {
+ background-color: rgba(255, 255, 255, 0.9);
+ padding: 3em 3em 1.5em 3em;
+ text-align: center;
+}
+.oo-ui-processDialog-errors .oo-ui-buttonWidget {
+ margin: 2em 1em 2em 1em;
+}
+.oo-ui-processDialog-errors-title {
+ font-size: 1.5em;
+ color: #000000;
+ margin-bottom: 2em;
+}
+.oo-ui-processDialog-error {
+ text-align: left;
+ margin: 1em;
+ padding: 1em;
+ border: 1px solid #ff9e9e;
+ background-color: #fff7f7;
+ border-radius: 2px;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+ position: fixed;
+ width: 0;
+ height: 0;
+ overflow: hidden;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-active {
+ width: auto;
+ height: auto;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: 1em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame {
+ position: absolute;
+ right: 0;
+ left: 0;
+ margin: auto;
+ overflow: hidden;
+ max-width: 100%;
+ max-height: 100%;
+}
+.oo-ui-windowManager-fullscreen > .oo-ui-dialog > .oo-ui-window-frame {
+ width: 100%;
+ height: 100%;
+ top: 0;
+ bottom: 0;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+ background-color: rgba(255, 255, 255, 0.5);
+ opacity: 0;
+ -webkit-transition: opacity 250ms;
+ -moz-transition: opacity 250ms;
+ transition: opacity 250ms;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog > .oo-ui-window-frame {
+ background-color: #ffffff;
+ opacity: 0;
+ -webkit-transform: scale(0.5);
+ -moz-transform: scale(0.5);
+ -ms-transform: scale(0.5);
+ transform: scale(0.5);
+ -webkit-transition: all 250ms;
+ -moz-transition: all 250ms;
+ transition: all 250ms;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup {
+ opacity: 1;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-ready > .oo-ui-window-frame {
+ opacity: 1;
+ -webkit-transform: scale(1);
+ -moz-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+}
+.oo-ui-windowManager-modal.oo-ui-windowManager-floating > .oo-ui-dialog > .oo-ui-window-frame {
+ top: 1em;
+ bottom: 1em;
+ max-height: 100%;
+ max-height: calc(100% - 2em);
+ border: 1px solid #aaaaaa;
+ border-radius: 2px;
+ box-shadow: 0 0.15em 0 0 rgba(0, 0, 0, 0.15);
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-windows-wikimediaui.css b/www/wiki/resources/lib/oojs-ui/oojs-ui-windows-wikimediaui.css
new file mode 100644
index 00000000..7c8c33b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-windows-wikimediaui.css
@@ -0,0 +1,422 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:24:03Z
+ */
+/**
+ * WikimediaUI Base v0.9.2
+ * Wikimedia Foundation user interface base variables
+ */
+/* Colors */
+/* Positioning */
+/* Box Model properties */
+/* Max Widths */
+/* Typography incl. print properties */
+/* Other Properties */
+/* Animation & Transition */
+.oo-ui-window {
+ background: transparent;
+}
+.oo-ui-window-frame {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-window-content {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+}
+.oo-ui-window-content:focus {
+ outline: 0;
+}
+.oo-ui-window-head,
+.oo-ui-window-foot {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.oo-ui-window-body {
+ margin: 0;
+ padding: 0;
+ background: none;
+}
+.oo-ui-window-overlay {
+ position: absolute;
+ top: 0;
+ /* @noflip */
+ left: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-head,
+.oo-ui-dialog-content > .oo-ui-window-body,
+.oo-ui-dialog-content > .oo-ui-window-foot {
+ position: absolute;
+ left: 0;
+ right: 0;
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+.oo-ui-dialog-content > .oo-ui-window-head {
+ overflow: hidden;
+ z-index: 1;
+ top: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-body {
+ overflow: auto;
+ z-index: 2;
+ top: 0;
+ bottom: 0;
+}
+.oo-ui-dialog-content > .oo-ui-window-foot {
+ z-index: 3;
+ bottom: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget {
+ position: relative;
+ text-align: center;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-buttonElement-button {
+ display: block;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-labelElement-label {
+ position: relative;
+ top: auto;
+ bottom: auto;
+}
+.oo-ui-messageDialog-actions-horizontal {
+ display: table;
+ table-layout: fixed;
+ width: 100%;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+ display: table-cell;
+ width: 1%;
+}
+.oo-ui-messageDialog-actions-vertical {
+ display: block;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+ display: block;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+.oo-ui-messageDialog-content > .oo-ui-window-foot {
+ outline: 1px solid #a2a9b1;
+}
+.oo-ui-messageDialog-title,
+.oo-ui-messageDialog-message {
+ display: block;
+ text-align: center;
+}
+.oo-ui-messageDialog-title.oo-ui-labelElement,
+.oo-ui-messageDialog-message.oo-ui-labelElement {
+ padding-top: 0.5em;
+}
+.oo-ui-messageDialog-title {
+ font-size: 1.5em;
+ line-height: 1;
+ color: #000;
+}
+.oo-ui-messageDialog-message {
+ font-size: 1.1em;
+ line-height: 1.4;
+ color: #222;
+ text-align: left;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget {
+ border-right: 1px solid #a2a9b1;
+ margin: 0;
+}
+.oo-ui-messageDialog-actions-horizontal .oo-ui-actionWidget:last-child {
+ border-right-width: 0;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget {
+ border-bottom: 1px solid #a2a9b1;
+ margin: 0;
+}
+.oo-ui-messageDialog-actions-vertical .oo-ui-actionWidget:last-child {
+ border-bottom-width: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget {
+ min-height: 3.4375em;
+ margin-right: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:last-child {
+ margin-right: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget:first-child {
+ margin-left: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget .oo-ui-buttonElement-button {
+ border: 0;
+ border-radius: 0;
+ padding: 0;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-labelElement .oo-ui-labelElement-label {
+ line-height: 3.4375em;
+ text-align: center;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button:hover {
+ background-color: #f8f9fa;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button:active {
+ background-color: #c8ccd1;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-widget-enabled .oo-ui-buttonElement-button:focus {
+ box-shadow: inset 0 0 0 1px #36c, 0 0 0 1px #36c;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive .oo-ui-buttonElement-button:hover,
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive .oo-ui-buttonElement-button:hover {
+ background-color: #eaf3ff;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive .oo-ui-buttonElement-button:active,
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive .oo-ui-buttonElement-button:active {
+ background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label,
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-constructive .oo-ui-labelElement-label {
+ font-weight: bold;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive .oo-ui-buttonElement-button:hover {
+ background-color: #fee7e6;
+}
+.oo-ui-messageDialog-actions .oo-ui-actionWidget.oo-ui-widget-enabled.oo-ui-flaggedElement-destructive .oo-ui-buttonElement-button:active {
+ background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-location {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+.oo-ui-processDialog-title {
+ display: inline;
+ padding: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget {
+ white-space: nowrap;
+}
+.oo-ui-processDialog-actions-safe,
+.oo-ui-processDialog-actions-primary {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+}
+.oo-ui-processDialog-actions-safe {
+ left: 0;
+}
+.oo-ui-processDialog-actions-primary {
+ right: 0;
+}
+.oo-ui-processDialog-errors {
+ position: absolute;
+ top: 0;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ z-index: 4;
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.oo-ui-processDialog-content .oo-ui-window-head {
+ height: 3.4375em;
+}
+.oo-ui-processDialog-content .oo-ui-window-body {
+ top: 3.4375em;
+ outline: 1px solid #c8ccd1;
+}
+.oo-ui-processDialog-navigation {
+ position: relative;
+ height: 3.4375em;
+}
+.oo-ui-processDialog-location {
+ height: 3.4375em;
+ cursor: default;
+ text-align: center;
+}
+.oo-ui-processDialog-title {
+ font-weight: bold;
+ line-height: 3.4375em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-framed,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-framed {
+ margin: 0.46875em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-iconElement:first-child,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-iconElement:first-child,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-iconElement:first-child {
+ margin-left: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-iconElement > .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-iconElement > .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-iconElement > .oo-ui-buttonElement-button {
+ padding-left: 2.875em;
+ padding-top: 0;
+ min-height: 3.4375em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-iconElement > .oo-ui-buttonElement-button > .oo-ui-iconElement-icon {
+ left: 0.5em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-labelElement:first-child,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-labelElement:first-child,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-labelElement:first-child {
+ margin-left: 0;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-labelElement > .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-labelElement > .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-labelElement > .oo-ui-buttonElement-button {
+ padding: 0.75em 1em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-labelElement.oo-ui-iconElement > .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-labelElement.oo-ui-iconElement > .oo-ui-buttonElement-button,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-labelElement.oo-ui-iconElement > .oo-ui-buttonElement-button {
+ padding-left: 2.625em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement-frameless .oo-ui-labelElement-label {
+ line-height: 1.875em;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless:hover {
+ background-color: rgba(0, 0, 0, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless:active {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:hover,
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:hover {
+ background-color: rgba(8, 126, 204, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive:active,
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive:active {
+ background-color: rgba(8, 126, 204, 0.1);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-progressive .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive .oo-ui-labelElement-label,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-constructive .oo-ui-labelElement-label {
+ font-weight: bold;
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:hover,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:hover {
+ background-color: rgba(212, 83, 83, 0.05);
+}
+.oo-ui-processDialog-actions-safe .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:active,
+.oo-ui-processDialog-actions-primary .oo-ui-actionWidget.oo-ui-buttonElement-frameless.oo-ui-flaggedElement-destructive:active {
+ background-color: rgba(212, 83, 83, 0.1);
+}
+.oo-ui-processDialog-actions-other .oo-ui-actionWidget.oo-ui-buttonElement {
+ margin-right: 0;
+}
+.oo-ui-processDialog > .oo-ui-window-frame {
+ min-height: 5em;
+}
+.oo-ui-processDialog-errors {
+ background-color: rgba(255, 255, 255, 0.9);
+ padding: 3em 3em 1.5em 3em;
+ text-align: center;
+}
+.oo-ui-processDialog-errors .oo-ui-buttonWidget {
+ margin: 2em 1em 2em 1em;
+}
+.oo-ui-processDialog-errors-title {
+ font-size: 1.5em;
+ color: #000;
+ margin-bottom: 2em;
+}
+.oo-ui-processDialog-error {
+ text-align: left;
+ margin: 1em;
+ padding: 1em;
+ border: 1px solid #d33;
+ background-color: #fff7f7;
+ border-radius: 2px;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+ position: fixed;
+ width: 0;
+ height: 0;
+ overflow: hidden;
+ z-index: 4;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-active {
+ width: auto;
+ height: auto;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ padding: 1em;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup > .oo-ui-window-frame {
+ position: absolute;
+ right: 0;
+ left: 0;
+ margin: auto;
+ overflow: hidden;
+ max-width: 100%;
+ max-height: 100%;
+}
+.oo-ui-windowManager-fullscreen > .oo-ui-dialog > .oo-ui-window-frame {
+ width: 100%;
+ height: 100%;
+ top: 0;
+ bottom: 0;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog {
+ background-color: rgba(255, 255, 255, 0.5);
+ opacity: 0;
+ -webkit-transition: opacity 250ms;
+ -moz-transition: opacity 250ms;
+ transition: opacity 250ms;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog > .oo-ui-window-frame {
+ background-color: #fff;
+ opacity: 0;
+ -webkit-transform: scale(0.5);
+ -moz-transform: scale(0.5);
+ -ms-transform: scale(0.5);
+ transform: scale(0.5);
+ -webkit-transition: all 250ms;
+ -moz-transition: all 250ms;
+ transition: all 250ms;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-setup {
+ opacity: 1;
+}
+.oo-ui-windowManager-modal > .oo-ui-dialog.oo-ui-window-ready > .oo-ui-window-frame {
+ opacity: 1;
+ -webkit-transform: scale(1);
+ -moz-transform: scale(1);
+ -ms-transform: scale(1);
+ transform: scale(1);
+}
+.oo-ui-windowManager-modal.oo-ui-windowManager-floating > .oo-ui-dialog > .oo-ui-window-frame {
+ top: 1em;
+ bottom: 1em;
+ max-height: 100%;
+ max-height: calc( 100% - 2em );
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ box-shadow: 0 2px 2px 0 rgba(0, 0, 0, 0.25);
+}
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-windows.js b/www/wiki/resources/lib/oojs-ui/oojs-ui-windows.js
new file mode 100644
index 00000000..2a0f02d6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-windows.js
@@ -0,0 +1,3571 @@
+/*!
+ * OOjs UI v0.23.0
+ * https://www.mediawiki.org/wiki/OOjs_UI
+ *
+ * Copyright 2011–2017 OOjs UI Team and other contributors.
+ * Released under the MIT license
+ * http://oojs.mit-license.org
+ *
+ * Date: 2017-09-05T21:23:58Z
+ */
+( function ( OO ) {
+
+'use strict';
+
+/**
+ * An ActionWidget is a {@link OO.ui.ButtonWidget button widget} that executes an action.
+ * Action widgets are used with OO.ui.ActionSet, which manages the behavior and availability
+ * of the actions.
+ *
+ * Both actions and action sets are primarily used with {@link OO.ui.Dialog Dialogs}.
+ * Please see the [OOjs UI documentation on MediaWiki] [1] for more information
+ * and examples.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs#Action_sets
+ *
+ * @class
+ * @extends OO.ui.ButtonWidget
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [action] Symbolic name of the action (e.g., ‘continue’ or ‘cancel’).
+ * @cfg {string[]} [modes] Symbolic names of the modes (e.g., ‘edit’ or ‘read’) in which the action
+ * should be made available. See the action set's {@link OO.ui.ActionSet#setMode setMode} method
+ * for more information about setting modes.
+ * @cfg {boolean} [framed=false] Render the action button with a frame
+ */
+OO.ui.ActionWidget = function OoUiActionWidget( config ) {
+ // Configuration initialization
+ config = $.extend( { framed: false }, config );
+
+ // Parent constructor
+ OO.ui.ActionWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ // Properties
+ this.action = config.action || '';
+ this.modes = config.modes || [];
+ this.width = 0;
+ this.height = 0;
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-actionWidget' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ActionWidget, OO.ui.ButtonWidget );
+OO.mixinClass( OO.ui.ActionWidget, OO.ui.mixin.PendingElement );
+
+/* Methods */
+
+/**
+ * Check if the action is configured to be available in the specified `mode`.
+ *
+ * @param {string} mode Name of mode
+ * @return {boolean} The action is configured with the mode
+ */
+OO.ui.ActionWidget.prototype.hasMode = function ( mode ) {
+ return this.modes.indexOf( mode ) !== -1;
+};
+
+/**
+ * Get the symbolic name of the action (e.g., ‘continue’ or ‘cancel’).
+ *
+ * @return {string}
+ */
+OO.ui.ActionWidget.prototype.getAction = function () {
+ return this.action;
+};
+
+/**
+ * Get the symbolic name of the mode or modes for which the action is configured to be available.
+ *
+ * The current mode is set with the action set's {@link OO.ui.ActionSet#setMode setMode} method.
+ * Only actions that are configured to be avaiable in the current mode will be visible. All other actions
+ * are hidden.
+ *
+ * @return {string[]}
+ */
+OO.ui.ActionWidget.prototype.getModes = function () {
+ return this.modes.slice();
+};
+
+/* eslint-disable no-unused-vars */
+/**
+ * ActionSets manage the behavior of the {@link OO.ui.ActionWidget action widgets} that comprise them.
+ * Actions can be made available for specific contexts (modes) and circumstances
+ * (abilities). Action sets are primarily used with {@link OO.ui.Dialog Dialogs}.
+ *
+ * ActionSets contain two types of actions:
+ *
+ * - Special: Special actions are the first visible actions with special flags, such as 'safe' and 'primary', the default special flags. Additional special flags can be configured in subclasses with the static #specialFlags property.
+ * - Other: Other actions include all non-special visible actions.
+ *
+ * Please see the [OOjs UI documentation on MediaWiki][1] for more information.
+ *
+ * @example
+ * // Example: An action set used in a process dialog
+ * function MyProcessDialog( config ) {
+ * MyProcessDialog.parent.call( this, config );
+ * }
+ * OO.inheritClass( MyProcessDialog, OO.ui.ProcessDialog );
+ * MyProcessDialog.static.title = 'An action set in a process dialog';
+ * MyProcessDialog.static.name = 'myProcessDialog';
+ * // An action set that uses modes ('edit' and 'help' mode, in this example).
+ * MyProcessDialog.static.actions = [
+ * { action: 'continue', modes: 'edit', label: 'Continue', flags: [ 'primary', 'constructive' ] },
+ * { action: 'help', modes: 'edit', label: 'Help' },
+ * { modes: 'edit', label: 'Cancel', flags: 'safe' },
+ * { action: 'back', modes: 'help', label: 'Back', flags: 'safe' }
+ * ];
+ *
+ * MyProcessDialog.prototype.initialize = function () {
+ * MyProcessDialog.parent.prototype.initialize.apply( this, arguments );
+ * this.panel1 = new OO.ui.PanelLayout( { padded: true, expanded: false } );
+ * this.panel1.$element.append( '<p>This dialog uses an action set (continue, help, cancel, back) configured with modes. This is edit mode. Click \'help\' to see help mode.</p>' );
+ * this.panel2 = new OO.ui.PanelLayout( { padded: true, expanded: false } );
+ * this.panel2.$element.append( '<p>This is help mode. Only the \'back\' action widget is configured to be visible here. Click \'back\' to return to \'edit\' mode.</p>' );
+ * this.stackLayout = new OO.ui.StackLayout( {
+ * items: [ this.panel1, this.panel2 ]
+ * } );
+ * this.$body.append( this.stackLayout.$element );
+ * };
+ * MyProcessDialog.prototype.getSetupProcess = function ( data ) {
+ * return MyProcessDialog.parent.prototype.getSetupProcess.call( this, data )
+ * .next( function () {
+ * this.actions.setMode( 'edit' );
+ * }, this );
+ * };
+ * MyProcessDialog.prototype.getActionProcess = function ( action ) {
+ * if ( action === 'help' ) {
+ * this.actions.setMode( 'help' );
+ * this.stackLayout.setItem( this.panel2 );
+ * } else if ( action === 'back' ) {
+ * this.actions.setMode( 'edit' );
+ * this.stackLayout.setItem( this.panel1 );
+ * } else if ( action === 'continue' ) {
+ * var dialog = this;
+ * return new OO.ui.Process( function () {
+ * dialog.close();
+ * } );
+ * }
+ * return MyProcessDialog.parent.prototype.getActionProcess.call( this, action );
+ * };
+ * MyProcessDialog.prototype.getBodyHeight = function () {
+ * return this.panel1.$element.outerHeight( true );
+ * };
+ * var windowManager = new OO.ui.WindowManager();
+ * $( 'body' ).append( windowManager.$element );
+ * var dialog = new MyProcessDialog( {
+ * size: 'medium'
+ * } );
+ * windowManager.addWindows( [ dialog ] );
+ * windowManager.openWindow( dialog );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs#Action_sets
+ *
+ * @abstract
+ * @class
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ActionSet = function OoUiActionSet( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+
+ // Properties
+ this.list = [];
+ this.categories = {
+ actions: 'getAction',
+ flags: 'getFlags',
+ modes: 'getModes'
+ };
+ this.categorized = {};
+ this.special = {};
+ this.others = [];
+ this.organized = false;
+ this.changing = false;
+ this.changed = false;
+};
+/* eslint-enable no-unused-vars */
+
+/* Setup */
+
+OO.mixinClass( OO.ui.ActionSet, OO.EventEmitter );
+
+/* Static Properties */
+
+/**
+ * Symbolic name of the flags used to identify special actions. Special actions are displayed in the
+ * header of a {@link OO.ui.ProcessDialog process dialog}.
+ * See the [OOjs UI documentation on MediaWiki][2] for more information and examples.
+ *
+ * [2]:https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs
+ *
+ * @abstract
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.ActionSet.static.specialFlags = [ 'safe', 'primary' ];
+
+/* Events */
+
+/**
+ * @event click
+ *
+ * A 'click' event is emitted when an action is clicked.
+ *
+ * @param {OO.ui.ActionWidget} action Action that was clicked
+ */
+
+/**
+ * @event add
+ *
+ * An 'add' event is emitted when actions are {@link #method-add added} to the action set.
+ *
+ * @param {OO.ui.ActionWidget[]} added Actions added
+ */
+
+/**
+ * @event remove
+ *
+ * A 'remove' event is emitted when actions are {@link #method-remove removed}
+ * or {@link #clear cleared}.
+ *
+ * @param {OO.ui.ActionWidget[]} added Actions removed
+ */
+
+/**
+ * @event change
+ *
+ * A 'change' event is emitted when actions are {@link #method-add added}, {@link #clear cleared},
+ * or {@link #method-remove removed} from the action set or when the {@link #setMode mode} is changed.
+ *
+ */
+
+/* Methods */
+
+/**
+ * Handle action change events.
+ *
+ * @private
+ * @fires change
+ */
+OO.ui.ActionSet.prototype.onActionChange = function () {
+ this.organized = false;
+ if ( this.changing ) {
+ this.changed = true;
+ } else {
+ this.emit( 'change' );
+ }
+};
+
+/**
+ * Check if an action is one of the special actions.
+ *
+ * @param {OO.ui.ActionWidget} action Action to check
+ * @return {boolean} Action is special
+ */
+OO.ui.ActionSet.prototype.isSpecial = function ( action ) {
+ var flag;
+
+ for ( flag in this.special ) {
+ if ( action === this.special[ flag ] ) {
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/**
+ * Get action widgets based on the specified filter: ‘actions’, ‘flags’, ‘modes’, ‘visible’,
+ * or ‘disabled’.
+ *
+ * @param {Object} [filters] Filters to use, omit to get all actions
+ * @param {string|string[]} [filters.actions] Actions that action widgets must have
+ * @param {string|string[]} [filters.flags] Flags that action widgets must have (e.g., 'safe')
+ * @param {string|string[]} [filters.modes] Modes that action widgets must have
+ * @param {boolean} [filters.visible] Action widgets must be visible
+ * @param {boolean} [filters.disabled] Action widgets must be disabled
+ * @return {OO.ui.ActionWidget[]} Action widgets matching all criteria
+ */
+OO.ui.ActionSet.prototype.get = function ( filters ) {
+ var i, len, list, category, actions, index, match, matches;
+
+ if ( filters ) {
+ this.organize();
+
+ // Collect category candidates
+ matches = [];
+ for ( category in this.categorized ) {
+ list = filters[ category ];
+ if ( list ) {
+ if ( !Array.isArray( list ) ) {
+ list = [ list ];
+ }
+ for ( i = 0, len = list.length; i < len; i++ ) {
+ actions = this.categorized[ category ][ list[ i ] ];
+ if ( Array.isArray( actions ) ) {
+ matches.push.apply( matches, actions );
+ }
+ }
+ }
+ }
+ // Remove by boolean filters
+ for ( i = 0, len = matches.length; i < len; i++ ) {
+ match = matches[ i ];
+ if (
+ ( filters.visible !== undefined && match.isVisible() !== filters.visible ) ||
+ ( filters.disabled !== undefined && match.isDisabled() !== filters.disabled )
+ ) {
+ matches.splice( i, 1 );
+ len--;
+ i--;
+ }
+ }
+ // Remove duplicates
+ for ( i = 0, len = matches.length; i < len; i++ ) {
+ match = matches[ i ];
+ index = matches.lastIndexOf( match );
+ while ( index !== i ) {
+ matches.splice( index, 1 );
+ len--;
+ index = matches.lastIndexOf( match );
+ }
+ }
+ return matches;
+ }
+ return this.list.slice();
+};
+
+/**
+ * Get 'special' actions.
+ *
+ * Special actions are the first visible action widgets with special flags, such as 'safe' and 'primary'.
+ * Special flags can be configured in subclasses by changing the static #specialFlags property.
+ *
+ * @return {OO.ui.ActionWidget[]|null} 'Special' action widgets.
+ */
+OO.ui.ActionSet.prototype.getSpecial = function () {
+ this.organize();
+ return $.extend( {}, this.special );
+};
+
+/**
+ * Get 'other' actions.
+ *
+ * Other actions include all non-special visible action widgets.
+ *
+ * @return {OO.ui.ActionWidget[]} 'Other' action widgets
+ */
+OO.ui.ActionSet.prototype.getOthers = function () {
+ this.organize();
+ return this.others.slice();
+};
+
+/**
+ * Set the mode (e.g., ‘edit’ or ‘view’). Only {@link OO.ui.ActionWidget#modes actions} configured
+ * to be available in the specified mode will be made visible. All other actions will be hidden.
+ *
+ * @param {string} mode The mode. Only actions configured to be available in the specified
+ * mode will be made visible.
+ * @chainable
+ * @fires toggle
+ * @fires change
+ */
+OO.ui.ActionSet.prototype.setMode = function ( mode ) {
+ var i, len, action;
+
+ this.changing = true;
+ for ( i = 0, len = this.list.length; i < len; i++ ) {
+ action = this.list[ i ];
+ action.toggle( action.hasMode( mode ) );
+ }
+
+ this.organized = false;
+ this.changing = false;
+ this.emit( 'change' );
+
+ return this;
+};
+
+/**
+ * Set the abilities of the specified actions.
+ *
+ * Action widgets that are configured with the specified actions will be enabled
+ * or disabled based on the boolean values specified in the `actions`
+ * parameter.
+ *
+ * @param {Object.<string,boolean>} actions A list keyed by action name with boolean
+ * values that indicate whether or not the action should be enabled.
+ * @chainable
+ */
+OO.ui.ActionSet.prototype.setAbilities = function ( actions ) {
+ var i, len, action, item;
+
+ for ( i = 0, len = this.list.length; i < len; i++ ) {
+ item = this.list[ i ];
+ action = item.getAction();
+ if ( actions[ action ] !== undefined ) {
+ item.setDisabled( !actions[ action ] );
+ }
+ }
+
+ return this;
+};
+
+/**
+ * Executes a function once per action.
+ *
+ * When making changes to multiple actions, use this method instead of iterating over the actions
+ * manually to defer emitting a #change event until after all actions have been changed.
+ *
+ * @param {Object|null} filter Filters to use to determine which actions to iterate over; see #get
+ * @param {Function} callback Callback to run for each action; callback is invoked with three
+ * arguments: the action, the action's index, the list of actions being iterated over
+ * @chainable
+ */
+OO.ui.ActionSet.prototype.forEach = function ( filter, callback ) {
+ this.changed = false;
+ this.changing = true;
+ this.get( filter ).forEach( callback );
+ this.changing = false;
+ if ( this.changed ) {
+ this.emit( 'change' );
+ }
+
+ return this;
+};
+
+/**
+ * Add action widgets to the action set.
+ *
+ * @param {OO.ui.ActionWidget[]} actions Action widgets to add
+ * @chainable
+ * @fires add
+ * @fires change
+ */
+OO.ui.ActionSet.prototype.add = function ( actions ) {
+ var i, len, action;
+
+ this.changing = true;
+ for ( i = 0, len = actions.length; i < len; i++ ) {
+ action = actions[ i ];
+ action.connect( this, {
+ click: [ 'emit', 'click', action ],
+ toggle: [ 'onActionChange' ]
+ } );
+ this.list.push( action );
+ }
+ this.organized = false;
+ this.emit( 'add', actions );
+ this.changing = false;
+ this.emit( 'change' );
+
+ return this;
+};
+
+/**
+ * Remove action widgets from the set.
+ *
+ * To remove all actions, you may wish to use the #clear method instead.
+ *
+ * @param {OO.ui.ActionWidget[]} actions Action widgets to remove
+ * @chainable
+ * @fires remove
+ * @fires change
+ */
+OO.ui.ActionSet.prototype.remove = function ( actions ) {
+ var i, len, index, action;
+
+ this.changing = true;
+ for ( i = 0, len = actions.length; i < len; i++ ) {
+ action = actions[ i ];
+ index = this.list.indexOf( action );
+ if ( index !== -1 ) {
+ action.disconnect( this );
+ this.list.splice( index, 1 );
+ }
+ }
+ this.organized = false;
+ this.emit( 'remove', actions );
+ this.changing = false;
+ this.emit( 'change' );
+
+ return this;
+};
+
+/**
+ * Remove all action widets from the set.
+ *
+ * To remove only specified actions, use the {@link #method-remove remove} method instead.
+ *
+ * @chainable
+ * @fires remove
+ * @fires change
+ */
+OO.ui.ActionSet.prototype.clear = function () {
+ var i, len, action,
+ removed = this.list.slice();
+
+ this.changing = true;
+ for ( i = 0, len = this.list.length; i < len; i++ ) {
+ action = this.list[ i ];
+ action.disconnect( this );
+ }
+
+ this.list = [];
+
+ this.organized = false;
+ this.emit( 'remove', removed );
+ this.changing = false;
+ this.emit( 'change' );
+
+ return this;
+};
+
+/**
+ * Organize actions.
+ *
+ * This is called whenever organized information is requested. It will only reorganize the actions
+ * if something has changed since the last time it ran.
+ *
+ * @private
+ * @chainable
+ */
+OO.ui.ActionSet.prototype.organize = function () {
+ var i, iLen, j, jLen, flag, action, category, list, item, special,
+ specialFlags = this.constructor.static.specialFlags;
+
+ if ( !this.organized ) {
+ this.categorized = {};
+ this.special = {};
+ this.others = [];
+ for ( i = 0, iLen = this.list.length; i < iLen; i++ ) {
+ action = this.list[ i ];
+ if ( action.isVisible() ) {
+ // Populate categories
+ for ( category in this.categories ) {
+ if ( !this.categorized[ category ] ) {
+ this.categorized[ category ] = {};
+ }
+ list = action[ this.categories[ category ] ]();
+ if ( !Array.isArray( list ) ) {
+ list = [ list ];
+ }
+ for ( j = 0, jLen = list.length; j < jLen; j++ ) {
+ item = list[ j ];
+ if ( !this.categorized[ category ][ item ] ) {
+ this.categorized[ category ][ item ] = [];
+ }
+ this.categorized[ category ][ item ].push( action );
+ }
+ }
+ // Populate special/others
+ special = false;
+ for ( j = 0, jLen = specialFlags.length; j < jLen; j++ ) {
+ flag = specialFlags[ j ];
+ if ( !this.special[ flag ] && action.hasFlag( flag ) ) {
+ this.special[ flag ] = action;
+ special = true;
+ break;
+ }
+ }
+ if ( !special ) {
+ this.others.push( action );
+ }
+ }
+ }
+ this.organized = true;
+ }
+
+ return this;
+};
+
+/**
+ * Errors contain a required message (either a string or jQuery selection) that is used to describe what went wrong
+ * in a {@link OO.ui.Process process}. The error's #recoverable and #warning configurations are used to customize the
+ * appearance and functionality of the error interface.
+ *
+ * The basic error interface contains a formatted error message as well as two buttons: 'Dismiss' and 'Try again' (i.e., the error
+ * is 'recoverable' by default). If the error is not recoverable, the 'Try again' button will not be rendered and the widget
+ * that initiated the failed process will be disabled.
+ *
+ * If the error is a warning, the error interface will include a 'Dismiss' and a 'Continue' button, which will try the
+ * process again.
+ *
+ * For an example of error interfaces, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs#Processes_and_errors
+ *
+ * @class
+ *
+ * @constructor
+ * @param {string|jQuery} message Description of error
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [recoverable=true] Error is recoverable.
+ * By default, errors are recoverable, and users can try the process again.
+ * @cfg {boolean} [warning=false] Error is a warning.
+ * If the error is a warning, the error interface will include a
+ * 'Dismiss' and a 'Continue' button. It is the responsibility of the developer to ensure that the warning
+ * is not triggered a second time if the user chooses to continue.
+ */
+OO.ui.Error = function OoUiError( message, config ) {
+ // Allow passing positional parameters inside the config object
+ if ( OO.isPlainObject( message ) && config === undefined ) {
+ config = message;
+ message = config.message;
+ }
+
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.message = message instanceof jQuery ? message : String( message );
+ this.recoverable = config.recoverable === undefined || !!config.recoverable;
+ this.warning = !!config.warning;
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.Error );
+
+/* Methods */
+
+/**
+ * Check if the error is recoverable.
+ *
+ * If the error is recoverable, users are able to try the process again.
+ *
+ * @return {boolean} Error is recoverable
+ */
+OO.ui.Error.prototype.isRecoverable = function () {
+ return this.recoverable;
+};
+
+/**
+ * Check if the error is a warning.
+ *
+ * If the error is a warning, the error interface will include a 'Dismiss' and a 'Continue' button.
+ *
+ * @return {boolean} Error is warning
+ */
+OO.ui.Error.prototype.isWarning = function () {
+ return this.warning;
+};
+
+/**
+ * Get error message as DOM nodes.
+ *
+ * @return {jQuery} Error message in DOM nodes
+ */
+OO.ui.Error.prototype.getMessage = function () {
+ return this.message instanceof jQuery ?
+ this.message.clone() :
+ $( '<div>' ).text( this.message ).contents();
+};
+
+/**
+ * Get the error message text.
+ *
+ * @return {string} Error message
+ */
+OO.ui.Error.prototype.getMessageText = function () {
+ return this.message instanceof jQuery ? this.message.text() : this.message;
+};
+
+/**
+ * A Process is a list of steps that are called in sequence. The step can be a number, a jQuery promise,
+ * or a function:
+ *
+ * - **number**: the process will wait for the specified number of milliseconds before proceeding.
+ * - **promise**: the process will continue to the next step when the promise is successfully resolved
+ * or stop if the promise is rejected.
+ * - **function**: the process will execute the function. The process will stop if the function returns
+ * either a boolean `false` or a promise that is rejected; if the function returns a number, the process
+ * will wait for that number of milliseconds before proceeding.
+ *
+ * If the process fails, an {@link OO.ui.Error error} is generated. Depending on how the error is
+ * configured, users can dismiss the error and try the process again, or not. If a process is stopped,
+ * its remaining steps will not be performed.
+ *
+ * @class
+ *
+ * @constructor
+ * @param {number|jQuery.Promise|Function} step Number of miliseconds to wait before proceeding, promise
+ * that must be resolved before proceeding, or a function to execute. See #createStep for more information. see #createStep for more information
+ * @param {Object} [context=null] Execution context of the function. The context is ignored if the step is
+ * a number or promise.
+ */
+OO.ui.Process = function ( step, context ) {
+ // Properties
+ this.steps = [];
+
+ // Initialization
+ if ( step !== undefined ) {
+ this.next( step, context );
+ }
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.Process );
+
+/* Methods */
+
+/**
+ * Start the process.
+ *
+ * @return {jQuery.Promise} Promise that is resolved when all steps have successfully completed.
+ * If any of the steps return a promise that is rejected or a boolean false, this promise is rejected
+ * and any remaining steps are not performed.
+ */
+OO.ui.Process.prototype.execute = function () {
+ var i, len, promise;
+
+ /**
+ * Continue execution.
+ *
+ * @ignore
+ * @param {Array} step A function and the context it should be called in
+ * @return {Function} Function that continues the process
+ */
+ function proceed( step ) {
+ return function () {
+ // Execute step in the correct context
+ var deferred,
+ result = step.callback.call( step.context );
+
+ if ( result === false ) {
+ // Use rejected promise for boolean false results
+ return $.Deferred().reject( [] ).promise();
+ }
+ if ( typeof result === 'number' ) {
+ if ( result < 0 ) {
+ throw new Error( 'Cannot go back in time: flux capacitor is out of service' );
+ }
+ // Use a delayed promise for numbers, expecting them to be in milliseconds
+ deferred = $.Deferred();
+ setTimeout( deferred.resolve, result );
+ return deferred.promise();
+ }
+ if ( result instanceof OO.ui.Error ) {
+ // Use rejected promise for error
+ return $.Deferred().reject( [ result ] ).promise();
+ }
+ if ( Array.isArray( result ) && result.length && result[ 0 ] instanceof OO.ui.Error ) {
+ // Use rejected promise for list of errors
+ return $.Deferred().reject( result ).promise();
+ }
+ // Duck-type the object to see if it can produce a promise
+ if ( result && $.isFunction( result.promise ) ) {
+ // Use a promise generated from the result
+ return result.promise();
+ }
+ // Use resolved promise for other results
+ return $.Deferred().resolve().promise();
+ };
+ }
+
+ if ( this.steps.length ) {
+ // Generate a chain reaction of promises
+ promise = proceed( this.steps[ 0 ] )();
+ for ( i = 1, len = this.steps.length; i < len; i++ ) {
+ promise = promise.then( proceed( this.steps[ i ] ) );
+ }
+ } else {
+ promise = $.Deferred().resolve().promise();
+ }
+
+ return promise;
+};
+
+/**
+ * Create a process step.
+ *
+ * @private
+ * @param {number|jQuery.Promise|Function} step
+ *
+ * - Number of milliseconds to wait before proceeding
+ * - Promise that must be resolved before proceeding
+ * - Function to execute
+ * - If the function returns a boolean false the process will stop
+ * - If the function returns a promise, the process will continue to the next
+ * step when the promise is resolved or stop if the promise is rejected
+ * - If the function returns a number, the process will wait for that number of
+ * milliseconds before proceeding
+ * @param {Object} [context=null] Execution context of the function. The context is
+ * ignored if the step is a number or promise.
+ * @return {Object} Step object, with `callback` and `context` properties
+ */
+OO.ui.Process.prototype.createStep = function ( step, context ) {
+ if ( typeof step === 'number' || $.isFunction( step.promise ) ) {
+ return {
+ callback: function () {
+ return step;
+ },
+ context: null
+ };
+ }
+ if ( $.isFunction( step ) ) {
+ return {
+ callback: step,
+ context: context
+ };
+ }
+ throw new Error( 'Cannot create process step: number, promise or function expected' );
+};
+
+/**
+ * Add step to the beginning of the process.
+ *
+ * @inheritdoc #createStep
+ * @return {OO.ui.Process} this
+ * @chainable
+ */
+OO.ui.Process.prototype.first = function ( step, context ) {
+ this.steps.unshift( this.createStep( step, context ) );
+ return this;
+};
+
+/**
+ * Add step to the end of the process.
+ *
+ * @inheritdoc #createStep
+ * @return {OO.ui.Process} this
+ * @chainable
+ */
+OO.ui.Process.prototype.next = function ( step, context ) {
+ this.steps.push( this.createStep( step, context ) );
+ return this;
+};
+
+/**
+ * A window instance represents the life cycle for one single opening of a window
+ * until its closing.
+ *
+ * While OO.ui.WindowManager will reuse OO.ui.Window objects, each time a window is
+ * opened, a new lifecycle starts.
+ *
+ * For more information, please see the [OOjs UI documentation on MediaWiki] [1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows
+ *
+ * @class
+ *
+ * @constructor
+ */
+OO.ui.WindowInstance = function OOuiWindowInstance() {
+ var deferreds = {
+ opening: $.Deferred(),
+ opened: $.Deferred(),
+ closing: $.Deferred(),
+ closed: $.Deferred()
+ };
+
+ /**
+ * @private
+ * @property {Object}
+ */
+ this.deferreds = deferreds;
+
+ // Set these up as chained promises so that rejecting of
+ // an earlier stage automatically rejects the subsequent
+ // would-be stages as well.
+
+ /**
+ * @property {jQuery.Promise}
+ */
+ this.opening = deferreds.opening.promise();
+ /**
+ * @property {jQuery.Promise}
+ */
+ this.opened = this.opening.then( function () {
+ return deferreds.opened;
+ } );
+ /**
+ * @property {jQuery.Promise}
+ */
+ this.closing = this.opened.then( function () {
+ return deferreds.closing;
+ } );
+ /**
+ * @property {jQuery.Promise}
+ */
+ this.closed = this.closing.then( function () {
+ return deferreds.closed;
+ } );
+};
+
+/* Setup */
+
+OO.initClass( OO.ui.WindowInstance );
+
+/**
+ * Check if window is opening.
+ *
+ * @return {boolean} Window is opening
+ */
+OO.ui.WindowInstance.prototype.isOpening = function () {
+ return this.deferreds.opened.state() === 'pending';
+};
+
+/**
+ * Check if window is opened.
+ *
+ * @return {boolean} Window is opened
+ */
+OO.ui.WindowInstance.prototype.isOpened = function () {
+ return this.deferreds.opened.state() === 'resolved' &&
+ this.deferreds.closing.state() === 'pending';
+};
+
+/**
+ * Check if window is closing.
+ *
+ * @return {boolean} Window is closing
+ */
+OO.ui.WindowInstance.prototype.isClosing = function () {
+ return this.deferreds.closing.state() === 'resolved' &&
+ this.deferreds.closed.state() === 'pending';
+};
+
+/**
+ * Check if window is closed.
+ *
+ * @return {boolean} Window is closed
+ */
+OO.ui.WindowInstance.prototype.isClosed = function () {
+ return this.deferreds.closed.state() === 'resolved';
+};
+
+/**
+ * Window managers are used to open and close {@link OO.ui.Window windows} and control their presentation.
+ * Managed windows are mutually exclusive. If a new window is opened while a current window is opening
+ * or is opened, the current window will be closed and any ongoing {@link OO.ui.Process process} will be cancelled. Windows
+ * themselves are persistent and—rather than being torn down when closed—can be repopulated with the
+ * pertinent data and reused.
+ *
+ * Over the lifecycle of a window, the window manager makes available three promises: `opening`,
+ * `opened`, and `closing`, which represent the primary stages of the cycle:
+ *
+ * **Opening**: the opening stage begins when the window manager’s #openWindow or a window’s
+ * {@link OO.ui.Window#open open} method is used, and the window manager begins to open the window.
+ *
+ * - an `opening` event is emitted with an `opening` promise
+ * - the #getSetupDelay method is called and the returned value is used to time a pause in execution before the
+ * window’s {@link OO.ui.Window#method-setup setup} method is called which executes OO.ui.Window#getSetupProcess.
+ * - a `setup` progress notification is emitted from the `opening` promise
+ * - the #getReadyDelay method is called the returned value is used to time a pause in execution before the
+ * window’s {@link OO.ui.Window#method-ready ready} method is called which executes OO.ui.Window#getReadyProcess.
+ * - a `ready` progress notification is emitted from the `opening` promise
+ * - the `opening` promise is resolved with an `opened` promise
+ *
+ * **Opened**: the window is now open.
+ *
+ * **Closing**: the closing stage begins when the window manager's #closeWindow or the
+ * window's {@link OO.ui.Window#close close} methods is used, and the window manager begins
+ * to close the window.
+ *
+ * - the `opened` promise is resolved with `closing` promise and a `closing` event is emitted
+ * - the #getHoldDelay method is called and the returned value is used to time a pause in execution before
+ * the window's {@link OO.ui.Window#getHoldProcess getHoldProces} method is called on the
+ * window and its result executed
+ * - a `hold` progress notification is emitted from the `closing` promise
+ * - the #getTeardownDelay() method is called and the returned value is used to time a pause in execution before
+ * the window's {@link OO.ui.Window#getTeardownProcess getTeardownProcess} method is called on the
+ * window and its result executed
+ * - a `teardown` progress notification is emitted from the `closing` promise
+ * - the `closing` promise is resolved. The window is now closed
+ *
+ * See the [OOjs UI documentation on MediaWiki][1] for more information.
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Window_managers
+ *
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {OO.Factory} [factory] Window factory to use for automatic instantiation
+ * Note that window classes that are instantiated with a factory must have
+ * a {@link OO.ui.Dialog#static-name static name} property that specifies a symbolic name.
+ * @cfg {boolean} [modal=true] Prevent interaction outside the dialog
+ */
+OO.ui.WindowManager = function OoUiWindowManager( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.WindowManager.parent.call( this, config );
+
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+
+ // Properties
+ this.factory = config.factory;
+ this.modal = config.modal === undefined || !!config.modal;
+ this.windows = {};
+ // Deprecated placeholder promise given to compatOpening in openWindow()
+ // that is resolved in closeWindow().
+ this.compatOpened = null;
+ this.preparingToOpen = null;
+ this.preparingToClose = null;
+ this.currentWindow = null;
+ this.globalEvents = false;
+ this.$returnFocusTo = null;
+ this.$ariaHidden = null;
+ this.onWindowResizeTimeout = null;
+ this.onWindowResizeHandler = this.onWindowResize.bind( this );
+ this.afterWindowResizeHandler = this.afterWindowResize.bind( this );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-windowManager' )
+ .toggleClass( 'oo-ui-windowManager-modal', this.modal );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.WindowManager, OO.ui.Element );
+OO.mixinClass( OO.ui.WindowManager, OO.EventEmitter );
+
+/* Events */
+
+/**
+ * An 'opening' event is emitted when the window begins to be opened.
+ *
+ * @event opening
+ * @param {OO.ui.Window} win Window that's being opened
+ * @param {jQuery.Promise} opened A promise resolved with a value when the window is opened successfully.
+ * This promise also emits `setup` and `ready` notifications. When this promise is resolved, the first
+ * argument of the value is an 'closed' promise, the second argument is the opening data.
+ * @param {Object} data Window opening data
+ */
+
+/**
+ * A 'closing' event is emitted when the window begins to be closed.
+ *
+ * @event closing
+ * @param {OO.ui.Window} win Window that's being closed
+ * @param {jQuery.Promise} closed A promise resolved with a value when the window is closed successfully.
+ * This promise also emits `hold` and `teardown` notifications. When this promise is resolved, the first
+ * argument of its value is the closing data.
+ * @param {Object} data Window closing data
+ */
+
+/**
+ * A 'resize' event is emitted when a window is resized.
+ *
+ * @event resize
+ * @param {OO.ui.Window} win Window that was resized
+ */
+
+/* Static Properties */
+
+/**
+ * Map of the symbolic name of each window size and its CSS properties.
+ *
+ * @static
+ * @inheritable
+ * @property {Object}
+ */
+OO.ui.WindowManager.static.sizes = {
+ small: {
+ width: 300
+ },
+ medium: {
+ width: 500
+ },
+ large: {
+ width: 700
+ },
+ larger: {
+ width: 900
+ },
+ full: {
+ // These can be non-numeric because they are never used in calculations
+ width: '100%',
+ height: '100%'
+ }
+};
+
+/**
+ * Symbolic name of the default window size.
+ *
+ * The default size is used if the window's requested size is not recognized.
+ *
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.WindowManager.static.defaultSize = 'medium';
+
+/* Methods */
+
+/**
+ * Handle window resize events.
+ *
+ * @private
+ * @param {jQuery.Event} e Window resize event
+ */
+OO.ui.WindowManager.prototype.onWindowResize = function () {
+ clearTimeout( this.onWindowResizeTimeout );
+ this.onWindowResizeTimeout = setTimeout( this.afterWindowResizeHandler, 200 );
+};
+
+/**
+ * Handle window resize events.
+ *
+ * @private
+ * @param {jQuery.Event} e Window resize event
+ */
+OO.ui.WindowManager.prototype.afterWindowResize = function () {
+ if ( this.currentWindow ) {
+ this.updateWindowSize( this.currentWindow );
+ }
+};
+
+/**
+ * Check if window is opening.
+ *
+ * @param {OO.ui.Window} win Window to check
+ * @return {boolean} Window is opening
+ */
+OO.ui.WindowManager.prototype.isOpening = function ( win ) {
+ return win === this.currentWindow && !!this.lifecycle &&
+ this.lifecycle.isOpening();
+};
+
+/**
+ * Check if window is closing.
+ *
+ * @param {OO.ui.Window} win Window to check
+ * @return {boolean} Window is closing
+ */
+OO.ui.WindowManager.prototype.isClosing = function ( win ) {
+ return win === this.currentWindow && !!this.lifecycle &&
+ this.lifecycle.isClosing();
+};
+
+/**
+ * Check if window is opened.
+ *
+ * @param {OO.ui.Window} win Window to check
+ * @return {boolean} Window is opened
+ */
+OO.ui.WindowManager.prototype.isOpened = function ( win ) {
+ return win === this.currentWindow && !!this.lifecycle &&
+ this.lifecycle.isOpened();
+};
+
+/**
+ * Check if a window is being managed.
+ *
+ * @param {OO.ui.Window} win Window to check
+ * @return {boolean} Window is being managed
+ */
+OO.ui.WindowManager.prototype.hasWindow = function ( win ) {
+ var name;
+
+ for ( name in this.windows ) {
+ if ( this.windows[ name ] === win ) {
+ return true;
+ }
+ }
+
+ return false;
+};
+
+/**
+ * Get the number of milliseconds to wait after opening begins before executing the ‘setup’ process.
+ *
+ * @param {OO.ui.Window} win Window being opened
+ * @param {Object} [data] Window opening data
+ * @return {number} Milliseconds to wait
+ */
+OO.ui.WindowManager.prototype.getSetupDelay = function () {
+ return 0;
+};
+
+/**
+ * Get the number of milliseconds to wait after setup has finished before executing the ‘ready’ process.
+ *
+ * @param {OO.ui.Window} win Window being opened
+ * @param {Object} [data] Window opening data
+ * @return {number} Milliseconds to wait
+ */
+OO.ui.WindowManager.prototype.getReadyDelay = function () {
+ return 0;
+};
+
+/**
+ * Get the number of milliseconds to wait after closing has begun before executing the 'hold' process.
+ *
+ * @param {OO.ui.Window} win Window being closed
+ * @param {Object} [data] Window closing data
+ * @return {number} Milliseconds to wait
+ */
+OO.ui.WindowManager.prototype.getHoldDelay = function () {
+ return 0;
+};
+
+/**
+ * Get the number of milliseconds to wait after the ‘hold’ process has finished before
+ * executing the ‘teardown’ process.
+ *
+ * @param {OO.ui.Window} win Window being closed
+ * @param {Object} [data] Window closing data
+ * @return {number} Milliseconds to wait
+ */
+OO.ui.WindowManager.prototype.getTeardownDelay = function () {
+ return this.modal ? 250 : 0;
+};
+
+/**
+ * Get a window by its symbolic name.
+ *
+ * If the window is not yet instantiated and its symbolic name is recognized by a factory, it will be
+ * instantiated and added to the window manager automatically. Please see the [OOjs UI documentation on MediaWiki][3]
+ * for more information about using factories.
+ * [3]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Window_managers
+ *
+ * @param {string} name Symbolic name of the window
+ * @return {jQuery.Promise} Promise resolved with matching window, or rejected with an OO.ui.Error
+ * @throws {Error} An error is thrown if the symbolic name is not recognized by the factory.
+ * @throws {Error} An error is thrown if the named window is not recognized as a managed window.
+ */
+OO.ui.WindowManager.prototype.getWindow = function ( name ) {
+ var deferred = $.Deferred(),
+ win = this.windows[ name ];
+
+ if ( !( win instanceof OO.ui.Window ) ) {
+ if ( this.factory ) {
+ if ( !this.factory.lookup( name ) ) {
+ deferred.reject( new OO.ui.Error(
+ 'Cannot auto-instantiate window: symbolic name is unrecognized by the factory'
+ ) );
+ } else {
+ win = this.factory.create( name );
+ this.addWindows( [ win ] );
+ deferred.resolve( win );
+ }
+ } else {
+ deferred.reject( new OO.ui.Error(
+ 'Cannot get unmanaged window: symbolic name unrecognized as a managed window'
+ ) );
+ }
+ } else {
+ deferred.resolve( win );
+ }
+
+ return deferred.promise();
+};
+
+/**
+ * Get current window.
+ *
+ * @return {OO.ui.Window|null} Currently opening/opened/closing window
+ */
+OO.ui.WindowManager.prototype.getCurrentWindow = function () {
+ return this.currentWindow;
+};
+
+/**
+ * Open a window.
+ *
+ * @param {OO.ui.Window|string} win Window object or symbolic name of window to open
+ * @param {Object} [data] Window opening data
+ * @param {jQuery|null} [data.$returnFocusTo] Element to which the window will return focus when closed.
+ * Defaults the current activeElement. If set to null, focus isn't changed on close.
+ * @return {OO.ui.WindowInstance|jQuery.Promise} A lifecycle object representing this particular
+ * opening of the window. For backwards-compatibility, then object is also a Thenable that is resolved
+ * when the window is done opening, with nested promise for when closing starts. This behaviour
+ * is deprecated and is not compatible with jQuery 3. See T163510.
+ * @fires opening
+ */
+OO.ui.WindowManager.prototype.openWindow = function ( win, data, lifecycle, compatOpening ) {
+ var error,
+ manager = this;
+ data = data || {};
+
+ // Internal parameter 'lifecycle' allows this method to always return
+ // a lifecycle even if the window still needs to be created
+ // asynchronously when 'win' is a string.
+ lifecycle = lifecycle || new OO.ui.WindowInstance();
+ compatOpening = compatOpening || $.Deferred();
+
+ // Turn lifecycle into a Thenable for backwards-compatibility with
+ // the deprecated nested-promise behaviour, see T163510.
+ [ 'state', 'always', 'catch', 'pipe', 'then', 'promise', 'progress', 'done', 'fail' ]
+ .forEach( function ( method ) {
+ lifecycle[ method ] = function () {
+ OO.ui.warnDeprecation(
+ 'Using the return value of openWindow as a promise is deprecated. ' +
+ 'Use .openWindow( ... ).opening.' + method + '( ... ) instead.'
+ );
+ return compatOpening[ method ].apply( this, arguments );
+ };
+ } );
+
+ // Argument handling
+ if ( typeof win === 'string' ) {
+ this.getWindow( win ).then(
+ function ( win ) {
+ manager.openWindow( win, data, lifecycle, compatOpening );
+ },
+ function ( err ) {
+ lifecycle.deferreds.opening.reject( err );
+ }
+ );
+ return lifecycle;
+ }
+
+ // Error handling
+ if ( !this.hasWindow( win ) ) {
+ error = 'Cannot open window: window is not attached to manager';
+ } else if ( this.lifecycle && this.lifecycle.isOpened() ) {
+ error = 'Cannot open window: another window is open';
+ } else if ( this.preparingToOpen || ( this.lifecycle && this.lifecycle.isOpening() ) ) {
+ error = 'Cannot open window: another window is opening';
+ }
+
+ if ( error ) {
+ compatOpening.reject( new OO.ui.Error( error ) );
+ lifecycle.deferreds.opening.reject( new OO.ui.Error( error ) );
+ return lifecycle;
+ }
+
+ // If a window is currently closing, wait for it to complete
+ this.preparingToOpen = $.when( this.lifecycle && this.lifecycle.closed );
+ // Ensure handlers get called after preparingToOpen is set
+ this.preparingToOpen.done( function () {
+ if ( manager.modal ) {
+ manager.toggleGlobalEvents( true );
+ manager.toggleAriaIsolation( true );
+ }
+ manager.$returnFocusTo = data.$returnFocusTo !== undefined ? data.$returnFocusTo : $( document.activeElement );
+ manager.currentWindow = win;
+ manager.lifecycle = lifecycle;
+ manager.preparingToOpen = null;
+ manager.emit( 'opening', win, compatOpening, data );
+ lifecycle.deferreds.opening.resolve( data );
+ setTimeout( function () {
+ manager.compatOpened = $.Deferred();
+ win.setup( data ).then( function () {
+ manager.updateWindowSize( win );
+ compatOpening.notify( { state: 'setup' } );
+ setTimeout( function () {
+ win.ready( data ).then( function () {
+ compatOpening.notify( { state: 'ready' } );
+ lifecycle.deferreds.opened.resolve( data );
+ compatOpening.resolve( manager.compatOpened.promise(), data );
+ }, function () {
+ lifecycle.deferreds.opened.reject();
+ compatOpening.reject();
+ manager.closeWindow( win );
+ } );
+ }, manager.getReadyDelay() );
+ }, function () {
+ lifecycle.deferreds.opened.reject();
+ compatOpening.reject();
+ manager.closeWindow( win );
+ } );
+ }, manager.getSetupDelay() );
+ } );
+
+ return lifecycle;
+};
+
+/**
+ * Close a window.
+ *
+ * @param {OO.ui.Window|string} win Window object or symbolic name of window to close
+ * @param {Object} [data] Window closing data
+ * @return {OO.ui.WindowInstance|jQuery.Promise} A lifecycle object representing this particular
+ * opening of the window. For backwards-compatibility, the object is also a Thenable that is resolved
+ * when the window is done closing, see T163510.
+ * @fires closing
+ */
+OO.ui.WindowManager.prototype.closeWindow = function ( win, data ) {
+ var error,
+ manager = this,
+ compatClosing = $.Deferred(),
+ lifecycle = this.lifecycle,
+ compatOpened;
+
+ // Argument handling
+ if ( typeof win === 'string' ) {
+ win = this.windows[ win ];
+ } else if ( !this.hasWindow( win ) ) {
+ win = null;
+ }
+
+ // Error handling
+ if ( !lifecycle ) {
+ error = 'Cannot close window: no window is currently open';
+ } else if ( !win ) {
+ error = 'Cannot close window: window is not attached to manager';
+ } else if ( win !== this.currentWindow || this.lifecycle.isClosed() ) {
+ error = 'Cannot close window: window already closed with different data';
+ } else if ( this.preparingToClose || this.lifecycle.isClosing() ) {
+ error = 'Cannot close window: window already closing with different data';
+ }
+
+ if ( error ) {
+ // This function was called for the wrong window and we don't want to mess with the current
+ // window's state.
+ lifecycle = new OO.ui.WindowInstance();
+ // Pretend the window has been opened, so that we can pretend to fail to close it.
+ lifecycle.deferreds.opening.resolve( {} );
+ lifecycle.deferreds.opened.resolve( {} );
+ }
+
+ // Turn lifecycle into a Thenable for backwards-compatibility with
+ // the deprecated nested-promise behaviour, see T163510.
+ [ 'state', 'always', 'catch', 'pipe', 'then', 'promise', 'progress', 'done', 'fail' ]
+ .forEach( function ( method ) {
+ lifecycle[ method ] = function () {
+ OO.ui.warnDeprecation(
+ 'Using the return value of closeWindow as a promise is deprecated. ' +
+ 'Use .closeWindow( ... ).closed.' + method + '( ... ) instead.'
+ );
+ return compatClosing[ method ].apply( this, arguments );
+ };
+ } );
+
+ if ( error ) {
+ compatClosing.reject( new OO.ui.Error( error ) );
+ lifecycle.deferreds.closing.reject( new OO.ui.Error( error ) );
+ return lifecycle;
+ }
+
+ // If the window is currently opening, close it when it's done
+ this.preparingToClose = $.when( this.lifecycle.opened );
+ // Ensure handlers get called after preparingToClose is set
+ this.preparingToClose.always( function () {
+ manager.preparingToClose = null;
+ manager.emit( 'closing', win, compatClosing, data );
+ lifecycle.deferreds.closing.resolve( data );
+ compatOpened = manager.compatOpened;
+ manager.compatOpened = null;
+ compatOpened.resolve( compatClosing.promise(), data );
+ setTimeout( function () {
+ win.hold( data ).then( function () {
+ compatClosing.notify( { state: 'hold' } );
+ setTimeout( function () {
+ win.teardown( data ).then( function () {
+ compatClosing.notify( { state: 'teardown' } );
+ if ( manager.modal ) {
+ manager.toggleGlobalEvents( false );
+ manager.toggleAriaIsolation( false );
+ }
+ if ( manager.$returnFocusTo && manager.$returnFocusTo.length ) {
+ manager.$returnFocusTo[ 0 ].focus();
+ }
+ manager.currentWindow = null;
+ manager.lifecycle = null;
+ lifecycle.deferreds.closed.resolve( data );
+ compatClosing.resolve( data );
+ } );
+ }, manager.getTeardownDelay() );
+ } );
+ }, manager.getHoldDelay() );
+ } );
+
+ return lifecycle;
+};
+
+/**
+ * Add windows to the window manager.
+ *
+ * Windows can be added by reference, symbolic name, or explicitly defined symbolic names.
+ * See the [OOjs ui documentation on MediaWiki] [2] for examples.
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Window_managers
+ *
+ * This function can be called in two manners:
+ *
+ * 1. `.addWindows( [ windowA, windowB, ... ] )` (where `windowA`, `windowB` are OO.ui.Window objects)
+ *
+ * This syntax registers windows under the symbolic names defined in their `.static.name`
+ * properties. For example, if `windowA.constructor.static.name` is `'nameA'`, calling
+ * `.openWindow( 'nameA' )` afterwards will open the window `windowA`. This syntax requires the
+ * static name to be set, otherwise an exception will be thrown.
+ *
+ * This is the recommended way, as it allows for an easier switch to using a window factory.
+ *
+ * 2. `.addWindows( { nameA: windowA, nameB: windowB, ... } )`
+ *
+ * This syntax registers windows under the explicitly given symbolic names. In this example,
+ * calling `.openWindow( 'nameA' )` afterwards will open the window `windowA`, regardless of what
+ * its `.static.name` is set to. The static name is not required to be set.
+ *
+ * This should only be used if you need to override the default symbolic names.
+ *
+ * Example:
+ *
+ * var windowManager = new OO.ui.WindowManager();
+ * $( 'body' ).append( windowManager.$element );
+ *
+ * // Add a window under the default name: see OO.ui.MessageDialog.static.name
+ * windowManager.addWindows( [ new OO.ui.MessageDialog() ] );
+ * // Add a window under an explicit name
+ * windowManager.addWindows( { myMessageDialog: new OO.ui.MessageDialog() } );
+ *
+ * // Open window by default name
+ * windowManager.openWindow( 'message' );
+ * // Open window by explicitly given name
+ * windowManager.openWindow( 'myMessageDialog' );
+ *
+ *
+ * @param {Object.<string,OO.ui.Window>|OO.ui.Window[]} windows An array of window objects specified
+ * by reference, symbolic name, or explicitly defined symbolic names.
+ * @throws {Error} An error is thrown if a window is added by symbolic name, but has neither an
+ * explicit nor a statically configured symbolic name.
+ */
+OO.ui.WindowManager.prototype.addWindows = function ( windows ) {
+ var i, len, win, name, list;
+
+ if ( Array.isArray( windows ) ) {
+ // Convert to map of windows by looking up symbolic names from static configuration
+ list = {};
+ for ( i = 0, len = windows.length; i < len; i++ ) {
+ name = windows[ i ].constructor.static.name;
+ if ( !name ) {
+ throw new Error( 'Windows must have a `name` static property defined.' );
+ }
+ list[ name ] = windows[ i ];
+ }
+ } else if ( OO.isPlainObject( windows ) ) {
+ list = windows;
+ }
+
+ // Add windows
+ for ( name in list ) {
+ win = list[ name ];
+ this.windows[ name ] = win.toggle( false );
+ this.$element.append( win.$element );
+ win.setManager( this );
+ }
+};
+
+/**
+ * Remove the specified windows from the windows manager.
+ *
+ * Windows will be closed before they are removed. If you wish to remove all windows, you may wish to use
+ * the #clearWindows method instead. If you no longer need the window manager and want to ensure that it no
+ * longer listens to events, use the #destroy method.
+ *
+ * @param {string[]} names Symbolic names of windows to remove
+ * @return {jQuery.Promise} Promise resolved when window is closed and removed
+ * @throws {Error} An error is thrown if the named windows are not managed by the window manager.
+ */
+OO.ui.WindowManager.prototype.removeWindows = function ( names ) {
+ var i, len, win, name, cleanupWindow,
+ manager = this,
+ promises = [],
+ cleanup = function ( name, win ) {
+ delete manager.windows[ name ];
+ win.$element.detach();
+ };
+
+ for ( i = 0, len = names.length; i < len; i++ ) {
+ name = names[ i ];
+ win = this.windows[ name ];
+ if ( !win ) {
+ throw new Error( 'Cannot remove window' );
+ }
+ cleanupWindow = cleanup.bind( null, name, win );
+ promises.push( this.closeWindow( name ).closed.then( cleanupWindow, cleanupWindow ) );
+ }
+
+ return $.when.apply( $, promises );
+};
+
+/**
+ * Remove all windows from the window manager.
+ *
+ * Windows will be closed before they are removed. Note that the window manager, though not in use, will still
+ * listen to events. If the window manager will not be used again, you may wish to use the #destroy method instead.
+ * To remove just a subset of windows, use the #removeWindows method.
+ *
+ * @return {jQuery.Promise} Promise resolved when all windows are closed and removed
+ */
+OO.ui.WindowManager.prototype.clearWindows = function () {
+ return this.removeWindows( Object.keys( this.windows ) );
+};
+
+/**
+ * Set dialog size. In general, this method should not be called directly.
+ *
+ * Fullscreen mode will be used if the dialog is too wide to fit in the screen.
+ *
+ * @param {OO.ui.Window} win Window to update, should be the current window
+ * @chainable
+ */
+OO.ui.WindowManager.prototype.updateWindowSize = function ( win ) {
+ var isFullscreen;
+
+ // Bypass for non-current, and thus invisible, windows
+ if ( win !== this.currentWindow ) {
+ return;
+ }
+
+ isFullscreen = win.getSize() === 'full';
+
+ this.$element.toggleClass( 'oo-ui-windowManager-fullscreen', isFullscreen );
+ this.$element.toggleClass( 'oo-ui-windowManager-floating', !isFullscreen );
+ win.setDimensions( win.getSizeProperties() );
+
+ this.emit( 'resize', win );
+
+ return this;
+};
+
+/**
+ * Bind or unbind global events for scrolling.
+ *
+ * @private
+ * @param {boolean} [on] Bind global events
+ * @chainable
+ */
+OO.ui.WindowManager.prototype.toggleGlobalEvents = function ( on ) {
+ var scrollWidth, bodyMargin,
+ $body = $( this.getElementDocument().body ),
+ // We could have multiple window managers open so only modify
+ // the body css at the bottom of the stack
+ stackDepth = $body.data( 'windowManagerGlobalEvents' ) || 0;
+
+ on = on === undefined ? !!this.globalEvents : !!on;
+
+ if ( on ) {
+ if ( !this.globalEvents ) {
+ $( this.getElementWindow() ).on( {
+ // Start listening for top-level window dimension changes
+ 'orientationchange resize': this.onWindowResizeHandler
+ } );
+ if ( stackDepth === 0 ) {
+ scrollWidth = window.innerWidth - document.documentElement.clientWidth;
+ bodyMargin = parseFloat( $body.css( 'margin-right' ) ) || 0;
+ $body.css( {
+ overflow: 'hidden',
+ 'margin-right': bodyMargin + scrollWidth
+ } );
+ }
+ stackDepth++;
+ this.globalEvents = true;
+ }
+ } else if ( this.globalEvents ) {
+ $( this.getElementWindow() ).off( {
+ // Stop listening for top-level window dimension changes
+ 'orientationchange resize': this.onWindowResizeHandler
+ } );
+ stackDepth--;
+ if ( stackDepth === 0 ) {
+ $body.css( {
+ overflow: '',
+ 'margin-right': ''
+ } );
+ }
+ this.globalEvents = false;
+ }
+ $body.data( 'windowManagerGlobalEvents', stackDepth );
+
+ return this;
+};
+
+/**
+ * Toggle screen reader visibility of content other than the window manager.
+ *
+ * @private
+ * @param {boolean} [isolate] Make only the window manager visible to screen readers
+ * @chainable
+ */
+OO.ui.WindowManager.prototype.toggleAriaIsolation = function ( isolate ) {
+ isolate = isolate === undefined ? !this.$ariaHidden : !!isolate;
+
+ if ( isolate ) {
+ if ( !this.$ariaHidden ) {
+ // Hide everything other than the window manager from screen readers
+ this.$ariaHidden = $( 'body' )
+ .children()
+ .not( this.$element.parentsUntil( 'body' ).last() )
+ .attr( 'aria-hidden', '' );
+ }
+ } else if ( this.$ariaHidden ) {
+ // Restore screen reader visibility
+ this.$ariaHidden.removeAttr( 'aria-hidden' );
+ this.$ariaHidden = null;
+ }
+
+ return this;
+};
+
+/**
+ * Destroy the window manager.
+ *
+ * Destroying the window manager ensures that it will no longer listen to events. If you would like to
+ * continue using the window manager, but wish to remove all windows from it, use the #clearWindows method
+ * instead.
+ */
+OO.ui.WindowManager.prototype.destroy = function () {
+ this.toggleGlobalEvents( false );
+ this.toggleAriaIsolation( false );
+ this.clearWindows();
+ this.$element.remove();
+};
+
+/**
+ * A window is a container for elements that are in a child frame. They are used with
+ * a window manager (OO.ui.WindowManager), which is used to open and close the window and control
+ * its presentation. The size of a window is specified using a symbolic name (e.g., ‘small’, ‘medium’,
+ * ‘large’), which is interpreted by the window manager. If the requested size is not recognized,
+ * the window manager will choose a sensible fallback.
+ *
+ * The lifecycle of a window has three primary stages (opening, opened, and closing) in which
+ * different processes are executed:
+ *
+ * **opening**: The opening stage begins when the window manager's {@link OO.ui.WindowManager#openWindow
+ * openWindow} or the window's {@link #open open} methods are used, and the window manager begins to open
+ * the window.
+ *
+ * - {@link #getSetupProcess} method is called and its result executed
+ * - {@link #getReadyProcess} method is called and its result executed
+ *
+ * **opened**: The window is now open
+ *
+ * **closing**: The closing stage begins when the window manager's
+ * {@link OO.ui.WindowManager#closeWindow closeWindow}
+ * or the window's {@link #close} methods are used, and the window manager begins to close the window.
+ *
+ * - {@link #getHoldProcess} method is called and its result executed
+ * - {@link #getTeardownProcess} method is called and its result executed. The window is now closed
+ *
+ * Each of the window's processes (setup, ready, hold, and teardown) can be extended in subclasses
+ * by overriding the window's #getSetupProcess, #getReadyProcess, #getHoldProcess and #getTeardownProcess
+ * methods. Note that each {@link OO.ui.Process process} is executed in series, so asynchronous
+ * processing can complete. Always assume window processes are executed asynchronously.
+ *
+ * For more information, please see the [OOjs UI documentation on MediaWiki] [1].
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Element
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [size] Symbolic name of the dialog size: `small`, `medium`, `large`, `larger` or
+ * `full`. If omitted, the value of the {@link #static-size static size} property will be used.
+ */
+OO.ui.Window = function OoUiWindow( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ OO.ui.Window.parent.call( this, config );
+
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+
+ // Properties
+ this.manager = null;
+ this.size = config.size || this.constructor.static.size;
+ this.$frame = $( '<div>' );
+ /**
+ * Overlay element to use for the `$overlay` configuration option of widgets that support it.
+ * Things put inside of it are overlaid on top of the window and are not bound to its dimensions.
+ * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.
+ *
+ * MyDialog.prototype.initialize = function () {
+ * ...
+ * var popupButton = new OO.ui.PopupButtonWidget( {
+ * $overlay: this.$overlay,
+ * label: 'Popup button',
+ * popup: {
+ * $content: $( '<p>Popup contents.</p><p>Popup contents.</p><p>Popup contents.</p>' ),
+ * padded: true
+ * }
+ * } );
+ * ...
+ * };
+ *
+ * @property {jQuery}
+ */
+ this.$overlay = $( '<div>' );
+ this.$content = $( '<div>' );
+
+ this.$focusTrapBefore = $( '<div>' ).prop( 'tabIndex', 0 );
+ this.$focusTrapAfter = $( '<div>' ).prop( 'tabIndex', 0 );
+ this.$focusTraps = this.$focusTrapBefore.add( this.$focusTrapAfter );
+
+ // Initialization
+ this.$overlay.addClass( 'oo-ui-window-overlay' );
+ this.$content
+ .addClass( 'oo-ui-window-content' )
+ .attr( 'tabindex', 0 );
+ this.$frame
+ .addClass( 'oo-ui-window-frame' )
+ .append( this.$focusTrapBefore, this.$content, this.$focusTrapAfter );
+
+ this.$element
+ .addClass( 'oo-ui-window' )
+ .append( this.$frame, this.$overlay );
+
+ // Initially hidden - using #toggle may cause errors if subclasses override toggle with methods
+ // that reference properties not initialized at that time of parent class construction
+ // TODO: Find a better way to handle post-constructor setup
+ this.visible = false;
+ this.$element.addClass( 'oo-ui-element-hidden' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Window, OO.ui.Element );
+OO.mixinClass( OO.ui.Window, OO.EventEmitter );
+
+/* Static Properties */
+
+/**
+ * Symbolic name of the window size: `small`, `medium`, `large`, `larger` or `full`.
+ *
+ * The static size is used if no #size is configured during construction.
+ *
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.Window.static.size = 'medium';
+
+/* Methods */
+
+/**
+ * Handle mouse down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse down event
+ */
+OO.ui.Window.prototype.onMouseDown = function ( e ) {
+ // Prevent clicking on the click-block from stealing focus
+ if ( e.target === this.$element[ 0 ] ) {
+ return false;
+ }
+};
+
+/**
+ * Check if the window has been initialized.
+ *
+ * Initialization occurs when a window is added to a manager.
+ *
+ * @return {boolean} Window has been initialized
+ */
+OO.ui.Window.prototype.isInitialized = function () {
+ return !!this.manager;
+};
+
+/**
+ * Check if the window is visible.
+ *
+ * @return {boolean} Window is visible
+ */
+OO.ui.Window.prototype.isVisible = function () {
+ return this.visible;
+};
+
+/**
+ * Check if the window is opening.
+ *
+ * This method is a wrapper around the window manager's {@link OO.ui.WindowManager#isOpening isOpening}
+ * method.
+ *
+ * @return {boolean} Window is opening
+ */
+OO.ui.Window.prototype.isOpening = function () {
+ return this.manager.isOpening( this );
+};
+
+/**
+ * Check if the window is closing.
+ *
+ * This method is a wrapper around the window manager's {@link OO.ui.WindowManager#isClosing isClosing} method.
+ *
+ * @return {boolean} Window is closing
+ */
+OO.ui.Window.prototype.isClosing = function () {
+ return this.manager.isClosing( this );
+};
+
+/**
+ * Check if the window is opened.
+ *
+ * This method is a wrapper around the window manager's {@link OO.ui.WindowManager#isOpened isOpened} method.
+ *
+ * @return {boolean} Window is opened
+ */
+OO.ui.Window.prototype.isOpened = function () {
+ return this.manager.isOpened( this );
+};
+
+/**
+ * Get the window manager.
+ *
+ * All windows must be attached to a window manager, which is used to open
+ * and close the window and control its presentation.
+ *
+ * @return {OO.ui.WindowManager} Manager of window
+ */
+OO.ui.Window.prototype.getManager = function () {
+ return this.manager;
+};
+
+/**
+ * Get the symbolic name of the window size (e.g., `small` or `medium`).
+ *
+ * @return {string} Symbolic name of the size: `small`, `medium`, `large`, `larger`, `full`
+ */
+OO.ui.Window.prototype.getSize = function () {
+ var viewport = OO.ui.Element.static.getDimensions( this.getElementWindow() ),
+ sizes = this.manager.constructor.static.sizes,
+ size = this.size;
+
+ if ( !sizes[ size ] ) {
+ size = this.manager.constructor.static.defaultSize;
+ }
+ if ( size !== 'full' && viewport.rect.right - viewport.rect.left < sizes[ size ].width ) {
+ size = 'full';
+ }
+
+ return size;
+};
+
+/**
+ * Get the size properties associated with the current window size
+ *
+ * @return {Object} Size properties
+ */
+OO.ui.Window.prototype.getSizeProperties = function () {
+ return this.manager.constructor.static.sizes[ this.getSize() ];
+};
+
+/**
+ * Disable transitions on window's frame for the duration of the callback function, then enable them
+ * back.
+ *
+ * @private
+ * @param {Function} callback Function to call while transitions are disabled
+ */
+OO.ui.Window.prototype.withoutSizeTransitions = function ( callback ) {
+ // Temporarily resize the frame so getBodyHeight() can use scrollHeight measurements.
+ // Disable transitions first, otherwise we'll get values from when the window was animating.
+ // We need to build the transition CSS properties using these specific properties since
+ // Firefox doesn't return anything useful when asked just for 'transition'.
+ var oldTransition = this.$frame.css( 'transition-property' ) + ' ' +
+ this.$frame.css( 'transition-duration' ) + ' ' +
+ this.$frame.css( 'transition-timing-function' ) + ' ' +
+ this.$frame.css( 'transition-delay' );
+
+ this.$frame.css( 'transition', 'none' );
+ callback();
+
+ // Force reflow to make sure the style changes done inside callback
+ // really are not transitioned
+ this.$frame.height();
+ this.$frame.css( 'transition', oldTransition );
+};
+
+/**
+ * Get the height of the full window contents (i.e., the window head, body and foot together).
+ *
+ * What consistitutes the head, body, and foot varies depending on the window type.
+ * A {@link OO.ui.MessageDialog message dialog} displays a title and message in its body,
+ * and any actions in the foot. A {@link OO.ui.ProcessDialog process dialog} displays a title
+ * and special actions in the head, and dialog content in the body.
+ *
+ * To get just the height of the dialog body, use the #getBodyHeight method.
+ *
+ * @return {number} The height of the window contents (the dialog head, body and foot) in pixels
+ */
+OO.ui.Window.prototype.getContentHeight = function () {
+ var bodyHeight,
+ win = this,
+ bodyStyleObj = this.$body[ 0 ].style,
+ frameStyleObj = this.$frame[ 0 ].style;
+
+ // Temporarily resize the frame so getBodyHeight() can use scrollHeight measurements.
+ // Disable transitions first, otherwise we'll get values from when the window was animating.
+ this.withoutSizeTransitions( function () {
+ var oldHeight = frameStyleObj.height,
+ oldPosition = bodyStyleObj.position;
+ frameStyleObj.height = '1px';
+ // Force body to resize to new width
+ bodyStyleObj.position = 'relative';
+ bodyHeight = win.getBodyHeight();
+ frameStyleObj.height = oldHeight;
+ bodyStyleObj.position = oldPosition;
+ } );
+
+ return (
+ // Add buffer for border
+ ( this.$frame.outerHeight() - this.$frame.innerHeight() ) +
+ // Use combined heights of children
+ ( this.$head.outerHeight( true ) + bodyHeight + this.$foot.outerHeight( true ) )
+ );
+};
+
+/**
+ * Get the height of the window body.
+ *
+ * To get the height of the full window contents (the window body, head, and foot together),
+ * use #getContentHeight.
+ *
+ * When this function is called, the window will temporarily have been resized
+ * to height=1px, so .scrollHeight measurements can be taken accurately.
+ *
+ * @return {number} Height of the window body in pixels
+ */
+OO.ui.Window.prototype.getBodyHeight = function () {
+ return this.$body[ 0 ].scrollHeight;
+};
+
+/**
+ * Get the directionality of the frame (right-to-left or left-to-right).
+ *
+ * @return {string} Directionality: `'ltr'` or `'rtl'`
+ */
+OO.ui.Window.prototype.getDir = function () {
+ return OO.ui.Element.static.getDir( this.$content ) || 'ltr';
+};
+
+/**
+ * Get the 'setup' process.
+ *
+ * The setup process is used to set up a window for use in a particular context,
+ * based on the `data` argument. This method is called during the opening phase of the window’s
+ * lifecycle.
+ *
+ * Override this method to add additional steps to the ‘setup’ process the parent method provides
+ * using the {@link OO.ui.Process#first first} and {@link OO.ui.Process#next next} methods
+ * of OO.ui.Process.
+ *
+ * To add window content that persists between openings, you may wish to use the #initialize method
+ * instead.
+ *
+ * @param {Object} [data] Window opening data
+ * @return {OO.ui.Process} Setup process
+ */
+OO.ui.Window.prototype.getSetupProcess = function () {
+ return new OO.ui.Process();
+};
+
+/**
+ * Get the ‘ready’ process.
+ *
+ * The ready process is used to ready a window for use in a particular
+ * context, based on the `data` argument. This method is called during the opening phase of
+ * the window’s lifecycle, after the window has been {@link #getSetupProcess setup}.
+ *
+ * Override this method to add additional steps to the ‘ready’ process the parent method
+ * provides using the {@link OO.ui.Process#first first} and {@link OO.ui.Process#next next}
+ * methods of OO.ui.Process.
+ *
+ * @param {Object} [data] Window opening data
+ * @return {OO.ui.Process} Ready process
+ */
+OO.ui.Window.prototype.getReadyProcess = function () {
+ return new OO.ui.Process();
+};
+
+/**
+ * Get the 'hold' process.
+ *
+ * The hold process is used to keep a window from being used in a particular context,
+ * based on the `data` argument. This method is called during the closing phase of the window’s
+ * lifecycle.
+ *
+ * Override this method to add additional steps to the 'hold' process the parent method provides
+ * using the {@link OO.ui.Process#first first} and {@link OO.ui.Process#next next} methods
+ * of OO.ui.Process.
+ *
+ * @param {Object} [data] Window closing data
+ * @return {OO.ui.Process} Hold process
+ */
+OO.ui.Window.prototype.getHoldProcess = function () {
+ return new OO.ui.Process();
+};
+
+/**
+ * Get the ‘teardown’ process.
+ *
+ * The teardown process is used to teardown a window after use. During teardown,
+ * user interactions within the window are conveyed and the window is closed, based on the `data`
+ * argument. This method is called during the closing phase of the window’s lifecycle.
+ *
+ * Override this method to add additional steps to the ‘teardown’ process the parent method provides
+ * using the {@link OO.ui.Process#first first} and {@link OO.ui.Process#next next} methods
+ * of OO.ui.Process.
+ *
+ * @param {Object} [data] Window closing data
+ * @return {OO.ui.Process} Teardown process
+ */
+OO.ui.Window.prototype.getTeardownProcess = function () {
+ return new OO.ui.Process();
+};
+
+/**
+ * Set the window manager.
+ *
+ * This will cause the window to initialize. Calling it more than once will cause an error.
+ *
+ * @param {OO.ui.WindowManager} manager Manager for this window
+ * @throws {Error} An error is thrown if the method is called more than once
+ * @chainable
+ */
+OO.ui.Window.prototype.setManager = function ( manager ) {
+ if ( this.manager ) {
+ throw new Error( 'Cannot set window manager, window already has a manager' );
+ }
+
+ this.manager = manager;
+ this.initialize();
+
+ return this;
+};
+
+/**
+ * Set the window size by symbolic name (e.g., 'small' or 'medium')
+ *
+ * @param {string} size Symbolic name of size: `small`, `medium`, `large`, `larger` or
+ * `full`
+ * @chainable
+ */
+OO.ui.Window.prototype.setSize = function ( size ) {
+ this.size = size;
+ this.updateSize();
+ return this;
+};
+
+/**
+ * Update the window size.
+ *
+ * @throws {Error} An error is thrown if the window is not attached to a window manager
+ * @chainable
+ */
+OO.ui.Window.prototype.updateSize = function () {
+ if ( !this.manager ) {
+ throw new Error( 'Cannot update window size, must be attached to a manager' );
+ }
+
+ this.manager.updateWindowSize( this );
+
+ return this;
+};
+
+/**
+ * Set window dimensions. This method is called by the {@link OO.ui.WindowManager window manager}
+ * when the window is opening. In general, setDimensions should not be called directly.
+ *
+ * To set the size of the window, use the #setSize method.
+ *
+ * @param {Object} dim CSS dimension properties
+ * @param {string|number} [dim.width] Width
+ * @param {string|number} [dim.minWidth] Minimum width
+ * @param {string|number} [dim.maxWidth] Maximum width
+ * @param {string|number} [dim.height] Height, omit to set based on height of contents
+ * @param {string|number} [dim.minHeight] Minimum height
+ * @param {string|number} [dim.maxHeight] Maximum height
+ * @chainable
+ */
+OO.ui.Window.prototype.setDimensions = function ( dim ) {
+ var height,
+ win = this,
+ styleObj = this.$frame[ 0 ].style;
+
+ // Calculate the height we need to set using the correct width
+ if ( dim.height === undefined ) {
+ this.withoutSizeTransitions( function () {
+ var oldWidth = styleObj.width;
+ win.$frame.css( 'width', dim.width || '' );
+ height = win.getContentHeight();
+ styleObj.width = oldWidth;
+ } );
+ } else {
+ height = dim.height;
+ }
+
+ this.$frame.css( {
+ width: dim.width || '',
+ minWidth: dim.minWidth || '',
+ maxWidth: dim.maxWidth || '',
+ height: height || '',
+ minHeight: dim.minHeight || '',
+ maxHeight: dim.maxHeight || ''
+ } );
+
+ return this;
+};
+
+/**
+ * Initialize window contents.
+ *
+ * Before the window is opened for the first time, #initialize is called so that content that
+ * persists between openings can be added to the window.
+ *
+ * To set up a window with new content each time the window opens, use #getSetupProcess.
+ *
+ * @throws {Error} An error is thrown if the window is not attached to a window manager
+ * @chainable
+ */
+OO.ui.Window.prototype.initialize = function () {
+ if ( !this.manager ) {
+ throw new Error( 'Cannot initialize window, must be attached to a manager' );
+ }
+
+ // Properties
+ this.$head = $( '<div>' );
+ this.$body = $( '<div>' );
+ this.$foot = $( '<div>' );
+ this.$document = $( this.getElementDocument() );
+
+ // Events
+ this.$element.on( 'mousedown', this.onMouseDown.bind( this ) );
+
+ // Initialization
+ this.$head.addClass( 'oo-ui-window-head' );
+ this.$body.addClass( 'oo-ui-window-body' );
+ this.$foot.addClass( 'oo-ui-window-foot' );
+ this.$content.append( this.$head, this.$body, this.$foot );
+
+ return this;
+};
+
+/**
+ * Called when someone tries to focus the hidden element at the end of the dialog.
+ * Sends focus back to the start of the dialog.
+ *
+ * @param {jQuery.Event} event Focus event
+ */
+OO.ui.Window.prototype.onFocusTrapFocused = function ( event ) {
+ var backwards = this.$focusTrapBefore.is( event.target ),
+ element = OO.ui.findFocusable( this.$content, backwards );
+ if ( element ) {
+ // There's a focusable element inside the content, at the front or
+ // back depending on which focus trap we hit; select it.
+ element.focus();
+ } else {
+ // There's nothing focusable inside the content. As a fallback,
+ // this.$content is focusable, and focusing it will keep our focus
+ // properly trapped. It's not a *meaningful* focus, since it's just
+ // the content-div for the Window, but it's better than letting focus
+ // escape into the page.
+ this.$content.focus();
+ }
+};
+
+/**
+ * Open the window.
+ *
+ * This method is a wrapper around a call to the window manager’s {@link OO.ui.WindowManager#openWindow openWindow}
+ * method, which returns a promise resolved when the window is done opening.
+ *
+ * To customize the window each time it opens, use #getSetupProcess or #getReadyProcess.
+ *
+ * @param {Object} [data] Window opening data
+ * @return {jQuery.Promise} Promise resolved with a value when the window is opened, or rejected
+ * if the window fails to open. When the promise is resolved successfully, the first argument of the
+ * value is a new promise, which is resolved when the window begins closing.
+ * @throws {Error} An error is thrown if the window is not attached to a window manager
+ */
+OO.ui.Window.prototype.open = function ( data ) {
+ if ( !this.manager ) {
+ throw new Error( 'Cannot open window, must be attached to a manager' );
+ }
+
+ return this.manager.openWindow( this, data );
+};
+
+/**
+ * Close the window.
+ *
+ * This method is a wrapper around a call to the window
+ * manager’s {@link OO.ui.WindowManager#closeWindow closeWindow} method,
+ * which returns a closing promise resolved when the window is done closing.
+ *
+ * The window's #getHoldProcess and #getTeardownProcess methods are called during the closing
+ * phase of the window’s lifecycle and can be used to specify closing behavior each time
+ * the window closes.
+ *
+ * @param {Object} [data] Window closing data
+ * @return {jQuery.Promise} Promise resolved when window is closed
+ * @throws {Error} An error is thrown if the window is not attached to a window manager
+ */
+OO.ui.Window.prototype.close = function ( data ) {
+ if ( !this.manager ) {
+ throw new Error( 'Cannot close window, must be attached to a manager' );
+ }
+
+ return this.manager.closeWindow( this, data );
+};
+
+/**
+ * Setup window.
+ *
+ * This is called by OO.ui.WindowManager during window opening, and should not be called directly
+ * by other systems.
+ *
+ * @param {Object} [data] Window opening data
+ * @return {jQuery.Promise} Promise resolved when window is setup
+ */
+OO.ui.Window.prototype.setup = function ( data ) {
+ var win = this;
+
+ this.toggle( true );
+
+ this.focusTrapHandler = OO.ui.bind( this.onFocusTrapFocused, this );
+ this.$focusTraps.on( 'focus', this.focusTrapHandler );
+
+ return this.getSetupProcess( data ).execute().then( function () {
+ // Force redraw by asking the browser to measure the elements' widths
+ win.$element.addClass( 'oo-ui-window-active oo-ui-window-setup' ).width();
+ win.$content.addClass( 'oo-ui-window-content-setup' ).width();
+ } );
+};
+
+/**
+ * Ready window.
+ *
+ * This is called by OO.ui.WindowManager during window opening, and should not be called directly
+ * by other systems.
+ *
+ * @param {Object} [data] Window opening data
+ * @return {jQuery.Promise} Promise resolved when window is ready
+ */
+OO.ui.Window.prototype.ready = function ( data ) {
+ var win = this;
+
+ this.$content.focus();
+ return this.getReadyProcess( data ).execute().then( function () {
+ // Force redraw by asking the browser to measure the elements' widths
+ win.$element.addClass( 'oo-ui-window-ready' ).width();
+ win.$content.addClass( 'oo-ui-window-content-ready' ).width();
+ } );
+};
+
+/**
+ * Hold window.
+ *
+ * This is called by OO.ui.WindowManager during window closing, and should not be called directly
+ * by other systems.
+ *
+ * @param {Object} [data] Window closing data
+ * @return {jQuery.Promise} Promise resolved when window is held
+ */
+OO.ui.Window.prototype.hold = function ( data ) {
+ var win = this;
+
+ return this.getHoldProcess( data ).execute().then( function () {
+ // Get the focused element within the window's content
+ var $focus = win.$content.find( OO.ui.Element.static.getDocument( win.$content ).activeElement );
+
+ // Blur the focused element
+ if ( $focus.length ) {
+ $focus[ 0 ].blur();
+ }
+
+ // Force redraw by asking the browser to measure the elements' widths
+ win.$element.removeClass( 'oo-ui-window-ready' ).width();
+ win.$content.removeClass( 'oo-ui-window-content-ready' ).width();
+ } );
+};
+
+/**
+ * Teardown window.
+ *
+ * This is called by OO.ui.WindowManager during window closing, and should not be called directly
+ * by other systems.
+ *
+ * @param {Object} [data] Window closing data
+ * @return {jQuery.Promise} Promise resolved when window is torn down
+ */
+OO.ui.Window.prototype.teardown = function ( data ) {
+ var win = this;
+
+ return this.getTeardownProcess( data ).execute().then( function () {
+ // Force redraw by asking the browser to measure the elements' widths
+ win.$element.removeClass( 'oo-ui-window-active oo-ui-window-setup' ).width();
+ win.$content.removeClass( 'oo-ui-window-content-setup' ).width();
+ win.$focusTraps.off( 'focus', win.focusTrapHandler );
+ win.toggle( false );
+ } );
+};
+
+/**
+ * The Dialog class serves as the base class for the other types of dialogs.
+ * Unless extended to include controls, the rendered dialog box is a simple window
+ * that users can close by hitting the ‘Esc’ key. Dialog windows are used with OO.ui.WindowManager,
+ * which opens, closes, and controls the presentation of the window. See the
+ * [OOjs UI documentation on MediaWiki] [1] for more information.
+ *
+ * @example
+ * // A simple dialog window.
+ * function MyDialog( config ) {
+ * MyDialog.parent.call( this, config );
+ * }
+ * OO.inheritClass( MyDialog, OO.ui.Dialog );
+ * MyDialog.static.name = 'myDialog';
+ * MyDialog.prototype.initialize = function () {
+ * MyDialog.parent.prototype.initialize.call( this );
+ * this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );
+ * this.content.$element.append( '<p>A simple dialog window. Press \'Esc\' to close.</p>' );
+ * this.$body.append( this.content.$element );
+ * };
+ * MyDialog.prototype.getBodyHeight = function () {
+ * return this.content.$element.outerHeight( true );
+ * };
+ * var myDialog = new MyDialog( {
+ * size: 'medium'
+ * } );
+ * // Create and append a window manager, which opens and closes the window.
+ * var windowManager = new OO.ui.WindowManager();
+ * $( 'body' ).append( windowManager.$element );
+ * windowManager.addWindows( [ myDialog ] );
+ * // Open the window!
+ * windowManager.openWindow( myDialog );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Dialogs
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Window
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.Dialog = function OoUiDialog( config ) {
+ // Parent constructor
+ OO.ui.Dialog.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.PendingElement.call( this );
+
+ // Properties
+ this.actions = new OO.ui.ActionSet();
+ this.attachedActions = [];
+ this.currentAction = null;
+ this.onDialogKeyDownHandler = this.onDialogKeyDown.bind( this );
+
+ // Events
+ this.actions.connect( this, {
+ click: 'onActionClick',
+ change: 'onActionsChange'
+ } );
+
+ // Initialization
+ this.$element
+ .addClass( 'oo-ui-dialog' )
+ .attr( 'role', 'dialog' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.Dialog, OO.ui.Window );
+OO.mixinClass( OO.ui.Dialog, OO.ui.mixin.PendingElement );
+
+/* Static Properties */
+
+/**
+ * Symbolic name of dialog.
+ *
+ * The dialog class must have a symbolic name in order to be registered with OO.Factory.
+ * Please see the [OOjs UI documentation on MediaWiki] [3] for more information.
+ *
+ * [3]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Window_managers
+ *
+ * @abstract
+ * @static
+ * @inheritable
+ * @property {string}
+ */
+OO.ui.Dialog.static.name = '';
+
+/**
+ * The dialog title.
+ *
+ * The title can be specified as a plaintext string, a {@link OO.ui.mixin.LabelElement Label} node, or a function
+ * that will produce a Label node or string. The title can also be specified with data passed to the
+ * constructor (see #getSetupProcess). In this case, the static value will be overridden.
+ *
+ * @abstract
+ * @static
+ * @inheritable
+ * @property {jQuery|string|Function}
+ */
+OO.ui.Dialog.static.title = '';
+
+/**
+ * An array of configured {@link OO.ui.ActionWidget action widgets}.
+ *
+ * Actions can also be specified with data passed to the constructor (see #getSetupProcess). In this case, the static
+ * value will be overridden.
+ *
+ * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs#Action_sets
+ *
+ * @static
+ * @inheritable
+ * @property {Object[]}
+ */
+OO.ui.Dialog.static.actions = [];
+
+/**
+ * Close the dialog when the 'Esc' key is pressed.
+ *
+ * @static
+ * @abstract
+ * @inheritable
+ * @property {boolean}
+ */
+OO.ui.Dialog.static.escapable = true;
+
+/* Methods */
+
+/**
+ * Handle frame document key down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key down event
+ */
+OO.ui.Dialog.prototype.onDialogKeyDown = function ( e ) {
+ var actions;
+ if ( e.which === OO.ui.Keys.ESCAPE && this.constructor.static.escapable ) {
+ this.executeAction( '' );
+ e.preventDefault();
+ e.stopPropagation();
+ } else if ( e.which === OO.ui.Keys.ENTER && ( e.ctrlKey || e.metaKey ) ) {
+ actions = this.actions.get( { flags: 'primary', visible: true, disabled: false } );
+ if ( actions.length > 0 ) {
+ this.executeAction( actions[ 0 ].getAction() );
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }
+};
+
+/**
+ * Handle action click events.
+ *
+ * @private
+ * @param {OO.ui.ActionWidget} action Action that was clicked
+ */
+OO.ui.Dialog.prototype.onActionClick = function ( action ) {
+ if ( !this.isPending() ) {
+ this.executeAction( action.getAction() );
+ }
+};
+
+/**
+ * Handle actions change event.
+ *
+ * @private
+ */
+OO.ui.Dialog.prototype.onActionsChange = function () {
+ this.detachActions();
+ if ( !this.isClosing() ) {
+ this.attachActions();
+ }
+};
+
+/**
+ * Get the set of actions used by the dialog.
+ *
+ * @return {OO.ui.ActionSet}
+ */
+OO.ui.Dialog.prototype.getActions = function () {
+ return this.actions;
+};
+
+/**
+ * Get a process for taking action.
+ *
+ * When you override this method, you can create a new OO.ui.Process and return it, or add additional
+ * accept steps to the process the parent method provides using the {@link OO.ui.Process#first 'first'}
+ * and {@link OO.ui.Process#next 'next'} methods of OO.ui.Process.
+ *
+ * @param {string} [action] Symbolic name of action
+ * @return {OO.ui.Process} Action process
+ */
+OO.ui.Dialog.prototype.getActionProcess = function ( action ) {
+ return new OO.ui.Process()
+ .next( function () {
+ if ( !action ) {
+ // An empty action always closes the dialog without data, which should always be
+ // safe and make no changes
+ this.close();
+ }
+ }, this );
+};
+
+/**
+ * @inheritdoc
+ *
+ * @param {Object} [data] Dialog opening data
+ * @param {jQuery|string|Function|null} [data.title] Dialog title, omit to use
+ * the {@link #static-title static title}
+ * @param {Object[]} [data.actions] List of configuration options for each
+ * {@link OO.ui.ActionWidget action widget}, omit to use {@link #static-actions static actions}.
+ */
+OO.ui.Dialog.prototype.getSetupProcess = function ( data ) {
+ data = data || {};
+
+ // Parent method
+ return OO.ui.Dialog.parent.prototype.getSetupProcess.call( this, data )
+ .next( function () {
+ var config = this.constructor.static,
+ actions = data.actions !== undefined ? data.actions : config.actions,
+ title = data.title !== undefined ? data.title : config.title;
+
+ this.title.setLabel( title ).setTitle( title );
+ this.actions.add( this.getActionWidgets( actions ) );
+
+ this.$element.on( 'keydown', this.onDialogKeyDownHandler );
+ }, this );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.Dialog.prototype.getTeardownProcess = function ( data ) {
+ // Parent method
+ return OO.ui.Dialog.parent.prototype.getTeardownProcess.call( this, data )
+ .first( function () {
+ this.$element.off( 'keydown', this.onDialogKeyDownHandler );
+
+ this.actions.clear();
+ this.currentAction = null;
+ }, this );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.Dialog.prototype.initialize = function () {
+ // Parent method
+ OO.ui.Dialog.parent.prototype.initialize.call( this );
+
+ // Properties
+ this.title = new OO.ui.LabelWidget();
+
+ // Initialization
+ this.$content.addClass( 'oo-ui-dialog-content' );
+ this.$element.attr( 'aria-labelledby', this.title.getElementId() );
+ this.setPendingElement( this.$head );
+};
+
+/**
+ * Get action widgets from a list of configs
+ *
+ * @param {Object[]} actions Action widget configs
+ * @return {OO.ui.ActionWidget[]} Action widgets
+ */
+OO.ui.Dialog.prototype.getActionWidgets = function ( actions ) {
+ var i, len, widgets = [];
+ for ( i = 0, len = actions.length; i < len; i++ ) {
+ widgets.push(
+ new OO.ui.ActionWidget( actions[ i ] )
+ );
+ }
+ return widgets;
+};
+
+/**
+ * Attach action actions.
+ *
+ * @protected
+ */
+OO.ui.Dialog.prototype.attachActions = function () {
+ // Remember the list of potentially attached actions
+ this.attachedActions = this.actions.get();
+};
+
+/**
+ * Detach action actions.
+ *
+ * @protected
+ * @chainable
+ */
+OO.ui.Dialog.prototype.detachActions = function () {
+ var i, len;
+
+ // Detach all actions that may have been previously attached
+ for ( i = 0, len = this.attachedActions.length; i < len; i++ ) {
+ this.attachedActions[ i ].$element.detach();
+ }
+ this.attachedActions = [];
+};
+
+/**
+ * Execute an action.
+ *
+ * @param {string} action Symbolic name of action to execute
+ * @return {jQuery.Promise} Promise resolved when action completes, rejected if it fails
+ */
+OO.ui.Dialog.prototype.executeAction = function ( action ) {
+ this.pushPending();
+ this.currentAction = action;
+ return this.getActionProcess( action ).execute()
+ .always( this.popPending.bind( this ) );
+};
+
+/**
+ * MessageDialogs display a confirmation or alert message. By default, the rendered dialog box
+ * consists of a header that contains the dialog title, a body with the message, and a footer that
+ * contains any {@link OO.ui.ActionWidget action widgets}. The MessageDialog class is the only type
+ * of {@link OO.ui.Dialog dialog} that is usually instantiated directly.
+ *
+ * There are two basic types of message dialogs, confirmation and alert:
+ *
+ * - **confirmation**: the dialog title describes what a progressive action will do and the message provides
+ * more details about the consequences.
+ * - **alert**: the dialog title describes which event occurred and the message provides more information
+ * about why the event occurred.
+ *
+ * The MessageDialog class specifies two actions: ‘accept’, the primary
+ * action (e.g., ‘ok’) and ‘reject,’ the safe action (e.g., ‘cancel’). Both will close the window,
+ * passing along the selected action.
+ *
+ * For more information and examples, please see the [OOjs UI documentation on MediaWiki][1].
+ *
+ * @example
+ * // Example: Creating and opening a message dialog window.
+ * var messageDialog = new OO.ui.MessageDialog();
+ *
+ * // Create and append a window manager.
+ * var windowManager = new OO.ui.WindowManager();
+ * $( 'body' ).append( windowManager.$element );
+ * windowManager.addWindows( [ messageDialog ] );
+ * // Open the window.
+ * windowManager.openWindow( messageDialog, {
+ * title: 'Basic message dialog',
+ * message: 'This is the message'
+ * } );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Message_Dialogs
+ *
+ * @class
+ * @extends OO.ui.Dialog
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.MessageDialog = function OoUiMessageDialog( config ) {
+ // Parent constructor
+ OO.ui.MessageDialog.parent.call( this, config );
+
+ // Properties
+ this.verticalActionLayout = null;
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-messageDialog' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.MessageDialog, OO.ui.Dialog );
+
+/* Static Properties */
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.static.name = 'message';
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.static.size = 'small';
+
+/**
+ * Dialog title.
+ *
+ * The title of a confirmation dialog describes what a progressive action will do. The
+ * title of an alert dialog describes which event occurred.
+ *
+ * @static
+ * @inheritable
+ * @property {jQuery|string|Function|null}
+ */
+OO.ui.MessageDialog.static.title = null;
+
+/**
+ * The message displayed in the dialog body.
+ *
+ * A confirmation message describes the consequences of a progressive action. An alert
+ * message describes why an event occurred.
+ *
+ * @static
+ * @inheritable
+ * @property {jQuery|string|Function|null}
+ */
+OO.ui.MessageDialog.static.message = null;
+
+/**
+ * @static
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.static.actions = [
+ // Note that OO.ui.alert() and OO.ui.confirm() rely on these.
+ { action: 'accept', label: OO.ui.deferMsg( 'ooui-dialog-message-accept' ), flags: 'primary' },
+ { action: 'reject', label: OO.ui.deferMsg( 'ooui-dialog-message-reject' ), flags: 'safe' }
+];
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.prototype.setManager = function ( manager ) {
+ OO.ui.MessageDialog.parent.prototype.setManager.call( this, manager );
+
+ // Events
+ this.manager.connect( this, {
+ resize: 'onResize'
+ } );
+
+ return this;
+};
+
+/**
+ * Handle window resized events.
+ *
+ * @private
+ */
+OO.ui.MessageDialog.prototype.onResize = function () {
+ var dialog = this;
+ dialog.fitActions();
+ // Wait for CSS transition to finish and do it again :(
+ setTimeout( function () {
+ dialog.fitActions();
+ }, 300 );
+};
+
+/**
+ * Toggle action layout between vertical and horizontal.
+ *
+ * @private
+ * @param {boolean} [value] Layout actions vertically, omit to toggle
+ * @chainable
+ */
+OO.ui.MessageDialog.prototype.toggleVerticalActionLayout = function ( value ) {
+ value = value === undefined ? !this.verticalActionLayout : !!value;
+
+ if ( value !== this.verticalActionLayout ) {
+ this.verticalActionLayout = value;
+ this.$actions
+ .toggleClass( 'oo-ui-messageDialog-actions-vertical', value )
+ .toggleClass( 'oo-ui-messageDialog-actions-horizontal', !value );
+ }
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.prototype.getActionProcess = function ( action ) {
+ if ( action ) {
+ return new OO.ui.Process( function () {
+ this.close( { action: action } );
+ }, this );
+ }
+ return OO.ui.MessageDialog.parent.prototype.getActionProcess.call( this, action );
+};
+
+/**
+ * @inheritdoc
+ *
+ * @param {Object} [data] Dialog opening data
+ * @param {jQuery|string|Function|null} [data.title] Description of the action being confirmed
+ * @param {jQuery|string|Function|null} [data.message] Description of the action's consequence
+ * @param {string} [data.size] Symbolic name of the dialog size, see OO.ui.Window
+ * @param {Object[]} [data.actions] List of OO.ui.ActionOptionWidget configuration options for each
+ * action item
+ */
+OO.ui.MessageDialog.prototype.getSetupProcess = function ( data ) {
+ data = data || {};
+
+ // Parent method
+ return OO.ui.MessageDialog.parent.prototype.getSetupProcess.call( this, data )
+ .next( function () {
+ this.title.setLabel(
+ data.title !== undefined ? data.title : this.constructor.static.title
+ );
+ this.message.setLabel(
+ data.message !== undefined ? data.message : this.constructor.static.message
+ );
+ this.size = data.size !== undefined ? data.size : this.constructor.static.size;
+ }, this );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.prototype.getReadyProcess = function ( data ) {
+ data = data || {};
+
+ // Parent method
+ return OO.ui.MessageDialog.parent.prototype.getReadyProcess.call( this, data )
+ .next( function () {
+ // Focus the primary action button
+ var actions = this.actions.get();
+ actions = actions.filter( function ( action ) {
+ return action.getFlags().indexOf( 'primary' ) > -1;
+ } );
+ if ( actions.length > 0 ) {
+ actions[ 0 ].focus();
+ }
+ }, this );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.prototype.getBodyHeight = function () {
+ var bodyHeight, oldOverflow,
+ $scrollable = this.container.$element;
+
+ oldOverflow = $scrollable[ 0 ].style.overflow;
+ $scrollable[ 0 ].style.overflow = 'hidden';
+
+ OO.ui.Element.static.reconsiderScrollbars( $scrollable[ 0 ] );
+
+ bodyHeight = this.text.$element.outerHeight( true );
+ $scrollable[ 0 ].style.overflow = oldOverflow;
+
+ return bodyHeight;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.prototype.setDimensions = function ( dim ) {
+ var $scrollable = this.container.$element;
+ OO.ui.MessageDialog.parent.prototype.setDimensions.call( this, dim );
+
+ // Twiddle the overflow property, otherwise an unnecessary scrollbar will be produced.
+ // Need to do it after transition completes (250ms), add 50ms just in case.
+ setTimeout( function () {
+ var oldOverflow = $scrollable[ 0 ].style.overflow,
+ activeElement = document.activeElement;
+
+ $scrollable[ 0 ].style.overflow = 'hidden';
+
+ OO.ui.Element.static.reconsiderScrollbars( $scrollable[ 0 ] );
+
+ // Check reconsiderScrollbars didn't destroy our focus, as we
+ // are doing this after the ready process.
+ if ( activeElement && activeElement !== document.activeElement && activeElement.focus ) {
+ activeElement.focus();
+ }
+
+ $scrollable[ 0 ].style.overflow = oldOverflow;
+ }, 300 );
+
+ return this;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.prototype.initialize = function () {
+ // Parent method
+ OO.ui.MessageDialog.parent.prototype.initialize.call( this );
+
+ // Properties
+ this.$actions = $( '<div>' );
+ this.container = new OO.ui.PanelLayout( {
+ scrollable: true, classes: [ 'oo-ui-messageDialog-container' ]
+ } );
+ this.text = new OO.ui.PanelLayout( {
+ padded: true, expanded: false, classes: [ 'oo-ui-messageDialog-text' ]
+ } );
+ this.message = new OO.ui.LabelWidget( {
+ classes: [ 'oo-ui-messageDialog-message' ]
+ } );
+
+ // Initialization
+ this.title.$element.addClass( 'oo-ui-messageDialog-title' );
+ this.$content.addClass( 'oo-ui-messageDialog-content' );
+ this.container.$element.append( this.text.$element );
+ this.text.$element.append( this.title.$element, this.message.$element );
+ this.$body.append( this.container.$element );
+ this.$actions.addClass( 'oo-ui-messageDialog-actions' );
+ this.$foot.append( this.$actions );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.MessageDialog.prototype.attachActions = function () {
+ var i, len, other, special, others;
+
+ // Parent method
+ OO.ui.MessageDialog.parent.prototype.attachActions.call( this );
+
+ special = this.actions.getSpecial();
+ others = this.actions.getOthers();
+
+ if ( special.safe ) {
+ this.$actions.append( special.safe.$element );
+ special.safe.toggleFramed( false );
+ }
+ if ( others.length ) {
+ for ( i = 0, len = others.length; i < len; i++ ) {
+ other = others[ i ];
+ this.$actions.append( other.$element );
+ other.toggleFramed( false );
+ }
+ }
+ if ( special.primary ) {
+ this.$actions.append( special.primary.$element );
+ special.primary.toggleFramed( false );
+ }
+
+ if ( !this.isOpening() ) {
+ // If the dialog is currently opening, this will be called automatically soon.
+ // This also calls #fitActions.
+ this.updateSize();
+ }
+};
+
+/**
+ * Fit action actions into columns or rows.
+ *
+ * Columns will be used if all labels can fit without overflow, otherwise rows will be used.
+ *
+ * @private
+ */
+OO.ui.MessageDialog.prototype.fitActions = function () {
+ var i, len, action,
+ previous = this.verticalActionLayout,
+ actions = this.actions.get();
+
+ // Detect clipping
+ this.toggleVerticalActionLayout( false );
+ for ( i = 0, len = actions.length; i < len; i++ ) {
+ action = actions[ i ];
+ if ( action.$element.innerWidth() < action.$label.outerWidth( true ) ) {
+ this.toggleVerticalActionLayout( true );
+ break;
+ }
+ }
+
+ // Move the body out of the way of the foot
+ this.$body.css( 'bottom', this.$foot.outerHeight( true ) );
+
+ if ( this.verticalActionLayout !== previous ) {
+ // We changed the layout, window height might need to be updated.
+ this.updateSize();
+ }
+};
+
+/**
+ * ProcessDialog windows encapsulate a {@link OO.ui.Process process} and all of the code necessary
+ * to complete it. If the process terminates with an error, a customizable {@link OO.ui.Error error
+ * interface} alerts users to the trouble, permitting the user to dismiss the error and try again when
+ * relevant. The ProcessDialog class is always extended and customized with the actions and content
+ * required for each process.
+ *
+ * The process dialog box consists of a header that visually represents the ‘working’ state of long
+ * processes with an animation. The header contains the dialog title as well as
+ * two {@link OO.ui.ActionWidget action widgets}: a ‘safe’ action on the left (e.g., ‘Cancel’) and
+ * a ‘primary’ action on the right (e.g., ‘Done’).
+ *
+ * Like other windows, the process dialog is managed by a {@link OO.ui.WindowManager window manager}.
+ * Please see the [OOjs UI documentation on MediaWiki][1] for more information and examples.
+ *
+ * @example
+ * // Example: Creating and opening a process dialog window.
+ * function MyProcessDialog( config ) {
+ * MyProcessDialog.parent.call( this, config );
+ * }
+ * OO.inheritClass( MyProcessDialog, OO.ui.ProcessDialog );
+ *
+ * MyProcessDialog.static.name = 'myProcessDialog';
+ * MyProcessDialog.static.title = 'Process dialog';
+ * MyProcessDialog.static.actions = [
+ * { action: 'save', label: 'Done', flags: 'primary' },
+ * { label: 'Cancel', flags: 'safe' }
+ * ];
+ *
+ * MyProcessDialog.prototype.initialize = function () {
+ * MyProcessDialog.parent.prototype.initialize.apply( this, arguments );
+ * this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );
+ * this.content.$element.append( '<p>This is a process dialog window. The header contains the title and two buttons: \'Cancel\' (a safe action) on the left and \'Done\' (a primary action) on the right.</p>' );
+ * this.$body.append( this.content.$element );
+ * };
+ * MyProcessDialog.prototype.getActionProcess = function ( action ) {
+ * var dialog = this;
+ * if ( action ) {
+ * return new OO.ui.Process( function () {
+ * dialog.close( { action: action } );
+ * } );
+ * }
+ * return MyProcessDialog.parent.prototype.getActionProcess.call( this, action );
+ * };
+ *
+ * var windowManager = new OO.ui.WindowManager();
+ * $( 'body' ).append( windowManager.$element );
+ *
+ * var dialog = new MyProcessDialog();
+ * windowManager.addWindows( [ dialog ] );
+ * windowManager.openWindow( dialog );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs
+ *
+ * @abstract
+ * @class
+ * @extends OO.ui.Dialog
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+OO.ui.ProcessDialog = function OoUiProcessDialog( config ) {
+ // Parent constructor
+ OO.ui.ProcessDialog.parent.call( this, config );
+
+ // Properties
+ this.fitOnOpen = false;
+
+ // Initialization
+ this.$element.addClass( 'oo-ui-processDialog' );
+};
+
+/* Setup */
+
+OO.inheritClass( OO.ui.ProcessDialog, OO.ui.Dialog );
+
+/* Methods */
+
+/**
+ * Handle dismiss button click events.
+ *
+ * Hides errors.
+ *
+ * @private
+ */
+OO.ui.ProcessDialog.prototype.onDismissErrorButtonClick = function () {
+ this.hideErrors();
+};
+
+/**
+ * Handle retry button click events.
+ *
+ * Hides errors and then tries again.
+ *
+ * @private
+ */
+OO.ui.ProcessDialog.prototype.onRetryButtonClick = function () {
+ this.hideErrors();
+ this.executeAction( this.currentAction );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ProcessDialog.prototype.initialize = function () {
+ // Parent method
+ OO.ui.ProcessDialog.parent.prototype.initialize.call( this );
+
+ // Properties
+ this.$navigation = $( '<div>' );
+ this.$location = $( '<div>' );
+ this.$safeActions = $( '<div>' );
+ this.$primaryActions = $( '<div>' );
+ this.$otherActions = $( '<div>' );
+ this.dismissButton = new OO.ui.ButtonWidget( {
+ label: OO.ui.msg( 'ooui-dialog-process-dismiss' )
+ } );
+ this.retryButton = new OO.ui.ButtonWidget();
+ this.$errors = $( '<div>' );
+ this.$errorsTitle = $( '<div>' );
+
+ // Events
+ this.dismissButton.connect( this, { click: 'onDismissErrorButtonClick' } );
+ this.retryButton.connect( this, { click: 'onRetryButtonClick' } );
+
+ // Initialization
+ this.title.$element.addClass( 'oo-ui-processDialog-title' );
+ this.$location
+ .append( this.title.$element )
+ .addClass( 'oo-ui-processDialog-location' );
+ this.$safeActions.addClass( 'oo-ui-processDialog-actions-safe' );
+ this.$primaryActions.addClass( 'oo-ui-processDialog-actions-primary' );
+ this.$otherActions.addClass( 'oo-ui-processDialog-actions-other' );
+ this.$errorsTitle
+ .addClass( 'oo-ui-processDialog-errors-title' )
+ .text( OO.ui.msg( 'ooui-dialog-process-error' ) );
+ this.$errors
+ .addClass( 'oo-ui-processDialog-errors oo-ui-element-hidden' )
+ .append( this.$errorsTitle, this.dismissButton.$element, this.retryButton.$element );
+ this.$content
+ .addClass( 'oo-ui-processDialog-content' )
+ .append( this.$errors );
+ this.$navigation
+ .addClass( 'oo-ui-processDialog-navigation' )
+ // Note: Order of appends below is important. These are in the order
+ // we want tab to go through them. Display-order is handled entirely
+ // by CSS absolute-positioning. As such, primary actions like "done"
+ // should go first.
+ .append( this.$primaryActions, this.$location, this.$safeActions );
+ this.$head.append( this.$navigation );
+ this.$foot.append( this.$otherActions );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ProcessDialog.prototype.getActionWidgets = function ( actions ) {
+ var i, len, config,
+ isMobile = OO.ui.isMobile(),
+ widgets = [];
+
+ for ( i = 0, len = actions.length; i < len; i++ ) {
+ config = $.extend( { framed: !OO.ui.isMobile() }, actions[ i ] );
+ if ( isMobile &&
+ ( config.flags === 'back' || ( Array.isArray( config.flags ) && config.flags.indexOf( 'back' ) !== -1 ) )
+ ) {
+ $.extend( config, {
+ icon: 'previous',
+ label: ''
+ } );
+ }
+ widgets.push(
+ new OO.ui.ActionWidget( config )
+ );
+ }
+ return widgets;
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ProcessDialog.prototype.attachActions = function () {
+ var i, len, other, special, others;
+
+ // Parent method
+ OO.ui.ProcessDialog.parent.prototype.attachActions.call( this );
+
+ special = this.actions.getSpecial();
+ others = this.actions.getOthers();
+ if ( special.primary ) {
+ this.$primaryActions.append( special.primary.$element );
+ }
+ for ( i = 0, len = others.length; i < len; i++ ) {
+ other = others[ i ];
+ this.$otherActions.append( other.$element );
+ }
+ if ( special.safe ) {
+ this.$safeActions.append( special.safe.$element );
+ }
+
+ this.fitLabel();
+ this.$body.css( 'bottom', this.$foot.outerHeight( true ) );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ProcessDialog.prototype.executeAction = function ( action ) {
+ var process = this;
+ return OO.ui.ProcessDialog.parent.prototype.executeAction.call( this, action )
+ .fail( function ( errors ) {
+ process.showErrors( errors || [] );
+ } );
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ProcessDialog.prototype.setDimensions = function () {
+ // Parent method
+ OO.ui.ProcessDialog.parent.prototype.setDimensions.apply( this, arguments );
+
+ this.fitLabel();
+};
+
+/**
+ * Fit label between actions.
+ *
+ * @private
+ * @chainable
+ */
+OO.ui.ProcessDialog.prototype.fitLabel = function () {
+ var safeWidth, primaryWidth, biggerWidth, labelWidth, navigationWidth, leftWidth, rightWidth,
+ size = this.getSizeProperties();
+
+ if ( typeof size.width !== 'number' ) {
+ if ( this.isOpened() ) {
+ navigationWidth = this.$head.width() - 20;
+ } else if ( this.isOpening() ) {
+ if ( !this.fitOnOpen ) {
+ // Size is relative and the dialog isn't open yet, so wait.
+ // FIXME: This should ideally be handled by setup somehow.
+ this.manager.lifecycle.opened.done( this.fitLabel.bind( this ) );
+ this.fitOnOpen = true;
+ }
+ return;
+ } else {
+ return;
+ }
+ } else {
+ navigationWidth = size.width - 20;
+ }
+
+ safeWidth = this.$safeActions.is( ':visible' ) ? this.$safeActions.width() : 0;
+ primaryWidth = this.$primaryActions.is( ':visible' ) ? this.$primaryActions.width() : 0;
+ biggerWidth = Math.max( safeWidth, primaryWidth );
+
+ labelWidth = this.title.$element.width();
+
+ if ( 2 * biggerWidth + labelWidth < navigationWidth ) {
+ // We have enough space to center the label
+ leftWidth = rightWidth = biggerWidth;
+ } else {
+ // Let's hope we at least have enough space not to overlap, because we can't wrap the label…
+ if ( this.getDir() === 'ltr' ) {
+ leftWidth = safeWidth;
+ rightWidth = primaryWidth;
+ } else {
+ leftWidth = primaryWidth;
+ rightWidth = safeWidth;
+ }
+ }
+
+ this.$location.css( { paddingLeft: leftWidth, paddingRight: rightWidth } );
+
+ return this;
+};
+
+/**
+ * Handle errors that occurred during accept or reject processes.
+ *
+ * @private
+ * @param {OO.ui.Error[]|OO.ui.Error} errors Errors to be handled
+ */
+OO.ui.ProcessDialog.prototype.showErrors = function ( errors ) {
+ var i, len, $item, actions,
+ items = [],
+ abilities = {},
+ recoverable = true,
+ warning = false;
+
+ if ( errors instanceof OO.ui.Error ) {
+ errors = [ errors ];
+ }
+
+ for ( i = 0, len = errors.length; i < len; i++ ) {
+ if ( !errors[ i ].isRecoverable() ) {
+ recoverable = false;
+ }
+ if ( errors[ i ].isWarning() ) {
+ warning = true;
+ }
+ $item = $( '<div>' )
+ .addClass( 'oo-ui-processDialog-error' )
+ .append( errors[ i ].getMessage() );
+ items.push( $item[ 0 ] );
+ }
+ this.$errorItems = $( items );
+ if ( recoverable ) {
+ abilities[ this.currentAction ] = true;
+ // Copy the flags from the first matching action
+ actions = this.actions.get( { actions: this.currentAction } );
+ if ( actions.length ) {
+ this.retryButton.clearFlags().setFlags( actions[ 0 ].getFlags() );
+ }
+ } else {
+ abilities[ this.currentAction ] = false;
+ this.actions.setAbilities( abilities );
+ }
+ if ( warning ) {
+ this.retryButton.setLabel( OO.ui.msg( 'ooui-dialog-process-continue' ) );
+ } else {
+ this.retryButton.setLabel( OO.ui.msg( 'ooui-dialog-process-retry' ) );
+ }
+ this.retryButton.toggle( recoverable );
+ this.$errorsTitle.after( this.$errorItems );
+ this.$errors.removeClass( 'oo-ui-element-hidden' ).scrollTop( 0 );
+};
+
+/**
+ * Hide errors.
+ *
+ * @private
+ */
+OO.ui.ProcessDialog.prototype.hideErrors = function () {
+ this.$errors.addClass( 'oo-ui-element-hidden' );
+ if ( this.$errorItems ) {
+ this.$errorItems.remove();
+ this.$errorItems = null;
+ }
+};
+
+/**
+ * @inheritdoc
+ */
+OO.ui.ProcessDialog.prototype.getTeardownProcess = function ( data ) {
+ // Parent method
+ return OO.ui.ProcessDialog.parent.prototype.getTeardownProcess.call( this, data )
+ .first( function () {
+ // Make sure to hide errors
+ this.hideErrors();
+ this.fitOnOpen = false;
+ }, this );
+};
+
+/**
+ * @class OO.ui
+ */
+
+/**
+ * Lazy-initialize and return a global OO.ui.WindowManager instance, used by OO.ui.alert and
+ * OO.ui.confirm.
+ *
+ * @private
+ * @return {OO.ui.WindowManager}
+ */
+OO.ui.getWindowManager = function () {
+ if ( !OO.ui.windowManager ) {
+ OO.ui.windowManager = new OO.ui.WindowManager();
+ $( 'body' ).append( OO.ui.windowManager.$element );
+ OO.ui.windowManager.addWindows( [ new OO.ui.MessageDialog() ] );
+ }
+ return OO.ui.windowManager;
+};
+
+/**
+ * Display a quick modal alert dialog, using a OO.ui.MessageDialog. While the dialog is open, the
+ * rest of the page will be dimmed out and the user won't be able to interact with it. The dialog
+ * has only one action button, labelled "OK", clicking it will simply close the dialog.
+ *
+ * A window manager is created automatically when this function is called for the first time.
+ *
+ * @example
+ * OO.ui.alert( 'Something happened!' ).done( function () {
+ * console.log( 'User closed the dialog.' );
+ * } );
+ *
+ * OO.ui.alert( 'Something larger happened!', { size: 'large' } );
+ *
+ * @param {jQuery|string} text Message text to display
+ * @param {Object} [options] Additional options, see OO.ui.MessageDialog#getSetupProcess
+ * @return {jQuery.Promise} Promise resolved when the user closes the dialog
+ */
+OO.ui.alert = function ( text, options ) {
+ return OO.ui.getWindowManager().openWindow( 'message', $.extend( {
+ message: text,
+ actions: [ OO.ui.MessageDialog.static.actions[ 0 ] ]
+ }, options ) ).closed.then( function () {
+ return undefined;
+ } );
+};
+
+/**
+ * Display a quick modal confirmation dialog, using a OO.ui.MessageDialog. While the dialog is open,
+ * the rest of the page will be dimmed out and the user won't be able to interact with it. The
+ * dialog has two action buttons, one to confirm an operation (labelled "OK") and one to cancel it
+ * (labelled "Cancel").
+ *
+ * A window manager is created automatically when this function is called for the first time.
+ *
+ * @example
+ * OO.ui.confirm( 'Are you sure?' ).done( function ( confirmed ) {
+ * if ( confirmed ) {
+ * console.log( 'User clicked "OK"!' );
+ * } else {
+ * console.log( 'User clicked "Cancel" or closed the dialog.' );
+ * }
+ * } );
+ *
+ * @param {jQuery|string} text Message text to display
+ * @param {Object} [options] Additional options, see OO.ui.MessageDialog#getSetupProcess
+ * @return {jQuery.Promise} Promise resolved when the user closes the dialog. If the user chose to
+ * confirm, the promise will resolve to boolean `true`; otherwise, it will resolve to boolean
+ * `false`.
+ */
+OO.ui.confirm = function ( text, options ) {
+ return OO.ui.getWindowManager().openWindow( 'message', $.extend( {
+ message: text
+ }, options ) ).closed.then( function ( data ) {
+ return !!( data && data.action === 'accept' );
+ } );
+};
+
+/**
+ * Display a quick modal prompt dialog, using a OO.ui.MessageDialog. While the dialog is open,
+ * the rest of the page will be dimmed out and the user won't be able to interact with it. The
+ * dialog has a text input widget and two action buttons, one to confirm an operation (labelled "OK")
+ * and one to cancel it (labelled "Cancel").
+ *
+ * A window manager is created automatically when this function is called for the first time.
+ *
+ * @example
+ * OO.ui.prompt( 'Choose a line to go to', { textInput: { placeholder: 'Line number' } } ).done( function ( result ) {
+ * if ( result !== null ) {
+ * console.log( 'User typed "' + result + '" then clicked "OK".' );
+ * } else {
+ * console.log( 'User clicked "Cancel" or closed the dialog.' );
+ * }
+ * } );
+ *
+ * @param {jQuery|string} text Message text to display
+ * @param {Object} [options] Additional options, see OO.ui.MessageDialog#getSetupProcess
+ * @param {Object} [options.textInput] Additional options for text input widget, see OO.ui.TextInputWidget
+ * @return {jQuery.Promise} Promise resolved when the user closes the dialog. If the user chose to
+ * confirm, the promise will resolve with the value of the text input widget; otherwise, it will
+ * resolve to `null`.
+ */
+OO.ui.prompt = function ( text, options ) {
+ var instance,
+ manager = OO.ui.getWindowManager(),
+ textInput = new OO.ui.TextInputWidget( ( options && options.textInput ) || {} ),
+ textField = new OO.ui.FieldLayout( textInput, {
+ align: 'top',
+ label: text
+ } );
+
+ instance = manager.openWindow( 'message', $.extend( {
+ message: textField.$element
+ }, options ) );
+
+ // TODO: This is a little hacky, and could be done by extending MessageDialog instead.
+ instance.opened.then( function () {
+ textInput.on( 'enter', function () {
+ manager.getCurrentWindow().close( { action: 'accept' } );
+ } );
+ textInput.focus();
+ } );
+
+ return instance.closed.then( function ( data ) {
+ return data && data.action === 'accept' ? textInput.getValue() : null;
+ } );
+};
+
+}( OO ) );
+
+//# sourceMappingURL=oojs-ui-windows.js.map \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/oojs-ui-windows.js.map b/www/wiki/resources/lib/oojs-ui/oojs-ui-windows.js.map
new file mode 100644
index 00000000..31ee8d3b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/oojs-ui-windows.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["../src/intro.js.txt","../src/widgets/ActionWidget.js","../src/ActionSet.js","../src/Error.js","../src/Process.js","../src/WindowInstance.js","../src/WindowManager.js","../src/Window.js","../src/Dialog.js","../src/dialogs/MessageDialog.js","../src/dialogs/ProcessDialog.js","../src/windows.js","../src/outro.js.txt"],"names":[],"mappings":"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","file":"oojs-ui-windows.js","sourcesContent":["( function ( OO ) {\n\n'use strict';\n","/**\n * An ActionWidget is a {@link OO.ui.ButtonWidget button widget} that executes an action.\n * Action widgets are used with OO.ui.ActionSet, which manages the behavior and availability\n * of the actions.\n *\n * Both actions and action sets are primarily used with {@link OO.ui.Dialog Dialogs}.\n * Please see the [OOjs UI documentation on MediaWiki] [1] for more information\n * and examples.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs#Action_sets\n *\n * @class\n * @extends OO.ui.ButtonWidget\n * @mixins OO.ui.mixin.PendingElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string} [action] Symbolic name of the action (e.g., ‘continue’ or ‘cancel’).\n * @cfg {string[]} [modes] Symbolic names of the modes (e.g., ‘edit’ or ‘read’) in which the action\n * should be made available. See the action set's {@link OO.ui.ActionSet#setMode setMode} method\n * for more information about setting modes.\n * @cfg {boolean} [framed=false] Render the action button with a frame\n */\nOO.ui.ActionWidget = function OoUiActionWidget( config ) {\n\t// Configuration initialization\n\tconfig = $.extend( { framed: false }, config );\n\n\t// Parent constructor\n\tOO.ui.ActionWidget.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.PendingElement.call( this, config );\n\n\t// Properties\n\tthis.action = config.action || '';\n\tthis.modes = config.modes || [];\n\tthis.width = 0;\n\tthis.height = 0;\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-actionWidget' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ActionWidget, OO.ui.ButtonWidget );\nOO.mixinClass( OO.ui.ActionWidget, OO.ui.mixin.PendingElement );\n\n/* Methods */\n\n/**\n * Check if the action is configured to be available in the specified `mode`.\n *\n * @param {string} mode Name of mode\n * @return {boolean} The action is configured with the mode\n */\nOO.ui.ActionWidget.prototype.hasMode = function ( mode ) {\n\treturn this.modes.indexOf( mode ) !== -1;\n};\n\n/**\n * Get the symbolic name of the action (e.g., ‘continue’ or ‘cancel’).\n *\n * @return {string}\n */\nOO.ui.ActionWidget.prototype.getAction = function () {\n\treturn this.action;\n};\n\n/**\n * Get the symbolic name of the mode or modes for which the action is configured to be available.\n *\n * The current mode is set with the action set's {@link OO.ui.ActionSet#setMode setMode} method.\n * Only actions that are configured to be avaiable in the current mode will be visible. All other actions\n * are hidden.\n *\n * @return {string[]}\n */\nOO.ui.ActionWidget.prototype.getModes = function () {\n\treturn this.modes.slice();\n};\n","/* eslint-disable no-unused-vars */\n/**\n * ActionSets manage the behavior of the {@link OO.ui.ActionWidget action widgets} that comprise them.\n * Actions can be made available for specific contexts (modes) and circumstances\n * (abilities). Action sets are primarily used with {@link OO.ui.Dialog Dialogs}.\n *\n * ActionSets contain two types of actions:\n *\n * - Special: Special actions are the first visible actions with special flags, such as 'safe' and 'primary', the default special flags. Additional special flags can be configured in subclasses with the static #specialFlags property.\n * - Other: Other actions include all non-special visible actions.\n *\n * Please see the [OOjs UI documentation on MediaWiki][1] for more information.\n *\n * @example\n * // Example: An action set used in a process dialog\n * function MyProcessDialog( config ) {\n * MyProcessDialog.parent.call( this, config );\n * }\n * OO.inheritClass( MyProcessDialog, OO.ui.ProcessDialog );\n * MyProcessDialog.static.title = 'An action set in a process dialog';\n * MyProcessDialog.static.name = 'myProcessDialog';\n * // An action set that uses modes ('edit' and 'help' mode, in this example).\n * MyProcessDialog.static.actions = [\n * { action: 'continue', modes: 'edit', label: 'Continue', flags: [ 'primary', 'constructive' ] },\n * { action: 'help', modes: 'edit', label: 'Help' },\n * { modes: 'edit', label: 'Cancel', flags: 'safe' },\n * { action: 'back', modes: 'help', label: 'Back', flags: 'safe' }\n * ];\n *\n * MyProcessDialog.prototype.initialize = function () {\n * MyProcessDialog.parent.prototype.initialize.apply( this, arguments );\n * this.panel1 = new OO.ui.PanelLayout( { padded: true, expanded: false } );\n * this.panel1.$element.append( '<p>This dialog uses an action set (continue, help, cancel, back) configured with modes. This is edit mode. Click \\'help\\' to see help mode.</p>' );\n * this.panel2 = new OO.ui.PanelLayout( { padded: true, expanded: false } );\n * this.panel2.$element.append( '<p>This is help mode. Only the \\'back\\' action widget is configured to be visible here. Click \\'back\\' to return to \\'edit\\' mode.</p>' );\n * this.stackLayout = new OO.ui.StackLayout( {\n * items: [ this.panel1, this.panel2 ]\n * } );\n * this.$body.append( this.stackLayout.$element );\n * };\n * MyProcessDialog.prototype.getSetupProcess = function ( data ) {\n * return MyProcessDialog.parent.prototype.getSetupProcess.call( this, data )\n * .next( function () {\n * this.actions.setMode( 'edit' );\n * }, this );\n * };\n * MyProcessDialog.prototype.getActionProcess = function ( action ) {\n * if ( action === 'help' ) {\n * this.actions.setMode( 'help' );\n * this.stackLayout.setItem( this.panel2 );\n * } else if ( action === 'back' ) {\n * this.actions.setMode( 'edit' );\n * this.stackLayout.setItem( this.panel1 );\n * } else if ( action === 'continue' ) {\n * var dialog = this;\n * return new OO.ui.Process( function () {\n * dialog.close();\n * } );\n * }\n * return MyProcessDialog.parent.prototype.getActionProcess.call( this, action );\n * };\n * MyProcessDialog.prototype.getBodyHeight = function () {\n * return this.panel1.$element.outerHeight( true );\n * };\n * var windowManager = new OO.ui.WindowManager();\n * $( 'body' ).append( windowManager.$element );\n * var dialog = new MyProcessDialog( {\n * size: 'medium'\n * } );\n * windowManager.addWindows( [ dialog ] );\n * windowManager.openWindow( dialog );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs#Action_sets\n *\n * @abstract\n * @class\n * @mixins OO.EventEmitter\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.ActionSet = function OoUiActionSet( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Mixin constructors\n\tOO.EventEmitter.call( this );\n\n\t// Properties\n\tthis.list = [];\n\tthis.categories = {\n\t\tactions: 'getAction',\n\t\tflags: 'getFlags',\n\t\tmodes: 'getModes'\n\t};\n\tthis.categorized = {};\n\tthis.special = {};\n\tthis.others = [];\n\tthis.organized = false;\n\tthis.changing = false;\n\tthis.changed = false;\n};\n/* eslint-enable no-unused-vars */\n\n/* Setup */\n\nOO.mixinClass( OO.ui.ActionSet, OO.EventEmitter );\n\n/* Static Properties */\n\n/**\n * Symbolic name of the flags used to identify special actions. Special actions are displayed in the\n * header of a {@link OO.ui.ProcessDialog process dialog}.\n * See the [OOjs UI documentation on MediaWiki][2] for more information and examples.\n *\n * [2]:https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs\n *\n * @abstract\n * @static\n * @inheritable\n * @property {string}\n */\nOO.ui.ActionSet.static.specialFlags = [ 'safe', 'primary' ];\n\n/* Events */\n\n/**\n * @event click\n *\n * A 'click' event is emitted when an action is clicked.\n *\n * @param {OO.ui.ActionWidget} action Action that was clicked\n */\n\n/**\n * @event add\n *\n * An 'add' event is emitted when actions are {@link #method-add added} to the action set.\n *\n * @param {OO.ui.ActionWidget[]} added Actions added\n */\n\n/**\n * @event remove\n *\n * A 'remove' event is emitted when actions are {@link #method-remove removed}\n * or {@link #clear cleared}.\n *\n * @param {OO.ui.ActionWidget[]} added Actions removed\n */\n\n/**\n * @event change\n *\n * A 'change' event is emitted when actions are {@link #method-add added}, {@link #clear cleared},\n * or {@link #method-remove removed} from the action set or when the {@link #setMode mode} is changed.\n *\n */\n\n/* Methods */\n\n/**\n * Handle action change events.\n *\n * @private\n * @fires change\n */\nOO.ui.ActionSet.prototype.onActionChange = function () {\n\tthis.organized = false;\n\tif ( this.changing ) {\n\t\tthis.changed = true;\n\t} else {\n\t\tthis.emit( 'change' );\n\t}\n};\n\n/**\n * Check if an action is one of the special actions.\n *\n * @param {OO.ui.ActionWidget} action Action to check\n * @return {boolean} Action is special\n */\nOO.ui.ActionSet.prototype.isSpecial = function ( action ) {\n\tvar flag;\n\n\tfor ( flag in this.special ) {\n\t\tif ( action === this.special[ flag ] ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n};\n\n/**\n * Get action widgets based on the specified filter: ‘actions’, ‘flags’, ‘modes’, ‘visible’,\n * or ‘disabled’.\n *\n * @param {Object} [filters] Filters to use, omit to get all actions\n * @param {string|string[]} [filters.actions] Actions that action widgets must have\n * @param {string|string[]} [filters.flags] Flags that action widgets must have (e.g., 'safe')\n * @param {string|string[]} [filters.modes] Modes that action widgets must have\n * @param {boolean} [filters.visible] Action widgets must be visible\n * @param {boolean} [filters.disabled] Action widgets must be disabled\n * @return {OO.ui.ActionWidget[]} Action widgets matching all criteria\n */\nOO.ui.ActionSet.prototype.get = function ( filters ) {\n\tvar i, len, list, category, actions, index, match, matches;\n\n\tif ( filters ) {\n\t\tthis.organize();\n\n\t\t// Collect category candidates\n\t\tmatches = [];\n\t\tfor ( category in this.categorized ) {\n\t\t\tlist = filters[ category ];\n\t\t\tif ( list ) {\n\t\t\t\tif ( !Array.isArray( list ) ) {\n\t\t\t\t\tlist = [ list ];\n\t\t\t\t}\n\t\t\t\tfor ( i = 0, len = list.length; i < len; i++ ) {\n\t\t\t\t\tactions = this.categorized[ category ][ list[ i ] ];\n\t\t\t\t\tif ( Array.isArray( actions ) ) {\n\t\t\t\t\t\tmatches.push.apply( matches, actions );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// Remove by boolean filters\n\t\tfor ( i = 0, len = matches.length; i < len; i++ ) {\n\t\t\tmatch = matches[ i ];\n\t\t\tif (\n\t\t\t\t( filters.visible !== undefined && match.isVisible() !== filters.visible ) ||\n\t\t\t\t( filters.disabled !== undefined && match.isDisabled() !== filters.disabled )\n\t\t\t) {\n\t\t\t\tmatches.splice( i, 1 );\n\t\t\t\tlen--;\n\t\t\t\ti--;\n\t\t\t}\n\t\t}\n\t\t// Remove duplicates\n\t\tfor ( i = 0, len = matches.length; i < len; i++ ) {\n\t\t\tmatch = matches[ i ];\n\t\t\tindex = matches.lastIndexOf( match );\n\t\t\twhile ( index !== i ) {\n\t\t\t\tmatches.splice( index, 1 );\n\t\t\t\tlen--;\n\t\t\t\tindex = matches.lastIndexOf( match );\n\t\t\t}\n\t\t}\n\t\treturn matches;\n\t}\n\treturn this.list.slice();\n};\n\n/**\n * Get 'special' actions.\n *\n * Special actions are the first visible action widgets with special flags, such as 'safe' and 'primary'.\n * Special flags can be configured in subclasses by changing the static #specialFlags property.\n *\n * @return {OO.ui.ActionWidget[]|null} 'Special' action widgets.\n */\nOO.ui.ActionSet.prototype.getSpecial = function () {\n\tthis.organize();\n\treturn $.extend( {}, this.special );\n};\n\n/**\n * Get 'other' actions.\n *\n * Other actions include all non-special visible action widgets.\n *\n * @return {OO.ui.ActionWidget[]} 'Other' action widgets\n */\nOO.ui.ActionSet.prototype.getOthers = function () {\n\tthis.organize();\n\treturn this.others.slice();\n};\n\n/**\n * Set the mode (e.g., ‘edit’ or ‘view’). Only {@link OO.ui.ActionWidget#modes actions} configured\n * to be available in the specified mode will be made visible. All other actions will be hidden.\n *\n * @param {string} mode The mode. Only actions configured to be available in the specified\n * mode will be made visible.\n * @chainable\n * @fires toggle\n * @fires change\n */\nOO.ui.ActionSet.prototype.setMode = function ( mode ) {\n\tvar i, len, action;\n\n\tthis.changing = true;\n\tfor ( i = 0, len = this.list.length; i < len; i++ ) {\n\t\taction = this.list[ i ];\n\t\taction.toggle( action.hasMode( mode ) );\n\t}\n\n\tthis.organized = false;\n\tthis.changing = false;\n\tthis.emit( 'change' );\n\n\treturn this;\n};\n\n/**\n * Set the abilities of the specified actions.\n *\n * Action widgets that are configured with the specified actions will be enabled\n * or disabled based on the boolean values specified in the `actions`\n * parameter.\n *\n * @param {Object.<string,boolean>} actions A list keyed by action name with boolean\n * values that indicate whether or not the action should be enabled.\n * @chainable\n */\nOO.ui.ActionSet.prototype.setAbilities = function ( actions ) {\n\tvar i, len, action, item;\n\n\tfor ( i = 0, len = this.list.length; i < len; i++ ) {\n\t\titem = this.list[ i ];\n\t\taction = item.getAction();\n\t\tif ( actions[ action ] !== undefined ) {\n\t\t\titem.setDisabled( !actions[ action ] );\n\t\t}\n\t}\n\n\treturn this;\n};\n\n/**\n * Executes a function once per action.\n *\n * When making changes to multiple actions, use this method instead of iterating over the actions\n * manually to defer emitting a #change event until after all actions have been changed.\n *\n * @param {Object|null} filter Filters to use to determine which actions to iterate over; see #get\n * @param {Function} callback Callback to run for each action; callback is invoked with three\n * arguments: the action, the action's index, the list of actions being iterated over\n * @chainable\n */\nOO.ui.ActionSet.prototype.forEach = function ( filter, callback ) {\n\tthis.changed = false;\n\tthis.changing = true;\n\tthis.get( filter ).forEach( callback );\n\tthis.changing = false;\n\tif ( this.changed ) {\n\t\tthis.emit( 'change' );\n\t}\n\n\treturn this;\n};\n\n/**\n * Add action widgets to the action set.\n *\n * @param {OO.ui.ActionWidget[]} actions Action widgets to add\n * @chainable\n * @fires add\n * @fires change\n */\nOO.ui.ActionSet.prototype.add = function ( actions ) {\n\tvar i, len, action;\n\n\tthis.changing = true;\n\tfor ( i = 0, len = actions.length; i < len; i++ ) {\n\t\taction = actions[ i ];\n\t\taction.connect( this, {\n\t\t\tclick: [ 'emit', 'click', action ],\n\t\t\ttoggle: [ 'onActionChange' ]\n\t\t} );\n\t\tthis.list.push( action );\n\t}\n\tthis.organized = false;\n\tthis.emit( 'add', actions );\n\tthis.changing = false;\n\tthis.emit( 'change' );\n\n\treturn this;\n};\n\n/**\n * Remove action widgets from the set.\n *\n * To remove all actions, you may wish to use the #clear method instead.\n *\n * @param {OO.ui.ActionWidget[]} actions Action widgets to remove\n * @chainable\n * @fires remove\n * @fires change\n */\nOO.ui.ActionSet.prototype.remove = function ( actions ) {\n\tvar i, len, index, action;\n\n\tthis.changing = true;\n\tfor ( i = 0, len = actions.length; i < len; i++ ) {\n\t\taction = actions[ i ];\n\t\tindex = this.list.indexOf( action );\n\t\tif ( index !== -1 ) {\n\t\t\taction.disconnect( this );\n\t\t\tthis.list.splice( index, 1 );\n\t\t}\n\t}\n\tthis.organized = false;\n\tthis.emit( 'remove', actions );\n\tthis.changing = false;\n\tthis.emit( 'change' );\n\n\treturn this;\n};\n\n/**\n * Remove all action widets from the set.\n *\n * To remove only specified actions, use the {@link #method-remove remove} method instead.\n *\n * @chainable\n * @fires remove\n * @fires change\n */\nOO.ui.ActionSet.prototype.clear = function () {\n\tvar i, len, action,\n\t\tremoved = this.list.slice();\n\n\tthis.changing = true;\n\tfor ( i = 0, len = this.list.length; i < len; i++ ) {\n\t\taction = this.list[ i ];\n\t\taction.disconnect( this );\n\t}\n\n\tthis.list = [];\n\n\tthis.organized = false;\n\tthis.emit( 'remove', removed );\n\tthis.changing = false;\n\tthis.emit( 'change' );\n\n\treturn this;\n};\n\n/**\n * Organize actions.\n *\n * This is called whenever organized information is requested. It will only reorganize the actions\n * if something has changed since the last time it ran.\n *\n * @private\n * @chainable\n */\nOO.ui.ActionSet.prototype.organize = function () {\n\tvar i, iLen, j, jLen, flag, action, category, list, item, special,\n\t\tspecialFlags = this.constructor.static.specialFlags;\n\n\tif ( !this.organized ) {\n\t\tthis.categorized = {};\n\t\tthis.special = {};\n\t\tthis.others = [];\n\t\tfor ( i = 0, iLen = this.list.length; i < iLen; i++ ) {\n\t\t\taction = this.list[ i ];\n\t\t\tif ( action.isVisible() ) {\n\t\t\t\t// Populate categories\n\t\t\t\tfor ( category in this.categories ) {\n\t\t\t\t\tif ( !this.categorized[ category ] ) {\n\t\t\t\t\t\tthis.categorized[ category ] = {};\n\t\t\t\t\t}\n\t\t\t\t\tlist = action[ this.categories[ category ] ]();\n\t\t\t\t\tif ( !Array.isArray( list ) ) {\n\t\t\t\t\t\tlist = [ list ];\n\t\t\t\t\t}\n\t\t\t\t\tfor ( j = 0, jLen = list.length; j < jLen; j++ ) {\n\t\t\t\t\t\titem = list[ j ];\n\t\t\t\t\t\tif ( !this.categorized[ category ][ item ] ) {\n\t\t\t\t\t\t\tthis.categorized[ category ][ item ] = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tthis.categorized[ category ][ item ].push( action );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// Populate special/others\n\t\t\t\tspecial = false;\n\t\t\t\tfor ( j = 0, jLen = specialFlags.length; j < jLen; j++ ) {\n\t\t\t\t\tflag = specialFlags[ j ];\n\t\t\t\t\tif ( !this.special[ flag ] && action.hasFlag( flag ) ) {\n\t\t\t\t\t\tthis.special[ flag ] = action;\n\t\t\t\t\t\tspecial = true;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( !special ) {\n\t\t\t\t\tthis.others.push( action );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.organized = true;\n\t}\n\n\treturn this;\n};\n","/**\n * Errors contain a required message (either a string or jQuery selection) that is used to describe what went wrong\n * in a {@link OO.ui.Process process}. The error's #recoverable and #warning configurations are used to customize the\n * appearance and functionality of the error interface.\n *\n * The basic error interface contains a formatted error message as well as two buttons: 'Dismiss' and 'Try again' (i.e., the error\n * is 'recoverable' by default). If the error is not recoverable, the 'Try again' button will not be rendered and the widget\n * that initiated the failed process will be disabled.\n *\n * If the error is a warning, the error interface will include a 'Dismiss' and a 'Continue' button, which will try the\n * process again.\n *\n * For an example of error interfaces, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs#Processes_and_errors\n *\n * @class\n *\n * @constructor\n * @param {string|jQuery} message Description of error\n * @param {Object} [config] Configuration options\n * @cfg {boolean} [recoverable=true] Error is recoverable.\n * By default, errors are recoverable, and users can try the process again.\n * @cfg {boolean} [warning=false] Error is a warning.\n * If the error is a warning, the error interface will include a\n * 'Dismiss' and a 'Continue' button. It is the responsibility of the developer to ensure that the warning\n * is not triggered a second time if the user chooses to continue.\n */\nOO.ui.Error = function OoUiError( message, config ) {\n\t// Allow passing positional parameters inside the config object\n\tif ( OO.isPlainObject( message ) && config === undefined ) {\n\t\tconfig = message;\n\t\tmessage = config.message;\n\t}\n\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Properties\n\tthis.message = message instanceof jQuery ? message : String( message );\n\tthis.recoverable = config.recoverable === undefined || !!config.recoverable;\n\tthis.warning = !!config.warning;\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.Error );\n\n/* Methods */\n\n/**\n * Check if the error is recoverable.\n *\n * If the error is recoverable, users are able to try the process again.\n *\n * @return {boolean} Error is recoverable\n */\nOO.ui.Error.prototype.isRecoverable = function () {\n\treturn this.recoverable;\n};\n\n/**\n * Check if the error is a warning.\n *\n * If the error is a warning, the error interface will include a 'Dismiss' and a 'Continue' button.\n *\n * @return {boolean} Error is warning\n */\nOO.ui.Error.prototype.isWarning = function () {\n\treturn this.warning;\n};\n\n/**\n * Get error message as DOM nodes.\n *\n * @return {jQuery} Error message in DOM nodes\n */\nOO.ui.Error.prototype.getMessage = function () {\n\treturn this.message instanceof jQuery ?\n\t\tthis.message.clone() :\n\t\t$( '<div>' ).text( this.message ).contents();\n};\n\n/**\n * Get the error message text.\n *\n * @return {string} Error message\n */\nOO.ui.Error.prototype.getMessageText = function () {\n\treturn this.message instanceof jQuery ? this.message.text() : this.message;\n};\n","/**\n * A Process is a list of steps that are called in sequence. The step can be a number, a jQuery promise,\n * or a function:\n *\n * - **number**: the process will wait for the specified number of milliseconds before proceeding.\n * - **promise**: the process will continue to the next step when the promise is successfully resolved\n * or stop if the promise is rejected.\n * - **function**: the process will execute the function. The process will stop if the function returns\n * either a boolean `false` or a promise that is rejected; if the function returns a number, the process\n * will wait for that number of milliseconds before proceeding.\n *\n * If the process fails, an {@link OO.ui.Error error} is generated. Depending on how the error is\n * configured, users can dismiss the error and try the process again, or not. If a process is stopped,\n * its remaining steps will not be performed.\n *\n * @class\n *\n * @constructor\n * @param {number|jQuery.Promise|Function} step Number of miliseconds to wait before proceeding, promise\n * that must be resolved before proceeding, or a function to execute. See #createStep for more information. see #createStep for more information\n * @param {Object} [context=null] Execution context of the function. The context is ignored if the step is\n * a number or promise.\n */\nOO.ui.Process = function ( step, context ) {\n\t// Properties\n\tthis.steps = [];\n\n\t// Initialization\n\tif ( step !== undefined ) {\n\t\tthis.next( step, context );\n\t}\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.Process );\n\n/* Methods */\n\n/**\n * Start the process.\n *\n * @return {jQuery.Promise} Promise that is resolved when all steps have successfully completed.\n * If any of the steps return a promise that is rejected or a boolean false, this promise is rejected\n * and any remaining steps are not performed.\n */\nOO.ui.Process.prototype.execute = function () {\n\tvar i, len, promise;\n\n\t/**\n\t * Continue execution.\n\t *\n\t * @ignore\n\t * @param {Array} step A function and the context it should be called in\n\t * @return {Function} Function that continues the process\n\t */\n\tfunction proceed( step ) {\n\t\treturn function () {\n\t\t\t// Execute step in the correct context\n\t\t\tvar deferred,\n\t\t\t\tresult = step.callback.call( step.context );\n\n\t\t\tif ( result === false ) {\n\t\t\t\t// Use rejected promise for boolean false results\n\t\t\t\treturn $.Deferred().reject( [] ).promise();\n\t\t\t}\n\t\t\tif ( typeof result === 'number' ) {\n\t\t\t\tif ( result < 0 ) {\n\t\t\t\t\tthrow new Error( 'Cannot go back in time: flux capacitor is out of service' );\n\t\t\t\t}\n\t\t\t\t// Use a delayed promise for numbers, expecting them to be in milliseconds\n\t\t\t\tdeferred = $.Deferred();\n\t\t\t\tsetTimeout( deferred.resolve, result );\n\t\t\t\treturn deferred.promise();\n\t\t\t}\n\t\t\tif ( result instanceof OO.ui.Error ) {\n\t\t\t\t// Use rejected promise for error\n\t\t\t\treturn $.Deferred().reject( [ result ] ).promise();\n\t\t\t}\n\t\t\tif ( Array.isArray( result ) && result.length && result[ 0 ] instanceof OO.ui.Error ) {\n\t\t\t\t// Use rejected promise for list of errors\n\t\t\t\treturn $.Deferred().reject( result ).promise();\n\t\t\t}\n\t\t\t// Duck-type the object to see if it can produce a promise\n\t\t\tif ( result && $.isFunction( result.promise ) ) {\n\t\t\t\t// Use a promise generated from the result\n\t\t\t\treturn result.promise();\n\t\t\t}\n\t\t\t// Use resolved promise for other results\n\t\t\treturn $.Deferred().resolve().promise();\n\t\t};\n\t}\n\n\tif ( this.steps.length ) {\n\t\t// Generate a chain reaction of promises\n\t\tpromise = proceed( this.steps[ 0 ] )();\n\t\tfor ( i = 1, len = this.steps.length; i < len; i++ ) {\n\t\t\tpromise = promise.then( proceed( this.steps[ i ] ) );\n\t\t}\n\t} else {\n\t\tpromise = $.Deferred().resolve().promise();\n\t}\n\n\treturn promise;\n};\n\n/**\n * Create a process step.\n *\n * @private\n * @param {number|jQuery.Promise|Function} step\n *\n * - Number of milliseconds to wait before proceeding\n * - Promise that must be resolved before proceeding\n * - Function to execute\n * - If the function returns a boolean false the process will stop\n * - If the function returns a promise, the process will continue to the next\n * step when the promise is resolved or stop if the promise is rejected\n * - If the function returns a number, the process will wait for that number of\n * milliseconds before proceeding\n * @param {Object} [context=null] Execution context of the function. The context is\n * ignored if the step is a number or promise.\n * @return {Object} Step object, with `callback` and `context` properties\n */\nOO.ui.Process.prototype.createStep = function ( step, context ) {\n\tif ( typeof step === 'number' || $.isFunction( step.promise ) ) {\n\t\treturn {\n\t\t\tcallback: function () {\n\t\t\t\treturn step;\n\t\t\t},\n\t\t\tcontext: null\n\t\t};\n\t}\n\tif ( $.isFunction( step ) ) {\n\t\treturn {\n\t\t\tcallback: step,\n\t\t\tcontext: context\n\t\t};\n\t}\n\tthrow new Error( 'Cannot create process step: number, promise or function expected' );\n};\n\n/**\n * Add step to the beginning of the process.\n *\n * @inheritdoc #createStep\n * @return {OO.ui.Process} this\n * @chainable\n */\nOO.ui.Process.prototype.first = function ( step, context ) {\n\tthis.steps.unshift( this.createStep( step, context ) );\n\treturn this;\n};\n\n/**\n * Add step to the end of the process.\n *\n * @inheritdoc #createStep\n * @return {OO.ui.Process} this\n * @chainable\n */\nOO.ui.Process.prototype.next = function ( step, context ) {\n\tthis.steps.push( this.createStep( step, context ) );\n\treturn this;\n};\n","/**\n * A window instance represents the life cycle for one single opening of a window\n * until its closing.\n *\n * While OO.ui.WindowManager will reuse OO.ui.Window objects, each time a window is\n * opened, a new lifecycle starts.\n *\n * For more information, please see the [OOjs UI documentation on MediaWiki] [1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows\n *\n * @class\n *\n * @constructor\n */\nOO.ui.WindowInstance = function OOuiWindowInstance() {\n\tvar deferreds = {\n\t\topening: $.Deferred(),\n\t\topened: $.Deferred(),\n\t\tclosing: $.Deferred(),\n\t\tclosed: $.Deferred()\n\t};\n\n\t/**\n\t * @private\n\t * @property {Object}\n\t */\n\tthis.deferreds = deferreds;\n\n\t// Set these up as chained promises so that rejecting of\n\t// an earlier stage automatically rejects the subsequent\n\t// would-be stages as well.\n\n\t/**\n\t * @property {jQuery.Promise}\n\t */\n\tthis.opening = deferreds.opening.promise();\n\t/**\n\t * @property {jQuery.Promise}\n\t */\n\tthis.opened = this.opening.then( function () {\n\t\treturn deferreds.opened;\n\t} );\n\t/**\n\t * @property {jQuery.Promise}\n\t */\n\tthis.closing = this.opened.then( function () {\n\t\treturn deferreds.closing;\n\t} );\n\t/**\n\t * @property {jQuery.Promise}\n\t */\n\tthis.closed = this.closing.then( function () {\n\t\treturn deferreds.closed;\n\t} );\n};\n\n/* Setup */\n\nOO.initClass( OO.ui.WindowInstance );\n\n/**\n * Check if window is opening.\n *\n * @return {boolean} Window is opening\n */\nOO.ui.WindowInstance.prototype.isOpening = function () {\n\treturn this.deferreds.opened.state() === 'pending';\n};\n\n/**\n * Check if window is opened.\n *\n * @return {boolean} Window is opened\n */\nOO.ui.WindowInstance.prototype.isOpened = function () {\n\treturn this.deferreds.opened.state() === 'resolved' &&\n\t\tthis.deferreds.closing.state() === 'pending';\n};\n\n/**\n * Check if window is closing.\n *\n * @return {boolean} Window is closing\n */\nOO.ui.WindowInstance.prototype.isClosing = function () {\n\treturn this.deferreds.closing.state() === 'resolved' &&\n\t\tthis.deferreds.closed.state() === 'pending';\n};\n\n/**\n * Check if window is closed.\n *\n * @return {boolean} Window is closed\n */\nOO.ui.WindowInstance.prototype.isClosed = function () {\n\treturn this.deferreds.closed.state() === 'resolved';\n};\n","/**\n * Window managers are used to open and close {@link OO.ui.Window windows} and control their presentation.\n * Managed windows are mutually exclusive. If a new window is opened while a current window is opening\n * or is opened, the current window will be closed and any ongoing {@link OO.ui.Process process} will be cancelled. Windows\n * themselves are persistent and—rather than being torn down when closed—can be repopulated with the\n * pertinent data and reused.\n *\n * Over the lifecycle of a window, the window manager makes available three promises: `opening`,\n * `opened`, and `closing`, which represent the primary stages of the cycle:\n *\n * **Opening**: the opening stage begins when the window manager’s #openWindow or a window’s\n * {@link OO.ui.Window#open open} method is used, and the window manager begins to open the window.\n *\n * - an `opening` event is emitted with an `opening` promise\n * - the #getSetupDelay method is called and the returned value is used to time a pause in execution before the\n * window’s {@link OO.ui.Window#method-setup setup} method is called which executes OO.ui.Window#getSetupProcess.\n * - a `setup` progress notification is emitted from the `opening` promise\n * - the #getReadyDelay method is called the returned value is used to time a pause in execution before the\n * window’s {@link OO.ui.Window#method-ready ready} method is called which executes OO.ui.Window#getReadyProcess.\n * - a `ready` progress notification is emitted from the `opening` promise\n * - the `opening` promise is resolved with an `opened` promise\n *\n * **Opened**: the window is now open.\n *\n * **Closing**: the closing stage begins when the window manager's #closeWindow or the\n * window's {@link OO.ui.Window#close close} methods is used, and the window manager begins\n * to close the window.\n *\n * - the `opened` promise is resolved with `closing` promise and a `closing` event is emitted\n * - the #getHoldDelay method is called and the returned value is used to time a pause in execution before\n * the window's {@link OO.ui.Window#getHoldProcess getHoldProces} method is called on the\n * window and its result executed\n * - a `hold` progress notification is emitted from the `closing` promise\n * - the #getTeardownDelay() method is called and the returned value is used to time a pause in execution before\n * the window's {@link OO.ui.Window#getTeardownProcess getTeardownProcess} method is called on the\n * window and its result executed\n * - a `teardown` progress notification is emitted from the `closing` promise\n * - the `closing` promise is resolved. The window is now closed\n *\n * See the [OOjs UI documentation on MediaWiki][1] for more information.\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Window_managers\n *\n * @class\n * @extends OO.ui.Element\n * @mixins OO.EventEmitter\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {OO.Factory} [factory] Window factory to use for automatic instantiation\n * Note that window classes that are instantiated with a factory must have\n * a {@link OO.ui.Dialog#static-name static name} property that specifies a symbolic name.\n * @cfg {boolean} [modal=true] Prevent interaction outside the dialog\n */\nOO.ui.WindowManager = function OoUiWindowManager( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.WindowManager.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.EventEmitter.call( this );\n\n\t// Properties\n\tthis.factory = config.factory;\n\tthis.modal = config.modal === undefined || !!config.modal;\n\tthis.windows = {};\n\t// Deprecated placeholder promise given to compatOpening in openWindow()\n\t// that is resolved in closeWindow().\n\tthis.compatOpened = null;\n\tthis.preparingToOpen = null;\n\tthis.preparingToClose = null;\n\tthis.currentWindow = null;\n\tthis.globalEvents = false;\n\tthis.$returnFocusTo = null;\n\tthis.$ariaHidden = null;\n\tthis.onWindowResizeTimeout = null;\n\tthis.onWindowResizeHandler = this.onWindowResize.bind( this );\n\tthis.afterWindowResizeHandler = this.afterWindowResize.bind( this );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-windowManager' )\n\t\t.toggleClass( 'oo-ui-windowManager-modal', this.modal );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.WindowManager, OO.ui.Element );\nOO.mixinClass( OO.ui.WindowManager, OO.EventEmitter );\n\n/* Events */\n\n/**\n * An 'opening' event is emitted when the window begins to be opened.\n *\n * @event opening\n * @param {OO.ui.Window} win Window that's being opened\n * @param {jQuery.Promise} opened A promise resolved with a value when the window is opened successfully.\n * This promise also emits `setup` and `ready` notifications. When this promise is resolved, the first\n * argument of the value is an 'closed' promise, the second argument is the opening data.\n * @param {Object} data Window opening data\n */\n\n/**\n * A 'closing' event is emitted when the window begins to be closed.\n *\n * @event closing\n * @param {OO.ui.Window} win Window that's being closed\n * @param {jQuery.Promise} closed A promise resolved with a value when the window is closed successfully.\n * This promise also emits `hold` and `teardown` notifications. When this promise is resolved, the first\n * argument of its value is the closing data.\n * @param {Object} data Window closing data\n */\n\n/**\n * A 'resize' event is emitted when a window is resized.\n *\n * @event resize\n * @param {OO.ui.Window} win Window that was resized\n */\n\n/* Static Properties */\n\n/**\n * Map of the symbolic name of each window size and its CSS properties.\n *\n * @static\n * @inheritable\n * @property {Object}\n */\nOO.ui.WindowManager.static.sizes = {\n\tsmall: {\n\t\twidth: 300\n\t},\n\tmedium: {\n\t\twidth: 500\n\t},\n\tlarge: {\n\t\twidth: 700\n\t},\n\tlarger: {\n\t\twidth: 900\n\t},\n\tfull: {\n\t\t// These can be non-numeric because they are never used in calculations\n\t\twidth: '100%',\n\t\theight: '100%'\n\t}\n};\n\n/**\n * Symbolic name of the default window size.\n *\n * The default size is used if the window's requested size is not recognized.\n *\n * @static\n * @inheritable\n * @property {string}\n */\nOO.ui.WindowManager.static.defaultSize = 'medium';\n\n/* Methods */\n\n/**\n * Handle window resize events.\n *\n * @private\n * @param {jQuery.Event} e Window resize event\n */\nOO.ui.WindowManager.prototype.onWindowResize = function () {\n\tclearTimeout( this.onWindowResizeTimeout );\n\tthis.onWindowResizeTimeout = setTimeout( this.afterWindowResizeHandler, 200 );\n};\n\n/**\n * Handle window resize events.\n *\n * @private\n * @param {jQuery.Event} e Window resize event\n */\nOO.ui.WindowManager.prototype.afterWindowResize = function () {\n\tif ( this.currentWindow ) {\n\t\tthis.updateWindowSize( this.currentWindow );\n\t}\n};\n\n/**\n * Check if window is opening.\n *\n * @param {OO.ui.Window} win Window to check\n * @return {boolean} Window is opening\n */\nOO.ui.WindowManager.prototype.isOpening = function ( win ) {\n\treturn win === this.currentWindow && !!this.lifecycle &&\n\t\tthis.lifecycle.isOpening();\n};\n\n/**\n * Check if window is closing.\n *\n * @param {OO.ui.Window} win Window to check\n * @return {boolean} Window is closing\n */\nOO.ui.WindowManager.prototype.isClosing = function ( win ) {\n\treturn win === this.currentWindow && !!this.lifecycle &&\n\t\tthis.lifecycle.isClosing();\n};\n\n/**\n * Check if window is opened.\n *\n * @param {OO.ui.Window} win Window to check\n * @return {boolean} Window is opened\n */\nOO.ui.WindowManager.prototype.isOpened = function ( win ) {\n\treturn win === this.currentWindow && !!this.lifecycle &&\n\t\tthis.lifecycle.isOpened();\n};\n\n/**\n * Check if a window is being managed.\n *\n * @param {OO.ui.Window} win Window to check\n * @return {boolean} Window is being managed\n */\nOO.ui.WindowManager.prototype.hasWindow = function ( win ) {\n\tvar name;\n\n\tfor ( name in this.windows ) {\n\t\tif ( this.windows[ name ] === win ) {\n\t\t\treturn true;\n\t\t}\n\t}\n\n\treturn false;\n};\n\n/**\n * Get the number of milliseconds to wait after opening begins before executing the ‘setup’ process.\n *\n * @param {OO.ui.Window} win Window being opened\n * @param {Object} [data] Window opening data\n * @return {number} Milliseconds to wait\n */\nOO.ui.WindowManager.prototype.getSetupDelay = function () {\n\treturn 0;\n};\n\n/**\n * Get the number of milliseconds to wait after setup has finished before executing the ‘ready’ process.\n *\n * @param {OO.ui.Window} win Window being opened\n * @param {Object} [data] Window opening data\n * @return {number} Milliseconds to wait\n */\nOO.ui.WindowManager.prototype.getReadyDelay = function () {\n\treturn 0;\n};\n\n/**\n * Get the number of milliseconds to wait after closing has begun before executing the 'hold' process.\n *\n * @param {OO.ui.Window} win Window being closed\n * @param {Object} [data] Window closing data\n * @return {number} Milliseconds to wait\n */\nOO.ui.WindowManager.prototype.getHoldDelay = function () {\n\treturn 0;\n};\n\n/**\n * Get the number of milliseconds to wait after the ‘hold’ process has finished before\n * executing the ‘teardown’ process.\n *\n * @param {OO.ui.Window} win Window being closed\n * @param {Object} [data] Window closing data\n * @return {number} Milliseconds to wait\n */\nOO.ui.WindowManager.prototype.getTeardownDelay = function () {\n\treturn this.modal ? 250 : 0;\n};\n\n/**\n * Get a window by its symbolic name.\n *\n * If the window is not yet instantiated and its symbolic name is recognized by a factory, it will be\n * instantiated and added to the window manager automatically. Please see the [OOjs UI documentation on MediaWiki][3]\n * for more information about using factories.\n * [3]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Window_managers\n *\n * @param {string} name Symbolic name of the window\n * @return {jQuery.Promise} Promise resolved with matching window, or rejected with an OO.ui.Error\n * @throws {Error} An error is thrown if the symbolic name is not recognized by the factory.\n * @throws {Error} An error is thrown if the named window is not recognized as a managed window.\n */\nOO.ui.WindowManager.prototype.getWindow = function ( name ) {\n\tvar deferred = $.Deferred(),\n\t\twin = this.windows[ name ];\n\n\tif ( !( win instanceof OO.ui.Window ) ) {\n\t\tif ( this.factory ) {\n\t\t\tif ( !this.factory.lookup( name ) ) {\n\t\t\t\tdeferred.reject( new OO.ui.Error(\n\t\t\t\t\t'Cannot auto-instantiate window: symbolic name is unrecognized by the factory'\n\t\t\t\t) );\n\t\t\t} else {\n\t\t\t\twin = this.factory.create( name );\n\t\t\t\tthis.addWindows( [ win ] );\n\t\t\t\tdeferred.resolve( win );\n\t\t\t}\n\t\t} else {\n\t\t\tdeferred.reject( new OO.ui.Error(\n\t\t\t\t'Cannot get unmanaged window: symbolic name unrecognized as a managed window'\n\t\t\t) );\n\t\t}\n\t} else {\n\t\tdeferred.resolve( win );\n\t}\n\n\treturn deferred.promise();\n};\n\n/**\n * Get current window.\n *\n * @return {OO.ui.Window|null} Currently opening/opened/closing window\n */\nOO.ui.WindowManager.prototype.getCurrentWindow = function () {\n\treturn this.currentWindow;\n};\n\n/**\n * Open a window.\n *\n * @param {OO.ui.Window|string} win Window object or symbolic name of window to open\n * @param {Object} [data] Window opening data\n * @param {jQuery|null} [data.$returnFocusTo] Element to which the window will return focus when closed.\n * Defaults the current activeElement. If set to null, focus isn't changed on close.\n * @return {OO.ui.WindowInstance|jQuery.Promise} A lifecycle object representing this particular\n * opening of the window. For backwards-compatibility, then object is also a Thenable that is resolved\n * when the window is done opening, with nested promise for when closing starts. This behaviour\n * is deprecated and is not compatible with jQuery 3. See T163510.\n * @fires opening\n */\nOO.ui.WindowManager.prototype.openWindow = function ( win, data, lifecycle, compatOpening ) {\n\tvar error,\n\t\tmanager = this;\n\tdata = data || {};\n\n\t// Internal parameter 'lifecycle' allows this method to always return\n\t// a lifecycle even if the window still needs to be created\n\t// asynchronously when 'win' is a string.\n\tlifecycle = lifecycle || new OO.ui.WindowInstance();\n\tcompatOpening = compatOpening || $.Deferred();\n\n\t// Turn lifecycle into a Thenable for backwards-compatibility with\n\t// the deprecated nested-promise behaviour, see T163510.\n\t[ 'state', 'always', 'catch', 'pipe', 'then', 'promise', 'progress', 'done', 'fail' ]\n\t\t.forEach( function ( method ) {\n\t\t\tlifecycle[ method ] = function () {\n\t\t\t\tOO.ui.warnDeprecation(\n\t\t\t\t\t'Using the return value of openWindow as a promise is deprecated. ' +\n\t\t\t\t\t'Use .openWindow( ... ).opening.' + method + '( ... ) instead.'\n\t\t\t\t);\n\t\t\t\treturn compatOpening[ method ].apply( this, arguments );\n\t\t\t};\n\t\t} );\n\n\t// Argument handling\n\tif ( typeof win === 'string' ) {\n\t\tthis.getWindow( win ).then(\n\t\t\tfunction ( win ) {\n\t\t\t\tmanager.openWindow( win, data, lifecycle, compatOpening );\n\t\t\t},\n\t\t\tfunction ( err ) {\n\t\t\t\tlifecycle.deferreds.opening.reject( err );\n\t\t\t}\n\t\t);\n\t\treturn lifecycle;\n\t}\n\n\t// Error handling\n\tif ( !this.hasWindow( win ) ) {\n\t\terror = 'Cannot open window: window is not attached to manager';\n\t} else if ( this.lifecycle && this.lifecycle.isOpened() ) {\n\t\terror = 'Cannot open window: another window is open';\n\t} else if ( this.preparingToOpen || ( this.lifecycle && this.lifecycle.isOpening() ) ) {\n\t\terror = 'Cannot open window: another window is opening';\n\t}\n\n\tif ( error ) {\n\t\tcompatOpening.reject( new OO.ui.Error( error ) );\n\t\tlifecycle.deferreds.opening.reject( new OO.ui.Error( error ) );\n\t\treturn lifecycle;\n\t}\n\n\t// If a window is currently closing, wait for it to complete\n\tthis.preparingToOpen = $.when( this.lifecycle && this.lifecycle.closed );\n\t// Ensure handlers get called after preparingToOpen is set\n\tthis.preparingToOpen.done( function () {\n\t\tif ( manager.modal ) {\n\t\t\tmanager.toggleGlobalEvents( true );\n\t\t\tmanager.toggleAriaIsolation( true );\n\t\t}\n\t\tmanager.$returnFocusTo = data.$returnFocusTo !== undefined ? data.$returnFocusTo : $( document.activeElement );\n\t\tmanager.currentWindow = win;\n\t\tmanager.lifecycle = lifecycle;\n\t\tmanager.preparingToOpen = null;\n\t\tmanager.emit( 'opening', win, compatOpening, data );\n\t\tlifecycle.deferreds.opening.resolve( data );\n\t\tsetTimeout( function () {\n\t\t\tmanager.compatOpened = $.Deferred();\n\t\t\twin.setup( data ).then( function () {\n\t\t\t\tmanager.updateWindowSize( win );\n\t\t\t\tcompatOpening.notify( { state: 'setup' } );\n\t\t\t\tsetTimeout( function () {\n\t\t\t\t\twin.ready( data ).then( function () {\n\t\t\t\t\t\tcompatOpening.notify( { state: 'ready' } );\n\t\t\t\t\t\tlifecycle.deferreds.opened.resolve( data );\n\t\t\t\t\t\tcompatOpening.resolve( manager.compatOpened.promise(), data );\n\t\t\t\t\t}, function () {\n\t\t\t\t\t\tlifecycle.deferreds.opened.reject();\n\t\t\t\t\t\tcompatOpening.reject();\n\t\t\t\t\t\tmanager.closeWindow( win );\n\t\t\t\t\t} );\n\t\t\t\t}, manager.getReadyDelay() );\n\t\t\t}, function () {\n\t\t\t\tlifecycle.deferreds.opened.reject();\n\t\t\t\tcompatOpening.reject();\n\t\t\t\tmanager.closeWindow( win );\n\t\t\t} );\n\t\t}, manager.getSetupDelay() );\n\t} );\n\n\treturn lifecycle;\n};\n\n/**\n * Close a window.\n *\n * @param {OO.ui.Window|string} win Window object or symbolic name of window to close\n * @param {Object} [data] Window closing data\n * @return {OO.ui.WindowInstance|jQuery.Promise} A lifecycle object representing this particular\n * opening of the window. For backwards-compatibility, the object is also a Thenable that is resolved\n * when the window is done closing, see T163510.\n * @fires closing\n */\nOO.ui.WindowManager.prototype.closeWindow = function ( win, data ) {\n\tvar error,\n\t\tmanager = this,\n\t\tcompatClosing = $.Deferred(),\n\t\tlifecycle = this.lifecycle,\n\t\tcompatOpened;\n\n\t// Argument handling\n\tif ( typeof win === 'string' ) {\n\t\twin = this.windows[ win ];\n\t} else if ( !this.hasWindow( win ) ) {\n\t\twin = null;\n\t}\n\n\t// Error handling\n\tif ( !lifecycle ) {\n\t\terror = 'Cannot close window: no window is currently open';\n\t} else if ( !win ) {\n\t\terror = 'Cannot close window: window is not attached to manager';\n\t} else if ( win !== this.currentWindow || this.lifecycle.isClosed() ) {\n\t\terror = 'Cannot close window: window already closed with different data';\n\t} else if ( this.preparingToClose || this.lifecycle.isClosing() ) {\n\t\terror = 'Cannot close window: window already closing with different data';\n\t}\n\n\tif ( error ) {\n\t\t// This function was called for the wrong window and we don't want to mess with the current\n\t\t// window's state.\n\t\tlifecycle = new OO.ui.WindowInstance();\n\t\t// Pretend the window has been opened, so that we can pretend to fail to close it.\n\t\tlifecycle.deferreds.opening.resolve( {} );\n\t\tlifecycle.deferreds.opened.resolve( {} );\n\t}\n\n\t// Turn lifecycle into a Thenable for backwards-compatibility with\n\t// the deprecated nested-promise behaviour, see T163510.\n\t[ 'state', 'always', 'catch', 'pipe', 'then', 'promise', 'progress', 'done', 'fail' ]\n\t\t.forEach( function ( method ) {\n\t\t\tlifecycle[ method ] = function () {\n\t\t\t\tOO.ui.warnDeprecation(\n\t\t\t\t\t'Using the return value of closeWindow as a promise is deprecated. ' +\n\t\t\t\t\t'Use .closeWindow( ... ).closed.' + method + '( ... ) instead.'\n\t\t\t\t);\n\t\t\t\treturn compatClosing[ method ].apply( this, arguments );\n\t\t\t};\n\t\t} );\n\n\tif ( error ) {\n\t\tcompatClosing.reject( new OO.ui.Error( error ) );\n\t\tlifecycle.deferreds.closing.reject( new OO.ui.Error( error ) );\n\t\treturn lifecycle;\n\t}\n\n\t// If the window is currently opening, close it when it's done\n\tthis.preparingToClose = $.when( this.lifecycle.opened );\n\t// Ensure handlers get called after preparingToClose is set\n\tthis.preparingToClose.always( function () {\n\t\tmanager.preparingToClose = null;\n\t\tmanager.emit( 'closing', win, compatClosing, data );\n\t\tlifecycle.deferreds.closing.resolve( data );\n\t\tcompatOpened = manager.compatOpened;\n\t\tmanager.compatOpened = null;\n\t\tcompatOpened.resolve( compatClosing.promise(), data );\n\t\tsetTimeout( function () {\n\t\t\twin.hold( data ).then( function () {\n\t\t\t\tcompatClosing.notify( { state: 'hold' } );\n\t\t\t\tsetTimeout( function () {\n\t\t\t\t\twin.teardown( data ).then( function () {\n\t\t\t\t\t\tcompatClosing.notify( { state: 'teardown' } );\n\t\t\t\t\t\tif ( manager.modal ) {\n\t\t\t\t\t\t\tmanager.toggleGlobalEvents( false );\n\t\t\t\t\t\t\tmanager.toggleAriaIsolation( false );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( manager.$returnFocusTo && manager.$returnFocusTo.length ) {\n\t\t\t\t\t\t\tmanager.$returnFocusTo[ 0 ].focus();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tmanager.currentWindow = null;\n\t\t\t\t\t\tmanager.lifecycle = null;\n\t\t\t\t\t\tlifecycle.deferreds.closed.resolve( data );\n\t\t\t\t\t\tcompatClosing.resolve( data );\n\t\t\t\t\t} );\n\t\t\t\t}, manager.getTeardownDelay() );\n\t\t\t} );\n\t\t}, manager.getHoldDelay() );\n\t} );\n\n\treturn lifecycle;\n};\n\n/**\n * Add windows to the window manager.\n *\n * Windows can be added by reference, symbolic name, or explicitly defined symbolic names.\n * See the [OOjs ui documentation on MediaWiki] [2] for examples.\n * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Window_managers\n *\n * This function can be called in two manners:\n *\n * 1. `.addWindows( [ windowA, windowB, ... ] )` (where `windowA`, `windowB` are OO.ui.Window objects)\n *\n * This syntax registers windows under the symbolic names defined in their `.static.name`\n * properties. For example, if `windowA.constructor.static.name` is `'nameA'`, calling\n * `.openWindow( 'nameA' )` afterwards will open the window `windowA`. This syntax requires the\n * static name to be set, otherwise an exception will be thrown.\n *\n * This is the recommended way, as it allows for an easier switch to using a window factory.\n *\n * 2. `.addWindows( { nameA: windowA, nameB: windowB, ... } )`\n *\n * This syntax registers windows under the explicitly given symbolic names. In this example,\n * calling `.openWindow( 'nameA' )` afterwards will open the window `windowA`, regardless of what\n * its `.static.name` is set to. The static name is not required to be set.\n *\n * This should only be used if you need to override the default symbolic names.\n *\n * Example:\n *\n * var windowManager = new OO.ui.WindowManager();\n * $( 'body' ).append( windowManager.$element );\n *\n * // Add a window under the default name: see OO.ui.MessageDialog.static.name\n * windowManager.addWindows( [ new OO.ui.MessageDialog() ] );\n * // Add a window under an explicit name\n * windowManager.addWindows( { myMessageDialog: new OO.ui.MessageDialog() } );\n *\n * // Open window by default name\n * windowManager.openWindow( 'message' );\n * // Open window by explicitly given name\n * windowManager.openWindow( 'myMessageDialog' );\n *\n *\n * @param {Object.<string,OO.ui.Window>|OO.ui.Window[]} windows An array of window objects specified\n * by reference, symbolic name, or explicitly defined symbolic names.\n * @throws {Error} An error is thrown if a window is added by symbolic name, but has neither an\n * explicit nor a statically configured symbolic name.\n */\nOO.ui.WindowManager.prototype.addWindows = function ( windows ) {\n\tvar i, len, win, name, list;\n\n\tif ( Array.isArray( windows ) ) {\n\t\t// Convert to map of windows by looking up symbolic names from static configuration\n\t\tlist = {};\n\t\tfor ( i = 0, len = windows.length; i < len; i++ ) {\n\t\t\tname = windows[ i ].constructor.static.name;\n\t\t\tif ( !name ) {\n\t\t\t\tthrow new Error( 'Windows must have a `name` static property defined.' );\n\t\t\t}\n\t\t\tlist[ name ] = windows[ i ];\n\t\t}\n\t} else if ( OO.isPlainObject( windows ) ) {\n\t\tlist = windows;\n\t}\n\n\t// Add windows\n\tfor ( name in list ) {\n\t\twin = list[ name ];\n\t\tthis.windows[ name ] = win.toggle( false );\n\t\tthis.$element.append( win.$element );\n\t\twin.setManager( this );\n\t}\n};\n\n/**\n * Remove the specified windows from the windows manager.\n *\n * Windows will be closed before they are removed. If you wish to remove all windows, you may wish to use\n * the #clearWindows method instead. If you no longer need the window manager and want to ensure that it no\n * longer listens to events, use the #destroy method.\n *\n * @param {string[]} names Symbolic names of windows to remove\n * @return {jQuery.Promise} Promise resolved when window is closed and removed\n * @throws {Error} An error is thrown if the named windows are not managed by the window manager.\n */\nOO.ui.WindowManager.prototype.removeWindows = function ( names ) {\n\tvar i, len, win, name, cleanupWindow,\n\t\tmanager = this,\n\t\tpromises = [],\n\t\tcleanup = function ( name, win ) {\n\t\t\tdelete manager.windows[ name ];\n\t\t\twin.$element.detach();\n\t\t};\n\n\tfor ( i = 0, len = names.length; i < len; i++ ) {\n\t\tname = names[ i ];\n\t\twin = this.windows[ name ];\n\t\tif ( !win ) {\n\t\t\tthrow new Error( 'Cannot remove window' );\n\t\t}\n\t\tcleanupWindow = cleanup.bind( null, name, win );\n\t\tpromises.push( this.closeWindow( name ).closed.then( cleanupWindow, cleanupWindow ) );\n\t}\n\n\treturn $.when.apply( $, promises );\n};\n\n/**\n * Remove all windows from the window manager.\n *\n * Windows will be closed before they are removed. Note that the window manager, though not in use, will still\n * listen to events. If the window manager will not be used again, you may wish to use the #destroy method instead.\n * To remove just a subset of windows, use the #removeWindows method.\n *\n * @return {jQuery.Promise} Promise resolved when all windows are closed and removed\n */\nOO.ui.WindowManager.prototype.clearWindows = function () {\n\treturn this.removeWindows( Object.keys( this.windows ) );\n};\n\n/**\n * Set dialog size. In general, this method should not be called directly.\n *\n * Fullscreen mode will be used if the dialog is too wide to fit in the screen.\n *\n * @param {OO.ui.Window} win Window to update, should be the current window\n * @chainable\n */\nOO.ui.WindowManager.prototype.updateWindowSize = function ( win ) {\n\tvar isFullscreen;\n\n\t// Bypass for non-current, and thus invisible, windows\n\tif ( win !== this.currentWindow ) {\n\t\treturn;\n\t}\n\n\tisFullscreen = win.getSize() === 'full';\n\n\tthis.$element.toggleClass( 'oo-ui-windowManager-fullscreen', isFullscreen );\n\tthis.$element.toggleClass( 'oo-ui-windowManager-floating', !isFullscreen );\n\twin.setDimensions( win.getSizeProperties() );\n\n\tthis.emit( 'resize', win );\n\n\treturn this;\n};\n\n/**\n * Bind or unbind global events for scrolling.\n *\n * @private\n * @param {boolean} [on] Bind global events\n * @chainable\n */\nOO.ui.WindowManager.prototype.toggleGlobalEvents = function ( on ) {\n\tvar scrollWidth, bodyMargin,\n\t\t$body = $( this.getElementDocument().body ),\n\t\t// We could have multiple window managers open so only modify\n\t\t// the body css at the bottom of the stack\n\t\tstackDepth = $body.data( 'windowManagerGlobalEvents' ) || 0;\n\n\ton = on === undefined ? !!this.globalEvents : !!on;\n\n\tif ( on ) {\n\t\tif ( !this.globalEvents ) {\n\t\t\t$( this.getElementWindow() ).on( {\n\t\t\t\t// Start listening for top-level window dimension changes\n\t\t\t\t'orientationchange resize': this.onWindowResizeHandler\n\t\t\t} );\n\t\t\tif ( stackDepth === 0 ) {\n\t\t\t\tscrollWidth = window.innerWidth - document.documentElement.clientWidth;\n\t\t\t\tbodyMargin = parseFloat( $body.css( 'margin-right' ) ) || 0;\n\t\t\t\t$body.css( {\n\t\t\t\t\toverflow: 'hidden',\n\t\t\t\t\t'margin-right': bodyMargin + scrollWidth\n\t\t\t\t} );\n\t\t\t}\n\t\t\tstackDepth++;\n\t\t\tthis.globalEvents = true;\n\t\t}\n\t} else if ( this.globalEvents ) {\n\t\t$( this.getElementWindow() ).off( {\n\t\t\t// Stop listening for top-level window dimension changes\n\t\t\t'orientationchange resize': this.onWindowResizeHandler\n\t\t} );\n\t\tstackDepth--;\n\t\tif ( stackDepth === 0 ) {\n\t\t\t$body.css( {\n\t\t\t\toverflow: '',\n\t\t\t\t'margin-right': ''\n\t\t\t} );\n\t\t}\n\t\tthis.globalEvents = false;\n\t}\n\t$body.data( 'windowManagerGlobalEvents', stackDepth );\n\n\treturn this;\n};\n\n/**\n * Toggle screen reader visibility of content other than the window manager.\n *\n * @private\n * @param {boolean} [isolate] Make only the window manager visible to screen readers\n * @chainable\n */\nOO.ui.WindowManager.prototype.toggleAriaIsolation = function ( isolate ) {\n\tisolate = isolate === undefined ? !this.$ariaHidden : !!isolate;\n\n\tif ( isolate ) {\n\t\tif ( !this.$ariaHidden ) {\n\t\t\t// Hide everything other than the window manager from screen readers\n\t\t\tthis.$ariaHidden = $( 'body' )\n\t\t\t\t.children()\n\t\t\t\t.not( this.$element.parentsUntil( 'body' ).last() )\n\t\t\t\t.attr( 'aria-hidden', '' );\n\t\t}\n\t} else if ( this.$ariaHidden ) {\n\t\t// Restore screen reader visibility\n\t\tthis.$ariaHidden.removeAttr( 'aria-hidden' );\n\t\tthis.$ariaHidden = null;\n\t}\n\n\treturn this;\n};\n\n/**\n * Destroy the window manager.\n *\n * Destroying the window manager ensures that it will no longer listen to events. If you would like to\n * continue using the window manager, but wish to remove all windows from it, use the #clearWindows method\n * instead.\n */\nOO.ui.WindowManager.prototype.destroy = function () {\n\tthis.toggleGlobalEvents( false );\n\tthis.toggleAriaIsolation( false );\n\tthis.clearWindows();\n\tthis.$element.remove();\n};\n","/**\n * A window is a container for elements that are in a child frame. They are used with\n * a window manager (OO.ui.WindowManager), which is used to open and close the window and control\n * its presentation. The size of a window is specified using a symbolic name (e.g., ‘small’, ‘medium’,\n * ‘large’), which is interpreted by the window manager. If the requested size is not recognized,\n * the window manager will choose a sensible fallback.\n *\n * The lifecycle of a window has three primary stages (opening, opened, and closing) in which\n * different processes are executed:\n *\n * **opening**: The opening stage begins when the window manager's {@link OO.ui.WindowManager#openWindow\n * openWindow} or the window's {@link #open open} methods are used, and the window manager begins to open\n * the window.\n *\n * - {@link #getSetupProcess} method is called and its result executed\n * - {@link #getReadyProcess} method is called and its result executed\n *\n * **opened**: The window is now open\n *\n * **closing**: The closing stage begins when the window manager's\n * {@link OO.ui.WindowManager#closeWindow closeWindow}\n * or the window's {@link #close} methods are used, and the window manager begins to close the window.\n *\n * - {@link #getHoldProcess} method is called and its result executed\n * - {@link #getTeardownProcess} method is called and its result executed. The window is now closed\n *\n * Each of the window's processes (setup, ready, hold, and teardown) can be extended in subclasses\n * by overriding the window's #getSetupProcess, #getReadyProcess, #getHoldProcess and #getTeardownProcess\n * methods. Note that each {@link OO.ui.Process process} is executed in series, so asynchronous\n * processing can complete. Always assume window processes are executed asynchronously.\n *\n * For more information, please see the [OOjs UI documentation on MediaWiki] [1].\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows\n *\n * @abstract\n * @class\n * @extends OO.ui.Element\n * @mixins OO.EventEmitter\n *\n * @constructor\n * @param {Object} [config] Configuration options\n * @cfg {string} [size] Symbolic name of the dialog size: `small`, `medium`, `large`, `larger` or\n * `full`. If omitted, the value of the {@link #static-size static size} property will be used.\n */\nOO.ui.Window = function OoUiWindow( config ) {\n\t// Configuration initialization\n\tconfig = config || {};\n\n\t// Parent constructor\n\tOO.ui.Window.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.EventEmitter.call( this );\n\n\t// Properties\n\tthis.manager = null;\n\tthis.size = config.size || this.constructor.static.size;\n\tthis.$frame = $( '<div>' );\n\t/**\n\t * Overlay element to use for the `$overlay` configuration option of widgets that support it.\n\t * Things put inside of it are overlaid on top of the window and are not bound to its dimensions.\n\t * See <https://www.mediawiki.org/wiki/OOjs_UI/Concepts#Overlays>.\n\t *\n\t * MyDialog.prototype.initialize = function () {\n\t * ...\n\t * var popupButton = new OO.ui.PopupButtonWidget( {\n\t * $overlay: this.$overlay,\n\t * label: 'Popup button',\n\t * popup: {\n\t * $content: $( '<p>Popup contents.</p><p>Popup contents.</p><p>Popup contents.</p>' ),\n\t * padded: true\n\t * }\n\t * } );\n\t * ...\n\t * };\n\t *\n\t * @property {jQuery}\n\t */\n\tthis.$overlay = $( '<div>' );\n\tthis.$content = $( '<div>' );\n\n\tthis.$focusTrapBefore = $( '<div>' ).prop( 'tabIndex', 0 );\n\tthis.$focusTrapAfter = $( '<div>' ).prop( 'tabIndex', 0 );\n\tthis.$focusTraps = this.$focusTrapBefore.add( this.$focusTrapAfter );\n\n\t// Initialization\n\tthis.$overlay.addClass( 'oo-ui-window-overlay' );\n\tthis.$content\n\t\t.addClass( 'oo-ui-window-content' )\n\t\t.attr( 'tabindex', 0 );\n\tthis.$frame\n\t\t.addClass( 'oo-ui-window-frame' )\n\t\t.append( this.$focusTrapBefore, this.$content, this.$focusTrapAfter );\n\n\tthis.$element\n\t\t.addClass( 'oo-ui-window' )\n\t\t.append( this.$frame, this.$overlay );\n\n\t// Initially hidden - using #toggle may cause errors if subclasses override toggle with methods\n\t// that reference properties not initialized at that time of parent class construction\n\t// TODO: Find a better way to handle post-constructor setup\n\tthis.visible = false;\n\tthis.$element.addClass( 'oo-ui-element-hidden' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.Window, OO.ui.Element );\nOO.mixinClass( OO.ui.Window, OO.EventEmitter );\n\n/* Static Properties */\n\n/**\n * Symbolic name of the window size: `small`, `medium`, `large`, `larger` or `full`.\n *\n * The static size is used if no #size is configured during construction.\n *\n * @static\n * @inheritable\n * @property {string}\n */\nOO.ui.Window.static.size = 'medium';\n\n/* Methods */\n\n/**\n * Handle mouse down events.\n *\n * @private\n * @param {jQuery.Event} e Mouse down event\n */\nOO.ui.Window.prototype.onMouseDown = function ( e ) {\n\t// Prevent clicking on the click-block from stealing focus\n\tif ( e.target === this.$element[ 0 ] ) {\n\t\treturn false;\n\t}\n};\n\n/**\n * Check if the window has been initialized.\n *\n * Initialization occurs when a window is added to a manager.\n *\n * @return {boolean} Window has been initialized\n */\nOO.ui.Window.prototype.isInitialized = function () {\n\treturn !!this.manager;\n};\n\n/**\n * Check if the window is visible.\n *\n * @return {boolean} Window is visible\n */\nOO.ui.Window.prototype.isVisible = function () {\n\treturn this.visible;\n};\n\n/**\n * Check if the window is opening.\n *\n * This method is a wrapper around the window manager's {@link OO.ui.WindowManager#isOpening isOpening}\n * method.\n *\n * @return {boolean} Window is opening\n */\nOO.ui.Window.prototype.isOpening = function () {\n\treturn this.manager.isOpening( this );\n};\n\n/**\n * Check if the window is closing.\n *\n * This method is a wrapper around the window manager's {@link OO.ui.WindowManager#isClosing isClosing} method.\n *\n * @return {boolean} Window is closing\n */\nOO.ui.Window.prototype.isClosing = function () {\n\treturn this.manager.isClosing( this );\n};\n\n/**\n * Check if the window is opened.\n *\n * This method is a wrapper around the window manager's {@link OO.ui.WindowManager#isOpened isOpened} method.\n *\n * @return {boolean} Window is opened\n */\nOO.ui.Window.prototype.isOpened = function () {\n\treturn this.manager.isOpened( this );\n};\n\n/**\n * Get the window manager.\n *\n * All windows must be attached to a window manager, which is used to open\n * and close the window and control its presentation.\n *\n * @return {OO.ui.WindowManager} Manager of window\n */\nOO.ui.Window.prototype.getManager = function () {\n\treturn this.manager;\n};\n\n/**\n * Get the symbolic name of the window size (e.g., `small` or `medium`).\n *\n * @return {string} Symbolic name of the size: `small`, `medium`, `large`, `larger`, `full`\n */\nOO.ui.Window.prototype.getSize = function () {\n\tvar viewport = OO.ui.Element.static.getDimensions( this.getElementWindow() ),\n\t\tsizes = this.manager.constructor.static.sizes,\n\t\tsize = this.size;\n\n\tif ( !sizes[ size ] ) {\n\t\tsize = this.manager.constructor.static.defaultSize;\n\t}\n\tif ( size !== 'full' && viewport.rect.right - viewport.rect.left < sizes[ size ].width ) {\n\t\tsize = 'full';\n\t}\n\n\treturn size;\n};\n\n/**\n * Get the size properties associated with the current window size\n *\n * @return {Object} Size properties\n */\nOO.ui.Window.prototype.getSizeProperties = function () {\n\treturn this.manager.constructor.static.sizes[ this.getSize() ];\n};\n\n/**\n * Disable transitions on window's frame for the duration of the callback function, then enable them\n * back.\n *\n * @private\n * @param {Function} callback Function to call while transitions are disabled\n */\nOO.ui.Window.prototype.withoutSizeTransitions = function ( callback ) {\n\t// Temporarily resize the frame so getBodyHeight() can use scrollHeight measurements.\n\t// Disable transitions first, otherwise we'll get values from when the window was animating.\n\t// We need to build the transition CSS properties using these specific properties since\n\t// Firefox doesn't return anything useful when asked just for 'transition'.\n\tvar oldTransition = this.$frame.css( 'transition-property' ) + ' ' +\n\t\tthis.$frame.css( 'transition-duration' ) + ' ' +\n\t\tthis.$frame.css( 'transition-timing-function' ) + ' ' +\n\t\tthis.$frame.css( 'transition-delay' );\n\n\tthis.$frame.css( 'transition', 'none' );\n\tcallback();\n\n\t// Force reflow to make sure the style changes done inside callback\n\t// really are not transitioned\n\tthis.$frame.height();\n\tthis.$frame.css( 'transition', oldTransition );\n};\n\n/**\n * Get the height of the full window contents (i.e., the window head, body and foot together).\n *\n * What consistitutes the head, body, and foot varies depending on the window type.\n * A {@link OO.ui.MessageDialog message dialog} displays a title and message in its body,\n * and any actions in the foot. A {@link OO.ui.ProcessDialog process dialog} displays a title\n * and special actions in the head, and dialog content in the body.\n *\n * To get just the height of the dialog body, use the #getBodyHeight method.\n *\n * @return {number} The height of the window contents (the dialog head, body and foot) in pixels\n */\nOO.ui.Window.prototype.getContentHeight = function () {\n\tvar bodyHeight,\n\t\twin = this,\n\t\tbodyStyleObj = this.$body[ 0 ].style,\n\t\tframeStyleObj = this.$frame[ 0 ].style;\n\n\t// Temporarily resize the frame so getBodyHeight() can use scrollHeight measurements.\n\t// Disable transitions first, otherwise we'll get values from when the window was animating.\n\tthis.withoutSizeTransitions( function () {\n\t\tvar oldHeight = frameStyleObj.height,\n\t\t\toldPosition = bodyStyleObj.position;\n\t\tframeStyleObj.height = '1px';\n\t\t// Force body to resize to new width\n\t\tbodyStyleObj.position = 'relative';\n\t\tbodyHeight = win.getBodyHeight();\n\t\tframeStyleObj.height = oldHeight;\n\t\tbodyStyleObj.position = oldPosition;\n\t} );\n\n\treturn (\n\t\t// Add buffer for border\n\t\t( this.$frame.outerHeight() - this.$frame.innerHeight() ) +\n\t\t// Use combined heights of children\n\t\t( this.$head.outerHeight( true ) + bodyHeight + this.$foot.outerHeight( true ) )\n\t);\n};\n\n/**\n * Get the height of the window body.\n *\n * To get the height of the full window contents (the window body, head, and foot together),\n * use #getContentHeight.\n *\n * When this function is called, the window will temporarily have been resized\n * to height=1px, so .scrollHeight measurements can be taken accurately.\n *\n * @return {number} Height of the window body in pixels\n */\nOO.ui.Window.prototype.getBodyHeight = function () {\n\treturn this.$body[ 0 ].scrollHeight;\n};\n\n/**\n * Get the directionality of the frame (right-to-left or left-to-right).\n *\n * @return {string} Directionality: `'ltr'` or `'rtl'`\n */\nOO.ui.Window.prototype.getDir = function () {\n\treturn OO.ui.Element.static.getDir( this.$content ) || 'ltr';\n};\n\n/**\n * Get the 'setup' process.\n *\n * The setup process is used to set up a window for use in a particular context,\n * based on the `data` argument. This method is called during the opening phase of the window’s\n * lifecycle.\n *\n * Override this method to add additional steps to the ‘setup’ process the parent method provides\n * using the {@link OO.ui.Process#first first} and {@link OO.ui.Process#next next} methods\n * of OO.ui.Process.\n *\n * To add window content that persists between openings, you may wish to use the #initialize method\n * instead.\n *\n * @param {Object} [data] Window opening data\n * @return {OO.ui.Process} Setup process\n */\nOO.ui.Window.prototype.getSetupProcess = function () {\n\treturn new OO.ui.Process();\n};\n\n/**\n * Get the ‘ready’ process.\n *\n * The ready process is used to ready a window for use in a particular\n * context, based on the `data` argument. This method is called during the opening phase of\n * the window’s lifecycle, after the window has been {@link #getSetupProcess setup}.\n *\n * Override this method to add additional steps to the ‘ready’ process the parent method\n * provides using the {@link OO.ui.Process#first first} and {@link OO.ui.Process#next next}\n * methods of OO.ui.Process.\n *\n * @param {Object} [data] Window opening data\n * @return {OO.ui.Process} Ready process\n */\nOO.ui.Window.prototype.getReadyProcess = function () {\n\treturn new OO.ui.Process();\n};\n\n/**\n * Get the 'hold' process.\n *\n * The hold process is used to keep a window from being used in a particular context,\n * based on the `data` argument. This method is called during the closing phase of the window’s\n * lifecycle.\n *\n * Override this method to add additional steps to the 'hold' process the parent method provides\n * using the {@link OO.ui.Process#first first} and {@link OO.ui.Process#next next} methods\n * of OO.ui.Process.\n *\n * @param {Object} [data] Window closing data\n * @return {OO.ui.Process} Hold process\n */\nOO.ui.Window.prototype.getHoldProcess = function () {\n\treturn new OO.ui.Process();\n};\n\n/**\n * Get the ‘teardown’ process.\n *\n * The teardown process is used to teardown a window after use. During teardown,\n * user interactions within the window are conveyed and the window is closed, based on the `data`\n * argument. This method is called during the closing phase of the window’s lifecycle.\n *\n * Override this method to add additional steps to the ‘teardown’ process the parent method provides\n * using the {@link OO.ui.Process#first first} and {@link OO.ui.Process#next next} methods\n * of OO.ui.Process.\n *\n * @param {Object} [data] Window closing data\n * @return {OO.ui.Process} Teardown process\n */\nOO.ui.Window.prototype.getTeardownProcess = function () {\n\treturn new OO.ui.Process();\n};\n\n/**\n * Set the window manager.\n *\n * This will cause the window to initialize. Calling it more than once will cause an error.\n *\n * @param {OO.ui.WindowManager} manager Manager for this window\n * @throws {Error} An error is thrown if the method is called more than once\n * @chainable\n */\nOO.ui.Window.prototype.setManager = function ( manager ) {\n\tif ( this.manager ) {\n\t\tthrow new Error( 'Cannot set window manager, window already has a manager' );\n\t}\n\n\tthis.manager = manager;\n\tthis.initialize();\n\n\treturn this;\n};\n\n/**\n * Set the window size by symbolic name (e.g., 'small' or 'medium')\n *\n * @param {string} size Symbolic name of size: `small`, `medium`, `large`, `larger` or\n * `full`\n * @chainable\n */\nOO.ui.Window.prototype.setSize = function ( size ) {\n\tthis.size = size;\n\tthis.updateSize();\n\treturn this;\n};\n\n/**\n * Update the window size.\n *\n * @throws {Error} An error is thrown if the window is not attached to a window manager\n * @chainable\n */\nOO.ui.Window.prototype.updateSize = function () {\n\tif ( !this.manager ) {\n\t\tthrow new Error( 'Cannot update window size, must be attached to a manager' );\n\t}\n\n\tthis.manager.updateWindowSize( this );\n\n\treturn this;\n};\n\n/**\n * Set window dimensions. This method is called by the {@link OO.ui.WindowManager window manager}\n * when the window is opening. In general, setDimensions should not be called directly.\n *\n * To set the size of the window, use the #setSize method.\n *\n * @param {Object} dim CSS dimension properties\n * @param {string|number} [dim.width] Width\n * @param {string|number} [dim.minWidth] Minimum width\n * @param {string|number} [dim.maxWidth] Maximum width\n * @param {string|number} [dim.height] Height, omit to set based on height of contents\n * @param {string|number} [dim.minHeight] Minimum height\n * @param {string|number} [dim.maxHeight] Maximum height\n * @chainable\n */\nOO.ui.Window.prototype.setDimensions = function ( dim ) {\n\tvar height,\n\t\twin = this,\n\t\tstyleObj = this.$frame[ 0 ].style;\n\n\t// Calculate the height we need to set using the correct width\n\tif ( dim.height === undefined ) {\n\t\tthis.withoutSizeTransitions( function () {\n\t\t\tvar oldWidth = styleObj.width;\n\t\t\twin.$frame.css( 'width', dim.width || '' );\n\t\t\theight = win.getContentHeight();\n\t\t\tstyleObj.width = oldWidth;\n\t\t} );\n\t} else {\n\t\theight = dim.height;\n\t}\n\n\tthis.$frame.css( {\n\t\twidth: dim.width || '',\n\t\tminWidth: dim.minWidth || '',\n\t\tmaxWidth: dim.maxWidth || '',\n\t\theight: height || '',\n\t\tminHeight: dim.minHeight || '',\n\t\tmaxHeight: dim.maxHeight || ''\n\t} );\n\n\treturn this;\n};\n\n/**\n * Initialize window contents.\n *\n * Before the window is opened for the first time, #initialize is called so that content that\n * persists between openings can be added to the window.\n *\n * To set up a window with new content each time the window opens, use #getSetupProcess.\n *\n * @throws {Error} An error is thrown if the window is not attached to a window manager\n * @chainable\n */\nOO.ui.Window.prototype.initialize = function () {\n\tif ( !this.manager ) {\n\t\tthrow new Error( 'Cannot initialize window, must be attached to a manager' );\n\t}\n\n\t// Properties\n\tthis.$head = $( '<div>' );\n\tthis.$body = $( '<div>' );\n\tthis.$foot = $( '<div>' );\n\tthis.$document = $( this.getElementDocument() );\n\n\t// Events\n\tthis.$element.on( 'mousedown', this.onMouseDown.bind( this ) );\n\n\t// Initialization\n\tthis.$head.addClass( 'oo-ui-window-head' );\n\tthis.$body.addClass( 'oo-ui-window-body' );\n\tthis.$foot.addClass( 'oo-ui-window-foot' );\n\tthis.$content.append( this.$head, this.$body, this.$foot );\n\n\treturn this;\n};\n\n/**\n * Called when someone tries to focus the hidden element at the end of the dialog.\n * Sends focus back to the start of the dialog.\n *\n * @param {jQuery.Event} event Focus event\n */\nOO.ui.Window.prototype.onFocusTrapFocused = function ( event ) {\n\tvar backwards = this.$focusTrapBefore.is( event.target ),\n\t\telement = OO.ui.findFocusable( this.$content, backwards );\n\tif ( element ) {\n\t\t// There's a focusable element inside the content, at the front or\n\t\t// back depending on which focus trap we hit; select it.\n\t\telement.focus();\n\t} else {\n\t\t// There's nothing focusable inside the content. As a fallback,\n\t\t// this.$content is focusable, and focusing it will keep our focus\n\t\t// properly trapped. It's not a *meaningful* focus, since it's just\n\t\t// the content-div for the Window, but it's better than letting focus\n\t\t// escape into the page.\n\t\tthis.$content.focus();\n\t}\n};\n\n/**\n * Open the window.\n *\n * This method is a wrapper around a call to the window manager’s {@link OO.ui.WindowManager#openWindow openWindow}\n * method, which returns a promise resolved when the window is done opening.\n *\n * To customize the window each time it opens, use #getSetupProcess or #getReadyProcess.\n *\n * @param {Object} [data] Window opening data\n * @return {jQuery.Promise} Promise resolved with a value when the window is opened, or rejected\n * if the window fails to open. When the promise is resolved successfully, the first argument of the\n * value is a new promise, which is resolved when the window begins closing.\n * @throws {Error} An error is thrown if the window is not attached to a window manager\n */\nOO.ui.Window.prototype.open = function ( data ) {\n\tif ( !this.manager ) {\n\t\tthrow new Error( 'Cannot open window, must be attached to a manager' );\n\t}\n\n\treturn this.manager.openWindow( this, data );\n};\n\n/**\n * Close the window.\n *\n * This method is a wrapper around a call to the window\n * manager’s {@link OO.ui.WindowManager#closeWindow closeWindow} method,\n * which returns a closing promise resolved when the window is done closing.\n *\n * The window's #getHoldProcess and #getTeardownProcess methods are called during the closing\n * phase of the window’s lifecycle and can be used to specify closing behavior each time\n * the window closes.\n *\n * @param {Object} [data] Window closing data\n * @return {jQuery.Promise} Promise resolved when window is closed\n * @throws {Error} An error is thrown if the window is not attached to a window manager\n */\nOO.ui.Window.prototype.close = function ( data ) {\n\tif ( !this.manager ) {\n\t\tthrow new Error( 'Cannot close window, must be attached to a manager' );\n\t}\n\n\treturn this.manager.closeWindow( this, data );\n};\n\n/**\n * Setup window.\n *\n * This is called by OO.ui.WindowManager during window opening, and should not be called directly\n * by other systems.\n *\n * @param {Object} [data] Window opening data\n * @return {jQuery.Promise} Promise resolved when window is setup\n */\nOO.ui.Window.prototype.setup = function ( data ) {\n\tvar win = this;\n\n\tthis.toggle( true );\n\n\tthis.focusTrapHandler = OO.ui.bind( this.onFocusTrapFocused, this );\n\tthis.$focusTraps.on( 'focus', this.focusTrapHandler );\n\n\treturn this.getSetupProcess( data ).execute().then( function () {\n\t\t// Force redraw by asking the browser to measure the elements' widths\n\t\twin.$element.addClass( 'oo-ui-window-active oo-ui-window-setup' ).width();\n\t\twin.$content.addClass( 'oo-ui-window-content-setup' ).width();\n\t} );\n};\n\n/**\n * Ready window.\n *\n * This is called by OO.ui.WindowManager during window opening, and should not be called directly\n * by other systems.\n *\n * @param {Object} [data] Window opening data\n * @return {jQuery.Promise} Promise resolved when window is ready\n */\nOO.ui.Window.prototype.ready = function ( data ) {\n\tvar win = this;\n\n\tthis.$content.focus();\n\treturn this.getReadyProcess( data ).execute().then( function () {\n\t\t// Force redraw by asking the browser to measure the elements' widths\n\t\twin.$element.addClass( 'oo-ui-window-ready' ).width();\n\t\twin.$content.addClass( 'oo-ui-window-content-ready' ).width();\n\t} );\n};\n\n/**\n * Hold window.\n *\n * This is called by OO.ui.WindowManager during window closing, and should not be called directly\n * by other systems.\n *\n * @param {Object} [data] Window closing data\n * @return {jQuery.Promise} Promise resolved when window is held\n */\nOO.ui.Window.prototype.hold = function ( data ) {\n\tvar win = this;\n\n\treturn this.getHoldProcess( data ).execute().then( function () {\n\t\t// Get the focused element within the window's content\n\t\tvar $focus = win.$content.find( OO.ui.Element.static.getDocument( win.$content ).activeElement );\n\n\t\t// Blur the focused element\n\t\tif ( $focus.length ) {\n\t\t\t$focus[ 0 ].blur();\n\t\t}\n\n\t\t// Force redraw by asking the browser to measure the elements' widths\n\t\twin.$element.removeClass( 'oo-ui-window-ready' ).width();\n\t\twin.$content.removeClass( 'oo-ui-window-content-ready' ).width();\n\t} );\n};\n\n/**\n * Teardown window.\n *\n * This is called by OO.ui.WindowManager during window closing, and should not be called directly\n * by other systems.\n *\n * @param {Object} [data] Window closing data\n * @return {jQuery.Promise} Promise resolved when window is torn down\n */\nOO.ui.Window.prototype.teardown = function ( data ) {\n\tvar win = this;\n\n\treturn this.getTeardownProcess( data ).execute().then( function () {\n\t\t// Force redraw by asking the browser to measure the elements' widths\n\t\twin.$element.removeClass( 'oo-ui-window-active oo-ui-window-setup' ).width();\n\t\twin.$content.removeClass( 'oo-ui-window-content-setup' ).width();\n\t\twin.$focusTraps.off( 'focus', win.focusTrapHandler );\n\t\twin.toggle( false );\n\t} );\n};\n","/**\n * The Dialog class serves as the base class for the other types of dialogs.\n * Unless extended to include controls, the rendered dialog box is a simple window\n * that users can close by hitting the ‘Esc’ key. Dialog windows are used with OO.ui.WindowManager,\n * which opens, closes, and controls the presentation of the window. See the\n * [OOjs UI documentation on MediaWiki] [1] for more information.\n *\n * @example\n * // A simple dialog window.\n * function MyDialog( config ) {\n * MyDialog.parent.call( this, config );\n * }\n * OO.inheritClass( MyDialog, OO.ui.Dialog );\n * MyDialog.static.name = 'myDialog';\n * MyDialog.prototype.initialize = function () {\n * MyDialog.parent.prototype.initialize.call( this );\n * this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );\n * this.content.$element.append( '<p>A simple dialog window. Press \\'Esc\\' to close.</p>' );\n * this.$body.append( this.content.$element );\n * };\n * MyDialog.prototype.getBodyHeight = function () {\n * return this.content.$element.outerHeight( true );\n * };\n * var myDialog = new MyDialog( {\n * size: 'medium'\n * } );\n * // Create and append a window manager, which opens and closes the window.\n * var windowManager = new OO.ui.WindowManager();\n * $( 'body' ).append( windowManager.$element );\n * windowManager.addWindows( [ myDialog ] );\n * // Open the window!\n * windowManager.openWindow( myDialog );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Dialogs\n *\n * @abstract\n * @class\n * @extends OO.ui.Window\n * @mixins OO.ui.mixin.PendingElement\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.Dialog = function OoUiDialog( config ) {\n\t// Parent constructor\n\tOO.ui.Dialog.parent.call( this, config );\n\n\t// Mixin constructors\n\tOO.ui.mixin.PendingElement.call( this );\n\n\t// Properties\n\tthis.actions = new OO.ui.ActionSet();\n\tthis.attachedActions = [];\n\tthis.currentAction = null;\n\tthis.onDialogKeyDownHandler = this.onDialogKeyDown.bind( this );\n\n\t// Events\n\tthis.actions.connect( this, {\n\t\tclick: 'onActionClick',\n\t\tchange: 'onActionsChange'\n\t} );\n\n\t// Initialization\n\tthis.$element\n\t\t.addClass( 'oo-ui-dialog' )\n\t\t.attr( 'role', 'dialog' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.Dialog, OO.ui.Window );\nOO.mixinClass( OO.ui.Dialog, OO.ui.mixin.PendingElement );\n\n/* Static Properties */\n\n/**\n * Symbolic name of dialog.\n *\n * The dialog class must have a symbolic name in order to be registered with OO.Factory.\n * Please see the [OOjs UI documentation on MediaWiki] [3] for more information.\n *\n * [3]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Window_managers\n *\n * @abstract\n * @static\n * @inheritable\n * @property {string}\n */\nOO.ui.Dialog.static.name = '';\n\n/**\n * The dialog title.\n *\n * The title can be specified as a plaintext string, a {@link OO.ui.mixin.LabelElement Label} node, or a function\n * that will produce a Label node or string. The title can also be specified with data passed to the\n * constructor (see #getSetupProcess). In this case, the static value will be overridden.\n *\n * @abstract\n * @static\n * @inheritable\n * @property {jQuery|string|Function}\n */\nOO.ui.Dialog.static.title = '';\n\n/**\n * An array of configured {@link OO.ui.ActionWidget action widgets}.\n *\n * Actions can also be specified with data passed to the constructor (see #getSetupProcess). In this case, the static\n * value will be overridden.\n *\n * [2]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs#Action_sets\n *\n * @static\n * @inheritable\n * @property {Object[]}\n */\nOO.ui.Dialog.static.actions = [];\n\n/**\n * Close the dialog when the 'Esc' key is pressed.\n *\n * @static\n * @abstract\n * @inheritable\n * @property {boolean}\n */\nOO.ui.Dialog.static.escapable = true;\n\n/* Methods */\n\n/**\n * Handle frame document key down events.\n *\n * @private\n * @param {jQuery.Event} e Key down event\n */\nOO.ui.Dialog.prototype.onDialogKeyDown = function ( e ) {\n\tvar actions;\n\tif ( e.which === OO.ui.Keys.ESCAPE && this.constructor.static.escapable ) {\n\t\tthis.executeAction( '' );\n\t\te.preventDefault();\n\t\te.stopPropagation();\n\t} else if ( e.which === OO.ui.Keys.ENTER && ( e.ctrlKey || e.metaKey ) ) {\n\t\tactions = this.actions.get( { flags: 'primary', visible: true, disabled: false } );\n\t\tif ( actions.length > 0 ) {\n\t\t\tthis.executeAction( actions[ 0 ].getAction() );\n\t\t\te.preventDefault();\n\t\t\te.stopPropagation();\n\t\t}\n\t}\n};\n\n/**\n * Handle action click events.\n *\n * @private\n * @param {OO.ui.ActionWidget} action Action that was clicked\n */\nOO.ui.Dialog.prototype.onActionClick = function ( action ) {\n\tif ( !this.isPending() ) {\n\t\tthis.executeAction( action.getAction() );\n\t}\n};\n\n/**\n * Handle actions change event.\n *\n * @private\n */\nOO.ui.Dialog.prototype.onActionsChange = function () {\n\tthis.detachActions();\n\tif ( !this.isClosing() ) {\n\t\tthis.attachActions();\n\t}\n};\n\n/**\n * Get the set of actions used by the dialog.\n *\n * @return {OO.ui.ActionSet}\n */\nOO.ui.Dialog.prototype.getActions = function () {\n\treturn this.actions;\n};\n\n/**\n * Get a process for taking action.\n *\n * When you override this method, you can create a new OO.ui.Process and return it, or add additional\n * accept steps to the process the parent method provides using the {@link OO.ui.Process#first 'first'}\n * and {@link OO.ui.Process#next 'next'} methods of OO.ui.Process.\n *\n * @param {string} [action] Symbolic name of action\n * @return {OO.ui.Process} Action process\n */\nOO.ui.Dialog.prototype.getActionProcess = function ( action ) {\n\treturn new OO.ui.Process()\n\t\t.next( function () {\n\t\t\tif ( !action ) {\n\t\t\t\t// An empty action always closes the dialog without data, which should always be\n\t\t\t\t// safe and make no changes\n\t\t\t\tthis.close();\n\t\t\t}\n\t\t}, this );\n};\n\n/**\n * @inheritdoc\n *\n * @param {Object} [data] Dialog opening data\n * @param {jQuery|string|Function|null} [data.title] Dialog title, omit to use\n * the {@link #static-title static title}\n * @param {Object[]} [data.actions] List of configuration options for each\n * {@link OO.ui.ActionWidget action widget}, omit to use {@link #static-actions static actions}.\n */\nOO.ui.Dialog.prototype.getSetupProcess = function ( data ) {\n\tdata = data || {};\n\n\t// Parent method\n\treturn OO.ui.Dialog.parent.prototype.getSetupProcess.call( this, data )\n\t\t.next( function () {\n\t\t\tvar config = this.constructor.static,\n\t\t\t\tactions = data.actions !== undefined ? data.actions : config.actions,\n\t\t\t\ttitle = data.title !== undefined ? data.title : config.title;\n\n\t\t\tthis.title.setLabel( title ).setTitle( title );\n\t\t\tthis.actions.add( this.getActionWidgets( actions ) );\n\n\t\t\tthis.$element.on( 'keydown', this.onDialogKeyDownHandler );\n\t\t}, this );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.Dialog.prototype.getTeardownProcess = function ( data ) {\n\t// Parent method\n\treturn OO.ui.Dialog.parent.prototype.getTeardownProcess.call( this, data )\n\t\t.first( function () {\n\t\t\tthis.$element.off( 'keydown', this.onDialogKeyDownHandler );\n\n\t\t\tthis.actions.clear();\n\t\t\tthis.currentAction = null;\n\t\t}, this );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.Dialog.prototype.initialize = function () {\n\t// Parent method\n\tOO.ui.Dialog.parent.prototype.initialize.call( this );\n\n\t// Properties\n\tthis.title = new OO.ui.LabelWidget();\n\n\t// Initialization\n\tthis.$content.addClass( 'oo-ui-dialog-content' );\n\tthis.$element.attr( 'aria-labelledby', this.title.getElementId() );\n\tthis.setPendingElement( this.$head );\n};\n\n/**\n * Get action widgets from a list of configs\n *\n * @param {Object[]} actions Action widget configs\n * @return {OO.ui.ActionWidget[]} Action widgets\n */\nOO.ui.Dialog.prototype.getActionWidgets = function ( actions ) {\n\tvar i, len, widgets = [];\n\tfor ( i = 0, len = actions.length; i < len; i++ ) {\n\t\twidgets.push(\n\t\t\tnew OO.ui.ActionWidget( actions[ i ] )\n\t\t);\n\t}\n\treturn widgets;\n};\n\n/**\n * Attach action actions.\n *\n * @protected\n */\nOO.ui.Dialog.prototype.attachActions = function () {\n\t// Remember the list of potentially attached actions\n\tthis.attachedActions = this.actions.get();\n};\n\n/**\n * Detach action actions.\n *\n * @protected\n * @chainable\n */\nOO.ui.Dialog.prototype.detachActions = function () {\n\tvar i, len;\n\n\t// Detach all actions that may have been previously attached\n\tfor ( i = 0, len = this.attachedActions.length; i < len; i++ ) {\n\t\tthis.attachedActions[ i ].$element.detach();\n\t}\n\tthis.attachedActions = [];\n};\n\n/**\n * Execute an action.\n *\n * @param {string} action Symbolic name of action to execute\n * @return {jQuery.Promise} Promise resolved when action completes, rejected if it fails\n */\nOO.ui.Dialog.prototype.executeAction = function ( action ) {\n\tthis.pushPending();\n\tthis.currentAction = action;\n\treturn this.getActionProcess( action ).execute()\n\t\t.always( this.popPending.bind( this ) );\n};\n","/**\n * MessageDialogs display a confirmation or alert message. By default, the rendered dialog box\n * consists of a header that contains the dialog title, a body with the message, and a footer that\n * contains any {@link OO.ui.ActionWidget action widgets}. The MessageDialog class is the only type\n * of {@link OO.ui.Dialog dialog} that is usually instantiated directly.\n *\n * There are two basic types of message dialogs, confirmation and alert:\n *\n * - **confirmation**: the dialog title describes what a progressive action will do and the message provides\n * more details about the consequences.\n * - **alert**: the dialog title describes which event occurred and the message provides more information\n * about why the event occurred.\n *\n * The MessageDialog class specifies two actions: ‘accept’, the primary\n * action (e.g., ‘ok’) and ‘reject,’ the safe action (e.g., ‘cancel’). Both will close the window,\n * passing along the selected action.\n *\n * For more information and examples, please see the [OOjs UI documentation on MediaWiki][1].\n *\n * @example\n * // Example: Creating and opening a message dialog window.\n * var messageDialog = new OO.ui.MessageDialog();\n *\n * // Create and append a window manager.\n * var windowManager = new OO.ui.WindowManager();\n * $( 'body' ).append( windowManager.$element );\n * windowManager.addWindows( [ messageDialog ] );\n * // Open the window.\n * windowManager.openWindow( messageDialog, {\n * title: 'Basic message dialog',\n * message: 'This is the message'\n * } );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Message_Dialogs\n *\n * @class\n * @extends OO.ui.Dialog\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.MessageDialog = function OoUiMessageDialog( config ) {\n\t// Parent constructor\n\tOO.ui.MessageDialog.parent.call( this, config );\n\n\t// Properties\n\tthis.verticalActionLayout = null;\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-messageDialog' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.MessageDialog, OO.ui.Dialog );\n\n/* Static Properties */\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.MessageDialog.static.name = 'message';\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.MessageDialog.static.size = 'small';\n\n/**\n * Dialog title.\n *\n * The title of a confirmation dialog describes what a progressive action will do. The\n * title of an alert dialog describes which event occurred.\n *\n * @static\n * @inheritable\n * @property {jQuery|string|Function|null}\n */\nOO.ui.MessageDialog.static.title = null;\n\n/**\n * The message displayed in the dialog body.\n *\n * A confirmation message describes the consequences of a progressive action. An alert\n * message describes why an event occurred.\n *\n * @static\n * @inheritable\n * @property {jQuery|string|Function|null}\n */\nOO.ui.MessageDialog.static.message = null;\n\n/**\n * @static\n * @inheritdoc\n */\nOO.ui.MessageDialog.static.actions = [\n\t// Note that OO.ui.alert() and OO.ui.confirm() rely on these.\n\t{ action: 'accept', label: OO.ui.deferMsg( 'ooui-dialog-message-accept' ), flags: 'primary' },\n\t{ action: 'reject', label: OO.ui.deferMsg( 'ooui-dialog-message-reject' ), flags: 'safe' }\n];\n\n/* Methods */\n\n/**\n * @inheritdoc\n */\nOO.ui.MessageDialog.prototype.setManager = function ( manager ) {\n\tOO.ui.MessageDialog.parent.prototype.setManager.call( this, manager );\n\n\t// Events\n\tthis.manager.connect( this, {\n\t\tresize: 'onResize'\n\t} );\n\n\treturn this;\n};\n\n/**\n * Handle window resized events.\n *\n * @private\n */\nOO.ui.MessageDialog.prototype.onResize = function () {\n\tvar dialog = this;\n\tdialog.fitActions();\n\t// Wait for CSS transition to finish and do it again :(\n\tsetTimeout( function () {\n\t\tdialog.fitActions();\n\t}, 300 );\n};\n\n/**\n * Toggle action layout between vertical and horizontal.\n *\n * @private\n * @param {boolean} [value] Layout actions vertically, omit to toggle\n * @chainable\n */\nOO.ui.MessageDialog.prototype.toggleVerticalActionLayout = function ( value ) {\n\tvalue = value === undefined ? !this.verticalActionLayout : !!value;\n\n\tif ( value !== this.verticalActionLayout ) {\n\t\tthis.verticalActionLayout = value;\n\t\tthis.$actions\n\t\t\t.toggleClass( 'oo-ui-messageDialog-actions-vertical', value )\n\t\t\t.toggleClass( 'oo-ui-messageDialog-actions-horizontal', !value );\n\t}\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MessageDialog.prototype.getActionProcess = function ( action ) {\n\tif ( action ) {\n\t\treturn new OO.ui.Process( function () {\n\t\t\tthis.close( { action: action } );\n\t\t}, this );\n\t}\n\treturn OO.ui.MessageDialog.parent.prototype.getActionProcess.call( this, action );\n};\n\n/**\n * @inheritdoc\n *\n * @param {Object} [data] Dialog opening data\n * @param {jQuery|string|Function|null} [data.title] Description of the action being confirmed\n * @param {jQuery|string|Function|null} [data.message] Description of the action's consequence\n * @param {string} [data.size] Symbolic name of the dialog size, see OO.ui.Window\n * @param {Object[]} [data.actions] List of OO.ui.ActionOptionWidget configuration options for each\n * action item\n */\nOO.ui.MessageDialog.prototype.getSetupProcess = function ( data ) {\n\tdata = data || {};\n\n\t// Parent method\n\treturn OO.ui.MessageDialog.parent.prototype.getSetupProcess.call( this, data )\n\t\t.next( function () {\n\t\t\tthis.title.setLabel(\n\t\t\t\tdata.title !== undefined ? data.title : this.constructor.static.title\n\t\t\t);\n\t\t\tthis.message.setLabel(\n\t\t\t\tdata.message !== undefined ? data.message : this.constructor.static.message\n\t\t\t);\n\t\t\tthis.size = data.size !== undefined ? data.size : this.constructor.static.size;\n\t\t}, this );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MessageDialog.prototype.getReadyProcess = function ( data ) {\n\tdata = data || {};\n\n\t// Parent method\n\treturn OO.ui.MessageDialog.parent.prototype.getReadyProcess.call( this, data )\n\t\t.next( function () {\n\t\t\t// Focus the primary action button\n\t\t\tvar actions = this.actions.get();\n\t\t\tactions = actions.filter( function ( action ) {\n\t\t\t\treturn action.getFlags().indexOf( 'primary' ) > -1;\n\t\t\t} );\n\t\t\tif ( actions.length > 0 ) {\n\t\t\t\tactions[ 0 ].focus();\n\t\t\t}\n\t\t}, this );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MessageDialog.prototype.getBodyHeight = function () {\n\tvar bodyHeight, oldOverflow,\n\t\t$scrollable = this.container.$element;\n\n\toldOverflow = $scrollable[ 0 ].style.overflow;\n\t$scrollable[ 0 ].style.overflow = 'hidden';\n\n\tOO.ui.Element.static.reconsiderScrollbars( $scrollable[ 0 ] );\n\n\tbodyHeight = this.text.$element.outerHeight( true );\n\t$scrollable[ 0 ].style.overflow = oldOverflow;\n\n\treturn bodyHeight;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MessageDialog.prototype.setDimensions = function ( dim ) {\n\tvar $scrollable = this.container.$element;\n\tOO.ui.MessageDialog.parent.prototype.setDimensions.call( this, dim );\n\n\t// Twiddle the overflow property, otherwise an unnecessary scrollbar will be produced.\n\t// Need to do it after transition completes (250ms), add 50ms just in case.\n\tsetTimeout( function () {\n\t\tvar oldOverflow = $scrollable[ 0 ].style.overflow,\n\t\t\tactiveElement = document.activeElement;\n\n\t\t$scrollable[ 0 ].style.overflow = 'hidden';\n\n\t\tOO.ui.Element.static.reconsiderScrollbars( $scrollable[ 0 ] );\n\n\t\t// Check reconsiderScrollbars didn't destroy our focus, as we\n\t\t// are doing this after the ready process.\n\t\tif ( activeElement && activeElement !== document.activeElement && activeElement.focus ) {\n\t\t\tactiveElement.focus();\n\t\t}\n\n\t\t$scrollable[ 0 ].style.overflow = oldOverflow;\n\t}, 300 );\n\n\treturn this;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MessageDialog.prototype.initialize = function () {\n\t// Parent method\n\tOO.ui.MessageDialog.parent.prototype.initialize.call( this );\n\n\t// Properties\n\tthis.$actions = $( '<div>' );\n\tthis.container = new OO.ui.PanelLayout( {\n\t\tscrollable: true, classes: [ 'oo-ui-messageDialog-container' ]\n\t} );\n\tthis.text = new OO.ui.PanelLayout( {\n\t\tpadded: true, expanded: false, classes: [ 'oo-ui-messageDialog-text' ]\n\t} );\n\tthis.message = new OO.ui.LabelWidget( {\n\t\tclasses: [ 'oo-ui-messageDialog-message' ]\n\t} );\n\n\t// Initialization\n\tthis.title.$element.addClass( 'oo-ui-messageDialog-title' );\n\tthis.$content.addClass( 'oo-ui-messageDialog-content' );\n\tthis.container.$element.append( this.text.$element );\n\tthis.text.$element.append( this.title.$element, this.message.$element );\n\tthis.$body.append( this.container.$element );\n\tthis.$actions.addClass( 'oo-ui-messageDialog-actions' );\n\tthis.$foot.append( this.$actions );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.MessageDialog.prototype.attachActions = function () {\n\tvar i, len, other, special, others;\n\n\t// Parent method\n\tOO.ui.MessageDialog.parent.prototype.attachActions.call( this );\n\n\tspecial = this.actions.getSpecial();\n\tothers = this.actions.getOthers();\n\n\tif ( special.safe ) {\n\t\tthis.$actions.append( special.safe.$element );\n\t\tspecial.safe.toggleFramed( false );\n\t}\n\tif ( others.length ) {\n\t\tfor ( i = 0, len = others.length; i < len; i++ ) {\n\t\t\tother = others[ i ];\n\t\t\tthis.$actions.append( other.$element );\n\t\t\tother.toggleFramed( false );\n\t\t}\n\t}\n\tif ( special.primary ) {\n\t\tthis.$actions.append( special.primary.$element );\n\t\tspecial.primary.toggleFramed( false );\n\t}\n\n\tif ( !this.isOpening() ) {\n\t\t// If the dialog is currently opening, this will be called automatically soon.\n\t\t// This also calls #fitActions.\n\t\tthis.updateSize();\n\t}\n};\n\n/**\n * Fit action actions into columns or rows.\n *\n * Columns will be used if all labels can fit without overflow, otherwise rows will be used.\n *\n * @private\n */\nOO.ui.MessageDialog.prototype.fitActions = function () {\n\tvar i, len, action,\n\t\tprevious = this.verticalActionLayout,\n\t\tactions = this.actions.get();\n\n\t// Detect clipping\n\tthis.toggleVerticalActionLayout( false );\n\tfor ( i = 0, len = actions.length; i < len; i++ ) {\n\t\taction = actions[ i ];\n\t\tif ( action.$element.innerWidth() < action.$label.outerWidth( true ) ) {\n\t\t\tthis.toggleVerticalActionLayout( true );\n\t\t\tbreak;\n\t\t}\n\t}\n\n\t// Move the body out of the way of the foot\n\tthis.$body.css( 'bottom', this.$foot.outerHeight( true ) );\n\n\tif ( this.verticalActionLayout !== previous ) {\n\t\t// We changed the layout, window height might need to be updated.\n\t\tthis.updateSize();\n\t}\n};\n","/**\n * ProcessDialog windows encapsulate a {@link OO.ui.Process process} and all of the code necessary\n * to complete it. If the process terminates with an error, a customizable {@link OO.ui.Error error\n * interface} alerts users to the trouble, permitting the user to dismiss the error and try again when\n * relevant. The ProcessDialog class is always extended and customized with the actions and content\n * required for each process.\n *\n * The process dialog box consists of a header that visually represents the ‘working’ state of long\n * processes with an animation. The header contains the dialog title as well as\n * two {@link OO.ui.ActionWidget action widgets}: a ‘safe’ action on the left (e.g., ‘Cancel’) and\n * a ‘primary’ action on the right (e.g., ‘Done’).\n *\n * Like other windows, the process dialog is managed by a {@link OO.ui.WindowManager window manager}.\n * Please see the [OOjs UI documentation on MediaWiki][1] for more information and examples.\n *\n * @example\n * // Example: Creating and opening a process dialog window.\n * function MyProcessDialog( config ) {\n * MyProcessDialog.parent.call( this, config );\n * }\n * OO.inheritClass( MyProcessDialog, OO.ui.ProcessDialog );\n *\n * MyProcessDialog.static.name = 'myProcessDialog';\n * MyProcessDialog.static.title = 'Process dialog';\n * MyProcessDialog.static.actions = [\n * { action: 'save', label: 'Done', flags: 'primary' },\n * { label: 'Cancel', flags: 'safe' }\n * ];\n *\n * MyProcessDialog.prototype.initialize = function () {\n * MyProcessDialog.parent.prototype.initialize.apply( this, arguments );\n * this.content = new OO.ui.PanelLayout( { padded: true, expanded: false } );\n * this.content.$element.append( '<p>This is a process dialog window. The header contains the title and two buttons: \\'Cancel\\' (a safe action) on the left and \\'Done\\' (a primary action) on the right.</p>' );\n * this.$body.append( this.content.$element );\n * };\n * MyProcessDialog.prototype.getActionProcess = function ( action ) {\n * var dialog = this;\n * if ( action ) {\n * return new OO.ui.Process( function () {\n * dialog.close( { action: action } );\n * } );\n * }\n * return MyProcessDialog.parent.prototype.getActionProcess.call( this, action );\n * };\n *\n * var windowManager = new OO.ui.WindowManager();\n * $( 'body' ).append( windowManager.$element );\n *\n * var dialog = new MyProcessDialog();\n * windowManager.addWindows( [ dialog ] );\n * windowManager.openWindow( dialog );\n *\n * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Windows/Process_Dialogs\n *\n * @abstract\n * @class\n * @extends OO.ui.Dialog\n *\n * @constructor\n * @param {Object} [config] Configuration options\n */\nOO.ui.ProcessDialog = function OoUiProcessDialog( config ) {\n\t// Parent constructor\n\tOO.ui.ProcessDialog.parent.call( this, config );\n\n\t// Properties\n\tthis.fitOnOpen = false;\n\n\t// Initialization\n\tthis.$element.addClass( 'oo-ui-processDialog' );\n};\n\n/* Setup */\n\nOO.inheritClass( OO.ui.ProcessDialog, OO.ui.Dialog );\n\n/* Methods */\n\n/**\n * Handle dismiss button click events.\n *\n * Hides errors.\n *\n * @private\n */\nOO.ui.ProcessDialog.prototype.onDismissErrorButtonClick = function () {\n\tthis.hideErrors();\n};\n\n/**\n * Handle retry button click events.\n *\n * Hides errors and then tries again.\n *\n * @private\n */\nOO.ui.ProcessDialog.prototype.onRetryButtonClick = function () {\n\tthis.hideErrors();\n\tthis.executeAction( this.currentAction );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ProcessDialog.prototype.initialize = function () {\n\t// Parent method\n\tOO.ui.ProcessDialog.parent.prototype.initialize.call( this );\n\n\t// Properties\n\tthis.$navigation = $( '<div>' );\n\tthis.$location = $( '<div>' );\n\tthis.$safeActions = $( '<div>' );\n\tthis.$primaryActions = $( '<div>' );\n\tthis.$otherActions = $( '<div>' );\n\tthis.dismissButton = new OO.ui.ButtonWidget( {\n\t\tlabel: OO.ui.msg( 'ooui-dialog-process-dismiss' )\n\t} );\n\tthis.retryButton = new OO.ui.ButtonWidget();\n\tthis.$errors = $( '<div>' );\n\tthis.$errorsTitle = $( '<div>' );\n\n\t// Events\n\tthis.dismissButton.connect( this, { click: 'onDismissErrorButtonClick' } );\n\tthis.retryButton.connect( this, { click: 'onRetryButtonClick' } );\n\n\t// Initialization\n\tthis.title.$element.addClass( 'oo-ui-processDialog-title' );\n\tthis.$location\n\t\t.append( this.title.$element )\n\t\t.addClass( 'oo-ui-processDialog-location' );\n\tthis.$safeActions.addClass( 'oo-ui-processDialog-actions-safe' );\n\tthis.$primaryActions.addClass( 'oo-ui-processDialog-actions-primary' );\n\tthis.$otherActions.addClass( 'oo-ui-processDialog-actions-other' );\n\tthis.$errorsTitle\n\t\t.addClass( 'oo-ui-processDialog-errors-title' )\n\t\t.text( OO.ui.msg( 'ooui-dialog-process-error' ) );\n\tthis.$errors\n\t\t.addClass( 'oo-ui-processDialog-errors oo-ui-element-hidden' )\n\t\t.append( this.$errorsTitle, this.dismissButton.$element, this.retryButton.$element );\n\tthis.$content\n\t\t.addClass( 'oo-ui-processDialog-content' )\n\t\t.append( this.$errors );\n\tthis.$navigation\n\t\t.addClass( 'oo-ui-processDialog-navigation' )\n\t\t// Note: Order of appends below is important. These are in the order\n\t\t// we want tab to go through them. Display-order is handled entirely\n\t\t// by CSS absolute-positioning. As such, primary actions like \"done\"\n\t\t// should go first.\n\t\t.append( this.$primaryActions, this.$location, this.$safeActions );\n\tthis.$head.append( this.$navigation );\n\tthis.$foot.append( this.$otherActions );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ProcessDialog.prototype.getActionWidgets = function ( actions ) {\n\tvar i, len, config,\n\t\tisMobile = OO.ui.isMobile(),\n\t\twidgets = [];\n\n\tfor ( i = 0, len = actions.length; i < len; i++ ) {\n\t\tconfig = $.extend( { framed: !OO.ui.isMobile() }, actions[ i ] );\n\t\tif ( isMobile &&\n\t\t\t( config.flags === 'back' || ( Array.isArray( config.flags ) && config.flags.indexOf( 'back' ) !== -1 ) )\n\t\t) {\n\t\t\t$.extend( config, {\n\t\t\t\ticon: 'previous',\n\t\t\t\tlabel: ''\n\t\t\t} );\n\t\t}\n\t\twidgets.push(\n\t\t\tnew OO.ui.ActionWidget( config )\n\t\t);\n\t}\n\treturn widgets;\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ProcessDialog.prototype.attachActions = function () {\n\tvar i, len, other, special, others;\n\n\t// Parent method\n\tOO.ui.ProcessDialog.parent.prototype.attachActions.call( this );\n\n\tspecial = this.actions.getSpecial();\n\tothers = this.actions.getOthers();\n\tif ( special.primary ) {\n\t\tthis.$primaryActions.append( special.primary.$element );\n\t}\n\tfor ( i = 0, len = others.length; i < len; i++ ) {\n\t\tother = others[ i ];\n\t\tthis.$otherActions.append( other.$element );\n\t}\n\tif ( special.safe ) {\n\t\tthis.$safeActions.append( special.safe.$element );\n\t}\n\n\tthis.fitLabel();\n\tthis.$body.css( 'bottom', this.$foot.outerHeight( true ) );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ProcessDialog.prototype.executeAction = function ( action ) {\n\tvar process = this;\n\treturn OO.ui.ProcessDialog.parent.prototype.executeAction.call( this, action )\n\t\t.fail( function ( errors ) {\n\t\t\tprocess.showErrors( errors || [] );\n\t\t} );\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ProcessDialog.prototype.setDimensions = function () {\n\t// Parent method\n\tOO.ui.ProcessDialog.parent.prototype.setDimensions.apply( this, arguments );\n\n\tthis.fitLabel();\n};\n\n/**\n * Fit label between actions.\n *\n * @private\n * @chainable\n */\nOO.ui.ProcessDialog.prototype.fitLabel = function () {\n\tvar safeWidth, primaryWidth, biggerWidth, labelWidth, navigationWidth, leftWidth, rightWidth,\n\t\tsize = this.getSizeProperties();\n\n\tif ( typeof size.width !== 'number' ) {\n\t\tif ( this.isOpened() ) {\n\t\t\tnavigationWidth = this.$head.width() - 20;\n\t\t} else if ( this.isOpening() ) {\n\t\t\tif ( !this.fitOnOpen ) {\n\t\t\t\t// Size is relative and the dialog isn't open yet, so wait.\n\t\t\t\t// FIXME: This should ideally be handled by setup somehow.\n\t\t\t\tthis.manager.lifecycle.opened.done( this.fitLabel.bind( this ) );\n\t\t\t\tthis.fitOnOpen = true;\n\t\t\t}\n\t\t\treturn;\n\t\t} else {\n\t\t\treturn;\n\t\t}\n\t} else {\n\t\tnavigationWidth = size.width - 20;\n\t}\n\n\tsafeWidth = this.$safeActions.is( ':visible' ) ? this.$safeActions.width() : 0;\n\tprimaryWidth = this.$primaryActions.is( ':visible' ) ? this.$primaryActions.width() : 0;\n\tbiggerWidth = Math.max( safeWidth, primaryWidth );\n\n\tlabelWidth = this.title.$element.width();\n\n\tif ( 2 * biggerWidth + labelWidth < navigationWidth ) {\n\t\t// We have enough space to center the label\n\t\tleftWidth = rightWidth = biggerWidth;\n\t} else {\n\t\t// Let's hope we at least have enough space not to overlap, because we can't wrap the label…\n\t\tif ( this.getDir() === 'ltr' ) {\n\t\t\tleftWidth = safeWidth;\n\t\t\trightWidth = primaryWidth;\n\t\t} else {\n\t\t\tleftWidth = primaryWidth;\n\t\t\trightWidth = safeWidth;\n\t\t}\n\t}\n\n\tthis.$location.css( { paddingLeft: leftWidth, paddingRight: rightWidth } );\n\n\treturn this;\n};\n\n/**\n * Handle errors that occurred during accept or reject processes.\n *\n * @private\n * @param {OO.ui.Error[]|OO.ui.Error} errors Errors to be handled\n */\nOO.ui.ProcessDialog.prototype.showErrors = function ( errors ) {\n\tvar i, len, $item, actions,\n\t\titems = [],\n\t\tabilities = {},\n\t\trecoverable = true,\n\t\twarning = false;\n\n\tif ( errors instanceof OO.ui.Error ) {\n\t\terrors = [ errors ];\n\t}\n\n\tfor ( i = 0, len = errors.length; i < len; i++ ) {\n\t\tif ( !errors[ i ].isRecoverable() ) {\n\t\t\trecoverable = false;\n\t\t}\n\t\tif ( errors[ i ].isWarning() ) {\n\t\t\twarning = true;\n\t\t}\n\t\t$item = $( '<div>' )\n\t\t\t.addClass( 'oo-ui-processDialog-error' )\n\t\t\t.append( errors[ i ].getMessage() );\n\t\titems.push( $item[ 0 ] );\n\t}\n\tthis.$errorItems = $( items );\n\tif ( recoverable ) {\n\t\tabilities[ this.currentAction ] = true;\n\t\t// Copy the flags from the first matching action\n\t\tactions = this.actions.get( { actions: this.currentAction } );\n\t\tif ( actions.length ) {\n\t\t\tthis.retryButton.clearFlags().setFlags( actions[ 0 ].getFlags() );\n\t\t}\n\t} else {\n\t\tabilities[ this.currentAction ] = false;\n\t\tthis.actions.setAbilities( abilities );\n\t}\n\tif ( warning ) {\n\t\tthis.retryButton.setLabel( OO.ui.msg( 'ooui-dialog-process-continue' ) );\n\t} else {\n\t\tthis.retryButton.setLabel( OO.ui.msg( 'ooui-dialog-process-retry' ) );\n\t}\n\tthis.retryButton.toggle( recoverable );\n\tthis.$errorsTitle.after( this.$errorItems );\n\tthis.$errors.removeClass( 'oo-ui-element-hidden' ).scrollTop( 0 );\n};\n\n/**\n * Hide errors.\n *\n * @private\n */\nOO.ui.ProcessDialog.prototype.hideErrors = function () {\n\tthis.$errors.addClass( 'oo-ui-element-hidden' );\n\tif ( this.$errorItems ) {\n\t\tthis.$errorItems.remove();\n\t\tthis.$errorItems = null;\n\t}\n};\n\n/**\n * @inheritdoc\n */\nOO.ui.ProcessDialog.prototype.getTeardownProcess = function ( data ) {\n\t// Parent method\n\treturn OO.ui.ProcessDialog.parent.prototype.getTeardownProcess.call( this, data )\n\t\t.first( function () {\n\t\t\t// Make sure to hide errors\n\t\t\tthis.hideErrors();\n\t\t\tthis.fitOnOpen = false;\n\t\t}, this );\n};\n","/**\n * @class OO.ui\n */\n\n/**\n * Lazy-initialize and return a global OO.ui.WindowManager instance, used by OO.ui.alert and\n * OO.ui.confirm.\n *\n * @private\n * @return {OO.ui.WindowManager}\n */\nOO.ui.getWindowManager = function () {\n\tif ( !OO.ui.windowManager ) {\n\t\tOO.ui.windowManager = new OO.ui.WindowManager();\n\t\t$( 'body' ).append( OO.ui.windowManager.$element );\n\t\tOO.ui.windowManager.addWindows( [ new OO.ui.MessageDialog() ] );\n\t}\n\treturn OO.ui.windowManager;\n};\n\n/**\n * Display a quick modal alert dialog, using a OO.ui.MessageDialog. While the dialog is open, the\n * rest of the page will be dimmed out and the user won't be able to interact with it. The dialog\n * has only one action button, labelled \"OK\", clicking it will simply close the dialog.\n *\n * A window manager is created automatically when this function is called for the first time.\n *\n * @example\n * OO.ui.alert( 'Something happened!' ).done( function () {\n * console.log( 'User closed the dialog.' );\n * } );\n *\n * OO.ui.alert( 'Something larger happened!', { size: 'large' } );\n *\n * @param {jQuery|string} text Message text to display\n * @param {Object} [options] Additional options, see OO.ui.MessageDialog#getSetupProcess\n * @return {jQuery.Promise} Promise resolved when the user closes the dialog\n */\nOO.ui.alert = function ( text, options ) {\n\treturn OO.ui.getWindowManager().openWindow( 'message', $.extend( {\n\t\tmessage: text,\n\t\tactions: [ OO.ui.MessageDialog.static.actions[ 0 ] ]\n\t}, options ) ).closed.then( function () {\n\t\treturn undefined;\n\t} );\n};\n\n/**\n * Display a quick modal confirmation dialog, using a OO.ui.MessageDialog. While the dialog is open,\n * the rest of the page will be dimmed out and the user won't be able to interact with it. The\n * dialog has two action buttons, one to confirm an operation (labelled \"OK\") and one to cancel it\n * (labelled \"Cancel\").\n *\n * A window manager is created automatically when this function is called for the first time.\n *\n * @example\n * OO.ui.confirm( 'Are you sure?' ).done( function ( confirmed ) {\n * if ( confirmed ) {\n * console.log( 'User clicked \"OK\"!' );\n * } else {\n * console.log( 'User clicked \"Cancel\" or closed the dialog.' );\n * }\n * } );\n *\n * @param {jQuery|string} text Message text to display\n * @param {Object} [options] Additional options, see OO.ui.MessageDialog#getSetupProcess\n * @return {jQuery.Promise} Promise resolved when the user closes the dialog. If the user chose to\n * confirm, the promise will resolve to boolean `true`; otherwise, it will resolve to boolean\n * `false`.\n */\nOO.ui.confirm = function ( text, options ) {\n\treturn OO.ui.getWindowManager().openWindow( 'message', $.extend( {\n\t\tmessage: text\n\t}, options ) ).closed.then( function ( data ) {\n\t\treturn !!( data && data.action === 'accept' );\n\t} );\n};\n\n/**\n * Display a quick modal prompt dialog, using a OO.ui.MessageDialog. While the dialog is open,\n * the rest of the page will be dimmed out and the user won't be able to interact with it. The\n * dialog has a text input widget and two action buttons, one to confirm an operation (labelled \"OK\")\n * and one to cancel it (labelled \"Cancel\").\n *\n * A window manager is created automatically when this function is called for the first time.\n *\n * @example\n * OO.ui.prompt( 'Choose a line to go to', { textInput: { placeholder: 'Line number' } } ).done( function ( result ) {\n * if ( result !== null ) {\n * console.log( 'User typed \"' + result + '\" then clicked \"OK\".' );\n * } else {\n * console.log( 'User clicked \"Cancel\" or closed the dialog.' );\n * }\n * } );\n *\n * @param {jQuery|string} text Message text to display\n * @param {Object} [options] Additional options, see OO.ui.MessageDialog#getSetupProcess\n * @param {Object} [options.textInput] Additional options for text input widget, see OO.ui.TextInputWidget\n * @return {jQuery.Promise} Promise resolved when the user closes the dialog. If the user chose to\n * confirm, the promise will resolve with the value of the text input widget; otherwise, it will\n * resolve to `null`.\n */\nOO.ui.prompt = function ( text, options ) {\n\tvar instance,\n\t\tmanager = OO.ui.getWindowManager(),\n\t\ttextInput = new OO.ui.TextInputWidget( ( options && options.textInput ) || {} ),\n\t\ttextField = new OO.ui.FieldLayout( textInput, {\n\t\t\talign: 'top',\n\t\t\tlabel: text\n\t\t} );\n\n\tinstance = manager.openWindow( 'message', $.extend( {\n\t\tmessage: textField.$element\n\t}, options ) );\n\n\t// TODO: This is a little hacky, and could be done by extending MessageDialog instead.\n\tinstance.opened.then( function () {\n\t\ttextInput.on( 'enter', function () {\n\t\t\tmanager.getCurrentWindow().close( { action: 'accept' } );\n\t\t} );\n\t\ttextInput.focus();\n\t} );\n\n\treturn instance.closed.then( function ( data ) {\n\t\treturn data && data.action === 'accept' ? textInput.getValue() : null;\n\t} );\n};\n","}( OO ) );\n"]} \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-accessibility.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-accessibility.json
new file mode 100644
index 00000000..656e321c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-accessibility.json
@@ -0,0 +1,28 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "bright": { "file": "images/icons/bright.svg" },
+ "halfBright": { "file": "images/icons/halfBright.svg" },
+ "notBright": { "file": "images/icons/notBright.svg" },
+ "eye": { "file": "images/icons/eye.svg" },
+ "eyeClosed": { "file": "images/icons/eyeClosed.svg" },
+ "moon": { "file": "images/icons/moon.svg" },
+ "largerText": { "file": {
+ "ltr": "images/icons/largerText-ltr.svg",
+ "rtl": "images/icons/largerText-rtl.svg"
+ } },
+ "smallerText": { "file": {
+ "ltr": "images/icons/smallerText-ltr.svg",
+ "rtl": "images/icons/smallerText-rtl.svg"
+ } },
+ "visionSimulator": { "file": "images/icons/visionSimulator.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-alerts.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-alerts.json
new file mode 100644
index 00000000..20d1c991
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-alerts.json
@@ -0,0 +1,44 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "alert": { "file": "images/icons/alert.svg" },
+ "bell": { "file": "images/icons/bell.svg" },
+ "bellOn": { "file": {
+ "ltr": "images/icons/bellOn-ltr.svg",
+ "rtl": "images/icons/bellOn-rtl.svg"
+ } },
+ "comment": { "file": "images/icons/comment.svg" },
+ "eye": {
+ "file": "images/icons/eye.svg",
+ "deprecated": "Moved since v0.23.0 to the 'accessibility' pack."
+ },
+ "eyeClosed": {
+ "file": "images/icons/eyeClosed.svg",
+ "deprecated": "Moved since v0.23.0 to the 'accessibility' pack."
+ },
+ "message": { "file": {
+ "ltr": "images/icons/message-ltr.svg",
+ "rtl": "images/icons/message-rtl.svg"
+ } },
+ "notice": { "file": "images/icons/notice.svg" },
+ "signature": { "file": {
+ "ltr": "images/icons/signature-ltr.svg",
+ "rtl": "images/icons/signature-rtl.svg"
+ },
+ "deprecated": "Moved since v0.23.0 to the 'editing-advanced' pack." },
+ "speechBubble": { "file": {
+ "ltr": "images/icons/speechBubble-ltr.svg",
+ "rtl": "images/icons/speechBubble-rtl.svg"
+ } },
+ "speechBubbleAdd": { "file": {
+ "ltr": "images/icons/speechBubbleAdd-ltr.svg",
+ "rtl": "images/icons/speechBubbleAdd-rtl.svg"
+ } },
+ "speechBubbles": { "file": {
+ "ltr": "images/icons/speechBubbles-ltr.svg",
+ "rtl": "images/icons/speechBubbles-rtl.svg"
+ } },
+ "tray": { "file": "images/icons/tray.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-content.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-content.json
new file mode 100644
index 00000000..cb405749
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-content.json
@@ -0,0 +1,30 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "article": { "file": {
+ "ltr": "images/icons/article-ltr.svg",
+ "rtl": "images/icons/article-rtl.svg"
+ } },
+ "articles": { "file": {
+ "ltr": "images/icons/articles-ltr.svg",
+ "rtl": "images/icons/articles-rtl.svg"
+ } },
+ "articleRedirect": { "file": {
+ "ltr": "images/icons/articleRedirect-ltr.svg",
+ "rtl": "images/icons/articleRedirect-rtl.svg"
+ } },
+ "history": { "file": "images/icons/history.svg" },
+ "info": { "file": "images/icons/info.svg" },
+ "journal": { "file": {
+ "ltr": "images/icons/journal-ltr.svg",
+ "rtl": "images/icons/journal-rtl.svg"
+ } },
+ "tag": { "file": "images/icons/tag.svg" },
+ "upload": { "file": {
+ "ltr": "images/icons/upload-ltr.svg",
+ "rtl": "images/icons/upload-rtl.svg"
+ } },
+ "window": { "file": "images/icons/window.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-advanced.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-advanced.json
new file mode 100644
index 00000000..a3c57731
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-advanced.json
@@ -0,0 +1,86 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "alignCentre": { "file": "images/icons/align-center.svg" },
+ "alignLeft": { "file": "images/icons/align-float-left.svg" },
+ "alignRight": { "file": "images/icons/align-float-right.svg" },
+ "attachment": { "file": {
+ "ltr": "images/icons/attachment-ltr.svg",
+ "rtl": "images/icons/attachment-rtl.svg"
+ } },
+ "calendar": { "file": {
+ "ltr": "images/icons/calendar-ltr.svg",
+ "rtl": "images/icons/calendar-rtl.svg"
+ } },
+ "code": { "file": "images/icons/code.svg" },
+ "find": { "file": {
+ "ltr": "images/icons/find-ltr.svg",
+ "rtl": "images/icons/find-rtl.svg"
+ } },
+ "language": { "file": {
+ "ltr": "images/icons/language-ltr.svg",
+ "rtl": "images/icons/language-rtl.svg"
+ } },
+ "layout": { "file": {
+ "ltr": "images/icons/layout-ltr.svg",
+ "rtl": "images/icons/layout-rtl.svg"
+ } },
+ "markup": { "file": "images/icons/markup.svg" },
+ "newline": { "file": {
+ "ltr": "images/icons/newline-ltr.svg",
+ "rtl": "images/icons/newline-rtl.svg"
+ } },
+ "noWikiText": { "file": {
+ "ltr": "images/icons/noWikiText-ltr.svg",
+ "rtl": "images/icons/noWikiText-rtl.svg"
+ } },
+ "outline": { "file": {
+ "ltr": "images/icons/outline-ltr.svg",
+ "rtl": "images/icons/outline-rtl.svg"
+ } },
+ "puzzle": { "file": "images/icons/puzzle.svg" },
+ "quotes": { "file": {
+ "ltr": "images/icons/quotes-ltr.svg",
+ "rtl": "images/icons/quotes-rtl.svg"
+ } },
+ "quotesAdd": { "file": {
+ "ltr": "images/icons/quotesAdd-ltr.svg",
+ "rtl": "images/icons/quotesAdd-rtl.svg"
+ } },
+ "redirect": { "file": {
+ "ltr": "images/icons/articleRedirect-ltr.svg",
+ "rtl": "images/icons/articleRedirect-rtl.svg"
+ } },
+ "searchCaseSensitive": { "file": "images/icons/case-sensitive.svg" },
+ "searchDiacritics": { "file": "images/icons/diacritic.svg" },
+ "searchRegularExpression": { "file": "images/icons/regular-expression.svg" },
+ "signature": { "file": {
+ "ltr": "images/icons/signature-ltr.svg",
+ "rtl": "images/icons/signature-rtl.svg"
+ } },
+ "specialCharacter": { "file": "images/icons/specialCharacter.svg" },
+ "table": { "file": "images/icons/table.svg" },
+ "tableAddColumnAfter": { "file": {
+ "ltr": "images/icons/table-insert-column-rtl.svg",
+ "rtl": "images/icons/table-insert-column-ltr.svg"
+ } },
+ "tableAddColumnBefore": { "file": {
+ "ltr": "images/icons/table-insert-column-ltr.svg",
+ "rtl": "images/icons/table-insert-column-rtl.svg"
+ } },
+ "tableAddRowAfter": { "file": "images/icons/table-insert-row-after.svg" },
+ "tableAddRowBefore": { "file": "images/icons/table-insert-row-before.svg" },
+ "tableCaption": { "file": "images/icons/table-caption.svg" },
+ "tableMergeCells": { "file": "images/icons/table-merge-cells.svg" },
+ "templateAdd": { "file": {
+ "ltr": "images/icons/templateAdd-ltr.svg",
+ "rtl": "images/icons/templateAdd-rtl.svg"
+ } },
+ "translation": { "file": {
+ "ltr": "images/icons/language-ltr.svg",
+ "rtl": "images/icons/language-rtl.svg"
+ } },
+ "wikiText": { "file": "images/icons/wikiText.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-core.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-core.json
new file mode 100644
index 00000000..b303071c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-core.json
@@ -0,0 +1,32 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "edit": { "file": {
+ "ltr": "images/icons/edit-ltr.svg",
+ "rtl": "images/icons/edit-rtl.svg"
+ } },
+ "editLock": { "file": {
+ "ltr": "images/icons/editLock-ltr.svg",
+ "rtl": "images/icons/editLock-rtl.svg"
+ } },
+ "editUndo": { "file": {
+ "ltr": "images/icons/editUndo-ltr.svg",
+ "rtl": "images/icons/editUndo-rtl.svg"
+ } },
+ "link": { "file": "images/icons/link.svg" },
+ "linkExternal": { "file": {
+ "ltr": "images/icons/external-link-ltr.svg",
+ "rtl": "images/icons/external-link-rtl.svg"
+ } },
+ "linkSecure": { "file": "images/icons/secure-link.svg" },
+ "redo": { "file": {
+ "ltr": "images/icons/arched-arrow-ltr.svg",
+ "rtl": "images/icons/arched-arrow-rtl.svg"
+ } },
+ "undo": { "file": {
+ "ltr": "images/icons/arched-arrow-rtl.svg",
+ "rtl": "images/icons/arched-arrow-ltr.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-list.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-list.json
new file mode 100644
index 00000000..490f8faf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-list.json
@@ -0,0 +1,22 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "indent": { "file": {
+ "ltr": "images/icons/indent-ltr.svg",
+ "rtl": "images/icons/indent-rtl.svg"
+ } },
+ "listBullet": { "file": {
+ "ltr": "images/icons/listBullet-ltr.svg",
+ "rtl": "images/icons/listBullet-rtl.svg"
+ } },
+ "listNumbered": { "file": {
+ "ltr": "images/icons/listNumbered-ltr.svg",
+ "rtl": "images/icons/listNumbered-rtl.svg"
+ } },
+ "outdent": { "file": {
+ "ltr": "images/icons/outdent-ltr.svg",
+ "rtl": "images/icons/outdent-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-styling.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-styling.json
new file mode 100644
index 00000000..718f9ffa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-editing-styling.json
@@ -0,0 +1,79 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "bigger": { "file": {
+ "ltr": "images/icons/bigger-ltr.svg",
+ "rtl": "images/icons/bigger-rtl.svg"
+ } },
+ "smaller": { "file": {
+ "ltr": "images/icons/smaller-ltr.svg",
+ "rtl": "images/icons/smaller-rtl.svg"
+ } },
+ "subscript": { "file": {
+ "ltr": "images/icons/subscript-ltr.svg",
+ "rtl": "images/icons/subscript-rtl.svg"
+ } },
+ "superscript": { "file": {
+ "ltr": "images/icons/superscript-ltr.svg",
+ "rtl": "images/icons/superscript-rtl.svg"
+ } },
+ "bold": { "file": {
+ "default": "images/icons/bold-a.svg",
+ "lang": {
+ "ar": "images/icons/bold-arab-ain.svg",
+ "be": "images/icons/bold-cyrl-te.svg",
+ "cs,en,en-ca,en-gb,he,ml,pl,sco": "images/icons/bold-b.svg",
+ "da,de,hu,ksh,nn,no,sv": "images/icons/bold-f.svg",
+ "es,gl,pt": "images/icons/bold-n.svg",
+ "eu,fi": "images/icons/bold-l.svg",
+ "fa": "images/icons/bold-arab-dad.svg",
+ "fr,it": "images/icons/bold-g.svg",
+ "hy": "images/icons/bold-armn-to.svg",
+ "ka": "images/icons/bold-geor-man.svg",
+ "ky,ru,uk": "images/icons/bold-cyrl-zhe.svg",
+ "nl": "images/icons/bold-v.svg",
+ "os": "images/icons/bold-cyrl-be.svg"
+ }
+ } },
+ "highlight": { "file": {
+ "ltr": "images/icons/highlight-ltr.svg",
+ "rtl": "images/icons/highlight-rtl.svg"
+ } },
+ "italic": { "file": {
+ "default": "images/icons/italic-a.svg",
+ "lang": {
+ "ar": "images/icons/italic-arab-meem.svg",
+ "cs,en,en-ca,en-gb,fr,he,ml,pl,pt,sco": "images/icons/italic-i.svg",
+ "be,da,de,fi,ky,nn,no,os,sv,ru,uk": "images/icons/italic-k.svg",
+ "es,gl,it,nl": "images/icons/italic-c.svg",
+ "eu": "images/icons/italic-e.svg",
+ "fa": "images/icons/italic-arab-keheh-jeem.svg",
+ "hu": "images/icons/italic-d.svg",
+ "hy": "images/icons/italic-armn-sha.svg",
+ "ksh": "images/icons/italic-s.svg",
+ "ka": "images/icons/italic-geor-kan.svg"
+ }
+ } },
+ "strikethrough": { "file": {
+ "default": "images/icons/strikethrough-a.svg",
+ "lang": {
+ "en,en-ca,en-gb": "images/icons/strikethrough-s.svg",
+ "fi": "images/icons/strikethrough-y.svg"
+ }
+ } },
+ "underline": { "file": {
+ "default": "images/icons/underline-a.svg",
+ "lang": {
+ "en,en-ca,en-gb": "images/icons/underline-u.svg"
+ }
+ } },
+ "textLanguage": { "file": {
+ "ltr": "images/icons/language-ltr.svg",
+ "rtl": "images/icons/language-rtl.svg"
+ } },
+ "textDirLTR": { "file": "images/icons/text-dir-lefttoright.svg" },
+ "textDirRTL": { "file": "images/icons/text-dir-righttoleft.svg" },
+ "textStyle": { "file": "images/icons/text-style.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-interactions.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-interactions.json
new file mode 100644
index 00000000..c1695a73
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-interactions.json
@@ -0,0 +1,71 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "add": { "file": "images/icons/add.svg" },
+ "advanced": { "file": "images/icons/advanced.svg" },
+ "browser": { "file": {
+ "ltr": "images/icons/browser-ltr.svg",
+ "rtl": "images/icons/browser-rtl.svg"
+ } },
+ "cancel": { "file": "images/icons/cancel.svg" },
+ "check": { "file": "images/icons/check.svg" },
+ "clear": { "file": "images/icons/clear.svg" },
+ "clock": { "file": "images/icons/clock.svg" },
+ "close": { "file": "images/icons/close.svg" },
+ "ellipsis": { "file": "images/icons/ellipsis.svg" },
+ "feedback": { "file": {
+ "ltr": "images/icons/feedback-ltr.svg",
+ "rtl": "images/icons/feedback-rtl.svg"
+ } },
+ "funnel": { "file": {
+ "ltr": "images/icons/funnel-ltr.svg",
+ "rtl": "images/icons/funnel-rtl.svg"
+ } },
+ "heart": { "file": "images/icons/heart.svg" },
+ "help": { "file": {
+ "ltr": "images/icons/help-ltr.svg",
+ "rtl": "images/icons/help-rtl.svg",
+ "lang": {
+ "he,yi": "images/icons/help-ltr.svg"
+ }
+ } },
+ "key": { "file": {
+ "ltr": "images/icons/key-ltr.svg",
+ "rtl": "images/icons/key-rtl.svg"
+ } },
+ "keyboard": { "file": {
+ "ltr": "images/icons/keyboard-ltr.svg",
+ "rtl": "images/icons/keyboard-rtl.svg"
+ } },
+ "logOut": { "file": {
+ "ltr": "images/icons/logOut-ltr.svg",
+ "rtl": "images/icons/logOut-rtl.svg"
+ } },
+ "newWindow": { "file": {
+ "ltr": "images/icons/newWindow-ltr.svg",
+ "rtl": "images/icons/newWindow-rtl.svg"
+ } },
+ "printer": { "file": {
+ "ltr": "images/icons/printer-ltr.svg",
+ "rtl": "images/icons/printer-rtl.svg"
+ } },
+ "search": { "file": {
+ "ltr": "images/icons/search-ltr.svg",
+ "rtl": "images/icons/search-rtl.svg"
+ }
+ },
+ "settings": { "file": "images/icons/settings.svg" },
+ "subtract": { "file": "images/icons/subtract.svg" },
+ "sun": { "file": {
+ "ltr": "images/icons/sun-ltr.svg",
+ "rtl": "images/icons/sun-rtl.svg"
+ },
+ "deprecated": "This will be removed in v0.24.0."
+ },
+ "watchlist": { "file": {
+ "ltr": "images/icons/watchlist-ltr.svg",
+ "rtl": "images/icons/watchlist-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-layout.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-layout.json
new file mode 100644
index 00000000..c274c5f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-layout.json
@@ -0,0 +1,28 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "menu": { "file": "images/icons/menu.svg" },
+ "stripeFlow": { "file": {
+ "ltr": "images/icons/stripeFlow-ltr.svg",
+ "rtl": "images/icons/stripeFlow-rtl.svg"
+ } },
+ "stripeSideMenu": {
+ "file": "images/icons/draggable.svg",
+ "deprecated": "Replaced since v0.22.2, use 'draggable' from the 'movement' pack instead."
+ },
+ "stripeSummary": { "file": {
+ "ltr": "images/icons/stripeSummary-ltr.svg",
+ "rtl": "images/icons/stripeSummary-rtl.svg"
+ } },
+ "stripeToC": { "file": {
+ "ltr": "images/icons/stripeToC-ltr.svg",
+ "rtl": "images/icons/stripeToC-rtl.svg"
+ } },
+ "viewCompact": { "file": "images/icons/viewCompact.svg" },
+ "viewDetails": { "file": {
+ "ltr": "images/icons/viewDetails-ltr.svg",
+ "rtl": "images/icons/viewDetails-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-media.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-media.json
new file mode 100644
index 00000000..dc4ca105
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-media.json
@@ -0,0 +1,16 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "fullScreen": { "file": "images/icons/fullScreen.svg" },
+ "image": { "file": "images/icons/image.svg" },
+ "imageGallery": { "file": {
+ "ltr": "images/icons/imageGallery-ltr.svg",
+ "rtl": "images/icons/imageGallery-rtl.svg"
+ } },
+ "play": { "file": {
+ "ltr": "images/icons/play-ltr.svg",
+ "rtl": "images/icons/play-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-moderation.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-moderation.json
new file mode 100644
index 00000000..6e6cde3e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-moderation.json
@@ -0,0 +1,44 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "block": { "file": "images/icons/block.svg" },
+ "unBlock": { "file": {
+ "ltr": "images/icons/unBlock-ltr.svg",
+ "rtl": "images/icons/unBlock-rtl.svg"
+ } },
+ "clip": { "file": "images/icons/clip.svg" },
+ "unClip": { "file": "images/icons/unClip.svg" },
+ "flag": { "file": {
+ "ltr": "images/icons/flag-ltr.svg",
+ "rtl": "images/icons/flag-rtl.svg"
+ } },
+ "unFlag": { "file": {
+ "ltr": "images/icons/unFlag-ltr.svg",
+ "rtl": "images/icons/unFlag-rtl.svg"
+ } },
+ "lock": { "file": "images/icons/lock.svg" },
+ "unLock": { "file": {
+ "ltr": "images/icons/unLock-ltr.svg",
+ "rtl": "images/icons/unLock-rtl.svg"
+ } },
+ "star": { "file": "images/icons/star.svg" },
+ "halfStar": { "file": {
+ "ltr": "images/icons/halfStar-ltr.svg",
+ "rtl": "images/icons/halfStar-rtl.svg"
+ } },
+ "unStar": { "file": "images/icons/unStar.svg" },
+ "trash": { "file": "images/icons/trash.svg" },
+ "unTrash": { "file": {
+ "ltr": "images/icons/unTrash-ltr.svg",
+ "rtl": "images/icons/unTrash-rtl.svg"
+ } },
+ "pushPin": { "file": "images/icons/pushPin.svg" },
+ "ongoingConversation": {
+ "file": {
+ "ltr": "images/icons/ongoingConversation-ltr.svg",
+ "rtl": "images/icons/ongoingConversation-rtl.svg"
+ }
+ }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-movement.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-movement.json
new file mode 100644
index 00000000..5ecee27e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-movement.json
@@ -0,0 +1,40 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "arrowNext": { "file": {
+ "ltr": "images/icons/arrow-ltr.svg",
+ "rtl": "images/icons/arrow-rtl.svg"
+ } },
+ "arrowLast": { "file": {
+ "ltr": "images/icons/arrow-rtl.svg",
+ "rtl": "images/icons/arrow-ltr.svg"
+ } },
+ "collapse": { "file": "images/icons/collapse.svg" },
+ "downTriangle": { "file": "images/icons/downTriangle.svg" },
+ "draggable": { "file": "images/icons/draggable.svg" },
+ "expand": { "file": "images/icons/expand.svg" },
+ "move": { "file": "images/icons/move.svg" },
+ "next": { "file": {
+ "ltr": "images/icons/move-ltr.svg",
+ "rtl": "images/icons/move-rtl.svg"
+ }
+ },
+ "previous": { "file": {
+ "ltr": "images/icons/move-rtl.svg",
+ "rtl": "images/icons/move-ltr.svg"
+ }
+ },
+ "last": { "file": {
+ "ltr": "images/icons/move-end-ltr.svg",
+ "rtl": "images/icons/move-end-rtl.svg"
+ }
+ },
+ "first": { "file": {
+ "ltr": "images/icons/move-end-rtl.svg",
+ "rtl": "images/icons/move-end-ltr.svg"
+ }
+ },
+ "upTriangle": { "file": "images/icons/upTriangle.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons-user.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-user.json
new file mode 100644
index 00000000..1aa87237
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons-user.json
@@ -0,0 +1,7 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "userAvatar": { "file": "images/icons/userAvatar.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/icons.json b/www/wiki/resources/lib/oojs-ui/themes/apex/icons.json
new file mode 100644
index 00000000..b5fbbed0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/icons.json
@@ -0,0 +1,50 @@
+{
+ "prefix": "oo-ui-icon",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "add": { "file": "images/icons/add.svg" },
+ "advanced": { "file": "images/icons/advanced.svg" },
+ "alert": { "file": "images/icons/alert.svg" },
+ "cancel": { "file": "images/icons/cancel.svg" },
+ "check": { "file": "images/icons/check.svg" },
+ "circle": { "file": "images/icons/circle.svg" },
+ "close": { "file": "images/icons/close.svg" },
+ "code": { "file": "images/icons/code.svg" },
+ "collapse": { "file": "images/icons/collapse.svg" },
+ "comment": { "file": "images/icons/comment.svg" },
+ "ellipsis": { "file": "images/icons/ellipsis.svg" },
+ "expand": { "file": "images/icons/expand.svg" },
+ "help": { "file": {
+ "ltr": "images/icons/help-ltr.svg",
+ "rtl": "images/icons/help-rtl.svg",
+ "lang": {
+ "he,yi": "images/icons/help-ltr.svg"
+ }
+ } },
+ "history": { "file": "images/icons/history.svg" },
+ "info": { "file": "images/icons/info.svg" },
+ "menu": { "file": "images/icons/menu.svg" },
+ "next": { "file": {
+ "ltr": "images/icons/move-ltr.svg",
+ "rtl": "images/icons/move-rtl.svg"
+ } },
+ "notice": { "file": "images/icons/notice.svg" },
+ "previous": { "file": {
+ "ltr": "images/icons/move-rtl.svg",
+ "rtl": "images/icons/move-ltr.svg"
+ } },
+ "redo": { "file": {
+ "ltr": "images/icons/arched-arrow-ltr.svg",
+ "rtl": "images/icons/arched-arrow-rtl.svg"
+ } },
+ "remove": { "file": "images/icons/trash.svg" },
+ "search": { "file": "images/icons/search.svg" },
+ "settings": { "file": "images/icons/settings.svg" },
+ "tag": { "file": "images/icons/tag.svg" },
+ "undo": { "file": {
+ "ltr": "images/icons/arched-arrow-rtl.svg",
+ "rtl": "images/icons/arched-arrow-ltr.svg"
+ } },
+ "window": { "file": "images/icons/window.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/add.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/add.png
new file mode 100644
index 00000000..4c70ee4a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/add.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/add.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/add.svg
new file mode 100644
index 00000000..62e54965
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/add.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="add">
+ <path id="plus" d="M13 6h-2v5H6v2h5v5h2v-5h5v-2h-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/advanced.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/advanced.png
new file mode 100644
index 00000000..dd3ef8ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/advanced.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/advanced.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/advanced.svg
new file mode 100644
index 00000000..b5e0e608
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/advanced.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="settings">
+ <path id="gear" d="M20.87 13.476c.078-.482.13-.972.13-1.476s-.052-.994-.13-1.476l-2.464-.26a6.618 6.618 0 0 0-.648-1.57l1.558-1.923a8.97 8.97 0 0 0-2.086-2.08L15.3 6.246a6.543 6.543 0 0 0-1.57-.648l-.26-2.463C12.996 3.054 12.506 3 12 3s-.994.052-1.476.13l-.26 2.464c-.554.15-1.08.367-1.57.648L6.772 4.685A8.995 8.995 0 0 0 4.687 6.77L6.245 8.7c-.28.488-.5 1.015-.648 1.57l-2.463.26c-.08.48-.132.97-.132 1.475s.052.995.13 1.477l2.464.26c.15.554.367 1.08.648 1.57l-1.558 1.92a8.984 8.984 0 0 0 2.087 2.086l1.925-1.558c.488.28 1.015.5 1.57.648l.26 2.463c.48.078.97.13 1.475.13s.994-.052 1.476-.13l.26-2.464a6.67 6.67 0 0 0 1.57-.648l1.92 1.558a8.984 8.984 0 0 0 2.083-2.087l-1.555-1.93c.28-.487.5-1.014.647-1.57l2.463-.26zM12 15.998a3.998 3.998 0 1 1 0-7.996 3.998 3.998 0 0 1 0 7.996z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/alert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/alert.png
new file mode 100644
index 00000000..73550841
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/alert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/alert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/alert.svg
new file mode 100644
index 00000000..8b601d5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/alert.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="alert">
+ <path id="point" d="M11 16h2v2h-2z"/>
+ <path id="stroke" d="M13.516 10h-3L11 15h2z"/>
+ <path id="triangle" d="M12.017 5.974L19.537 19H4.497l7.52-13.026m0-2.474c-.545 0-1.09.357-1.5 1.07L2.53 18.403C1.705 19.833 2.38 21 4.03 21H20c1.65 0 2.325-1.17 1.5-2.6L13.517 4.575c-.413-.715-.956-1.072-1.5-1.072z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-center.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-center.png
new file mode 100644
index 00000000..a912b033
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-center.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-center.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-center.svg
new file mode 100644
index 00000000..6f479773
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-center.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H9c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm-5.5 9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0-12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-center"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-left.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-left.png
new file mode 100644
index 00000000..e3950369
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-left.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-left.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-left.svg
new file mode 100644
index 00000000..a577600d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-left.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H4c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm9.5 0h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm-10-9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0 12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-float-left"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-right.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-right.png
new file mode 100644
index 00000000..c72a9560
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-right.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-right.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-right.svg
new file mode 100644
index 00000000..0f46bc1f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/align-float-right.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 9h-6c-.554 0-1 .446-1 1v5c0 .554.446 1 1 1h6c.554 0 1-.446 1-1v-5c0-.554-.446-1-1-1zm-9.5 0h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm10-9h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1zm0 12h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1z" id="align-float-right"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-ltr.png
new file mode 100644
index 00000000..87a84e2b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-ltr.svg
new file mode 100644
index 00000000..f36b6973
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="arched-arrow-ltr">
+ <path id="arrow" d="M19.925 14.937l-2.39-6.9-1.48 2.328c-.965-.845-2.7-1.85-5.514-1.823-4.88.046-6.52 4.244-6.52 4.244s2.756-2.64 6.928-1.95c1.73.287 3.007 1.207 3.675 1.792l-1.474 2.32 6.78-.01z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-rtl.png
new file mode 100644
index 00000000..12285f92
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-rtl.svg
new file mode 100644
index 00000000..9a7dbe62
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arched-arrow-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="arched-arrow-rtl">
+ <path id="arrow" d="M13.4 8.542c-2.813-.027-4.548.978-5.512 1.823l-1.48-2.33-2.39 6.902 6.78.01-1.473-2.32c.668-.584 1.945-1.504 3.675-1.79 4.172-.69 6.925 1.948 6.925 1.948S18.288 8.588 13.4 8.542z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-ltr.png
new file mode 100644
index 00000000..24905bc4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-ltr.svg
new file mode 100644
index 00000000..b4c0e0d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 12H6c-1.7 0-3 1.3-3 3h13v3l5-4.5L16 9v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-rtl.png
new file mode 100644
index 00000000..1cd81cbb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-rtl.svg
new file mode 100644
index 00000000..1087ff94
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/arrow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 12h10c1.7 0 3 1.3 3 3H8v3l-5-4.5L8 9v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-ltr.png
new file mode 100644
index 00000000..cf7de13a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-ltr.svg
new file mode 100644
index 00000000..862bc2b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 10h4V5h-4v5zm-5 2h9v-1H7v1zm0 2h9v-1H7v1zm0 2h9v-1H7v1zm4-9H7v1h4V7zm0 2H7v1h4V9zm0-4H7v1h4V5zM5 3h13v16H8c-1.7 0-3-1.3-3-3V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-rtl.png
new file mode 100644
index 00000000..d0b0e70d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-rtl.svg
new file mode 100644
index 00000000..3b16dcbc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/article-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 10H7V5h4v5zm5 2H7v-1h9v1zm0 2H7v-1h9v1zm0 2H7v-1h9v1zm-4-9h4v1h-4V7zm0 2h4v1h-4V9zm0-4h4v1h-4V5zm6-2H5v16h10c1.7 0 3-1.3 3-3V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-ltr.png
new file mode 100644
index 00000000..3dbe20ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-ltr.svg
new file mode 100644
index 00000000..028c64c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="article-redirect">
+ <path id="arrow" d="M18.1 14.2L23 18l-4.9 4.8v-2.2c-1.7 0-2.9-.2-4.3-1.2-1.2-.8-2.5-2.6-2.3-4.1 1.4 1 2.9 1.5 4.4 1.5.7 0 1.4-.1 2.1-.3l.1-2.3"/>
+ <path id="page" d="M5 3v13c0 1.7 1.3 3 3 3h3.375c-.157-.205-.3-.43-.438-.656-.42-.688-.77-1.483-.843-2.344H7v-1h3.125l.125-1H7v-1h3.375l.03-.188.283.188H16v1h-3.906l.22.156c.523.375 1.065.64 1.592.844H16v.406c.208-.013.418-.07.625-.094.068-1.294.125-3.874.125-3.874l1.25.968V3H5zm2 2h4v1H7V5zm5 0h4v5h-4V5zM7 7h4v1H7V7zm0 2h4v1H7V9zm0 2h9v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-rtl.png
new file mode 100644
index 00000000..60beb6ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-rtl.svg
new file mode 100644
index 00000000..316d36ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articleRedirect-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="article-redirect">
+ <path id="arrow" d="M5.9 14.2L1 18l4.9 4.8v-2.2c1.7 0 2.9-.2 4.3-1.2 1.2-.8 2.5-2.6 2.3-4.1-1.4 1-2.9 1.5-4.4 1.5-.7 0-1.4-.1-2.1-.3l-.1-2.3"/>
+ <path id="page" d="M19 3v13c0 1.7-1.3 3-3 3h-3.375c.157-.205.3-.43.438-.656.42-.688.77-1.483.843-2.344H17v-1h-3.125l-.125-1H17v-1h-3.375l-.03-.188-.283.188H8v1h3.906l-.22.156a7.097 7.097 0 0 1-1.592.844H8v.406c-.208-.013-.418-.07-.625-.094a178.903 178.903 0 0 1-.125-3.874L6 12.405V3zm-2 2h-4v1h4zm-5 0H8v5h4zm5 2h-4v1h4zm0 2h-4v1h4zm0 2H8v1h9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.png
new file mode 100644
index 00000000..bd048c45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.svg
new file mode 100644
index 00000000..c1944975
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 12h4V7h-4v5zm-5 2h9v-1H6v1zm0 2h9v-1H6v1zm0 2h9v-1H6v1zm4-9H6v1h4V9zm0 2H6v1h4v-1zm0-4H6v1h4V7zM4 5h13v16H7c-1.7 0-3-1.3-3-3V5z"/>
+ <path d="M18 4v14h2V2H7v2" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.png
new file mode 100644
index 00000000..3ebb1133
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.svg
new file mode 100644
index 00000000..40a9348f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/articles-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M13 12H9V7h4v5zm5 2H9v-1h9v1zm0 2H9v-1h9v1zm0 2H9v-1h9v1zm-4-9h4v1h-4V9zm0 2h4v1h-4v-1zm0-4h4v1h-4V7zm6-2H7v16h10c1.7 0 3-1.3 3-3V5z"/>
+ <path d="M6 4v14H4V2h13v2" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-ltr.png
new file mode 100644
index 00000000..92dfaf21
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-ltr.svg
new file mode 100644
index 00000000..74a4d646
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-293 385 24 24">
+ <path d="M-274.3 390.9c-1.6-1.6-4.3-1.5-5.8.1l.2.2c.5.5 1.3.7 2.1.4.8-.3 1.7-.1 2.4.6 1 .9.9 2.4 0 3.4l-7.1 7.1c-.9 1-2.4.9-3.4 0s-.9-2.4 0-3.4l4.4-4.4c.3-.3.9-.5 1.3-.1s.2 1-.1 1.3l-3.4 3.4c-.6.6-.6 1.7.1 2.3l4.3-4.3c.8-.8 1.1-1.8.9-2.7-.2-.9-.9-1.6-1.7-1.9-.9-.2-1.9 0-2.6.7l-4.4 4.4c-1.6 1.6-1.6 4.3.1 5.8 1.5 1.6 4.3 1.5 5.8-.1l7-7c.8-.8 1.2-1.9 1.2-3s-.5-2.1-1.3-2.8c-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-1.5-1.6.8.7 0 0z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-rtl.png
new file mode 100644
index 00000000..f793246d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-rtl.svg
new file mode 100644
index 00000000..f53f5a47
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/attachment-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-119 70 24 24">
+ <path d="M-113.3 75.6c-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7-1.3 1.7-1.3 2.8 0 1.1.4 2.2 1.2 3l7 7c1.5 1.6 4.3 1.7 5.8.1 1.7-1.5 1.7-4.2.1-5.8l-4.4-4.4c-.7-.7-1.7-.9-2.6-.7-.8.3-1.5 1-1.7 1.9-.2.9.1 1.9.9 2.7l4.3 4.3c.7-.6.7-1.7.1-2.3l-3.4-3.4c-.3-.3-.5-.9-.1-1.3s1-.2 1.3.1l4.4 4.4c.9 1 1 2.5 0 3.4s-2.5 1-3.4 0l-7.1-7.1c-.9-1-1-2.5 0-3.4.7-.7 1.6-.9 2.4-.6.8.3 1.6.1 2.1-.4l.2-.2c-1.5-1.6-4.2-1.8-5.8-.1-.8.7 1.5-1.7 0 0z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bell.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bell.png
new file mode 100644
index 00000000..91e83972
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bell.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bell.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bell.svg
new file mode 100644
index 00000000..09b65f29
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bell.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.5 13V8c0-3-2.3-5-5.5-5S6.5 5 6.5 8v5c0 2 0 3-2 3v1h15v-1c-2 0-2-1-2-3zM12 19H9c0 1 1.6 2 3 2s3-1 3-2h-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.png
new file mode 100644
index 00000000..fb13de1a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.svg
new file mode 100644
index 00000000..855581b0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.8 13.7L19.5 9c1-2.8-.5-5.5-3.5-6.6-3-1.1-5.9 0-6.9 2.8L7.4 9.9c-.7 1.9-1 2.8-2.9 2.1l-.3 1 14.1 5.1.3-.9c-1.9-.7-1.5-1.6-.8-3.5zM12 18.8l-2.8-1c-.3.9.8 2.4 2.1 2.9s3.2.1 3.5-.9l-2.8-1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.png
new file mode 100644
index 00000000..b05fd4c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.svg
new file mode 100644
index 00000000..e1f2961c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bellOn-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6.21 13.7L4.51 9c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta-invert.png
new file mode 100644
index 00000000..c3b26b85
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta-invert.svg
new file mode 100644
index 00000000..4d8c6732
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 12l-3-2-1 4-1-4-3 2 2-3-4-1 4-1-2-3 3 2 1-4 1 4 3-2-2 3 4 1-4 1 2 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta.png
new file mode 100644
index 00000000..7b31e1e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta.svg
new file mode 100644
index 00000000..51a5c782
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/beta.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 12l-3-2-1 4-1-4-3 2 2-3-4-1 4-1-2-3 3 2 1-4 1 4 3-2-2 3 4 1-4 1 2 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch-invert.png
new file mode 100644
index 00000000..09635383
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch-invert.svg
new file mode 100644
index 00000000..5058629b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M15.3 14.7C16.1 10.9 14.7 4 12 4c-2.7 0-4.2 6.7-3.4 10.5L7 18h2.7l.3 1h4c.2-.3.1-.5.3-1H17l-1.7-3.3zM12 10c-.8 0-1.5-.7-1.5-1.5S11.2 7 12 7s1.5.7 1.5 1.5S12.8 10 12 10zm2 10c0 1.1-2 2-2 2s-2-.9-2-2"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch.png
new file mode 100644
index 00000000..6d3c067c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch.svg
new file mode 100644
index 00000000..c3f99d6a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/betaLaunch.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15.3 14.7C16.1 10.9 14.7 4 12 4c-2.7 0-4.2 6.7-3.4 10.5L7 18h2.7l.3 1h4c.2-.3.1-.5.3-1H17l-1.7-3.3zM12 10c-.8 0-1.5-.7-1.5-1.5S11.2 7 12 7s1.5.7 1.5 1.5S12.8 10 12 10zm2 10c0 1.1-2 2-2 2s-2-.9-2-2"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-ltr.png
new file mode 100644
index 00000000..e8b2911d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-ltr.svg
new file mode 100644
index 00000000..fffbcdd3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="big-a" d="M14.334 6h1.372l4.48 12H18.48l-1.493-4h-4l-1.507 4H9.814zm2.28 7l-1.617-4.333L13.363 13h3.25z"/>
+ <path id="small-a" d="M6.172 12h.686l2.24 6h-.853L7.5 16H5.497l-.753 2h-.833zm1.14 3.5l-.81-2.166-.816 2.166h1.625z"/>
+ <path id="arrow" d="M9 9H4l2.5-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-rtl.png
new file mode 100644
index 00000000..2f5e05df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-rtl.svg
new file mode 100644
index 00000000..7b903c4b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bigger-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="big-a" d="M9.666 6H8.294l-4.48 12H5.52l1.493-4h4l1.507 4h1.666zm-2.28 7l1.617-4.333L10.637 13h-3.25z"/>
+ <path id="small-a" d="M17.828 12h-.686l-2.24 6h.853l.747-2h2l.753 2h.833zm-1.14 3.5l.81-2.167.816 2.167H16.69z"/>
+ <path id="arrow" d="M15 9h5l-2.5-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/block.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/block.png
new file mode 100644
index 00000000..7f8eb2a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/block.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/block.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/block.svg
new file mode 100644
index 00000000..b50bb618
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/block.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm5 9H7v-2h10v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-ltr.png
new file mode 100644
index 00000000..640bb2a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-ltr.svg
new file mode 100644
index 00000000..160219c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 11v2h-2l3.6 3.6c.9-1.3 1.4-2.9 1.4-4.6 0-4.4-3.6-8-8-8-1.7 0-3.3.5-4.6 1.4L13 11h4zM4 4L3 5l2.4 2.4C4.5 8.7 4 10.3 4 12c0 4.4 3.6 8 8 8 1.7 0 3.3-.5 4.6-1.4L19 21l1-1L4 4zm3 9v-2h2l2 2H7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-rtl.png
new file mode 100644
index 00000000..2475b061
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-rtl.svg
new file mode 100644
index 00000000..90fe46ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/blockUndo-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 11v2h2l-3.6 3.6C4.5 15.3 4 13.7 4 12c0-4.4 3.6-8 8-8 1.7 0 3.3.5 4.6 1.4L11 11H7zm13-7l1 1-2.4 2.4c.9 1.3 1.4 2.9 1.4 4.6 0 4.4-3.6 8-8 8-1.7 0-3.3-.5-4.6-1.4L5 21l-1-1L20 4zm-3 9v-2h-2l-2 2h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-a.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-a.png
new file mode 100644
index 00000000..2907677f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-a.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-a.svg
new file mode 100644
index 00000000..ce9f4f84
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-a.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 18h3L14 6h-3L6 18h3l1.25-3h4.5L16 18zm-4.917-5L12.5 9.6l1.417 3.4h-2.834z" id="bold-a"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-ain.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-ain.png
new file mode 100644
index 00000000..931b6cfd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-ain.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-ain.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-ain.svg
new file mode 100644
index 00000000..452c3d0c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-ain.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-arab-ain">
+ <path id="arab-ain" d="M9.337 13.616c0 1.35 1.386 2.1 4.16 2.258l2.186-.03.318.045c-.03.12-.25.34-.66.65l-.09.06c-1.233.93-2.42 1.394-3.56 1.394-1.14 0-2.043-.33-2.71-.99-.65-.66-.973-1.56-.973-2.7.006-1.353.567-2.572 1.685-3.657v-.044l-.606-.55a.952.952 0 0 1-.222-.63c0-.49.24-1.11.72-1.863.65-1.045 1.302-1.565 1.957-1.56.886.005 1.618.42 2.194 1.246.325.48-.03.55-1.064.22-.843-.33-1.528-.05-2.055.826l.016.074 1.125.866.05.005c1.405-.497 2.42-.74 3.044-.725-.06.116-.14.36-.244.732a27.75 27.75 0 0 1-.304.982l-.125.372-.386.05c-1.743.24-2.992.716-3.745 1.43-.465.463-.7.972-.704 1.524"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-dad.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-dad.png
new file mode 100644
index 00000000..11212576
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-dad.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-dad.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-dad.svg
new file mode 100644
index 00000000..b90bb77a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-arab-dad.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-arab-dad">
+ <path id="arab-dad" d="M16.41 8.232l-1.675-.665L15.43 6l1.687.64-.707 1.592m.775 3.078c-.51-.286-1-.427-1.476-.423-.478 0-.99.205-1.54.616l-.505.38.006.024c1.085.066 1.935.1 2.55.1h.315c.57-.022.994-.065 1.278-.132-.067-.17-.275-.36-.625-.566h-.006M10.38 14.6c-.016-.905-.33-1.87-.937-2.9l1.294-1.73.118.15c.267.337.504.925.713 1.767l.064.05c.496-.007.942-.17 1.338-.484v-.006l1.732-1.53c.68-.6 1.282-.9 1.807-.9.383.003.85.194 1.394.57.55.378.884.697 1 .96.063.15.094.385.094.71 0 .694-.11 1.227-.33 1.596-.193.31-.474.555-.845.734-.438.208-1.55.312-3.333.312-.8 0-1.794-.02-2.982-.064l-.142.43c-.254.67-.463 1.112-.625 1.323-.724.937-1.785 1.405-3.182 1.405-1.71-.006-2.56-.92-2.56-2.74.003-.94.278-1.814.824-2.618.15-.216.298-.367.444-.454.225-.133.288-.09.188.124-.396.862-.596 1.548-.6 2.058.008 1.177.752 1.768 2.232 1.772 1.038-.004 1.803-.182 2.295-.535"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-armn-to.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-armn-to.png
new file mode 100644
index 00000000..6f6349b0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-armn-to.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-armn-to.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-armn-to.svg
new file mode 100644
index 00000000..c35979af
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-armn-to.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-armn-to">
+ <path id="armn-to" d="M13.86 16.257c.124 0 .254-.026.39-.078.135-.06.257-.15.367-.28a1.43 1.43 0 0 0 .273-.517c.073-.214.11-.48.11-.798V13h-1.14c-.14 0-.284.026-.43.078a.905.905 0 0 0-.383.258c-.11.125-.2.294-.274.508-.067.213-.1.487-.1.82 0 .34.035.47.108.695.08.21.18.39.29.53.12.13.25.23.39.29.14.05.276.07.406.07m-2.97-7.84a2.67 2.67 0 0 0-.975.45 2.1 2.1 0 0 0-.672.813c-.16.342-.242.78-.242 1.31V18H6v-7.188c0-.776.15-1.455.453-2.04a4.227 4.227 0 0 1 1.234-1.467c.52-.39 1.13-.685 1.83-.883a8.114 8.114 0 0 1 2.225-.297c.526 0 1.04.044 1.54.133.504.088.98.22 1.43.398.447.172.858.388 1.233.65.375.26.698.564.97.913.275.34.49.73.64 1.17.15.43.226 1.09.226 1.61h1.36v2.04h-1.36v1.6c0 .58-.102 1.09-.31 1.54-.21.44-.49.81-.844 1.11-.35.302-.834.53-1.297.687-.465.15-.954.226-1.47.226-.51 0-.997-.08-1.46-.235a3.46 3.46 0 0 1-1.22-.703 3.452 3.452 0 0 1-.836-1.174c-.203-.472-.304-1.027-.304-1.662s.1-1.18.32-1.64c.21-.46.49-.684.85-.976.35-.297.76-.513 1.22-.648.452-.14.93-.21 1.43-.21h1.13c-.01-.49-.04-1.044-.24-1.36a2.26 2.26 0 0 0-.77-.767 3.234 3.234 0 0 0-.986-.427c-.375-.09-.578-.094-1.1-.094-.52 0-.64.02-1.01.102z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-b.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-b.png
new file mode 100644
index 00000000..8d09636e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-b.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-b.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-b.svg
new file mode 100644
index 00000000..1806709a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-b.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-b">
+ <path id="b" d="M7 18h6c2 0 4-1 4-3 0-1.064.01-1.975-1.99-3 2-.975 1.99-1.935 1.99-3 0-2-2-3-4-3H7v12zm7-8c0 1 0 1-2 1h-2V8h2c2 0 2 0 2 1v1zm-2 6h-2v-3h2c2 0 2 0 2 1v1s0 1-2 1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-be.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-be.png
new file mode 100644
index 00000000..de9e9d1b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-be.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-be.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-be.svg
new file mode 100644
index 00000000..9d84cb04
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-be.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-cyrl-be">
+ <path id="cyrl-be" d="M7 6h9v2h-6v3h2.65c.892 0 1.632.11 2.22.327.587.218 1.087.622 1.5 1.21.42.59.63 1.188.63 1.98 0 .812-.21 1.397-.63 1.976-.418.578-.897.974-1.436 1.187-.533.213-1.295.32-2.286.32h-5.65m4.768-2c.75 0 1.28-.05 1.584-.12.305-.077.57-.247.792-.51.23-.26.343-.472.343-.854 0-.557-.2-.868-.596-1.12-.4-.255-1.07-.397-2.02-.397H10v3"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-te.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-te.png
new file mode 100644
index 00000000..281d7187
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-te.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-te.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-te.svg
new file mode 100644
index 00000000..63aee3ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-te.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-cyrl-te">
+ <path id="te" d="M11 18V8H7V6h11v2h-4v10"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-zhe.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-zhe.png
new file mode 100644
index 00000000..98387012
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-zhe.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-zhe.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-zhe.svg
new file mode 100644
index 00000000..aab3f4c1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-cyrl-zhe.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-cyrl-zhe">
+ <path id="cyrl-zhe" d="M13 6v5.154c.328-.033.537-.18.705-.447.168-.266.4-.873.698-1.82.39-1.242.79-2.034 1.197-2.375.403-.336 1.075-.504 2.014-.504L18 6v1.78l-.386-.008c-.4 0-.69.062-.878.187-.186.112-.337.3-.452.55-.115.25-.286.76-.512 1.533-.12.41-.25.755-.392 1.032-.137.275-.383.536-.738.78.44.156.8.465 1.084.926.288.455.603 1.103.944 1.943L18 18h-2.314l-1.17-3.08-.113-.253-.24-.56c-.247-.57-.45-.933-.61-1.09A.726.726 0 0 0 13 12.78V18h-2v-5.22c-.226 0-.382.077-.546.23-.164.15-.368.517-.612 1.097l-.246.56-.113.253L8.313 18H6l1.33-3.267c.327-.808.635-1.447.923-1.92.293-.476.663-.793 1.11-.95-.355-.244-.603-.5-.745-.772a6.357 6.357 0 0 1-.392-1.04c-.222-.76-.39-1.26-.505-1.52-.11-.25-.26-.44-.45-.57-.18-.12-.49-.18-.912-.18H6V6l.386.008c.953 0 1.63.17 2.034.512.4.347.79 1.136 1.177 2.366.3.954.534 1.564.698 1.83.168.26.377.405.705.438V6.002"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-f.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-f.png
new file mode 100644
index 00000000..ad0d89b8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-f.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-f.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-f.svg
new file mode 100644
index 00000000..89061f10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-f.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-f">
+ <path id="f" d="M16 8V6H8v12h3v-5h4v-2h-4V8z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-g.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-g.png
new file mode 100644
index 00000000..55e766a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-g.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-g.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-g.svg
new file mode 100644
index 00000000..3150d95c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-g.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-g">
+ <path id="g" d="M12 14v-2h5v4.203c-.497.475-1.22.894-2.166 1.26A7.994 7.994 0 0 1 11.97 18c-1.23 0-2.303-.253-3.217-.76a4.908 4.908 0 0 1-2.062-2.185A7.008 7.008 0 0 1 6 11.96c0-1.208.26-2.282.77-3.222.518-.94 1.27-1.66 2.26-2.16.754-.386 1.693-.58 2.816-.58 1.46 0 2.6.304 3.418.91.825.603 1.354 1.436 1.59 2.502l-2.36.435a2.433 2.433 0 0 0-.94-1.346c-.454-.34-1.022-.5-1.707-.5-1.038 0-1.864.32-2.48.97-.61.65-.914 1.61-.914 2.89 0 1.375.31 2.41.93 3.1.62.687 1.434 1.03 2.44 1.03.497 0 .995-.095 1.49-.285.505-.196 1.334-.57 1.69-.846v-.868"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-geor-man.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-geor-man.png
new file mode 100644
index 00000000..c0500747
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-geor-man.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-geor-man.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-geor-man.svg
new file mode 100644
index 00000000..deb95b70
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-geor-man.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-geor-man">
+ <path id="geor-man" d="M13.832 14.06c0-1.714-.394-2.572-1.182-2.572-.868 0-1.302.78-1.302 2.338-.01 1.624.42 2.436 1.295 2.436.793 0 1.19-.734 1.19-2.2m2.167 0C16 16.686 14.884 18 12.65 18 10.218 18 9 16.614 9 13.84c0-2.737 1.217-4.105 3.65-4.105.842 0 1.183.63 1.183.63v-1.58c0-.788-.45-1.183-1.347-1.183-.572 0-.858.374-.858 1.123h-2.34C9.29 6.908 10.35 6 12.462 6 14.83 6 16.01 6.946 16 8.84"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-l.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-l.png
new file mode 100644
index 00000000..11b67a1c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-l.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-l.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-l.svg
new file mode 100644
index 00000000..76956234
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-l.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-l">
+ <path id="l" d="M8 18V6h3v10h5v2"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-n.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-n.png
new file mode 100644
index 00000000..708d421f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-n.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-n.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-n.svg
new file mode 100644
index 00000000..62f66a2f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-n.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-n">
+ <path id="n" d="M7 18V6h3l4 8V6h3v12h-3l-4-8v8H7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-v.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-v.png
new file mode 100644
index 00000000..a60786c9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-v.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-v.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-v.svg
new file mode 100644
index 00000000..027db273
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bold-v.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-v">
+ <path id="v" d="M10.5 18L6 6h3l3 8 3-8h3l-4.5 12"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr-invert.png
new file mode 100644
index 00000000..084cbc7e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr-invert.svg
new file mode 100644
index 00000000..bf39564a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M15 5H8c-1.1 0-2 .9-2 2v3h3v11l4-3 4 3V7c0-1.1-.9-2-2-2zM9 9H7V7c0-.6.4-1 1-1h1v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr.png
new file mode 100644
index 00000000..ad046b6e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr.svg
new file mode 100644
index 00000000..ba3ff91a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 5H8c-1.1 0-2 .9-2 2v3h3v11l4-3 4 3V7c0-1.1-.9-2-2-2zM9 9H7V7c0-.6.4-1 1-1h1v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl-invert.png
new file mode 100644
index 00000000..125fb746
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl-invert.svg
new file mode 100644
index 00000000..729b8c2e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M8 5h7c1.1 0 2 .9 2 2v3h-3v11l-4-3-4 3V7c0-1.1.9-2 2-2zm6 4h2V7c0-.6-.4-1-1-1h-1v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl.png
new file mode 100644
index 00000000..0d19f03e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl.svg
new file mode 100644
index 00000000..fcbd1358
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bookmark-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 5h7c1.1 0 2 .9 2 2v3h-3v11l-4-3-4 3V7c0-1.1.9-2 2-2zm6 4h2V7c0-.6-.4-1-1-1h-1v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright-invert.png
new file mode 100644
index 00000000..6194ed4a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright-invert.svg
new file mode 100644
index 00000000..8f41c1ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9-.3.3-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+ <path d="M12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright.png
new file mode 100644
index 00000000..788fc94b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright.svg
new file mode 100644
index 00000000..5a399fe2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/bright.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9-.3.3-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+ <path d="M12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr-invert.png
new file mode 100644
index 00000000..027df2df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr-invert.svg
new file mode 100644
index 00000000..762e6418
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M3 6v11c0 1.7 1.3 3 3 3h15V6H3zm2.5 1C6.3 7 7 7.7 7 8.5S6.3 10 5.5 10 4 9.3 4 8.5 4.7 7 5.5 7zM20 19H6c-1.1 0-2-.9-2-2v-6h16v8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr.png
new file mode 100644
index 00000000..ae059ad0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr.svg
new file mode 100644
index 00000000..e7be7e56
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 6v11c0 1.7 1.3 3 3 3h15V6H3zm2.5 1C6.3 7 7 7.7 7 8.5S6.3 10 5.5 10 4 9.3 4 8.5 4.7 7 5.5 7zM20 19H6c-1.1 0-2-.9-2-2v-6h16v8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl-invert.png
new file mode 100644
index 00000000..51937b73
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl-invert.svg
new file mode 100644
index 00000000..d6378bf6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M21 6v11c0 1.7-1.3 3-3 3H3V6h18zm-2.5 1c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5S20 9.3 20 8.5 19.3 7 18.5 7zM4 19h14c1.1 0 2-.9 2-2v-6H4v8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl.png
new file mode 100644
index 00000000..939a858a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl.svg
new file mode 100644
index 00000000..38807b5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/browser-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 6v11c0 1.7-1.3 3-3 3H3V6h18zm-2.5 1c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5S20 9.3 20 8.5 19.3 7 18.5 7zM4 19h14c1.1 0 2-.9 2-2v-6H4v8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.png
new file mode 100644
index 00000000..0ab46dd6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.svg
new file mode 100644
index 00000000..b0bc0e51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 5v10c0 1.7 1.3 3 3 3h14V8c0-1.7-1.3-3-3-3H4zm2 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zM5 9h3v2H5V9zm4 0h3v2H9V9zm4 0h3v2h-3V9zm4 0h3v2h-3V9zM5 12h3v2H5v-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2zM5 15h3v2H7c-1.195 0-2-.805-2-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.png
new file mode 100644
index 00000000..0236393b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.svg
new file mode 100644
index 00000000..d8ff5a95
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/calendar-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 5v10c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3h14zm-2 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zM7 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm13 3h-3v2h3V9zm-4 0h-3v2h3V9zm-4 0H9v2h3V9zM8 9H5v2h3V9zm12 3h-3v2h3v-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2zm12 3h-3v2h1c1.195 0 2-.805 2-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/cancel.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/cancel.png
new file mode 100644
index 00000000..f9354e3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/cancel.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/cancel.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/cancel.svg
new file mode 100644
index 00000000..04ff5c32
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/cancel.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="cancel">
+ <path id="circle-with-strike" d="M12 5.022a6.98 6.98 0 0 0-.003 13.956 6.98 6.98 0 0 0-.002-13.956zM6.885 12c0-1.092.572-3.25.93-2.93l7.113 7.114c.487.525-1.838.93-2.93.93A5.113 5.113 0 0 1 6.884 12zm9.298 2.93L9.07 7.815c-.445-.483 1.837-.93 2.93-.93a5.112 5.112 0 0 1 5.114 5.113c0 1.092-.364 3.542-.93 2.93z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-ltr.png
new file mode 100644
index 00000000..e95caf23
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-ltr.svg
new file mode 100644
index 00000000..44d2d1a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 13.1l8.9 8.9c.8-.8.8-2 0-2.8l-6.1-6.1 6-6.1c.8-.8.8-2 0-2.8L7 13.1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-rtl.png
new file mode 100644
index 00000000..e59bdd5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-rtl.svg
new file mode 100644
index 00000000..1f90f5c6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caret-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16.5 13.1L7.6 22c-.8-.8-.8-2 0-2.8l6.1-6.1-6-6.1c-.8-.8-.8-2 0-2.8l8.8 8.9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretDown.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretDown.png
new file mode 100644
index 00000000..a46ffdba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretDown.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretDown.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretDown.svg
new file mode 100644
index 00000000..89e06124
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretDown.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 16l8.9-8.9c-.8-.8-2-.8-2.8 0L12 13.2l-6.1-6c-.8-.8-2-.8-2.8 0L12 16z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretUp.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretUp.png
new file mode 100644
index 00000000..9e5c022a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretUp.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretUp.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretUp.svg
new file mode 100644
index 00000000..fcf4e135
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/caretUp.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 6.5l8.9 8.9c-.8.8-2 .8-2.8 0L12 9.3l-6.1 6c-.8.8-2 .8-2.8 0L12 6.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/case-sensitive.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/case-sensitive.png
new file mode 100644
index 00000000..426c5de5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/case-sensitive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/case-sensitive.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/case-sensitive.svg
new file mode 100644
index 00000000..749e38ff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/case-sensitive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="case-sensitive">
+ <path id="upper-case" d="M7.53 7L4 17h2.063l.72-2.406h3.624l.72 2.406h2.062L9.65 7h-2.12zm1.064 1.53L9.938 13H7.25l1.344-4.47z"/>
+ <path id="lower-case" d="M18.55 17l-.184-1.035h-.055c-.35.44-.71.747-1.08.92-.37.167-.85.25-1.44.25-.564 0-.955-.208-1.377-.625-.42-.418-.627-1.012-.627-1.784 0-.808.283-1.403.846-1.784.568-.386 1.193-.607 2.208-.64l1.322-.04v-.335c0-.772-.396-1.158-1.187-1.158-.61 0-1.325.18-2.147.55l-.688-1.4c.877-.46 1.85-.69 2.916-.69 1.024 0 1.59.22 2.134.662.545.445.818 1.12.818 2.03V17h-1.45m-.394-3.527l-.802.027c-.604.018-1.054.127-1.35.327-.294.2-.442.504-.442.912 0 .58.336.87 1.008.87.48 0 .865-.137 1.152-.414.29-.277.436-.645.436-1.103v-.627"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/check.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/check.png
new file mode 100644
index 00000000..0cc9f745
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/check.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/check.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/check.svg
new file mode 100644
index 00000000..0c5332bd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/check.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7.105 13.473l1.422-1.423 1.9 1.902L15.237 7l1.66 1.148L10.634 17z" id="check"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/circle.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/circle.png
new file mode 100644
index 00000000..32ba403f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/circle.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/circle.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/circle.svg
new file mode 100644
index 00000000..18133cc9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/circle.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <circle cx="12" cy="12" r="6"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear-invert.png
new file mode 100644
index 00000000..ec90ed93
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear-invert.svg
new file mode 100644
index 00000000..07382052
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <g id="clear">
+ <path id="circle-with-cross" d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 11l-1 1-3-3-3 3-1-1 3-3-3-3 1-1 3 3 3-3 1 1-3 3 3 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear.png
new file mode 100644
index 00000000..973dc036
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear.svg
new file mode 100644
index 00000000..8689e770
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clear.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="clear">
+ <path id="circle-with-cross" d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 11l-1 1-3-3-3 3-1-1 3-3-3-3 1-1 3 3 3-3 1 1-3 3 3 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clip.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clip.png
new file mode 100644
index 00000000..ac254835
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clip.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clip.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clip.svg
new file mode 100644
index 00000000..86d1dbfb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clip.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.5 4.5v13.2L12 13.5l-5.5 4.2V4.5zM5 21l7-6 7 6V3H5z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock-invert.png
new file mode 100644
index 00000000..fdd3e51c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock-invert.svg
new file mode 100644
index 00000000..322fc31f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <g id="clock">
+ <path id="circle" d="M12 5a7 7 0 1 0 0 14 7 7 0 0 0 0-14zm0 1.25a5.75 5.75 0 0 1 0 11.5 5.75 5.75 0 0 1 0-11.5z"/>
+ <path id="hands" d="M15.605 14.08s-1.674-1.36-2.81-2.15c.504-1.683 1.194-4.605 1.194-4.605s-3.057 3.765-3.427 4.703c-.325.82 1.024 1.55 1.647 1.178 1.335.387 3.394.873 3.394.873z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock.png
new file mode 100644
index 00000000..b8264573
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock.svg
new file mode 100644
index 00000000..2a944938
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/clock.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="clock">
+ <path id="circle" d="M12 5a7 7 0 1 0 0 14 7 7 0 0 0 0-14zm0 1.25a5.75 5.75 0 0 1 0 11.5 5.75 5.75 0 0 1 0-11.5z"/>
+ <path id="hands" d="M15.605 14.08s-1.674-1.36-2.81-2.15c.504-1.683 1.194-4.605 1.194-4.605s-3.057 3.765-3.427 4.703c-.325.82 1.024 1.55 1.647 1.178 1.335.387 3.394.873 3.394.873z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/close.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/close.png
new file mode 100644
index 00000000..9b3d4ae4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/close.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/close.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/close.svg
new file mode 100644
index 00000000..b379e185
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/close.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.717 7.697l-1.414-1.414L12 10.586 7.697 6.283 6.283 7.697 10.586 12l-4.303 4.303 1.414 1.414L12 13.414l4.303 4.303 1.414-1.414L13.414 12z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/code.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/code.png
new file mode 100644
index 00000000..ba89e4ec
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/code.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/code.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/code.svg
new file mode 100644
index 00000000..a00d1582
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/code.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="code">
+ <path id="left-bracket" d="M4 12v-1h1c1 0 1 0 1-1V7.614c0-.514.024-.896.073-1.142.054-.252.14-.463.257-.633.204-.28.473-.48.808-.59.335-.11.872-.25 1.835-.25H10v1h-.752c-.457 0-.77.19-.936.406-.167.216-.312.446-.312 1.07v1.856c0 .73-.04 1.18-.244 1.493-.2.307-.562.53-1.09.667.535.155.9.385 1.096.688.2.31.238.76.238 1.49v1.86c0 .62.145.85.312 1.06.166.22.48.41.936.41H10v1H8.973c-.963 0-1.5-.133-1.835-.248a1.578 1.578 0 0 1-.808-.59 1.68 1.68 0 0 1-.257-.626C6.023 16.283 6 15.9 6 15.386V13c0-1 0-1-1-1H4z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" width="24" height="24" xlink:href="#left-bracket"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/collapse.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/collapse.png
new file mode 100644
index 00000000..1d8c6db1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/collapse.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/collapse.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/collapse.svg
new file mode 100644
index 00000000..645bfda5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/collapse.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="collapse">
+ <path id="arrow" d="M6.697 15.714L12 10.412l5.303 5.302 1.414-1.414L12 7.583 5.283 14.3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/comment.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/comment.png
new file mode 100644
index 00000000..dcaa8814
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/comment.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/comment.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/comment.svg
new file mode 100644
index 00000000..861611ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/comment.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="comment">
+ <path id="speech-bubble" d="M15 6H9a3 3 0 0 0-3 3v4a3 3 0 0 0 3 3v3l3-3h3a3 3 0 0 0 3-3V9a3 3 0 0 0-3-3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/diacritic.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/diacritic.png
new file mode 100644
index 00000000..2359b196
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/diacritic.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/diacritic.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/diacritic.svg
new file mode 100644
index 00000000..45651013
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/diacritic.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="diacritic">
+ <path id="letter-a" d="M13.55 17l-.184-1.035h-.055c-.35.44-.71.747-1.08.92-.37.167-.85.25-1.44.25-.563 0-.954-.208-1.376-.625-.42-.418-.627-1.012-.627-1.784 0-.808.283-1.403.846-1.784.568-.386 1.193-.607 2.208-.64l1.323-.04v-.335c0-.772-.396-1.158-1.187-1.158-.61 0-1.325.18-2.147.55l-.69-1.4c.878-.46 1.85-.69 2.917-.69 1.024 0 1.59.22 2.134.66.546.446.82 1.12.82 2.03V17h-1.45m-.395-3.527l-.802.027c-.604.018-1.054.127-1.35.327-.294.2-.442.504-.442.912 0 .58.337.87 1.01.87.48 0 .864-.138 1.15-.415.29-.277.437-.645.437-1.103v-.627"/>
+ <path id="tilde" d="M12.012 7.527l-.466-.306a.832.832 0 0 1-.085-.048c-.264-.17-.467-.256-.608-.256a.518.518 0 0 0-.466.256c-.107.17-.16.418-.16.743v.066H9.047c0-.748.144-1.326.432-1.733.294-.407.703-.61 1.228-.61.203 0 .406.037.61.114.208.073.43.19.66.357l.517.355c.124.082.237.146.338.19a.77.77 0 0 0 .288.066c.204 0 .362-.088.475-.265.113-.176.17-.42.17-.735v-.066h1.177c0 .75-.147 1.327-.44 1.735-.29.407-.695.61-1.22.61-.203 0-.4-.032-.593-.098a3.107 3.107 0 0 1-.678-.373z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/downTriangle.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/downTriangle.png
new file mode 100644
index 00000000..7df0592f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/downTriangle.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/downTriangle.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/downTriangle.svg
new file mode 100644
index 00000000..e1fb989c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/downTriangle.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 18l8-10H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/draggable.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/draggable.png
new file mode 100644
index 00000000..e031527d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/draggable.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/draggable.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/draggable.svg
new file mode 100644
index 00000000..e63a7d5c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/draggable.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 19H4v-2h16v2zM20 15H4v-2h16v2zM20 11H4V9h16v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-ltr.png
new file mode 100644
index 00000000..504f29bb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-ltr.svg
new file mode 100644
index 00000000..02ab6e42
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 2L5 14l-1 5 5-1L21 6c0-2-2-4-4-4zM7.2 15.5c-.3-.3-.7-.6-1-.8C8.5 12.4 17.5 3.3 17.5 3.3c.4.1.7.3 1 .7L7.2 15.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-rtl.png
new file mode 100644
index 00000000..7ea3aee9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-rtl.svg
new file mode 100644
index 00000000..83033c5a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/edit-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 2l12 12 1 5-5-1L4 6c0-2 2-4 4-4zm9.8 13.5c.3-.3.7-.6 1-.8C16.5 12.4 7.5 3.3 7.5 3.3c-.4.1-.7.3-1 .7l11.3 11.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-ltr.png
new file mode 100644
index 00000000..aa4b8c3b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-ltr.svg
new file mode 100644
index 00000000..e06e5a05
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 4V3s0-3-3-3-3 3-3 3v1h-1v6h8V4zm-1.5 0h-3V3s0-1.5 1.5-1.5c1.48.06 1.5 1.5 1.5 1.5zM13 9.6l-6.8 6.9c-.3-.3-.7-.6-1-.8 1.4-1.4 5-5 7.8-7.9V6l-9 9-1 5 5-1 8-8h-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-rtl.png
new file mode 100644
index 00000000..3d8b751f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-rtl.svg
new file mode 100644
index 00000000..fb1001f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editLock-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 4V3s0-3 3-3 3 3 3 3v1h1v6H3V4zm1.5 0h3V3s0-1.5-1.5-1.5C5.52 1.56 5.5 3 5.5 3zM12 9.6l6.8 6.9c.3-.3.7-.6 1-.8-1.4-1.4-5-5-7.8-7.9V6l9 9 1 5-5-1-8-8h3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-ltr.png
new file mode 100644
index 00000000..c1633605
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-ltr.svg
new file mode 100644
index 00000000..50f4214d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14.9 2.8c.9 0 1.8.2 2.7.6.9.4 1.6.9 1.9 1.6-2.8.1-5 1.1-6.6 3.1l1.3 2-6.7-.3L8 3l1.7 2c1.8-1.5 3.5-2.2 5.2-2.2z"/>
+ <path d="M15.2 11.1l-2.6-.1-5.4 5.5c-.3-.3-.7-.6-1-.8.9-.9 2.8-2.8 4.7-4.8H9.1L5 15l-1 5 5-1 7.8-7.8-1.6-.1zM20.6 6c-1.7 0-3.2.5-4.4 1.4l-.9.9.8 1.3.9 1.4 4-4c0-.3-.1-.7-.2-1h-.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-rtl.png
new file mode 100644
index 00000000..fc989682
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-rtl.svg
new file mode 100644
index 00000000..b7cfed78
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/editUndo-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10.1 2.8c-.9 0-1.8.2-2.7.6-.9.4-1.6.9-1.9 1.6 2.8.1 5 1.1 6.6 3.1l-1.3 2 6.7-.3L17 3l-1.7 2c-1.8-1.5-3.5-2.2-5.2-2.2z"/>
+ <path d="M9.8 11.1l2.6-.1 5.4 5.5c.3-.3.7-.6 1-.8-.9-.9-2.8-2.8-4.7-4.8h1.8L20 15l1 5-5-1-7.8-7.8 1.6-.1zM4.4 6c1.7 0 3.2.5 4.4 1.4l.9.9-.8 1.3L8 11 4 7c0-.3.1-.7.2-1h.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ellipsis.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ellipsis.png
new file mode 100644
index 00000000..85fa4f36
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ellipsis.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ellipsis.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ellipsis.svg
new file mode 100644
index 00000000..ef7d485b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ellipsis.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM14 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM20 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/expand.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/expand.png
new file mode 100644
index 00000000..f72b6f2e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/expand.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/expand.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/expand.svg
new file mode 100644
index 00000000..84b9e0a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/expand.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="expand">
+ <path id="arrow" d="M17.303 8.283L12 13.586 6.697 8.283 5.283 9.697 12 16.414l6.717-6.717z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-ltr.png
new file mode 100644
index 00000000..185ffc6a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-ltr.svg
new file mode 100644
index 00000000..1d7980dc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="external">
+ <path id="box" d="M4 4h6v2H6v12h12v-4h2v6H4z"/>
+ <path id="arrow" d="M12.42 4H20v7.58l-2.84-2.846L12.892 13 11 11.106l4.264-4.266z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-rtl.png
new file mode 100644
index 00000000..7066001c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-rtl.svg
new file mode 100644
index 00000000..7e25d034
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/external-link-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="external">
+ <path id="box" d="M20 4h-6v2h4v12H6v-4H4v6h16z"/>
+ <path id="arrow" d="M11.58 4H4v7.58l2.84-2.846L11.108 13 13 11.106 8.736 6.84z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye-invert.png
new file mode 100644
index 00000000..4e11ebcb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye-invert.svg
new file mode 100644
index 00000000..c2651c05
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path id="sclera" d="M12 6C7 6 1 12 1 12s6 6 11 6 11-6 11-6-6-6-11-6zm0 10c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+ <circle id="pupil" r="2" cy="12" cx="12"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye.png
new file mode 100644
index 00000000..eb5f9635
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye.svg
new file mode 100644
index 00000000..cec85d0b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eye.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="sclera" d="M12 6C7 6 1 12 1 12s6 6 11 6 11-6 11-6-6-6-11-6zm0 10c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+ <circle id="pupil" r="2" cy="12" cx="12"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed-invert.png
new file mode 100644
index 00000000..bd499f10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed-invert.svg
new file mode 100644
index 00000000..d394a983
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M19.4 12.7c.7-.8 1.2-1.7 1.4-2.7h-1.6c-.9 2.5-3.9 4.4-7.7 4.6h-.1c-3.7-.2-6.8-2.1-7.7-4.6H2.2c.2 1 .8 1.9 1.4 2.7l-2 2 .7.7 2-2c.8.6 1.7 1.2 2.7 1.7l-1 2.8.9.3 1-2.8c1 .3 2 .6 3.1.6v3h1v-3c1.1-.1 2.2-.3 3.1-.6l1 2.8.9-.3-1-2.8c1-.4 1.9-1 2.6-1.7l2 2 .7-.7-1.9-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.png
new file mode 100644
index 00000000..1ac37d6d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.svg
new file mode 100644
index 00000000..d17f2c8a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/eyeClosed.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19.4 12.7c.7-.8 1.2-1.7 1.4-2.7h-1.6c-.9 2.5-3.9 4.4-7.7 4.6h-.1c-3.7-.2-6.8-2.1-7.7-4.6H2.2c.2 1 .8 1.9 1.4 2.7l-2 2 .7.7 2-2c.8.6 1.7 1.2 2.7 1.7l-1 2.8.9.3 1-2.8c1 .3 2 .6 3.1.6v3h1v-3c1.1-.1 2.2-.3 3.1-.6l1 2.8.9-.3-1-2.8c1-.4 1.9-1 2.6-1.7l2 2 .7-.7-1.9-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-ltr.png
new file mode 100644
index 00000000..ac5787bd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-ltr.svg
new file mode 100644
index 00000000..0fdeed9a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8.202 15.834l.568 2.101c.198.765 1.06 1.22 1.8 1.016.698-.193 1.125-.983.926-1.747l-.38-1.37H20L17.229 5 4.155 12.652c-.427.762.088 2.748.823 3.182h3.224z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-rtl.png
new file mode 100644
index 00000000..fdbe5e1e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-rtl.svg
new file mode 100644
index 00000000..022d86d1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/feedback-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15.798 15.834l-.568 2.101c-.198.765-1.06 1.22-1.8 1.016-.698-.193-1.125-.983-.926-1.747l.38-1.37H4L6.771 5l13.074 7.652c.427.762-.088 2.748-.823 3.182h-3.224z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-ltr.png
new file mode 100644
index 00000000..066d84a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-ltr.svg
new file mode 100644
index 00000000..ef44f579
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="find">
+ <path id="magnifying-glass" d="M13.656 11c-1.92 0-3.5 1.548-3.5 3.47 0 1.92 1.58 3.5 3.5 3.5.75 0 1.432-.253 2-.657l.094.156 2.375 2.37c.19.19.534.15.78-.096s.315-.59.126-.78l-2.37-2.377-.185-.094a3.545 3.545 0 0 0 .655-2.03c0-1.92-1.55-3.47-3.47-3.47zm0 1.656a1.8 1.8 0 0 1 1.813 1.813 1.83 1.83 0 0 1-1.82 1.84c-1.01 0-1.844-.83-1.844-1.847s.832-1.814 1.844-1.814z"/>
+ <path id="text" d="M6 5v2h10V5H6zm0 3v2h11V8H6zm0 3v2h3.53a4.443 4.443 0 0 1 1.44-2H6zm0 3v2h3.53c-.177-.48-.28-.99-.28-1.53 0-.16.046-.315.063-.47H6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-rtl.png
new file mode 100644
index 00000000..ed834afe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-rtl.svg
new file mode 100644
index 00000000..51fd39ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/find-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="find">
+ <path id="magnifying-glass" d="M11.344 11c1.92 0 3.5 1.548 3.5 3.47 0 1.92-1.58 3.5-3.5 3.5-.75 0-1.432-.253-2-.657l-.094.156-2.375 2.37c-.19.19-.534.15-.78-.096s-.315-.59-.126-.78l2.37-2.377.185-.094a3.545 3.545 0 0 1-.655-2.03c0-1.92 1.55-3.47 3.47-3.47zm0 1.656A1.8 1.8 0 0 0 9.53 14.47c0 1.01.806 1.84 1.818 1.84 1.01 0 1.844-.83 1.844-1.845s-.832-1.814-1.844-1.814z"/>
+ <path id="text" d="M19 5v2H9V5zm0 3v2H8V8zm0 3v2h-3.53a4.443 4.443 0 0 0-1.44-2zm0 3v2h-3.53c.177-.48.28-.99.28-1.53 0-.16-.046-.315-.063-.47z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-ltr.png
new file mode 100644
index 00000000..bd19f2b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-ltr.svg
new file mode 100644
index 00000000..10975612
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14 6.5V5c-1.4-1.5-5.2-1.2-6 0V4H7v15h1v-7c.8-.8 3.4-.9 5-.5V13c1.2 1.5 4.3 1.2 5 0V6c-.7.7-2.7.9-4 .5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-rtl.png
new file mode 100644
index 00000000..a9943cce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-rtl.svg
new file mode 100644
index 00000000..397a3da2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flag-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10.3 7.5V6c1.4-1.5 5.2-1.2 6 0V5h1v15h-1v-7c-.8-.8-3.4-.9-5-.5V14c-1.2 1.5-4.3 1.2-5 0V7c.7.7 2.7.9 4 .5z"/>
+</svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-ltr.png
new file mode 100644
index 00000000..033adde2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-ltr.svg
new file mode 100644
index 00000000..516a3ea2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18 2L2.03 17.97l.97 1 4-4V19h1v-5.03l2.688-2.69c.81-.02 1.645.053 2.312.22V13c1.2 1.5 4.3 1.2 5 0V6c-.493.493-1.635.725-2.72.688L19 2.968zM7 4v7.03l6.438-6.436C11.778 3.61 8.71 3.934 8 5V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-rtl.png
new file mode 100644
index 00000000..fca73fd5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-rtl.svg
new file mode 100644
index 00000000..8ed159e6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/flagUndo-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 2l-1 .97 3.72 3.717C8.634 6.727 7.492 6.494 7 6v7c.7 1.2 3.8 1.5 5 0v-1.5c.667-.167 1.5-.24 2.313-.22L17 13.97V19h1v-4.03l4 4 .97-1zm7.22 2c-.952-.03-1.932.163-2.658.594L18 11.03V4h-1v1c-.4-.6-1.556-.963-2.78-1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/fullScreen.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/fullScreen.png
new file mode 100644
index 00000000..ced10354
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/fullScreen.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/fullScreen.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/fullScreen.svg
new file mode 100644
index 00000000..06b709ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/fullScreen.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <path id="arrow" d="M6 6v4l1.28-1.28 2 2 1.423-1.44-2-2L10 6z"/>
+ <use transform="rotate(90 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(180 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(-90 12 12)" xlink:href="#arrow"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr-invert.png
new file mode 100644
index 00000000..2949648d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr-invert.svg
new file mode 100644
index 00000000..40d01b4b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M11 13L5 6h15l-6 7v7c-1.7 0-3-1.3-3-3v-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr.png
new file mode 100644
index 00000000..9396cba0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr.svg
new file mode 100644
index 00000000..df863b9c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 13L5 6h15l-6 7v7c-1.7 0-3-1.3-3-3v-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl-invert.png
new file mode 100644
index 00000000..c0f155ae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl-invert.svg
new file mode 100644
index 00000000..d960a650
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M14 13l6-7H5l6 7v7c1.7 0 3-1.3 3-3v-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl.png
new file mode 100644
index 00000000..7aee05f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl.svg
new file mode 100644
index 00000000..4eade2d6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/funnel-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14 13l6-7H5l6 7v7c1.7 0 3-1.3 3-3v-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright-invert.png
new file mode 100644
index 00000000..2a4d5478
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright-invert.svg
new file mode 100644
index 00000000..82f466eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M11.4 5.4V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm-5.2-.5c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 7c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm-3 4c0-1.7 1.3-3 3-3v6c-1.7 0-3-1.3-3-3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright.png
new file mode 100644
index 00000000..f8432105
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright.svg
new file mode 100644
index 00000000..2745ec7f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfBright.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11.4 5.4V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm-5.2-.5c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 7c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm-3 4c0-1.7 1.3-3 3-3v6c-1.7 0-3-1.3-3-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-ltr.png
new file mode 100644
index 00000000..d52a9080
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-ltr.svg
new file mode 100644
index 00000000..cfb17d8c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+ <path d="M10.1 11l-3.9.5L9 14.3l-.6 3.9 3.6-1.7-.1-9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-rtl.png
new file mode 100644
index 00000000..4991b65c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-rtl.svg
new file mode 100644
index 00000000..c649b505
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/halfStar-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 7.4L10.3 11l-4 .5L9 14.3l-.5 3.9 3.5-1.7 3.6 1.7-.6-3.9 2.8-2.8-3.9-.5L12 7.4M12 4l2.8 5.6 6.2.9-4.5 4.4 1.1 6.1-5.6-3-5.5 3 1-6.2L3 10.4l6.3-.9L12 4z"/>
+ <path d="M12.1 7.5l1.8 3.5 3.9.5-2.8 2.8.6 3.9-3.6-1.7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart-invert.png
new file mode 100644
index 00000000..2070997e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart-invert.svg
new file mode 100644
index 00000000..fc782264
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M15 7c-2 0-3 2-3 2s-1-2-3-2c-2.5 0-4 2-4 4 0 4 5 5 7 8 2-3 7-4 7-8 0-2-1.5-4-4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart.png
new file mode 100644
index 00000000..76d76d0a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart.svg
new file mode 100644
index 00000000..6433201a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/heart.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 7c-2 0-3 2-3 2s-1-2-3-2c-2.5 0-4 2-4 4 0 4 5 5 7 8 2-3 7-4 7-8 0-2-1.5-4-4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-ltr.png
new file mode 100644
index 00000000..9bb1382a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-ltr.svg
new file mode 100644
index 00000000..a77dca2c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-ltr.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="help">
+ <path id="circle" d="M12 2.085c-5.477 0-9.915 4.438-9.915 9.916 0 5.48 4.438 9.92 9.916 9.92 5.48 0 9.92-4.44 9.92-9.913 0-5.477-4.44-9.915-9.913-9.915zm.002 18a8.084 8.084 0 1 1 0-16.168 8.084 8.084 0 0 1 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M11.766 6.688c-2.5 0-3.22 2.188-3.22 2.188l1.412.854s.298-.79.9-1.23c.517-.374 1.626-.624 2.22.126.7.885-.17 1.587-1.078 2.72C11.047 12.53 11 15 11 15h1.97s.134-2.318 1.04-3.38c.603-.708 1.443-1.34 1.443-2.495s-1.187-2.437-3.687-2.437z"/>
+ <path id="bottom" d="M11 16h2v2h-2z"/>
+ </g>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-rtl.png
new file mode 100644
index 00000000..50899b0d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-rtl.svg
new file mode 100644
index 00000000..278b906b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/help-rtl.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="help">
+ <path id="circle" d="M12 2.085c5.477 0 9.915 4.438 9.915 9.916 0 5.48-4.438 9.92-9.916 9.92-5.48 0-9.92-4.44-9.92-9.913 0-5.477 4.44-9.915 9.913-9.915zm-.002 18a8.084 8.084 0 1 0 0-16.168 8.084 8.084 0 0 0 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M12.234 6.688c2.5 0 3.22 2.188 3.22 2.188l-1.412.854s-.298-.79-.9-1.23c-.517-.374-1.626-.624-2.22.126-.7.885.17 1.587 1.078 2.72C12.953 12.53 13 15 13 15h-1.97s-.134-2.318-1.04-3.38c-.603-.708-1.443-1.34-1.443-2.495 0-1.156 1.187-2.437 3.687-2.437z"/>
+ <path id="bottom" d="M13 16h-2v2h2z"/>
+ </g>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-ltr.png
new file mode 100644
index 00000000..73dd6b9c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-ltr.svg
new file mode 100644
index 00000000..eb42923d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24" width="24">
+ <path d="M5.066 18.236l.14-.244c.976-1.69 1.341-4.587.815-6.469l-.14-.507.2-.365L11.074 2l9.011 5.203-4.994 8.65-.204.354-.522.134c-1.893.485-4.22 2.252-5.195 3.94l-.14.244-.721-.416-1.041 1.89H3.914l1.893-3.336z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-rtl.png
new file mode 100644
index 00000000..2ea29830
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-rtl.svg
new file mode 100644
index 00000000..9b1940eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/highlight-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24" width="24">
+ <path d="M18.934 18.236l-.14-.244c-.976-1.69-1.341-4.587-.815-6.469l.14-.507-.2-.365L12.926 2 3.914 7.203l4.994 8.65.204.354.522.134c1.893.485 4.22 2.252 5.195 3.94l.14.244.721-.416 1.041 1.89h3.355l-1.893-3.336z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/history.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/history.png
new file mode 100644
index 00000000..417f5293
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/history.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/history.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/history.svg
new file mode 100644
index 00000000..68beaa13
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/history.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="history">
+ <path id="clock-hands" d="M17.26 15.076s-2.385-1.935-4.005-3.062c.72-2.397 1.702-6.56 1.702-6.56s-4.35 5.364-4.877 6.7c-.463 1.168 1.46 2.21 2.346 1.678 1.9.55 4.834 1.244 4.834 1.244z"/>
+ <path id="arrow" d="M12.086 2.085C6.608 2.085 2.17 6.523 2.17 12a9.86 9.86 0 0 0 1.3 4.9l-2.22 2.04h5.688v-5.22L4.87 15.616A7.982 7.982 0 0 1 4.004 12a8.084 8.084 0 0 1 16.167.004 8.08 8.08 0 0 1-8.08 8.085 7.975 7.975 0 0 1-3.21-.68L8.05 21.04a9.81 9.81 0 0 0 4.045.874C17.563 21.914 22 17.476 22 12c0-5.477-4.438-9.915-9.914-9.915z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/image.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/image.png
new file mode 100644
index 00000000..f76b3749
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/image.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/image.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/image.svg
new file mode 100644
index 00000000..00bcd21d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/image.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="image">
+ <path id="frame" d="M4 5v13h16V5zm15 12H5V6h14z"/>
+ <path id="mountains" d="M9.5 10l2.328 2.312-1.312 1.094.875 1.032L15.5 11l2.5 2v3H6v-2.5z"/>
+ <path id="sky" d="M9.516 7.844l3.046 3.172L15.5 9l2.5 2V7H6v5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-ltr.png
new file mode 100644
index 00000000..937ef3c8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-ltr.svg
new file mode 100644
index 00000000..c1970e41
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 8v11h14V8zm13 10H8V9h12zM9 14.945l2.917-2.723 1.94 1.8-1.094.85.73 1.024L16.917 13 19 14.556V17H9zm0-1.167l2.93-3.232 2.538 2.467 2.45-1.568L19 13v-3H9zM19 6v1H6v10H5V6zM3 4h14v1H4v10H3z" id="imageGallery"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-rtl.png
new file mode 100644
index 00000000..8a263225
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-rtl.svg
new file mode 100644
index 00000000..90298d2d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/imageGallery-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 8v11H3V8zM4 18h12V9H4zm11-3.055l-2.917-2.723-1.94 1.8 1.094.85-.73 1.024L7.083 13 5 14.556V17h10zm0-1.167l-2.93-3.232-2.538 2.467-2.45-1.568L5 13v-3h10zM5 6v1h13v10h1V6zm16-2H7v1h13v10h1z" id="imageGallery"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-ltr.png
new file mode 100644
index 00000000..ea48759b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-ltr.svg
new file mode 100644
index 00000000..cb238775
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-ltr.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="indent-list-ltr">
+ <path id="arrow" d="M5 15.08l4.794-3.528-4.704-3.6L5.08 10H3v3h2z"/>
+ <path id="bottom_line" d="M20 17H4a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h16a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1z"/>
+ <path id="middle_line" d="M20 10h-7a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h7a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1z"/>
+ <path id="top_line" d="M20 3H4a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h16a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-rtl.png
new file mode 100644
index 00000000..ea967d0c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-rtl.svg
new file mode 100644
index 00000000..c6527eec
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/indent-rtl.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="indent-list-rtl">
+ <path id="arrow" d="M19 15.08l-4.794-3.528 4.704-3.6.01 2.048H21v3h-2z"/>
+ <path id="bottom_line" d="M4 17h16a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1z"/>
+ <path id="middle_line" d="M4 10h7a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1z"/>
+ <path id="top_line_5_" d="M4 3h16a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/info.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/info.png
new file mode 100644
index 00000000..0b4270d6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/info.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/info.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/info.svg
new file mode 100644
index 00000000..72a9b4c6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/info.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="info">
+ <path id="circled-i" d="M11.5 17a5.5 5.5 0 1 1 0-11 5.5 5.5 0 0 1 0 11zm0-12a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zm.5 5v4h1v1h-3v-1h1v-3h-1v-1zm-1-2h1v1h-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-a.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-a.png
new file mode 100644
index 00000000..2f5fd187
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-a.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-a.svg
new file mode 100644
index 00000000..a3a11c68
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-a.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-a">
+ <path id="a" d="M14.667 6h-1.372l-7 12H8l2.333-4h4L15 18h1.667l-2-12zm-3.75 7l2.527-4.333.723 4.333h-3.25z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-keheh-jeem.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-keheh-jeem.png
new file mode 100644
index 00000000..c8e03eea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-keheh-jeem.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-keheh-jeem.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-keheh-jeem.svg
new file mode 100644
index 00000000..11b1458e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-keheh-jeem.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-arab-keheh-jeem">
+ <path id="arab-keheh-jeem" d="M18.125 5.844c-1.695.555-3.297 1.162-4.594 1.938-.49.3-.77.712-.87 1.125a1.26 1.26 0 0 0 .065.78c.19.406.54.575.844.814l.093-.12.53.627c.14.165.345.514.47.94.138.462.08.724 0 1.124h-3.44c-.34 0-.592.007-.766-.02-.34-.053-.256-.21-.234-.34.33-.127.56-.173.934-.14.29-.495.593-.886.906-1.314-.98.037-1.877.015-2.687-.094-.346-.046-.698-.185-1.094-.155-.36.026-.77.24-1.03.72-.25.447-.436.838-.66 1.28l.75-.47c.23-.14.486-.226.72-.218.158.004.276.053.407.093-.234.204-.51.4-.72.56-.3.26-.704.69-.908 1-.403.617-.694 1.086-.875 1.78-.18.69.003 1.34.468 1.75.426.38.846.52 1.28.566.65.064 1.206.092 2-.19.658-.23 1.022-.552 1.5-.97-.882.11-1.816.09-2.53.033-.87-.07-1.268-.386-1.47-.596-.27-.283-.306-.64-.155-1.22a1.44 1.44 0 0 1 .25-.53c.17-.228.363-.435.593-.656.45-.436 1.01-.737 1.46-.94-.042.207-.104.444-.052.69.05.23.25.38.44.47.26.12.506.152.69.153 1.42.01 2.86 0 4.28 0 .246 0 .45-.163.593-.375.14-.21.25-.48.343-.845.13-.5.094-1.062-.094-1.625a4.812 4.812 0 0 0-.72-1.406c-.336-.444-.675-.83-1-1.22 1.256-.815 2.715-1.24 3.97-1.688.12-.452.222-.926.31-1.313zm-9.47 8.438c-.26.394-.583.69-.874 1 .38.286.75.556 1.1.813.336-.303.627-.674.876-.97-.39-.267-.77-.587-1.093-.843z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-meem.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-meem.png
new file mode 100644
index 00000000..409a4165
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-meem.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-meem.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-meem.svg
new file mode 100644
index 00000000..f15586e0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-arab-meem.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-arab-meem">
+ <path id="arab-meem" d="M16 9.73l-.93 2.19h-4.663c-.48 0-.857.12-1.135.366l-.06.11c-.185 2.016-.503 3.558-.956 4.627a8.31 8.31 0 0 1-1.082 1.833c-.177.226-.22.186-.126-.12l.142-.503.17-.67.234-.87.002-.008.202-1.045.258-1.41.353-1.907c.19-.312.42-.638.692-.98a24.1 24.1 0 0 1 .94-1.09c.13-.092.697-.18 1.705-.266 1.05-.086 1.64-.183 1.765-.293l.065-.128c.01-.11-.01-.24-.052-.394a2.403 2.403 0 0 0-.232-.522c-.22-.428-.438-.64-.654-.64-.294 0-.915.268-1.864.805-.36.208-.378.125-.05-.247 1.555-1.71 2.705-2.566 3.45-2.566.38 0 .67.13.86.394.134.195.25.6.343 1.21l.202 1.2c.105.586.24.895.408.925"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-armn-sha.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-armn-sha.png
new file mode 100644
index 00000000..2dd80f7f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-armn-sha.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-armn-sha.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-armn-sha.svg
new file mode 100644
index 00000000..c32ff494
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-armn-sha.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-armn-sha">
+ <path id="armn-sha" d="M11.564 7.678a3.073 3.073 0 0 0-.93-.268c-.35-.047-.75-.07-1.197-.07h-1.11L8.587 6h1.723c.558 0 1.042.032 1.45.095.416.063.794.173 1.136.33l4.483 2.033-.33 1.67-2.625-1.165a1.867 1.867 0 0 0-.433-.134 2.45 2.45 0 0 0-.576-.06 4.88 4.88 0 0 0-1.663.28c-.526.19-1 .46-1.427.812-.42.35-.776.78-1.07 1.283a5.48 5.48 0 0 0-.63 1.71c-.24 1.255-.15 2.21.27 2.87.424.65 1.19.976 2.292.976.55 0 1.044-.08 1.48-.236a3.488 3.488 0 0 0 1.135-.66c.325-.29.59-.634.795-1.034.21-.4.363-.84.458-1.322l.11-.56h1.6l-.12.59a5.925 5.925 0 0 1-.676 1.844 5.19 5.19 0 0 1-1.214 1.423c-.488.395-1.053.7-1.694.923a6.573 6.573 0 0 1-2.106.324c-.767 0-1.434-.114-2-.34-.568-.226-1.025-.554-1.372-.985-.347-.437-.573-.97-.678-1.608-.105-.64-.078-1.366.08-2.186.125-.66.346-1.274.66-1.836A6.332 6.332 0 0 1 8.792 9.54a5.955 5.955 0 0 1 1.496-1.072 5.87 5.87 0 0 1 1.732-.57l-.465-.23"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-c.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-c.png
new file mode 100644
index 00000000..dc70ded4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-c.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-c.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-c.svg
new file mode 100644
index 00000000..b85eb029
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-c.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-c">
+ <path id="c" d="M15.008 13.718l1.48.214c-.467 1.34-1.15 2.354-2.045 3.04a4.835 4.835 0 0 1-3.015 1.03c-1.36 0-2.438-.43-3.237-1.29C7.4 15.85 7 14.618 7 13.012c0-2.09.606-3.817 1.817-5.184C9.897 6.61 11.237 6 12.84 6c1.186 0 2.145.33 2.878.99.738.66 1.165 1.546 1.282 2.66l-1.397.135c-.148-.84-.453-1.464-.916-1.876-.458-.42-1.05-.63-1.78-.63-1.368 0-2.475.63-3.32 1.89-.733 1.087-1.1 2.377-1.1 3.87 0 1.194.283 2.104.848 2.732.565.628 1.3.942 2.206.942.78 0 1.48-.26 2.1-.785.63-.52 1.08-1.26 1.37-2.216"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-d.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-d.png
new file mode 100644
index 00000000..cd5ac9d4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-d.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-d.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-d.svg
new file mode 100644
index 00000000..dbc1d40f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-d.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-d">
+ <path id="d" d="M7 18L9.462 6h3.557c.85 0 1.5.063 1.95.188.642.17 1.192.472 1.65.91.454.43.8.97 1.03 1.62.23.65.344 1.378.344 2.186 0 .966-.146 1.847-.436 2.644-.284.79-.66 1.49-1.127 2.095-.46.6-.946 1.072-1.455 1.416-.504.33-1.1.582-1.794.75-.525.122-1.17.19-1.94.19H7m1.86-1.36h1.866c.842 0 1.59-.08 2.245-.24a3.26 3.26 0 0 0 1.05-.436 4.19 4.19 0 0 0 1.04-.975 6.652 6.652 0 0 0 .975-1.825c.247-.687.37-1.467.37-2.34 0-.97-.166-1.716-.5-2.235-.332-.522-.755-.87-1.27-1.04-.38-.124-.974-.186-1.78-.186H11L9.095 16.64"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-e.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-e.png
new file mode 100644
index 00000000..bb51c22c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-e.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-e.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-e.svg
new file mode 100644
index 00000000..f3851498
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-e.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-e">
+ <path id="e" d="M7 18L9.474 6H18l-.282 1.367H10.77L10.02 11h6.09l-.28 1.367H9.74l-.88 4.273h7.44L16.018 18H7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-geor-kan.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-geor-kan.png
new file mode 100644
index 00000000..9750f428
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-geor-kan.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-geor-kan.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-geor-kan.svg
new file mode 100644
index 00000000..9a54880e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-geor-kan.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-geor-kan">
+ <path id="geor-kan" d="M15.057 14.663C14.617 16.888 13.223 18 10.88 18 8.96 18 8 17.213 8 15.64c0-.298.036-.624.108-.977.083-.43.245-.836.488-1.217l1.24.605-.206.62c-.055.26-.083.497-.083.71 0 .97.52 1.46 1.564 1.46 1.31 0 2.108-.724 2.39-2.17l.058-.33a3.17 3.17 0 0 0 .066-.615c0-.927-.546-1.39-1.64-1.39H10.87l.247-1.26h1.118c1.203-.004 1.91-.55 2.12-1.64.04-.18.057-.355.057-.52 0-1.144-.9-1.715-2.696-1.715L11.94 6C14.646 6 16 6.877 16 8.627c0 .248-.027.516-.082.803-.204 1.092-1.05 1.824-2.54 2.194l-.033.166c1.23.2 1.845.823 1.845 1.872 0 .21-.025.433-.074.67l-.058.332"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-i.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-i.png
new file mode 100644
index 00000000..a37620b7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-i.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-i.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-i.svg
new file mode 100644
index 00000000..e670e9bf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-i.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-i">
+ <path id="i" d="M12.5 18l.25-.995h-1.5l2.508-10.037h1.5L15.5 6h-5l-.242.968h1.5l-2.51 10.037h-1.5L7.5 18z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-k.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-k.png
new file mode 100644
index 00000000..9b156fd2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-k.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-k.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-k.svg
new file mode 100644
index 00000000..38bcd73a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-k.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-k">
+ <path id="k" d="M12.018 10.652L17 6h-2l-5.31 5.234L11 6H9.5l-3 12H8l1.173-4.693 1.54-1.438C11 16 14 18 14 18h2s-4-2-3.982-7.348z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-s.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-s.png
new file mode 100644
index 00000000..3213d6d8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-s.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-s.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-s.svg
new file mode 100644
index 00000000..b3fb3403
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/italic-s.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-s">
+ <path id="s" d="M16.474 6.59l-.302 1.525a7.36 7.36 0 0 0-1.557-.628 5.432 5.432 0 0 0-1.487-.217c-.935 0-1.68.204-2.23.612-.554.408-.83.95-.83 1.627 0 .37.1.65.302.86.207.19.733.4 1.58.63l.937.23c1.06.274 1.795.622 2.208 1.046.413.42.62 1.007.62 1.766 0 1.167-.46 2.117-1.38 2.85-.913.734-2.12 1.1-3.617 1.1-.615 0-1.232-.06-1.852-.185-.62-.12-1.242-.3-1.867-.55l.31-1.61a7.613 7.613 0 0 0 1.72.805c.58.18 1.155.27 1.73.27.976 0 1.76-.216 2.347-.65.59-.434.883-1 .883-1.697 0-.465-.12-.816-.354-1.054-.233-.242-.737-.46-1.512-.657l-.937-.24c-1.07-.28-1.8-.6-2.19-.964-.39-.368-.584-.88-.584-1.535 0-1.152.442-2.094 1.325-2.828.89-.74 2.043-1.108 3.463-1.108.555 0 1.1.05 1.644.146.542.1 1.085.245 1.627.442"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-ltr.png
new file mode 100644
index 00000000..2af4eb0e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-ltr.svg
new file mode 100644
index 00000000..8a83e417
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 8V7h-6v1h6zm-2 2V9h-4v1h4zM6 4h1v16H6V4zm2 0h10v13c0 1.7-1.3 3-3 3H8V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-rtl.png
new file mode 100644
index 00000000..033ede13
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-rtl.svg
new file mode 100644
index 00000000..2a07a44a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/journal-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 8V7h6v1H8zm2 2V9h4v1h-4zm8-6h-1v16h1V4zm-2 0H6v13c0 1.7 1.3 3 3 3h7V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr-invert.png
new file mode 100644
index 00000000..265da142
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr-invert.svg
new file mode 100644
index 00000000..131bbdbc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M14.5 4C11.5 4 9 6.5 9 9.5c0 1 .3 1.9.7 2.8L4 18v2h4v-2h2v-2h2l1.2-1.2c.4.1.9.2 1.3.2 3 0 5.5-2.5 5.5-5.5S17.5 4 14.5 4zM16 9c-.8 0-1.5-.7-1.5-1.5S15.2 6 16 6s1.5.7 1.5 1.5S16.8 9 16 9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr.png
new file mode 100644
index 00000000..9a4dca83
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr.svg
new file mode 100644
index 00000000..fc0d3c34
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14.5 4C11.5 4 9 6.5 9 9.5c0 1 .3 1.9.7 2.8L4 18v2h4v-2h2v-2h2l1.2-1.2c.4.1.9.2 1.3.2 3 0 5.5-2.5 5.5-5.5S17.5 4 14.5 4zM16 9c-.8 0-1.5-.7-1.5-1.5S15.2 6 16 6s1.5.7 1.5 1.5S16.8 9 16 9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl-invert.png
new file mode 100644
index 00000000..a5f29046
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl-invert.svg
new file mode 100644
index 00000000..906ee6e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M9.5 4c3 0 5.5 2.5 5.5 5.5 0 1-.3 1.9-.7 2.8L20 18v2h-4v-2h-2v-2h-2l-1.2-1.2c-.4.1-.9.2-1.3.2-3 0-5.5-2.5-5.5-5.5S6.5 4 9.5 4zM8 9c.8 0 1.5-.7 1.5-1.5S8.8 6 8 6s-1.5.7-1.5 1.5S7.2 9 8 9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl.png
new file mode 100644
index 00000000..f49e1125
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl.svg
new file mode 100644
index 00000000..6dedfe83
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/key-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9.5 4c3 0 5.5 2.5 5.5 5.5 0 1-.3 1.9-.7 2.8L20 18v2h-4v-2h-2v-2h-2l-1.2-1.2c-.4.1-.9.2-1.3.2-3 0-5.5-2.5-5.5-5.5S6.5 4 9.5 4zM8 9c.8 0 1.5-.7 1.5-1.5S8.8 6 8 6s-1.5.7-1.5 1.5S7.2 9 8 9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr-invert.png
new file mode 100644
index 00000000..d7d1a0be
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr-invert.svg
new file mode 100644
index 00000000..238ca48f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M3 7v9c0 1.7 1.3 3 3 3h15V7H3zm8 2h2v2h-2V9zm0 3h2v2h-2v-2zM8 9h2v2H8V9zm0 3h2v2H8v-2zm-1 5H6c-.6 0-1-.4-1-1v-1h2v2zm0-3H5v-2h2v2zm0-3H5V9h2v2zm9 6H8v-2h8v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2zm3 6h-2v-2h2v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr.png
new file mode 100644
index 00000000..886d37a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr.svg
new file mode 100644
index 00000000..c4c442ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 7v9c0 1.7 1.3 3 3 3h15V7H3zm8 2h2v2h-2V9zm0 3h2v2h-2v-2zM8 9h2v2H8V9zm0 3h2v2H8v-2zm-1 5H6c-.6 0-1-.4-1-1v-1h2v2zm0-3H5v-2h2v2zm0-3H5V9h2v2zm9 6H8v-2h8v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2zm3 6h-2v-2h2v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl-invert.png
new file mode 100644
index 00000000..1b0275e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl-invert.svg
new file mode 100644
index 00000000..82488041
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M21 7v9c0 1.7-1.3 3-3 3H3V7h18zm-8 2h-2v2h2V9zm0 3h-2v2h2v-2zm3-3h-2v2h2V9zm0 3h-2v2h2v-2zm1 5h1c.6 0 1-.4 1-1v-1h-2v2zm0-3h2v-2h-2v2zm0-3h2V9h-2v2zm-9 6h8v-2H8v2zm0-3h2v-2H8v2zm0-3h2V9H8v2zm-3 6h2v-2H5v2zm0-3h2v-2H5v2zm0-3h2V9H5v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl.png
new file mode 100644
index 00000000..790a5e2d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl.svg
new file mode 100644
index 00000000..b37d7f4c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/keyboard-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 7v9c0 1.7-1.3 3-3 3H3V7h18zm-8 2h-2v2h2V9zm0 3h-2v2h2v-2zm3-3h-2v2h2V9zm0 3h-2v2h2v-2zm1 5h1c.6 0 1-.4 1-1v-1h-2v2zm0-3h2v-2h-2v2zm0-3h2V9h-2v2zm-9 6h8v-2H8v2zm0-3h2v-2H8v2zm0-3h2V9H8v2zm-3 6h2v-2H5v2zm0-3h2v-2H5v2zm0-3h2V9H5v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-ltr.png
new file mode 100644
index 00000000..f7b785c9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-ltr.svg
new file mode 100644
index 00000000..d64b7343
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-ltr.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="A">
+ <path d="M18.738 15.673l1.137 3.15h1.575L17.775 7.448h-2.188l-3.85 11.375h1.575l1.05-3.15h4.375zM16.55 8.76l1.837 5.427h-3.675l1.838-5.425z"/>
+ </g>
+ <g id="文">
+ <path d="M8.325 6.573h.787l-.875-1.75h-1.75l.438.875a1.56 1.56 0 0 0 1.4.875z"/>
+ <path d="m 9.202,12.874 c 0.7,0.525 1.486,0.963 2.45,1.225 l -0.438,1.31 A 9.17,9.17 0 0 1 8.151,13.835 c -1.49,1.137 -3.063,1.837 -4.813,2.363 L 2.9,14.885 C 4.386,14.36 5.874,13.835 7.1,12.872 5.962,11.648 5.174,10.335 4.65,8.758 l -1.663,0 0,-1.31 10.85,0 -0.438,1.312 -1.75,0 c -0.308,1.33 -1.255,2.957 -2.45,4.114 z m 1.05,-4.114 -4.114,0 c 0.35,1.226 1.138,2.363 2.013,3.238 0.926,-1 1.617,-1.957 2.1,-3.237 z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-rtl.png
new file mode 100644
index 00000000..c78f2cd6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-rtl.svg
new file mode 100644
index 00000000..cf6c1d51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/language-rtl.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="A">
+ <path d="M5.612 15.673l-1.137 3.15H2.9L6.575 7.448h2.188l3.85 11.375h-1.575l-1.05-3.15H5.613zM7.8 8.76l-1.837 5.427h3.675L7.8 8.762z" id="path5"/>
+ </g>
+ <g id="文">
+ <path d="M16.384 6.573h.787l-.873-1.75h-1.75l.438.875c.26.535.805.874 1.4.875z" id="path7"/>
+ <path d="M15.15 12.874c-.7.525-1.486.963-2.45 1.225l.438 1.31a9.17 9.17 0 0 0 3.063-1.575c1.49 1.137 3.064 1.837 4.814 2.363l.438-1.313c-1.486-.525-2.974-1.05-4.2-2.013 1.138-1.224 1.926-2.537 2.45-4.114h1.663v-1.31h-10.85l.438 1.312h1.75c.308 1.33 1.255 2.957 2.45 4.114zM14.1 8.76h4.114c-.35 1.226-1.138 2.363-2.013 3.238-.925-1-1.616-1.957-2.1-3.237z" id="path11-7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr-invert.png
new file mode 100644
index 00000000..264811bc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr-invert.svg
new file mode 100644
index 00000000..491adb53
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M20.8 20h-8.1v-.8c.4 0 .8-.1 1.3-.2s.8-.2.8-.4v-.2c0-.1 0-.2-.1-.3L13.4 15H8.3c-.1.3-.2.6-.4 1-.1.4-.3.7-.4 1-.1.4-.2.7-.2.8v.4c0 .2.2.4.5.6.3.2.9.3 1.7.3v.9H3.4v-.8c.2 0 .5-.1.8-.1.3-.1.5-.1.7-.2.3-.2.5-.4.7-.6.2-.3.4-.6.5-.9.8-2 1.6-3.9 2.4-5.9.8-2 1.7-4.1 2.7-6.5h2.1c1.4 3.3 2.4 6 3.2 7.9.8 1.9 1.4 3.6 2 4.8l.3.6c.1.2.3.3.6.5.2.1.4.2.7.3.3.1.5.1.7.1v.8zM13 14l-2.1-5.3L8.8 14H13z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr.png
new file mode 100644
index 00000000..4b6d298f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr.svg
new file mode 100644
index 00000000..4b01d742
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20.8 20h-8.1v-.8c.4 0 .8-.1 1.3-.2s.8-.2.8-.4v-.2c0-.1 0-.2-.1-.3L13.4 15H8.3c-.1.3-.2.6-.4 1-.1.4-.3.7-.4 1-.1.4-.2.7-.2.8v.4c0 .2.2.4.5.6.3.2.9.3 1.7.3v.9H3.4v-.8c.2 0 .5-.1.8-.1.3-.1.5-.1.7-.2.3-.2.5-.4.7-.6.2-.3.4-.6.5-.9.8-2 1.6-3.9 2.4-5.9.8-2 1.7-4.1 2.7-6.5h2.1c1.4 3.3 2.4 6 3.2 7.9.8 1.9 1.4 3.6 2 4.8l.3.6c.1.2.3.3.6.5.2.1.4.2.7.3.3.1.5.1.7.1v.8zM13 14l-2.1-5.3L8.8 14H13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl-invert.png
new file mode 100644
index 00000000..b91b35c8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl-invert.svg
new file mode 100644
index 00000000..4842411a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M3.4 20h8.1v-.8c-.4 0-.8-.1-1.3-.2s-.8-.2-.8-.4v-.2c0-.1 0-.2.1-.3l1.3-3.1h5.1c.1.3.2.6.4 1 .1.4.3.7.4 1 .1.4.2.7.2.8v.4c0 .2-.2.4-.5.6-.3.2-.9.3-1.7.3v.9h6.1v-.8c-.2 0-.5-.1-.8-.1-.3-.1-.5-.1-.7-.2-.3-.2-.5-.4-.7-.6-.2-.3-.4-.6-.5-.9-.8-2-1.6-3.9-2.4-5.9-.8-2-1.7-4.1-2.7-6.5h-2.1c-1.4 3.3-2.4 6-3.2 7.9-.8 1.9-1.4 3.6-2 4.8l-.3.6c-.1.2-.3.3-.6.5-.2.1-.4.2-.7.3-.3.1-.5.1-.7.1v.8zm7.8-6l2.1-5.3 2.1 5.3h-4.2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl.png
new file mode 100644
index 00000000..77d77968
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl.svg
new file mode 100644
index 00000000..6ac62dc9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/largerText-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3.4 20h8.1v-.8c-.4 0-.8-.1-1.3-.2s-.8-.2-.8-.4v-.2c0-.1 0-.2.1-.3l1.3-3.1h5.1c.1.3.2.6.4 1 .1.4.3.7.4 1 .1.4.2.7.2.8v.4c0 .2-.2.4-.5.6-.3.2-.9.3-1.7.3v.9h6.1v-.8c-.2 0-.5-.1-.8-.1-.3-.1-.5-.1-.7-.2-.3-.2-.5-.4-.7-.6-.2-.3-.4-.6-.5-.9-.8-2-1.6-3.9-2.4-5.9-.8-2-1.7-4.1-2.7-6.5h-2.1c-1.4 3.3-2.4 6-3.2 7.9-.8 1.9-1.4 3.6-2 4.8l-.3.6c-.1.2-.3.3-.6.5-.2.1-.4.2-.7.3-.3.1-.5.1-.7.1v.8zm7.8-6l2.1-5.3 2.1 5.3h-4.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-ltr.png
new file mode 100644
index 00000000..ea6d2f5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-ltr.svg
new file mode 100644
index 00000000..c3be66cc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="layout-ltr">
+ <path id="text" d="M5 19V5h6v8h8v6H5z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm5 5h-4V6h4v4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-rtl.png
new file mode 100644
index 00000000..46bf59b1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-rtl.svg
new file mode 100644
index 00000000..ce7feb8d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/layout-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="layout-rtl">
+ <path id="text" d="M5 19v-6h8V5h6v14H5z"/>
+ <path id="float" d="M5 5v6h6V5H5zm1 1h4v4H6V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/link.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/link.png
new file mode 100644
index 00000000..985a5205
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/link.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/link.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/link.svg
new file mode 100644
index 00000000..e37b3900
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/link.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="link">
+ <path id="right" d="M19.188 12c0 1.1-.89 2.016-1.988 2.016L13.005 14c.538 1.09.963 2 1.997 2h3C19.658 16 21 13.657 21 12s-1.342-4-2.998-4h-3c-1.034 0-1.46.91-1.998 2l4.195-.016c1.09 0 1.982.917 1.982 2.017z"/>
+ <path id="center" d="M8 12c0 .535.42 1 .938 1h6.11c.517 0 .937-.465.937-1 0-.534-.42-1-.938-1h-6.11C8.42 11 8 11.466 8 12z"/>
+ <path id="left" d="M4.816 12c0-1.1.89-2.016 1.988-2.016L11 10c-.54-1.09-.964-2-1.998-2h-3c-1.656 0-2.998 2.343-2.998 4s1.342 4 2.998 4h3c1.034 0 1.46-.91 1.998-2l-4.195.016c-1.098 0-1.99-.917-1.99-2.017z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-ltr.png
new file mode 100644
index 00000000..e6787338
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-ltr.svg
new file mode 100644
index 00000000..94ae5b49
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-ltr.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bullet-list-ltr">
+ <path id="bottom_dot" d="M5 10H4a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1z"/>
+ <path id="middle_dot" d="M5 17H4a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1z"/>
+ <path id="top_dot" d="M5 3H4a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h1a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1z"/>
+ <path id="bottom_line" d="M20 17H9a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1z"/>
+ <path id="middle_line" d="M20 10H9a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1z"/>
+ <path id="top_line" d="M20 3H9a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h11a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-rtl.png
new file mode 100644
index 00000000..d5bba7a4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-rtl.svg
new file mode 100644
index 00000000..c37a729b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listBullet-rtl.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bullet-list-rtl">
+ <path id="bottom_dot_1_" d="M19 10h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1z"/>
+ <path id="middle_dot_1_" d="M19 17h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1z"/>
+ <path id="top_dot_1_" d="M19 3h1a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1h-1a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/>
+ <path id="bottom_line_7_" d="M4 17h11a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1z"/>
+ <path id="middle_line_7_" d="M4 10h11a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1z"/>
+ <path id="top_line_7_" d="M4 3h11a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-ltr.png
new file mode 100644
index 00000000..fc2a369d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-ltr.svg
new file mode 100644
index 00000000..8c4fcf29
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-ltr.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="number-list-ltr">
+ <path id="bottom_dot" d="M3 16v1h1.993l.03 1H4v1h1v1H3v1h2.023L6 19.998v-1l-.955-.53.955-.5v-.97L4.993 16z"/>
+ <path id="middle_dot" d="M3 9v1h2.117L3 12.187v1.81l3-.06V13H3.882L6 10.812V9.78L5.332 9z"/>
+ <path id="top_dot" d="M4.993 2h-.648L3.018 3.39l.03.61h1.026l-.068 2H3v1h3V6H4.963z"/>
+ <path id="bottom_line" d="M20.002 17H9a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h11.002A1 1 0 0 0 21 19v-1a1 1 0 0 0-.998-1z"/>
+ <path id="middle_line" d="M20.002 10H9a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h11.002A1 1 0 0 0 21 12v-1a1 1 0 0 0-.998-1z"/>
+ <path id="top_line" d="M20.002 3H9a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h11.002A1 1 0 0 0 21 5V4a1 1 0 0 0-.998-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-rtl.png
new file mode 100644
index 00000000..fd7bc005
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-rtl.svg
new file mode 100644
index 00000000..f26313b2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/listNumbered-rtl.svg
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="number-list-rtl">
+ <path id="bottom_dot" d="M18 16v1h1.993l.03 1H19v1h1v1h-2v1h2.023L21 19.998v-1l-.956-.53.956-.5v-.97L19.993 16z"/>
+ <path id="middle_dot" d="M18 9v1h2.116L18 12.187v1.81l3-.06V13h-2.118L21 10.812V9.78L20.33 9z"/>
+ <path id="top_dot" d="M19.993 2h-.648l-1.328 1.39.03.61h1.027l-.07 2H18v1h3V6h-1.038z"/>
+ <path id="bottom_line" d="M4 17h11a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1z"/>
+ <path id="middle_line" d="M4 10h11a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1z"/>
+ <path id="top_line" d="M4 3h11a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/lock.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/lock.png
new file mode 100644
index 00000000..5f295f8b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/lock.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/lock.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/lock.svg
new file mode 100644
index 00000000..d9356469
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/lock.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 6a4 4 0 0 0-4 4v1H7v7h10v-7h-1v-1a4 4 0 0 0-4-4zm0 2a2 2 0 0 1 2 2v1h-4v-1a2 2 0 0 1 2-2z" id="lock"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr-invert.png
new file mode 100644
index 00000000..fb1bb0c9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr-invert.svg
new file mode 100644
index 00000000..8b10f255
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M15 14v3l5-4.5L15 8v3H8c0 1.7 1.3 3 3 3h4zm-1-9H4v15h10v-2H6V7h8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr.png
new file mode 100644
index 00000000..18f82eb8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr.svg
new file mode 100644
index 00000000..f2be068b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 14v3l5-4.5L15 8v3H8c0 1.7 1.3 3 3 3h4zm-1-9H4v15h10v-2H6V7h8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl-invert.png
new file mode 100644
index 00000000..dcd2f15e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl-invert.svg
new file mode 100644
index 00000000..412cd928
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M9 14v3l-5-4.5L9 8v3h7c0 1.7-1.3 3-3 3H9zm1-9h10v15H10v-2h8V7h-8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl.png
new file mode 100644
index 00000000..0ffb7235
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl.svg
new file mode 100644
index 00000000..5f5ebb90
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/logOut-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 14v3l-5-4.5L9 8v3h7c0 1.7-1.3 3-3 3H9zm1-9h10v15H10v-2h8V7h-8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/markup.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/markup.png
new file mode 100644
index 00000000..c78f4185
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/markup.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/markup.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/markup.svg
new file mode 100644
index 00000000..7f8c2535
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/markup.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="markup">
+ <path id="left-bracket" d="M9.665 6.32l-4.259 4.274-1.406 1.406 1.406 1.406 4.259 4.274 1.406-1.438-4.259-4.243 4.259-4.243z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" xlink:href="#left-bracket"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/menu.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/menu.png
new file mode 100644
index 00000000..d2278db8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/menu.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/menu.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/menu.svg
new file mode 100644
index 00000000..a33c21ca
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/menu.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="menu">
+ <path id="lines" d="M6 15h12a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1zm-1-4v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1zm0-5v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.png
new file mode 100644
index 00000000..2171c1f3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.svg
new file mode 100644
index 00000000..842d312c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 9c0-1.7-1.3-3-3-3H3v3l9 4 9-4zM3 11v6c0 1.7 1.3 3 3 3h15v-9l-9 4-9-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.png
new file mode 100644
index 00000000..fba79205
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.svg
new file mode 100644
index 00000000..0a22c751
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/message-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 9c0-1.7 1.3-3 3-3h15v3l-9 4-9-4zm18 2v6c0 1.7-1.3 3-3 3H3v-9l9 4 9-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon-invert.png
new file mode 100644
index 00000000..38bcc0ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon-invert.svg
new file mode 100644
index 00000000..7ecd512b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M19.1 17.5c-3.3 1.4-7.1-.2-8.5-3.5-1.4-3.3.2-7.1 3.5-8.5.2-.1.5-.2.7-.3-1.6-.4-3.2-.3-4.8.4C6 7.3 4 12 5.7 16c1.7 4.1 6.4 6 10.5 4.3 1.7-.7 3-1.9 3.8-3.4-.3.3-.6.4-.9.6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon.png
new file mode 100644
index 00000000..7aef8bd8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon.svg
new file mode 100644
index 00000000..bdbf2346
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/moon.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19.1 17.5c-3.3 1.4-7.1-.2-8.5-3.5-1.4-3.3.2-7.1 3.5-8.5.2-.1.5-.2.7-.3-1.6-.4-3.2-.3-4.8.4C6 7.3 4 12 5.7 16c1.7 4.1 6.4 6 10.5 4.3 1.7-.7 3-1.9 3.8-3.4-.3.3-.6.4-.9.6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-ltr.png
new file mode 100644
index 00000000..9d35b9ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-ltr.svg
new file mode 100644
index 00000000..98adcf7a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="move-end-ltr">
+ <path id="arrow" d="M7.935 7.18l5.302 5.303-5.302 5.303L9.35 19.2l6.715-6.717L9.35 5.767z"/>
+ <path id="bar" d="M16 7h2v11h-2z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-rtl.png
new file mode 100644
index 00000000..bcd8a0c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-rtl.svg
new file mode 100644
index 00000000..5f9d60d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-end-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="move-end-ltr">
+ <path id="arrow" d="M16.065 17.786l-5.302-5.303 5.302-5.302-1.415-1.41-6.714 6.72 6.714 6.71z"/>
+ <path id="bar" d="M6 7h2v11H6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-ltr.png
new file mode 100644
index 00000000..b57d8daa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-ltr.svg
new file mode 100644
index 00000000..670d84d1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="move-ltr">
+ <path id="arrow" d="M8.935 7.18l5.302 5.303-5.302 5.303L10.35 19.2l6.715-6.717-6.716-6.716z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-rtl.png
new file mode 100644
index 00000000..e401a8f8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-rtl.svg
new file mode 100644
index 00000000..ce5b444f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="move-rtl">
+ <path id="arrow" d="M15.065 17.786l-5.302-5.303 5.302-5.302-1.415-1.41-6.714 6.72 6.714 6.71z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move.png
new file mode 100644
index 00000000..7071499f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move.svg
new file mode 100644
index 00000000..b04ecdd4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/move.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 11l-4-3v2h-3V7h2l-3-4-3 4h2v3H8V8l-4 3 4 3v-2h3v3H9l3 4 3-4h-2v-3h3v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr-invert.png
new file mode 100644
index 00000000..5e432b04
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr-invert.svg
new file mode 100644
index 00000000..18e41186
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M12 5l2.5 2.5L11 11c-1.2 1.2-1.2 2.8 0 4l5.5-5.5L19 12V5h-7zm5 12H8c-.6 0-1-.4-1-1V7h3L8 5H5v11c0 1.7 1.3 3 3 3h11v-3l-2-2v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr.png
new file mode 100644
index 00000000..29563d87
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr.svg
new file mode 100644
index 00000000..2d19a78f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5l2.5 2.5L11 11c-1.2 1.2-1.2 2.8 0 4l5.5-5.5L19 12V5h-7zm5 12H8c-.6 0-1-.4-1-1V7h3L8 5H5v11c0 1.7 1.3 3 3 3h11v-3l-2-2v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl-invert.png
new file mode 100644
index 00000000..f9a742e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl-invert.svg
new file mode 100644
index 00000000..e357be69
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M12 5L9.5 7.5 13 11c1.2 1.2 1.2 2.8 0 4L7.5 9.5 5 12V5h7zM7 17h9c.6 0 1-.4 1-1V7h-3l2-2h3v11c0 1.7-1.3 3-3 3H5v-3l2-2v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl.png
new file mode 100644
index 00000000..c49609f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl.svg
new file mode 100644
index 00000000..133442ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newWindow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5L9.5 7.5 13 11c1.2 1.2 1.2 2.8 0 4L7.5 9.5 5 12V5h7zM7 17h9c.6 0 1-.4 1-1V7h-3l2-2h3v11c0 1.7-1.3 3-3 3H5v-3l2-2v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-ltr.png
new file mode 100644
index 00000000..f41eb0c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-ltr.svg
new file mode 100644
index 00000000..a7e5b126
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.8 5.7c-.5 0-.9.2-1.2.5s-.5.7-.5 1.2v4.3H11v-4l-6 5.5 6 5.5v-4h8v-9h-1.2z" id="line_return"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-rtl.png
new file mode 100644
index 00000000..93c7e52c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-rtl.svg
new file mode 100644
index 00000000..40752fa7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/newline-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6.2 5.7c.5 0 .9.2 1.2.5.3.3.5.7.5 1.2v4.3H13v-4l6 5.5-6 5.5v-4H5v-9h1.2z" id="line_return"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-ltr.png
new file mode 100644
index 00000000..2623b845
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-ltr.svg
new file mode 100644
index 00000000..2dfa2c73
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 13l2 2V5h-3v2h1zM3 3L2 4l1 1v14h3v-2H5V7l2 2v10h3v-2H9v-6l6 6h-1v2h3l3 3 1-1-3-3zm7 4V5H7l2 2zm8-2v2h1v10l2 2V5z" id="noWikiText-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-rtl.png
new file mode 100644
index 00000000..4d0ce869
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-rtl.svg
new file mode 100644
index 00000000..4f275fd6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/noWikiText-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 13l-2 2V5h3v2H9zM21 3l1 1-1 1v14h-3v-2h1V7l-2 2v10h-3v-2h1v-6l-6 6h1v2H7l-3 3-1-1 3-3zm-7 4V5h3l-2 2zM6 5v2H5v10l-2 2V5z" id="noWikiText-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright-invert.png
new file mode 100644
index 00000000..de7e5297
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright-invert.svg
new file mode 100644
index 00000000..ca20b5ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright.png
new file mode 100644
index 00000000..5273b4c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright.svg
new file mode 100644
index 00000000..af87ff9f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notBright.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notice.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notice.png
new file mode 100644
index 00000000..114020ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notice.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notice.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notice.svg
new file mode 100644
index 00000000..8dc4fec7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/notice.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="svg3116">
+ <path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm-1-5h2V8h-2zm0 3h2v-2h-2z" id="alert"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-ltr.png
new file mode 100644
index 00000000..df49095b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-ltr.svg
new file mode 100644
index 00000000..658809d8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M17.8 18.6H2.5l2.7-2.7V6h15.3v9.9c0 1.53-1.17 2.7-2.7 2.7zm-7.542-4.95c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945z" id="ongoing-conversation" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-rtl.png
new file mode 100644
index 00000000..3d7e9bda
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-rtl.svg
new file mode 100644
index 00000000..648ce55a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ongoingConversation-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M5.2 18.6h15.3l-2.7-2.7V6H2.5v9.9c0 1.53 1.17 2.7 2.7 2.7zm7.542-4.95c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.608.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.608-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.608.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.332 1.332 0 0 0-.945-.405c-.337 0-.675.135-.945.405-.27.27-.405.608-.405.945z" id="ongoing-conversation" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-ltr.png
new file mode 100644
index 00000000..e3af6729
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-ltr.svg
new file mode 100644
index 00000000..ad55ed42
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-ltr.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="outdent-list-ltr">
+ <path id="arrow" d="M8 13h2v-3H7.948l-.03-2.06-4.713 3.585L8 15.08z"/>
+ <path id="bottom_line" d="M20 17H4a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h16a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1z"/>
+ <path id="middle_line" d="M20 10h-7a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h7a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1z"/>
+ <path id="top_line" d="M20 3H4a1 1 0 0 0-1 1v1a1 1 0 0 0 1 1h16a1 1 0 0 0 1-1V4a1 1 0 0 0-1-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-rtl.png
new file mode 100644
index 00000000..ff08acf1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-rtl.svg
new file mode 100644
index 00000000..64ad8b04
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outdent-rtl.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="outdent-list-rtl">
+ <path id="arrow" d="M16 13h-2v-3h2.052l.03-2.06 4.713 3.585L16 15.08z"/>
+ <path id="bottom_line" d="M4 17h16a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1z"/>
+ <path id="middle_line" d="M4 10h7a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1z"/>
+ <path id="top_line" d="M4 3h16a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-ltr.png
new file mode 100644
index 00000000..bcbfa5ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-ltr.svg
new file mode 100644
index 00000000..44c1591d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="outline-ltr">
+ <path id="text" d="M5 13h14v6H5v-6z"/>
+ <path id="float" d="M5 5v6h6V5H5zm5 5H6V6h4v4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-rtl.png
new file mode 100644
index 00000000..d89e06e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-rtl.svg
new file mode 100644
index 00000000..c5b19c8f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/outline-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="outline-rtl">
+ <path id="text" d="M19 19H5v-6h14v6z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm1 1h4v4h-4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-ltr.png
new file mode 100644
index 00000000..ef332517
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-ltr.svg
new file mode 100644
index 00000000..e9704fdf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm-2 12V8l6 4-6 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-rtl.png
new file mode 100644
index 00000000..a8c59a95
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-rtl.svg
new file mode 100644
index 00000000..ec0dcf21
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/play-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 4c4.4 0 8 3.6 8 8s-3.6 8-8 8-8-3.6-8-8 3.6-8 8-8zm2 12V8l-6 4 6 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr-invert.png
new file mode 100644
index 00000000..25171661
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr-invert.svg
new file mode 100644
index 00000000..08c2c36e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M18 8h-1V4H7v4H3v6c0 1.7 1.3 3 3 3h1v3h10v-3h4v-6c0-1.7-1.3-3-3-3zM8 5h8v3H8V5zm8 14H8v-6h8v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr.png
new file mode 100644
index 00000000..a7f67176
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr.svg
new file mode 100644
index 00000000..7081606b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18 8h-1V4H7v4H3v6c0 1.7 1.3 3 3 3h1v3h10v-3h4v-6c0-1.7-1.3-3-3-3zM8 5h8v3H8V5zm8 14H8v-6h8v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl-invert.png
new file mode 100644
index 00000000..37a9e3da
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl-invert.svg
new file mode 100644
index 00000000..d4317037
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M6 8h1V4h10v4h4v6c0 1.7-1.3 3-3 3h-1v3H7v-3H3v-6c0-1.7 1.3-3 3-3zm10-3H8v3h8V5zM8 19h8v-6H8v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl.png
new file mode 100644
index 00000000..6e5b1756
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl.svg
new file mode 100644
index 00000000..d6188ebb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/printer-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6 8h1V4h10v4h4v6c0 1.7-1.3 3-3 3h-1v3H7v-3H3v-6c0-1.7 1.3-3 3-3zm10-3H8v3h8V5zM8 19h8v-6H8v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/pushPin.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/pushPin.png
new file mode 100644
index 00000000..27d49e21
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/pushPin.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/pushPin.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/pushPin.svg
new file mode 100644
index 00000000..b852cd06
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/pushPin.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.445 12.225c-.813-.935-1.775-.739-2.883-1.768-.55-.511-.498-2.36-.498-2.36s-.041-1.836.524-2.401c.39-.39 1.076-.49 1.475-.883a.973.973 0 0 0 .217-.317c.007-.013.014-.023.018-.035.035-.092.054-.2.064-.316.003-.03.017-.055.017-.085 0-.005-.003-.01-.004-.015.001-.008.004-.014.004-.022 0-.02-.015-.03-.017-.048a1.052 1.052 0 0 0-1.043-.974H8.681c-.555 0-.997.43-1.043.974-.002.018-.017.028-.017.048 0 .008.003.014.003.022 0 .006-.003.01-.003.015 0 .03.014.055.017.085.01.116.029.224.064.316.004.012.012.022.018.035a.965.965 0 0 0 .217.317c.399.393 1.084.493 1.475.883.565.565.523 2.401.523 2.401s.053 1.849-.497 2.36c-1.108 1.03-2.07.833-2.883 1.768C5.979 12.887 6 14 6 14h5.333v4.578L12 21l.668-2.422V14H18s.02-1.113-.555-1.775z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-ltr.png
new file mode 100644
index 00000000..9b406097
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-ltr.svg
new file mode 100644
index 00000000..fb9d3383
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18 9.9c-.7 0-1.4.3-1.8.9V6h-4c.2-.4.4-.8.4-1.2 0-1.2-1-2.2-2.2-2.2-1.3-.1-2.3.9-2.3 2.2 0 .4.2.8.4 1.2H4.1v3.6l.6-.1c1.4 0 2.5 1.1 2.5 2.5s-1.1 2.5-2.5 2.5c-.2 0-.4 0-.6-.1V18H9c-.5.4-.9 1-.9 1.8 0 1.2 1 2.2 2.3 2.2 1.2 0 2.2-1 2.2-2.2 0-.7-.3-1.4-.9-1.8h4.5v-4.5c.4.5 1 .9 1.8.9 1.2 0 2.2-1 2.2-2.2 0-1.3-1-2.3-2.2-2.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-rtl.png
new file mode 100644
index 00000000..6f7334b5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-rtl.svg
new file mode 100644
index 00000000..1d483084
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6.3 9.9c.7 0 1.4.3 1.8.9V6h4c-.2-.4-.4-.8-.4-1.2 0-1.2 1-2.2 2.2-2.2 1.3-.1 2.3.9 2.3 2.2 0 .4-.2.8-.4 1.2h4.4v3.6l-.6-.1c-1.4 0-2.5 1.1-2.5 2.5s1.1 2.5 2.5 2.5c.2 0 .4 0 .6-.1V18h-4.9c.5.4.9 1 .9 1.8 0 1.2-1 2.2-2.3 2.2-1.2 0-2.2-1-2.2-2.2 0-.7.3-1.4.9-1.8H8.1v-4.5c-.4.5-1 .9-1.8.9-1.2 0-2.2-1-2.2-2.2 0-1.3 1-2.3 2.2-2.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle.png
new file mode 100644
index 00000000..6ce22fe5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle.svg
new file mode 100644
index 00000000..cfcbbcc5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/puzzle.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="puzzle-piece" d="M19.46 10.417c-.351-.404-1.641-.501-1.983-.162-.769.758-1.926 1.308-1.952.162.088-2.081.818-3.743.818-3.743a.46.46 0 0 0-.463-.456s-1.586-.111-3.59-.164l-1.25-.001c-.127.406.274 1.09.782 1.604.339.344.242 1.633-.162 1.984-.393.34-1.197.539-1.662.539-.445 0-1.222-.158-1.612-.479-.438-.356-.332-1.686.02-2.044.47-.476.838-1.185.721-1.606h-.483c-2.074.05-3.514.167-3.514.167a.46.46 0 0 0-.463.456s-.558 2.58-.558 5.348c0 2.762.558 5.331.558 5.331a.46.46 0 0 0 .463.457s2.615.19 5.493.19c2.723 0 5.258-.19 5.258-.19a.46.46 0 0 0 .463-.457s-.739-1.73-.824-3.869c.031-1.004 1.255-.506 1.958.188.356.353 1.688.458 2.045.021.318-.392.477-1.169.477-1.614 0-.465-.199-1.269-.54-1.662z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-ltr.png
new file mode 100644
index 00000000..0252b746
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-ltr.svg
new file mode 100644
index 00000000..dc366b7d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes">
+ <path id="quote" d="M6.9 8.4c-.446.55-1.974 2.6-1.9 5.7V17h4.7c.9 0 1.6-.7 1.6-1.6V11H8.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ </g>
+ <use transform="translate(8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-rtl.png
new file mode 100644
index 00000000..7bcc7c7b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-rtl.svg
new file mode 100644
index 00000000..e652b317
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotes-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes">
+ <path id="quote" d="M17.1 8.4c.446.55 1.9 2.6 1.9 5.7V17h-4.7c-.9 0-1.6-.7-1.6-1.6V11h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ </g>
+ <use transform="translate(-8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-ltr.png
new file mode 100644
index 00000000..e1a0c4ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-ltr.svg
new file mode 100644
index 00000000..6704c516
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-ltr.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes-add">
+ <path id="quote" d="M5.9 10.4c-.446.55-1.974 2.6-1.9 5.7V19h4.7c.9 0 1.593-.7 1.6-1.6V13H7.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ <path id="quote2" d="M15 9.344c-.476.32-.78.677-1.094 1.062A8.76 8.76 0 0 0 12 16.094V19h4.688a1.6 1.6 0 0 0 1.625-1.594V13H15V9.344z"/>
+ <path id="add" d="M18 6V2h-2v4h-4v2h4v4h2V8h4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-rtl.png
new file mode 100644
index 00000000..0ef9d016
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-rtl.svg
new file mode 100644
index 00000000..d972ad3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/quotesAdd-rtl.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes-add">
+ <path id="quote" d="M18.097 10.4c.446.55 1.974 2.6 1.9 5.7V19h-4.7c-.9 0-1.593-.7-1.6-1.6V13h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ <path id="quote2" d="M8.997 9.344c.476.32.782.677 1.094 1.062A8.758 8.758 0 0 1 12 16.094V19H7.31c-.9 0-1.618-.694-1.625-1.594V13h3.312V9.344z"/>
+ <path id="add" d="M5.997 6V2h2v4h4v2h-4v4h-2V8h-4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/regular-expression.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/regular-expression.png
new file mode 100644
index 00000000..f27e4212
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/regular-expression.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/regular-expression.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/regular-expression.svg
new file mode 100644
index 00000000..d5fcfcf0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/regular-expression.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="regular-expression">
+ <path id="left-bracket" d="M3 12.045c0-.99.15-1.915.45-2.777A6.886 6.886 0 0 1 4.764 7H6.23a7.923 7.923 0 0 0-1.25 2.374 8.563 8.563 0 0 0 .007 5.314c.29.85.7 1.622 1.23 2.312h-1.45a6.53 6.53 0 0 1-1.314-2.223 8.126 8.126 0 0 1-.45-2.732"/>
+ <path id="dot" d="M10 16a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
+ <path id="star" d="M14.25 7.013l-.24 2.156 2.187-.61.193 1.47-1.992.14 1.307 1.74-1.33.71-.914-1.833-.8 1.822-1.38-.698 1.296-1.74-1.98-.152.23-1.464 2.14.61-.24-2.158h1.534"/>
+ <path id="right-bracket" d="M21 12.045c0 .982-.152 1.896-.457 2.744A6.51 6.51 0 0 1 19.236 17h-1.453a8.017 8.017 0 0 0 1.225-2.31c.29-.855.434-1.74.434-2.66 0-.91-.14-1.797-.422-2.66a7.913 7.913 0 0 0-1.248-2.374h1.465a6.764 6.764 0 0 1 1.313 2.28c.3.86.45 1.782.45 2.764"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize-invert.png
new file mode 100644
index 00000000..46a180d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize-invert.svg
new file mode 100644
index 00000000..3a098642
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <circle cx="11.5" cy="8.5" r="2.5"/>
+ <path d="M16.3 8.7L17 8l-.8-.8.4-.8-1.1-.5.1-.9-1.2-.2-.1-.9-1.2.2-.4-.8-1.1.5L11 3l-.8.8-.9-.4-.5 1.1-.9-.2-.2 1.2-.9.2.2 1.2-.9.4.5 1.1L6 9l.8.8-.4.8 1.1.5-.1.9 1.2.2.1.9 1.2-.2.4.8 1.1-.5.6.8.8-.8.8.4.5-1.1.9.1.2-1.2.9-.1-.2-1.2.8-.4-.4-1zM11.5 12C9.6 12 8 10.4 8 8.5S9.6 5 11.5 5 15 6.6 15 8.5 13.4 12 11.5 12zm.5 3l-.7-.7-1.1.6-.4-.7-.8.3V23l2.5-3 2.5 3v-8.5l-1-.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize.png
new file mode 100644
index 00000000..10105740
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize.svg
new file mode 100644
index 00000000..45df8b71
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/ribbonPrize.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <circle cx="11.5" cy="8.5" r="2.5"/>
+ <path d="M16.3 8.7L17 8l-.8-.8.4-.8-1.1-.5.1-.9-1.2-.2-.1-.9-1.2.2-.4-.8-1.1.5L11 3l-.8.8-.9-.4-.5 1.1-.9-.2-.2 1.2-.9.2.2 1.2-.9.4.5 1.1L6 9l.8.8-.4.8 1.1.5-.1.9 1.2.2.1.9 1.2-.2.4.8 1.1-.5.6.8.8-.8.8.4.5-1.1.9.1.2-1.2.9-.1-.2-1.2.8-.4-.4-1zM11.5 12C9.6 12 8 10.4 8 8.5S9.6 5 11.5 5 15 6.6 15 8.5 13.4 12 11.5 12zm.5 3l-.7-.7-1.1.6-.4-.7-.8.3V23l2.5-3 2.5 3v-8.5l-1-.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-ltr.png
new file mode 100644
index 00000000..e8e99f84
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-ltr.svg
new file mode 100644
index 00000000..ebc654a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="search">
+ <path id="magnifying-glass" d="M10.5 4a6.5 6.5 0 1 0 2.844 12.344L16 19c1.4 1.4 2.5 1.5 4 0l-4.438-4.438A6.426 6.426 0 0 0 17 10.5 6.5 6.5 0 0 0 10.5 4zm0 2a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-rtl.png
new file mode 100644
index 00000000..3ab96bec
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-rtl.svg
new file mode 100644
index 00000000..c51d4cb0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="search">
+ <path id="magnifying-glass" d="M13.5 4a6.5 6.5 0 1 1-2.844 12.344L8 19c-1.4 1.4-2.5 1.5-4 0l4.438-4.438A6.426 6.426 0 0 1 7 10.5 6.5 6.5 0 0 1 13.5 4zm0 2a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search.png
new file mode 100644
index 00000000..7b475398
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search.svg
new file mode 100644
index 00000000..823ebf28
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/search.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="search">
+ <path id="magnifying-glass" d="M18.87 18.375l-3.987-3.99-.286-.17a5.774 5.774 0 0 0 1.082-3.372C15.67 7.616 13.06 5 9.84 5A5.843 5.843 0 0 0 4 10.844a5.84 5.84 0 0 0 5.842 5.842c1.26 0 2.423-.403 3.377-1.08l.16.286 3.99 3.987c.32.31.91.24 1.33-.18.41-.42.49-1.01.17-1.33zM9.837 14.56a3.72 3.72 0 0 1-3.718-3.717c0-2.05 1.67-3.72 3.72-3.72s3.72 1.668 3.72 3.72a3.722 3.722 0 0 1-3.72 3.718z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/secure-link.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/secure-link.png
new file mode 100644
index 00000000..8a44a929
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/secure-link.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/secure-link.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/secure-link.svg
new file mode 100644
index 00000000..453d1663
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/secure-link.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="secure">
+ <path id="lock" d="M8 5h.02v-.997c0-.057.003-1.41-.833-2.255-.434-.438-.998-.66-1.68-.66s-1.244.222-1.677.66c-.837.846-.833 2.198-.832 2.25V5H3a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h5a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1zM3.998 5V3.993c0-.01.005-1 .543-1.543.49-.485 1.45-.487 1.94-.002.543.546.545 1.536.545 1.55V5H3.998z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/settings.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/settings.png
new file mode 100644
index 00000000..1c8e5874
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/settings.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/settings.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/settings.svg
new file mode 100644
index 00000000..3245dbe3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/settings.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="settings">
+ <path id="gear" d="M3 4h3v2H3zm9 0h9v2h-9zM8 3h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm-5 8h9v2H3zm15 0h3v2h-3zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zM3 18h6v2H3zm12 0h6v2h-6zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.png
new file mode 100644
index 00000000..f68a7bf2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.svg
new file mode 100644
index 00000000..03b34cf8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M0 20h24v1H0v-1zm6-8l-1-1-2 2-2-2-1 1 2 2-2 2 1 1 2-2 2 2 1-1-2-2zm15.6 3.7c-.9-.5-1.9-.5-2.7 0-1.5.9-3.1.4-3.1.4-.4-.2-.8-.4-1.1-.6 2.2-.6 4.4-1.8 6-3.9 1.1-1.2 2.5-3.9.4-6-.7-.7-1.6-1.1-2.7-1-1.4.1-2.8.9-3.9 2.1-.9 1.1-3.1 4.5-2.3 7.5 0 .1 0 .2.1.3-2.3.3-4.2.2-4.4.1v1.5c.7.1 2.7.2 5.1-.2.5.7 1.3 1.2 2.3 1.6.1 0 2.4.8 4.5-.6.5-.3.9-.1 1.1 0 .4.2.7.6.7 1H23c0-.8-.6-1.7-1.4-2.2zm-8-1.7c-.5-2.2 1.1-5.1 2-6.2.8-.9 1.8-1.5 2.8-1.6h.1c.6 0 1.1.2 1.5.6 1.6 1.6-.4 3.9-.5 4-1.5 2-3.7 3-5.8 3.5l-.1-.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.png
new file mode 100644
index 00000000..9166e8dd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.svg
new file mode 100644
index 00000000..326281a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/signature-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M24 20H0v1h24v-1zm-6-8l1-1 2 2 2-2 1 1-2 2 2 2-1 1-2-2-2 2-1-1 2-2zM2.4 15.7c.9-.5 1.9-.5 2.7 0 1.5.9 3.1.4 3.1.4.4-.2.8-.4 1.1-.6-2.2-.6-4.4-1.8-6-3.9-1.1-1.2-2.5-3.9-.4-6 .7-.7 1.6-1.1 2.7-1 1.4.1 2.8.9 3.9 2.1.9 1.1 3.1 4.5 2.3 7.5 0 .1 0 .2-.1.3 2.3.3 4.2.2 4.4.1v1.5c-.7.1-2.7.2-5.1-.2-.5.7-1.3 1.2-2.3 1.6-.1 0-2.4.8-4.5-.6-.5-.3-.9-.1-1.1 0-.4.2-.7.6-.7 1H1c0-.8.6-1.7 1.4-2.2zm8-1.7c.5-2.2-1.1-5.1-2-6.2-.8-.9-1.8-1.5-2.8-1.6h-.1c-.6 0-1.1.2-1.5.6-1.6 1.6.4 3.9.5 4 1.5 2 3.7 3 5.8 3.5l.1-.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-ltr.png
new file mode 100644
index 00000000..a9b29d88
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-ltr.svg
new file mode 100644
index 00000000..94312522
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="big-a" d="M9.666 6H8.294l-4.48 12H5.52l1.493-4h4l1.507 4h1.666zm-2.28 7l1.617-4.333L10.637 13h-3.25z"/>
+ <path id="small-a" d="M17.828 12h-.686l-2.24 6h.853l.747-2h2l.753 2h.833zm-1.14 3.5l.81-2.167.816 2.167H16.69z"/>
+ <path id="arrow" d="M15 6h5l-2.5 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-rtl.png
new file mode 100644
index 00000000..006bd2bd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-rtl.svg
new file mode 100644
index 00000000..d2d28587
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smaller-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="big-a" d="M14.334 6h1.372l4.48 12H18.48l-1.493-4h-4l-1.507 4H9.814zm2.28 7l-1.617-4.333L13.363 13h3.25z"/>
+ <path id="small-a" d="M6.172 12h.686l2.24 6h-.853L7.5 16H5.497l-.753 2h-.833zm1.14 3.5l-.81-2.166-.816 2.166h1.625z"/>
+ <path id="arrow" d="M9 6H4l2.5 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr-invert.png
new file mode 100644
index 00000000..dec125ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr-invert.svg
new file mode 100644
index 00000000..146a2126
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M17.6 20h-5.4v-.5c.2 0 .5-.1.9-.1.3-.1.5-.2.5-.3V19s0-.1-.1-.2l-.8-2H9.3c-.1.2-.2.4-.3.7-.1.3-.2.5-.2.7-.1.3-.1.4-.2.6v.2c0 .1.1.3.3.4.2.1.6.2 1.1.2v.4H6v-.5c.2 0 .3 0 .5-.1.2 0 .3-.1.5-.2s.4-.2.5-.4l.3-.6c.5-1.3 1.1-2.6 1.6-3.9.5-1.3 1.1-2.7 1.8-4.3h1.4c.9 2.2 1.6 4 2.1 5.3.5 1.3 1 2.4 1.3 3.2.1.1.1.3.2.4.1.1.2.2.4.3.1.1.3.1.5.2s.3.1.5.1v.5zm-5.2-4L11 12.4 9.6 16h2.8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr.png
new file mode 100644
index 00000000..b38dca38
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr.svg
new file mode 100644
index 00000000..446d10a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.6 20h-5.4v-.5c.2 0 .5-.1.9-.1.3-.1.5-.2.5-.3V19s0-.1-.1-.2l-.8-2H9.3c-.1.2-.2.4-.3.7-.1.3-.2.5-.2.7-.1.3-.1.4-.2.6v.2c0 .1.1.3.3.4.2.1.6.2 1.1.2v.4H6v-.5c.2 0 .3 0 .5-.1.2 0 .3-.1.5-.2s.4-.2.5-.4l.3-.6c.5-1.3 1.1-2.6 1.6-3.9.5-1.3 1.1-2.7 1.8-4.3h1.4c.9 2.2 1.6 4 2.1 5.3.5 1.3 1 2.4 1.3 3.2.1.1.1.3.2.4.1.1.2.2.4.3.1.1.3.1.5.2s.3.1.5.1v.5zm-5.2-4L11 12.4 9.6 16h2.8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl-invert.png
new file mode 100644
index 00000000..9aba2460
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl-invert.svg
new file mode 100644
index 00000000..960793c5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M6 19.5c.1 0 .3 0 .5-.1s.3-.1.5-.2.3-.2.4-.3c.1-.1.2-.2.2-.4.4-.9.8-1.9 1.3-3.2.5-1.3 1.2-3.1 2.1-5.3h1.4c.7 1.6 1.2 3 1.8 4.3.5 1.3 1.1 2.6 1.6 3.9l.3.6c.1.2.3.3.5.4.1.1.3.1.5.2.2 0 .4.1.5.1v.5h-4v-.5c.5 0 .9-.1 1.1-.2.2-.1.3-.2.3-.4v-.2c0-.1-.1-.3-.2-.6-.1-.2-.2-.4-.2-.7-.1-.3-.2-.5-.3-.7h-3.4l-.8 2c0 .1-.1.1-.1.2v.1c0 .1.2.2.5.3.3.1.6.1.9.1v.6H6v-.5zm8-3.5l-1.4-3.6-1.4 3.6H14z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl.png
new file mode 100644
index 00000000..b9864efb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl.svg
new file mode 100644
index 00000000..ebcea4df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/smallerText-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6 19.5c.1 0 .3 0 .5-.1s.3-.1.5-.2.3-.2.4-.3c.1-.1.2-.2.2-.4.4-.9.8-1.9 1.3-3.2.5-1.3 1.2-3.1 2.1-5.3h1.4c.7 1.6 1.2 3 1.8 4.3.5 1.3 1.1 2.6 1.6 3.9l.3.6c.1.2.3.3.5.4.1.1.3.1.5.2.2 0 .4.1.5.1v.5h-4v-.5c.5 0 .9-.1 1.1-.2.2-.1.3-.2.3-.4v-.2c0-.1-.1-.3-.2-.6-.1-.2-.2-.4-.2-.7-.1-.3-.2-.5-.3-.7h-3.4l-.8 2c0 .1-.1.1-.1.2v.1c0 .1.2.2.5.3.3.1.6.1.9.1v.6H6v-.5zm8-3.5l-1.4-3.6-1.4 3.6H14z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/specialCharacter.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/specialCharacter.png
new file mode 100644
index 00000000..9b02a410
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/specialCharacter.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/specialCharacter.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/specialCharacter.svg
new file mode 100644
index 00000000..5cba0801
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/specialCharacter.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="special-character">
+ <path id="omega" d="M12 6.708c-.794 0-1.368.103-1.894.31-.525.207-.944.496-1.255.867-.31.366-.53.808-.66 1.327a7.232 7.232 0 0 0-.19 1.7c0 .512.06 1 .18 1.46.12.46.31.87.567 1.23.63.862 1.156 1.138 2.012 1.362L11 18H6v-3h.604l.53 1.353.395.053.6.044.75.035.455.01H10l-.09-.895c-.63-.094-.812-.268-1.337-.522-.525-.26-.98-.59-1.365-.99a4.428 4.428 0 0 1-.89-1.4 4.78 4.78 0 0 1-.32-1.778c0-.82.13-1.537.394-2.15a3.97 3.97 0 0 1 1.163-1.54c.507-.407 1.133-.71 1.878-.912.745-.206 1.6-.31 2.565-.31.96 0 1.81.103 2.556.31.75.2 1.38.504 1.887.912.51.407.9.92 1.16 1.54.27.614.404 1.33.404 2.15a4.79 4.79 0 0 1-.32 1.78 4.35 4.35 0 0 1-.9 1.397c-.38.4-.83.732-1.355.99-.526.255-.708.43-1.337.523l-.092.894h.66l.448-.01.75-.034.606-.044.4-.053.534-1.354H18v3h-5l.246-3.04c1.066-.11 1.337-.698 2.002-1.365.263-.36.452-.77.568-1.23.122-.46.183-.947.183-1.46 0-.62-.07-1.186-.198-1.7a3.175 3.175 0 0 0-.66-1.326c-.31-.37-.73-.66-1.255-.867-.525-.206-1.1-.31-1.894-.31"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.png
new file mode 100644
index 00000000..2eedf9f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.svg
new file mode 100644
index 00000000..83d47c1d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19 20H2l3-3V6h17v11c0 1.7-1.3 3-3 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.png
new file mode 100644
index 00000000..0d144431
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.svg
new file mode 100644
index 00000000..e7dd6681
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubble-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 20h17l-3-3V6H2v11c0 1.7 1.3 3 3 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.png
new file mode 100644
index 00000000..aafac18f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.svg
new file mode 100644
index 00000000..c7134c33
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm8 3h1v3h3v1h-3v3h-1v-3h-3v-1h3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.png
new file mode 100644
index 00000000..feff2ba7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.svg
new file mode 100644
index 00000000..08462e0c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbleAdd-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M2 6v11c0 1.7 1.3 3 3 3h17l-3-3V6H2zm8 3h1v3h3v1h-3v3h-1v-3H7v-1h3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.png
new file mode 100644
index 00000000..f2e0564d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.svg
new file mode 100644
index 00000000..d6832183
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 9v9l2 2H8V9h12zM3 4h12v4H7v7H1l2-2V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.png
new file mode 100644
index 00000000..9c67f3fe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.svg
new file mode 100644
index 00000000..db548a45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/speechBubbles-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 9v9l-2 2h14V9H3zm17-5H8v4h8v7h6l-2-2V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/star.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/star.png
new file mode 100644
index 00000000..36b6a1ff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/star.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/star.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/star.svg
new file mode 100644
index 00000000..54ba77ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/star.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-a.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-a.png
new file mode 100644
index 00000000..279d1f72
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-a.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-a.svg
new file mode 100644
index 00000000..070d7853
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-a.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="strikethrough-a">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-s.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-s.png
new file mode 100644
index 00000000..21b9baaf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-s.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-s.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-s.svg
new file mode 100644
index 00000000..171f8f38
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-s.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="strikethrough-s">
+ <path id="strikethrough" d="M6 12h12v1H6v-1z"/>
+ <path id="s" d="M12.094 6c-1.133 0-2.076.287-2.75.9-.67.613-1 1.49-1 2.52 0 .89.22 1.602.72 2.13.497.528 1.278.91 2.31 1.14l.813.182v-.03c.656.147 1.128.375 1.375.63.252.256.375.607.375 1.11 0 .573-.172.97-.53 1.26-.36.29-.895.45-1.626.45-.47 0-.962-.074-1.462-.24a7.288 7.288 0 0 1-1.562-.75l-.374-.238v2.158l.156.062c.58.237 1.144.417 1.69.54.548.12 1.07.18 1.56.18 1.287 0 2.298-.293 3-.9.71-.605 1.063-1.486 1.063-2.608 0-.943-.256-1.726-.78-2.312-.522-.592-1.306-1-2.345-1.23l-.812-.18c-.714-.148-1.202-.352-1.404-.54-.206-.202-.313-.484-.313-.934 0-.533.162-.9.5-1.17.342-.27.836-.42 1.53-.42.396 0 .82.052 1.25.18.434.128.91.334 1.407.6l.375.18V6.63s-1.19-.383-1.69-.48c-.5-.097-.983-.15-1.467-.15z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-y.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-y.png
new file mode 100644
index 00000000..d7694682
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-y.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-y.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-y.svg
new file mode 100644
index 00000000..2fdbc871
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/strikethrough-y.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="strikethrough-y">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M7 6h1.724l3.288 4.935L15.276 6H17l-4.194 6.285V18h-1.612v-5.715L7 6"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-ltr.png
new file mode 100644
index 00000000..5423b36e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-ltr.svg
new file mode 100644
index 00000000..2112bb2d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 9h12v2H4V9zm0 3h8v2H4v-2zm0-7h16v3H4V5zm16 14H4v-3h16v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-rtl.png
new file mode 100644
index 00000000..0ff3d7cf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-rtl.svg
new file mode 100644
index 00000000..39790a9a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeFlow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 9H8v2h12V9zm0 3h-8v2h8v-2zm0-7H4v3h16V5zM4 19h16v-3H4v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-ltr.png
new file mode 100644
index 00000000..ce15bd87
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-ltr.svg
new file mode 100644
index 00000000..767d6cda
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 11H4V9h16v2zM4 12h8v2H4v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-rtl.png
new file mode 100644
index 00000000..82ca2bf5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-rtl.svg
new file mode 100644
index 00000000..4d16337e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeSummary-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 11h16V9H4v2zm16 1h-8v2h8v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-ltr.png
new file mode 100644
index 00000000..b482d3e6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-ltr.svg
new file mode 100644
index 00000000..d7c202e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 13H4v-3h13v3zm-5 6H4v-3h8v3zM4 7V4h16v3H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-rtl.png
new file mode 100644
index 00000000..516bc2c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-rtl.svg
new file mode 100644
index 00000000..0859be6b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/stripeToC-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 13h13v-3H7v3zm5 6h8v-3h-8v3zm8-12V4H4v3h16z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-ltr.png
new file mode 100644
index 00000000..c2cf4cf5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-ltr.svg
new file mode 100644
index 00000000..fbb0c3c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 13l-1 1v3l1 1h-1l-.527-.46L16 18h-1l1-1v-3l-1-1h1l.485.497L17 13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-rtl.png
new file mode 100644
index 00000000..b1ee51b6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-rtl.svg
new file mode 100644
index 00000000..91a71ecc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subscript-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 13l1 1v3l-1 1h1l.527-.46L10 18h1l-1-1v-3l1-1h-1l-.485.497L9 13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subtract.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subtract.png
new file mode 100644
index 00000000..bd719cb6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subtract.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subtract.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subtract.svg
new file mode 100644
index 00000000..a79f0b50
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/subtract.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18 13H6v-2h12"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr-invert.png
new file mode 100644
index 00000000..2bc944a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr-invert.svg
new file mode 100644
index 00000000..7f7ef3a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9s-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4s.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9s.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8s.1-.6.3-.8z"/>
+ <circle cx="12" cy="11" r="4"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr.png
new file mode 100644
index 00000000..0c00745b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr.svg
new file mode 100644
index 00000000..4bde1836
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9s-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4s.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9s.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8s.1-.6.3-.8z"/>
+ <circle cx="12" cy="11" r="4"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl-invert.png
new file mode 100644
index 00000000..7ac54ff4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl-invert.svg
new file mode 100644
index 00000000..7559366e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M5.9 5.1c0 .3.1.6.3.9l1.4 1.4.9-.8-2.2-2.2c-.3.1-.4.4-.4.7zm.5 5.3H3.2c0 .3.1.6.4.9.3.3.5.4.8.4h2v-1.3zm6.2-5V2.2c-.3 0-.6.1-.9.4-.3.3-.4.5-.4.8v2h1.3zM6.2 17.1c.3 0 .6-.1.8-.3l1.4-1.4-.8-.8-2.2 2.2c.2.2.5.3.8.3zM17.8 4.9c-.3 0-.6.1-.8.3l-1.4 1.4.8.9 2.2-2.3c-.2-.2-.5-.3-.8-.3zm-5.2 11.7h-1.2v3.2c.3 0 .6-.1.9-.4.3-.3.4-.5.4-.8l-.1-2zm7-6.2h-2v1.2h3.2c0-.3-.1-.6-.4-.9-.3-.3-.5-.3-.8-.3zM17.8 16l-1.4-1.4-.8.8 2.2 2.2c.2-.2.3-.5.3-.8 0-.3-.1-.6-.3-.8z"/>
+ <circle cx="12" cy="11" r="4" transform="matrix(-1 0 0 1 24 0)"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl.png
new file mode 100644
index 00000000..77c78060
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl.svg
new file mode 100644
index 00000000..868334e4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/sun-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5.9 5.1c0 .3.1.6.3.9l1.4 1.4.9-.8-2.2-2.2c-.3.1-.4.4-.4.7zm.5 5.3H3.2c0 .3.1.6.4.9.3.3.5.4.8.4h2v-1.3zm6.2-5V2.2c-.3 0-.6.1-.9.4-.3.3-.4.5-.4.8v2h1.3zM6.2 17.1c.3 0 .6-.1.8-.3l1.4-1.4-.8-.8-2.2 2.2c.2.2.5.3.8.3zM17.8 4.9c-.3 0-.6.1-.8.3l-1.4 1.4.8.9 2.2-2.3c-.2-.2-.5-.3-.8-.3zm-5.2 11.7h-1.2v3.2c.3 0 .6-.1.9-.4.3-.3.4-.5.4-.8l-.1-2zm7-6.2h-2v1.2h3.2c0-.3-.1-.6-.4-.9-.3-.3-.5-.3-.8-.3zM17.8 16l-1.4-1.4-.8.8 2.2 2.2c.2-.2.3-.5.3-.8 0-.3-.1-.6-.3-.8z"/>
+ <circle cx="12" cy="11" r="4" transform="matrix(-1 0 0 1 24 0)"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-ltr.png
new file mode 100644
index 00000000..8df46091
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-ltr.svg
new file mode 100644
index 00000000..45abfda2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 7l-1 1v3l1 1h-1l-.527-.46L16 12h-1l1-1V8l-1-1h1l.485.497L17 7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-rtl.png
new file mode 100644
index 00000000..48bfd688
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-rtl.svg
new file mode 100644
index 00000000..33b5814b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/superscript-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 7l1 1v3l-1 1h1l.527-.46L10 12h1l-1-1V8l1-1h-1l-.485.497L9 7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-caption.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-caption.png
new file mode 100644
index 00000000..80b474d4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-caption.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-caption.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-caption.svg
new file mode 100644
index 00000000..6b7edc6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-caption.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-caption">
+ <path id="caption" d="M6 6h12v3H6z"/>
+ <path id="table" d="M4 10v7h16v-7H4zm1 1h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2zM5 14h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-ltr.png
new file mode 100644
index 00000000..fe3eb18f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-ltr.svg
new file mode 100644
index 00000000..a67ed201
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-column-ltr">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h2v14H5z" id="column"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-rtl.png
new file mode 100644
index 00000000..ddaafe9a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-rtl.svg
new file mode 100644
index 00000000..dee782e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-column-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-column-rtl">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M17 5h2v14h-2z" id="column"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-after.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-after.png
new file mode 100644
index 00000000..31a23066
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-after.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-after.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-after.svg
new file mode 100644
index 00000000..ad9d86db
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-after.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-row-after">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 17h14v2H5z" id="row"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-before.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-before.png
new file mode 100644
index 00000000..24774750
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-before.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-before.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-before.svg
new file mode 100644
index 00000000..e9dfe048
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-insert-row-before.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-row-before">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h14v2H5z" id="row"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-merge-cells.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-merge-cells.png
new file mode 100644
index 00000000..e6b2da3e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-merge-cells.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-merge-cells.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-merge-cells.svg
new file mode 100644
index 00000000..3ffb9e5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table-merge-cells.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-merge-cells">
+ <g id="merge-cell-left">
+ <path id="cell-border" d="M4 7v9h7v-3l-1 .834V15H5V8h5v1.167L11 10V7z"/>
+ <path id="arrow" d="M8 9v2H6v1h2v2l3-2.5z"/>
+ </g>
+ <use id="merge-cell-right" xlink:href="#merge-cell-left" transform="matrix(-1 0 0 1 24 0)"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table.png
new file mode 100644
index 00000000..f4008f6b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table.svg
new file mode 100644
index 00000000..b5733fba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/table.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert">
+ <path id="table" d="M4 6v11h15V6zm1 3h6v3H5zm7 0h6v3h-6zm-7 4h6v3H5zm7 0h6v3h-6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tag.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tag.png
new file mode 100644
index 00000000..82461ef7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tag.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tag.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tag.svg
new file mode 100644
index 00000000..7a211a3f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tag.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-ltr.png
new file mode 100644
index 00000000..f3ce49ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-ltr.svg
new file mode 100644
index 00000000..8cd95e0a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="template-add">
+ <path id="add" d="M23 7h-4V3h-2v4h-4v2h4v4h2V9h4z"/>
+ <path id="template" d="M18 14v4H6c-1.1 0-2-.9-2-2V8h8V7H3v9c0 1.7 1.3 3 3 3h13v-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-rtl.png
new file mode 100644
index 00000000..448caf4f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-rtl.svg
new file mode 100644
index 00000000..62b30f5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/templateAdd-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="template-add">
+ <path id="add" d="M1 7h4V3h2v4h4v2H7v4H5V9H1z"/>
+ <path id="template" d="M6 14v4h12c1.1 0 2-.9 2-2V8h-8V7h9v9c0 1.7-1.3 3-3 3H5v-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-lefttoright.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-lefttoright.png
new file mode 100644
index 00000000..fede39a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-lefttoright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-lefttoright.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-lefttoright.svg
new file mode 100644
index 00000000..83dd7697
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-lefttoright.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 7H5V6h2l.47.5L8 6h2v1H8v10h2v1H8l-.5-.53L7 18H5v-1h2zm6.976 9v-2H11v-4h2.976V8.044L20 12.022z" id="text-dir-ltr"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-righttoleft.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-righttoleft.png
new file mode 100644
index 00000000..9f60ed5a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-righttoleft.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-righttoleft.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-righttoleft.svg
new file mode 100644
index 00000000..78cb85b3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-dir-righttoleft.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 17h2v1h-2l-.47-.5-.53.5h-2v-1h2V7h-2V6h2l.5.53L17 6h2v1h-2zm-6.976-9v2H13v4h-2.976v1.956L4 11.978z" id="text-dir-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-style.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-style.png
new file mode 100644
index 00000000..65ab476a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-style.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-style.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-style.svg
new file mode 100644
index 00000000..466672eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/text-style.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="text-style">
+ <path id="a" d="M15.296 18h2.79l-1.14-12h-2.79L6 18h2.79l2.038-3h4.183l.29 3zm-3.11-5L14.5 9.6l.323 3.4H12.19z"/>
+ <path id="underline" d="M6 19h12v1H6v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trash.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trash.png
new file mode 100644
index 00000000..7f14fca0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trash.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trash.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trash.svg
new file mode 100644
index 00000000..ef7032da
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trash.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 10h-1v6h1v-6zm-2 0H9v6h1v-6zm4 0h-1v6h1v-6zm0-4V5H9v1H6v3h1v7.966l1 1.03v-.073V18h6.984l.016-.018v.015l1-1.03V9h1V6h-3zm1 11H8V9h7v8zm1-9H7V7h9v1z" id="trash-can"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-ltr.png
new file mode 100644
index 00000000..dce4a9fc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-ltr.svg
new file mode 100644
index 00000000..9a625b89
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4.5 3.5l-1 1L6 7v2h1v7.97L8 18h6.97l.03-.03 1-.97 2.5 2.5 1-1L16 15l-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1zM9 5v1l1 1h6v1h-5l1 1h3v3l1 1V9h1V6h-3V5zM8 9l1 1v6h1v-5l1 1v4h1v-3l1 1v2h1v-1l1 1v1H8zm5 1l1 1v-1z" id="trash-can-undo"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-rtl.png
new file mode 100644
index 00000000..f3801e4f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-rtl.svg
new file mode 100644
index 00000000..17ca8dc9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/trashUndo-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.5 3.5l1 1L17 7v2h-1v7.97L15 18H8.03L8 17.97 7 17l-2.5 2.5-1-1L7 15l1-1 1-1 1-1 1-1 1-1 1-1 1-1 1-1 1-1zM14 5v1l-1 1H7v1h5l-1 1H8v3l-1 1V9H6V6h3V5zm1 4l-1 1v6h-1v-5l-1 1v4h-1v-3l-1 1v2H9v-1l-1 1v1h7zm-5 1l-1 1v-1z" id="trash-can-undo"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tray.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tray.png
new file mode 100644
index 00000000..e5c5e8fc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tray.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tray.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tray.svg
new file mode 100644
index 00000000..d7ab69b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/tray.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 13.35l1.8-7.2c.2-.996.81-1.8 1.8-1.8h10.8c.99 0 1.6.867 1.8 1.8l1.8 7.2v4.5c0 .99-.81 1.8-1.8 1.8H4.8c-.99 0-1.8-.81-1.8-1.8v-4.5zm6.96 1.8h4.08c-.49.557-1.212.9-2.04.9a2.68 2.68 0 0 1-2.04-.9h4.08c.414-.472.66-1.098.66-1.8h4.14l-1.44-7.2H6.6l-1.44 7.2H9.3c0 .702.246 1.328.66 1.8z" id="tray"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-ltr.png
new file mode 100644
index 00000000..640bb2a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-ltr.svg
new file mode 100644
index 00000000..160219c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 11v2h-2l3.6 3.6c.9-1.3 1.4-2.9 1.4-4.6 0-4.4-3.6-8-8-8-1.7 0-3.3.5-4.6 1.4L13 11h4zM4 4L3 5l2.4 2.4C4.5 8.7 4 10.3 4 12c0 4.4 3.6 8 8 8 1.7 0 3.3-.5 4.6-1.4L19 21l1-1L4 4zm3 9v-2h2l2 2H7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-rtl.png
new file mode 100644
index 00000000..2475b061
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-rtl.svg
new file mode 100644
index 00000000..90fe46ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unBlock-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 11v2h2l-3.6 3.6C4.5 15.3 4 13.7 4 12c0-4.4 3.6-8 8-8 1.7 0 3.3.5 4.6 1.4L11 11H7zm13-7l1 1-2.4 2.4c.9 1.3 1.4 2.9 1.4 4.6 0 4.4-3.6 8-8 8-1.7 0-3.3-.5-4.6-1.4L5 21l-1-1L20 4zm-3 9v-2h-2l-2 2h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unClip.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unClip.png
new file mode 100644
index 00000000..37916ef2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unClip.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unClip.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unClip.svg
new file mode 100644
index 00000000..68459db6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unClip.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 21l7-6 7 6V3H5z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-ltr.png
new file mode 100644
index 00000000..780cb87f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-ltr.svg
new file mode 100644
index 00000000..4bbd61ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19.9 19.6l-16-16-1.1 1.1L6 7.9V20h1v-7c.6-.6 2-.8 3.4-.7l8.4 8.4 1.1-1.1zM17 14V7c-.7.7-2.7.9-4 .5V6c-1.2-1.3-3.9-1.3-5.4-.5l8.9 9c.3-.2.4-.3.5-.5z"/>
+</svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-rtl.png
new file mode 100644
index 00000000..fa3696ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-rtl.svg
new file mode 100644
index 00000000..5d944258
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unFlag-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3.5 19.6l16-16 1.1 1.1-3.2 3.2V20h-1v-7c-.6-.6-2-.8-3.4-.7l-8.4 8.4-1.1-1.1zM6.3 14V7c.7.7 2.7.9 4 .5V6c1.2-1.3 3.9-1.3 5.4-.5l-8.9 9c-.3-.2-.4-.3-.5-.5z"/>
+</svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-ltr.png
new file mode 100644
index 00000000..82919e77
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-ltr.svg
new file mode 100644
index 00000000..cc386c01
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 6a4 4 0 0 0-4 4v1h2v-1a2 2 0 0 1 4 0v1H9v7h10v-7h-7v-1a4 4 0 0 0-4-4z" id="unLock"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-rtl.png
new file mode 100644
index 00000000..94d15938
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-rtl.svg
new file mode 100644
index 00000000..b223490c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unLock-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 6a4 4 0 0 1 4 4v1h-2v-1a2 2 0 0 0-4 0v1h1v7H4v-7h7v-1a4 4 0 0 1 4-4z" id="unLock"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unStar.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unStar.png
new file mode 100644
index 00000000..2329af3e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unStar.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unStar.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unStar.svg
new file mode 100644
index 00000000..724d1901
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unStar.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 11l-6-1-3-6-3 6-6 1 4 4-1 6 6-3 6 3-1-6 4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-ltr.png
new file mode 100644
index 00000000..87590fa3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-ltr.svg
new file mode 100644
index 00000000..9a625b89
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4.5 3.5l-1 1L6 7v2h1v7.97L8 18h6.97l.03-.03 1-.97 2.5 2.5 1-1L16 15l-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1-1zM9 5v1l1 1h6v1h-5l1 1h3v3l1 1V9h1V6h-3V5zM8 9l1 1v6h1v-5l1 1v4h1v-3l1 1v2h1v-1l1 1v1H8zm5 1l1 1v-1z" id="trash-can-undo"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-rtl.png
new file mode 100644
index 00000000..dd350237
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-rtl.svg
new file mode 100644
index 00000000..17ca8dc9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/unTrash-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.5 3.5l1 1L17 7v2h-1v7.97L15 18H8.03L8 17.97 7 17l-2.5 2.5-1-1L7 15l1-1 1-1 1-1 1-1 1-1 1-1 1-1 1-1 1-1zM14 5v1l-1 1H7v1h5l-1 1H8v3l-1 1V9H6V6h3V5zm1 4l-1 1v6h-1v-5l-1 1v4h-1v-3l-1 1v2H9v-1l-1 1v1h7zm-5 1l-1 1v-1z" id="trash-can-undo"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-a.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-a.png
new file mode 100644
index 00000000..78a3c3f0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-a.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-a.svg
new file mode 100644
index 00000000..1ddae104
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-a.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="underline-a">
+ <path id="a" d="M14.424 16H16.5L13.037 6H10.96L7.5 16h2.077l.627-2h3.604l.616 2zm-3.92-3.623L12 7.997l1.51 4.38h-3z"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-u.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-u.png
new file mode 100644
index 00000000..0dbeb80c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-u.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-u.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-u.svg
new file mode 100644
index 00000000..ff47e2ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/underline-u.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="underline-u">
+ <path id="u" d="M8 6h2v5.96c-.104 1.706.695 2 2 2.04 1.777.062 2.002-.88 2-2.04V6h2v6.123c0 1.28-.338 2.245-1.016 2.898-.672.658-1.666.98-2.98.98-1.32 0-2.32-.32-2.996-.98C8.336 14.37 8 13.41 8 12.13V6"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upTriangle.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upTriangle.png
new file mode 100644
index 00000000..f1aca31a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upTriangle.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upTriangle.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upTriangle.svg
new file mode 100644
index 00000000..9f0efc59
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upTriangle.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 8l8 10H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-ltr.png
new file mode 100644
index 00000000..08e31e9e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-ltr.svg
new file mode 100644
index 00000000..dc4676fb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10 13c0 1.7 1.3 3 3 3V9h3l-4.5-5L7 9h3v4zm7 0v5H7c-.6 0-1-.4-1-1v-4H4v4c0 1.9 1.3 3 3 3h12v-7h-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-rtl.png
new file mode 100644
index 00000000..ccabf989
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-rtl.svg
new file mode 100644
index 00000000..ed3fe772
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/upload-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M13 13c0 1.7-1.3 3-3 3V9H7l4.5-5L16 9h-3v4zm-7 0v5h10c.6 0 1-.4 1-1v-4h2v4c0 1.9-1.3 3-3 3H4v-7h2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/userAvatar.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/userAvatar.png
new file mode 100644
index 00000000..81900956
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/userAvatar.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/userAvatar.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/userAvatar.svg
new file mode 100644
index 00000000..ce714e60
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/userAvatar.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.75 17.4c-1.08-.36-3.6-1.35-3.6-1.35-.81-.27-.81-.99-.9-1.8v-.09c1.26-1.08 2.25-2.88 2.25-4.86 0-4.23-1.8-5.85-4.5-5.85-1.89 0-4.5 1.08-4.5 5.85 0 1.89.99 3.69 2.25 4.86v.09c0 .81-.09 1.53-.9 1.8 0 0-2.61.99-3.6 1.35-1.17.36-2.25.9-2.25 2.25v.9h18v-.9c0-1.08-.72-1.8-2.25-2.25z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewCompact.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewCompact.png
new file mode 100644
index 00000000..13fe4207
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewCompact.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewCompact.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewCompact.svg
new file mode 100644
index 00000000..d96a2e3f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewCompact.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="viewCompact">
+ <circle cx="6" cy="6" r="2"/>
+ <circle cx="12" cy="6" r="2"/>
+ <circle cx="18" cy="6" r="2"/>
+ <circle cx="6" cy="12" r="2"/>
+ <circle cx="12" cy="12" r="2"/>
+ <circle cx="18" cy="12" r="2"/>
+ <circle cx="6" cy="18" r="2"/>
+ <circle cx="12" cy="18" r="2"/>
+ <circle cx="18" cy="18" r="2"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-ltr.png
new file mode 100644
index 00000000..4341f0e6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-ltr.svg
new file mode 100644
index 00000000..1a5092a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-ltr.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="viewDetails">
+ <circle cx="5.5" cy="8.5" r="2.5"/>
+ <path d="M10 6h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ <circle cx="5.5" cy="16.5" r="2.5"/>
+ <path d="M10 14h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-rtl.png
new file mode 100644
index 00000000..338294c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-rtl.svg
new file mode 100644
index 00000000..f43b05f1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/viewDetails-rtl.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="viewDetails">
+ <circle cx="18.5" cy="8.5" r="2.5"/>
+ <path d="M14 6H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ <circle cx="18.5" cy="16.5" r="2.5"/>
+ <path d="M14 14H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator-invert.png
new file mode 100644
index 00000000..e18ee176
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator-invert.svg
new file mode 100644
index 00000000..10edb0f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M0 10v8h2.3c.3.6 1 1 1.7 1h4c1.5 0 2.7-.8 3-2h2c.3 1.2 1.5 2 3 2h4c.7 0 1.4 0 1.7-1H24v-8zm10 6c0 1-.4 2-2 2H4c-.6 0-1-.4-1-1v-3c0-.6.4-1 1-1h5c.6 0 1 .4 1 1zm11 1c0 .6-.4 1-1 1h-4c-1.6 0-2-1-2-2v-2c0-.6.4-1 1-1h5c.6 0 1 .4 1 1z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator.png
new file mode 100644
index 00000000..afa56528
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator.svg
new file mode 100644
index 00000000..ae6ba27a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/visionSimulator.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M0 10v8h2.3c.3.6 1 1 1.7 1h4c1.5 0 2.7-.8 3-2h2c.3 1.2 1.5 2 3 2h4c.7 0 1.4 0 1.7-1H24v-8zm10 6c0 1-.4 2-2 2H4c-.6 0-1-.4-1-1v-3c0-.6.4-1 1-1h5c.6 0 1 .4 1 1zm11 1c0 .6-.4 1-1 1h-4c-1.6 0-2-1-2-2v-2c0-.6.4-1 1-1h5c.6 0 1 .4 1 1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr-invert.png
new file mode 100644
index 00000000..70189688
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr-invert.svg
new file mode 100644
index 00000000..7545aeb1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M13 14h5v1h-5v-1zm0 3h5v-1h-5v1zm0 1h5v1h-5v-1zm-1-5v3l-5 3 1-6-4-3 6-1 2-5s1.9 5 2 5l6 1-4 3h-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr.png
new file mode 100644
index 00000000..53e70116
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr.svg
new file mode 100644
index 00000000..b13df22d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M13 14h5v1h-5v-1zm0 3h5v-1h-5v1zm0 1h5v1h-5v-1zm-1-5v3l-5 3 1-6-4-3 6-1 2-5s1.9 5 2 5l6 1-4 3h-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl-invert.png
new file mode 100644
index 00000000..28008b5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl-invert.svg
new file mode 100644
index 00000000..812ee388
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M11 14H6v1h5v-1zm0 3H6v-1h5v1zm0 1H6v1h5v-1zm1-5v3l5 3-1-6 4-3-6-1-2-5s-1.9 5-2 5l-6 1 4 3h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl.png
new file mode 100644
index 00000000..8fc4df52
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl.svg
new file mode 100644
index 00000000..a4ec49a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/watchlist-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 14H6v1h5v-1zm0 3H6v-1h5v1zm0 1H6v1h5v-1zm1-5v3l5 3-1-6 4-3-6-1-2-5s-1.9 5-2 5l-6 1 4 3h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/wikiText.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/wikiText.png
new file mode 100644
index 00000000..40309aac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/wikiText.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/wikiText.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/wikiText.svg
new file mode 100644
index 00000000..4512cf56
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/wikiText.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="wikiText">
+ <path id="opening-bracket-inner" d="M7 19h3v-2H9V7h1V5H7z"/>
+ <path id="closing-bracket-inner" d="M17 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="closing-bracket-outer" d="M21 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="opening-bracket-outer" d="M3 19h3v-2H5V7h1V5H3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/window.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/window.png
new file mode 100644
index 00000000..bae13d71
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/window.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/window.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/window.svg
new file mode 100644
index 00000000..093c8228
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/icons/window.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="window">
+ <path id="title" d="M7 10h10v1H7z"/>
+ <path id="frame" d="M16 19H8c-2.206 0-4-1.794-4-4V9c0-2.206 1.794-4 4-4h8c2.206 0 4 1.794 4 4v6c0 2.206-1.794 4-4 4zM8 7c-1.103 0-2 .897-2 2v6c0 1.103.897 2 2 2h8c1.103 0 2-.897 2-2V9c0-1.103-.897-2-2-2H8z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/alert.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/alert.png
new file mode 100644
index 00000000..9d25a24e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/alert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/alert.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/alert.svg
new file mode 100644
index 00000000..f94346ac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/alert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <path d="M6 12A6 6 0 1 1 6 0a6 6 0 0 1 0 12zM5 7h2V2H5zm0 3h2V8H5z" id="alert"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-down.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-down.png
new file mode 100644
index 00000000..f6ff705d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-down.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-down.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-down.svg
new file mode 100644
index 00000000..5ce25ba0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-down.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="down">
+ <path id="arrow" d="M2 3l3.5 6L9 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-ltr.png
new file mode 100644
index 00000000..3c94da36
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-ltr.svg
new file mode 100644
index 00000000..e0f13e6d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="ltr">
+ <path id="arrow" d="M3 9V2l6 3.5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-rtl.png
new file mode 100644
index 00000000..6b1422fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-rtl.svg
new file mode 100644
index 00000000..c88c364b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="rtl">
+ <path id="arrow" d="M3 5.5L9 9V2z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-up.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-up.png
new file mode 100644
index 00000000..5b2081c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-up.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-up.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-up.svg
new file mode 100644
index 00000000..7a250f58
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/arrow-up.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="up">
+ <path id="arrow" d="M5.5 2L2 8h7z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/clear.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/clear.png
new file mode 100644
index 00000000..a858a031
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/clear.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/clear.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/clear.svg
new file mode 100644
index 00000000..3c010c10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/clear.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="clear">
+ <path id="circle-with-cross" d="M6 0C2.7 0 0 2.7 0 6s2.7 6 6 6 6-2.7 6-6-2.7-6-6-6zM3.5 2.5L6 5l2.5-2.5 1 1L7 6l2.5 2.5-1 1L6 7 3.5 9.5l-1-1L5 6 2.5 3.5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/required.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/required.png
new file mode 100644
index 00000000..aca92390
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/required.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/required.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/required.svg
new file mode 100644
index 00000000..94b0066e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/required.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <path d="M5 1h2v10H5zm4.83 1.634l1 1.732-8.66 5-1-1.732zM1.17 4.366l1-1.732 8.66 5-1 1.732z" id="required"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-ltr.png
new file mode 100644
index 00000000..123fbfa2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-ltr.svg
new file mode 100644
index 00000000..80c72bb5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="search">
+ <path id="magnifying-glass" d="M10.37 9.474L7.994 7.1l-.17-.1a3.45 3.45 0 0 0 .644-2.01A3.478 3.478 0 1 0 4.99 8.47c.75 0 1.442-.24 2.01-.648l.098.17 2.375 2.373c.19.188.543.142.79-.105s.293-.6.104-.79zm-5.38-2.27a2.21 2.21 0 1 1 2.21-2.21A2.21 2.21 0 0 1 4.99 7.21z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-rtl.png
new file mode 100644
index 00000000..db740615
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-rtl.svg
new file mode 100644
index 00000000..4b3cff42
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/indicators/search-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="search">
+ <path id="magnifying-glass" d="M1.63 9.474L4.006 7.1l.17-.1a3.45 3.45 0 0 1-.644-2.01A3.478 3.478 0 1 1 7.01 8.47 3.43 3.43 0 0 1 5 7.822l-.098.17-2.375 2.373c-.19.188-.543.142-.79-.105s-.293-.6-.104-.79zm5.378-2.27A2.21 2.21 0 1 0 4.8 4.994 2.21 2.21 0 0 0 7.01 7.21z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/pending.gif b/www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/pending.gif
new file mode 100644
index 00000000..1194eed2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/pending.gif
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/transparency.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/transparency.png
new file mode 100644
index 00000000..dbf69b93
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/transparency.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/transparency.svg b/www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/transparency.svg
new file mode 100644
index 00000000..cadec2a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/textures/transparency.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+ <g id="transparency">
+ <path d="M0 0h8v8H0zm8 8h8v8H8z" fill="#ccc"/>
+ <path d="M8 0h8v8H8zM0 8h8v8H0z" fill="#fff"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/images/toolbar-shadow.png b/www/wiki/resources/lib/oojs-ui/themes/apex/images/toolbar-shadow.png
new file mode 100644
index 00000000..eeb20b0b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/images/toolbar-shadow.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/indicators.json b/www/wiki/resources/lib/oojs-ui/themes/apex/indicators.json
new file mode 100644
index 00000000..9a9afa8b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/indicators.json
@@ -0,0 +1,23 @@
+{
+ "prefix": "oo-ui-indicator",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "alert": { "file": "images/indicators/alert.svg" },
+ "clear": { "file": "images/indicators/clear.svg" },
+ "up": { "file": "images/indicators/arrow-up.svg" },
+ "down": { "file": "images/indicators/arrow-down.svg" },
+ "next": { "file": {
+ "ltr": "images/indicators/arrow-ltr.svg",
+ "rtl": "images/indicators/arrow-rtl.svg"
+ } },
+ "previous": { "file": {
+ "ltr": "images/indicators/arrow-rtl.svg",
+ "rtl": "images/indicators/arrow-ltr.svg"
+ } },
+ "required": { "file": "images/indicators/required.svg" },
+ "search": { "file": {
+ "ltr": "images/indicators/search-ltr.svg",
+ "rtl": "images/indicators/search-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/apex/textures.json b/www/wiki/resources/lib/oojs-ui/themes/apex/textures.json
new file mode 100644
index 00000000..e90730ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/apex/textures.json
@@ -0,0 +1,8 @@
+{
+ "prefix": "oo-ui-texture",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "pending": { "file": "images/textures/pending.gif" },
+ "transparency": { "file": "images/textures/transparency.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-accessibility.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-accessibility.json
new file mode 100644
index 00000000..4db45f4c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-accessibility.json
@@ -0,0 +1,26 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "bright": { "file": "images/icons/bright.svg" },
+ "halfBright": { "file": "images/icons/halfBright.svg" },
+ "notBright": { "file": "images/icons/notBright.svg" },
+ "moon": { "file": "images/icons/moon.svg" },
+ "largerText": { "file": {
+ "ltr": "images/icons/largerText-ltr.svg",
+ "rtl": "images/icons/largerText-rtl.svg"
+ } },
+ "smallerText": { "file": {
+ "ltr": "images/icons/smallerText-ltr.svg",
+ "rtl": "images/icons/smallerText-rtl.svg"
+ } },
+ "visionSimulator": { "file": "images/icons/visionSimulator.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-alerts.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-alerts.json
new file mode 100644
index 00000000..79f644ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-alerts.json
@@ -0,0 +1,40 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "bell": { "file": "images/icons/bell.svg" },
+ "bellOn": { "file": {
+ "ltr": "images/icons/bellOn-ltr.svg",
+ "rtl": "images/icons/bellOn-rtl.svg"
+ } },
+ "eye": { "file": "images/icons/eye.svg" },
+ "eyeClosed": { "file": "images/icons/eyeClosed.svg" },
+ "message": { "file": {
+ "ltr": "images/icons/message-ltr.svg",
+ "rtl": "images/icons/message-rtl.svg"
+ } },
+ "signature": { "file": {
+ "ltr": "images/icons/signature-ltr.svg",
+ "rtl": "images/icons/signature-rtl.svg"
+ } },
+ "speechBubble": { "file": {
+ "ltr": "images/icons/speechBubble-ltr.svg",
+ "rtl": "images/icons/speechBubble-rtl.svg"
+ } },
+ "speechBubbleAdd": { "file": {
+ "ltr": "images/icons/speechBubbleAdd-ltr.svg",
+ "rtl": "images/icons/speechBubbleAdd-rtl.svg"
+ } },
+ "speechBubbles": { "file": {
+ "ltr": "images/icons/speechBubbles-ltr.svg",
+ "rtl": "images/icons/speechBubbles-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-content.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-content.json
new file mode 100644
index 00000000..c04573f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-content.json
@@ -0,0 +1,65 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "article": { "file": {
+ "ltr": "images/icons/article-ltr.svg",
+ "rtl": "images/icons/article-rtl.svg"
+ } },
+ "articles": { "file": {
+ "ltr": "images/icons/articles-ltr.svg",
+ "rtl": "images/icons/articles-rtl.svg"
+ } },
+ "articleCheck": { "file": {
+ "ltr": "images/icons/articleCheck-ltr.svg",
+ "rtl": "images/icons/articleCheck-rtl.svg"
+ } },
+ "articleSearch": { "file": {
+ "ltr": "images/icons/articleSearch-ltr.svg",
+ "rtl": "images/icons/articleSearch-rtl.svg"
+ } },
+ "articleRedirect": { "file": {
+ "ltr": "images/icons/articleRedirect-ltr.svg",
+ "rtl": "images/icons/articleRedirect-rtl.svg"
+ } },
+ "book": { "file": {
+ "ltr": "images/icons/book-ltr.svg",
+ "rtl": "images/icons/book-rtl.svg"
+ } },
+ "citeArticle": { "file": {
+ "ltr": "images/icons/citeArticle-ltr.svg",
+ "rtl": "images/icons/citeArticle-rtl.svg"
+ } },
+ "die": { "file": {
+ "ltr": "images/icons/die-ltr.svg",
+ "rtl": "images/icons/die-rtl.svg"
+ } },
+ "download": { "file": {
+ "ltr": "images/icons/download-ltr.svg",
+ "rtl": "images/icons/download-rtl.svg"
+ } },
+ "folderPlaceholder": { "file": {
+ "ltr": "images/icons/folderPlaceholder-ltr.svg",
+ "rtl": "images/icons/folderPlaceholder-rtl.svg"
+ } },
+ "journal": { "file": {
+ "ltr": "images/icons/journal-ltr.svg",
+ "rtl": "images/icons/journal-rtl.svg"
+ } },
+ "newspaper": { "file": {
+ "ltr": "images/icons/newspaper-ltr.svg",
+ "rtl": "images/icons/newspaper-rtl.svg"
+ } },
+ "upload": { "file": {
+ "ltr": "images/icons/upload-ltr.svg",
+ "rtl": "images/icons/upload-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-advanced.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-advanced.json
new file mode 100644
index 00000000..40516c0b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-advanced.json
@@ -0,0 +1,91 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "alignCentre": { "file": "images/icons/align-center.svg" },
+ "alignLeft": { "file": "images/icons/align-float-left.svg" },
+ "alignRight": { "file": "images/icons/align-float-right.svg" },
+ "attachment": { "file": {
+ "ltr": "images/icons/attachment-ltr.svg",
+ "rtl": "images/icons/attachment-rtl.svg"
+ } },
+ "calendar": { "file": {
+ "ltr": "images/icons/calendar-ltr.svg",
+ "rtl": "images/icons/calendar-rtl.svg"
+ } },
+ "code": { "file": "images/icons/code.svg" },
+ "find": { "file": {
+ "ltr": "images/icons/find-ltr.svg",
+ "rtl": "images/icons/find-rtl.svg"
+ } },
+ "language": { "file": {
+ "ltr": "images/icons/language-ltr.svg",
+ "rtl": "images/icons/language-rtl.svg"
+ } },
+ "layout": { "file": {
+ "ltr": "images/icons/layout-ltr.svg",
+ "rtl": "images/icons/layout-rtl.svg"
+ } },
+ "markup": { "file": "images/icons/markup.svg" },
+ "newline": { "file": {
+ "ltr": "images/icons/newline-ltr.svg",
+ "rtl": "images/icons/newline-rtl.svg"
+ } },
+ "noWikiText": { "file": {
+ "ltr": "images/icons/noWikiText-ltr.svg",
+ "rtl": "images/icons/noWikiText-rtl.svg"
+ } },
+ "outline": { "file": {
+ "ltr": "images/icons/outline-ltr.svg",
+ "rtl": "images/icons/outline-rtl.svg"
+ } },
+ "puzzle": { "file": {
+ "ltr": "images/icons/puzzle-ltr.svg",
+ "rtl": "images/icons/puzzle-rtl.svg"
+ } },
+ "quotes": { "file": {
+ "ltr": "images/icons/quotes-ltr.svg",
+ "rtl": "images/icons/quotes-rtl.svg"
+ } },
+ "quotesAdd": { "file": {
+ "ltr": "images/icons/quotesAdd-ltr.svg",
+ "rtl": "images/icons/quotesAdd-rtl.svg"
+ } },
+ "redirect": { "file": {
+ "ltr": "images/icons/articleRedirect-ltr.svg",
+ "rtl": "images/icons/articleRedirect-rtl.svg"
+ } },
+ "searchCaseSensitive": { "file": "images/icons/case-sensitive.svg" },
+ "searchRegularExpression": { "file": "images/icons/regular-expression.svg" },
+ "specialCharacter": { "file": "images/icons/specialCharacter.svg" },
+ "table": { "file": "images/icons/table.svg" },
+ "tableAddColumnAfter": { "file": {
+ "ltr": "images/icons/table-insert-column-rtl.svg",
+ "rtl": "images/icons/table-insert-column-ltr.svg"
+ } },
+ "tableAddColumnBefore": { "file": {
+ "ltr": "images/icons/table-insert-column-ltr.svg",
+ "rtl": "images/icons/table-insert-column-rtl.svg"
+ } },
+ "tableAddRowAfter": { "file": "images/icons/table-insert-row-after.svg" },
+ "tableAddRowBefore": { "file": "images/icons/table-insert-row-before.svg" },
+ "tableCaption": { "file": "images/icons/table-caption.svg" },
+ "tableMergeCells": { "file": "images/icons/table-merge-cells.svg" },
+ "templateAdd": { "file": {
+ "ltr": "images/icons/templateAdd-ltr.svg",
+ "rtl": "images/icons/templateAdd-rtl.svg"
+ } },
+ "translation": { "file": {
+ "ltr": "images/icons/language-ltr.svg",
+ "rtl": "images/icons/language-rtl.svg"
+ } },
+ "wikiText": { "file": "images/icons/wikiText.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-core.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-core.json
new file mode 100644
index 00000000..d70f60e3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-core.json
@@ -0,0 +1,54 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#347bff"
+ },
+ "constructive": {
+ "color": "#347bff"
+ },
+ "destructive": {
+ "color": "#d11d13"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "edit": { "file": {
+ "ltr": "images/icons/edit-ltr.svg",
+ "rtl": "images/icons/edit-rtl.svg"
+ }, "variants": [ "progressive" ] },
+ "editLock": { "file": {
+ "ltr": "images/icons/editLock-ltr.svg",
+ "rtl": "images/icons/editLock-rtl.svg"
+ } },
+ "editUndo": { "file": {
+ "ltr": "images/icons/editUndo-ltr.svg",
+ "rtl": "images/icons/editUndo-rtl.svg"
+ } },
+ "link": { "file": {
+ "ltr": "images/icons/link-ltr.svg",
+ "rtl": "images/icons/link-rtl.svg"
+ } },
+ "linkExternal": { "file": {
+ "ltr": "images/icons/external-link-ltr.svg",
+ "rtl": "images/icons/external-link-rtl.svg"
+ } },
+ "linkSecure": { "file": "images/icons/secure-link.svg" },
+ "redo": { "file": {
+ "ltr": "images/icons/arched-arrow-ltr.svg",
+ "rtl": "images/icons/arched-arrow-rtl.svg"
+ } },
+ "undo": { "file": {
+ "ltr": "images/icons/arched-arrow-rtl.svg",
+ "rtl": "images/icons/arched-arrow-ltr.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-list.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-list.json
new file mode 100644
index 00000000..489d6cac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-list.json
@@ -0,0 +1,29 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "indent": { "file": {
+ "ltr": "images/icons/indent-ltr.svg",
+ "rtl": "images/icons/indent-rtl.svg"
+ } },
+ "listBullet": { "file": {
+ "ltr": "images/icons/listBullet-ltr.svg",
+ "rtl": "images/icons/listBullet-rtl.svg"
+ } },
+ "listNumbered": { "file": {
+ "ltr": "images/icons/listNumbered-ltr.svg",
+ "rtl": "images/icons/listNumbered-rtl.svg"
+ } },
+ "outdent": { "file": {
+ "ltr": "images/icons/outdent-ltr.svg",
+ "rtl": "images/icons/outdent-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-styling.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-styling.json
new file mode 100644
index 00000000..45c6a643
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-editing-styling.json
@@ -0,0 +1,82 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "bigger": { "file": {
+ "ltr": "images/icons/bigger-ltr.svg",
+ "rtl": "images/icons/bigger-rtl.svg"
+ } },
+ "smaller": { "file": {
+ "ltr": "images/icons/smaller-ltr.svg",
+ "rtl": "images/icons/smaller-rtl.svg"
+ } },
+ "subscript": { "file": {
+ "ltr": "images/icons/subscript-ltr.svg",
+ "rtl": "images/icons/subscript-rtl.svg"
+ } },
+ "superscript": { "file": {
+ "ltr": "images/icons/superscript-ltr.svg",
+ "rtl": "images/icons/superscript-rtl.svg"
+ } },
+ "bold": { "file": {
+ "default": "images/icons/bold-a.svg",
+ "lang": {
+ "ar": "images/icons/bold-arab-ain.svg",
+ "be": "images/icons/bold-cyrl-te.svg",
+ "cs,en,he,ml,pl,sco": "images/icons/bold-b.svg",
+ "da,de,hu,ksh,nn,no,sv": "images/icons/bold-f.svg",
+ "es,gl,pt": "images/icons/bold-n.svg",
+ "eu,fi": "images/icons/bold-l.svg",
+ "fa": "images/icons/bold-arab-dad.svg",
+ "fr,it": "images/icons/bold-g.svg",
+ "hy": "images/icons/bold-armn-to.svg",
+ "ka": "images/icons/bold-geor-man.svg",
+ "ky,ru,uk": "images/icons/bold-cyrl-zhe.svg",
+ "nl": "images/icons/bold-v.svg",
+ "os": "images/icons/bold-cyrl-be.svg"
+ }
+ } },
+ "italic": { "file": {
+ "default": "images/icons/italic-a.svg",
+ "lang": {
+ "ar": "images/icons/italic-arab-meem.svg",
+ "cs,en,fr,he,ml,pl,pt,sco": "images/icons/italic-i.svg",
+ "be,da,de,fi,ky,nn,no,os,sv,ru,uk": "images/icons/italic-k.svg",
+ "es,gl,it,nl": "images/icons/italic-c.svg",
+ "eu": "images/icons/italic-e.svg",
+ "fa": "images/icons/italic-arab-keheh-jeem.svg",
+ "hu": "images/icons/italic-d.svg",
+ "hy": "images/icons/italic-armn-sha.svg",
+ "ksh": "images/icons/italic-s.svg",
+ "ka": "images/icons/italic-geor-kan.svg"
+ }
+ } },
+ "strikethrough": { "file": {
+ "default": "images/icons/strikethrough-a.svg",
+ "lang": {
+ "en": "images/icons/strikethrough-s.svg",
+ "fi": "images/icons/strikethrough-y.svg"
+ }
+ } },
+ "underline": { "file": {
+ "default": "images/icons/underline-a.svg",
+ "lang": {
+ "en": "images/icons/underline-u.svg"
+ }
+ } },
+ "textLanguage": { "file": {
+ "ltr": "images/icons/language-ltr.svg",
+ "rtl": "images/icons/language-rtl.svg"
+ } },
+ "textDirLTR": { "file": "images/icons/text-dir-lefttoright.svg" },
+ "textDirRTL": { "file": "images/icons/text-dir-righttoleft.svg" },
+ "textStyle": { "file": "images/icons/text-style.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-interactions.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-interactions.json
new file mode 100644
index 00000000..c3263e2c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-interactions.json
@@ -0,0 +1,59 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "beta": { "file": "images/icons/beta.svg" },
+ "betaLaunch": { "file": "images/icons/betaLaunch.svg" },
+ "bookmark": { "file": {
+ "ltr": "images/icons/bookmark-ltr.svg",
+ "rtl": "images/icons/bookmark-rtl.svg"
+ } },
+ "browser": { "file": {
+ "ltr": "images/icons/browser-ltr.svg",
+ "rtl": "images/icons/browser-rtl.svg"
+ } },
+ "clear": { "file": "images/icons/clear.svg" },
+ "clock": { "file": "images/icons/clock.svg" },
+ "funnel": { "file": {
+ "ltr": "images/icons/funnel-ltr.svg",
+ "rtl": "images/icons/funnel-rtl.svg"
+ } },
+ "heart": { "file": "images/icons/heart.svg" },
+ "key": { "file": {
+ "ltr": "images/icons/key-ltr.svg",
+ "rtl": "images/icons/key-rtl.svg"
+ } },
+ "keyboard": { "file": {
+ "ltr": "images/icons/keyboard-ltr.svg",
+ "rtl": "images/icons/keyboard-rtl.svg"
+ } },
+ "logOut": { "file": {
+ "ltr": "images/icons/logOut-ltr.svg",
+ "rtl": "images/icons/logOut-rtl.svg"
+ } },
+ "newWindow": { "file": {
+ "ltr": "images/icons/newWindow-ltr.svg",
+ "rtl": "images/icons/newWindow-rtl.svg"
+ } },
+ "printer": { "file": {
+ "ltr": "images/icons/printer-ltr.svg",
+ "rtl": "images/icons/printer-rtl.svg"
+ } },
+ "ribbonPrize": { "file": "images/icons/ribbonPrize.svg" },
+ "sun": { "file": {
+ "ltr": "images/icons/sun-ltr.svg",
+ "rtl": "images/icons/sun-rtl.svg"
+ } },
+ "watchlist": { "file": {
+ "ltr": "images/icons/watchlist-ltr.svg",
+ "rtl": "images/icons/watchlist-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-layout.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-layout.json
new file mode 100644
index 00000000..efad42ed
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-layout.json
@@ -0,0 +1,43 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#347bff"
+ },
+ "constructive": {
+ "color": "#347bff"
+ },
+ "destructive": {
+ "color": "#d11d13"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "stripeFlow": { "file": {
+ "ltr": "images/icons/stripeFlow-ltr.svg",
+ "rtl": "images/icons/stripeFlow-rtl.svg"
+ } },
+ "stripeSideMenu": { "file": "images/icons/stripeSideMenu.svg" },
+ "stripeSummary": { "file": {
+ "ltr": "images/icons/stripeSummary-ltr.svg",
+ "rtl": "images/icons/stripeSummary-rtl.svg"
+ } },
+ "stripeToC": { "file": {
+ "ltr": "images/icons/stripeToC-ltr.svg",
+ "rtl": "images/icons/stripeToC-rtl.svg"
+ }, "variants": [ "progressive" ] },
+ "viewCompact": { "file": "images/icons/viewCompact.svg" },
+ "viewDetails": { "file": {
+ "ltr": "images/icons/viewDetails-ltr.svg",
+ "rtl": "images/icons/viewDetails-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-location.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-location.json
new file mode 100644
index 00000000..c53946f4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-location.json
@@ -0,0 +1,26 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "map": { "file": {
+ "ltr": "images/icons/map-ltr.svg",
+ "rtl": "images/icons/map-rtl.svg"
+ } },
+ "mapPin": { "file": "images/icons/mapPin.svg" },
+ "mapPinAdd": { "file": {
+ "ltr": "images/icons/mapPinAdd-ltr.svg",
+ "rtl": "images/icons/mapPinAdd-rtl.svg"
+ } },
+ "wikitrail": { "file": {
+ "ltr": "images/icons/wikitrail-ltr.svg",
+ "rtl": "images/icons/wikitrail-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-media.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-media.json
new file mode 100644
index 00000000..56da53cd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-media.json
@@ -0,0 +1,39 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "fullScreen": { "file": "images/icons/fullScreen.svg" },
+ "image": { "file": {
+ "ltr": "images/icons/image-ltr.svg",
+ "rtl": "images/icons/image-rtl.svg"
+ } },
+ "imageAdd": { "file": {
+ "ltr": "images/icons/imageAdd-ltr.svg",
+ "rtl": "images/icons/imageAdd-rtl.svg"
+ } },
+ "imageLock": { "file": {
+ "ltr": "images/icons/imageLock-ltr.svg",
+ "rtl": "images/icons/imageLock-rtl.svg"
+ } },
+ "imageGallery": { "file": {
+ "ltr": "images/icons/imageGallery-ltr.svg",
+ "rtl": "images/icons/imageGallery-rtl.svg"
+ } },
+ "photoGallery": { "file": {
+ "ltr": "images/icons/imageGallery-ltr.svg",
+ "rtl": "images/icons/imageGallery-rtl.svg"
+ } },
+ "play": { "file": {
+ "ltr": "images/icons/play-ltr.svg",
+ "rtl": "images/icons/play-rtl.svg"
+ } },
+ "stop": { "file": "images/icons/stop.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-moderation.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-moderation.json
new file mode 100644
index 00000000..65c7c5bd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-moderation.json
@@ -0,0 +1,60 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#347bff"
+ },
+ "constructive": {
+ "color": "#347bff"
+ },
+ "destructive": {
+ "color": "#d11d13"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "block": { "file": "images/icons/block.svg", "variants": [ "destructive" ] },
+ "blockUndo": { "file": {
+ "ltr": "images/icons/blockUndo-ltr.svg",
+ "rtl": "images/icons/blockUndo-rtl.svg"
+ } },
+ "flag": { "file": {
+ "ltr": "images/icons/flag-ltr.svg",
+ "rtl": "images/icons/flag-rtl.svg"
+ } },
+ "flagUndo": { "file": {
+ "ltr": "images/icons/flagUndo-ltr.svg",
+ "rtl": "images/icons/flagUndo-rtl.svg"
+ } },
+ "lock": { "file": {
+ "ltr": "images/icons/lock-ltr.svg",
+ "rtl": "images/icons/lock-rtl.svg"
+ }, "variants": [ "destructive" ] },
+ "ongoingConversation": {
+ "file": {
+ "ltr": "images/icons/ongoingConversation-ltr.svg",
+ "rtl": "images/icons/ongoingConversation-rtl.svg"
+ },
+ "variants": [ "progressive" ]
+ },
+ "star": { "file": "images/icons/star.svg", "variants": [ "constructive", "progressive" ] },
+ "trash": { "file": "images/icons/trash.svg" },
+ "trashUndo": { "file": {
+ "ltr": "images/icons/trashUndo-ltr.svg",
+ "rtl": "images/icons/trashUndo-rtl.svg"
+ } },
+ "unLock": { "file": {
+ "ltr": "images/icons/unLock-ltr.svg",
+ "rtl": "images/icons/unLock-rtl.svg"
+ }, "variants": [ "destructive" ] },
+ "unStar": { "file": "images/icons/unStar.svg", "variants": [ "constructive", "progressive" ] }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-movement.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-movement.json
new file mode 100644
index 00000000..c216c376
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-movement.json
@@ -0,0 +1,34 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "arrowNext": { "file": {
+ "ltr": "images/icons/arrow-ltr.svg",
+ "rtl": "images/icons/arrow-rtl.svg"
+ } },
+ "arrowLast": { "file": {
+ "ltr": "images/icons/arrow-rtl.svg",
+ "rtl": "images/icons/arrow-ltr.svg"
+ } },
+ "caretNext": { "file": {
+ "ltr": "images/icons/caret-rtl.svg",
+ "rtl": "images/icons/caret-ltr.svg"
+ } },
+ "caretLast": { "file": {
+ "ltr": "images/icons/caret-ltr.svg",
+ "rtl": "images/icons/caret-rtl.svg"
+ } },
+ "caretDown": { "file": "images/icons/caretDown.svg" },
+ "caretUp": { "file": "images/icons/caretUp.svg" },
+ "downTriangle": { "file": "images/icons/downTriangle.svg" },
+ "move": { "file": "images/icons/move.svg" },
+ "upTriangle": { "file": "images/icons/upTriangle.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-user.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-user.json
new file mode 100644
index 00000000..1b9359a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-user.json
@@ -0,0 +1,26 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#FFFFFF",
+ "global": true
+ }
+ },
+ "images": {
+ "userActive": { "file": {
+ "ltr": "images/icons/userActive-ltr.svg",
+ "rtl": "images/icons/userActive-rtl.svg"
+ } },
+ "userAvatar": { "file": "images/icons/userAvatar.svg" },
+ "userInactive": { "file": {
+ "ltr": "images/icons/userInactive-ltr.svg",
+ "rtl": "images/icons/userInactive-rtl.svg"
+ } },
+ "userTalk": { "file": {
+ "ltr": "images/icons/userTalk-ltr.svg",
+ "rtl": "images/icons/userTalk-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-wikimedia.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-wikimedia.json
new file mode 100644
index 00000000..cf19c6c6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons-wikimedia.json
@@ -0,0 +1,16 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "logoCC": { "file": "images/icons/logo-cc.svg" },
+ "logoWikimediaCommons": { "file": "images/icons/logo-wikimediaCommons.svg" },
+ "logoWikipedia": { "file": "images/icons/logo-wikipedia.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons.json
new file mode 100644
index 00000000..047bc6b4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/icons.json
@@ -0,0 +1,78 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#347bff"
+ },
+ "constructive": {
+ "color": "#347bff"
+ },
+ "constructive-deprecated": {
+ "color": "#00af89"
+ },
+ "destructive": {
+ "color": "#d11d13"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "add": { "file": "images/icons/add.svg", "variants": [ "constructive", "progressive" ] },
+ "advanced": { "file": "images/icons/advanced.svg" },
+ "alert": { "file": "images/icons/alert.svg", "variants": [ "warning" ] },
+ "cancel": { "file": "images/icons/cancel.svg", "variants": [ "destructive" ] },
+ "check": { "file": "images/icons/check.svg", "variants": [ "constructive-deprecated", "constructive", "progressive", "destructive" ] },
+ "circle": { "file": "images/icons/circle.svg", "variants": [ "constructive-deprecated", "constructive", "progressive" ] },
+ "close": { "file": {
+ "ltr": "images/icons/close-ltr.svg",
+ "rtl": "images/icons/close-rtl.svg"
+ } },
+ "code": { "file": "images/icons/code.svg" },
+ "collapse": { "file": "images/icons/collapse.svg" },
+ "comment": { "file": "images/icons/comment.svg" },
+ "ellipsis": { "file": "images/icons/ellipsis.svg" },
+ "expand": { "file": "images/icons/expand.svg" },
+ "help": { "file": {
+ "ltr": "images/icons/help-ltr.svg",
+ "rtl": "images/icons/help-rtl.svg",
+ "lang": {
+ "he,yi": "images/icons/help-ltr.svg"
+ }
+ } },
+ "history": { "file": "images/icons/history.svg" },
+ "info": { "file": "images/icons/info.svg" },
+ "menu": { "file": "images/icons/menu.svg" },
+ "next": { "file": {
+ "ltr": "images/icons/move-ltr.svg",
+ "rtl": "images/icons/move-rtl.svg"
+ } },
+ "notice": { "file": "images/icons/notice.svg" },
+ "previous": { "file": {
+ "ltr": "images/icons/move-rtl.svg",
+ "rtl": "images/icons/move-ltr.svg"
+ } },
+ "redo": { "file": {
+ "ltr": "images/icons/arched-arrow-ltr.svg",
+ "rtl": "images/icons/arched-arrow-rtl.svg"
+ } },
+ "remove": { "file": "images/icons/trash.svg", "variants": [ "destructive" ] },
+ "search": { "file": {
+ "ltr": "images/icons/search-ltr.svg",
+ "rtl": "images/icons/search-rtl.svg"
+ } },
+ "settings": { "file": "images/icons/settings.svg" },
+ "tag": { "file": "images/icons/tag.svg", "variants": [ "destructive", "warning", "constructive", "progressive" ] },
+ "undo": { "file": {
+ "ltr": "images/icons/arched-arrow-rtl.svg",
+ "rtl": "images/icons/arched-arrow-ltr.svg"
+ } },
+ "window": { "file": "images/icons/window.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-constructive.png
new file mode 100644
index 00000000..02d4f126
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-constructive.svg
new file mode 100644
index 00000000..34a4bba6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-constructive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <g id="add">
+ <path id="plus" d="M13 6h-2v5H6v2h5v5h2v-5h5v-2h-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-invert.png
new file mode 100644
index 00000000..8deeddf4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-invert.svg
new file mode 100644
index 00000000..bedfe5a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="add">
+ <path id="plus" d="M13 6h-2v5H6v2h5v5h2v-5h5v-2h-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-progressive.png
new file mode 100644
index 00000000..02d4f126
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-progressive.svg
new file mode 100644
index 00000000..34a4bba6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <g id="add">
+ <path id="plus" d="M13 6h-2v5H6v2h5v5h2v-5h5v-2h-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add.png
new file mode 100644
index 00000000..4c70ee4a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add.svg
new file mode 100644
index 00000000..62e54965
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/add.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="add">
+ <path id="plus" d="M13 6h-2v5H6v2h5v5h2v-5h5v-2h-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced-invert.png
new file mode 100644
index 00000000..67fec171
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced-invert.svg
new file mode 100644
index 00000000..9cf7fabf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M20 13.44v-2.88l-1.8-.3c-.1-.397-.3-.794-.6-1.39l1.1-1.49-2.1-2.088-1.5 1.093c-.5-.298-1-.497-1.4-.596L13.5 4h-2.9l-.3 1.79c-.5.098-.9.297-1.4.595L7.4 5.292 5.3 7.38l1 1.49c-.3.496-.4.894-.6 1.39l-1.7.2v2.882l1.8.298c.1.497.3.894.6 1.39l-1 1.492 2.1 2.087 1.5-1c.4.2.9.395 1.4.594l.3 1.79h3l.3-1.79c.5-.1.9-.298 1.4-.596l1.5 1.092 2.1-2.08-1.1-1.49c.3-.496.5-.993.6-1.39l1.5-.3zm-8 1.492c-1.7 0-3-1.292-3-2.982 0-1.69 1.3-2.98 3-2.98s3 1.29 3 2.98-1.3 2.982-3 2.982z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced.png
new file mode 100644
index 00000000..32892a59
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced.svg
new file mode 100644
index 00000000..95d72f97
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/advanced.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 13.44v-2.88l-1.8-.3c-.1-.397-.3-.794-.6-1.39l1.1-1.49-2.1-2.088-1.5 1.093c-.5-.298-1-.497-1.4-.596L13.5 4h-2.9l-.3 1.79c-.5.098-.9.297-1.4.595L7.4 5.292 5.3 7.38l1 1.49c-.3.496-.4.894-.6 1.39l-1.7.2v2.882l1.8.298c.1.497.3.894.6 1.39l-1 1.492 2.1 2.087 1.5-1c.4.2.9.395 1.4.594l.3 1.79h3l.3-1.79c.5-.1.9-.298 1.4-.596l1.5 1.092 2.1-2.08-1.1-1.49c.3-.496.5-.993.6-1.39l1.5-.3zm-8 1.492c-1.7 0-3-1.292-3-2.982 0-1.69 1.3-2.98 3-2.98s3 1.29 3 2.98-1.3 2.982-3 2.982z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-invert.png
new file mode 100644
index 00000000..2a66b030
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-invert.svg
new file mode 100644
index 00000000..74bb91dd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-invert.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="alert">
+ <path id="point" d="M11 16h2v2h-2z"/>
+ <path id="stroke" d="M13.516 10h-3L11 15h2z"/>
+ <path id="triangle" d="M12.017 5.974L19.537 19H4.497l7.52-13.026m0-2.474c-.545 0-1.09.357-1.5 1.07L2.53 18.403C1.705 19.833 2.38 21 4.03 21H20c1.65 0 2.325-1.17 1.5-2.6L13.517 4.575c-.413-.715-.956-1.072-1.5-1.072z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-warning.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-warning.png
new file mode 100644
index 00000000..6276502c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-warning.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-warning.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-warning.svg
new file mode 100644
index 00000000..c5c56877
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert-warning.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ff5d00 }</style>
+ <g id="alert">
+ <path id="point" d="M11 16h2v2h-2z"/>
+ <path id="stroke" d="M13.516 10h-3L11 15h2z"/>
+ <path id="triangle" d="M12.017 5.974L19.537 19H4.497l7.52-13.026m0-2.474c-.545 0-1.09.357-1.5 1.07L2.53 18.403C1.705 19.833 2.38 21 4.03 21H20c1.65 0 2.325-1.17 1.5-2.6L13.517 4.575c-.413-.715-.956-1.072-1.5-1.072z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert.png
new file mode 100644
index 00000000..73550841
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert.svg
new file mode 100644
index 00000000..8b601d5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/alert.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="alert">
+ <path id="point" d="M11 16h2v2h-2z"/>
+ <path id="stroke" d="M13.516 10h-3L11 15h2z"/>
+ <path id="triangle" d="M12.017 5.974L19.537 19H4.497l7.52-13.026m0-2.474c-.545 0-1.09.357-1.5 1.07L2.53 18.403C1.705 19.833 2.38 21 4.03 21H20c1.65 0 2.325-1.17 1.5-2.6L13.517 4.575c-.413-.715-.956-1.072-1.5-1.072z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center-invert.png
new file mode 100644
index 00000000..0343b3f1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center-invert.svg
new file mode 100644
index 00000000..197e0379
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M9 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H9c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm-5.5 9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0-12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-center"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center.png
new file mode 100644
index 00000000..a912b033
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center.svg
new file mode 100644
index 00000000..6f479773
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-center.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H9c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm-5.5 9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0-12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-center"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left-invert.png
new file mode 100644
index 00000000..6d3d3757
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left-invert.svg
new file mode 100644
index 00000000..663ba94f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M4 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H4c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm9.5 0h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm-10-9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0 12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-float-left"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left.png
new file mode 100644
index 00000000..e3950369
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left.svg
new file mode 100644
index 00000000..a577600d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-left.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H4c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm9.5 0h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm-10-9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0 12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-float-left"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right-invert.png
new file mode 100644
index 00000000..655d7ccd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right-invert.svg
new file mode 100644
index 00000000..41be0691
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M20 9h-6c-.554 0-1 .446-1 1v5c0 .554.446 1 1 1h6c.554 0 1-.446 1-1v-5c0-.554-.446-1-1-1zm-9.5 0h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm10-9h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1zm0 12h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1z" id="align-float-right"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right.png
new file mode 100644
index 00000000..c72a9560
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right.svg
new file mode 100644
index 00000000..0f46bc1f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/align-float-right.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 9h-6c-.554 0-1 .446-1 1v5c0 .554.446 1 1 1h6c.554 0 1-.446 1-1v-5c0-.554-.446-1-1-1zm-9.5 0h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm10-9h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1zm0 12h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1z" id="align-float-right"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr-invert.png
new file mode 100644
index 00000000..d8d64f1a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr-invert.svg
new file mode 100644
index 00000000..3dc51251
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M13.3 6.3l6.3 5.7-6.3 5.7v-3.8H12c-3.2 0-6.3 1.3-7.6 3.8 0-4.7 2.8-7.6 7.9-7.6h.9V6.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr.png
new file mode 100644
index 00000000..c2fae72d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr.svg
new file mode 100644
index 00000000..c2291200
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M13.3 6.3l6.3 5.7-6.3 5.7v-3.8H12c-3.2 0-6.3 1.3-7.6 3.8 0-4.7 2.8-7.6 7.9-7.6h.9V6.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl-invert.png
new file mode 100644
index 00000000..21fa9abb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl-invert.svg
new file mode 100644
index 00000000..0e2c2f3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M10.7 6.3L4.4 12l6.3 5.7v-3.8H12c3.2 0 6.3 1.3 7.6 3.8 0-4.7-2.8-7.6-7.9-7.6h-.9V6.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl.png
new file mode 100644
index 00000000..df22b7de
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl.svg
new file mode 100644
index 00000000..9f4bd135
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arched-arrow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10.7 6.3L4.4 12l6.3 5.7v-3.8H12c3.2 0 6.3 1.3 7.6 3.8 0-4.7-2.8-7.6-7.9-7.6h-.9V6.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr-invert.png
new file mode 100644
index 00000000..6299e866
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr-invert.svg
new file mode 100644
index 00000000..3c5c48bf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M16 12H6c-1.7 0-3 1.3-3 3h13v3l5-4.5L16 9v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr.png
new file mode 100644
index 00000000..24905bc4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr.svg
new file mode 100644
index 00000000..b4c0e0d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 12H6c-1.7 0-3 1.3-3 3h13v3l5-4.5L16 9v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl-invert.png
new file mode 100644
index 00000000..fb375e48
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl-invert.svg
new file mode 100644
index 00000000..da0c6ece
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M8 12h10c1.7 0 3 1.3 3 3H8v3l-5-4.5L8 9v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl.png
new file mode 100644
index 00000000..1cd81cbb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl.svg
new file mode 100644
index 00000000..1087ff94
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/arrow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 12h10c1.7 0 3 1.3 3 3H8v3l-5-4.5L8 9v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr-invert.png
new file mode 100644
index 00000000..8c264dd9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr-invert.svg
new file mode 100644
index 00000000..80e7992d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 10h4V5h-4v5zm-5 2h9v-1H7v1zm0 2h9v-1H7v1zm0 2h9v-1H7v1zm4-9H7v1h4V7zm0 2H7v1h4V9zm0-4H7v1h4V5zM5 3h13v16H8c-1.7 0-3-1.3-3-3V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr.png
new file mode 100644
index 00000000..cf7de13a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr.svg
new file mode 100644
index 00000000..862bc2b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 10h4V5h-4v5zm-5 2h9v-1H7v1zm0 2h9v-1H7v1zm0 2h9v-1H7v1zm4-9H7v1h4V7zm0 2H7v1h4V9zm0-4H7v1h4V5zM5 3h13v16H8c-1.7 0-3-1.3-3-3V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl-invert.png
new file mode 100644
index 00000000..ab207181
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl-invert.svg
new file mode 100644
index 00000000..f0a4a6aa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M11 10H7V5h4v5zm5 2H7v-1h9v1zm0 2H7v-1h9v1zm0 2H7v-1h9v1zm-4-9h4v1h-4V7zm0 2h4v1h-4V9zm0-4h4v1h-4V5zm6-2H5v16h10c1.7 0 3-1.3 3-3V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl.png
new file mode 100644
index 00000000..d0b0e70d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl.svg
new file mode 100644
index 00000000..3b16dcbc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/article-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 10H7V5h4v5zm5 2H7v-1h9v1zm0 2H7v-1h9v1zm0 2H7v-1h9v1zm-4-9h4v1h-4V7zm0 2h4v1h-4V9zm0-4h4v1h-4V5zm6-2H5v16h10c1.7 0 3-1.3 3-3V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr-invert.png
new file mode 100644
index 00000000..5eed7170
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr-invert.svg
new file mode 100644
index 00000000..77febef3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M21 11l-6 7-4-4-1 1 5 5 7-8z"/>
+ <path d="M17 14V3H4v13c0 1.7 1.3 3 3 3h5l-3-3H6v-1h2.6l1-1H6v-1h9v1h-2l1 1h2l1-1zM6 5h4v1H6V5zm0 2h4v1H6V7zm0 2h4v1H6V9zm9 3H6v-1h9v1zm-4-2V5h4v5h-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr.png
new file mode 100644
index 00000000..5b169e27
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr.svg
new file mode 100644
index 00000000..396e6a1e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 11l-6 7-4-4-1 1 5 5 7-8z"/>
+ <path d="M17 14V3H4v13c0 1.7 1.3 3 3 3h5l-3-3H6v-1h2.6l1-1H6v-1h9v1h-2l1 1h2l1-1zM6 5h4v1H6V5zm0 2h4v1H6V7zm0 2h4v1H6V9zm9 3H6v-1h9v1zm-4-2V5h4v5h-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl-invert.png
new file mode 100644
index 00000000..cc9c9dee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl-invert.svg
new file mode 100644
index 00000000..c80c83f4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M5 11l6 7 4-4 1 1-5 5-7-8z"/>
+ <path d="M9 14V3h13v13c0 1.7-1.3 3-3 3h-5l3-3h3v-1h-2.6l-1-1H20v-1h-9v1h2l-1 1h-2l-1-1zm11-9h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm-9 3h9v-1h-9v1zm4-2V5h-4v5h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl.png
new file mode 100644
index 00000000..9f22672a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl.svg
new file mode 100644
index 00000000..604143bb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleCheck-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 11l6 7 4-4 1 1-5 5-7-8z"/>
+ <path d="M9 14V3h13v13c0 1.7-1.3 3-3 3h-5l3-3h3v-1h-2.6l-1-1H20v-1h-9v1h2l-1 1h-2l-1-1zm11-9h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm-9 3h9v-1h-9v1zm4-2V5h-4v5h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr-invert.png
new file mode 100644
index 00000000..76cc11ff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr-invert.svg
new file mode 100644
index 00000000..0ed1d316
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="article-redirect">
+ <path id="arrow" d="M18.1 14.2L23 18l-4.9 4.8v-2.2c-1.7 0-2.9-.2-4.3-1.2-1.2-.8-2.5-2.6-2.3-4.1 1.4 1 2.9 1.5 4.4 1.5.7 0 1.4-.1 2.1-.3l.1-2.3"/>
+ <path id="page" d="M5 3v13c0 1.7 1.3 3 3 3h3.375c-.157-.205-.3-.43-.438-.656-.42-.688-.77-1.483-.843-2.344H7v-1h3.125l.125-1H7v-1h3.375l.03-.188.283.188H16v1h-3.906l.22.156c.523.375 1.065.64 1.592.844H16v.406c.208-.013.418-.07.625-.094.068-1.294.125-3.874.125-3.874l1.25.968V3H5zm2 2h4v1H7V5zm5 0h4v5h-4V5zM7 7h4v1H7V7zm0 2h4v1H7V9zm0 2h9v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr.png
new file mode 100644
index 00000000..3dbe20ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr.svg
new file mode 100644
index 00000000..028c64c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="article-redirect">
+ <path id="arrow" d="M18.1 14.2L23 18l-4.9 4.8v-2.2c-1.7 0-2.9-.2-4.3-1.2-1.2-.8-2.5-2.6-2.3-4.1 1.4 1 2.9 1.5 4.4 1.5.7 0 1.4-.1 2.1-.3l.1-2.3"/>
+ <path id="page" d="M5 3v13c0 1.7 1.3 3 3 3h3.375c-.157-.205-.3-.43-.438-.656-.42-.688-.77-1.483-.843-2.344H7v-1h3.125l.125-1H7v-1h3.375l.03-.188.283.188H16v1h-3.906l.22.156c.523.375 1.065.64 1.592.844H16v.406c.208-.013.418-.07.625-.094.068-1.294.125-3.874.125-3.874l1.25.968V3H5zm2 2h4v1H7V5zm5 0h4v5h-4V5zM7 7h4v1H7V7zm0 2h4v1H7V9zm0 2h9v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl-invert.png
new file mode 100644
index 00000000..b31e0f97
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl-invert.svg
new file mode 100644
index 00000000..1a5b22a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="article-redirect">
+ <path id="arrow" d="M5.9 14.2L1 18l4.9 4.8v-2.2c1.7 0 2.9-.2 4.3-1.2 1.2-.8 2.5-2.6 2.3-4.1-1.4 1-2.9 1.5-4.4 1.5-.7 0-1.4-.1-2.1-.3l-.1-2.3"/>
+ <path id="page" d="M19 3v13c0 1.7-1.3 3-3 3h-3.375c.157-.205.3-.43.438-.656.42-.688.77-1.483.843-2.344H17v-1h-3.125l-.125-1H17v-1h-3.375l-.03-.188-.283.188H8v1h3.906l-.22.156a7.097 7.097 0 0 1-1.592.844H8v.406c-.208-.013-.418-.07-.625-.094a178.903 178.903 0 0 1-.125-3.874L6 12.405V3zm-2 2h-4v1h4zm-5 0H8v5h4zm5 2h-4v1h4zm0 2h-4v1h4zm0 2H8v1h9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl.png
new file mode 100644
index 00000000..60beb6ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl.svg
new file mode 100644
index 00000000..316d36ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleRedirect-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="article-redirect">
+ <path id="arrow" d="M5.9 14.2L1 18l4.9 4.8v-2.2c1.7 0 2.9-.2 4.3-1.2 1.2-.8 2.5-2.6 2.3-4.1-1.4 1-2.9 1.5-4.4 1.5-.7 0-1.4-.1-2.1-.3l-.1-2.3"/>
+ <path id="page" d="M19 3v13c0 1.7-1.3 3-3 3h-3.375c.157-.205.3-.43.438-.656.42-.688.77-1.483.843-2.344H17v-1h-3.125l-.125-1H17v-1h-3.375l-.03-.188-.283.188H8v1h3.906l-.22.156a7.097 7.097 0 0 1-1.592.844H8v.406c-.208-.013-.418-.07-.625-.094a178.903 178.903 0 0 1-.125-3.874L6 12.405V3zm-2 2h-4v1h4zm-5 0H8v5h4zm5 2h-4v1h4zm0 2h-4v1h4zm0 2H8v1h9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr-invert.png
new file mode 100644
index 00000000..1bd1587b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr-invert.svg
new file mode 100644
index 00000000..de091d90
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M19.1 18.5c.6-.7.9-1.5.9-2.5 0-2.2-1.8-4-4-4s-4 1.8-4 4 1.8 4 4 4c.7 0 1.3-.1 1.8-.4l2.7 2.7 1.1-1.1-2.5-2.7zm-3.1-.3c-1.2 0-2.2-1-2.2-2.3 0-1.2 1-2.2 2.2-2.2 1.2 0 2.3 1 2.3 2.2-.1 1.3-1.1 2.3-2.3 2.3zM11.8 13c.3-.4.6-.7 1-1H7v-1h9s1.2 0 2 .6V3H5v13c0 1.7 1.3 3 3 3h3.8c-.6-.8-1-1.9-1-3H7v-1h3.9l.3-1H7v-1h4.8zm.2-8h4v5h-4V5zM7 5h4v1H7V5zm0 2h4v1H7V7zm0 2h4v1H7V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr.png
new file mode 100644
index 00000000..1802dfc7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr.svg
new file mode 100644
index 00000000..ac41c2b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19.1 18.5c.6-.7.9-1.5.9-2.5 0-2.2-1.8-4-4-4s-4 1.8-4 4 1.8 4 4 4c.7 0 1.3-.1 1.8-.4l2.7 2.7 1.1-1.1-2.5-2.7zm-3.1-.3c-1.2 0-2.2-1-2.2-2.3 0-1.2 1-2.2 2.2-2.2 1.2 0 2.3 1 2.3 2.2-.1 1.3-1.1 2.3-2.3 2.3zM11.8 13c.3-.4.6-.7 1-1H7v-1h9s1.2 0 2 .6V3H5v13c0 1.7 1.3 3 3 3h3.8c-.6-.8-1-1.9-1-3H7v-1h3.9l.3-1H7v-1h4.8zm.2-8h4v5h-4V5zM7 5h4v1H7V5zm0 2h4v1H7V7zm0 2h4v1H7V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl-invert.png
new file mode 100644
index 00000000..a8e8a3aa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl-invert.svg
new file mode 100644
index 00000000..abb7ce72
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M7.5 18.5c-.6-.7-.9-1.5-.9-2.5 0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4c-.7 0-1.3-.1-1.8-.4l-2.7 2.7L5 21.2l2.5-2.7zm3.1-.3c1.2 0 2.2-1 2.2-2.3 0-1.2-1-2.2-2.2-2.2-1.2 0-2.3 1-2.3 2.2.1 1.3 1.1 2.3 2.3 2.3zm4.2-5.2c-.3-.4-.6-.7-1-1h5.8v-1h-9s-1.2 0-2 .6V3h13v13c0 1.7-1.3 3-3 3h-3.8c.6-.8 1-1.9 1-3h3.8v-1h-3.9l-.3-1h4.2v-1h-4.8zm-.2-8h-4v5h4V5zm5 0h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl.png
new file mode 100644
index 00000000..a2611daf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl.svg
new file mode 100644
index 00000000..ed43acf5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articleSearch-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7.5 18.5c-.6-.7-.9-1.5-.9-2.5 0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4c-.7 0-1.3-.1-1.8-.4l-2.7 2.7L5 21.2l2.5-2.7zm3.1-.3c1.2 0 2.2-1 2.2-2.3 0-1.2-1-2.2-2.2-2.2-1.2 0-2.3 1-2.3 2.2.1 1.3 1.1 2.3 2.3 2.3zm4.2-5.2c-.3-.4-.6-.7-1-1h5.8v-1h-9s-1.2 0-2 .6V3h13v13c0 1.7-1.3 3-3 3h-3.8c.6-.8 1-1.9 1-3h3.8v-1h-3.9l-.3-1h4.2v-1h-4.8zm-.2-8h-4v5h4V5zm5 0h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.png
new file mode 100644
index 00000000..edfe4064
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.svg
new file mode 100644
index 00000000..83979627
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M11 12h4V7h-4v5zm-5 2h9v-1H6v1zm0 2h9v-1H6v1zm0 2h9v-1H6v1zm4-9H6v1h4V9zm0 2H6v1h4v-1zm0-4H6v1h4V7zM4 5h13v16H7c-1.7 0-3-1.3-3-3V5z"/>
+ <path d="M18 4v14h2V2H7v2" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.png
new file mode 100644
index 00000000..7dc69876
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.svg
new file mode 100644
index 00000000..9dd3404f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 12h4V7h-4v5zm-5 2h9v-1H6v1zm0 2h9v-1H6v1zm0 2h9v-1H6v1zm4-9H6v1h4V9zm0 2H6v1h4v-1zm0-4H6v1h4V7zM4 5h13v16H7c-1.7 0-3-1.3-3-3V5z"/>
+ <path d="M18 4v14h2V2H7v2" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.png
new file mode 100644
index 00000000..153d5348
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.svg
new file mode 100644
index 00000000..12432a28
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M13 12H9V7h4v5zm5 2H9v-1h9v1zm0 2H9v-1h9v1zm0 2H9v-1h9v1zm-4-9h4v1h-4V9zm0 2h4v1h-4v-1zm0-4h4v1h-4V7zm6-2H7v16h10c1.7 0 3-1.3 3-3V5z"/>
+ <path d="M6 4v14H4V2h13v2" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.png
new file mode 100644
index 00000000..9a7ce13f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.svg
new file mode 100644
index 00000000..b57dae25
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/articles-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M13 12H9V7h4v5zm5 2H9v-1h9v1zm0 2H9v-1h9v1zm0 2H9v-1h9v1zm-4-9h4v1h-4V9zm0 2h4v1h-4v-1zm0-4h4v1h-4V7zm6-2H7v16h10c1.7 0 3-1.3 3-3V5z"/>
+ <path d="M6 4v14H4V2h13v2" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr-invert.png
new file mode 100644
index 00000000..aa1b38e7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr-invert.svg
new file mode 100644
index 00000000..67c3ae91
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-293 385 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M-274.3 390.9c-1.6-1.6-4.3-1.5-5.8.1l.2.2c.5.5 1.3.7 2.1.4.8-.3 1.7-.1 2.4.6 1 .9.9 2.4 0 3.4l-7.1 7.1c-.9 1-2.4.9-3.4 0s-.9-2.4 0-3.4l4.4-4.4c.3-.3.9-.5 1.3-.1s.2 1-.1 1.3l-3.4 3.4c-.6.6-.6 1.7.1 2.3l4.3-4.3c.8-.8 1.1-1.8.9-2.7-.2-.9-.9-1.6-1.7-1.9-.9-.2-1.9 0-2.6.7l-4.4 4.4c-1.6 1.6-1.6 4.3.1 5.8 1.5 1.6 4.3 1.5 5.8-.1l7-7c.8-.8 1.2-1.9 1.2-3s-.5-2.1-1.3-2.8c-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-1.5-1.6.8.7 0 0z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr.png
new file mode 100644
index 00000000..92dfaf21
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr.svg
new file mode 100644
index 00000000..74a4d646
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-293 385 24 24">
+ <path d="M-274.3 390.9c-1.6-1.6-4.3-1.5-5.8.1l.2.2c.5.5 1.3.7 2.1.4.8-.3 1.7-.1 2.4.6 1 .9.9 2.4 0 3.4l-7.1 7.1c-.9 1-2.4.9-3.4 0s-.9-2.4 0-3.4l4.4-4.4c.3-.3.9-.5 1.3-.1s.2 1-.1 1.3l-3.4 3.4c-.6.6-.6 1.7.1 2.3l4.3-4.3c.8-.8 1.1-1.8.9-2.7-.2-.9-.9-1.6-1.7-1.9-.9-.2-1.9 0-2.6.7l-4.4 4.4c-1.6 1.6-1.6 4.3.1 5.8 1.5 1.6 4.3 1.5 5.8-.1l7-7c.8-.8 1.2-1.9 1.2-3s-.5-2.1-1.3-2.8c-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-1.5-1.6.8.7 0 0z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl-invert.png
new file mode 100644
index 00000000..bba8db56
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl-invert.svg
new file mode 100644
index 00000000..61e11d09
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-119 70 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M-113.3 75.6c-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7-1.3 1.7-1.3 2.8 0 1.1.4 2.2 1.2 3l7 7c1.5 1.6 4.3 1.7 5.8.1 1.7-1.5 1.7-4.2.1-5.8l-4.4-4.4c-.7-.7-1.7-.9-2.6-.7-.8.3-1.5 1-1.7 1.9-.2.9.1 1.9.9 2.7l4.3 4.3c.7-.6.7-1.7.1-2.3l-3.4-3.4c-.3-.3-.5-.9-.1-1.3s1-.2 1.3.1l4.4 4.4c.9 1 1 2.5 0 3.4s-2.5 1-3.4 0l-7.1-7.1c-.9-1-1-2.5 0-3.4.7-.7 1.6-.9 2.4-.6.8.3 1.6.1 2.1-.4l.2-.2c-1.5-1.6-4.2-1.8-5.8-.1-.8.7 1.5-1.7 0 0z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl.png
new file mode 100644
index 00000000..f793246d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl.svg
new file mode 100644
index 00000000..f53f5a47
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/attachment-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-119 70 24 24">
+ <path d="M-113.3 75.6c-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7-1.3 1.7-1.3 2.8 0 1.1.4 2.2 1.2 3l7 7c1.5 1.6 4.3 1.7 5.8.1 1.7-1.5 1.7-4.2.1-5.8l-4.4-4.4c-.7-.7-1.7-.9-2.6-.7-.8.3-1.5 1-1.7 1.9-.2.9.1 1.9.9 2.7l4.3 4.3c.7-.6.7-1.7.1-2.3l-3.4-3.4c-.3-.3-.5-.9-.1-1.3s1-.2 1.3.1l4.4 4.4c.9 1 1 2.5 0 3.4s-2.5 1-3.4 0l-7.1-7.1c-.9-1-1-2.5 0-3.4.7-.7 1.6-.9 2.4-.6.8.3 1.6.1 2.1-.4l.2-.2c-1.5-1.6-4.2-1.8-5.8-.1-.8.7 1.5-1.7 0 0z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.png
new file mode 100644
index 00000000..2f0c960f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.svg
new file mode 100644
index 00000000..7ed36358
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M17.5 14V9c0-3-2.3-5-5.5-5S6.5 6 6.5 9v5c0 2 0 3-2 3v1h15v-1c-2 0-2-1-2-3zM12 20H9c0 1 1.6 2 3 2s3-1 3-2h-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.png
new file mode 100644
index 00000000..b86d5f79
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.svg
new file mode 100644
index 00000000..787ed141
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bell.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.5 14V9c0-3-2.3-5-5.5-5S6.5 6 6.5 9v5c0 2 0 3-2 3v1h15v-1c-2 0-2-1-2-3zM12 20H9c0 1 1.6 2 3 2s3-1 3-2h-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.png
new file mode 100644
index 00000000..1c0de727
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.svg
new file mode 100644
index 00000000..c032294c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M17.8 14.7l1.7-4.7c1-2.8-.5-5.5-3.5-6.6s-5.9 0-6.9 2.8l-1.7 4.7c-.7 1.9-1 2.8-2.9 2.1l-.3 1 14.1 5.1.3-.9c-1.9-.7-1.5-1.6-.8-3.5zM12 19.8l-2.8-1c-.3.9.8 2.4 2.1 2.9s3.2.1 3.5-.9l-2.8-1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.png
new file mode 100644
index 00000000..1f9ae71f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.svg
new file mode 100644
index 00000000..f68a8e0e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.8 14.7l1.7-4.7c1-2.8-.5-5.5-3.5-6.6s-5.9 0-6.9 2.8l-1.7 4.7c-.7 1.9-1 2.8-2.9 2.1l-.3 1 14.1 5.1.3-.9c-1.9-.7-1.5-1.6-.8-3.5zM12 19.8l-2.8-1c-.3.9.8 2.4 2.1 2.9s3.2.1 3.5-.9l-2.8-1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.png
new file mode 100644
index 00000000..c21e1c02
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.svg
new file mode 100644
index 00000000..34ec94b3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M6.21 14.7L4.51 10c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.png
new file mode 100644
index 00000000..81d9a0aa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.svg
new file mode 100644
index 00000000..92bcef54
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bellOn-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6.21 14.7L4.51 10c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta-invert.png
new file mode 100644
index 00000000..c3b26b85
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta-invert.svg
new file mode 100644
index 00000000..d4635774
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 12l-3-2-1 4-1-4-3 2 2-3-4-1 4-1-2-3 3 2 1-4 1 4 3-2-2 3 4 1-4 1 2 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta.png
new file mode 100644
index 00000000..7b31e1e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta.svg
new file mode 100644
index 00000000..51a5c782
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/beta.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 12l-3-2-1 4-1-4-3 2 2-3-4-1 4-1-2-3 3 2 1-4 1 4 3-2-2 3 4 1-4 1 2 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch-invert.png
new file mode 100644
index 00000000..09635383
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch-invert.svg
new file mode 100644
index 00000000..2b8ee7a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M15.3 14.7C16.1 10.9 14.7 4 12 4c-2.7 0-4.2 6.7-3.4 10.5L7 18h2.7l.3 1h4c.2-.3.1-.5.3-1H17l-1.7-3.3zM12 10c-.8 0-1.5-.7-1.5-1.5S11.2 7 12 7s1.5.7 1.5 1.5S12.8 10 12 10zm2 10c0 1.1-2 2-2 2s-2-.9-2-2"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch.png
new file mode 100644
index 00000000..6d3c067c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch.svg
new file mode 100644
index 00000000..c3f99d6a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/betaLaunch.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15.3 14.7C16.1 10.9 14.7 4 12 4c-2.7 0-4.2 6.7-3.4 10.5L7 18h2.7l.3 1h4c.2-.3.1-.5.3-1H17l-1.7-3.3zM12 10c-.8 0-1.5-.7-1.5-1.5S11.2 7 12 7s1.5.7 1.5 1.5S12.8 10 12 10zm2 10c0 1.1-2 2-2 2s-2-.9-2-2"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr-invert.png
new file mode 100644
index 00000000..97f77f48
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr-invert.svg
new file mode 100644
index 00000000..41d644a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z" id="a"/>
+ <g id="up">
+ <path id="arrow" d="M15.5 9h7L19 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr.png
new file mode 100644
index 00000000..82fbd14d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr.svg
new file mode 100644
index 00000000..6d95fc66
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z" id="a"/>
+ <g id="up">
+ <path id="arrow" d="M15.5 9h7L19 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl-invert.png
new file mode 100644
index 00000000..628de3db
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl-invert.svg
new file mode 100644
index 00000000..4101ddfc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z" id="a"/>
+ <g id="up">
+ <path id="arrow" d="M1.5 9h7L5 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl.png
new file mode 100644
index 00000000..64d1cf1d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl.svg
new file mode 100644
index 00000000..807cdd91
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bigger-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z" id="a"/>
+ <g id="up">
+ <path id="arrow" d="M1.5 9h7L5 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.png
new file mode 100644
index 00000000..31f14c56
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.svg
new file mode 100644
index 00000000..2cf60bcd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d11d13 }</style>
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm5 9H7v-2h10v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-invert.png
new file mode 100644
index 00000000..ca81ab7f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-invert.svg
new file mode 100644
index 00000000..a2f916e3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm5 9H7v-2h10v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block.png
new file mode 100644
index 00000000..7f8eb2a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block.svg
new file mode 100644
index 00000000..b50bb618
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/block.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm5 9H7v-2h10v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr-invert.png
new file mode 100644
index 00000000..7426f564
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr-invert.svg
new file mode 100644
index 00000000..1d41a44d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M17 11v2h-2l3.6 3.6c.9-1.3 1.4-2.9 1.4-4.6 0-4.4-3.6-8-8-8-1.7 0-3.3.5-4.6 1.4L13 11h4zM4 4L3 5l2.4 2.4C4.5 8.7 4 10.3 4 12c0 4.4 3.6 8 8 8 1.7 0 3.3-.5 4.6-1.4L19 21l1-1L4 4zm3 9v-2h2l2 2H7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr.png
new file mode 100644
index 00000000..640bb2a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr.svg
new file mode 100644
index 00000000..160219c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 11v2h-2l3.6 3.6c.9-1.3 1.4-2.9 1.4-4.6 0-4.4-3.6-8-8-8-1.7 0-3.3.5-4.6 1.4L13 11h4zM4 4L3 5l2.4 2.4C4.5 8.7 4 10.3 4 12c0 4.4 3.6 8 8 8 1.7 0 3.3-.5 4.6-1.4L19 21l1-1L4 4zm3 9v-2h2l2 2H7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl-invert.png
new file mode 100644
index 00000000..a02e2e0d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl-invert.svg
new file mode 100644
index 00000000..ca592ede
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M7 11v2h2l-3.6 3.6C4.5 15.3 4 13.7 4 12c0-4.4 3.6-8 8-8 1.7 0 3.3.5 4.6 1.4L11 11H7zm13-7l1 1-2.4 2.4c.9 1.3 1.4 2.9 1.4 4.6 0 4.4-3.6 8-8 8-1.7 0-3.3-.5-4.6-1.4L5 21l-1-1L20 4zm-3 9v-2h-2l-2 2h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl.png
new file mode 100644
index 00000000..2475b061
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl.svg
new file mode 100644
index 00000000..90fe46ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/blockUndo-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 11v2h2l-3.6 3.6C4.5 15.3 4 13.7 4 12c0-4.4 3.6-8 8-8 1.7 0 3.3.5 4.6 1.4L11 11H7zm13-7l1 1-2.4 2.4c.9 1.3 1.4 2.9 1.4 4.6 0 4.4-3.6 8-8 8-1.7 0-3.3-.5-4.6-1.4L5 21l-1-1L20 4zm-3 9v-2h-2l-2 2h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a-invert.png
new file mode 100644
index 00000000..8c11dadc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a-invert.svg
new file mode 100644
index 00000000..519f850d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M16 18h3L14 6h-3L6 18h3l1.25-3h4.5L16 18zm-4.917-5L12.5 9.6l1.417 3.4h-2.834z" id="bold-a"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a.png
new file mode 100644
index 00000000..2907677f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a.svg
new file mode 100644
index 00000000..ce9f4f84
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-a.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 18h3L14 6h-3L6 18h3l1.25-3h4.5L16 18zm-4.917-5L12.5 9.6l1.417 3.4h-2.834z" id="bold-a"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain-invert.png
new file mode 100644
index 00000000..eac1ac74
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain-invert.svg
new file mode 100644
index 00000000..e43c4b5f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-arab-ain">
+ <path id="arab-ain" d="M9.337 13.616c0 1.35 1.386 2.1 4.16 2.258l2.186-.03.318.045c-.03.12-.25.34-.66.65l-.09.06c-1.233.93-2.42 1.394-3.56 1.394-1.14 0-2.043-.33-2.71-.99-.65-.66-.973-1.56-.973-2.7.006-1.353.567-2.572 1.685-3.657v-.044l-.606-.55a.952.952 0 0 1-.222-.63c0-.49.24-1.11.72-1.863.65-1.045 1.302-1.565 1.957-1.56.886.005 1.618.42 2.194 1.246.325.48-.03.55-1.064.22-.843-.33-1.528-.05-2.055.826l.016.074 1.125.866.05.005c1.405-.497 2.42-.74 3.044-.725-.06.116-.14.36-.244.732a27.75 27.75 0 0 1-.304.982l-.125.372-.386.05c-1.743.24-2.992.716-3.745 1.43-.465.463-.7.972-.704 1.524"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain.png
new file mode 100644
index 00000000..931b6cfd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain.svg
new file mode 100644
index 00000000..452c3d0c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-ain.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-arab-ain">
+ <path id="arab-ain" d="M9.337 13.616c0 1.35 1.386 2.1 4.16 2.258l2.186-.03.318.045c-.03.12-.25.34-.66.65l-.09.06c-1.233.93-2.42 1.394-3.56 1.394-1.14 0-2.043-.33-2.71-.99-.65-.66-.973-1.56-.973-2.7.006-1.353.567-2.572 1.685-3.657v-.044l-.606-.55a.952.952 0 0 1-.222-.63c0-.49.24-1.11.72-1.863.65-1.045 1.302-1.565 1.957-1.56.886.005 1.618.42 2.194 1.246.325.48-.03.55-1.064.22-.843-.33-1.528-.05-2.055.826l.016.074 1.125.866.05.005c1.405-.497 2.42-.74 3.044-.725-.06.116-.14.36-.244.732a27.75 27.75 0 0 1-.304.982l-.125.372-.386.05c-1.743.24-2.992.716-3.745 1.43-.465.463-.7.972-.704 1.524"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad-invert.png
new file mode 100644
index 00000000..0973b1f4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad-invert.svg
new file mode 100644
index 00000000..7f24cbc2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-arab-dad">
+ <path id="arab-dad" d="M16.41 8.232l-1.675-.665L15.43 6l1.687.64-.707 1.592m.775 3.078c-.51-.286-1-.427-1.476-.423-.478 0-.99.205-1.54.616l-.505.38.006.024c1.085.066 1.935.1 2.55.1h.315c.57-.022.994-.065 1.278-.132-.067-.17-.275-.36-.625-.566h-.006M10.38 14.6c-.016-.905-.33-1.87-.937-2.9l1.294-1.73.118.15c.267.337.504.925.713 1.767l.064.05c.496-.007.942-.17 1.338-.484v-.006l1.732-1.53c.68-.6 1.282-.9 1.807-.9.383.003.85.194 1.394.57.55.378.884.697 1 .96.063.15.094.385.094.71 0 .694-.11 1.227-.33 1.596-.193.31-.474.555-.845.734-.438.208-1.55.312-3.333.312-.8 0-1.794-.02-2.982-.064l-.142.43c-.254.67-.463 1.112-.625 1.323-.724.937-1.785 1.405-3.182 1.405-1.71-.006-2.56-.92-2.56-2.74.003-.94.278-1.814.824-2.618.15-.216.298-.367.444-.454.225-.133.288-.09.188.124-.396.862-.596 1.548-.6 2.058.008 1.177.752 1.768 2.232 1.772 1.038-.004 1.803-.182 2.295-.535"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad.png
new file mode 100644
index 00000000..11212576
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad.svg
new file mode 100644
index 00000000..b90bb77a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-arab-dad.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-arab-dad">
+ <path id="arab-dad" d="M16.41 8.232l-1.675-.665L15.43 6l1.687.64-.707 1.592m.775 3.078c-.51-.286-1-.427-1.476-.423-.478 0-.99.205-1.54.616l-.505.38.006.024c1.085.066 1.935.1 2.55.1h.315c.57-.022.994-.065 1.278-.132-.067-.17-.275-.36-.625-.566h-.006M10.38 14.6c-.016-.905-.33-1.87-.937-2.9l1.294-1.73.118.15c.267.337.504.925.713 1.767l.064.05c.496-.007.942-.17 1.338-.484v-.006l1.732-1.53c.68-.6 1.282-.9 1.807-.9.383.003.85.194 1.394.57.55.378.884.697 1 .96.063.15.094.385.094.71 0 .694-.11 1.227-.33 1.596-.193.31-.474.555-.845.734-.438.208-1.55.312-3.333.312-.8 0-1.794-.02-2.982-.064l-.142.43c-.254.67-.463 1.112-.625 1.323-.724.937-1.785 1.405-3.182 1.405-1.71-.006-2.56-.92-2.56-2.74.003-.94.278-1.814.824-2.618.15-.216.298-.367.444-.454.225-.133.288-.09.188.124-.396.862-.596 1.548-.6 2.058.008 1.177.752 1.768 2.232 1.772 1.038-.004 1.803-.182 2.295-.535"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to-invert.png
new file mode 100644
index 00000000..2ae27c21
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to-invert.svg
new file mode 100644
index 00000000..3ad81f5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-armn-to">
+ <path id="armn-to" d="M13.86 16.257c.124 0 .254-.026.39-.078.135-.06.257-.15.367-.28a1.43 1.43 0 0 0 .273-.517c.073-.214.11-.48.11-.798V13h-1.14c-.14 0-.284.026-.43.078a.905.905 0 0 0-.383.258c-.11.125-.2.294-.274.508-.067.213-.1.487-.1.82 0 .34.035.47.108.695.08.21.18.39.29.53.12.13.25.23.39.29.14.05.276.07.406.07m-2.97-7.84a2.67 2.67 0 0 0-.975.45 2.1 2.1 0 0 0-.672.813c-.16.342-.242.78-.242 1.31V18H6v-7.188c0-.776.15-1.455.453-2.04a4.227 4.227 0 0 1 1.234-1.467c.52-.39 1.13-.685 1.83-.883a8.114 8.114 0 0 1 2.225-.297c.526 0 1.04.044 1.54.133.504.088.98.22 1.43.398.447.172.858.388 1.233.65.375.26.698.564.97.913.275.34.49.73.64 1.17.15.43.226 1.09.226 1.61h1.36v2.04h-1.36v1.6c0 .58-.102 1.09-.31 1.54-.21.44-.49.81-.844 1.11-.35.302-.834.53-1.297.687-.465.15-.954.226-1.47.226-.51 0-.997-.08-1.46-.235a3.46 3.46 0 0 1-1.22-.703 3.452 3.452 0 0 1-.836-1.174c-.203-.472-.304-1.027-.304-1.662s.1-1.18.32-1.64c.21-.46.49-.684.85-.976.35-.297.76-.513 1.22-.648.452-.14.93-.21 1.43-.21h1.13c-.01-.49-.04-1.044-.24-1.36a2.26 2.26 0 0 0-.77-.767 3.234 3.234 0 0 0-.986-.427c-.375-.09-.578-.094-1.1-.094-.52 0-.64.02-1.01.102z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to.png
new file mode 100644
index 00000000..6f6349b0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to.svg
new file mode 100644
index 00000000..c35979af
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-armn-to.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-armn-to">
+ <path id="armn-to" d="M13.86 16.257c.124 0 .254-.026.39-.078.135-.06.257-.15.367-.28a1.43 1.43 0 0 0 .273-.517c.073-.214.11-.48.11-.798V13h-1.14c-.14 0-.284.026-.43.078a.905.905 0 0 0-.383.258c-.11.125-.2.294-.274.508-.067.213-.1.487-.1.82 0 .34.035.47.108.695.08.21.18.39.29.53.12.13.25.23.39.29.14.05.276.07.406.07m-2.97-7.84a2.67 2.67 0 0 0-.975.45 2.1 2.1 0 0 0-.672.813c-.16.342-.242.78-.242 1.31V18H6v-7.188c0-.776.15-1.455.453-2.04a4.227 4.227 0 0 1 1.234-1.467c.52-.39 1.13-.685 1.83-.883a8.114 8.114 0 0 1 2.225-.297c.526 0 1.04.044 1.54.133.504.088.98.22 1.43.398.447.172.858.388 1.233.65.375.26.698.564.97.913.275.34.49.73.64 1.17.15.43.226 1.09.226 1.61h1.36v2.04h-1.36v1.6c0 .58-.102 1.09-.31 1.54-.21.44-.49.81-.844 1.11-.35.302-.834.53-1.297.687-.465.15-.954.226-1.47.226-.51 0-.997-.08-1.46-.235a3.46 3.46 0 0 1-1.22-.703 3.452 3.452 0 0 1-.836-1.174c-.203-.472-.304-1.027-.304-1.662s.1-1.18.32-1.64c.21-.46.49-.684.85-.976.35-.297.76-.513 1.22-.648.452-.14.93-.21 1.43-.21h1.13c-.01-.49-.04-1.044-.24-1.36a2.26 2.26 0 0 0-.77-.767 3.234 3.234 0 0 0-.986-.427c-.375-.09-.578-.094-1.1-.094-.52 0-.64.02-1.01.102z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b-invert.png
new file mode 100644
index 00000000..e242b55d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b-invert.svg
new file mode 100644
index 00000000..2ba09bc6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-b">
+ <path id="b" d="M7 18h6c2 0 4-1 4-3 0-1.064.01-1.975-1.99-3 2-.975 1.99-1.935 1.99-3 0-2-2-3-4-3H7v12zm7-8c0 1 0 1-2 1h-2V8h2c2 0 2 0 2 1v1zm-2 6h-2v-3h2c2 0 2 0 2 1v1s0 1-2 1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b.png
new file mode 100644
index 00000000..8d09636e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b.svg
new file mode 100644
index 00000000..1806709a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-b.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-b">
+ <path id="b" d="M7 18h6c2 0 4-1 4-3 0-1.064.01-1.975-1.99-3 2-.975 1.99-1.935 1.99-3 0-2-2-3-4-3H7v12zm7-8c0 1 0 1-2 1h-2V8h2c2 0 2 0 2 1v1zm-2 6h-2v-3h2c2 0 2 0 2 1v1s0 1-2 1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be-invert.png
new file mode 100644
index 00000000..c131903a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be-invert.svg
new file mode 100644
index 00000000..3a6ec975
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-cyrl-be">
+ <path id="cyrl-be" d="M7 6h9v2h-6v3h2.65c.892 0 1.632.11 2.22.327.587.218 1.087.622 1.5 1.21.42.59.63 1.188.63 1.98 0 .812-.21 1.397-.63 1.976-.418.578-.897.974-1.436 1.187-.533.213-1.295.32-2.286.32h-5.65m4.768-2c.75 0 1.28-.05 1.584-.12.305-.077.57-.247.792-.51.23-.26.343-.472.343-.854 0-.557-.2-.868-.596-1.12-.4-.255-1.07-.397-2.02-.397H10v3"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be.png
new file mode 100644
index 00000000..de9e9d1b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be.svg
new file mode 100644
index 00000000..9d84cb04
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-be.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-cyrl-be">
+ <path id="cyrl-be" d="M7 6h9v2h-6v3h2.65c.892 0 1.632.11 2.22.327.587.218 1.087.622 1.5 1.21.42.59.63 1.188.63 1.98 0 .812-.21 1.397-.63 1.976-.418.578-.897.974-1.436 1.187-.533.213-1.295.32-2.286.32h-5.65m4.768-2c.75 0 1.28-.05 1.584-.12.305-.077.57-.247.792-.51.23-.26.343-.472.343-.854 0-.557-.2-.868-.596-1.12-.4-.255-1.07-.397-2.02-.397H10v3"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te-invert.png
new file mode 100644
index 00000000..803d066a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te-invert.svg
new file mode 100644
index 00000000..490c6156
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-cyrl-te">
+ <path id="te" d="M11 18V8H7V6h11v2h-4v10"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te.png
new file mode 100644
index 00000000..281d7187
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te.svg
new file mode 100644
index 00000000..63aee3ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-te.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-cyrl-te">
+ <path id="te" d="M11 18V8H7V6h11v2h-4v10"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe-invert.png
new file mode 100644
index 00000000..080e7316
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe-invert.svg
new file mode 100644
index 00000000..91f80dc5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-cyrl-zhe">
+ <path id="cyrl-zhe" d="M13 6v5.154c.328-.033.537-.18.705-.447.168-.266.4-.873.698-1.82.39-1.242.79-2.034 1.197-2.375.403-.336 1.075-.504 2.014-.504L18 6v1.78l-.386-.008c-.4 0-.69.062-.878.187-.186.112-.337.3-.452.55-.115.25-.286.76-.512 1.533-.12.41-.25.755-.392 1.032-.137.275-.383.536-.738.78.44.156.8.465 1.084.926.288.455.603 1.103.944 1.943L18 18h-2.314l-1.17-3.08-.113-.253-.24-.56c-.247-.57-.45-.933-.61-1.09A.726.726 0 0 0 13 12.78V18h-2v-5.22c-.226 0-.382.077-.546.23-.164.15-.368.517-.612 1.097l-.246.56-.113.253L8.313 18H6l1.33-3.267c.327-.808.635-1.447.923-1.92.293-.476.663-.793 1.11-.95-.355-.244-.603-.5-.745-.772a6.357 6.357 0 0 1-.392-1.04c-.222-.76-.39-1.26-.505-1.52-.11-.25-.26-.44-.45-.57-.18-.12-.49-.18-.912-.18H6V6l.386.008c.953 0 1.63.17 2.034.512.4.347.79 1.136 1.177 2.366.3.954.534 1.564.698 1.83.168.26.377.405.705.438V6.002"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe.png
new file mode 100644
index 00000000..98387012
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe.svg
new file mode 100644
index 00000000..aab3f4c1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-cyrl-zhe.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-cyrl-zhe">
+ <path id="cyrl-zhe" d="M13 6v5.154c.328-.033.537-.18.705-.447.168-.266.4-.873.698-1.82.39-1.242.79-2.034 1.197-2.375.403-.336 1.075-.504 2.014-.504L18 6v1.78l-.386-.008c-.4 0-.69.062-.878.187-.186.112-.337.3-.452.55-.115.25-.286.76-.512 1.533-.12.41-.25.755-.392 1.032-.137.275-.383.536-.738.78.44.156.8.465 1.084.926.288.455.603 1.103.944 1.943L18 18h-2.314l-1.17-3.08-.113-.253-.24-.56c-.247-.57-.45-.933-.61-1.09A.726.726 0 0 0 13 12.78V18h-2v-5.22c-.226 0-.382.077-.546.23-.164.15-.368.517-.612 1.097l-.246.56-.113.253L8.313 18H6l1.33-3.267c.327-.808.635-1.447.923-1.92.293-.476.663-.793 1.11-.95-.355-.244-.603-.5-.745-.772a6.357 6.357 0 0 1-.392-1.04c-.222-.76-.39-1.26-.505-1.52-.11-.25-.26-.44-.45-.57-.18-.12-.49-.18-.912-.18H6V6l.386.008c.953 0 1.63.17 2.034.512.4.347.79 1.136 1.177 2.366.3.954.534 1.564.698 1.83.168.26.377.405.705.438V6.002"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f-invert.png
new file mode 100644
index 00000000..9281a0dc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f-invert.svg
new file mode 100644
index 00000000..1954e934
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-f">
+ <path id="f" d="M16 8V6H8v12h3v-5h4v-2h-4V8z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f.png
new file mode 100644
index 00000000..ad0d89b8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f.svg
new file mode 100644
index 00000000..89061f10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-f.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-f">
+ <path id="f" d="M16 8V6H8v12h3v-5h4v-2h-4V8z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g-invert.png
new file mode 100644
index 00000000..2f1b7ac2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g-invert.svg
new file mode 100644
index 00000000..03f95194
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-g">
+ <path id="g" d="M12 14v-2h5v4.203c-.497.475-1.22.894-2.166 1.26A7.994 7.994 0 0 1 11.97 18c-1.23 0-2.303-.253-3.217-.76a4.908 4.908 0 0 1-2.062-2.185A7.008 7.008 0 0 1 6 11.96c0-1.208.26-2.282.77-3.222.518-.94 1.27-1.66 2.26-2.16.754-.386 1.693-.58 2.816-.58 1.46 0 2.6.304 3.418.91.825.603 1.354 1.436 1.59 2.502l-2.36.435a2.433 2.433 0 0 0-.94-1.346c-.454-.34-1.022-.5-1.707-.5-1.038 0-1.864.32-2.48.97-.61.65-.914 1.61-.914 2.89 0 1.375.31 2.41.93 3.1.62.687 1.434 1.03 2.44 1.03.497 0 .995-.095 1.49-.285.505-.196 1.334-.57 1.69-.846v-.868"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g.png
new file mode 100644
index 00000000..55e766a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g.svg
new file mode 100644
index 00000000..3150d95c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-g.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-g">
+ <path id="g" d="M12 14v-2h5v4.203c-.497.475-1.22.894-2.166 1.26A7.994 7.994 0 0 1 11.97 18c-1.23 0-2.303-.253-3.217-.76a4.908 4.908 0 0 1-2.062-2.185A7.008 7.008 0 0 1 6 11.96c0-1.208.26-2.282.77-3.222.518-.94 1.27-1.66 2.26-2.16.754-.386 1.693-.58 2.816-.58 1.46 0 2.6.304 3.418.91.825.603 1.354 1.436 1.59 2.502l-2.36.435a2.433 2.433 0 0 0-.94-1.346c-.454-.34-1.022-.5-1.707-.5-1.038 0-1.864.32-2.48.97-.61.65-.914 1.61-.914 2.89 0 1.375.31 2.41.93 3.1.62.687 1.434 1.03 2.44 1.03.497 0 .995-.095 1.49-.285.505-.196 1.334-.57 1.69-.846v-.868"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man-invert.png
new file mode 100644
index 00000000..ef2da34f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man-invert.svg
new file mode 100644
index 00000000..290fd4c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-geor-man">
+ <path id="geor-man" d="M13.832 14.06c0-1.714-.394-2.572-1.182-2.572-.868 0-1.302.78-1.302 2.338-.01 1.624.42 2.436 1.295 2.436.793 0 1.19-.734 1.19-2.2m2.167 0C16 16.686 14.884 18 12.65 18 10.218 18 9 16.614 9 13.84c0-2.737 1.217-4.105 3.65-4.105.842 0 1.183.63 1.183.63v-1.58c0-.788-.45-1.183-1.347-1.183-.572 0-.858.374-.858 1.123h-2.34C9.29 6.908 10.35 6 12.462 6 14.83 6 16.01 6.946 16 8.84"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man.png
new file mode 100644
index 00000000..c0500747
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man.svg
new file mode 100644
index 00000000..deb95b70
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-geor-man.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-geor-man">
+ <path id="geor-man" d="M13.832 14.06c0-1.714-.394-2.572-1.182-2.572-.868 0-1.302.78-1.302 2.338-.01 1.624.42 2.436 1.295 2.436.793 0 1.19-.734 1.19-2.2m2.167 0C16 16.686 14.884 18 12.65 18 10.218 18 9 16.614 9 13.84c0-2.737 1.217-4.105 3.65-4.105.842 0 1.183.63 1.183.63v-1.58c0-.788-.45-1.183-1.347-1.183-.572 0-.858.374-.858 1.123h-2.34C9.29 6.908 10.35 6 12.462 6 14.83 6 16.01 6.946 16 8.84"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l-invert.png
new file mode 100644
index 00000000..26c70183
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l-invert.svg
new file mode 100644
index 00000000..356145b1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-l">
+ <path id="l" d="M8 18V6h3v10h5v2"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l.png
new file mode 100644
index 00000000..11b67a1c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l.svg
new file mode 100644
index 00000000..76956234
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-l.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-l">
+ <path id="l" d="M8 18V6h3v10h5v2"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n-invert.png
new file mode 100644
index 00000000..d57d0a58
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n-invert.svg
new file mode 100644
index 00000000..82e1c0b6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-n">
+ <path id="n" d="M7 18V6h3l4 8V6h3v12h-3l-4-8v8H7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n.png
new file mode 100644
index 00000000..708d421f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n.svg
new file mode 100644
index 00000000..62f66a2f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-n.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-n">
+ <path id="n" d="M7 18V6h3l4 8V6h3v12h-3l-4-8v8H7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v-invert.png
new file mode 100644
index 00000000..ad990bec
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v-invert.svg
new file mode 100644
index 00000000..18aef7b5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="bold-v">
+ <path id="v" d="M10.5 18L6 6h3l3 8 3-8h3l-4.5 12"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v.png
new file mode 100644
index 00000000..a60786c9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v.svg
new file mode 100644
index 00000000..027db273
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bold-v.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-v">
+ <path id="v" d="M10.5 18L6 6h3l3 8 3-8h3l-4.5 12"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr-invert.png
new file mode 100644
index 00000000..a32272e6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr-invert.svg
new file mode 100644
index 00000000..c383e619
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M15 7c-1.7 0-3 1.3-3 3 0-1.7-1.3-3-3-3H3v13h6c1.7 0 3 1 3 2 0-1 1.3-2 3-2h6V7h-6zm5 12h-5c-1.7 0-2 .4-2 .4v-8.9C13 9.1 14.1 8 15.5 8H20v11z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr.png
new file mode 100644
index 00000000..49ac06ae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr.svg
new file mode 100644
index 00000000..6a9a7488
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 7c-1.7 0-3 1.3-3 3 0-1.7-1.3-3-3-3H3v13h6c1.7 0 3 1 3 2 0-1 1.3-2 3-2h6V7h-6zm5 12h-5c-1.7 0-2 .4-2 .4v-8.9C13 9.1 14.1 8 15.5 8H20v11z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl-invert.png
new file mode 100644
index 00000000..7258970d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl-invert.svg
new file mode 100644
index 00000000..390902f8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M9 7c1.7 0 3 1.3 3 3 0-1.7 1.3-3 3-3h6v13h-6c-1.7 0-3 1-3 2 0-1-1.3-2-3-2H3V7h6zM4 19h5c1.7 0 2 .4 2 .4v-8.9C11 9.1 9.9 8 8.5 8H4v11z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl.png
new file mode 100644
index 00000000..e0edc34b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl.svg
new file mode 100644
index 00000000..37973289
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/book-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 7c1.7 0 3 1.3 3 3 0-1.7 1.3-3 3-3h6v13h-6c-1.7 0-3 1-3 2 0-1-1.3-2-3-2H3V7h6zM4 19h5c1.7 0 2 .4 2 .4v-8.9C11 9.1 9.9 8 8.5 8H4v11z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr-invert.png
new file mode 100644
index 00000000..084cbc7e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr-invert.svg
new file mode 100644
index 00000000..ea474cbd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M15 5H8c-1.1 0-2 .9-2 2v3h3v11l4-3 4 3V7c0-1.1-.9-2-2-2zM9 9H7V7c0-.6.4-1 1-1h1v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr.png
new file mode 100644
index 00000000..ad046b6e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr.svg
new file mode 100644
index 00000000..ba3ff91a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 5H8c-1.1 0-2 .9-2 2v3h3v11l4-3 4 3V7c0-1.1-.9-2-2-2zM9 9H7V7c0-.6.4-1 1-1h1v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl-invert.png
new file mode 100644
index 00000000..125fb746
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl-invert.svg
new file mode 100644
index 00000000..90498811
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M8 5h7c1.1 0 2 .9 2 2v3h-3v11l-4-3-4 3V7c0-1.1.9-2 2-2zm6 4h2V7c0-.6-.4-1-1-1h-1v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl.png
new file mode 100644
index 00000000..0d19f03e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl.svg
new file mode 100644
index 00000000..fcbd1358
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bookmark-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 5h7c1.1 0 2 .9 2 2v3h-3v11l-4-3-4 3V7c0-1.1.9-2 2-2zm6 4h2V7c0-.6-.4-1-1-1h-1v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright-invert.png
new file mode 100644
index 00000000..6194ed4a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright-invert.svg
new file mode 100644
index 00000000..28fac211
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9-.3.3-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+ <path d="M12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright.png
new file mode 100644
index 00000000..788fc94b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright.svg
new file mode 100644
index 00000000..5a399fe2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/bright.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9-.3.3-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+ <path d="M12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr-invert.png
new file mode 100644
index 00000000..027df2df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr-invert.svg
new file mode 100644
index 00000000..85c7273e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M3 6v11c0 1.7 1.3 3 3 3h15V6H3zm2.5 1C6.3 7 7 7.7 7 8.5S6.3 10 5.5 10 4 9.3 4 8.5 4.7 7 5.5 7zM20 19H6c-1.1 0-2-.9-2-2v-6h16v8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr.png
new file mode 100644
index 00000000..ae059ad0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr.svg
new file mode 100644
index 00000000..e7be7e56
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 6v11c0 1.7 1.3 3 3 3h15V6H3zm2.5 1C6.3 7 7 7.7 7 8.5S6.3 10 5.5 10 4 9.3 4 8.5 4.7 7 5.5 7zM20 19H6c-1.1 0-2-.9-2-2v-6h16v8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl-invert.png
new file mode 100644
index 00000000..51937b73
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl-invert.svg
new file mode 100644
index 00000000..38778ec0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M21 6v11c0 1.7-1.3 3-3 3H3V6h18zm-2.5 1c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5S20 9.3 20 8.5 19.3 7 18.5 7zM4 19h14c1.1 0 2-.9 2-2v-6H4v8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl.png
new file mode 100644
index 00000000..939a858a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl.svg
new file mode 100644
index 00000000..38807b5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/browser-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 6v11c0 1.7-1.3 3-3 3H3V6h18zm-2.5 1c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5S20 9.3 20 8.5 19.3 7 18.5 7zM4 19h14c1.1 0 2-.9 2-2v-6H4v8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.png
new file mode 100644
index 00000000..14638742
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.svg
new file mode 100644
index 00000000..f820d7a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M4 5v10c0 1.7 1.3 3 3 3h14V8c0-1.7-1.3-3-3-3H4zm2 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zM5 9h3v2H5V9zm4 0h3v2H9V9zm4 0h3v2h-3V9zm4 0h3v2h-3V9zM5 12h3v2H5v-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2zM5 15h3v2H7c-1.195 0-2-.805-2-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.png
new file mode 100644
index 00000000..0ab46dd6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.svg
new file mode 100644
index 00000000..b0bc0e51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 5v10c0 1.7 1.3 3 3 3h14V8c0-1.7-1.3-3-3-3H4zm2 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zM5 9h3v2H5V9zm4 0h3v2H9V9zm4 0h3v2h-3V9zm4 0h3v2h-3V9zM5 12h3v2H5v-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2zM5 15h3v2H7c-1.195 0-2-.805-2-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.png
new file mode 100644
index 00000000..806c55de
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.svg
new file mode 100644
index 00000000..e430f0bf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M21 5v10c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3h14zm-2 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zM7 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm13 3h-3v2h3V9zm-4 0h-3v2h3V9zm-4 0H9v2h3V9zM8 9H5v2h3V9zm12 3h-3v2h3v-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2zm12 3h-3v2h1c1.195 0 2-.805 2-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.png
new file mode 100644
index 00000000..0236393b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.svg
new file mode 100644
index 00000000..d8ff5a95
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/calendar-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 5v10c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3h14zm-2 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zM7 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm13 3h-3v2h3V9zm-4 0h-3v2h3V9zm-4 0H9v2h3V9zM8 9H5v2h3V9zm12 3h-3v2h3v-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2zm12 3h-3v2h1c1.195 0 2-.805 2-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.png
new file mode 100644
index 00000000..50c6acd8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.svg
new file mode 100644
index 00000000..5970559a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-destructive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d11d13 }</style>
+ <g id="cancel">
+ <path id="circle-with-strike" d="M12 5.022a6.98 6.98 0 0 0-.003 13.956 6.98 6.98 0 0 0-.002-13.956zM6.885 12c0-1.092.572-3.25.93-2.93l7.113 7.114c.487.525-1.838.93-2.93.93A5.113 5.113 0 0 1 6.884 12zm9.298 2.93L9.07 7.815c-.445-.483 1.837-.93 2.93-.93a5.112 5.112 0 0 1 5.114 5.113c0 1.092-.364 3.542-.93 2.93z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-invert.png
new file mode 100644
index 00000000..b7529a24
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-invert.svg
new file mode 100644
index 00000000..553e9f67
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="cancel">
+ <path id="circle-with-strike" d="M12 5.022a6.98 6.98 0 0 0-.003 13.956 6.98 6.98 0 0 0-.002-13.956zM6.885 12c0-1.092.572-3.25.93-2.93l7.113 7.114c.487.525-1.838.93-2.93.93A5.113 5.113 0 0 1 6.884 12zm9.298 2.93L9.07 7.815c-.445-.483 1.837-.93 2.93-.93a5.112 5.112 0 0 1 5.114 5.113c0 1.092-.364 3.542-.93 2.93z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel.png
new file mode 100644
index 00000000..f9354e3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel.svg
new file mode 100644
index 00000000..04ff5c32
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/cancel.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="cancel">
+ <path id="circle-with-strike" d="M12 5.022a6.98 6.98 0 0 0-.003 13.956 6.98 6.98 0 0 0-.002-13.956zM6.885 12c0-1.092.572-3.25.93-2.93l7.113 7.114c.487.525-1.838.93-2.93.93A5.113 5.113 0 0 1 6.884 12zm9.298 2.93L9.07 7.815c-.445-.483 1.837-.93 2.93-.93a5.112 5.112 0 0 1 5.114 5.113c0 1.092-.364 3.542-.93 2.93z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr-invert.png
new file mode 100644
index 00000000..0bf82864
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr-invert.svg
new file mode 100644
index 00000000..28490a31
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M7 13.1l8.9 8.9c.8-.8.8-2 0-2.8l-6.1-6.1 6-6.1c.8-.8.8-2 0-2.8L7 13.1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr.png
new file mode 100644
index 00000000..e95caf23
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr.svg
new file mode 100644
index 00000000..44d2d1a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 13.1l8.9 8.9c.8-.8.8-2 0-2.8l-6.1-6.1 6-6.1c.8-.8.8-2 0-2.8L7 13.1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl-invert.png
new file mode 100644
index 00000000..4a880d3c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl-invert.svg
new file mode 100644
index 00000000..1a3447eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M16.5 13.1L7.6 22c-.8-.8-.8-2 0-2.8l6.1-6.1-6-6.1c-.8-.8-.8-2 0-2.8l8.8 8.9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl.png
new file mode 100644
index 00000000..e59bdd5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl.svg
new file mode 100644
index 00000000..1f90f5c6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caret-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16.5 13.1L7.6 22c-.8-.8-.8-2 0-2.8l6.1-6.1-6-6.1c-.8-.8-.8-2 0-2.8l8.8 8.9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown-invert.png
new file mode 100644
index 00000000..f3031d92
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown-invert.svg
new file mode 100644
index 00000000..04e6e5e2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 16l8.9-8.9c-.8-.8-2-.8-2.8 0L12 13.2l-6.1-6c-.8-.8-2-.8-2.8 0L12 16z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown.png
new file mode 100644
index 00000000..a46ffdba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown.svg
new file mode 100644
index 00000000..89e06124
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretDown.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 16l8.9-8.9c-.8-.8-2-.8-2.8 0L12 13.2l-6.1-6c-.8-.8-2-.8-2.8 0L12 16z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp-invert.png
new file mode 100644
index 00000000..5706cb44
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp-invert.svg
new file mode 100644
index 00000000..2cbec641
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 6.5l8.9 8.9c-.8.8-2 .8-2.8 0L12 9.3l-6.1 6c-.8.8-2 .8-2.8 0L12 6.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp.png
new file mode 100644
index 00000000..9e5c022a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp.svg
new file mode 100644
index 00000000..fcf4e135
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/caretUp.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 6.5l8.9 8.9c-.8.8-2 .8-2.8 0L12 9.3l-6.1 6c-.8.8-2 .8-2.8 0L12 6.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive-invert.png
new file mode 100644
index 00000000..6fe12607
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive-invert.svg
new file mode 100644
index 00000000..e39d780e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="regular-expression">
+ <path id="upper-case" d="M7.53 7L4 17h2.063l.72-2.406h3.624l.72 2.406h2.062L9.65 7h-2.12zm1.064 1.53L9.938 13H7.25l1.344-4.47z"/>
+ <path id="lower-case" d="M18.55 17l-.184-1.035h-.055c-.35.44-.71.747-1.08.92-.37.167-.85.25-1.44.25-.564 0-.955-.208-1.377-.625-.42-.418-.627-1.012-.627-1.784 0-.808.283-1.403.846-1.784.568-.386 1.193-.607 2.208-.64l1.322-.04v-.335c0-.772-.396-1.158-1.187-1.158-.61 0-1.325.18-2.147.55l-.688-1.4c.877-.46 1.85-.69 2.916-.69 1.024 0 1.59.22 2.134.662.545.445.818 1.12.818 2.03V17h-1.45m-.394-3.527l-.802.027c-.604.018-1.054.127-1.35.327-.294.2-.442.504-.442.912 0 .58.336.87 1.008.87.48 0 .865-.137 1.152-.414.29-.277.436-.645.436-1.103v-.627"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive.png
new file mode 100644
index 00000000..426c5de5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive.svg
new file mode 100644
index 00000000..46cd9b0f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/case-sensitive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="regular-expression">
+ <path id="upper-case" d="M7.53 7L4 17h2.063l.72-2.406h3.624l.72 2.406h2.062L9.65 7h-2.12zm1.064 1.53L9.938 13H7.25l1.344-4.47z"/>
+ <path id="lower-case" d="M18.55 17l-.184-1.035h-.055c-.35.44-.71.747-1.08.92-.37.167-.85.25-1.44.25-.564 0-.955-.208-1.377-.625-.42-.418-.627-1.012-.627-1.784 0-.808.283-1.403.846-1.784.568-.386 1.193-.607 2.208-.64l1.322-.04v-.335c0-.772-.396-1.158-1.187-1.158-.61 0-1.325.18-2.147.55l-.688-1.4c.877-.46 1.85-.69 2.916-.69 1.024 0 1.59.22 2.134.662.545.445.818 1.12.818 2.03V17h-1.45m-.394-3.527l-.802.027c-.604.018-1.054.127-1.35.327-.294.2-.442.504-.442.912 0 .58.336.87 1.008.87.48 0 .865-.137 1.152-.414.29-.277.436-.645.436-1.103v-.627"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive-deprecated.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive-deprecated.png
new file mode 100644
index 00000000..a0f98716
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive-deprecated.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive-deprecated.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive-deprecated.svg
new file mode 100644
index 00000000..07a56140
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive-deprecated.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #00af89 }</style>
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive.png
new file mode 100644
index 00000000..eb72d143
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive.svg
new file mode 100644
index 00000000..3084e5a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-constructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.png
new file mode 100644
index 00000000..65e5e8d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.svg
new file mode 100644
index 00000000..eb495e4c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d11d13 }</style>
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-invert.png
new file mode 100644
index 00000000..708bb396
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-invert.svg
new file mode 100644
index 00000000..1c198c5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-progressive.png
new file mode 100644
index 00000000..eb72d143
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-progressive.svg
new file mode 100644
index 00000000..3084e5a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check.png
new file mode 100644
index 00000000..65ab0e9c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check.svg
new file mode 100644
index 00000000..2fa9dfbe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/check.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive-deprecated.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive-deprecated.png
new file mode 100644
index 00000000..43ed4825
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive-deprecated.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive-deprecated.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive-deprecated.svg
new file mode 100644
index 00000000..b96e771b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive-deprecated.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #00af89 }</style>
+ <circle cx="12" cy="12" r="6"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive.png
new file mode 100644
index 00000000..d2e71c61
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive.svg
new file mode 100644
index 00000000..136b43ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-constructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <circle cx="12" cy="12" r="6"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-invert.png
new file mode 100644
index 00000000..f4dd1ff6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-invert.svg
new file mode 100644
index 00000000..ddc7b85d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <circle cx="12" cy="12" r="6"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-progressive.png
new file mode 100644
index 00000000..d2e71c61
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-progressive.svg
new file mode 100644
index 00000000..136b43ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <circle cx="12" cy="12" r="6"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle.png
new file mode 100644
index 00000000..32ba403f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle.svg
new file mode 100644
index 00000000..18133cc9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/circle.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <circle cx="12" cy="12" r="6"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr-invert.png
new file mode 100644
index 00000000..c6a47511
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr-invert.svg
new file mode 100644
index 00000000..a6bf1ce4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M7 12h9v-1H7v1zm0 2h9v-1H7v1zm0 2h9v-1H7v1zm4-9H7v1h4V7zm0 2H7v1h4V9zm0-4H7v1h4V5zm5-2h2v16H8c-1.7 0-3-1.3-3-3V3h8v7l1.5-2 1.5 2V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr.png
new file mode 100644
index 00000000..bf131c5d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr.svg
new file mode 100644
index 00000000..6a55c053
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 12h9v-1H7v1zm0 2h9v-1H7v1zm0 2h9v-1H7v1zm4-9H7v1h4V7zm0 2H7v1h4V9zm0-4H7v1h4V5zm5-2h2v16H8c-1.7 0-3-1.3-3-3V3h8v7l1.5-2 1.5 2V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl-invert.png
new file mode 100644
index 00000000..7b90a835
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl-invert.svg
new file mode 100644
index 00000000..72472b6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M16 12H7v-1h9v1zm0 2H7v-1h9v1zm0 2H7v-1h9v1zm-4-9h4v1h-4V7zm0 2h4v1h-4V9zm0-4h4v1h-4V5zM7 3H5v16h10c1.7 0 3-1.3 3-3V3h-8v7L8.5 8 7 10V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl.png
new file mode 100644
index 00000000..df0c2047
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl.svg
new file mode 100644
index 00000000..0c0c411a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/citeArticle-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 12H7v-1h9v1zm0 2H7v-1h9v1zm0 2H7v-1h9v1zm-4-9h4v1h-4V7zm0 2h4v1h-4V9zm0-4h4v1h-4V5zM7 3H5v16h10c1.7 0 3-1.3 3-3V3h-8v7L8.5 8 7 10V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear-invert.png
new file mode 100644
index 00000000..ec90ed93
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear-invert.svg
new file mode 100644
index 00000000..7a6b1c03
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="clear">
+ <path id="circle-with-cross" d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 11l-1 1-3-3-3 3-1-1 3-3-3-3 1-1 3 3 3-3 1 1-3 3 3 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear.png
new file mode 100644
index 00000000..973dc036
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear.svg
new file mode 100644
index 00000000..8689e770
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clear.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="clear">
+ <path id="circle-with-cross" d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 11l-1 1-3-3-3 3-1-1 3-3-3-3 1-1 3 3 3-3 1 1-3 3 3 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock-invert.png
new file mode 100644
index 00000000..2f944d79
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock-invert.svg
new file mode 100644
index 00000000..6eb6e0a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3 12l-4-3V8h2v5l1.7 1.2c1.3.9 1 1.9.3 2.8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock.png
new file mode 100644
index 00000000..98b504e4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock.svg
new file mode 100644
index 00000000..85b0628a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/clock.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3 12l-4-3V8h2v5l1.7 1.2c1.3.9 1 1.9.3 2.8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.png
new file mode 100644
index 00000000..a35e9d12
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.svg
new file mode 100644
index 00000000..b90f0318
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="close">
+ <path id="cross" d="M17.4 8.1c.8-.8.8-2 0-2.8L12 10.8 7.4 6.2 6 7.6l4.6 4.6-4 4c-.8.8-.8 2 0 2.8l5.4-5.4 4.6 4.6 1.4-1.4-4.6-4.6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.png
new file mode 100644
index 00000000..b6a42b80
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.svg
new file mode 100644
index 00000000..c2693163
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="close">
+ <path id="cross" d="M17.4 8.1c.8-.8.8-2 0-2.8L12 10.8 7.4 6.2 6 7.6l4.6 4.6-4 4c-.8.8-.8 2 0 2.8l5.4-5.4 4.6 4.6 1.4-1.4-4.6-4.6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.png
new file mode 100644
index 00000000..16462a26
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.svg
new file mode 100644
index 00000000..34afc435
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="close">
+ <path id="cross" d="M6.6 8.1c-.8-.8-.8-2 0-2.8l5.4 5.5 4.6-4.6L18 7.6l-4.6 4.6 4 4c.8.8.8 2 0 2.8L12 13.6l-4.6 4.6L6 16.8l4.6-4.6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.png
new file mode 100644
index 00000000..e3e24176
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.svg
new file mode 100644
index 00000000..36e58ec2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/close-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="close">
+ <path id="cross" d="M6.6 8.1c-.8-.8-.8-2 0-2.8l5.4 5.5 4.6-4.6L18 7.6l-4.6 4.6 4 4c.8.8.8 2 0 2.8L12 13.6l-4.6 4.6L6 16.8l4.6-4.6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code-invert.png
new file mode 100644
index 00000000..1804fb89
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code-invert.svg
new file mode 100644
index 00000000..3b129c0f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="code">
+ <path id="left-bracket" d="M4 12v-1h1c1 0 1 0 1-1V7.614c0-.514.024-.896.073-1.142.054-.252.14-.463.257-.633.204-.28.473-.48.808-.59.335-.11.872-.25 1.835-.25H10v1h-.752c-.457 0-.77.19-.936.406-.167.216-.312.446-.312 1.07v1.856c0 .73-.04 1.18-.244 1.493-.2.307-.562.53-1.09.667.535.155.9.385 1.096.688.2.31.238.76.238 1.49v1.86c0 .62.145.85.312 1.06.166.22.48.41.936.41H10v1H8.973c-.963 0-1.5-.133-1.835-.248a1.578 1.578 0 0 1-.808-.59 1.68 1.68 0 0 1-.257-.626C6.023 16.283 6 15.9 6 15.386V13c0-1 0-1-1-1H4z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" width="24" height="24" xlink:href="#left-bracket"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code.png
new file mode 100644
index 00000000..ba89e4ec
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code.svg
new file mode 100644
index 00000000..a00d1582
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/code.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="code">
+ <path id="left-bracket" d="M4 12v-1h1c1 0 1 0 1-1V7.614c0-.514.024-.896.073-1.142.054-.252.14-.463.257-.633.204-.28.473-.48.808-.59.335-.11.872-.25 1.835-.25H10v1h-.752c-.457 0-.77.19-.936.406-.167.216-.312.446-.312 1.07v1.856c0 .73-.04 1.18-.244 1.493-.2.307-.562.53-1.09.667.535.155.9.385 1.096.688.2.31.238.76.238 1.49v1.86c0 .62.145.85.312 1.06.166.22.48.41.936.41H10v1H8.973c-.963 0-1.5-.133-1.835-.248a1.578 1.578 0 0 1-.808-.59 1.68 1.68 0 0 1-.257-.626C6.023 16.283 6 15.9 6 15.386V13c0-1 0-1-1-1H4z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" width="24" height="24" xlink:href="#left-bracket"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse-invert.png
new file mode 100644
index 00000000..951a8407
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse-invert.svg
new file mode 100644
index 00000000..239a248d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="collapse">
+ <path id="arrow" d="M6.697 15.714L12 10.412l5.303 5.302 1.414-1.414L12 7.583 5.283 14.3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse.png
new file mode 100644
index 00000000..1d8c6db1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse.svg
new file mode 100644
index 00000000..645bfda5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/collapse.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="collapse">
+ <path id="arrow" d="M6.697 15.714L12 10.412l5.303 5.302 1.414-1.414L12 7.583 5.283 14.3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment-invert.png
new file mode 100644
index 00000000..1de3b9db
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment-invert.svg
new file mode 100644
index 00000000..c123fd79
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="comment">
+ <path id="speech-bubble" d="M15 6H9a3 3 0 0 0-3 3v4a3 3 0 0 0 3 3v3l3-3h3a3 3 0 0 0 3-3V9a3 3 0 0 0-3-3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment.png
new file mode 100644
index 00000000..dcaa8814
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment.svg
new file mode 100644
index 00000000..861611ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/comment.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="comment">
+ <path id="speech-bubble" d="M15 6H9a3 3 0 0 0-3 3v4a3 3 0 0 0 3 3v3l3-3h3a3 3 0 0 0 3-3V9a3 3 0 0 0-3-3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr-invert.png
new file mode 100644
index 00000000..014f7fe6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr-invert.svg
new file mode 100644
index 00000000..92f19bf7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M16 5H4v12c0 1.6 1.3 3 3 3h12V8c0-1.7-1.4-3-3-3zM7.5 17c-.8 0-1.5-.7-1.5-1.5S6.7 14 7.5 14s1.5.7 1.5 1.5S8.3 17 7.5 17zm0-6C6.7 11 6 10.3 6 9.5S6.7 8 7.5 8 9 8.7 9 9.5 8.3 11 7.5 11zm4 3c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm4 3c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm0-6c-.8 0-1.5-.7-1.5-1.5S14.7 8 15.5 8s1.5.7 1.5 1.5-.7 1.5-1.5 1.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr.png
new file mode 100644
index 00000000..79f4497b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr.svg
new file mode 100644
index 00000000..2571d4dc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 5H4v12c0 1.6 1.3 3 3 3h12V8c0-1.7-1.4-3-3-3zM7.5 17c-.8 0-1.5-.7-1.5-1.5S6.7 14 7.5 14s1.5.7 1.5 1.5S8.3 17 7.5 17zm0-6C6.7 11 6 10.3 6 9.5S6.7 8 7.5 8 9 8.7 9 9.5 8.3 11 7.5 11zm4 3c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm4 3c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm0-6c-.8 0-1.5-.7-1.5-1.5S14.7 8 15.5 8s1.5.7 1.5 1.5-.7 1.5-1.5 1.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl-invert.png
new file mode 100644
index 00000000..9848fcd4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl-invert.svg
new file mode 100644
index 00000000..b7c1c5cb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M7 5h12v12c0 1.6-1.3 3-3 3H4V8c0-1.7 1.4-3 3-3zm8.5 12c.8 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5-1.5.7-1.5 1.5.7 1.5 1.5 1.5zm0-6c.8 0 1.5-.7 1.5-1.5S16.3 8 15.5 8 14 8.7 14 9.5s.7 1.5 1.5 1.5zm-4 3c.8 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5-1.5.7-1.5 1.5.7 1.5 1.5 1.5zm-4 3c.8 0 1.5-.7 1.5-1.5S8.3 14 7.5 14 6 14.7 6 15.5 6.7 17 7.5 17zm0-6c.8 0 1.5-.7 1.5-1.5S8.3 8 7.5 8 6 8.7 6 9.5 6.7 11 7.5 11z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl.png
new file mode 100644
index 00000000..c01002f1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl.svg
new file mode 100644
index 00000000..9be97f6b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/die-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 5h12v12c0 1.6-1.3 3-3 3H4V8c0-1.7 1.4-3 3-3zm8.5 12c.8 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5-1.5.7-1.5 1.5.7 1.5 1.5 1.5zm0-6c.8 0 1.5-.7 1.5-1.5S16.3 8 15.5 8 14 8.7 14 9.5s.7 1.5 1.5 1.5zm-4 3c.8 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5-1.5.7-1.5 1.5.7 1.5 1.5 1.5zm-4 3c.8 0 1.5-.7 1.5-1.5S8.3 14 7.5 14 6 14.7 6 15.5 6.7 17 7.5 17zm0-6c.8 0 1.5-.7 1.5-1.5S8.3 8 7.5 8 6 8.7 6 9.5 6.7 11 7.5 11z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle-invert.png
new file mode 100644
index 00000000..b186eb0b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle-invert.svg
new file mode 100644
index 00000000..e4592ed0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 18l8-10H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle.png
new file mode 100644
index 00000000..7df0592f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle.svg
new file mode 100644
index 00000000..e1fb989c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/downTriangle.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 18l8-10H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr-invert.png
new file mode 100644
index 00000000..ce0f041c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr-invert.svg
new file mode 100644
index 00000000..a1104a82
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M16 11h-3V4c-1.7 0-3 1.3-3 3v4H7l4.5 5 4.5-5zm1 2v5H7c-.6 0-1-.4-1-1v-4H4v4c0 1.9 1.3 3 3 3h12v-7h-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr.png
new file mode 100644
index 00000000..4d67c8da
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr.svg
new file mode 100644
index 00000000..dfb2bb6b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 11h-3V4c-1.7 0-3 1.3-3 3v4H7l4.5 5 4.5-5zm1 2v5H7c-.6 0-1-.4-1-1v-4H4v4c0 1.9 1.3 3 3 3h12v-7h-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl-invert.png
new file mode 100644
index 00000000..09286f75
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl-invert.svg
new file mode 100644
index 00000000..fb82869b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M7 11h3V4c1.7 0 3 1.3 3 3v4h3l-4.5 5L7 11zm-1 2v5h10c.6 0 1-.4 1-1v-4h2v4c0 1.9-1.3 3-3 3H4v-7h2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl.png
new file mode 100644
index 00000000..660d7d0e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl.svg
new file mode 100644
index 00000000..276b1536
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/download-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 11h3V4c1.7 0 3 1.3 3 3v4h3l-4.5 5L7 11zm-1 2v5h10c.6 0 1-.4 1-1v-4h2v4c0 1.9-1.3 3-3 3H4v-7h2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-invert.png
new file mode 100644
index 00000000..682e18f9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-invert.svg
new file mode 100644
index 00000000..7c0fd754
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M17 2L5 14l-1 5 5-1L21 6c0-2-2-4-4-4zM7.2 15.5c-.3-.3-.7-.6-1-.8C8.5 12.4 17.5 3.3 17.5 3.3c.4.1.7.3 1 .7L7.2 15.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-progressive.png
new file mode 100644
index 00000000..44ceb9c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-progressive.svg
new file mode 100644
index 00000000..6dbfe37f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M17 2L5 14l-1 5 5-1L21 6c0-2-2-4-4-4zM7.2 15.5c-.3-.3-.7-.6-1-.8C8.5 12.4 17.5 3.3 17.5 3.3c.4.1.7.3 1 .7L7.2 15.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr.png
new file mode 100644
index 00000000..504f29bb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr.svg
new file mode 100644
index 00000000..02ab6e42
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 2L5 14l-1 5 5-1L21 6c0-2-2-4-4-4zM7.2 15.5c-.3-.3-.7-.6-1-.8C8.5 12.4 17.5 3.3 17.5 3.3c.4.1.7.3 1 .7L7.2 15.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-invert.png
new file mode 100644
index 00000000..2d23719c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-invert.svg
new file mode 100644
index 00000000..fdfbca55
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M8 2l12 12 1 5-5-1L4 6c0-2 2-4 4-4zm9.8 13.5c.3-.3.7-.6 1-.8C16.5 12.4 7.5 3.3 7.5 3.3c-.4.1-.7.3-1 .7l11.3 11.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-progressive.png
new file mode 100644
index 00000000..4d2e0a44
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-progressive.svg
new file mode 100644
index 00000000..213841da
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M8 2l12 12 1 5-5-1L4 6c0-2 2-4 4-4zm9.8 13.5c.3-.3.7-.6 1-.8C16.5 12.4 7.5 3.3 7.5 3.3c-.4.1-.7.3-1 .7l11.3 11.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl.png
new file mode 100644
index 00000000..7ea3aee9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl.svg
new file mode 100644
index 00000000..83033c5a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/edit-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 2l12 12 1 5-5-1L4 6c0-2 2-4 4-4zm9.8 13.5c.3-.3.7-.6 1-.8C16.5 12.4 7.5 3.3 7.5 3.3c-.4.1-.7.3-1 .7l11.3 11.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr-invert.png
new file mode 100644
index 00000000..c90c5933
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr-invert.svg
new file mode 100644
index 00000000..2f9ab93e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M21 4V3s0-3-3-3-3 3-3 3v1h-1v6h8V4zm-1.5 0h-3V3s0-1.5 1.5-1.5c1.48.06 1.5 1.5 1.5 1.5zM13 9.6l-6.8 6.9c-.3-.3-.7-.6-1-.8 1.4-1.4 5-5 7.8-7.9V6l-9 9-1 5 5-1 8-8h-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr.png
new file mode 100644
index 00000000..aa4b8c3b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr.svg
new file mode 100644
index 00000000..e06e5a05
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 4V3s0-3-3-3-3 3-3 3v1h-1v6h8V4zm-1.5 0h-3V3s0-1.5 1.5-1.5c1.48.06 1.5 1.5 1.5 1.5zM13 9.6l-6.8 6.9c-.3-.3-.7-.6-1-.8 1.4-1.4 5-5 7.8-7.9V6l-9 9-1 5 5-1 8-8h-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl-invert.png
new file mode 100644
index 00000000..5a40486b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl-invert.svg
new file mode 100644
index 00000000..9d563fb7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M4 4V3s0-3 3-3 3 3 3 3v1h1v6H3V4zm1.5 0h3V3s0-1.5-1.5-1.5C5.52 1.56 5.5 3 5.5 3zM12 9.6l6.8 6.9c.3-.3.7-.6 1-.8-1.4-1.4-5-5-7.8-7.9V6l9 9 1 5-5-1-8-8h3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl.png
new file mode 100644
index 00000000..3d8b751f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl.svg
new file mode 100644
index 00000000..fb1001f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editLock-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 4V3s0-3 3-3 3 3 3 3v1h1v6H3V4zm1.5 0h3V3s0-1.5-1.5-1.5C5.52 1.56 5.5 3 5.5 3zM12 9.6l6.8 6.9c.3-.3.7-.6 1-.8-1.4-1.4-5-5-7.8-7.9V6l9 9 1 5-5-1-8-8h3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr-invert.png
new file mode 100644
index 00000000..19726d14
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr-invert.svg
new file mode 100644
index 00000000..bdcbb21d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M14.9 2.8c.9 0 1.8.2 2.7.6.9.4 1.6.9 1.9 1.6-2.8.1-5 1.1-6.6 3.1l1.3 2-6.7-.3L8 3l1.7 2c1.8-1.5 3.5-2.2 5.2-2.2z"/>
+ <path d="M15.2 11.1l-2.6-.1-5.4 5.5c-.3-.3-.7-.6-1-.8.9-.9 2.8-2.8 4.7-4.8H9.1L5 15l-1 5 5-1 7.8-7.8-1.6-.1zM20.6 6c-1.7 0-3.2.5-4.4 1.4l-.9.9.8 1.3.9 1.4 4-4c0-.3-.1-.7-.2-1h-.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr.png
new file mode 100644
index 00000000..c1633605
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr.svg
new file mode 100644
index 00000000..50f4214d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14.9 2.8c.9 0 1.8.2 2.7.6.9.4 1.6.9 1.9 1.6-2.8.1-5 1.1-6.6 3.1l1.3 2-6.7-.3L8 3l1.7 2c1.8-1.5 3.5-2.2 5.2-2.2z"/>
+ <path d="M15.2 11.1l-2.6-.1-5.4 5.5c-.3-.3-.7-.6-1-.8.9-.9 2.8-2.8 4.7-4.8H9.1L5 15l-1 5 5-1 7.8-7.8-1.6-.1zM20.6 6c-1.7 0-3.2.5-4.4 1.4l-.9.9.8 1.3.9 1.4 4-4c0-.3-.1-.7-.2-1h-.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl-invert.png
new file mode 100644
index 00000000..8e72010c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl-invert.svg
new file mode 100644
index 00000000..dfe68777
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M10.1 2.8c-.9 0-1.8.2-2.7.6-.9.4-1.6.9-1.9 1.6 2.8.1 5 1.1 6.6 3.1l-1.3 2 6.7-.3L17 3l-1.7 2c-1.8-1.5-3.5-2.2-5.2-2.2z"/>
+ <path d="M9.8 11.1l2.6-.1 5.4 5.5c.3-.3.7-.6 1-.8-.9-.9-2.8-2.8-4.7-4.8h1.8L20 15l1 5-5-1-7.8-7.8 1.6-.1zM4.4 6c1.7 0 3.2.5 4.4 1.4l.9.9-.8 1.3L8 11 4 7c0-.3.1-.7.2-1h.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl.png
new file mode 100644
index 00000000..fc989682
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl.svg
new file mode 100644
index 00000000..b7cfed78
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/editUndo-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10.1 2.8c-.9 0-1.8.2-2.7.6-.9.4-1.6.9-1.9 1.6 2.8.1 5 1.1 6.6 3.1l-1.3 2 6.7-.3L17 3l-1.7 2c-1.8-1.5-3.5-2.2-5.2-2.2z"/>
+ <path d="M9.8 11.1l2.6-.1 5.4 5.5c.3-.3.7-.6 1-.8-.9-.9-2.8-2.8-4.7-4.8h1.8L20 15l1 5-5-1-7.8-7.8 1.6-.1zM4.4 6c1.7 0 3.2.5 4.4 1.4l.9.9-.8 1.3L8 11 4 7c0-.3.1-.7.2-1h.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis-invert.png
new file mode 100644
index 00000000..7d57d117
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis-invert.svg
new file mode 100644
index 00000000..b512f82b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M8 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM14 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM20 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis.png
new file mode 100644
index 00000000..85fa4f36
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis.svg
new file mode 100644
index 00000000..ef7d485b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ellipsis.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM14 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM20 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand-invert.png
new file mode 100644
index 00000000..38a2c391
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand-invert.svg
new file mode 100644
index 00000000..28fb1ef4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="expand">
+ <path id="arrow" d="M17.303 8.283L12 13.586 6.697 8.283 5.283 9.697 12 16.414l6.717-6.717z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand.png
new file mode 100644
index 00000000..f72b6f2e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand.svg
new file mode 100644
index 00000000..84b9e0a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/expand.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="expand">
+ <path id="arrow" d="M17.303 8.283L12 13.586 6.697 8.283 5.283 9.697 12 16.414l6.717-6.717z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr-invert.png
new file mode 100644
index 00000000..18a18015
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr-invert.svg
new file mode 100644
index 00000000..269d813b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="external">
+ <path id="box" d="M4 4h6v2H6v12h12v-4h2v6H4z"/>
+ <path id="arrow" d="M12.42 4H20v7.58l-2.84-2.846L12.892 13 11 11.106l4.264-4.266z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr.png
new file mode 100644
index 00000000..185ffc6a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr.svg
new file mode 100644
index 00000000..1d7980dc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="external">
+ <path id="box" d="M4 4h6v2H6v12h12v-4h2v6H4z"/>
+ <path id="arrow" d="M12.42 4H20v7.58l-2.84-2.846L12.892 13 11 11.106l4.264-4.266z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl-invert.png
new file mode 100644
index 00000000..105fd0d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl-invert.svg
new file mode 100644
index 00000000..cc06c3ae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="external">
+ <path id="box" d="M20 4h-6v2h4v12H6v-4H4v6h16z"/>
+ <path id="arrow" d="M11.58 4H4v7.58l2.84-2.846L11.108 13 13 11.106 8.736 6.84z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl.png
new file mode 100644
index 00000000..7066001c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl.svg
new file mode 100644
index 00000000..7e25d034
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/external-link-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="external">
+ <path id="box" d="M20 4h-6v2h4v12H6v-4H4v6h16z"/>
+ <path id="arrow" d="M11.58 4H4v7.58l2.84-2.846L11.108 13 13 11.106 8.736 6.84z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye-invert.png
new file mode 100644
index 00000000..b4564780
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye-invert.svg
new file mode 100644
index 00000000..fb90b1eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 8c-5 0-11 6-11 6s6 6 11 6 11-6 11-6-6-6-11-6zm0 10c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+ <circle cx="12" cy="14" r="2"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye.png
new file mode 100644
index 00000000..62c82c0b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye.svg
new file mode 100644
index 00000000..343e9cf5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eye.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 8c-5 0-11 6-11 6s6 6 11 6 11-6 11-6-6-6-11-6zm0 10c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+ <circle cx="12" cy="14" r="2"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed-invert.png
new file mode 100644
index 00000000..bd499f10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed-invert.svg
new file mode 100644
index 00000000..3ce3da3d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M19.4 12.7c.7-.8 1.2-1.7 1.4-2.7h-1.6c-.9 2.5-3.9 4.4-7.7 4.6h-.1c-3.7-.2-6.8-2.1-7.7-4.6H2.2c.2 1 .8 1.9 1.4 2.7l-2 2 .7.7 2-2c.8.6 1.7 1.2 2.7 1.7l-1 2.8.9.3 1-2.8c1 .3 2 .6 3.1.6v3h1v-3c1.1-.1 2.2-.3 3.1-.6l1 2.8.9-.3-1-2.8c1-.4 1.9-1 2.6-1.7l2 2 .7-.7-1.9-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed.png
new file mode 100644
index 00000000..1ac37d6d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed.svg
new file mode 100644
index 00000000..d17f2c8a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/eyeClosed.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19.4 12.7c.7-.8 1.2-1.7 1.4-2.7h-1.6c-.9 2.5-3.9 4.4-7.7 4.6h-.1c-3.7-.2-6.8-2.1-7.7-4.6H2.2c.2 1 .8 1.9 1.4 2.7l-2 2 .7.7 2-2c.8.6 1.7 1.2 2.7 1.7l-1 2.8.9.3 1-2.8c1 .3 2 .6 3.1.6v3h1v-3c1.1-.1 2.2-.3 3.1-.6l1 2.8.9-.3-1-2.8c1-.4 1.9-1 2.6-1.7l2 2 .7-.7-1.9-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr-invert.png
new file mode 100644
index 00000000..e6602c96
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr-invert.svg
new file mode 100644
index 00000000..55e6441e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="find">
+ <path id="magnifying-glass" d="M13.656 11c-1.92 0-3.5 1.548-3.5 3.47 0 1.92 1.58 3.5 3.5 3.5.75 0 1.432-.253 2-.657l.094.156 2.375 2.37c.19.19.534.15.78-.096s.315-.59.126-.78l-2.37-2.377-.185-.094a3.545 3.545 0 0 0 .655-2.03c0-1.92-1.55-3.47-3.47-3.47zm0 1.656a1.8 1.8 0 0 1 1.813 1.813 1.83 1.83 0 0 1-1.82 1.84c-1.01 0-1.844-.83-1.844-1.847s.832-1.814 1.844-1.814z"/>
+ <path id="text" d="M6 5v2h10V5H6zm0 3v2h11V8H6zm0 3v2h3.53a4.443 4.443 0 0 1 1.44-2H6zm0 3v2h3.53c-.177-.48-.28-.99-.28-1.53 0-.16.046-.315.063-.47H6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr.png
new file mode 100644
index 00000000..066d84a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr.svg
new file mode 100644
index 00000000..ef44f579
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="find">
+ <path id="magnifying-glass" d="M13.656 11c-1.92 0-3.5 1.548-3.5 3.47 0 1.92 1.58 3.5 3.5 3.5.75 0 1.432-.253 2-.657l.094.156 2.375 2.37c.19.19.534.15.78-.096s.315-.59.126-.78l-2.37-2.377-.185-.094a3.545 3.545 0 0 0 .655-2.03c0-1.92-1.55-3.47-3.47-3.47zm0 1.656a1.8 1.8 0 0 1 1.813 1.813 1.83 1.83 0 0 1-1.82 1.84c-1.01 0-1.844-.83-1.844-1.847s.832-1.814 1.844-1.814z"/>
+ <path id="text" d="M6 5v2h10V5H6zm0 3v2h11V8H6zm0 3v2h3.53a4.443 4.443 0 0 1 1.44-2H6zm0 3v2h3.53c-.177-.48-.28-.99-.28-1.53 0-.16.046-.315.063-.47H6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl-invert.png
new file mode 100644
index 00000000..bd3e862e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl-invert.svg
new file mode 100644
index 00000000..e6c6bb55
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="find">
+ <path id="magnifying-glass" d="M11.344 11c1.92 0 3.5 1.548 3.5 3.47 0 1.92-1.58 3.5-3.5 3.5-.75 0-1.432-.253-2-.657l-.094.156-2.375 2.37c-.19.19-.534.15-.78-.096s-.315-.59-.126-.78l2.37-2.377.185-.094a3.545 3.545 0 0 1-.655-2.03c0-1.92 1.55-3.47 3.47-3.47zm0 1.656A1.8 1.8 0 0 0 9.53 14.47c0 1.01.806 1.84 1.818 1.84 1.01 0 1.844-.83 1.844-1.845s-.832-1.814-1.844-1.814z"/>
+ <path id="text" d="M19 5v2H9V5zm0 3v2H8V8zm0 3v2h-3.53a4.443 4.443 0 0 0-1.44-2zm0 3v2h-3.53c.177-.48.28-.99.28-1.53 0-.16-.046-.315-.063-.47z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl.png
new file mode 100644
index 00000000..ed834afe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl.svg
new file mode 100644
index 00000000..51fd39ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/find-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="find">
+ <path id="magnifying-glass" d="M11.344 11c1.92 0 3.5 1.548 3.5 3.47 0 1.92-1.58 3.5-3.5 3.5-.75 0-1.432-.253-2-.657l-.094.156-2.375 2.37c-.19.19-.534.15-.78-.096s-.315-.59-.126-.78l2.37-2.377.185-.094a3.545 3.545 0 0 1-.655-2.03c0-1.92 1.55-3.47 3.47-3.47zm0 1.656A1.8 1.8 0 0 0 9.53 14.47c0 1.01.806 1.84 1.818 1.84 1.01 0 1.844-.83 1.844-1.845s-.832-1.814-1.844-1.814z"/>
+ <path id="text" d="M19 5v2H9V5zm0 3v2H8V8zm0 3v2h-3.53a4.443 4.443 0 0 0-1.44-2zm0 3v2h-3.53c.177-.48.28-.99.28-1.53 0-.16-.046-.315-.063-.47z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr-invert.png
new file mode 100644
index 00000000..ea79f46b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr-invert.svg
new file mode 100644
index 00000000..832c44f1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M14 6.5V5c-1.4-1.5-5.2-1.2-6 0V4H7v15h1v-7c.8-.8 3.4-.9 5-.5V13c1.2 1.5 4.3 1.2 5 0V6c-.7.7-2.7.9-4 .5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr.png
new file mode 100644
index 00000000..bd19f2b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr.svg
new file mode 100644
index 00000000..10975612
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14 6.5V5c-1.4-1.5-5.2-1.2-6 0V4H7v15h1v-7c.8-.8 3.4-.9 5-.5V13c1.2 1.5 4.3 1.2 5 0V6c-.7.7-2.7.9-4 .5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl-invert.png
new file mode 100644
index 00000000..e0b88595
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl-invert.svg
new file mode 100644
index 00000000..3946c4a1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M11 6.5V5c1.4-1.5 5.2-1.2 6 0V4h1v15h-1v-7c-.8-.8-3.4-.9-5-.5V13c-1.2 1.5-4.3 1.2-5 0V6c.7.7 2.7.9 4 .5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl.png
new file mode 100644
index 00000000..e881d7c7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl.svg
new file mode 100644
index 00000000..0f7e7ced
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flag-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 6.5V5c1.4-1.5 5.2-1.2 6 0V4h1v15h-1v-7c-.8-.8-3.4-.9-5-.5V13c-1.2 1.5-4.3 1.2-5 0V6c.7.7 2.7.9 4 .5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr-invert.png
new file mode 100644
index 00000000..49859116
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr-invert.svg
new file mode 100644
index 00000000..0d074de7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M18 2L2.03 17.97l.97 1 4-4V19h1v-5.03l2.688-2.69c.81-.02 1.645.053 2.312.22V13c1.2 1.5 4.3 1.2 5 0V6c-.493.493-1.635.725-2.72.688L19 2.968zM7 4v7.03l6.438-6.436C11.778 3.61 8.71 3.934 8 5V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr.png
new file mode 100644
index 00000000..033adde2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr.svg
new file mode 100644
index 00000000..516a3ea2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18 2L2.03 17.97l.97 1 4-4V19h1v-5.03l2.688-2.69c.81-.02 1.645.053 2.312.22V13c1.2 1.5 4.3 1.2 5 0V6c-.493.493-1.635.725-2.72.688L19 2.968zM7 4v7.03l6.438-6.436C11.778 3.61 8.71 3.934 8 5V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl-invert.png
new file mode 100644
index 00000000..4e1a6d1d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl-invert.svg
new file mode 100644
index 00000000..0653df3f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M7 2l-1 .97 3.72 3.717C8.634 6.727 7.492 6.494 7 6v7c.7 1.2 3.8 1.5 5 0v-1.5c.667-.167 1.5-.24 2.313-.22L17 13.97V19h1v-4.03l4 4 .97-1zm7.22 2c-.952-.03-1.932.163-2.658.594L18 11.03V4h-1v1c-.4-.6-1.556-.963-2.78-1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl.png
new file mode 100644
index 00000000..fca73fd5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl.svg
new file mode 100644
index 00000000..8ed159e6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/flagUndo-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 2l-1 .97 3.72 3.717C8.634 6.727 7.492 6.494 7 6v7c.7 1.2 3.8 1.5 5 0v-1.5c.667-.167 1.5-.24 2.313-.22L17 13.97V19h1v-4.03l4 4 .97-1zm7.22 2c-.952-.03-1.932.163-2.658.594L18 11.03V4h-1v1c-.4-.6-1.556-.963-2.78-1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr-invert.png
new file mode 100644
index 00000000..d7c6e288
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr-invert.svg
new file mode 100644
index 00000000..c66c2816
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M2 5v15h20V5H2zm15 11H8c-.6 0-1-.4-1-1V9h3l2 1h5v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr.png
new file mode 100644
index 00000000..45c3ee9d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr.svg
new file mode 100644
index 00000000..7e60fb4b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M2 5v15h20V5H2zm15 11H8c-.6 0-1-.4-1-1V9h3l2 1h5v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl-invert.png
new file mode 100644
index 00000000..46b3f945
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl-invert.svg
new file mode 100644
index 00000000..f2d9fabb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M22 5v15H2V5h20zM7 16h9c.6 0 1-.4 1-1V9h-3l-2 1H7v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl.png
new file mode 100644
index 00000000..8a624c19
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl.svg
new file mode 100644
index 00000000..e0a6f619
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/folderPlaceholder-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M22 5v15H2V5h20zM7 16h9c.6 0 1-.4 1-1V9h-3l-2 1H7v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen-invert.png
new file mode 100644
index 00000000..b7a3cb51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen-invert.svg
new file mode 100644
index 00000000..e7aec3db
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path id="arrow" d="M6 6v4l1.28-1.28 2 2 1.423-1.44-2-2L10 6z"/>
+ <use transform="rotate(90 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(180 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(-90 12 12)" xlink:href="#arrow"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen.png
new file mode 100644
index 00000000..ced10354
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen.svg
new file mode 100644
index 00000000..06b709ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/fullScreen.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <path id="arrow" d="M6 6v4l1.28-1.28 2 2 1.423-1.44-2-2L10 6z"/>
+ <use transform="rotate(90 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(180 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(-90 12 12)" xlink:href="#arrow"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr-invert.png
new file mode 100644
index 00000000..2949648d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr-invert.svg
new file mode 100644
index 00000000..00d26951
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M11 13L5 6h15l-6 7v7c-1.7 0-3-1.3-3-3v-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr.png
new file mode 100644
index 00000000..9396cba0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr.svg
new file mode 100644
index 00000000..df863b9c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 13L5 6h15l-6 7v7c-1.7 0-3-1.3-3-3v-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl-invert.png
new file mode 100644
index 00000000..c0f155ae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl-invert.svg
new file mode 100644
index 00000000..bd2d7de3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M14 13l6-7H5l6 7v7c1.7 0 3-1.3 3-3v-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl.png
new file mode 100644
index 00000000..7aee05f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl.svg
new file mode 100644
index 00000000..4eade2d6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/funnel-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14 13l6-7H5l6 7v7c1.7 0 3-1.3 3-3v-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright-invert.png
new file mode 100644
index 00000000..2a4d5478
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright-invert.svg
new file mode 100644
index 00000000..95b83c2c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M11.4 5.4V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm-5.2-.5c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 7c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm-3 4c0-1.7 1.3-3 3-3v6c-1.7 0-3-1.3-3-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright.png
new file mode 100644
index 00000000..f8432105
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright.svg
new file mode 100644
index 00000000..2745ec7f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/halfBright.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11.4 5.4V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm-5.2-.5c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 7c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm-3 4c0-1.7 1.3-3 3-3v6c-1.7 0-3-1.3-3-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart-invert.png
new file mode 100644
index 00000000..2070997e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart-invert.svg
new file mode 100644
index 00000000..7ace9e4d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M15 7c-2 0-3 2-3 2s-1-2-3-2c-2.5 0-4 2-4 4 0 4 5 5 7 8 2-3 7-4 7-8 0-2-1.5-4-4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart.png
new file mode 100644
index 00000000..76d76d0a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart.svg
new file mode 100644
index 00000000..6433201a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/heart.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 7c-2 0-3 2-3 2s-1-2-3-2c-2.5 0-4 2-4 4 0 4 5 5 7 8 2-3 7-4 7-8 0-2-1.5-4-4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr-invert.png
new file mode 100644
index 00000000..35d8f226
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr-invert.svg
new file mode 100644
index 00000000..a43996c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr-invert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="help">
+ <path id="circle" d="M12 2.085c-5.477 0-9.915 4.438-9.915 9.916 0 5.48 4.438 9.92 9.916 9.92 5.48 0 9.92-4.44 9.92-9.913 0-5.477-4.44-9.915-9.913-9.915zm.002 18a8.084 8.084 0 1 1 0-16.168 8.084 8.084 0 0 1 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M11.766 6.688c-2.5 0-3.22 2.188-3.22 2.188l1.412.854s.298-.79.9-1.23c.517-.374 1.626-.624 2.22.126.7.885-.17 1.587-1.078 2.72C11.047 12.53 11 15 11 15h1.97s.134-2.318 1.04-3.38c.603-.708 1.443-1.34 1.443-2.495s-1.187-2.437-3.687-2.437z"/>
+ <path id="bottom" d="M11 16h2v2h-2z"/>
+ </g>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr.png
new file mode 100644
index 00000000..9bb1382a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr.svg
new file mode 100644
index 00000000..a77dca2c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-ltr.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="help">
+ <path id="circle" d="M12 2.085c-5.477 0-9.915 4.438-9.915 9.916 0 5.48 4.438 9.92 9.916 9.92 5.48 0 9.92-4.44 9.92-9.913 0-5.477-4.44-9.915-9.913-9.915zm.002 18a8.084 8.084 0 1 1 0-16.168 8.084 8.084 0 0 1 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M11.766 6.688c-2.5 0-3.22 2.188-3.22 2.188l1.412.854s.298-.79.9-1.23c.517-.374 1.626-.624 2.22.126.7.885-.17 1.587-1.078 2.72C11.047 12.53 11 15 11 15h1.97s.134-2.318 1.04-3.38c.603-.708 1.443-1.34 1.443-2.495s-1.187-2.437-3.687-2.437z"/>
+ <path id="bottom" d="M11 16h2v2h-2z"/>
+ </g>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl-invert.png
new file mode 100644
index 00000000..9cb8cb28
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl-invert.svg
new file mode 100644
index 00000000..0c0368e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl-invert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="help">
+ <path id="circle" d="M12 2.085c5.477 0 9.915 4.438 9.915 9.916 0 5.48-4.438 9.92-9.916 9.92-5.48 0-9.92-4.44-9.92-9.913 0-5.477 4.44-9.915 9.913-9.915zm-.002 18a8.084 8.084 0 1 0 0-16.168 8.084 8.084 0 0 0 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M12.234 6.688c2.5 0 3.22 2.188 3.22 2.188l-1.412.854s-.298-.79-.9-1.23c-.517-.374-1.626-.624-2.22.126-.7.885.17 1.587 1.078 2.72C12.953 12.53 13 15 13 15h-1.97s-.134-2.318-1.04-3.38c-.603-.708-1.443-1.34-1.443-2.495 0-1.156 1.187-2.437 3.687-2.437z"/>
+ <path id="bottom" d="M13 16h-2v2h2z"/>
+ </g>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl.png
new file mode 100644
index 00000000..50899b0d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl.svg
new file mode 100644
index 00000000..278b906b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/help-rtl.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="help">
+ <path id="circle" d="M12 2.085c5.477 0 9.915 4.438 9.915 9.916 0 5.48-4.438 9.92-9.916 9.92-5.48 0-9.92-4.44-9.92-9.913 0-5.477 4.44-9.915 9.913-9.915zm-.002 18a8.084 8.084 0 1 0 0-16.168 8.084 8.084 0 0 0 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M12.234 6.688c2.5 0 3.22 2.188 3.22 2.188l-1.412.854s-.298-.79-.9-1.23c-.517-.374-1.626-.624-2.22.126-.7.885.17 1.587 1.078 2.72C12.953 12.53 13 15 13 15h-1.97s-.134-2.318-1.04-3.38c-.603-.708-1.443-1.34-1.443-2.495 0-1.156 1.187-2.437 3.687-2.437z"/>
+ <path id="bottom" d="M13 16h-2v2h2z"/>
+ </g>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history-invert.png
new file mode 100644
index 00000000..0bd8394f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history-invert.svg
new file mode 100644
index 00000000..6b469209
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="history">
+ <path id="clock-hands" d="M17.26 15.076s-2.385-1.935-4.005-3.062c.72-2.397 1.702-6.56 1.702-6.56s-4.35 5.364-4.877 6.7c-.463 1.168 1.46 2.21 2.346 1.678 1.9.55 4.834 1.244 4.834 1.244z"/>
+ <path id="arrow" d="M12.086 2.085C6.608 2.085 2.17 6.523 2.17 12a9.86 9.86 0 0 0 1.3 4.9l-2.22 2.04h5.688v-5.22L4.87 15.616A7.982 7.982 0 0 1 4.004 12a8.084 8.084 0 0 1 16.167.004 8.08 8.08 0 0 1-8.08 8.085 7.975 7.975 0 0 1-3.21-.68L8.05 21.04a9.81 9.81 0 0 0 4.045.874C17.563 21.914 22 17.476 22 12c0-5.477-4.438-9.915-9.914-9.915z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history.png
new file mode 100644
index 00000000..417f5293
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history.svg
new file mode 100644
index 00000000..68beaa13
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/history.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="history">
+ <path id="clock-hands" d="M17.26 15.076s-2.385-1.935-4.005-3.062c.72-2.397 1.702-6.56 1.702-6.56s-4.35 5.364-4.877 6.7c-.463 1.168 1.46 2.21 2.346 1.678 1.9.55 4.834 1.244 4.834 1.244z"/>
+ <path id="arrow" d="M12.086 2.085C6.608 2.085 2.17 6.523 2.17 12a9.86 9.86 0 0 0 1.3 4.9l-2.22 2.04h5.688v-5.22L4.87 15.616A7.982 7.982 0 0 1 4.004 12a8.084 8.084 0 0 1 16.167.004 8.08 8.08 0 0 1-8.08 8.085 7.975 7.975 0 0 1-3.21-.68L8.05 21.04a9.81 9.81 0 0 0 4.045.874C17.563 21.914 22 17.476 22 12c0-5.477-4.438-9.915-9.914-9.915z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr-invert.png
new file mode 100644
index 00000000..42797a25
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr-invert.svg
new file mode 100644
index 00000000..aeb89843
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="image">
+ <path id="mountains" d="M18 17l-3-3-2 1-3-3-4 5zm2-11v13H4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr.png
new file mode 100644
index 00000000..f91dfa23
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr.svg
new file mode 100644
index 00000000..dfcbd8bb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="image">
+ <path id="mountains" d="M18 17l-3-3-2 1-3-3-4 5zm2-11v13H4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl-invert.png
new file mode 100644
index 00000000..c33eed61
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl-invert.svg
new file mode 100644
index 00000000..8b82c203
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="image">
+ <path id="mountains" d="M6 17l3-3 2 1 3-3 4 5zM4 6v13h16V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl.png
new file mode 100644
index 00000000..f33be17f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl.svg
new file mode 100644
index 00000000..2251c0e7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/image-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="image">
+ <path id="mountains" d="M6 17l3-3 2 1 3-3 4 5zM4 6v13h16V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr-invert.png
new file mode 100644
index 00000000..422f8eab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr-invert.svg
new file mode 100644
index 00000000..81b67833
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="imageAdd">
+ <path id="mountains" d="M16 17l-3-3-2 1-3-3-4 5zm-1-8v4h3v6H2V6h9v3z"/>
+ <path id="add" d="M22 6h-4V2h-2v4h-4v2h4v4h2V8h4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr.png
new file mode 100644
index 00000000..f08883c4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr.svg
new file mode 100644
index 00000000..1b60cf00
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="imageAdd">
+ <path id="mountains" d="M16 17l-3-3-2 1-3-3-4 5zm-1-8v4h3v6H2V6h9v3z"/>
+ <path id="add" d="M22 6h-4V2h-2v4h-4v2h4v4h2V8h4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl-invert.png
new file mode 100644
index 00000000..375a79f5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl-invert.svg
new file mode 100644
index 00000000..f14a20ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="imageAdd">
+ <path id="mountains" d="M8 17l3-3 2 1 3-3 4 5zm1-8v4H6v6h16V6h-9v3z"/>
+ <path id="add" d="M2 6h4V2h2v4h4v2H8v4H6V8H2z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl.png
new file mode 100644
index 00000000..dd60447c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl.svg
new file mode 100644
index 00000000..b86d4999
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageAdd-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="imageAdd">
+ <path id="mountains" d="M8 17l3-3 2 1 3-3 4 5zm1-8v4H6v6h16V6h-9v3z"/>
+ <path id="add" d="M2 6h4V2h2v4h4v2H8v4H6V8H2z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr-invert.png
new file mode 100644
index 00000000..bd15ff00
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr-invert.svg
new file mode 100644
index 00000000..785bd497
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M2 4v14h2V6h15V4H2zm3 3v13h16V7H5zm6 6l3 3 2-1 3 3H7l4-5z" id="imageGallery"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr.png
new file mode 100644
index 00000000..3934d14f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr.svg
new file mode 100644
index 00000000..2fa2e528
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M2 4v14h2V6h15V4H2zm3 3v13h16V7H5zm6 6l3 3 2-1 3 3H7l4-5z" id="imageGallery"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl-invert.png
new file mode 100644
index 00000000..85b22c4b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl-invert.svg
new file mode 100644
index 00000000..fe66e4fc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M21 4v14h-2V6H4V4h17zm-3 3v13H2V7h16zm-6 6l-3 3-2-1-3 3h12l-4-5z" id="imageGallery"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl.png
new file mode 100644
index 00000000..f8af41f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl.svg
new file mode 100644
index 00000000..c705cecc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageGallery-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 4v14h-2V6H4V4h17zm-3 3v13H2V7h16zm-6 6l-3 3-2-1-3 3h12l-4-5z" id="imageGallery"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr-invert.png
new file mode 100644
index 00000000..61b5d229
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr-invert.svg
new file mode 100644
index 00000000..59325257
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="imageAdd">
+ <path id="mountains" d="M18 17l-3-3-2 1-3-3-4 5zm2-5v7H4V6h8v6z"/>
+ <path id="lock" d="M18.5 5h-3V4s0-1.5 1.5-1.5c1.5.06 1.5 1.5 1.5 1.5zM20 5V4s0-3-3-3-3 3-3 3v1h-1v6h8V5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr.png
new file mode 100644
index 00000000..a1a1e1ed
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr.svg
new file mode 100644
index 00000000..50a928a5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="imageAdd">
+ <path id="mountains" d="M18 17l-3-3-2 1-3-3-4 5zm2-5v7H4V6h8v6z"/>
+ <path id="lock" d="M18.5 5h-3V4s0-1.5 1.5-1.5c1.5.06 1.5 1.5 1.5 1.5zM20 5V4s0-3-3-3-3 3-3 3v1h-1v6h8V5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl-invert.png
new file mode 100644
index 00000000..2223f5f9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl-invert.svg
new file mode 100644
index 00000000..b92b212a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="imageAdd">
+ <path id="mountains" d="M7 17l3-3 2 1 3-3 4 5zm-2-5v7h16V6h-8v6z"/>
+ <path id="lock" d="M6.5 5h3V4s0-1.5-1.5-1.5C6.5 2.56 6.5 4 6.5 4zM5 5V4s0-3 3-3 3 3 3 3v1h1v6H4V5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl.png
new file mode 100644
index 00000000..f0ddda4d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl.svg
new file mode 100644
index 00000000..e8ac3ed8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/imageLock-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="imageAdd">
+ <path id="mountains" d="M7 17l3-3 2 1 3-3 4 5zm-2-5v7h16V6h-8v6z"/>
+ <path id="lock" d="M6.5 5h3V4s0-1.5-1.5-1.5C6.5 2.56 6.5 4 6.5 4zM5 5V4s0-3 3-3 3 3 3 3v1h1v6H4V5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr-invert.png
new file mode 100644
index 00000000..af944e7f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr-invert.svg
new file mode 100644
index 00000000..718c2b08
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M10 8h9v2h-9V8zm0 3h9v2h-9v-2zm0 3h6v2h-6v-2zm11-8H3V4h18v2zm0 14H3v-2h18v2zM3 8v8l5-4-5-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr.png
new file mode 100644
index 00000000..b7663ae6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr.svg
new file mode 100644
index 00000000..37606969
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10 8h9v2h-9V8zm0 3h9v2h-9v-2zm0 3h6v2h-6v-2zm11-8H3V4h18v2zm0 14H3v-2h18v2zM3 8v8l5-4-5-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl-invert.png
new file mode 100644
index 00000000..f52ff9b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl-invert.svg
new file mode 100644
index 00000000..e6abc951
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M14 8H5v2h9V8zm0 3H5v2h9v-2zm0 3H8v2h6v-2zM3 6h18V4H3v2zm0 14h18v-2H3v2zM21 8v8l-5-4 5-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl.png
new file mode 100644
index 00000000..63b2750c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl.svg
new file mode 100644
index 00000000..9648f34f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/indent-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14 8H5v2h9V8zm0 3H5v2h9v-2zm0 3H8v2h6v-2zM3 6h18V4H3v2zm0 14h18v-2H3v2zM21 8v8l-5-4 5-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info-invert.png
new file mode 100644
index 00000000..2c4e0284
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info-invert.svg
new file mode 100644
index 00000000..e519d7e3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="info">
+ <path id="circled-i" d="M11.5 17a5.5 5.5 0 1 1 0-11 5.5 5.5 0 0 1 0 11zm0-12a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zm.5 5v4h1v1h-3v-1h1v-3h-1v-1zm-1-2h1v1h-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info.png
new file mode 100644
index 00000000..d9f5d75f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info.svg
new file mode 100644
index 00000000..72a9b4c6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/info.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="info">
+ <path id="circled-i" d="M11.5 17a5.5 5.5 0 1 1 0-11 5.5 5.5 0 0 1 0 11zm0-12a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zm.5 5v4h1v1h-3v-1h1v-3h-1v-1zm-1-2h1v1h-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a-invert.png
new file mode 100644
index 00000000..12dfc565
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a-invert.svg
new file mode 100644
index 00000000..ac33a08d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="italic-a">
+ <path id="a" d="M14.667 6h-1.372l-7 12H8l2.333-4h4L15 18h1.667l-2-12zm-3.75 7l2.527-4.333.723 4.333h-3.25z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a.png
new file mode 100644
index 00000000..2f5fd187
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a.svg
new file mode 100644
index 00000000..a3a11c68
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-a.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-a">
+ <path id="a" d="M14.667 6h-1.372l-7 12H8l2.333-4h4L15 18h1.667l-2-12zm-3.75 7l2.527-4.333.723 4.333h-3.25z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem-invert.png
new file mode 100644
index 00000000..567b290f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem-invert.svg
new file mode 100644
index 00000000..5ea6072e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="italic-arab-keheh-jeem">
+ <path id="arab-keheh-jeem" d="M18.125 5.844c-1.695.555-3.297 1.162-4.594 1.938-.49.3-.77.712-.87 1.125a1.26 1.26 0 0 0 .065.78c.19.406.54.575.844.814l.093-.12.53.627c.14.165.345.514.47.94.138.462.08.724 0 1.124h-3.44c-.34 0-.592.007-.766-.02-.34-.053-.256-.21-.234-.34.33-.127.56-.173.934-.14.29-.495.593-.886.906-1.314-.98.037-1.877.015-2.687-.094-.346-.046-.698-.185-1.094-.155-.36.026-.77.24-1.03.72-.25.447-.436.838-.66 1.28l.75-.47c.23-.14.486-.226.72-.218.158.004.276.053.407.093-.234.204-.51.4-.72.56-.3.26-.704.69-.908 1-.403.617-.694 1.086-.875 1.78-.18.69.003 1.34.468 1.75.426.38.846.52 1.28.566.65.064 1.206.092 2-.19.658-.23 1.022-.552 1.5-.97-.882.11-1.816.09-2.53.033-.87-.07-1.268-.386-1.47-.596-.27-.283-.306-.64-.155-1.22a1.44 1.44 0 0 1 .25-.53c.17-.228.363-.435.593-.656.45-.436 1.01-.737 1.46-.94-.042.207-.104.444-.052.69.05.23.25.38.44.47.26.12.506.152.69.153 1.42.01 2.86 0 4.28 0 .246 0 .45-.163.593-.375.14-.21.25-.48.343-.845.13-.5.094-1.062-.094-1.625a4.812 4.812 0 0 0-.72-1.406c-.336-.444-.675-.83-1-1.22 1.256-.815 2.715-1.24 3.97-1.688.12-.452.222-.926.31-1.313zm-9.47 8.438c-.26.394-.583.69-.874 1 .38.286.75.556 1.1.813.336-.303.627-.674.876-.97-.39-.267-.77-.587-1.093-.843z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem.png
new file mode 100644
index 00000000..c8e03eea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem.svg
new file mode 100644
index 00000000..11b1458e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-keheh-jeem.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-arab-keheh-jeem">
+ <path id="arab-keheh-jeem" d="M18.125 5.844c-1.695.555-3.297 1.162-4.594 1.938-.49.3-.77.712-.87 1.125a1.26 1.26 0 0 0 .065.78c.19.406.54.575.844.814l.093-.12.53.627c.14.165.345.514.47.94.138.462.08.724 0 1.124h-3.44c-.34 0-.592.007-.766-.02-.34-.053-.256-.21-.234-.34.33-.127.56-.173.934-.14.29-.495.593-.886.906-1.314-.98.037-1.877.015-2.687-.094-.346-.046-.698-.185-1.094-.155-.36.026-.77.24-1.03.72-.25.447-.436.838-.66 1.28l.75-.47c.23-.14.486-.226.72-.218.158.004.276.053.407.093-.234.204-.51.4-.72.56-.3.26-.704.69-.908 1-.403.617-.694 1.086-.875 1.78-.18.69.003 1.34.468 1.75.426.38.846.52 1.28.566.65.064 1.206.092 2-.19.658-.23 1.022-.552 1.5-.97-.882.11-1.816.09-2.53.033-.87-.07-1.268-.386-1.47-.596-.27-.283-.306-.64-.155-1.22a1.44 1.44 0 0 1 .25-.53c.17-.228.363-.435.593-.656.45-.436 1.01-.737 1.46-.94-.042.207-.104.444-.052.69.05.23.25.38.44.47.26.12.506.152.69.153 1.42.01 2.86 0 4.28 0 .246 0 .45-.163.593-.375.14-.21.25-.48.343-.845.13-.5.094-1.062-.094-1.625a4.812 4.812 0 0 0-.72-1.406c-.336-.444-.675-.83-1-1.22 1.256-.815 2.715-1.24 3.97-1.688.12-.452.222-.926.31-1.313zm-9.47 8.438c-.26.394-.583.69-.874 1 .38.286.75.556 1.1.813.336-.303.627-.674.876-.97-.39-.267-.77-.587-1.093-.843z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem-invert.png
new file mode 100644
index 00000000..03989d47
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem-invert.svg
new file mode 100644
index 00000000..5b4cd21c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="italic-arab-meem">
+ <path id="arab-meem" d="M16 9.73l-.93 2.19h-4.663c-.48 0-.857.12-1.135.366l-.06.11c-.185 2.016-.503 3.558-.956 4.627a8.31 8.31 0 0 1-1.082 1.833c-.177.226-.22.186-.126-.12l.142-.503.17-.67.234-.87.002-.008.202-1.045.258-1.41.353-1.907c.19-.312.42-.638.692-.98a24.1 24.1 0 0 1 .94-1.09c.13-.092.697-.18 1.705-.266 1.05-.086 1.64-.183 1.765-.293l.065-.128c.01-.11-.01-.24-.052-.394a2.403 2.403 0 0 0-.232-.522c-.22-.428-.438-.64-.654-.64-.294 0-.915.268-1.864.805-.36.208-.378.125-.05-.247 1.555-1.71 2.705-2.566 3.45-2.566.38 0 .67.13.86.394.134.195.25.6.343 1.21l.202 1.2c.105.586.24.895.408.925"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem.png
new file mode 100644
index 00000000..409a4165
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem.svg
new file mode 100644
index 00000000..f15586e0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-arab-meem.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-arab-meem">
+ <path id="arab-meem" d="M16 9.73l-.93 2.19h-4.663c-.48 0-.857.12-1.135.366l-.06.11c-.185 2.016-.503 3.558-.956 4.627a8.31 8.31 0 0 1-1.082 1.833c-.177.226-.22.186-.126-.12l.142-.503.17-.67.234-.87.002-.008.202-1.045.258-1.41.353-1.907c.19-.312.42-.638.692-.98a24.1 24.1 0 0 1 .94-1.09c.13-.092.697-.18 1.705-.266 1.05-.086 1.64-.183 1.765-.293l.065-.128c.01-.11-.01-.24-.052-.394a2.403 2.403 0 0 0-.232-.522c-.22-.428-.438-.64-.654-.64-.294 0-.915.268-1.864.805-.36.208-.378.125-.05-.247 1.555-1.71 2.705-2.566 3.45-2.566.38 0 .67.13.86.394.134.195.25.6.343 1.21l.202 1.2c.105.586.24.895.408.925"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha-invert.png
new file mode 100644
index 00000000..75dc339d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha-invert.svg
new file mode 100644
index 00000000..44753a9b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="italic-armn-sha">
+ <path id="armn-sha" d="M11.564 7.678a3.073 3.073 0 0 0-.93-.268c-.35-.047-.75-.07-1.197-.07h-1.11L8.587 6h1.723c.558 0 1.042.032 1.45.095.416.063.794.173 1.136.33l4.483 2.033-.33 1.67-2.625-1.165a1.867 1.867 0 0 0-.433-.134 2.45 2.45 0 0 0-.576-.06 4.88 4.88 0 0 0-1.663.28c-.526.19-1 .46-1.427.812-.42.35-.776.78-1.07 1.283a5.48 5.48 0 0 0-.63 1.71c-.24 1.255-.15 2.21.27 2.87.424.65 1.19.976 2.292.976.55 0 1.044-.08 1.48-.236a3.488 3.488 0 0 0 1.135-.66c.325-.29.59-.634.795-1.034.21-.4.363-.84.458-1.322l.11-.56h1.6l-.12.59a5.925 5.925 0 0 1-.676 1.844 5.19 5.19 0 0 1-1.214 1.423c-.488.395-1.053.7-1.694.923a6.573 6.573 0 0 1-2.106.324c-.767 0-1.434-.114-2-.34-.568-.226-1.025-.554-1.372-.985-.347-.437-.573-.97-.678-1.608-.105-.64-.078-1.366.08-2.186.125-.66.346-1.274.66-1.836A6.332 6.332 0 0 1 8.792 9.54a5.955 5.955 0 0 1 1.496-1.072 5.87 5.87 0 0 1 1.732-.57l-.465-.23"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha.png
new file mode 100644
index 00000000..2dd80f7f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha.svg
new file mode 100644
index 00000000..c32ff494
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-armn-sha.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-armn-sha">
+ <path id="armn-sha" d="M11.564 7.678a3.073 3.073 0 0 0-.93-.268c-.35-.047-.75-.07-1.197-.07h-1.11L8.587 6h1.723c.558 0 1.042.032 1.45.095.416.063.794.173 1.136.33l4.483 2.033-.33 1.67-2.625-1.165a1.867 1.867 0 0 0-.433-.134 2.45 2.45 0 0 0-.576-.06 4.88 4.88 0 0 0-1.663.28c-.526.19-1 .46-1.427.812-.42.35-.776.78-1.07 1.283a5.48 5.48 0 0 0-.63 1.71c-.24 1.255-.15 2.21.27 2.87.424.65 1.19.976 2.292.976.55 0 1.044-.08 1.48-.236a3.488 3.488 0 0 0 1.135-.66c.325-.29.59-.634.795-1.034.21-.4.363-.84.458-1.322l.11-.56h1.6l-.12.59a5.925 5.925 0 0 1-.676 1.844 5.19 5.19 0 0 1-1.214 1.423c-.488.395-1.053.7-1.694.923a6.573 6.573 0 0 1-2.106.324c-.767 0-1.434-.114-2-.34-.568-.226-1.025-.554-1.372-.985-.347-.437-.573-.97-.678-1.608-.105-.64-.078-1.366.08-2.186.125-.66.346-1.274.66-1.836A6.332 6.332 0 0 1 8.792 9.54a5.955 5.955 0 0 1 1.496-1.072 5.87 5.87 0 0 1 1.732-.57l-.465-.23"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c-invert.png
new file mode 100644
index 00000000..a1656575
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c-invert.svg
new file mode 100644
index 00000000..467d12df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="italic-c">
+ <path id="c" d="M15.008 13.718l1.48.214c-.467 1.34-1.15 2.354-2.045 3.04a4.835 4.835 0 0 1-3.015 1.03c-1.36 0-2.438-.43-3.237-1.29C7.4 15.85 7 14.618 7 13.012c0-2.09.606-3.817 1.817-5.184C9.897 6.61 11.237 6 12.84 6c1.186 0 2.145.33 2.878.99.738.66 1.165 1.546 1.282 2.66l-1.397.135c-.148-.84-.453-1.464-.916-1.876-.458-.42-1.05-.63-1.78-.63-1.368 0-2.475.63-3.32 1.89-.733 1.087-1.1 2.377-1.1 3.87 0 1.194.283 2.104.848 2.732.565.628 1.3.942 2.206.942.78 0 1.48-.26 2.1-.785.63-.52 1.08-1.26 1.37-2.216"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c.png
new file mode 100644
index 00000000..dc70ded4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c.svg
new file mode 100644
index 00000000..b85eb029
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-c.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-c">
+ <path id="c" d="M15.008 13.718l1.48.214c-.467 1.34-1.15 2.354-2.045 3.04a4.835 4.835 0 0 1-3.015 1.03c-1.36 0-2.438-.43-3.237-1.29C7.4 15.85 7 14.618 7 13.012c0-2.09.606-3.817 1.817-5.184C9.897 6.61 11.237 6 12.84 6c1.186 0 2.145.33 2.878.99.738.66 1.165 1.546 1.282 2.66l-1.397.135c-.148-.84-.453-1.464-.916-1.876-.458-.42-1.05-.63-1.78-.63-1.368 0-2.475.63-3.32 1.89-.733 1.087-1.1 2.377-1.1 3.87 0 1.194.283 2.104.848 2.732.565.628 1.3.942 2.206.942.78 0 1.48-.26 2.1-.785.63-.52 1.08-1.26 1.37-2.216"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d-invert.png
new file mode 100644
index 00000000..b656d1c5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d-invert.svg
new file mode 100644
index 00000000..7774790d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="italic-d">
+ <path id="d" d="M7 18L9.462 6h3.557c.85 0 1.5.063 1.95.188.642.17 1.192.472 1.65.91.454.43.8.97 1.03 1.62.23.65.344 1.378.344 2.186 0 .966-.146 1.847-.436 2.644-.284.79-.66 1.49-1.127 2.095-.46.6-.946 1.072-1.455 1.416-.504.33-1.1.582-1.794.75-.525.122-1.17.19-1.94.19H7m1.86-1.36h1.866c.842 0 1.59-.08 2.245-.24a3.26 3.26 0 0 0 1.05-.436 4.19 4.19 0 0 0 1.04-.975 6.652 6.652 0 0 0 .975-1.825c.247-.687.37-1.467.37-2.34 0-.97-.166-1.716-.5-2.235-.332-.522-.755-.87-1.27-1.04-.38-.124-.974-.186-1.78-.186H11L9.095 16.64"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d.png
new file mode 100644
index 00000000..cd5ac9d4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d.svg
new file mode 100644
index 00000000..dbc1d40f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-d.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-d">
+ <path id="d" d="M7 18L9.462 6h3.557c.85 0 1.5.063 1.95.188.642.17 1.192.472 1.65.91.454.43.8.97 1.03 1.62.23.65.344 1.378.344 2.186 0 .966-.146 1.847-.436 2.644-.284.79-.66 1.49-1.127 2.095-.46.6-.946 1.072-1.455 1.416-.504.33-1.1.582-1.794.75-.525.122-1.17.19-1.94.19H7m1.86-1.36h1.866c.842 0 1.59-.08 2.245-.24a3.26 3.26 0 0 0 1.05-.436 4.19 4.19 0 0 0 1.04-.975 6.652 6.652 0 0 0 .975-1.825c.247-.687.37-1.467.37-2.34 0-.97-.166-1.716-.5-2.235-.332-.522-.755-.87-1.27-1.04-.38-.124-.974-.186-1.78-.186H11L9.095 16.64"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e-invert.png
new file mode 100644
index 00000000..2e0918d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e-invert.svg
new file mode 100644
index 00000000..da226ae0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="italic-e">
+ <path id="e" d="M7 18L9.474 6H18l-.282 1.367H10.77L10.02 11h6.09l-.28 1.367H9.74l-.88 4.273h7.44L16.018 18H7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e.png
new file mode 100644
index 00000000..bb51c22c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e.svg
new file mode 100644
index 00000000..f3851498
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-e.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-e">
+ <path id="e" d="M7 18L9.474 6H18l-.282 1.367H10.77L10.02 11h6.09l-.28 1.367H9.74l-.88 4.273h7.44L16.018 18H7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan-invert.png
new file mode 100644
index 00000000..b0e5b2c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan-invert.svg
new file mode 100644
index 00000000..d8481974
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="italic-geor-kan">
+ <path id="geor-kan" d="M15.057 14.663C14.617 16.888 13.223 18 10.88 18 8.96 18 8 17.213 8 15.64c0-.298.036-.624.108-.977.083-.43.245-.836.488-1.217l1.24.605-.206.62c-.055.26-.083.497-.083.71 0 .97.52 1.46 1.564 1.46 1.31 0 2.108-.724 2.39-2.17l.058-.33a3.17 3.17 0 0 0 .066-.615c0-.927-.546-1.39-1.64-1.39H10.87l.247-1.26h1.118c1.203-.004 1.91-.55 2.12-1.64.04-.18.057-.355.057-.52 0-1.144-.9-1.715-2.696-1.715L11.94 6C14.646 6 16 6.877 16 8.627c0 .248-.027.516-.082.803-.204 1.092-1.05 1.824-2.54 2.194l-.033.166c1.23.2 1.845.823 1.845 1.872 0 .21-.025.433-.074.67l-.058.332"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan.png
new file mode 100644
index 00000000..9750f428
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan.svg
new file mode 100644
index 00000000..9a54880e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-geor-kan.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-geor-kan">
+ <path id="geor-kan" d="M15.057 14.663C14.617 16.888 13.223 18 10.88 18 8.96 18 8 17.213 8 15.64c0-.298.036-.624.108-.977.083-.43.245-.836.488-1.217l1.24.605-.206.62c-.055.26-.083.497-.083.71 0 .97.52 1.46 1.564 1.46 1.31 0 2.108-.724 2.39-2.17l.058-.33a3.17 3.17 0 0 0 .066-.615c0-.927-.546-1.39-1.64-1.39H10.87l.247-1.26h1.118c1.203-.004 1.91-.55 2.12-1.64.04-.18.057-.355.057-.52 0-1.144-.9-1.715-2.696-1.715L11.94 6C14.646 6 16 6.877 16 8.627c0 .248-.027.516-.082.803-.204 1.092-1.05 1.824-2.54 2.194l-.033.166c1.23.2 1.845.823 1.845 1.872 0 .21-.025.433-.074.67l-.058.332"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i-invert.png
new file mode 100644
index 00000000..cc8fee4e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i-invert.svg
new file mode 100644
index 00000000..3b471d27
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="italic-i">
+ <path id="i" d="M12.5 18l.25-.995h-1.5l2.508-10.037h1.5L15.5 6h-5l-.242.968h1.5l-2.51 10.037h-1.5L7.5 18z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i.png
new file mode 100644
index 00000000..a37620b7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i.svg
new file mode 100644
index 00000000..e670e9bf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-i.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-i">
+ <path id="i" d="M12.5 18l.25-.995h-1.5l2.508-10.037h1.5L15.5 6h-5l-.242.968h1.5l-2.51 10.037h-1.5L7.5 18z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k-invert.png
new file mode 100644
index 00000000..5387c369
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k-invert.svg
new file mode 100644
index 00000000..b7190959
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="italic-k">
+ <path id="k" d="M12.018 10.652L17 6h-2l-5.31 5.234L11 6H9.5l-3 12H8l1.173-4.693 1.54-1.438C11 16 14 18 14 18h2s-4-2-3.982-7.348z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k.png
new file mode 100644
index 00000000..9b156fd2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k.svg
new file mode 100644
index 00000000..38bcd73a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-k.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-k">
+ <path id="k" d="M12.018 10.652L17 6h-2l-5.31 5.234L11 6H9.5l-3 12H8l1.173-4.693 1.54-1.438C11 16 14 18 14 18h2s-4-2-3.982-7.348z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s-invert.png
new file mode 100644
index 00000000..42b674e5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s-invert.svg
new file mode 100644
index 00000000..1cfeb7a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="italic-s">
+ <path id="s" d="M16.474 6.59l-.302 1.525a7.36 7.36 0 0 0-1.557-.628 5.432 5.432 0 0 0-1.487-.217c-.935 0-1.68.204-2.23.612-.554.408-.83.95-.83 1.627 0 .37.1.65.302.86.207.19.733.4 1.58.63l.937.23c1.06.274 1.795.622 2.208 1.046.413.42.62 1.007.62 1.766 0 1.167-.46 2.117-1.38 2.85-.913.734-2.12 1.1-3.617 1.1-.615 0-1.232-.06-1.852-.185-.62-.12-1.242-.3-1.867-.55l.31-1.61a7.613 7.613 0 0 0 1.72.805c.58.18 1.155.27 1.73.27.976 0 1.76-.216 2.347-.65.59-.434.883-1 .883-1.697 0-.465-.12-.816-.354-1.054-.233-.242-.737-.46-1.512-.657l-.937-.24c-1.07-.28-1.8-.6-2.19-.964-.39-.368-.584-.88-.584-1.535 0-1.152.442-2.094 1.325-2.828.89-.74 2.043-1.108 3.463-1.108.555 0 1.1.05 1.644.146.542.1 1.085.245 1.627.442"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s.png
new file mode 100644
index 00000000..3213d6d8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s.svg
new file mode 100644
index 00000000..b3fb3403
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/italic-s.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-s">
+ <path id="s" d="M16.474 6.59l-.302 1.525a7.36 7.36 0 0 0-1.557-.628 5.432 5.432 0 0 0-1.487-.217c-.935 0-1.68.204-2.23.612-.554.408-.83.95-.83 1.627 0 .37.1.65.302.86.207.19.733.4 1.58.63l.937.23c1.06.274 1.795.622 2.208 1.046.413.42.62 1.007.62 1.766 0 1.167-.46 2.117-1.38 2.85-.913.734-2.12 1.1-3.617 1.1-.615 0-1.232-.06-1.852-.185-.62-.12-1.242-.3-1.867-.55l.31-1.61a7.613 7.613 0 0 0 1.72.805c.58.18 1.155.27 1.73.27.976 0 1.76-.216 2.347-.65.59-.434.883-1 .883-1.697 0-.465-.12-.816-.354-1.054-.233-.242-.737-.46-1.512-.657l-.937-.24c-1.07-.28-1.8-.6-2.19-.964-.39-.368-.584-.88-.584-1.535 0-1.152.442-2.094 1.325-2.828.89-.74 2.043-1.108 3.463-1.108.555 0 1.1.05 1.644.146.542.1 1.085.245 1.627.442"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr-invert.png
new file mode 100644
index 00000000..7ce988d8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr-invert.svg
new file mode 100644
index 00000000..45b03916
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M16 9V8h-6v1h6zm-2 2v-1h-4v1h4zM6 5h1v16H6V5zm2 0h10v13c0 1.7-1.3 3-3 3H8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr.png
new file mode 100644
index 00000000..f30b5ff3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr.svg
new file mode 100644
index 00000000..c9fa5536
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 9V8h-6v1h6zm-2 2v-1h-4v1h4zM6 5h1v16H6V5zm2 0h10v13c0 1.7-1.3 3-3 3H8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl-invert.png
new file mode 100644
index 00000000..4c30950c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl-invert.svg
new file mode 100644
index 00000000..77cf7574
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M8 9V8h6v1H8zm2 2v-1h4v1h-4zm8-6h-1v16h1V5zm-2 0H6v13c0 1.7 1.3 3 3 3h7V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl.png
new file mode 100644
index 00000000..7826fa80
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl.svg
new file mode 100644
index 00000000..84da9fa6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/journal-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 9V8h6v1H8zm2 2v-1h4v1h-4zm8-6h-1v16h1V5zm-2 0H6v13c0 1.7 1.3 3 3 3h7V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr-invert.png
new file mode 100644
index 00000000..265da142
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr-invert.svg
new file mode 100644
index 00000000..988f38e0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M14.5 4C11.5 4 9 6.5 9 9.5c0 1 .3 1.9.7 2.8L4 18v2h4v-2h2v-2h2l1.2-1.2c.4.1.9.2 1.3.2 3 0 5.5-2.5 5.5-5.5S17.5 4 14.5 4zM16 9c-.8 0-1.5-.7-1.5-1.5S15.2 6 16 6s1.5.7 1.5 1.5S16.8 9 16 9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr.png
new file mode 100644
index 00000000..9a4dca83
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr.svg
new file mode 100644
index 00000000..fc0d3c34
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14.5 4C11.5 4 9 6.5 9 9.5c0 1 .3 1.9.7 2.8L4 18v2h4v-2h2v-2h2l1.2-1.2c.4.1.9.2 1.3.2 3 0 5.5-2.5 5.5-5.5S17.5 4 14.5 4zM16 9c-.8 0-1.5-.7-1.5-1.5S15.2 6 16 6s1.5.7 1.5 1.5S16.8 9 16 9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl-invert.png
new file mode 100644
index 00000000..a5f29046
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl-invert.svg
new file mode 100644
index 00000000..7ca2f8f4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M9.5 4c3 0 5.5 2.5 5.5 5.5 0 1-.3 1.9-.7 2.8L20 18v2h-4v-2h-2v-2h-2l-1.2-1.2c-.4.1-.9.2-1.3.2-3 0-5.5-2.5-5.5-5.5S6.5 4 9.5 4zM8 9c.8 0 1.5-.7 1.5-1.5S8.8 6 8 6s-1.5.7-1.5 1.5S7.2 9 8 9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl.png
new file mode 100644
index 00000000..f49e1125
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl.svg
new file mode 100644
index 00000000..6dedfe83
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/key-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9.5 4c3 0 5.5 2.5 5.5 5.5 0 1-.3 1.9-.7 2.8L20 18v2h-4v-2h-2v-2h-2l-1.2-1.2c-.4.1-.9.2-1.3.2-3 0-5.5-2.5-5.5-5.5S6.5 4 9.5 4zM8 9c.8 0 1.5-.7 1.5-1.5S8.8 6 8 6s-1.5.7-1.5 1.5S7.2 9 8 9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr-invert.png
new file mode 100644
index 00000000..d7d1a0be
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr-invert.svg
new file mode 100644
index 00000000..b9cbad02
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M3 7v9c0 1.7 1.3 3 3 3h15V7H3zm8 2h2v2h-2V9zm0 3h2v2h-2v-2zM8 9h2v2H8V9zm0 3h2v2H8v-2zm-1 5H6c-.6 0-1-.4-1-1v-1h2v2zm0-3H5v-2h2v2zm0-3H5V9h2v2zm9 6H8v-2h8v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2zm3 6h-2v-2h2v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr.png
new file mode 100644
index 00000000..886d37a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr.svg
new file mode 100644
index 00000000..c4c442ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 7v9c0 1.7 1.3 3 3 3h15V7H3zm8 2h2v2h-2V9zm0 3h2v2h-2v-2zM8 9h2v2H8V9zm0 3h2v2H8v-2zm-1 5H6c-.6 0-1-.4-1-1v-1h2v2zm0-3H5v-2h2v2zm0-3H5V9h2v2zm9 6H8v-2h8v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2zm3 6h-2v-2h2v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl-invert.png
new file mode 100644
index 00000000..1b0275e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl-invert.svg
new file mode 100644
index 00000000..d235a35f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M21 7v9c0 1.7-1.3 3-3 3H3V7h18zm-8 2h-2v2h2V9zm0 3h-2v2h2v-2zm3-3h-2v2h2V9zm0 3h-2v2h2v-2zm1 5h1c.6 0 1-.4 1-1v-1h-2v2zm0-3h2v-2h-2v2zm0-3h2V9h-2v2zm-9 6h8v-2H8v2zm0-3h2v-2H8v2zm0-3h2V9H8v2zm-3 6h2v-2H5v2zm0-3h2v-2H5v2zm0-3h2V9H5v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl.png
new file mode 100644
index 00000000..790a5e2d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl.svg
new file mode 100644
index 00000000..b37d7f4c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/keyboard-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 7v9c0 1.7-1.3 3-3 3H3V7h18zm-8 2h-2v2h2V9zm0 3h-2v2h2v-2zm3-3h-2v2h2V9zm0 3h-2v2h2v-2zm1 5h1c.6 0 1-.4 1-1v-1h-2v2zm0-3h2v-2h-2v2zm0-3h2V9h-2v2zm-9 6h8v-2H8v2zm0-3h2v-2H8v2zm0-3h2V9H8v2zm-3 6h2v-2H5v2zm0-3h2v-2H5v2zm0-3h2V9H5v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr-invert.png
new file mode 100644
index 00000000..d9ac3481
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr-invert.svg
new file mode 100644
index 00000000..429ee294
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr-invert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="A">
+ <path d="M18.738 15.673l1.137 3.15h1.575L17.775 7.448h-2.188l-3.85 11.375h1.575l1.05-3.15h4.375zM16.55 8.76l1.837 5.427h-3.675l1.838-5.425z"/>
+ </g>
+ <g id="文">
+ <path d="M8.325 6.573h.787l-.875-1.75h-1.75l.438.875a1.56 1.56 0 0 0 1.4.875z"/>
+ <path d="m 9.202,12.874 c 0.7,0.525 1.486,0.963 2.45,1.225 l -0.438,1.31 A 9.17,9.17 0 0 1 8.151,13.835 c -1.49,1.137 -3.063,1.837 -4.813,2.363 L 2.9,14.885 C 4.386,14.36 5.874,13.835 7.1,12.872 5.962,11.648 5.174,10.335 4.65,8.758 l -1.663,0 0,-1.31 10.85,0 -0.438,1.312 -1.75,0 c -0.308,1.33 -1.255,2.957 -2.45,4.114 z m 1.05,-4.114 -4.114,0 c 0.35,1.226 1.138,2.363 2.013,3.238 0.926,-1 1.617,-1.957 2.1,-3.237 z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr.png
new file mode 100644
index 00000000..f7b785c9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr.svg
new file mode 100644
index 00000000..d64b7343
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-ltr.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="A">
+ <path d="M18.738 15.673l1.137 3.15h1.575L17.775 7.448h-2.188l-3.85 11.375h1.575l1.05-3.15h4.375zM16.55 8.76l1.837 5.427h-3.675l1.838-5.425z"/>
+ </g>
+ <g id="文">
+ <path d="M8.325 6.573h.787l-.875-1.75h-1.75l.438.875a1.56 1.56 0 0 0 1.4.875z"/>
+ <path d="m 9.202,12.874 c 0.7,0.525 1.486,0.963 2.45,1.225 l -0.438,1.31 A 9.17,9.17 0 0 1 8.151,13.835 c -1.49,1.137 -3.063,1.837 -4.813,2.363 L 2.9,14.885 C 4.386,14.36 5.874,13.835 7.1,12.872 5.962,11.648 5.174,10.335 4.65,8.758 l -1.663,0 0,-1.31 10.85,0 -0.438,1.312 -1.75,0 c -0.308,1.33 -1.255,2.957 -2.45,4.114 z m 1.05,-4.114 -4.114,0 c 0.35,1.226 1.138,2.363 2.013,3.238 0.926,-1 1.617,-1.957 2.1,-3.237 z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl-invert.png
new file mode 100644
index 00000000..80dad942
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl-invert.svg
new file mode 100644
index 00000000..f3c32ebf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl-invert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="A">
+ <path d="M5.612 15.673l-1.137 3.15H2.9L6.575 7.448h2.188l3.85 11.375h-1.575l-1.05-3.15H5.613zM7.8 8.76l-1.837 5.427h3.675L7.8 8.762z" id="path5"/>
+ </g>
+ <g id="文">
+ <path d="M16.384 6.573h.787l-.873-1.75h-1.75l.438.875c.26.535.805.874 1.4.875z" id="path7"/>
+ <path d="M15.15 12.874c-.7.525-1.486.963-2.45 1.225l.438 1.31a9.17 9.17 0 0 0 3.063-1.575c1.49 1.137 3.064 1.837 4.814 2.363l.438-1.313c-1.486-.525-2.974-1.05-4.2-2.013 1.138-1.224 1.926-2.537 2.45-4.114h1.663v-1.31h-10.85l.438 1.312h1.75c.308 1.33 1.255 2.957 2.45 4.114zM14.1 8.76h4.114c-.35 1.226-1.138 2.363-2.013 3.238-.925-1-1.616-1.957-2.1-3.237z" id="path11-7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl.png
new file mode 100644
index 00000000..c78f2cd6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl.svg
new file mode 100644
index 00000000..cf6c1d51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/language-rtl.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="A">
+ <path d="M5.612 15.673l-1.137 3.15H2.9L6.575 7.448h2.188l3.85 11.375h-1.575l-1.05-3.15H5.613zM7.8 8.76l-1.837 5.427h3.675L7.8 8.762z" id="path5"/>
+ </g>
+ <g id="文">
+ <path d="M16.384 6.573h.787l-.873-1.75h-1.75l.438.875c.26.535.805.874 1.4.875z" id="path7"/>
+ <path d="M15.15 12.874c-.7.525-1.486.963-2.45 1.225l.438 1.31a9.17 9.17 0 0 0 3.063-1.575c1.49 1.137 3.064 1.837 4.814 2.363l.438-1.313c-1.486-.525-2.974-1.05-4.2-2.013 1.138-1.224 1.926-2.537 2.45-4.114h1.663v-1.31h-10.85l.438 1.312h1.75c.308 1.33 1.255 2.957 2.45 4.114zM14.1 8.76h4.114c-.35 1.226-1.138 2.363-2.013 3.238-.925-1-1.616-1.957-2.1-3.237z" id="path11-7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr-invert.png
new file mode 100644
index 00000000..264811bc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr-invert.svg
new file mode 100644
index 00000000..f6e3d8ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M20.8 20h-8.1v-.8c.4 0 .8-.1 1.3-.2s.8-.2.8-.4v-.2c0-.1 0-.2-.1-.3L13.4 15H8.3c-.1.3-.2.6-.4 1-.1.4-.3.7-.4 1-.1.4-.2.7-.2.8v.4c0 .2.2.4.5.6.3.2.9.3 1.7.3v.9H3.4v-.8c.2 0 .5-.1.8-.1.3-.1.5-.1.7-.2.3-.2.5-.4.7-.6.2-.3.4-.6.5-.9.8-2 1.6-3.9 2.4-5.9.8-2 1.7-4.1 2.7-6.5h2.1c1.4 3.3 2.4 6 3.2 7.9.8 1.9 1.4 3.6 2 4.8l.3.6c.1.2.3.3.6.5.2.1.4.2.7.3.3.1.5.1.7.1v.8zM13 14l-2.1-5.3L8.8 14H13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr.png
new file mode 100644
index 00000000..4b6d298f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr.svg
new file mode 100644
index 00000000..4b01d742
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20.8 20h-8.1v-.8c.4 0 .8-.1 1.3-.2s.8-.2.8-.4v-.2c0-.1 0-.2-.1-.3L13.4 15H8.3c-.1.3-.2.6-.4 1-.1.4-.3.7-.4 1-.1.4-.2.7-.2.8v.4c0 .2.2.4.5.6.3.2.9.3 1.7.3v.9H3.4v-.8c.2 0 .5-.1.8-.1.3-.1.5-.1.7-.2.3-.2.5-.4.7-.6.2-.3.4-.6.5-.9.8-2 1.6-3.9 2.4-5.9.8-2 1.7-4.1 2.7-6.5h2.1c1.4 3.3 2.4 6 3.2 7.9.8 1.9 1.4 3.6 2 4.8l.3.6c.1.2.3.3.6.5.2.1.4.2.7.3.3.1.5.1.7.1v.8zM13 14l-2.1-5.3L8.8 14H13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl-invert.png
new file mode 100644
index 00000000..264811bc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl-invert.svg
new file mode 100644
index 00000000..f6e3d8ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M20.8 20h-8.1v-.8c.4 0 .8-.1 1.3-.2s.8-.2.8-.4v-.2c0-.1 0-.2-.1-.3L13.4 15H8.3c-.1.3-.2.6-.4 1-.1.4-.3.7-.4 1-.1.4-.2.7-.2.8v.4c0 .2.2.4.5.6.3.2.9.3 1.7.3v.9H3.4v-.8c.2 0 .5-.1.8-.1.3-.1.5-.1.7-.2.3-.2.5-.4.7-.6.2-.3.4-.6.5-.9.8-2 1.6-3.9 2.4-5.9.8-2 1.7-4.1 2.7-6.5h2.1c1.4 3.3 2.4 6 3.2 7.9.8 1.9 1.4 3.6 2 4.8l.3.6c.1.2.3.3.6.5.2.1.4.2.7.3.3.1.5.1.7.1v.8zM13 14l-2.1-5.3L8.8 14H13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl.png
new file mode 100644
index 00000000..4b6d298f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl.svg
new file mode 100644
index 00000000..4b01d742
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/largerText-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20.8 20h-8.1v-.8c.4 0 .8-.1 1.3-.2s.8-.2.8-.4v-.2c0-.1 0-.2-.1-.3L13.4 15H8.3c-.1.3-.2.6-.4 1-.1.4-.3.7-.4 1-.1.4-.2.7-.2.8v.4c0 .2.2.4.5.6.3.2.9.3 1.7.3v.9H3.4v-.8c.2 0 .5-.1.8-.1.3-.1.5-.1.7-.2.3-.2.5-.4.7-.6.2-.3.4-.6.5-.9.8-2 1.6-3.9 2.4-5.9.8-2 1.7-4.1 2.7-6.5h2.1c1.4 3.3 2.4 6 3.2 7.9.8 1.9 1.4 3.6 2 4.8l.3.6c.1.2.3.3.6.5.2.1.4.2.7.3.3.1.5.1.7.1v.8zM13 14l-2.1-5.3L8.8 14H13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr-invert.png
new file mode 100644
index 00000000..68f2452c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr-invert.svg
new file mode 100644
index 00000000..36a81654
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="layout-ltr">
+ <path id="text" d="M5 19V5h6v8h8v6H5z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm5 5h-4V6h4v4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr.png
new file mode 100644
index 00000000..ea6d2f5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr.svg
new file mode 100644
index 00000000..c3be66cc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="layout-ltr">
+ <path id="text" d="M5 19V5h6v8h8v6H5z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm5 5h-4V6h4v4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl-invert.png
new file mode 100644
index 00000000..1ef7734d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl-invert.svg
new file mode 100644
index 00000000..39ba9c46
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="layout-rtl">
+ <path id="text" d="M5 19v-6h8V5h6v14H5z"/>
+ <path id="float" d="M5 5v6h6V5H5zm1 1h4v4H6V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl.png
new file mode 100644
index 00000000..46bf59b1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl.svg
new file mode 100644
index 00000000..ce7feb8d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/layout-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="layout-rtl">
+ <path id="text" d="M5 19v-6h8V5h6v14H5z"/>
+ <path id="float" d="M5 5v6h6V5H5zm1 1h4v4H6V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr-invert.png
new file mode 100644
index 00000000..7c9195e7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr-invert.svg
new file mode 100644
index 00000000..5bee6d51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M15.387 4.33c-2.1 0-3.6 1.9-5.1 3.3.2 0 .5-.1.8-.1.5 0 1 .1 1.5.3.8-.8 1.6-1.7 2.8-1.7.6 0 1.3.3 1.8.7 1 1 1 2.6 0 3.6l-2.6 2.6c-.4.4-1.2.7-1.8.7-1.4 0-2.1-.9-2.6-2l-1.3 1.3c.8 1.5 2 2.6 3.8 2.6 1.2 0 2.3-.5 3-1.3l2.6-2.6c.9-.9 1.5-2 1.5-3.3-.2-2.2-2.2-4.1-4.4-4.1zm-4.3 12.1l-.9.9c-.4.4-1.2.7-1.8.7-.6 0-1.3-.3-1.8-.7-1-1-1-2.7 0-3.6l2.6-2.6c.4-.4 1.2-.7 1.8-.7 1.4 0 2.1 1 2.6 2l1.3-1.3c-.8-1.5-2-2.6-3.8-2.6-1.2 0-2.3.5-3 1.3l-2.6 2.6c-1.7 1.7-1.7 4.4 0 6 1.6 1.6 4.4 1.7 5.9 0l1.9-1.9c-.3.1-.6.1-.9.1-.5 0-.9 0-1.3-.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr.png
new file mode 100644
index 00000000..617d3257
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr.svg
new file mode 100644
index 00000000..aaaee540
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15.387 4.33c-2.1 0-3.6 1.9-5.1 3.3.2 0 .5-.1.8-.1.5 0 1 .1 1.5.3.8-.8 1.6-1.7 2.8-1.7.6 0 1.3.3 1.8.7 1 1 1 2.6 0 3.6l-2.6 2.6c-.4.4-1.2.7-1.8.7-1.4 0-2.1-.9-2.6-2l-1.3 1.3c.8 1.5 2 2.6 3.8 2.6 1.2 0 2.3-.5 3-1.3l2.6-2.6c.9-.9 1.5-2 1.5-3.3-.2-2.2-2.2-4.1-4.4-4.1zm-4.3 12.1l-.9.9c-.4.4-1.2.7-1.8.7-.6 0-1.3-.3-1.8-.7-1-1-1-2.7 0-3.6l2.6-2.6c.4-.4 1.2-.7 1.8-.7 1.4 0 2.1 1 2.6 2l1.3-1.3c-.8-1.5-2-2.6-3.8-2.6-1.2 0-2.3.5-3 1.3l-2.6 2.6c-1.7 1.7-1.7 4.4 0 6 1.6 1.6 4.4 1.7 5.9 0l1.9-1.9c-.3.1-.6.1-.9.1-.5 0-.9 0-1.3-.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl-invert.png
new file mode 100644
index 00000000..ece611a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl-invert.svg
new file mode 100644
index 00000000..8e343611
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M9.025 3.6c2.1 0 3.6 1.9 5.1 3.3-.2 0-.5-.1-.8-.1-.5 0-1 .1-1.5.3-.8-.8-1.6-1.7-2.8-1.7-.6 0-1.3.3-1.8.7-1 1-1 2.6 0 3.6l2.6 2.6c.4.4 1.2.7 1.8.7 1.4 0 2.1-.9 2.6-2l1.3 1.3c-.8 1.5-2 2.6-3.8 2.6-1.2 0-2.3-.5-3-1.3l-2.6-2.6c-.9-.9-1.5-2-1.5-3.3.2-2.2 2.2-4.1 4.4-4.1zm4.3 12.1l.9.9c.4.4 1.2.7 1.8.7.6 0 1.3-.3 1.8-.7 1-1 1-2.7 0-3.6l-2.6-2.6c-.4-.4-1.2-.7-1.8-.7-1.4 0-2.1 1-2.6 2l-1.3-1.3c.8-1.5 2-2.6 3.8-2.6 1.2 0 2.3.5 3 1.3l2.6 2.6c1.7 1.7 1.7 4.4 0 6-1.6 1.6-4.4 1.7-5.9 0l-1.9-1.9c.3.1.6.1.9.1.5 0 .9 0 1.3-.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl.png
new file mode 100644
index 00000000..ef484134
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl.svg
new file mode 100644
index 00000000..82a8e634
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/link-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9.025 3.6c2.1 0 3.6 1.9 5.1 3.3-.2 0-.5-.1-.8-.1-.5 0-1 .1-1.5.3-.8-.8-1.6-1.7-2.8-1.7-.6 0-1.3.3-1.8.7-1 1-1 2.6 0 3.6l2.6 2.6c.4.4 1.2.7 1.8.7 1.4 0 2.1-.9 2.6-2l1.3 1.3c-.8 1.5-2 2.6-3.8 2.6-1.2 0-2.3-.5-3-1.3l-2.6-2.6c-.9-.9-1.5-2-1.5-3.3.2-2.2 2.2-4.1 4.4-4.1zm4.3 12.1l.9.9c.4.4 1.2.7 1.8.7.6 0 1.3-.3 1.8-.7 1-1 1-2.7 0-3.6l-2.6-2.6c-.4-.4-1.2-.7-1.8-.7-1.4 0-2.1 1-2.6 2l-1.3-1.3c.8-1.5 2-2.6 3.8-2.6 1.2 0 2.3.5 3 1.3l2.6 2.6c1.7 1.7 1.7 4.4 0 6-1.6 1.6-4.4 1.7-5.9 0l-1.9-1.9c.3.1.6.1.9.1.5 0 .9 0 1.3-.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr-invert.png
new file mode 100644
index 00000000..05d41809
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr-invert.svg
new file mode 100644
index 00000000..2eb53290
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M21 7H9V5h12v2zM7 6c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm14 7H9v-2h12v2zM7 12c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm14 7H9v-2h12v2zM7 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr.png
new file mode 100644
index 00000000..7796dd15
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr.svg
new file mode 100644
index 00000000..5f0b15f8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 7H9V5h12v2zM7 6c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm14 7H9v-2h12v2zM7 12c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm14 7H9v-2h12v2zM7 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl-invert.png
new file mode 100644
index 00000000..6aeed4c8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl-invert.svg
new file mode 100644
index 00000000..dcce2aee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M3 7h12V5H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2zM3 13h12v-2H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2zM3 19h12v-2H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl.png
new file mode 100644
index 00000000..2c727b17
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl.svg
new file mode 100644
index 00000000..c9c94ebf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listBullet-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 7h12V5H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2zM3 13h12v-2H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2zM3 19h12v-2H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr-invert.png
new file mode 100644
index 00000000..208c7268
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr-invert.svg
new file mode 100644
index 00000000..1ab3f232
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M21 7H8V5h13v2zm0 6H8v-2h13v2zm0 6H8v-2h13v2zM4 4h2v4H5V5H4zm-1 6V9h3v3H4v1h2v1H3v-3h2v-1zm3 10H3v-1h2v-1H4v-1h1v-1H3v-1h3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr.png
new file mode 100644
index 00000000..c2d28dc8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr.svg
new file mode 100644
index 00000000..8e849a76
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 7H8V5h13v2zm0 6H8v-2h13v2zm0 6H8v-2h13v2zM4 4h2v4H5V5H4zm-1 6V9h3v3H4v1h2v1H3v-3h2v-1zm3 10H3v-1h2v-1H4v-1h1v-1H3v-1h3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl-invert.png
new file mode 100644
index 00000000..58be38a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl-invert.svg
new file mode 100644
index 00000000..ab12c83d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M3 7h13V5H3zm0 6h13v-2H3zm0 6h13v-2H3zM18 4h2v4h-1V5h-1zm0 6V9h3v3h-2v1h2v1h-3v-3h2v-1zm3 10h-3v-1h2v-1h-1v-1h1v-1h-2v-1h3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl.png
new file mode 100644
index 00000000..b0bd9598
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl.svg
new file mode 100644
index 00000000..9ec48012
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/listNumbered-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 7h13V5H3zm0 6h13v-2H3zm0 6h13v-2H3zM18 4h2v4h-1V5h-1zm0 6V9h3v3h-2v1h2v1h-3v-3h2v-1zm3 10h-3v-1h2v-1h-1v-1h1v-1h-2v-1h3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.png
new file mode 100644
index 00000000..9c3c9488
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.svg
new file mode 100644
index 00000000..e0c482ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d11d13 }</style>
+ <path d="M15 8s0-3-2.5-3S10 8 10 8v1h5zm2 0v1h2v10H9c-1.7 0-3-1.3-3-3V9h2V8s0-5 4.5-5S17 8 17 8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-invert.png
new file mode 100644
index 00000000..a81a2a17
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-invert.svg
new file mode 100644
index 00000000..ee341a93
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M15 8s0-3-2.5-3S10 8 10 8v1h5zm2 0v1h2v10H9c-1.7 0-3-1.3-3-3V9h2V8s0-5 4.5-5S17 8 17 8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr.png
new file mode 100644
index 00000000..a87541f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr.svg
new file mode 100644
index 00000000..a18b2c46
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 8s0-3-2.5-3S10 8 10 8v1h5zm2 0v1h2v10H9c-1.7 0-3-1.3-3-3V9h2V8s0-5 4.5-5S17 8 17 8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.png
new file mode 100644
index 00000000..53ca51a5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.svg
new file mode 100644
index 00000000..edc93128
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d11d13 }</style>
+ <path d="M10 8s0-3 2.5-3S15 8 15 8v1h-5zM8 8v1H6v10h10c1.7 0 3-1.3 3-3V9h-2V8s0-5-4.5-5S8 8 8 8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-invert.png
new file mode 100644
index 00000000..ab62257a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-invert.svg
new file mode 100644
index 00000000..2f8851cb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M10 8s0-3 2.5-3S15 8 15 8v1h-5zM8 8v1H6v10h10c1.7 0 3-1.3 3-3V9h-2V8s0-5-4.5-5S8 8 8 8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl.png
new file mode 100644
index 00000000..55f2d224
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl.svg
new file mode 100644
index 00000000..6c4a3c51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/lock-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10 8s0-3 2.5-3S15 8 15 8v1h-5zM8 8v1H6v10h10c1.7 0 3-1.3 3-3V9h-2V8s0-5-4.5-5S8 8 8 8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr-invert.png
new file mode 100644
index 00000000..fb1bb0c9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr-invert.svg
new file mode 100644
index 00000000..f81d7c47
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M15 14v3l5-4.5L15 8v3H8c0 1.7 1.3 3 3 3h4zm-1-9H4v15h10v-2H6V7h8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr.png
new file mode 100644
index 00000000..18f82eb8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr.svg
new file mode 100644
index 00000000..f2be068b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 14v3l5-4.5L15 8v3H8c0 1.7 1.3 3 3 3h4zm-1-9H4v15h10v-2H6V7h8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl-invert.png
new file mode 100644
index 00000000..dcd2f15e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl-invert.svg
new file mode 100644
index 00000000..d3fae895
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M9 14v3l-5-4.5L9 8v3h7c0 1.7-1.3 3-3 3H9zm1-9h10v15H10v-2h8V7h-8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl.png
new file mode 100644
index 00000000..0ffb7235
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl.svg
new file mode 100644
index 00000000..5f5ebb90
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logOut-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 14v3l-5-4.5L9 8v3h7c0 1.7-1.3 3-3 3H9zm1-9h10v15H10v-2h8V7h-8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc-invert.png
new file mode 100644
index 00000000..7f04a806
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc-invert.svg
new file mode 100644
index 00000000..48eafd4e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 6c-3.9 0-7 3.1-7 7s3.1 7 7 7 7-3.1 7-7-3.1-7-7-7zm0 13c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6zm-1.7-4.6c-.7 0-1-.4-1-1.2s.3-1.2 1-1.2c.4 0 .6.2.8.6l.9-.5c-.4-.7-1-1-1.9-1-.6 0-1.1.2-1.5.6s-.6.8-.6 1.5.2 1.2.6 1.6c.4.4.9.6 1.5.6.8 0 1.4-.4 1.9-1.1l-.9-.4c-.2.3-.5.5-.8.5zm4 0c-.7 0-1-.4-1-1.2s.3-1.2 1-1.2c.4 0 .6.2.8.6l.9-.5c-.4-.7-1-1-1.9-1-.6 0-1.1.2-1.5.6s-.6.8-.6 1.5.2 1.2.6 1.6c.4.4.9.6 1.5.6.8 0 1.4-.4 1.9-1.1l-.9-.4c-.2.3-.5.5-.8.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc.png
new file mode 100644
index 00000000..80ef2a62
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc.svg
new file mode 100644
index 00000000..00af35db
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-cc.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 6c-3.9 0-7 3.1-7 7s3.1 7 7 7 7-3.1 7-7-3.1-7-7-7zm0 13c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6zm-1.7-4.6c-.7 0-1-.4-1-1.2s.3-1.2 1-1.2c.4 0 .6.2.8.6l.9-.5c-.4-.7-1-1-1.9-1-.6 0-1.1.2-1.5.6s-.6.8-.6 1.5.2 1.2.6 1.6c.4.4.9.6 1.5.6.8 0 1.4-.4 1.9-1.1l-.9-.4c-.2.3-.5.5-.8.5zm4 0c-.7 0-1-.4-1-1.2s.3-1.2 1-1.2c.4 0 .6.2.8.6l.9-.5c-.4-.7-1-1-1.9-1-.6 0-1.1.2-1.5.6s-.6.8-.6 1.5.2 1.2.6 1.6c.4.4.9.6 1.5.6.8 0 1.4-.4 1.9-1.1l-.9-.4c-.2.3-.5.5-.8.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons-invert.png
new file mode 100644
index 00000000..0f8d9a62
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons-invert.svg
new file mode 100644
index 00000000..4794f331
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M15.4 7.8c-2-.9-2.3-2.5-2.4-2.8.1.1 2 1 2 1l-3-5-3 5 2-1s0 .8.6 2.1c.8 1.5 2.2 2.2 2.2 2.2s1.6.7 2.2 1.3l-.7.7-.5-.5-.4 1.8 1.8-.4-.5-.5.7-.7c.9 1 1.5 2.3 1.6 3.8h-1V14l-1.5 1 1.5 1v-.8h1c-.1 1.5-.6 2.8-1.6 3.8l-.7-.7.5-.5-1.8-.4.4 1.8.5-.5.7.7c-1 .9-2.3 1.5-3.8 1.6v-1h.8l-1-1.5-1 1.5h.8v1c-1.5-.1-2.8-.6-3.8-1.6l.7-.7.5.5.4-1.8-1.8.4.5.5-.7.7c-.9-1-1.5-2.3-1.6-3.8h1v.8l1.5-1L7 14v.8H6c.1-1.5.6-2.8 1.6-3.8l.7.7-.5.5 1.8.4-.4-1.8-.5.5-.7-.7-1.5-1.4A7.99 7.99 0 0 0 4 15c0 4.4 3.6 8 8 8s8-3.6 8-8c0-3.2-1.9-5.9-4.6-7.2z"/>
+ <circle cx="12" cy="15" r="3"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons.png
new file mode 100644
index 00000000..c41c2470
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons.svg
new file mode 100644
index 00000000..f2492ce1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikimediaCommons.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15.4 7.8c-2-.9-2.3-2.5-2.4-2.8.1.1 2 1 2 1l-3-5-3 5 2-1s0 .8.6 2.1c.8 1.5 2.2 2.2 2.2 2.2s1.6.7 2.2 1.3l-.7.7-.5-.5-.4 1.8 1.8-.4-.5-.5.7-.7c.9 1 1.5 2.3 1.6 3.8h-1V14l-1.5 1 1.5 1v-.8h1c-.1 1.5-.6 2.8-1.6 3.8l-.7-.7.5-.5-1.8-.4.4 1.8.5-.5.7.7c-1 .9-2.3 1.5-3.8 1.6v-1h.8l-1-1.5-1 1.5h.8v1c-1.5-.1-2.8-.6-3.8-1.6l.7-.7.5.5.4-1.8-1.8.4.5.5-.7.7c-.9-1-1.5-2.3-1.6-3.8h1v.8l1.5-1L7 14v.8H6c.1-1.5.6-2.8 1.6-3.8l.7.7-.5.5 1.8.4-.4-1.8-.5.5-.7-.7-1.5-1.4A7.99 7.99 0 0 0 4 15c0 4.4 3.6 8 8 8s8-3.6 8-8c0-3.2-1.9-5.9-4.6-7.2z"/>
+ <circle cx="12" cy="15" r="3"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia-invert.png
new file mode 100644
index 00000000..9d576d08
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia-invert.svg
new file mode 100644
index 00000000..1fe32773
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M22.3 6.3c0 .2 0 .3-.1.3-.7.1-1.2.5-1.6 1.1-.1.2-.2.4-.3.7l-4.6 10.1c-.1.2-.2.3-.2.3s-.1.1-.2.1c-.2 0-.4-.1-.5-.4L12.2 13l-2.8 5.5c-.1.3-.3.4-.5.4s-.4-.1-.5-.4L4.1 8.4c-.3-.8-.6-1.2-.8-1.4-.2-.2-.5-.3-1-.4-.1-.1-.1-.2-.1-.3 0-.2 0-.3.1-.3h4.3c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.6.1-1 .2-1.1.4-.1.2 0 .6.3 1.2l3.6 8.2h.1l2.2-4.4L10 8.4c-.3-.7-.6-1.2-.8-1.4s-.5-.3-.9-.4c-.1-.1-.1-.2-.1-.3 0-.2 0-.3.1-.3h3.6c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.4.1-.6.2-.6.4s.1.6.4 1.2l1 1.9 1-1.9c.3-.6.5-.9.5-1.1 0-.2 0-.3-.1-.4-.1-.1-.3-.1-.5-.1l-.1-.3c0-.2 0-.3.1-.3h3c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.5.1-.8.2-1.1.5-.3.3-.6.7-.8 1.3l-1.3 2.8 2.5 5.2h.1l3.7-8.1c.3-.5.3-.9.2-1.2-.1-.3-.5-.4-1.1-.5-.1-.1-.1-.2-.1-.3s0-.3.1-.3h3.7c-.2.1-.2.2-.2.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia.png
new file mode 100644
index 00000000..f1d8330f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia.svg
new file mode 100644
index 00000000..9208f3b6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/logo-wikipedia.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M22.3 6.3c0 .2 0 .3-.1.3-.7.1-1.2.5-1.6 1.1-.1.2-.2.4-.3.7l-4.6 10.1c-.1.2-.2.3-.2.3s-.1.1-.2.1c-.2 0-.4-.1-.5-.4L12.2 13l-2.8 5.5c-.1.3-.3.4-.5.4s-.4-.1-.5-.4L4.1 8.4c-.3-.8-.6-1.2-.8-1.4-.2-.2-.5-.3-1-.4-.1-.1-.1-.2-.1-.3 0-.2 0-.3.1-.3h4.3c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.6.1-1 .2-1.1.4-.1.2 0 .6.3 1.2l3.6 8.2h.1l2.2-4.4L10 8.4c-.3-.7-.6-1.2-.8-1.4s-.5-.3-.9-.4c-.1-.1-.1-.2-.1-.3 0-.2 0-.3.1-.3h3.6c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.4.1-.6.2-.6.4s.1.6.4 1.2l1 1.9 1-1.9c.3-.6.5-.9.5-1.1 0-.2 0-.3-.1-.4-.1-.1-.3-.1-.5-.1l-.1-.3c0-.2 0-.3.1-.3h3c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.5.1-.8.2-1.1.5-.3.3-.6.7-.8 1.3l-1.3 2.8 2.5 5.2h.1l3.7-8.1c.3-.5.3-.9.2-1.2-.1-.3-.5-.4-1.1-.5-.1-.1-.1-.2-.1-.3s0-.3.1-.3h3.7c-.2.1-.2.2-.2.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr-invert.png
new file mode 100644
index 00000000..6e0cd017
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr-invert.svg
new file mode 100644
index 00000000..2d6d0a0b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M15 6L9 4 3 6v15l6-2 6 2 6-2V4l-6 2zM8.7 18.1L4 19.6V6.7L9 5v12.9l-.3.2zm11.3.2L15 20V7.1l.3-.1L20 5.4v12.9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr.png
new file mode 100644
index 00000000..43a97d29
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr.svg
new file mode 100644
index 00000000..0e5a52e4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 6L9 4 3 6v15l6-2 6 2 6-2V4l-6 2zM8.7 18.1L4 19.6V6.7L9 5v12.9l-.3.2zm11.3.2L15 20V7.1l.3-.1L20 5.4v12.9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl-invert.png
new file mode 100644
index 00000000..4993f575
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl-invert.svg
new file mode 100644
index 00000000..00d3efc2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M9 6l6-2 6 2v15l-6-2-6 2-6-2V4l6 2zm6.3 12.1l4.7 1.5V6.7L15 5v12.9l.3.2zM4 18.3L9 20V7.1L8.7 7 4 5.4v12.9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl.png
new file mode 100644
index 00000000..36e9cad9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl.svg
new file mode 100644
index 00000000..835781d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/map-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 6l6-2 6 2v15l-6-2-6 2-6-2V4l6 2zm6.3 12.1l4.7 1.5V6.7L15 5v12.9l.3.2zM4 18.3L9 20V7.1L8.7 7 4 5.4v12.9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.png
new file mode 100644
index 00000000..55a68db7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.svg
new file mode 100644
index 00000000..dc9791e3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M19 12c0-3.9-3.1-7-7-7s-7 3.1-7 7c0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7zm-7 4c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.png
new file mode 100644
index 00000000..536e77c8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.svg
new file mode 100644
index 00000000..f1fa246a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPin.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19 12c0-3.9-3.1-7-7-7s-7 3.1-7 7c0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7zm-7 4c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.png
new file mode 100644
index 00000000..607354cf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.svg
new file mode 100644
index 00000000..68fe22ae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M24 4h-4V0h-2v4h-4v2h4v4h2V6h4z"/>
+ <path d="M18 11h-1V7.1l-.1-.1H13V5.1c-.3-.1-.7-.1-1-.1-3.9 0-7 3.1-7 7 0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7 0-.3 0-.7-.1-1H18zm-6 5c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.png
new file mode 100644
index 00000000..88160bcc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.svg
new file mode 100644
index 00000000..d84970fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M24 4h-4V0h-2v4h-4v2h4v4h2V6h4z"/>
+ <path d="M18 11h-1V7.1l-.1-.1H13V5.1c-.3-.1-.7-.1-1-.1-3.9 0-7 3.1-7 7 0 1.4.4 2.6 1.1 3.7L12 23l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7 0-.3 0-.7-.1-1H18zm-6 5c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.png
new file mode 100644
index 00000000..6ea82260
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.svg
new file mode 100644
index 00000000..e3ba3792
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M0 4h4V0h2v4h4v2H6v4H4V6H0z"/>
+ <path d="M6 11h1V7.1l.1-.1H11V5.1c.3-.1.7-.1 1-.1 3.9 0 7 3.1 7 7 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-.3 0-.7.1-1H6zm6 5c2.2 0 4-1.8 4-4s-1.8-4-4-4-4 1.8-4 4 1.8 4 4 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.png
new file mode 100644
index 00000000..20aba255
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.svg
new file mode 100644
index 00000000..8f35458a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/mapPinAdd-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M0 4h4V0h2v4h4v2H6v4H4V6H0z"/>
+ <path d="M6 11h1V7.1l.1-.1H11V5.1c.3-.1.7-.1 1-.1 3.9 0 7 3.1 7 7 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-.3 0-.7.1-1H6zm6 5c2.2 0 4-1.8 4-4s-1.8-4-4-4-4 1.8-4 4 1.8 4 4 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup-invert.png
new file mode 100644
index 00000000..0f64c023
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup-invert.svg
new file mode 100644
index 00000000..9d877256
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="markup">
+ <path id="left-bracket" d="M9.665 6.32l-4.259 4.274-1.406 1.406 1.406 1.406 4.259 4.274 1.406-1.438-4.259-4.243 4.259-4.243z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" xlink:href="#left-bracket"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup.png
new file mode 100644
index 00000000..c78f4185
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup.svg
new file mode 100644
index 00000000..7f8c2535
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/markup.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="markup">
+ <path id="left-bracket" d="M9.665 6.32l-4.259 4.274-1.406 1.406 1.406 1.406 4.259 4.274 1.406-1.438-4.259-4.243 4.259-4.243z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" xlink:href="#left-bracket"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu-invert.png
new file mode 100644
index 00000000..b61db4a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu-invert.svg
new file mode 100644
index 00000000..dbd4a987
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="menu">
+ <path id="lines" d="M6 15h12a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1zm-1-4v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1zm0-5v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu.png
new file mode 100644
index 00000000..d2278db8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu.svg
new file mode 100644
index 00000000..a33c21ca
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/menu.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="menu">
+ <path id="lines" d="M6 15h12a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1zm-1-4v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1zm0-5v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr-invert.png
new file mode 100644
index 00000000..33a98009
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr-invert.svg
new file mode 100644
index 00000000..df724508
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M21 9c0-1.7-1.3-3-3-3H3v3l9 4 9-4zM3 11v6c0 1.7 1.3 3 3 3h15v-9l-9 4-9-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr.png
new file mode 100644
index 00000000..2171c1f3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr.svg
new file mode 100644
index 00000000..842d312c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 9c0-1.7-1.3-3-3-3H3v3l9 4 9-4zM3 11v6c0 1.7 1.3 3 3 3h15v-9l-9 4-9-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl-invert.png
new file mode 100644
index 00000000..c2d617b4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl-invert.svg
new file mode 100644
index 00000000..1bb1dae7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M3 9c0-1.7 1.3-3 3-3h15v3l-9 4-9-4zm18 2v6c0 1.7-1.3 3-3 3H3v-9l9 4 9-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl.png
new file mode 100644
index 00000000..fba79205
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl.svg
new file mode 100644
index 00000000..0a22c751
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/message-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 9c0-1.7 1.3-3 3-3h15v3l-9 4-9-4zm18 2v6c0 1.7-1.3 3-3 3H3v-9l9 4 9-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon-invert.png
new file mode 100644
index 00000000..38bcc0ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon-invert.svg
new file mode 100644
index 00000000..6fce33f9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M19.1 17.5c-3.3 1.4-7.1-.2-8.5-3.5-1.4-3.3.2-7.1 3.5-8.5.2-.1.5-.2.7-.3-1.6-.4-3.2-.3-4.8.4C6 7.3 4 12 5.7 16c1.7 4.1 6.4 6 10.5 4.3 1.7-.7 3-1.9 3.8-3.4-.3.3-.6.4-.9.6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon.png
new file mode 100644
index 00000000..7aef8bd8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon.svg
new file mode 100644
index 00000000..bdbf2346
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/moon.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19.1 17.5c-3.3 1.4-7.1-.2-8.5-3.5-1.4-3.3.2-7.1 3.5-8.5.2-.1.5-.2.7-.3-1.6-.4-3.2-.3-4.8.4C6 7.3 4 12 5.7 16c1.7 4.1 6.4 6 10.5 4.3 1.7-.7 3-1.9 3.8-3.4-.3.3-.6.4-.9.6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-invert.png
new file mode 100644
index 00000000..6d7e5eca
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-invert.svg
new file mode 100644
index 00000000..63c7b4cc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M20 11l-4-3v2h-3V7h2l-3-4-3 4h2v3H8V8l-4 3 4 3v-2h3v3H9l3 4 3-4h-2v-3h3v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr-invert.png
new file mode 100644
index 00000000..fe5f614c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr-invert.svg
new file mode 100644
index 00000000..6fdddd8e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="move-ltr">
+ <path id="arrow" d="M8.935 7.18l5.302 5.303-5.302 5.303L10.35 19.2l6.715-6.717-6.716-6.716z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr.png
new file mode 100644
index 00000000..b57d8daa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr.svg
new file mode 100644
index 00000000..670d84d1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="move-ltr">
+ <path id="arrow" d="M8.935 7.18l5.302 5.303-5.302 5.303L10.35 19.2l6.715-6.717-6.716-6.716z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl-invert.png
new file mode 100644
index 00000000..cfca1e24
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl-invert.svg
new file mode 100644
index 00000000..2f1e91e0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="move-rtl">
+ <path id="arrow" d="M15.065 17.786l-5.302-5.303 5.302-5.302-1.415-1.41-6.714 6.72 6.714 6.71z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl.png
new file mode 100644
index 00000000..e401a8f8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl.svg
new file mode 100644
index 00000000..ce5b444f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="move-rtl">
+ <path id="arrow" d="M15.065 17.786l-5.302-5.303 5.302-5.302-1.415-1.41-6.714 6.72 6.714 6.71z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move.png
new file mode 100644
index 00000000..7071499f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move.svg
new file mode 100644
index 00000000..b04ecdd4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/move.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 11l-4-3v2h-3V7h2l-3-4-3 4h2v3H8V8l-4 3 4 3v-2h3v3H9l3 4 3-4h-2v-3h3v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr-invert.png
new file mode 100644
index 00000000..5e432b04
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr-invert.svg
new file mode 100644
index 00000000..25cf3218
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 5l2.5 2.5L11 11c-1.2 1.2-1.2 2.8 0 4l5.5-5.5L19 12V5h-7zm5 12H8c-.6 0-1-.4-1-1V7h3L8 5H5v11c0 1.7 1.3 3 3 3h11v-3l-2-2v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr.png
new file mode 100644
index 00000000..29563d87
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr.svg
new file mode 100644
index 00000000..2d19a78f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5l2.5 2.5L11 11c-1.2 1.2-1.2 2.8 0 4l5.5-5.5L19 12V5h-7zm5 12H8c-.6 0-1-.4-1-1V7h3L8 5H5v11c0 1.7 1.3 3 3 3h11v-3l-2-2v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl-invert.png
new file mode 100644
index 00000000..f9a742e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl-invert.svg
new file mode 100644
index 00000000..cb0a0357
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 5L9.5 7.5 13 11c1.2 1.2 1.2 2.8 0 4L7.5 9.5 5 12V5h7zM7 17h9c.6 0 1-.4 1-1V7h-3l2-2h3v11c0 1.7-1.3 3-3 3H5v-3l2-2v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl.png
new file mode 100644
index 00000000..c49609f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl.svg
new file mode 100644
index 00000000..133442ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newWindow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5L9.5 7.5 13 11c1.2 1.2 1.2 2.8 0 4L7.5 9.5 5 12V5h7zM7 17h9c.6 0 1-.4 1-1V7h-3l2-2h3v11c0 1.7-1.3 3-3 3H5v-3l2-2v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr-invert.png
new file mode 100644
index 00000000..874ff294
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr-invert.svg
new file mode 100644
index 00000000..220450a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M17.8 5.7c-.5 0-.9.2-1.2.5s-.5.7-.5 1.2v4.3H11v-4l-6 5.5 6 5.5v-4h8v-9h-1.2z" id="line_return"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr.png
new file mode 100644
index 00000000..f41eb0c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr.svg
new file mode 100644
index 00000000..a7e5b126
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.8 5.7c-.5 0-.9.2-1.2.5s-.5.7-.5 1.2v4.3H11v-4l-6 5.5 6 5.5v-4h8v-9h-1.2z" id="line_return"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl-invert.png
new file mode 100644
index 00000000..99be840f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl-invert.svg
new file mode 100644
index 00000000..214aea9e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M6.2 5.7c.5 0 .9.2 1.2.5.3.3.5.7.5 1.2v4.3H13v-4l6 5.5-6 5.5v-4H5v-9h1.2z" id="line_return"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl.png
new file mode 100644
index 00000000..93c7e52c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl.svg
new file mode 100644
index 00000000..40752fa7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newline-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6.2 5.7c.5 0 .9.2 1.2.5.3.3.5.7.5 1.2v4.3H13v-4l6 5.5-6 5.5v-4H5v-9h1.2z" id="line_return"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr-invert.png
new file mode 100644
index 00000000..3f48ede6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr-invert.svg
new file mode 100644
index 00000000..171f6e6a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M6 7v12c-.6 0-1-.4-1-1V9H4v9c0 1.1.9 2 2 2h15V7H6zm9 11H8v-1h7v1zm0-2H8v-1h7v1zm0-2H8v-1h7v1zm4 4h-3v-5h3v5zm0-7H8V9h11v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr.png
new file mode 100644
index 00000000..ccd64748
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr.svg
new file mode 100644
index 00000000..4ff58564
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6 7v12c-.6 0-1-.4-1-1V9H4v9c0 1.1.9 2 2 2h15V7H6zm9 11H8v-1h7v1zm0-2H8v-1h7v1zm0-2H8v-1h7v1zm4 4h-3v-5h3v5zm0-7H8V9h11v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl-invert.png
new file mode 100644
index 00000000..85cfa839
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl-invert.svg
new file mode 100644
index 00000000..c161b6e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M19 7v12c.6 0 1-.4 1-1V9h1v9c0 1.1-.9 2-2 2H4V7h15zm-9 11h7v-1h-7v1zm0-2h7v-1h-7v1zm0-2h7v-1h-7v1zm-4 4h3v-5H6v5zm0-7h11V9H6v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl.png
new file mode 100644
index 00000000..b5df1df6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl.svg
new file mode 100644
index 00000000..f9d4e557
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/newspaper-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19 7v12c.6 0 1-.4 1-1V9h1v9c0 1.1-.9 2-2 2H4V7h15zm-9 11h7v-1h-7v1zm0-2h7v-1h-7v1zm0-2h7v-1h-7v1zm-4 4h3v-5H6v5zm0-7h11V9H6v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr-invert.png
new file mode 100644
index 00000000..aacaccae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr-invert.svg
new file mode 100644
index 00000000..92882b06
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M15 13l2 2V5h-3v2h1zM3 3L2 4l1 1v14h3v-2H5V7l2 2v10h3v-2H9v-6l6 6h-1v2h3l3 3 1-1-3-3zm7 4V5H7l2 2zm8-2v2h1v10l2 2V5z" id="noWikiText-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr.png
new file mode 100644
index 00000000..f9fcbba5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr.svg
new file mode 100644
index 00000000..2dfa2c73
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 13l2 2V5h-3v2h1zM3 3L2 4l1 1v14h3v-2H5V7l2 2v10h3v-2H9v-6l6 6h-1v2h3l3 3 1-1-3-3zm7 4V5H7l2 2zm8-2v2h1v10l2 2V5z" id="noWikiText-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl-invert.png
new file mode 100644
index 00000000..5e509516
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl-invert.svg
new file mode 100644
index 00000000..b07a6a1d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M9 13l-2 2V5h3v2H9zM21 3l1 1-1 1v14h-3v-2h1V7l-2 2v10h-3v-2h1v-6l-6 6h1v2H7l-3 3-1-1 3-3zm-7 4V5h3l-2 2zM6 5v2H5v10l-2 2V5z" id="noWikiText-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl.png
new file mode 100644
index 00000000..a4dad7f8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl.svg
new file mode 100644
index 00000000..4f275fd6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/noWikiText-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 13l-2 2V5h3v2H9zM21 3l1 1-1 1v14h-3v-2h1V7l-2 2v10h-3v-2h1v-6l-6 6h1v2H7l-3 3-1-1 3-3zm-7 4V5h3l-2 2zM6 5v2H5v10l-2 2V5z" id="noWikiText-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright-invert.png
new file mode 100644
index 00000000..de7e5297
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright-invert.svg
new file mode 100644
index 00000000..94fd0b82
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright.png
new file mode 100644
index 00000000..5273b4c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright.svg
new file mode 100644
index 00000000..af87ff9f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notBright.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice-invert.png
new file mode 100644
index 00000000..e18795b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice-invert.svg
new file mode 100644
index 00000000..50d4ad6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="svg3116"><style>* { fill: #ffffff }</style>
+ <path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm-1-5h2V8h-2zm0 3h2v-2h-2z" id="alert"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice.png
new file mode 100644
index 00000000..114020ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice.svg
new file mode 100644
index 00000000..8dc4fec7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/notice.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="svg3116">
+ <path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm-1-5h2V8h-2zm0 3h2v-2h-2z" id="alert"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-invert.png
new file mode 100644
index 00000000..b2dea7c6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-invert.svg
new file mode 100644
index 00000000..e8a56bc6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>* { fill: #ffffff }</style>
+ <path d="M17.8 18.6H2.5l2.7-2.7V6h15.3v9.9c0 1.53-1.17 2.7-2.7 2.7zm-7.542-4.95c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945z" id="ongoing-conversation" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-progressive.png
new file mode 100644
index 00000000..6fffe1a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-progressive.svg
new file mode 100644
index 00000000..89d2745c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>* { fill: #347bff }</style>
+ <path d="M17.8 18.6H2.5l2.7-2.7V6h15.3v9.9c0 1.53-1.17 2.7-2.7 2.7zm-7.542-4.95c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945z" id="ongoing-conversation" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr.png
new file mode 100644
index 00000000..df49095b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr.svg
new file mode 100644
index 00000000..658809d8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M17.8 18.6H2.5l2.7-2.7V6h15.3v9.9c0 1.53-1.17 2.7-2.7 2.7zm-7.542-4.95c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945z" id="ongoing-conversation" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-invert.png
new file mode 100644
index 00000000..a3d60134
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-invert.svg
new file mode 100644
index 00000000..a66123e7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>* { fill: #ffffff }</style>
+ <path d="M5.2 18.6h15.3l-2.7-2.7V6H2.5v9.9c0 1.53 1.17 2.7 2.7 2.7zm7.542-4.95c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.608.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.608-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.608.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.332 1.332 0 0 0-.945-.405c-.337 0-.675.135-.945.405-.27.27-.405.608-.405.945z" id="ongoing-conversation" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-progressive.png
new file mode 100644
index 00000000..4c0bd30a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-progressive.svg
new file mode 100644
index 00000000..d0c3c64f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><style>* { fill: #347bff }</style>
+ <path d="M5.2 18.6h15.3l-2.7-2.7V6H2.5v9.9c0 1.53 1.17 2.7 2.7 2.7zm7.542-4.95c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.608.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.608-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.608.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.332 1.332 0 0 0-.945-.405c-.337 0-.675.135-.945.405-.27.27-.405.608-.405.945z" id="ongoing-conversation" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl.png
new file mode 100644
index 00000000..3d7e9bda
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl.svg
new file mode 100644
index 00000000..648ce55a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ongoingConversation-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
+ <path d="M5.2 18.6h15.3l-2.7-2.7V6H2.5v9.9c0 1.53 1.17 2.7 2.7 2.7zm7.542-4.95c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.608.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.608-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.608.405.945.405.405 0 .675-.135.945-.405.27-.27.405-.607.405-.945 0-.337-.135-.675-.405-.945a1.332 1.332 0 0 0-.945-.405c-.337 0-.675.135-.945.405-.27.27-.405.608-.405.945z" id="ongoing-conversation" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr-invert.png
new file mode 100644
index 00000000..6bb2f992
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr-invert.svg
new file mode 100644
index 00000000..8136cb91
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M10 8h9v2h-9V8zm0 3h9v2h-9v-2zm0 3h6v2h-6v-2zm11-8H3V4h18v2zm0 14H3v-2h18v2zM3 12l5 4V8l-5 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr.png
new file mode 100644
index 00000000..c1cd66a1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr.svg
new file mode 100644
index 00000000..c004db0f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10 8h9v2h-9V8zm0 3h9v2h-9v-2zm0 3h6v2h-6v-2zm11-8H3V4h18v2zm0 14H3v-2h18v2zM3 12l5 4V8l-5 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl-invert.png
new file mode 100644
index 00000000..eb3d7005
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl-invert.svg
new file mode 100644
index 00000000..4a08f5f7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M14 8H5v2h9V8zm0 3H5v2h9v-2zm0 3H8v2h6v-2zM3 6h18V4H3v2zm0 14h18v-2H3v2zm18-8l-5 4V8l5 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl.png
new file mode 100644
index 00000000..a1d94545
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl.svg
new file mode 100644
index 00000000..a71bfdc6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outdent-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14 8H5v2h9V8zm0 3H5v2h9v-2zm0 3H8v2h6v-2zM3 6h18V4H3v2zm0 14h18v-2H3v2zm18-8l-5 4V8l5 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr-invert.png
new file mode 100644
index 00000000..eceedbdd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr-invert.svg
new file mode 100644
index 00000000..d9d13909
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="outline-ltr">
+ <path id="text" d="M5 13h14v6H5v-6z"/>
+ <path id="float" d="M5 5v6h6V5H5zm5 5H6V6h4v4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr.png
new file mode 100644
index 00000000..bcbfa5ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr.svg
new file mode 100644
index 00000000..44c1591d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="outline-ltr">
+ <path id="text" d="M5 13h14v6H5v-6z"/>
+ <path id="float" d="M5 5v6h6V5H5zm5 5H6V6h4v4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl-invert.png
new file mode 100644
index 00000000..96c4719a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl-invert.svg
new file mode 100644
index 00000000..f1dd2df0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="outline-rtl">
+ <path id="text" d="M19 19H5v-6h14v6z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm1 1h4v4h-4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl.png
new file mode 100644
index 00000000..d89e06e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl.svg
new file mode 100644
index 00000000..c5b19c8f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/outline-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="outline-rtl">
+ <path id="text" d="M19 19H5v-6h14v6z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm1 1h4v4h-4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr-invert.png
new file mode 100644
index 00000000..82fcfa39
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr-invert.svg
new file mode 100644
index 00000000..ffc0cc0d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm-2 12V9l6 4-6 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr.png
new file mode 100644
index 00000000..a3b711b0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr.svg
new file mode 100644
index 00000000..82a16a4a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm-2 12V9l6 4-6 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl-invert.png
new file mode 100644
index 00000000..c31dbea2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl-invert.svg
new file mode 100644
index 00000000..9c3220b3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 5c4.4 0 8 3.6 8 8s-3.6 8-8 8-8-3.6-8-8 3.6-8 8-8zm2 12V9l-6 4 6 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl.png
new file mode 100644
index 00000000..2e45883c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl.svg
new file mode 100644
index 00000000..dae95c40
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/play-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5c4.4 0 8 3.6 8 8s-3.6 8-8 8-8-3.6-8-8 3.6-8 8-8zm2 12V9l-6 4 6 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr-invert.png
new file mode 100644
index 00000000..25171661
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr-invert.svg
new file mode 100644
index 00000000..47377692
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M18 8h-1V4H7v4H3v6c0 1.7 1.3 3 3 3h1v3h10v-3h4v-6c0-1.7-1.3-3-3-3zM8 5h8v3H8V5zm8 14H8v-6h8v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr.png
new file mode 100644
index 00000000..0084ac9c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr.svg
new file mode 100644
index 00000000..7081606b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18 8h-1V4H7v4H3v6c0 1.7 1.3 3 3 3h1v3h10v-3h4v-6c0-1.7-1.3-3-3-3zM8 5h8v3H8V5zm8 14H8v-6h8v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl-invert.png
new file mode 100644
index 00000000..37a9e3da
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl-invert.svg
new file mode 100644
index 00000000..14d5bfe7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M6 8h1V4h10v4h4v6c0 1.7-1.3 3-3 3h-1v3H7v-3H3v-6c0-1.7 1.3-3 3-3zm10-3H8v3h8V5zM8 19h8v-6H8v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl.png
new file mode 100644
index 00000000..6e5b1756
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl.svg
new file mode 100644
index 00000000..d6188ebb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/printer-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6 8h1V4h10v4h4v6c0 1.7-1.3 3-3 3h-1v3H7v-3H3v-6c0-1.7 1.3-3 3-3zm10-3H8v3h8V5zM8 19h8v-6H8v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr-invert.png
new file mode 100644
index 00000000..0dbe87e1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr-invert.svg
new file mode 100644
index 00000000..fb03c633
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M18 9.9c-.7 0-1.4.3-1.8.9V6h-4c.2-.4.4-.8.4-1.2 0-1.2-1-2.2-2.2-2.2-1.3-.1-2.3.9-2.3 2.2 0 .4.2.8.4 1.2H4.1v3.6l.6-.1c1.4 0 2.5 1.1 2.5 2.5s-1.1 2.5-2.5 2.5c-.2 0-.4 0-.6-.1V18H9c-.5.4-.9 1-.9 1.8 0 1.2 1 2.2 2.3 2.2 1.2 0 2.2-1 2.2-2.2 0-.7-.3-1.4-.9-1.8h4.5v-4.5c.4.5 1 .9 1.8.9 1.2 0 2.2-1 2.2-2.2 0-1.3-1-2.3-2.2-2.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr.png
new file mode 100644
index 00000000..9b406097
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr.svg
new file mode 100644
index 00000000..fb9d3383
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18 9.9c-.7 0-1.4.3-1.8.9V6h-4c.2-.4.4-.8.4-1.2 0-1.2-1-2.2-2.2-2.2-1.3-.1-2.3.9-2.3 2.2 0 .4.2.8.4 1.2H4.1v3.6l.6-.1c1.4 0 2.5 1.1 2.5 2.5s-1.1 2.5-2.5 2.5c-.2 0-.4 0-.6-.1V18H9c-.5.4-.9 1-.9 1.8 0 1.2 1 2.2 2.3 2.2 1.2 0 2.2-1 2.2-2.2 0-.7-.3-1.4-.9-1.8h4.5v-4.5c.4.5 1 .9 1.8.9 1.2 0 2.2-1 2.2-2.2 0-1.3-1-2.3-2.2-2.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl-invert.png
new file mode 100644
index 00000000..dc5a97ff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl-invert.svg
new file mode 100644
index 00000000..9f7ce1e5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M6.3 9.9c.7 0 1.4.3 1.8.9V6h4c-.2-.4-.4-.8-.4-1.2 0-1.2 1-2.2 2.2-2.2 1.3-.1 2.3.9 2.3 2.2 0 .4-.2.8-.4 1.2h4.4v3.6l-.6-.1c-1.4 0-2.5 1.1-2.5 2.5s1.1 2.5 2.5 2.5c.2 0 .4 0 .6-.1V18h-4.9c.5.4.9 1 .9 1.8 0 1.2-1 2.2-2.3 2.2-1.2 0-2.2-1-2.2-2.2 0-.7.3-1.4.9-1.8H8.1v-4.5c-.4.5-1 .9-1.8.9-1.2 0-2.2-1-2.2-2.2 0-1.3 1-2.3 2.2-2.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl.png
new file mode 100644
index 00000000..6f7334b5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl.svg
new file mode 100644
index 00000000..1d483084
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/puzzle-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6.3 9.9c.7 0 1.4.3 1.8.9V6h4c-.2-.4-.4-.8-.4-1.2 0-1.2 1-2.2 2.2-2.2 1.3-.1 2.3.9 2.3 2.2 0 .4-.2.8-.4 1.2h4.4v3.6l-.6-.1c-1.4 0-2.5 1.1-2.5 2.5s1.1 2.5 2.5 2.5c.2 0 .4 0 .6-.1V18h-4.9c.5.4.9 1 .9 1.8 0 1.2-1 2.2-2.3 2.2-1.2 0-2.2-1-2.2-2.2 0-.7.3-1.4.9-1.8H8.1v-4.5c-.4.5-1 .9-1.8.9-1.2 0-2.2-1-2.2-2.2 0-1.3 1-2.3 2.2-2.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr-invert.png
new file mode 100644
index 00000000..46ac1813
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr-invert.svg
new file mode 100644
index 00000000..17de62bd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="quotes">
+ <path id="quote" d="M6.9 8.4c-.446.55-1.974 2.6-1.9 5.7V17h4.7c.9 0 1.6-.7 1.6-1.6V11H8.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ </g>
+ <use transform="translate(8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr.png
new file mode 100644
index 00000000..0252b746
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr.svg
new file mode 100644
index 00000000..dc366b7d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes">
+ <path id="quote" d="M6.9 8.4c-.446.55-1.974 2.6-1.9 5.7V17h4.7c.9 0 1.6-.7 1.6-1.6V11H8.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ </g>
+ <use transform="translate(8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl-invert.png
new file mode 100644
index 00000000..6637ca22
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl-invert.svg
new file mode 100644
index 00000000..0ac72cb0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="quotes">
+ <path id="quote" d="M17.1 8.4c.446.55 1.9 2.6 1.9 5.7V17h-4.7c-.9 0-1.6-.7-1.6-1.6V11h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ </g>
+ <use transform="translate(-8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl.png
new file mode 100644
index 00000000..7bcc7c7b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl.svg
new file mode 100644
index 00000000..e652b317
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotes-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes">
+ <path id="quote" d="M17.1 8.4c.446.55 1.9 2.6 1.9 5.7V17h-4.7c-.9 0-1.6-.7-1.6-1.6V11h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ </g>
+ <use transform="translate(-8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr-invert.png
new file mode 100644
index 00000000..40e3a064
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr-invert.svg
new file mode 100644
index 00000000..8953f4d0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr-invert.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="quotes-add">
+ <path id="quote" d="M5.9 10.4c-.446.55-1.974 2.6-1.9 5.7V19h4.7c.9 0 1.593-.7 1.6-1.6V13H7.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ <path id="quote2" d="M15 9.344c-.476.32-.78.677-1.094 1.062A8.76 8.76 0 0 0 12 16.094V19h4.688a1.6 1.6 0 0 0 1.625-1.594V13H15V9.344z"/>
+ <path id="add" d="M18 6V2h-2v4h-4v2h4v4h2V8h4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr.png
new file mode 100644
index 00000000..e1a0c4ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr.svg
new file mode 100644
index 00000000..6704c516
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-ltr.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes-add">
+ <path id="quote" d="M5.9 10.4c-.446.55-1.974 2.6-1.9 5.7V19h4.7c.9 0 1.593-.7 1.6-1.6V13H7.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ <path id="quote2" d="M15 9.344c-.476.32-.78.677-1.094 1.062A8.76 8.76 0 0 0 12 16.094V19h4.688a1.6 1.6 0 0 0 1.625-1.594V13H15V9.344z"/>
+ <path id="add" d="M18 6V2h-2v4h-4v2h4v4h2V8h4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl-invert.png
new file mode 100644
index 00000000..e15cc905
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl-invert.svg
new file mode 100644
index 00000000..1ada793b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl-invert.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="quotes-add">
+ <path id="quote" d="M18.097 10.4c.446.55 1.974 2.6 1.9 5.7V19h-4.7c-.9 0-1.593-.7-1.6-1.6V13h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ <path id="quote2" d="M8.997 9.344c.476.32.782.677 1.094 1.062A8.758 8.758 0 0 1 12 16.094V19H7.31c-.9 0-1.618-.694-1.625-1.594V13h3.312V9.344z"/>
+ <path id="add" d="M5.997 6V2h2v4h4v2h-4v4h-2V8h-4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl.png
new file mode 100644
index 00000000..0ef9d016
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl.svg
new file mode 100644
index 00000000..d972ad3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/quotesAdd-rtl.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes-add">
+ <path id="quote" d="M18.097 10.4c.446.55 1.974 2.6 1.9 5.7V19h-4.7c-.9 0-1.593-.7-1.6-1.6V13h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ <path id="quote2" d="M8.997 9.344c.476.32.782.677 1.094 1.062A8.758 8.758 0 0 1 12 16.094V19H7.31c-.9 0-1.618-.694-1.625-1.594V13h3.312V9.344z"/>
+ <path id="add" d="M5.997 6V2h2v4h4v2h-4v4h-2V8h-4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression-invert.png
new file mode 100644
index 00000000..0206be91
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression-invert.svg
new file mode 100644
index 00000000..61b1550b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression-invert.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="regular-expression">
+ <path id="left-bracket" d="M3 12.045c0-.99.15-1.915.45-2.777A6.886 6.886 0 0 1 4.764 7H6.23a7.923 7.923 0 0 0-1.25 2.374 8.563 8.563 0 0 0 .007 5.314c.29.85.7 1.622 1.23 2.312h-1.45a6.53 6.53 0 0 1-1.314-2.223 8.126 8.126 0 0 1-.45-2.732"/>
+ <path id="dot" d="M10 16a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
+ <path id="star" d="M14.25 7.013l-.24 2.156 2.187-.61.193 1.47-1.992.14 1.307 1.74-1.33.71-.914-1.833-.8 1.822-1.38-.698 1.296-1.74-1.98-.152.23-1.464 2.14.61-.24-2.158h1.534"/>
+ <path id="right-bracket" d="M21 12.045c0 .982-.152 1.896-.457 2.744A6.51 6.51 0 0 1 19.236 17h-1.453a8.017 8.017 0 0 0 1.225-2.31c.29-.855.434-1.74.434-2.66 0-.91-.14-1.797-.422-2.66a7.913 7.913 0 0 0-1.248-2.374h1.465a6.764 6.764 0 0 1 1.313 2.28c.3.86.45 1.782.45 2.764"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression.png
new file mode 100644
index 00000000..f27e4212
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression.svg
new file mode 100644
index 00000000..d5fcfcf0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/regular-expression.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="regular-expression">
+ <path id="left-bracket" d="M3 12.045c0-.99.15-1.915.45-2.777A6.886 6.886 0 0 1 4.764 7H6.23a7.923 7.923 0 0 0-1.25 2.374 8.563 8.563 0 0 0 .007 5.314c.29.85.7 1.622 1.23 2.312h-1.45a6.53 6.53 0 0 1-1.314-2.223 8.126 8.126 0 0 1-.45-2.732"/>
+ <path id="dot" d="M10 16a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
+ <path id="star" d="M14.25 7.013l-.24 2.156 2.187-.61.193 1.47-1.992.14 1.307 1.74-1.33.71-.914-1.833-.8 1.822-1.38-.698 1.296-1.74-1.98-.152.23-1.464 2.14.61-.24-2.158h1.534"/>
+ <path id="right-bracket" d="M21 12.045c0 .982-.152 1.896-.457 2.744A6.51 6.51 0 0 1 19.236 17h-1.453a8.017 8.017 0 0 0 1.225-2.31c.29-.855.434-1.74.434-2.66 0-.91-.14-1.797-.422-2.66a7.913 7.913 0 0 0-1.248-2.374h1.465a6.764 6.764 0 0 1 1.313 2.28c.3.86.45 1.782.45 2.764"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize-invert.png
new file mode 100644
index 00000000..46a180d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize-invert.svg
new file mode 100644
index 00000000..458abd04
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <circle cx="11.5" cy="8.5" r="2.5"/>
+ <path d="M16.3 8.7L17 8l-.8-.8.4-.8-1.1-.5.1-.9-1.2-.2-.1-.9-1.2.2-.4-.8-1.1.5L11 3l-.8.8-.9-.4-.5 1.1-.9-.2-.2 1.2-.9.2.2 1.2-.9.4.5 1.1L6 9l.8.8-.4.8 1.1.5-.1.9 1.2.2.1.9 1.2-.2.4.8 1.1-.5.6.8.8-.8.8.4.5-1.1.9.1.2-1.2.9-.1-.2-1.2.8-.4-.4-1zM11.5 12C9.6 12 8 10.4 8 8.5S9.6 5 11.5 5 15 6.6 15 8.5 13.4 12 11.5 12zm.5 3l-.7-.7-1.1.6-.4-.7-.8.3V23l2.5-3 2.5 3v-8.5l-1-.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize.png
new file mode 100644
index 00000000..10105740
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize.svg
new file mode 100644
index 00000000..45df8b71
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/ribbonPrize.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <circle cx="11.5" cy="8.5" r="2.5"/>
+ <path d="M16.3 8.7L17 8l-.8-.8.4-.8-1.1-.5.1-.9-1.2-.2-.1-.9-1.2.2-.4-.8-1.1.5L11 3l-.8.8-.9-.4-.5 1.1-.9-.2-.2 1.2-.9.2.2 1.2-.9.4.5 1.1L6 9l.8.8-.4.8 1.1.5-.1.9 1.2.2.1.9 1.2-.2.4.8 1.1-.5.6.8.8-.8.8.4.5-1.1.9.1.2-1.2.9-.1-.2-1.2.8-.4-.4-1zM11.5 12C9.6 12 8 10.4 8 8.5S9.6 5 11.5 5 15 6.6 15 8.5 13.4 12 11.5 12zm.5 3l-.7-.7-1.1.6-.4-.7-.8.3V23l2.5-3 2.5 3v-8.5l-1-.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr-invert.png
new file mode 100644
index 00000000..4b2913bc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr-invert.svg
new file mode 100644
index 00000000..316ac6d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="search">
+ <path id="magnifying-glass" d="M10.5 4a6.5 6.5 0 1 0 2.844 12.344L16 19c1.4 1.4 2.5 1.5 4 0l-4.438-4.438A6.426 6.426 0 0 0 17 10.5 6.5 6.5 0 0 0 10.5 4zm0 2a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr.png
new file mode 100644
index 00000000..e8e99f84
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr.svg
new file mode 100644
index 00000000..ebc654a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="search">
+ <path id="magnifying-glass" d="M10.5 4a6.5 6.5 0 1 0 2.844 12.344L16 19c1.4 1.4 2.5 1.5 4 0l-4.438-4.438A6.426 6.426 0 0 0 17 10.5 6.5 6.5 0 0 0 10.5 4zm0 2a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl-invert.png
new file mode 100644
index 00000000..0409aa49
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl-invert.svg
new file mode 100644
index 00000000..1d36daff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="search">
+ <path id="magnifying-glass" d="M13.5 4a6.5 6.5 0 1 1-2.844 12.344L8 19c-1.4 1.4-2.5 1.5-4 0l4.438-4.438A6.426 6.426 0 0 1 7 10.5 6.5 6.5 0 0 1 13.5 4zm0 2a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl.png
new file mode 100644
index 00000000..3ab96bec
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl.svg
new file mode 100644
index 00000000..c51d4cb0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/search-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="search">
+ <path id="magnifying-glass" d="M13.5 4a6.5 6.5 0 1 1-2.844 12.344L8 19c-1.4 1.4-2.5 1.5-4 0l4.438-4.438A6.426 6.426 0 0 1 7 10.5 6.5 6.5 0 0 1 13.5 4zm0 2a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link-invert.png
new file mode 100644
index 00000000..a74063d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link-invert.svg
new file mode 100644
index 00000000..488e2e28
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><style>* { fill: #ffffff }</style>
+ <g id="secure">
+ <path id="lock" d="M8 5h.02v-.997c0-.057.003-1.41-.833-2.255-.434-.438-.998-.66-1.68-.66s-1.244.222-1.677.66c-.837.846-.833 2.198-.832 2.25V5H3a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h5a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1zM3.998 5V3.993c0-.01.005-1 .543-1.543.49-.485 1.45-.487 1.94-.002.543.546.545 1.536.545 1.55V5H3.998z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link.png
new file mode 100644
index 00000000..8a44a929
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link.svg
new file mode 100644
index 00000000..453d1663
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/secure-link.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="secure">
+ <path id="lock" d="M8 5h.02v-.997c0-.057.003-1.41-.833-2.255-.434-.438-.998-.66-1.68-.66s-1.244.222-1.677.66c-.837.846-.833 2.198-.832 2.25V5H3a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h5a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1zM3.998 5V3.993c0-.01.005-1 .543-1.543.49-.485 1.45-.487 1.94-.002.543.546.545 1.536.545 1.55V5H3.998z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings-invert.png
new file mode 100644
index 00000000..34c6afe5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings-invert.svg
new file mode 100644
index 00000000..543adedd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="settings">
+ <path id="gear" d="M3 4h3v2H3zm9 0h9v2h-9zM8 3h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm-5 8h9v2H3zm15 0h3v2h-3zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zM3 18h6v2H3zm12 0h6v2h-6zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings.png
new file mode 100644
index 00000000..1c8e5874
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings.svg
new file mode 100644
index 00000000..3245dbe3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/settings.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="settings">
+ <path id="gear" d="M3 4h3v2H3zm9 0h9v2h-9zM8 3h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm-5 8h9v2H3zm15 0h3v2h-3zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zM3 18h6v2H3zm12 0h6v2h-6zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr-invert.png
new file mode 100644
index 00000000..4538011a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr-invert.svg
new file mode 100644
index 00000000..101e2afb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M0 20h24v1H0v-1zm6-8l-1-1-2 2-2-2-1 1 2 2-2 2 1 1 2-2 2 2 1-1-2-2zm15.6 3.7c-.9-.5-1.9-.5-2.7 0-1.5.9-3.1.4-3.1.4-.4-.2-.8-.4-1.1-.6 2.2-.6 4.4-1.8 6-3.9 1.1-1.2 2.5-3.9.4-6-.7-.7-1.6-1.1-2.7-1-1.4.1-2.8.9-3.9 2.1-.9 1.1-3.1 4.5-2.3 7.5 0 .1 0 .2.1.3-2.3.3-4.2.2-4.4.1v1.5c.7.1 2.7.2 5.1-.2.5.7 1.3 1.2 2.3 1.6.1 0 2.4.8 4.5-.6.5-.3.9-.1 1.1 0 .4.2.7.6.7 1H23c0-.8-.6-1.7-1.4-2.2zm-8-1.7c-.5-2.2 1.1-5.1 2-6.2.8-.9 1.8-1.5 2.8-1.6h.1c.6 0 1.1.2 1.5.6 1.6 1.6-.4 3.9-.5 4-1.5 2-3.7 3-5.8 3.5l-.1-.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr.png
new file mode 100644
index 00000000..f68a7bf2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr.svg
new file mode 100644
index 00000000..03b34cf8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M0 20h24v1H0v-1zm6-8l-1-1-2 2-2-2-1 1 2 2-2 2 1 1 2-2 2 2 1-1-2-2zm15.6 3.7c-.9-.5-1.9-.5-2.7 0-1.5.9-3.1.4-3.1.4-.4-.2-.8-.4-1.1-.6 2.2-.6 4.4-1.8 6-3.9 1.1-1.2 2.5-3.9.4-6-.7-.7-1.6-1.1-2.7-1-1.4.1-2.8.9-3.9 2.1-.9 1.1-3.1 4.5-2.3 7.5 0 .1 0 .2.1.3-2.3.3-4.2.2-4.4.1v1.5c.7.1 2.7.2 5.1-.2.5.7 1.3 1.2 2.3 1.6.1 0 2.4.8 4.5-.6.5-.3.9-.1 1.1 0 .4.2.7.6.7 1H23c0-.8-.6-1.7-1.4-2.2zm-8-1.7c-.5-2.2 1.1-5.1 2-6.2.8-.9 1.8-1.5 2.8-1.6h.1c.6 0 1.1.2 1.5.6 1.6 1.6-.4 3.9-.5 4-1.5 2-3.7 3-5.8 3.5l-.1-.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl-invert.png
new file mode 100644
index 00000000..a99fe522
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl-invert.svg
new file mode 100644
index 00000000..67bd7382
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M24 20H0v1h24v-1zm-6-8l1-1 2 2 2-2 1 1-2 2 2 2-1 1-2-2-2 2-1-1 2-2zM2.4 15.7c.9-.5 1.9-.5 2.7 0 1.5.9 3.1.4 3.1.4.4-.2.8-.4 1.1-.6-2.2-.6-4.4-1.8-6-3.9-1.1-1.2-2.5-3.9-.4-6 .7-.7 1.6-1.1 2.7-1 1.4.1 2.8.9 3.9 2.1.9 1.1 3.1 4.5 2.3 7.5 0 .1 0 .2-.1.3 2.3.3 4.2.2 4.4.1v1.5c-.7.1-2.7.2-5.1-.2-.5.7-1.3 1.2-2.3 1.6-.1 0-2.4.8-4.5-.6-.5-.3-.9-.1-1.1 0-.4.2-.7.6-.7 1H1c0-.8.6-1.7 1.4-2.2zm8-1.7c.5-2.2-1.1-5.1-2-6.2-.8-.9-1.8-1.5-2.8-1.6h-.1c-.6 0-1.1.2-1.5.6-1.6 1.6.4 3.9.5 4 1.5 2 3.7 3 5.8 3.5l.1-.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl.png
new file mode 100644
index 00000000..9166e8dd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl.svg
new file mode 100644
index 00000000..326281a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/signature-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M24 20H0v1h24v-1zm-6-8l1-1 2 2 2-2 1 1-2 2 2 2-1 1-2-2-2 2-1-1 2-2zM2.4 15.7c.9-.5 1.9-.5 2.7 0 1.5.9 3.1.4 3.1.4.4-.2.8-.4 1.1-.6-2.2-.6-4.4-1.8-6-3.9-1.1-1.2-2.5-3.9-.4-6 .7-.7 1.6-1.1 2.7-1 1.4.1 2.8.9 3.9 2.1.9 1.1 3.1 4.5 2.3 7.5 0 .1 0 .2-.1.3 2.3.3 4.2.2 4.4.1v1.5c-.7.1-2.7.2-5.1-.2-.5.7-1.3 1.2-2.3 1.6-.1 0-2.4.8-4.5-.6-.5-.3-.9-.1-1.1 0-.4.2-.7.6-.7 1H1c0-.8.6-1.7 1.4-2.2zm8-1.7c.5-2.2-1.1-5.1-2-6.2-.8-.9-1.8-1.5-2.8-1.6h-.1c-.6 0-1.1.2-1.5.6-1.6 1.6.4 3.9.5 4 1.5 2 3.7 3 5.8 3.5l.1-.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr-invert.png
new file mode 100644
index 00000000..84b1bcd1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr-invert.svg
new file mode 100644
index 00000000..ebbc3c18
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path id="a" d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z"/>
+ <g id="down">
+ <path id="arrow" d="M22 3l-3.5 6L15 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr.png
new file mode 100644
index 00000000..f5e89ba8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr.svg
new file mode 100644
index 00000000..82d16af9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="a" d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z"/>
+ <g id="down">
+ <path id="arrow" d="M22 3l-3.5 6L15 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl-invert.png
new file mode 100644
index 00000000..c9cdd774
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl-invert.svg
new file mode 100644
index 00000000..02a8fe6e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path id="a" d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z"/>
+ <g id="down">
+ <path id="arrow" d="M9 3L5.5 9 2 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl.png
new file mode 100644
index 00000000..e07c7b0d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl.svg
new file mode 100644
index 00000000..7466f48b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smaller-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="a" d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z"/>
+ <g id="down">
+ <path id="arrow" d="M9 3L5.5 9 2 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr-invert.png
new file mode 100644
index 00000000..dec125ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr-invert.svg
new file mode 100644
index 00000000..107f5f63
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M17.6 20h-5.4v-.5c.2 0 .5-.1.9-.1.3-.1.5-.2.5-.3V19s0-.1-.1-.2l-.8-2H9.3c-.1.2-.2.4-.3.7-.1.3-.2.5-.2.7-.1.3-.1.4-.2.6v.2c0 .1.1.3.3.4.2.1.6.2 1.1.2v.4H6v-.5c.2 0 .3 0 .5-.1.2 0 .3-.1.5-.2s.4-.2.5-.4l.3-.6c.5-1.3 1.1-2.6 1.6-3.9.5-1.3 1.1-2.7 1.8-4.3h1.4c.9 2.2 1.6 4 2.1 5.3.5 1.3 1 2.4 1.3 3.2.1.1.1.3.2.4.1.1.2.2.4.3.1.1.3.1.5.2s.3.1.5.1v.5zm-5.2-4L11 12.4 9.6 16h2.8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr.png
new file mode 100644
index 00000000..b38dca38
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr.svg
new file mode 100644
index 00000000..446d10a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.6 20h-5.4v-.5c.2 0 .5-.1.9-.1.3-.1.5-.2.5-.3V19s0-.1-.1-.2l-.8-2H9.3c-.1.2-.2.4-.3.7-.1.3-.2.5-.2.7-.1.3-.1.4-.2.6v.2c0 .1.1.3.3.4.2.1.6.2 1.1.2v.4H6v-.5c.2 0 .3 0 .5-.1.2 0 .3-.1.5-.2s.4-.2.5-.4l.3-.6c.5-1.3 1.1-2.6 1.6-3.9.5-1.3 1.1-2.7 1.8-4.3h1.4c.9 2.2 1.6 4 2.1 5.3.5 1.3 1 2.4 1.3 3.2.1.1.1.3.2.4.1.1.2.2.4.3.1.1.3.1.5.2s.3.1.5.1v.5zm-5.2-4L11 12.4 9.6 16h2.8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl-invert.png
new file mode 100644
index 00000000..9aba2460
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl-invert.svg
new file mode 100644
index 00000000..a290c92b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M6 19.5c.1 0 .3 0 .5-.1s.3-.1.5-.2.3-.2.4-.3c.1-.1.2-.2.2-.4.4-.9.8-1.9 1.3-3.2.5-1.3 1.2-3.1 2.1-5.3h1.4c.7 1.6 1.2 3 1.8 4.3.5 1.3 1.1 2.6 1.6 3.9l.3.6c.1.2.3.3.5.4.1.1.3.1.5.2.2 0 .4.1.5.1v.5h-4v-.5c.5 0 .9-.1 1.1-.2.2-.1.3-.2.3-.4v-.2c0-.1-.1-.3-.2-.6-.1-.2-.2-.4-.2-.7-.1-.3-.2-.5-.3-.7h-3.4l-.8 2c0 .1-.1.1-.1.2v.1c0 .1.2.2.5.3.3.1.6.1.9.1v.6H6v-.5zm8-3.5l-1.4-3.6-1.4 3.6H14z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl.png
new file mode 100644
index 00000000..b9864efb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl.svg
new file mode 100644
index 00000000..ebcea4df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/smallerText-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6 19.5c.1 0 .3 0 .5-.1s.3-.1.5-.2.3-.2.4-.3c.1-.1.2-.2.2-.4.4-.9.8-1.9 1.3-3.2.5-1.3 1.2-3.1 2.1-5.3h1.4c.7 1.6 1.2 3 1.8 4.3.5 1.3 1.1 2.6 1.6 3.9l.3.6c.1.2.3.3.5.4.1.1.3.1.5.2.2 0 .4.1.5.1v.5h-4v-.5c.5 0 .9-.1 1.1-.2.2-.1.3-.2.3-.4v-.2c0-.1-.1-.3-.2-.6-.1-.2-.2-.4-.2-.7-.1-.3-.2-.5-.3-.7h-3.4l-.8 2c0 .1-.1.1-.1.2v.1c0 .1.2.2.5.3.3.1.6.1.9.1v.6H6v-.5zm8-3.5l-1.4-3.6-1.4 3.6H14z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter-invert.png
new file mode 100644
index 00000000..b7c99967
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter-invert.svg
new file mode 100644
index 00000000..43e26067
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="special-character">
+ <path id="omega" d="M12 6.708c-.794 0-1.368.103-1.894.31-.525.207-.944.496-1.255.867-.31.366-.53.808-.66 1.327a7.232 7.232 0 0 0-.19 1.7c0 .512.06 1 .18 1.46.12.46.31.87.567 1.23.63.862 1.156 1.138 2.012 1.362L11 18H6v-3h.604l.53 1.353.395.053.6.044.75.035.455.01H10l-.09-.895c-.63-.094-.812-.268-1.337-.522-.525-.26-.98-.59-1.365-.99a4.428 4.428 0 0 1-.89-1.4 4.78 4.78 0 0 1-.32-1.778c0-.82.13-1.537.394-2.15a3.97 3.97 0 0 1 1.163-1.54c.507-.407 1.133-.71 1.878-.912.745-.206 1.6-.31 2.565-.31.96 0 1.81.103 2.556.31.75.2 1.38.504 1.887.912.51.407.9.92 1.16 1.54.27.614.404 1.33.404 2.15a4.79 4.79 0 0 1-.32 1.78 4.35 4.35 0 0 1-.9 1.397c-.38.4-.83.732-1.355.99-.526.255-.708.43-1.337.523l-.092.894h.66l.448-.01.75-.034.606-.044.4-.053.534-1.354H18v3h-5l.246-3.04c1.066-.11 1.337-.698 2.002-1.365.263-.36.452-.77.568-1.23.122-.46.183-.947.183-1.46 0-.62-.07-1.186-.198-1.7a3.175 3.175 0 0 0-.66-1.326c-.31-.37-.73-.66-1.255-.867-.525-.206-1.1-.31-1.894-.31"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter.png
new file mode 100644
index 00000000..9b02a410
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter.svg
new file mode 100644
index 00000000..5cba0801
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/specialCharacter.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="special-character">
+ <path id="omega" d="M12 6.708c-.794 0-1.368.103-1.894.31-.525.207-.944.496-1.255.867-.31.366-.53.808-.66 1.327a7.232 7.232 0 0 0-.19 1.7c0 .512.06 1 .18 1.46.12.46.31.87.567 1.23.63.862 1.156 1.138 2.012 1.362L11 18H6v-3h.604l.53 1.353.395.053.6.044.75.035.455.01H10l-.09-.895c-.63-.094-.812-.268-1.337-.522-.525-.26-.98-.59-1.365-.99a4.428 4.428 0 0 1-.89-1.4 4.78 4.78 0 0 1-.32-1.778c0-.82.13-1.537.394-2.15a3.97 3.97 0 0 1 1.163-1.54c.507-.407 1.133-.71 1.878-.912.745-.206 1.6-.31 2.565-.31.96 0 1.81.103 2.556.31.75.2 1.38.504 1.887.912.51.407.9.92 1.16 1.54.27.614.404 1.33.404 2.15a4.79 4.79 0 0 1-.32 1.78 4.35 4.35 0 0 1-.9 1.397c-.38.4-.83.732-1.355.99-.526.255-.708.43-1.337.523l-.092.894h.66l.448-.01.75-.034.606-.044.4-.053.534-1.354H18v3h-5l.246-3.04c1.066-.11 1.337-.698 2.002-1.365.263-.36.452-.77.568-1.23.122-.46.183-.947.183-1.46 0-.62-.07-1.186-.198-1.7a3.175 3.175 0 0 0-.66-1.326c-.31-.37-.73-.66-1.255-.867-.525-.206-1.1-.31-1.894-.31"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr-invert.png
new file mode 100644
index 00000000..6409de22
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr-invert.svg
new file mode 100644
index 00000000..500bbfba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M19 20H2l3-3V6h17v11c0 1.7-1.3 3-3 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr.png
new file mode 100644
index 00000000..2eedf9f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr.svg
new file mode 100644
index 00000000..83d47c1d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19 20H2l3-3V6h17v11c0 1.7-1.3 3-3 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl-invert.png
new file mode 100644
index 00000000..e85fd440
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl-invert.svg
new file mode 100644
index 00000000..1a9f6c87
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M5 20h17l-3-3V6H2v11c0 1.7 1.3 3 3 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl.png
new file mode 100644
index 00000000..0d144431
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl.svg
new file mode 100644
index 00000000..e7dd6681
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubble-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 20h17l-3-3V6H2v11c0 1.7 1.3 3 3 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr-invert.png
new file mode 100644
index 00000000..9de1eabb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr-invert.svg
new file mode 100644
index 00000000..701dbd48
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm8 3h1v3h3v1h-3v3h-1v-3h-3v-1h3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr.png
new file mode 100644
index 00000000..aafac18f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr.svg
new file mode 100644
index 00000000..c7134c33
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm8 3h1v3h3v1h-3v3h-1v-3h-3v-1h3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl-invert.png
new file mode 100644
index 00000000..0520123f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl-invert.svg
new file mode 100644
index 00000000..8ae203e3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M2 6v11c0 1.7 1.3 3 3 3h17l-3-3V6H2zm8 3h1v3h3v1h-3v3h-1v-3H7v-1h3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl.png
new file mode 100644
index 00000000..92548440
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl.svg
new file mode 100644
index 00000000..08462e0c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbleAdd-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M2 6v11c0 1.7 1.3 3 3 3h17l-3-3V6H2zm8 3h1v3h3v1h-3v3h-1v-3H7v-1h3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr-invert.png
new file mode 100644
index 00000000..24a8e4e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr-invert.svg
new file mode 100644
index 00000000..090099b3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M20 9v9l2 2H8V9h12zM3 4h12v4H7v7H1l2-2V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr.png
new file mode 100644
index 00000000..f2e0564d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr.svg
new file mode 100644
index 00000000..d6832183
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 9v9l2 2H8V9h12zM3 4h12v4H7v7H1l2-2V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl-invert.png
new file mode 100644
index 00000000..4119746b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl-invert.svg
new file mode 100644
index 00000000..18456842
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M3 9v9l-2 2h14V9H3zm17-5H8v4h8v7h6l-2-2V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl.png
new file mode 100644
index 00000000..9c67f3fe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl.svg
new file mode 100644
index 00000000..db548a45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/speechBubbles-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 9v9l-2 2h14V9H3zm17-5H8v4h8v7h6l-2-2V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-constructive.png
new file mode 100644
index 00000000..39e79786
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-constructive.svg
new file mode 100644
index 00000000..4a6dae99
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-constructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-invert.png
new file mode 100644
index 00000000..7c949a68
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-invert.svg
new file mode 100644
index 00000000..c7457061
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-progressive.png
new file mode 100644
index 00000000..39e79786
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-progressive.svg
new file mode 100644
index 00000000..4a6dae99
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star.png
new file mode 100644
index 00000000..36b6a1ff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star.svg
new file mode 100644
index 00000000..54ba77ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/star.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop-invert.png
new file mode 100644
index 00000000..4c74c3e2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop-invert.svg
new file mode 100644
index 00000000..8b49792b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 6c3.9 0 7 3.1 7 7s-3.1 7-7 7-7-3.1-7-7 3.1-7 7-7m0-1c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm-3 5h6v6H9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop.png
new file mode 100644
index 00000000..12a19125
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop.svg
new file mode 100644
index 00000000..aa25e3d4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stop.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 6c3.9 0 7 3.1 7 7s-3.1 7-7 7-7-3.1-7-7 3.1-7 7-7m0-1c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm-3 5h6v6H9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a-invert.png
new file mode 100644
index 00000000..ebabd3b2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a-invert.svg
new file mode 100644
index 00000000..6f3ab7ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="strikethrough-a">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a.png
new file mode 100644
index 00000000..279d1f72
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a.svg
new file mode 100644
index 00000000..070d7853
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-a.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="strikethrough-a">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s-invert.png
new file mode 100644
index 00000000..2a29a6ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s-invert.svg
new file mode 100644
index 00000000..b3361b10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="strikethrough-s">
+ <path id="strikethrough" d="M6 12h12v1H6v-1z"/>
+ <path id="s" d="M12.094 6c-1.133 0-2.076.287-2.75.9-.67.613-1 1.49-1 2.52 0 .89.22 1.602.72 2.13.497.528 1.278.91 2.31 1.14l.813.182v-.03c.656.147 1.128.375 1.375.63.252.256.375.607.375 1.11 0 .573-.172.97-.53 1.26-.36.29-.895.45-1.626.45-.47 0-.962-.074-1.462-.24a7.288 7.288 0 0 1-1.562-.75l-.374-.238v2.158l.156.062c.58.237 1.144.417 1.69.54.548.12 1.07.18 1.56.18 1.287 0 2.298-.293 3-.9.71-.605 1.063-1.486 1.063-2.608 0-.943-.256-1.726-.78-2.312-.522-.592-1.306-1-2.345-1.23l-.812-.18c-.714-.148-1.202-.352-1.404-.54-.206-.202-.313-.484-.313-.934 0-.533.162-.9.5-1.17.342-.27.836-.42 1.53-.42.396 0 .82.052 1.25.18.434.128.91.334 1.407.6l.375.18V6.63s-1.19-.383-1.69-.48c-.5-.097-.983-.15-1.467-.15z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s.png
new file mode 100644
index 00000000..21b9baaf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s.svg
new file mode 100644
index 00000000..171f8f38
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-s.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="strikethrough-s">
+ <path id="strikethrough" d="M6 12h12v1H6v-1z"/>
+ <path id="s" d="M12.094 6c-1.133 0-2.076.287-2.75.9-.67.613-1 1.49-1 2.52 0 .89.22 1.602.72 2.13.497.528 1.278.91 2.31 1.14l.813.182v-.03c.656.147 1.128.375 1.375.63.252.256.375.607.375 1.11 0 .573-.172.97-.53 1.26-.36.29-.895.45-1.626.45-.47 0-.962-.074-1.462-.24a7.288 7.288 0 0 1-1.562-.75l-.374-.238v2.158l.156.062c.58.237 1.144.417 1.69.54.548.12 1.07.18 1.56.18 1.287 0 2.298-.293 3-.9.71-.605 1.063-1.486 1.063-2.608 0-.943-.256-1.726-.78-2.312-.522-.592-1.306-1-2.345-1.23l-.812-.18c-.714-.148-1.202-.352-1.404-.54-.206-.202-.313-.484-.313-.934 0-.533.162-.9.5-1.17.342-.27.836-.42 1.53-.42.396 0 .82.052 1.25.18.434.128.91.334 1.407.6l.375.18V6.63s-1.19-.383-1.69-.48c-.5-.097-.983-.15-1.467-.15z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y-invert.png
new file mode 100644
index 00000000..5ed90976
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y-invert.svg
new file mode 100644
index 00000000..bdb6528f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="strikethrough-y">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M7 6h1.724l3.288 4.935L15.276 6H17l-4.194 6.285V18h-1.612v-5.715L7 6"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y.png
new file mode 100644
index 00000000..d7694682
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y.svg
new file mode 100644
index 00000000..2fdbc871
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/strikethrough-y.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="strikethrough-y">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M7 6h1.724l3.288 4.935L15.276 6H17l-4.194 6.285V18h-1.612v-5.715L7 6"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr-invert.png
new file mode 100644
index 00000000..966d7d92
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr-invert.svg
new file mode 100644
index 00000000..7eaeea52
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M4 9h12v2H4V9zm0 3h8v2H4v-2zm0-7h16v3H4V5zm16 14H4v-3h16v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr.png
new file mode 100644
index 00000000..5423b36e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr.svg
new file mode 100644
index 00000000..2112bb2d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 9h12v2H4V9zm0 3h8v2H4v-2zm0-7h16v3H4V5zm16 14H4v-3h16v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl-invert.png
new file mode 100644
index 00000000..a89c9922
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl-invert.svg
new file mode 100644
index 00000000..f23d8ab9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M20 9H8v2h12V9zm0 3h-8v2h8v-2zm0-7H4v3h16V5zM4 19h16v-3H4v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl.png
new file mode 100644
index 00000000..0ff3d7cf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl.svg
new file mode 100644
index 00000000..39790a9a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeFlow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 9H8v2h12V9zm0 3h-8v2h8v-2zm0-7H4v3h16V5zM4 19h16v-3H4v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu-invert.png
new file mode 100644
index 00000000..19691959
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu-invert.svg
new file mode 100644
index 00000000..5600c605
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M20 19H4v-2h16v2zM20 15H4v-2h16v2zM20 11H4V9h16v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu.png
new file mode 100644
index 00000000..93c22fbe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu.svg
new file mode 100644
index 00000000..e63a7d5c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSideMenu.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 19H4v-2h16v2zM20 15H4v-2h16v2zM20 11H4V9h16v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr-invert.png
new file mode 100644
index 00000000..fdbdabe8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr-invert.svg
new file mode 100644
index 00000000..8f263c07
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M20 11H4V9h16v2zM4 12h8v2H4v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr.png
new file mode 100644
index 00000000..21af7858
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr.svg
new file mode 100644
index 00000000..767d6cda
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 11H4V9h16v2zM4 12h8v2H4v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl-invert.png
new file mode 100644
index 00000000..96795300
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl-invert.svg
new file mode 100644
index 00000000..f543b9df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M4 11h16V9H4v2zm16 1h-8v2h8v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl.png
new file mode 100644
index 00000000..82ca2bf5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl.svg
new file mode 100644
index 00000000..4d16337e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeSummary-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 11h16V9H4v2zm16 1h-8v2h8v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-invert.png
new file mode 100644
index 00000000..629ea356
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-invert.svg
new file mode 100644
index 00000000..52487c4e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M17 13H4v-3h13v3zm-5 6H4v-3h8v3zM4 7V4h16v3H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-progressive.png
new file mode 100644
index 00000000..126e8bd4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-progressive.svg
new file mode 100644
index 00000000..7c367768
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M17 13H4v-3h13v3zm-5 6H4v-3h8v3zM4 7V4h16v3H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr.png
new file mode 100644
index 00000000..b482d3e6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr.svg
new file mode 100644
index 00000000..d7c202e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 13H4v-3h13v3zm-5 6H4v-3h8v3zM4 7V4h16v3H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-invert.png
new file mode 100644
index 00000000..f81e503c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-invert.svg
new file mode 100644
index 00000000..f656017e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M7 13h13v-3H7v3zm5 6h8v-3h-8v3zm8-12V4H4v3h16z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-progressive.png
new file mode 100644
index 00000000..03b65551
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-progressive.svg
new file mode 100644
index 00000000..26a9fc50
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M7 13h13v-3H7v3zm5 6h8v-3h-8v3zm8-12V4H4v3h16z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl.png
new file mode 100644
index 00000000..516bc2c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl.svg
new file mode 100644
index 00000000..0859be6b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/stripeToC-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 13h13v-3H7v3zm5 6h8v-3h-8v3zm8-12V4H4v3h16z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr-invert.png
new file mode 100644
index 00000000..f7f291e5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr-invert.svg
new file mode 100644
index 00000000..4638e319
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 13l-1 1v3l1 1h-1l-.527-.46L16 18h-1l1-1v-3l-1-1h1l.485.497L17 13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr.png
new file mode 100644
index 00000000..c2cf4cf5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr.svg
new file mode 100644
index 00000000..fbb0c3c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 13l-1 1v3l1 1h-1l-.527-.46L16 18h-1l1-1v-3l-1-1h1l.485.497L17 13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl-invert.png
new file mode 100644
index 00000000..56ad252a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl-invert.svg
new file mode 100644
index 00000000..76a8659c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 13l1 1v3l-1 1h1l.527-.46L10 18h1l-1-1v-3l1-1h-1l-.485.497L9 13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl.png
new file mode 100644
index 00000000..b1ee51b6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl.svg
new file mode 100644
index 00000000..91a71ecc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/subscript-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 13l1 1v3l-1 1h1l.527-.46L10 18h1l-1-1v-3l1-1h-1l-.485.497L9 13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr-invert.png
new file mode 100644
index 00000000..2bc944a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr-invert.svg
new file mode 100644
index 00000000..76601efd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9s-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4s.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9s.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8s.1-.6.3-.8z"/>
+ <circle cx="12" cy="11" r="4"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr.png
new file mode 100644
index 00000000..0c00745b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr.svg
new file mode 100644
index 00000000..4bde1836
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9s-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4s.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9s.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8s.1-.6.3-.8z"/>
+ <circle cx="12" cy="11" r="4"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl-invert.png
new file mode 100644
index 00000000..7ac54ff4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl-invert.svg
new file mode 100644
index 00000000..99bed351
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M5.9 5.1c0 .3.1.6.3.9l1.4 1.4.9-.8-2.2-2.2c-.3.1-.4.4-.4.7zm.5 5.3H3.2c0 .3.1.6.4.9.3.3.5.4.8.4h2v-1.3zm6.2-5V2.2c-.3 0-.6.1-.9.4-.3.3-.4.5-.4.8v2h1.3zM6.2 17.1c.3 0 .6-.1.8-.3l1.4-1.4-.8-.8-2.2 2.2c.2.2.5.3.8.3zM17.8 4.9c-.3 0-.6.1-.8.3l-1.4 1.4.8.9 2.2-2.3c-.2-.2-.5-.3-.8-.3zm-5.2 11.7h-1.2v3.2c.3 0 .6-.1.9-.4.3-.3.4-.5.4-.8l-.1-2zm7-6.2h-2v1.2h3.2c0-.3-.1-.6-.4-.9-.3-.3-.5-.3-.8-.3zM17.8 16l-1.4-1.4-.8.8 2.2 2.2c.2-.2.3-.5.3-.8 0-.3-.1-.6-.3-.8z"/>
+ <circle cx="12" cy="11" r="4" transform="matrix(-1 0 0 1 24 0)"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl.png
new file mode 100644
index 00000000..77c78060
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl.svg
new file mode 100644
index 00000000..868334e4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/sun-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5.9 5.1c0 .3.1.6.3.9l1.4 1.4.9-.8-2.2-2.2c-.3.1-.4.4-.4.7zm.5 5.3H3.2c0 .3.1.6.4.9.3.3.5.4.8.4h2v-1.3zm6.2-5V2.2c-.3 0-.6.1-.9.4-.3.3-.4.5-.4.8v2h1.3zM6.2 17.1c.3 0 .6-.1.8-.3l1.4-1.4-.8-.8-2.2 2.2c.2.2.5.3.8.3zM17.8 4.9c-.3 0-.6.1-.8.3l-1.4 1.4.8.9 2.2-2.3c-.2-.2-.5-.3-.8-.3zm-5.2 11.7h-1.2v3.2c.3 0 .6-.1.9-.4.3-.3.4-.5.4-.8l-.1-2zm7-6.2h-2v1.2h3.2c0-.3-.1-.6-.4-.9-.3-.3-.5-.3-.8-.3zM17.8 16l-1.4-1.4-.8.8 2.2 2.2c.2-.2.3-.5.3-.8 0-.3-.1-.6-.3-.8z"/>
+ <circle cx="12" cy="11" r="4" transform="matrix(-1 0 0 1 24 0)"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr-invert.png
new file mode 100644
index 00000000..abb7229e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr-invert.svg
new file mode 100644
index 00000000..bd2e11d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 7l-1 1v3l1 1h-1l-.527-.46L16 12h-1l1-1V8l-1-1h1l.485.497L17 7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr.png
new file mode 100644
index 00000000..8df46091
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr.svg
new file mode 100644
index 00000000..45abfda2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 7l-1 1v3l1 1h-1l-.527-.46L16 12h-1l1-1V8l-1-1h1l.485.497L17 7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl-invert.png
new file mode 100644
index 00000000..ee76ff42
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl-invert.svg
new file mode 100644
index 00000000..7e0f907b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 7l1 1v3l-1 1h1l.527-.46L10 12h1l-1-1V8l1-1h-1l-.485.497L9 7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl.png
new file mode 100644
index 00000000..48bfd688
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl.svg
new file mode 100644
index 00000000..33b5814b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/superscript-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 7l1 1v3l-1 1h1l.527-.46L10 12h1l-1-1V8l1-1h-1l-.485.497L9 7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption-invert.png
new file mode 100644
index 00000000..9d50a427
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption-invert.svg
new file mode 100644
index 00000000..72af30cf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="table-caption">
+ <path id="caption" d="M6 6h12v3H6z"/>
+ <path id="table" d="M4 10v7h16v-7H4zm1 1h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2zM5 14h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption.png
new file mode 100644
index 00000000..80b474d4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption.svg
new file mode 100644
index 00000000..6b7edc6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-caption.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-caption">
+ <path id="caption" d="M6 6h12v3H6z"/>
+ <path id="table" d="M4 10v7h16v-7H4zm1 1h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2zM5 14h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr-invert.png
new file mode 100644
index 00000000..5884af36
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr-invert.svg
new file mode 100644
index 00000000..37449b3e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="table-insert-column-ltr">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h2v14H5z" id="column"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr.png
new file mode 100644
index 00000000..64c21487
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr.svg
new file mode 100644
index 00000000..a67ed201
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-column-ltr">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h2v14H5z" id="column"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl-invert.png
new file mode 100644
index 00000000..b3790720
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl-invert.svg
new file mode 100644
index 00000000..7dbd4f6e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="table-insert-column-rtl">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M17 5h2v14h-2z" id="column"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl.png
new file mode 100644
index 00000000..650be0c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl.svg
new file mode 100644
index 00000000..dee782e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-column-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-column-rtl">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M17 5h2v14h-2z" id="column"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after-invert.png
new file mode 100644
index 00000000..e0737909
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after-invert.svg
new file mode 100644
index 00000000..fdb668f9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="table-insert-row-after">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 17h14v2H5z" id="row"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after.png
new file mode 100644
index 00000000..67d488da
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after.svg
new file mode 100644
index 00000000..ad9d86db
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-after.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-row-after">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 17h14v2H5z" id="row"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before-invert.png
new file mode 100644
index 00000000..6a5f1a0d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before-invert.svg
new file mode 100644
index 00000000..38998d4c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="table-insert-row-before">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h14v2H5z" id="row"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before.png
new file mode 100644
index 00000000..24774750
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before.svg
new file mode 100644
index 00000000..e9dfe048
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-insert-row-before.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-row-before">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h14v2H5z" id="row"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.png
new file mode 100644
index 00000000..4c192030
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.svg
new file mode 100644
index 00000000..3866463a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="table-insert">
+ <path id="table" d="M4 6v11h15V6zm1 3h6v3H5zm7 0h6v3h-6zm-7 4h6v3H5zm7 0h6v3h-6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells-invert.png
new file mode 100644
index 00000000..b24537d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells-invert.svg
new file mode 100644
index 00000000..bd571af7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells-invert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="table-merge-cells">
+ <g id="merge-cell-left">
+ <path id="cell-border" d="M4 7v9h7v-3l-1 .834V15H5V8h5v1.167L11 10V7z"/>
+ <path id="arrow" d="M8 9v2H6v1h2v2l3-2.5z"/>
+ </g>
+ <use id="merge-cell-right" xlink:href="#merge-cell-left" transform="matrix(-1 0 0 1 24 0)"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells.png
new file mode 100644
index 00000000..e6b2da3e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells.svg
new file mode 100644
index 00000000..3ffb9e5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table-merge-cells.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-merge-cells">
+ <g id="merge-cell-left">
+ <path id="cell-border" d="M4 7v9h7v-3l-1 .834V15H5V8h5v1.167L11 10V7z"/>
+ <path id="arrow" d="M8 9v2H6v1h2v2l3-2.5z"/>
+ </g>
+ <use id="merge-cell-right" xlink:href="#merge-cell-left" transform="matrix(-1 0 0 1 24 0)"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table.png
new file mode 100644
index 00000000..f4008f6b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table.svg
new file mode 100644
index 00000000..b5733fba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/table.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert">
+ <path id="table" d="M4 6v11h15V6zm1 3h6v3H5zm7 0h6v3h-6zm-7 4h6v3H5zm7 0h6v3h-6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-constructive.png
new file mode 100644
index 00000000..41e2735f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-constructive.svg
new file mode 100644
index 00000000..15263064
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-constructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.png
new file mode 100644
index 00000000..45d27671
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.svg
new file mode 100644
index 00000000..1058e830
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d11d13 }</style>
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-invert.png
new file mode 100644
index 00000000..fd5956cb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-invert.svg
new file mode 100644
index 00000000..066801a0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-progressive.png
new file mode 100644
index 00000000..41e2735f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-progressive.svg
new file mode 100644
index 00000000..15263064
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-warning.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-warning.png
new file mode 100644
index 00000000..880616f8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-warning.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-warning.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-warning.svg
new file mode 100644
index 00000000..df57de54
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag-warning.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ff5d00 }</style>
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag.png
new file mode 100644
index 00000000..82461ef7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag.svg
new file mode 100644
index 00000000..7a211a3f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/tag.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr-invert.png
new file mode 100644
index 00000000..cba38d26
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr-invert.svg
new file mode 100644
index 00000000..2f1a02ac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="template-add">
+ <path id="add" d="M23 7h-4V3h-2v4h-4v2h4v4h2V9h4z"/>
+ <path id="template" d="M18 14v4H6c-1.1 0-2-.9-2-2V8h8V7H3v9c0 1.7 1.3 3 3 3h13v-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr.png
new file mode 100644
index 00000000..f3ce49ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr.svg
new file mode 100644
index 00000000..8cd95e0a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="template-add">
+ <path id="add" d="M23 7h-4V3h-2v4h-4v2h4v4h2V9h4z"/>
+ <path id="template" d="M18 14v4H6c-1.1 0-2-.9-2-2V8h8V7H3v9c0 1.7 1.3 3 3 3h13v-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl-invert.png
new file mode 100644
index 00000000..eb8d08d8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl-invert.svg
new file mode 100644
index 00000000..70ce39f3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="template-add">
+ <path id="add" d="M1 7h4V3h2v4h4v2H7v4H5V9H1z"/>
+ <path id="template" d="M6 14v4h12c1.1 0 2-.9 2-2V8h-8V7h9v9c0 1.7-1.3 3-3 3H5v-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl.png
new file mode 100644
index 00000000..448caf4f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl.svg
new file mode 100644
index 00000000..62b30f5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/templateAdd-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="template-add">
+ <path id="add" d="M1 7h4V3h2v4h4v2H7v4H5V9H1z"/>
+ <path id="template" d="M6 14v4h12c1.1 0 2-.9 2-2V8h-8V7h9v9c0 1.7-1.3 3-3 3H5v-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright-invert.png
new file mode 100644
index 00000000..44394d9e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright-invert.svg
new file mode 100644
index 00000000..fb1a4667
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M7 7H5V6h2l.47.5L8 6h2v1H8v10h2v1H8l-.5-.53L7 18H5v-1h2zm6.976 9v-2H11v-4h2.976V8.044L20 12.022z" id="text-dir-ltr"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright.png
new file mode 100644
index 00000000..fede39a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright.svg
new file mode 100644
index 00000000..83dd7697
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-lefttoright.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 7H5V6h2l.47.5L8 6h2v1H8v10h2v1H8l-.5-.53L7 18H5v-1h2zm6.976 9v-2H11v-4h2.976V8.044L20 12.022z" id="text-dir-ltr"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft-invert.png
new file mode 100644
index 00000000..d5b78c24
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft-invert.svg
new file mode 100644
index 00000000..867e464a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M17 17h2v1h-2l-.47-.5-.53.5h-2v-1h2V7h-2V6h2l.5.53L17 6h2v1h-2zm-6.976-9v2H13v4h-2.976v1.956L4 11.978z" id="text-dir-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft.png
new file mode 100644
index 00000000..9f60ed5a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft.svg
new file mode 100644
index 00000000..78cb85b3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-dir-righttoleft.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 17h2v1h-2l-.47-.5-.53.5h-2v-1h2V7h-2V6h2l.5.53L17 6h2v1h-2zm-6.976-9v2H13v4h-2.976v1.956L4 11.978z" id="text-dir-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style-invert.png
new file mode 100644
index 00000000..f173ad7c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style-invert.svg
new file mode 100644
index 00000000..9a713d93
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="text-style">
+ <path id="a" d="M15.296 18h2.79l-1.14-12h-2.79L6 18h2.79l2.038-3h4.183l.29 3zm-3.11-5L14.5 9.6l.323 3.4H12.19z"/>
+ <path id="underline" d="M6 19h12v1H6v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style.png
new file mode 100644
index 00000000..65ab476a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style.svg
new file mode 100644
index 00000000..466672eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/text-style.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="text-style">
+ <path id="a" d="M15.296 18h2.79l-1.14-12h-2.79L6 18h2.79l2.038-3h4.183l.29 3zm-3.11-5L14.5 9.6l.323 3.4H12.19z"/>
+ <path id="underline" d="M6 19h12v1H6v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.png
new file mode 100644
index 00000000..722eebe7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.svg
new file mode 100644
index 00000000..7489b7a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d11d13 }</style>
+ <path d="M6 8c0-1.1.9-2 2-2h2l1-1h2l1 1h2c1.1 0 2 .9 2 2H6zm1 1h10l-1 11H8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-invert.png
new file mode 100644
index 00000000..04eaa413
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-invert.svg
new file mode 100644
index 00000000..90c82f21
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M6 8c0-1.1.9-2 2-2h2l1-1h2l1 1h2c1.1 0 2 .9 2 2H6zm1 1h10l-1 11H8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash.png
new file mode 100644
index 00000000..b3e899d8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash.svg
new file mode 100644
index 00000000..76502dce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trash.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6 8c0-1.1.9-2 2-2h2l1-1h2l1 1h2c1.1 0 2 .9 2 2H6zm1 1h10l-1 11H8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr-invert.png
new file mode 100644
index 00000000..af3f0e98
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr-invert.svg
new file mode 100644
index 00000000..70b6f83e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M20.5 20.5L5 5 4 6l3 3 1 11h8l.2-1.8 3.3 3.3zM17 9h-6l5.5 5.5zm1-1c0-1.1-.9-2-2-2h-2l-1-1h-2l-1 1H8l2 2h8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr.png
new file mode 100644
index 00000000..3b5231fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr.svg
new file mode 100644
index 00000000..64b3b71e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20.5 20.5L5 5 4 6l3 3 1 11h8l.2-1.8 3.3 3.3zM17 9h-6l5.5 5.5zm1-1c0-1.1-.9-2-2-2h-2l-1-1h-2l-1 1H8l2 2h8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl-invert.png
new file mode 100644
index 00000000..1cb54499
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl-invert.svg
new file mode 100644
index 00000000..d5edf148
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M4 20.5L19.5 5l1 1-3 3-1 11h-8l-.2-1.8L5 21.5zM7.5 9h6L8 14.5zm-1-1c0-1.1.9-2 2-2h2l1-1h2l1 1h2l-2 2h-8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl.png
new file mode 100644
index 00000000..a1d23882
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl.svg
new file mode 100644
index 00000000..e5e40322
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/trashUndo-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 20.5L19.5 5l1 1-3 3-1 11h-8l-.2-1.8L5 21.5zM7.5 9h6L8 14.5zm-1-1c0-1.1.9-2 2-2h2l1-1h2l1 1h2l-2 2h-8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.png
new file mode 100644
index 00000000..3b9a7360
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.svg
new file mode 100644
index 00000000..385686c8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d11d13 }</style>
+ <path d="M12 9V7s0-5-4.5-5S3 7 3 7h2s0-3 2.5-3S10 7 10 7v2H7v7c0 1.7 1.3 3 3 3h10V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-invert.png
new file mode 100644
index 00000000..68c14374
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-invert.svg
new file mode 100644
index 00000000..3ac59e0e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 9V7s0-5-4.5-5S3 7 3 7h2s0-3 2.5-3S10 7 10 7v2H7v7c0 1.7 1.3 3 3 3h10V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr.png
new file mode 100644
index 00000000..e6d9aae4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr.svg
new file mode 100644
index 00000000..25e08600
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 9V7s0-5-4.5-5S3 7 3 7h2s0-3 2.5-3S10 7 10 7v2H7v7c0 1.7 1.3 3 3 3h10V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.png
new file mode 100644
index 00000000..7db9feae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.svg
new file mode 100644
index 00000000..0f79916f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #d11d13 }</style>
+ <path d="M11 9V7s0-5 4.5-5S20 7 20 7h-2s0-3-2.5-3S13 7 13 7v2h3v7c0 1.7-1.3 3-3 3H3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-invert.png
new file mode 100644
index 00000000..d50b4c70
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-invert.svg
new file mode 100644
index 00000000..d182c6d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M11 9V7s0-5 4.5-5S20 7 20 7h-2s0-3-2.5-3S13 7 13 7v2h3v7c0 1.7-1.3 3-3 3H3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl.png
new file mode 100644
index 00000000..0529c16c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl.svg
new file mode 100644
index 00000000..577b5705
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unLock-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 9V7s0-5 4.5-5S20 7 20 7h-2s0-3-2.5-3S13 7 13 7v2h3v7c0 1.7-1.3 3-3 3H3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-constructive.png
new file mode 100644
index 00000000..76019517
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-constructive.svg
new file mode 100644
index 00000000..131743d9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-constructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M21 11l-6-1-3-6-3 6-6 1 4 4-1 6 6-3 6 3-1-6 4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-invert.png
new file mode 100644
index 00000000..20ce036d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-invert.svg
new file mode 100644
index 00000000..73d8054e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M21 11l-6-1-3-6-3 6-6 1 4 4-1 6 6-3 6 3-1-6 4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-progressive.png
new file mode 100644
index 00000000..76019517
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-progressive.svg
new file mode 100644
index 00000000..131743d9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #347bff }</style>
+ <path d="M21 11l-6-1-3-6-3 6-6 1 4 4-1 6 6-3 6 3-1-6 4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar.png
new file mode 100644
index 00000000..2329af3e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar.svg
new file mode 100644
index 00000000..724d1901
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/unStar.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 11l-6-1-3-6-3 6-6 1 4 4-1 6 6-3 6 3-1-6 4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a-invert.png
new file mode 100644
index 00000000..8a6ca429
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a-invert.svg
new file mode 100644
index 00000000..79fcbf3d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="underline-a">
+ <path id="a" d="M14.424 16H16.5L13.037 6H10.96L7.5 16h2.077l.627-2h3.604l.616 2zm-3.92-3.623L12 7.997l1.51 4.38h-3z"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a.png
new file mode 100644
index 00000000..78a3c3f0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a.svg
new file mode 100644
index 00000000..1ddae104
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-a.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="underline-a">
+ <path id="a" d="M14.424 16H16.5L13.037 6H10.96L7.5 16h2.077l.627-2h3.604l.616 2zm-3.92-3.623L12 7.997l1.51 4.38h-3z"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u-invert.png
new file mode 100644
index 00000000..9f0af6c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u-invert.svg
new file mode 100644
index 00000000..9e7353ed
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="underline-u">
+ <path id="u" d="M8 6h2v5.96c-.104 1.706.695 2 2 2.04 1.777.062 2.002-.88 2-2.04V6h2v6.123c0 1.28-.338 2.245-1.016 2.898-.672.658-1.666.98-2.98.98-1.32 0-2.32-.32-2.996-.98C8.336 14.37 8 13.41 8 12.13V6"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u.png
new file mode 100644
index 00000000..0dbeb80c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u.svg
new file mode 100644
index 00000000..ff47e2ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/underline-u.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="underline-u">
+ <path id="u" d="M8 6h2v5.96c-.104 1.706.695 2 2 2.04 1.777.062 2.002-.88 2-2.04V6h2v6.123c0 1.28-.338 2.245-1.016 2.898-.672.658-1.666.98-2.98.98-1.32 0-2.32-.32-2.996-.98C8.336 14.37 8 13.41 8 12.13V6"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle-invert.png
new file mode 100644
index 00000000..9fcea7f3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle-invert.svg
new file mode 100644
index 00000000..52223ab2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M12 8l8 10H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle.png
new file mode 100644
index 00000000..f1aca31a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle.svg
new file mode 100644
index 00000000..9f0efc59
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upTriangle.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 8l8 10H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr-invert.png
new file mode 100644
index 00000000..aa26066b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr-invert.svg
new file mode 100644
index 00000000..f29501fb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M10 13c0 1.7 1.3 3 3 3V9h3l-4.5-5L7 9h3v4zm7 0v5H7c-.6 0-1-.4-1-1v-4H4v4c0 1.9 1.3 3 3 3h12v-7h-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr.png
new file mode 100644
index 00000000..08e31e9e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr.svg
new file mode 100644
index 00000000..dc4676fb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10 13c0 1.7 1.3 3 3 3V9h3l-4.5-5L7 9h3v4zm7 0v5H7c-.6 0-1-.4-1-1v-4H4v4c0 1.9 1.3 3 3 3h12v-7h-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl-invert.png
new file mode 100644
index 00000000..602ae423
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl-invert.svg
new file mode 100644
index 00000000..68b8b1fb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M13 13c0 1.7-1.3 3-3 3V9H7l4.5-5L16 9h-3v4zm-7 0v5h10c.6 0 1-.4 1-1v-4h2v4c0 1.9-1.3 3-3 3H4v-7h2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl.png
new file mode 100644
index 00000000..ccabf989
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl.svg
new file mode 100644
index 00000000..ed3fe772
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/upload-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M13 13c0 1.7-1.3 3-3 3V9H7l4.5-5L16 9h-3v4zm-7 0v5h10c.6 0 1-.4 1-1v-4h2v4c0 1.9-1.3 3-3 3H4v-7h2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr-invert.png
new file mode 100644
index 00000000..98083bea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr-invert.svg
new file mode 100644
index 00000000..af68b98b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M16 5H4v12c0 1.7 1.3 3 3 3h12V8c0-1.7-1.3-3-3-3zm-2 4c.7 0 1.2.6 1.2 1.2s-.6 1.2-1.2 1.2-1.2-.6-1.2-1.2S13.3 9 14 9zM9 9c.7 0 1.2.6 1.2 1.2s-.5 1.3-1.2 1.3-1.2-.6-1.2-1.2S8.3 9 9 9zm7 5.4c0 .2-.1.3-.3.5-.7.6-1.6 1-2.6 1.3s-2.1.2-3.1 0-2-.9-2.7-1.5c-.1-.1-.2-.3-.2-.4s.1-.3.2-.4c.1-.1.3-.2.4-.2.2 0 .3.1.4.2.5.5 1.2.9 2.1 1.1s1.7.2 2.6 0 1.6-.5 2.1-1c.1-.1.3-.2.4-.2s.3.1.5.2.2.2.2.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr.png
new file mode 100644
index 00000000..ce385f97
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr.svg
new file mode 100644
index 00000000..7f526e52
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 5H4v12c0 1.7 1.3 3 3 3h12V8c0-1.7-1.3-3-3-3zm-2 4c.7 0 1.2.6 1.2 1.2s-.6 1.2-1.2 1.2-1.2-.6-1.2-1.2S13.3 9 14 9zM9 9c.7 0 1.2.6 1.2 1.2s-.5 1.3-1.2 1.3-1.2-.6-1.2-1.2S8.3 9 9 9zm7 5.4c0 .2-.1.3-.3.5-.7.6-1.6 1-2.6 1.3s-2.1.2-3.1 0-2-.9-2.7-1.5c-.1-.1-.2-.3-.2-.4s.1-.3.2-.4c.1-.1.3-.2.4-.2.2 0 .3.1.4.2.5.5 1.2.9 2.1 1.1s1.7.2 2.6 0 1.6-.5 2.1-1c.1-.1.3-.2.4-.2s.3.1.5.2.2.2.2.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl-invert.png
new file mode 100644
index 00000000..3dc0f442
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl-invert.svg
new file mode 100644
index 00000000..80c3aa85
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M7 5h12v12c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3zm2 4c-.7 0-1.2.6-1.2 1.2s.6 1.2 1.2 1.2 1.2-.6 1.2-1.2S9.7 9 9 9zm5 0c-.7 0-1.2.6-1.2 1.2s.5 1.3 1.2 1.3 1.2-.6 1.2-1.2S14.7 9 14 9zm-7 5.4c0 .2.1.3.3.5.7.6 1.6 1 2.6 1.3 1 .3 2.1.2 3.1 0s2-.9 2.7-1.5c.1-.1.2-.3.2-.4 0-.1-.1-.3-.2-.4-.1-.1-.3-.2-.4-.2-.2 0-.3.1-.4.2-.5.5-1.2.9-2.1 1.1-.9.2-1.7.2-2.6 0-.9-.2-1.6-.5-2.1-1-.1-.1-.3-.2-.4-.2-.1 0-.3.1-.5.2s-.2.2-.2.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl.png
new file mode 100644
index 00000000..ee1afbce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl.svg
new file mode 100644
index 00000000..838ae31c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userActive-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 5h12v12c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3zm2 4c-.7 0-1.2.6-1.2 1.2s.6 1.2 1.2 1.2 1.2-.6 1.2-1.2S9.7 9 9 9zm5 0c-.7 0-1.2.6-1.2 1.2s.5 1.3 1.2 1.3 1.2-.6 1.2-1.2S14.7 9 14 9zm-7 5.4c0 .2.1.3.3.5.7.6 1.6 1 2.6 1.3 1 .3 2.1.2 3.1 0s2-.9 2.7-1.5c.1-.1.2-.3.2-.4 0-.1-.1-.3-.2-.4-.1-.1-.3-.2-.4-.2-.2 0-.3.1-.4.2-.5.5-1.2.9-2.1 1.1-.9.2-1.7.2-2.6 0-.9-.2-1.6-.5-2.1-1-.1-.1-.3-.2-.4-.2-.1 0-.3.1-.5.2s-.2.2-.2.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar-invert.png
new file mode 100644
index 00000000..1f4d3a4d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar-invert.svg
new file mode 100644
index 00000000..60a35c7b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M18.75 17.4c-1.08-.36-3.6-1.35-3.6-1.35-.81-.27-.81-.99-.9-1.8v-.09c1.26-1.08 2.25-2.88 2.25-4.86 0-4.23-1.8-5.85-4.5-5.85-1.89 0-4.5 1.08-4.5 5.85 0 1.89.99 3.69 2.25 4.86v.09c0 .81-.09 1.53-.9 1.8 0 0-2.61.99-3.6 1.35-1.17.36-2.25.9-2.25 2.25v.9h18v-.9c0-1.08-.72-1.8-2.25-2.25z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar.png
new file mode 100644
index 00000000..81900956
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar.svg
new file mode 100644
index 00000000..ce714e60
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userAvatar.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.75 17.4c-1.08-.36-3.6-1.35-3.6-1.35-.81-.27-.81-.99-.9-1.8v-.09c1.26-1.08 2.25-2.88 2.25-4.86 0-4.23-1.8-5.85-4.5-5.85-1.89 0-4.5 1.08-4.5 5.85 0 1.89.99 3.69 2.25 4.86v.09c0 .81-.09 1.53-.9 1.8 0 0-2.61.99-3.6 1.35-1.17.36-2.25.9-2.25 2.25v.9h18v-.9c0-1.08-.72-1.8-2.25-2.25z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr-invert.png
new file mode 100644
index 00000000..db34f591
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr-invert.svg
new file mode 100644
index 00000000..9bfdcd90
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M16 5H4v12c0 1.7 1.3 3 3 3h12V8c0-1.7-1.3-3-3-3zm-9.3 5.4C6.2 10 6 9.6 6 9c.6.6 1.5.9 2.5.9s1.9-.3 2.5-.9c0 .6-.2 1-.7 1.4-.5.4-1.1.6-1.8.6s-1.3-.2-1.8-.6zm8.4 4.3c0 .2-.1.3-.3.4-1 .6-2.2.9-3.5.9-1.2 0-2.3-.3-3.3-1-.2-.1-.2-.2-.3-.4s0-.3.1-.5.2-.2.4-.3.3 0 .5.1c.8.5 1.7.8 2.8.8s2-.2 2.8-.7c.1-.1.3-.1.5-.1s.3.1.4.3l-.1.5zm1.2-4.3c-.5.4-1.1.6-1.8.6s-1.3-.2-1.8-.6S12 9.6 12 9c.6.6 1.5.9 2.5.9s1.9-.3 2.5-.9c0 .6-.2 1-.7 1.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr.png
new file mode 100644
index 00000000..05170e12
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr.svg
new file mode 100644
index 00000000..e58bbc3f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 5H4v12c0 1.7 1.3 3 3 3h12V8c0-1.7-1.3-3-3-3zm-9.3 5.4C6.2 10 6 9.6 6 9c.6.6 1.5.9 2.5.9s1.9-.3 2.5-.9c0 .6-.2 1-.7 1.4-.5.4-1.1.6-1.8.6s-1.3-.2-1.8-.6zm8.4 4.3c0 .2-.1.3-.3.4-1 .6-2.2.9-3.5.9-1.2 0-2.3-.3-3.3-1-.2-.1-.2-.2-.3-.4s0-.3.1-.5.2-.2.4-.3.3 0 .5.1c.8.5 1.7.8 2.8.8s2-.2 2.8-.7c.1-.1.3-.1.5-.1s.3.1.4.3l-.1.5zm1.2-4.3c-.5.4-1.1.6-1.8.6s-1.3-.2-1.8-.6S12 9.6 12 9c.6.6 1.5.9 2.5.9s1.9-.3 2.5-.9c0 .6-.2 1-.7 1.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl-invert.png
new file mode 100644
index 00000000..8fe830a4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl-invert.svg
new file mode 100644
index 00000000..309c972a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M7 5h12v12c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3zm9.3 5.4c.5-.4.7-.8.7-1.4-.6.6-1.5.9-2.5.9S12.6 9.6 12 9c0 .6.2 1 .7 1.4.5.4 1.1.6 1.8.6s1.3-.2 1.8-.6zm-8.4 4.3c0 .2.1.3.3.4 1 .6 2.2.9 3.5.9 1.2 0 2.3-.3 3.3-1 .2-.1.2-.2.3-.4.1-.2 0-.3-.1-.5s-.2-.2-.4-.3c-.2-.1-.3 0-.5.1-.8.5-1.7.8-2.8.8-1.1 0-2-.2-2.8-.7-.1-.1-.3-.1-.5-.1s-.3.1-.4.3l.1.5zm-1.2-4.3c.5.4 1.1.6 1.8.6s1.3-.2 1.8-.6c.5-.4.7-.8.7-1.4-.6.6-1.5.9-2.5.9S6.6 9.6 6 9c0 .6.2 1 .7 1.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl.png
new file mode 100644
index 00000000..bf953f1d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl.svg
new file mode 100644
index 00000000..039e6627
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userInactive-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 5h12v12c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3zm9.3 5.4c.5-.4.7-.8.7-1.4-.6.6-1.5.9-2.5.9S12.6 9.6 12 9c0 .6.2 1 .7 1.4.5.4 1.1.6 1.8.6s1.3-.2 1.8-.6zm-8.4 4.3c0 .2.1.3.3.4 1 .6 2.2.9 3.5.9 1.2 0 2.3-.3 3.3-1 .2-.1.2-.2.3-.4.1-.2 0-.3-.1-.5s-.2-.2-.4-.3c-.2-.1-.3 0-.5.1-.8.5-1.7.8-2.8.8-1.1 0-2-.2-2.8-.7-.1-.1-.3-.1-.5-.1s-.3.1-.4.3l.1.5zm-1.2-4.3c.5.4 1.1.6 1.8.6s1.3-.2 1.8-.6c.5-.4.7-.8.7-1.4-.6.6-1.5.9-2.5.9S6.6 9.6 6 9c0 .6.2 1 .7 1.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr-invert.png
new file mode 100644
index 00000000..332bcba6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr-invert.svg
new file mode 100644
index 00000000..9d1146e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm11.2 2.5c.7 0 1.2.6 1.2 1.2s-.5 1.3-1.2 1.3-1.2-.6-1.2-1.2.6-1.3 1.2-1.3zm-5.4 0c.7 0 1.2.6 1.2 1.2s-.6 1.3-1.2 1.3-1.2-.6-1.2-1.2.5-1.3 1.2-1.3zm2.7 8.5c-5.1 0-6-5-6-5s2 1 6 1l6-1s-1 5-6 5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr.png
new file mode 100644
index 00000000..18981fd9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr.svg
new file mode 100644
index 00000000..f277ce4d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm11.2 2.5c.7 0 1.2.6 1.2 1.2s-.5 1.3-1.2 1.3-1.2-.6-1.2-1.2.6-1.3 1.2-1.3zm-5.4 0c.7 0 1.2.6 1.2 1.2s-.6 1.3-1.2 1.3-1.2-.6-1.2-1.2.5-1.3 1.2-1.3zm2.7 8.5c-5.1 0-6-5-6-5s2 1 6 1l6-1s-1 5-6 5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl-invert.png
new file mode 100644
index 00000000..187f3e68
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl-invert.svg
new file mode 100644
index 00000000..47355269
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #FFFFFF }</style>
+ <path d="M19 6v11l3 3H5c-1.7 0-3-1.3-3-3V6h17zM7.8 8.5c-.7 0-1.2.6-1.2 1.2S7.1 11 7.8 11 9 10.4 9 9.8s-.6-1.3-1.2-1.3zm5.4 0c-.7 0-1.2.6-1.2 1.2s.6 1.3 1.2 1.3 1.2-.6 1.2-1.2-.5-1.3-1.2-1.3zM10.5 17c5.1 0 6-5 6-5s-2 1-6 1l-6-1s1 5 6 5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl.png
new file mode 100644
index 00000000..7122efa5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl.svg
new file mode 100644
index 00000000..0f9a6fb3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/userTalk-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19 6v11l3 3H5c-1.7 0-3-1.3-3-3V6h17zM7.8 8.5c-.7 0-1.2.6-1.2 1.2S7.1 11 7.8 11 9 10.4 9 9.8s-.6-1.3-1.2-1.3zm5.4 0c-.7 0-1.2.6-1.2 1.2s.6 1.3 1.2 1.3 1.2-.6 1.2-1.2-.5-1.3-1.2-1.3zM10.5 17c5.1 0 6-5 6-5s-2 1-6 1l-6-1s1 5 6 5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact-invert.png
new file mode 100644
index 00000000..e716ba54
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact-invert.svg
new file mode 100644
index 00000000..25923e25
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact-invert.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="viewCompact">
+ <circle cx="6" cy="6" r="2"/>
+ <circle cx="12" cy="6" r="2"/>
+ <circle cx="18" cy="6" r="2"/>
+ <circle cx="6" cy="12" r="2"/>
+ <circle cx="12" cy="12" r="2"/>
+ <circle cx="18" cy="12" r="2"/>
+ <circle cx="6" cy="18" r="2"/>
+ <circle cx="12" cy="18" r="2"/>
+ <circle cx="18" cy="18" r="2"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact.png
new file mode 100644
index 00000000..13fe4207
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact.svg
new file mode 100644
index 00000000..d96a2e3f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewCompact.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="viewCompact">
+ <circle cx="6" cy="6" r="2"/>
+ <circle cx="12" cy="6" r="2"/>
+ <circle cx="18" cy="6" r="2"/>
+ <circle cx="6" cy="12" r="2"/>
+ <circle cx="12" cy="12" r="2"/>
+ <circle cx="18" cy="12" r="2"/>
+ <circle cx="6" cy="18" r="2"/>
+ <circle cx="12" cy="18" r="2"/>
+ <circle cx="18" cy="18" r="2"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr-invert.png
new file mode 100644
index 00000000..3cfba947
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr-invert.svg
new file mode 100644
index 00000000..4471f593
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr-invert.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="viewDetails">
+ <circle cx="5.5" cy="8.5" r="2.5"/>
+ <path d="M10 6h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ <circle cx="5.5" cy="16.5" r="2.5"/>
+ <path d="M10 14h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr.png
new file mode 100644
index 00000000..4341f0e6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr.svg
new file mode 100644
index 00000000..1a5092a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-ltr.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="viewDetails">
+ <circle cx="5.5" cy="8.5" r="2.5"/>
+ <path d="M10 6h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ <circle cx="5.5" cy="16.5" r="2.5"/>
+ <path d="M10 14h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl-invert.png
new file mode 100644
index 00000000..9bac0da8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl-invert.svg
new file mode 100644
index 00000000..dad4b910
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl-invert.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="viewDetails">
+ <circle cx="18.5" cy="8.5" r="2.5"/>
+ <path d="M14 6H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ <circle cx="18.5" cy="16.5" r="2.5"/>
+ <path d="M14 14H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl.png
new file mode 100644
index 00000000..29059034
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl.svg
new file mode 100644
index 00000000..f43b05f1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/viewDetails-rtl.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="viewDetails">
+ <circle cx="18.5" cy="8.5" r="2.5"/>
+ <path d="M14 6H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ <circle cx="18.5" cy="16.5" r="2.5"/>
+ <path d="M14 14H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator-invert.png
new file mode 100644
index 00000000..e18ee176
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator-invert.svg
new file mode 100644
index 00000000..0e7728f5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M0 10v8h2.3c.3.6 1 1 1.7 1h4c1.5 0 2.7-.8 3-2h2c.3 1.2 1.5 2 3 2h4c.7 0 1.4 0 1.7-1H24v-8zm10 6c0 1-.4 2-2 2H4c-.6 0-1-.4-1-1v-3c0-.6.4-1 1-1h5c.6 0 1 .4 1 1zm11 1c0 .6-.4 1-1 1h-4c-1.6 0-2-1-2-2v-2c0-.6.4-1 1-1h5c.6 0 1 .4 1 1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator.png
new file mode 100644
index 00000000..afa56528
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator.svg
new file mode 100644
index 00000000..ae6ba27a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/visionSimulator.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M0 10v8h2.3c.3.6 1 1 1.7 1h4c1.5 0 2.7-.8 3-2h2c.3 1.2 1.5 2 3 2h4c.7 0 1.4 0 1.7-1H24v-8zm10 6c0 1-.4 2-2 2H4c-.6 0-1-.4-1-1v-3c0-.6.4-1 1-1h5c.6 0 1 .4 1 1zm11 1c0 .6-.4 1-1 1h-4c-1.6 0-2-1-2-2v-2c0-.6.4-1 1-1h5c.6 0 1 .4 1 1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr-invert.png
new file mode 100644
index 00000000..70189688
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr-invert.svg
new file mode 100644
index 00000000..d52e65ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M13 14h5v1h-5v-1zm0 3h5v-1h-5v1zm0 1h5v1h-5v-1zm-1-5v3l-5 3 1-6-4-3 6-1 2-5s1.9 5 2 5l6 1-4 3h-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr.png
new file mode 100644
index 00000000..53e70116
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr.svg
new file mode 100644
index 00000000..b13df22d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M13 14h5v1h-5v-1zm0 3h5v-1h-5v1zm0 1h5v1h-5v-1zm-1-5v3l-5 3 1-6-4-3 6-1 2-5s1.9 5 2 5l6 1-4 3h-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl-invert.png
new file mode 100644
index 00000000..28008b5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl-invert.svg
new file mode 100644
index 00000000..f1939158
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M11 14H6v1h5v-1zm0 3H6v-1h5v1zm0 1H6v1h5v-1zm1-5v3l5 3-1-6 4-3-6-1-2-5s-1.9 5-2 5l-6 1 4 3h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl.png
new file mode 100644
index 00000000..8fc4df52
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl.svg
new file mode 100644
index 00000000..a4ec49a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/watchlist-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 14H6v1h5v-1zm0 3H6v-1h5v1zm0 1H6v1h5v-1zm1-5v3l5 3-1-6 4-3-6-1-2-5s-1.9 5-2 5l-6 1 4 3h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText-invert.png
new file mode 100644
index 00000000..bed3a113
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText-invert.svg
new file mode 100644
index 00000000..131c83df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText-invert.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="wikiText">
+ <path id="opening-bracket-inner" d="M7 19h3v-2H9V7h1V5H7z"/>
+ <path id="closing-bracket-inner" d="M17 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="closing-bracket-outer" d="M21 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="opening-bracket-outer" d="M3 19h3v-2H5V7h1V5H3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText.png
new file mode 100644
index 00000000..40309aac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText.svg
new file mode 100644
index 00000000..4512cf56
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikiText.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="wikiText">
+ <path id="opening-bracket-inner" d="M7 19h3v-2H9V7h1V5H7z"/>
+ <path id="closing-bracket-inner" d="M17 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="closing-bracket-outer" d="M21 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="opening-bracket-outer" d="M3 19h3v-2H5V7h1V5H3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr-invert.png
new file mode 100644
index 00000000..075f84e0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr-invert.svg
new file mode 100644
index 00000000..df03c66c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M15 9l.7-1.8c.9.4 1.8.7 2.4.9l-.6 1.7v.2L15 9zm-4.3-1.9l.8-1.8c1.2.5 2.6 1.1 3 1.4l-.8 1.8-3-1.4zm-5.9-1c-.8 0-1.4.2-2 .6L1.7 5c.9-.6 1.9-.9 3.1-.9v2zm-4.3.7l1.8.8c-.3.7-.3 1.3-.1 1.8l-1.9.7C0 8.9 0 7.8.5 6.8zm4.2 5.4l-1.3 1.5c-1-1-1.7-1.6-2-2l1.5-1.3c.7.8 1.3 1.4 1.8 1.8zm7.3 4.3c0 1.9-1.6 3.5-3.5 3.5S5 18.4 5 16.5 6.6 13 8.5 13s3.5 1.6 3.5 3.5zM24 8l-1-1-1.5 1.5L20 7l-1 1 1.5 1.5L19 11l1 1 1.5-1.5L23 12l1-1-1.5-1.5z"/>
+ <circle cx="8" cy="5" r="2"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr.png
new file mode 100644
index 00000000..331fd595
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr.svg
new file mode 100644
index 00000000..cb073b9d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 9l.7-1.8c.9.4 1.8.7 2.4.9l-.6 1.7v.2L15 9zm-4.3-1.9l.8-1.8c1.2.5 2.6 1.1 3 1.4l-.8 1.8-3-1.4zm-5.9-1c-.8 0-1.4.2-2 .6L1.7 5c.9-.6 1.9-.9 3.1-.9v2zm-4.3.7l1.8.8c-.3.7-.3 1.3-.1 1.8l-1.9.7C0 8.9 0 7.8.5 6.8zm4.2 5.4l-1.3 1.5c-1-1-1.7-1.6-2-2l1.5-1.3c.7.8 1.3 1.4 1.8 1.8zm7.3 4.3c0 1.9-1.6 3.5-3.5 3.5S5 18.4 5 16.5 6.6 13 8.5 13s3.5 1.6 3.5 3.5zM24 8l-1-1-1.5 1.5L20 7l-1 1 1.5 1.5L19 11l1 1 1.5-1.5L23 12l1-1-1.5-1.5z"/>
+ <circle cx="8" cy="5" r="2"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl-invert.png
new file mode 100644
index 00000000..75c8dcfc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl-invert.svg
new file mode 100644
index 00000000..9153a1ae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <path d="M9.095 9l-.7-1.8c-.9.4-1.8.7-2.4.9l.6 1.7v.2l2.5-1zm4.3-1.9l-.8-1.8c-1.2.5-2.6 1.1-3 1.4l.8 1.8 3-1.4zm5.9-1c.8 0 1.4.2 2 .6l1.1-1.7c-.9-.6-1.9-.9-3.1-.9v2zm4.3.7l-1.8.8c.3.7.3 1.3.1 1.8l1.9.7c.3-1.2.3-2.3-.2-3.3zm-4.2 5.4l1.3 1.5c1-1 1.7-1.6 2-2l-1.5-1.3c-.7.8-1.3 1.4-1.8 1.8zm-7.3 4.3c0 1.9 1.6 3.5 3.5 3.5s3.5-1.6 3.5-3.5-1.6-3.5-3.5-3.5-3.5 1.6-3.5 3.5zM.095 8l1-1 1.5 1.5 1.5-1.5 1 1-1.5 1.5 1.5 1.5-1 1-1.5-1.5-1.5 1.5-1-1 1.5-1.5z"/>
+ <circle cx="8" cy="5" r="2" transform="matrix(-1 0 0 1 24.095 0)"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl.png
new file mode 100644
index 00000000..62f1fe91
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl.svg
new file mode 100644
index 00000000..e8b1a08c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/wikitrail-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9.095 9l-.7-1.8c-.9.4-1.8.7-2.4.9l.6 1.7v.2l2.5-1zm4.3-1.9l-.8-1.8c-1.2.5-2.6 1.1-3 1.4l.8 1.8 3-1.4zm5.9-1c.8 0 1.4.2 2 .6l1.1-1.7c-.9-.6-1.9-.9-3.1-.9v2zm4.3.7l-1.8.8c.3.7.3 1.3.1 1.8l1.9.7c.3-1.2.3-2.3-.2-3.3zm-4.2 5.4l1.3 1.5c1-1 1.7-1.6 2-2l-1.5-1.3c-.7.8-1.3 1.4-1.8 1.8zm-7.3 4.3c0 1.9 1.6 3.5 3.5 3.5s3.5-1.6 3.5-3.5-1.6-3.5-3.5-3.5-3.5 1.6-3.5 3.5zM.095 8l1-1 1.5 1.5 1.5-1.5 1 1-1.5 1.5 1.5 1.5-1 1-1.5-1.5-1.5 1.5-1-1 1.5-1.5z"/>
+ <circle cx="8" cy="5" r="2" transform="matrix(-1 0 0 1 24.095 0)"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window-invert.png
new file mode 100644
index 00000000..74c54ff7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window-invert.svg
new file mode 100644
index 00000000..699d6b95
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><style>* { fill: #ffffff }</style>
+ <g id="window">
+ <path id="title" d="M7 10h10v1H7z"/>
+ <path id="frame" d="M16 19H8c-2.206 0-4-1.794-4-4V9c0-2.206 1.794-4 4-4h8c2.206 0 4 1.794 4 4v6c0 2.206-1.794 4-4 4zM8 7c-1.103 0-2 .897-2 2v6c0 1.103.897 2 2 2h8c1.103 0 2-.897 2-2V9c0-1.103-.897-2-2-2H8z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window.png
new file mode 100644
index 00000000..bae13d71
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window.svg
new file mode 100644
index 00000000..093c8228
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/icons/window.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="window">
+ <path id="title" d="M7 10h10v1H7z"/>
+ <path id="frame" d="M16 19H8c-2.206 0-4-1.794-4-4V9c0-2.206 1.794-4 4-4h8c2.206 0 4 1.794 4 4v6c0 2.206-1.794 4-4 4zM8 7c-1.103 0-2 .897-2 2v6c0 1.103.897 2 2 2h8c1.103 0 2-.897 2-2V9c0-1.103-.897-2-2-2H8z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert-invert.png
new file mode 100644
index 00000000..035b6269
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert-invert.svg
new file mode 100644
index 00000000..0b692e39
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><style>* { fill: #ffffff }</style>
+ <path d="M6 12A6 6 0 1 1 6 0a6 6 0 0 1 0 12zM5 7h2V2H5zm0 3h2V8H5z" id="alert"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert.png
new file mode 100644
index 00000000..9d25a24e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert.svg
new file mode 100644
index 00000000..f94346ac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/alert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <path d="M6 12A6 6 0 1 1 6 0a6 6 0 0 1 0 12zM5 7h2V2H5zm0 3h2V8H5z" id="alert"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.png
new file mode 100644
index 00000000..582adceb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.svg
new file mode 100644
index 00000000..3f7f4470
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><style>* { fill: #ffffff }</style>
+ <g id="down">
+ <path id="arrow" d="M1 4h10L6 9 1 4"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.png
new file mode 100644
index 00000000..af67c7ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.svg
new file mode 100644
index 00000000..f5c76f37
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-down.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="down">
+ <path id="arrow" d="M1 4h10L6 9 1 4"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.png
new file mode 100644
index 00000000..05578bed
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.svg
new file mode 100644
index 00000000..01ec154d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><style>* { fill: #ffffff }</style>
+ <g id="ltr">
+ <path id="arrow" d="M4 1v10l5-5-5-5"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.png
new file mode 100644
index 00000000..d7a41110
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.svg
new file mode 100644
index 00000000..059372d5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="ltr">
+ <path id="arrow" d="M4 1v10l5-5-5-5"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.png
new file mode 100644
index 00000000..9731658b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.svg
new file mode 100644
index 00000000..a12a0e7e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><style>* { fill: #ffffff }</style>
+ <g id="rtl">
+ <path id="arrow" d="M8 11V1L3 6l5 5"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.png
new file mode 100644
index 00000000..afceed6c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.svg
new file mode 100644
index 00000000..c6498e82
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="rtl">
+ <path id="arrow" d="M8 11V1L3 6l5 5"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.png
new file mode 100644
index 00000000..218a7005
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.svg
new file mode 100644
index 00000000..a561ff74
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><style>* { fill: #ffffff }</style>
+ <g id="up">
+ <path id="arrow" d="M1 8h10L6 3 1 8"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.png
new file mode 100644
index 00000000..ee12d6e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.svg
new file mode 100644
index 00000000..5eada07d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/arrow-up.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="up">
+ <path id="arrow" d="M1 8h10L6 3 1 8"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear-invert.png
new file mode 100644
index 00000000..82f5bf11
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear-invert.svg
new file mode 100644
index 00000000..36b5dd7e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><style>* { fill: #ffffff }</style>
+ <g id="clear">
+ <path id="circle-with-cross" d="M6 0C2.7 0 0 2.7 0 6s2.7 6 6 6 6-2.7 6-6-2.7-6-6-6zM3.5 2.5L6 5l2.5-2.5 1 1L7 6l2.5 2.5-1 1L6 7 3.5 9.5l-1-1L5 6 2.5 3.5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear.png
new file mode 100644
index 00000000..a858a031
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear.svg
new file mode 100644
index 00000000..3c010c10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/clear.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="clear">
+ <path id="circle-with-cross" d="M6 0C2.7 0 0 2.7 0 6s2.7 6 6 6 6-2.7 6-6-2.7-6-6-6zM3.5 2.5L6 5l2.5-2.5 1 1L7 6l2.5 2.5-1 1L6 7 3.5 9.5l-1-1L5 6 2.5 3.5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required-invert.png
new file mode 100644
index 00000000..d9ff42fb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required-invert.svg
new file mode 100644
index 00000000..b3a37459
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><style>* { fill: #ffffff }</style>
+ <path d="M5 1h2v10H5zm4.83 1.634l1 1.732-8.66 5-1-1.732zM1.17 4.366l1-1.732 8.66 5-1 1.732z" id="required"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required.png
new file mode 100644
index 00000000..aca92390
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required.svg
new file mode 100644
index 00000000..94b0066e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/required.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <path d="M5 1h2v10H5zm4.83 1.634l1 1.732-8.66 5-1-1.732zM1.17 4.366l1-1.732 8.66 5-1 1.732z" id="required"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr-invert.png
new file mode 100644
index 00000000..95298032
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr-invert.svg
new file mode 100644
index 00000000..b16e1015
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><style>* { fill: #ffffff }</style>
+ <g id="search">
+ <path id="magnifying-glass" d="M10.37 9.474L7.994 7.1l-.17-.1a3.45 3.45 0 0 0 .644-2.01A3.478 3.478 0 1 0 4.99 8.47c.75 0 1.442-.24 2.01-.648l.098.17 2.375 2.373c.19.188.543.142.79-.105s.293-.6.104-.79zm-5.38-2.27a2.21 2.21 0 1 1 2.21-2.21A2.21 2.21 0 0 1 4.99 7.21z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr.png
new file mode 100644
index 00000000..123fbfa2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr.svg
new file mode 100644
index 00000000..80c72bb5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="search">
+ <path id="magnifying-glass" d="M10.37 9.474L7.994 7.1l-.17-.1a3.45 3.45 0 0 0 .644-2.01A3.478 3.478 0 1 0 4.99 8.47c.75 0 1.442-.24 2.01-.648l.098.17 2.375 2.373c.19.188.543.142.79-.105s.293-.6.104-.79zm-5.38-2.27a2.21 2.21 0 1 1 2.21-2.21A2.21 2.21 0 0 1 4.99 7.21z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl-invert.png
new file mode 100644
index 00000000..a7270579
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl-invert.svg
new file mode 100644
index 00000000..ee8ad618
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><style>* { fill: #ffffff }</style>
+ <g id="search">
+ <path id="magnifying-glass" d="M1.63 9.474L4.006 7.1l.17-.1a3.45 3.45 0 0 1-.644-2.01A3.478 3.478 0 1 1 7.01 8.47 3.43 3.43 0 0 1 5 7.822l-.098.17-2.375 2.373c-.19.188-.543.142-.79-.105s-.293-.6-.104-.79zm5.378-2.27A2.21 2.21 0 1 0 4.8 4.994 2.21 2.21 0 0 0 7.01 7.21z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl.png
new file mode 100644
index 00000000..db740615
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl.svg
new file mode 100644
index 00000000..4b3cff42
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/indicators/search-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="search">
+ <path id="magnifying-glass" d="M1.63 9.474L4.006 7.1l.17-.1a3.45 3.45 0 0 1-.644-2.01A3.478 3.478 0 1 1 7.01 8.47 3.43 3.43 0 0 1 5 7.822l-.098.17-2.375 2.373c-.19.188-.543.142-.79-.105s-.293-.6-.104-.79zm5.378-2.27A2.21 2.21 0 1 0 4.8 4.994 2.21 2.21 0 0 0 7.01 7.21z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/pending.gif b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/pending.gif
new file mode 100644
index 00000000..1194eed2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/pending.gif
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/transparency.png b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/transparency.png
new file mode 100644
index 00000000..dbf69b93
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/transparency.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/transparency.svg b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/transparency.svg
new file mode 100644
index 00000000..cadec2a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/images/textures/transparency.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+ <g id="transparency">
+ <path d="M0 0h8v8H0zm8 8h8v8H8z" fill="#ccc"/>
+ <path d="M8 0h8v8H8zM0 8h8v8H0z" fill="#fff"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/indicators.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/indicators.json
new file mode 100644
index 00000000..876a0557
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/indicators.json
@@ -0,0 +1,30 @@
+{
+ "selectorWithoutVariant": ".oo-ui-indicator-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-indicator-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "alert": { "file": "images/indicators/alert.svg" },
+ "clear": { "file": "images/indicators/clear.svg" },
+ "up": { "file": "images/indicators/arrow-up.svg" },
+ "down": { "file": "images/indicators/arrow-down.svg" },
+ "next": { "file": {
+ "ltr": "images/indicators/arrow-ltr.svg",
+ "rtl": "images/indicators/arrow-rtl.svg"
+ } },
+ "previous": { "file": {
+ "ltr": "images/indicators/arrow-rtl.svg",
+ "rtl": "images/indicators/arrow-ltr.svg"
+ } },
+ "required": { "file": "images/indicators/required.svg" },
+ "search": { "file": {
+ "ltr": "images/indicators/search-ltr.svg",
+ "rtl": "images/indicators/search-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/mediawiki/textures.json b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/textures.json
new file mode 100644
index 00000000..e90730ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/mediawiki/textures.json
@@ -0,0 +1,8 @@
+{
+ "prefix": "oo-ui-texture",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "pending": { "file": "images/textures/pending.gif" },
+ "transparency": { "file": "images/textures/transparency.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-accessibility.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-accessibility.json
new file mode 100644
index 00000000..656e321c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-accessibility.json
@@ -0,0 +1,28 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#ffffff",
+ "global": true
+ }
+ },
+ "images": {
+ "bright": { "file": "images/icons/bright.svg" },
+ "halfBright": { "file": "images/icons/halfBright.svg" },
+ "notBright": { "file": "images/icons/notBright.svg" },
+ "eye": { "file": "images/icons/eye.svg" },
+ "eyeClosed": { "file": "images/icons/eyeClosed.svg" },
+ "moon": { "file": "images/icons/moon.svg" },
+ "largerText": { "file": {
+ "ltr": "images/icons/largerText-ltr.svg",
+ "rtl": "images/icons/largerText-rtl.svg"
+ } },
+ "smallerText": { "file": {
+ "ltr": "images/icons/smallerText-ltr.svg",
+ "rtl": "images/icons/smallerText-rtl.svg"
+ } },
+ "visionSimulator": { "file": "images/icons/visionSimulator.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-alerts.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-alerts.json
new file mode 100644
index 00000000..fd2f35eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-alerts.json
@@ -0,0 +1,64 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "alert": { "file": "images/icons/alert.svg", "variants": [ "warning" ] },
+ "bell": { "file": "images/icons/bell.svg" },
+ "bellOn": { "file": {
+ "ltr": "images/icons/bellOn-ltr.svg",
+ "rtl": "images/icons/bellOn-rtl.svg"
+ } },
+ "comment": { "file": "images/icons/comment.svg" },
+ "eye": {
+ "file": "images/icons/eye.svg",
+ "deprecated": "Moved since v0.23.0 to the 'accessibility' pack."
+ },
+ "eyeClosed": {
+ "file": "images/icons/eyeClosed.svg",
+ "deprecated": "Moved since v0.23.0 to the 'accessibility' pack."
+ },
+ "message": { "file": {
+ "ltr": "images/icons/message-ltr.svg",
+ "rtl": "images/icons/message-rtl.svg"
+ } },
+ "notice": { "file": "images/icons/notice.svg" },
+ "signature": { "file": {
+ "ltr": "images/icons/signature-ltr.svg",
+ "rtl": "images/icons/signature-rtl.svg"
+ },
+ "deprecated": "Moved since v0.23.0 to the 'editing-advanced' pack." },
+ "speechBubble": { "file": {
+ "ltr": "images/icons/speechBubble-ltr.svg",
+ "rtl": "images/icons/speechBubble-rtl.svg"
+ } },
+ "speechBubbleAdd": { "file": {
+ "ltr": "images/icons/speechBubbleAdd-ltr.svg",
+ "rtl": "images/icons/speechBubbleAdd-rtl.svg"
+ } },
+ "speechBubbles": { "file": {
+ "ltr": "images/icons/speechBubbles-ltr.svg",
+ "rtl": "images/icons/speechBubbles-rtl.svg"
+ } },
+ "tray": { "file": "images/icons/tray.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-content.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-content.json
new file mode 100644
index 00000000..e952108a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-content.json
@@ -0,0 +1,82 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "article": { "file": {
+ "ltr": "images/icons/article-ltr.svg",
+ "rtl": "images/icons/article-rtl.svg"
+ } },
+ "articles": { "file": {
+ "ltr": "images/icons/articles-ltr.svg",
+ "rtl": "images/icons/articles-rtl.svg"
+ } },
+ "articleCheck": { "file": {
+ "ltr": "images/icons/articleCheck-ltr.svg",
+ "rtl": "images/icons/articleCheck-rtl.svg"
+ } },
+ "articleSearch": { "file": {
+ "ltr": "images/icons/articleSearch-ltr.svg",
+ "rtl": "images/icons/articleSearch-rtl.svg"
+ } },
+ "articleRedirect": { "file": {
+ "ltr": "images/icons/articleRedirect-ltr.svg",
+ "rtl": "images/icons/articleRedirect-rtl.svg"
+ } },
+ "book": { "file": {
+ "ltr": "images/icons/book-ltr.svg",
+ "rtl": "images/icons/book-rtl.svg"
+ } },
+ "citeArticle": { "file": {
+ "ltr": "images/icons/citeArticle-ltr.svg",
+ "rtl": "images/icons/citeArticle-rtl.svg"
+ } },
+ "die": { "file": {
+ "ltr": "images/icons/die-ltr.svg",
+ "rtl": "images/icons/die-rtl.svg"
+ } },
+ "download": { "file": {
+ "ltr": "images/icons/download-ltr.svg",
+ "rtl": "images/icons/download-rtl.svg"
+ } },
+ "folderPlaceholder": { "file": {
+ "ltr": "images/icons/folderPlaceholder-ltr.svg",
+ "rtl": "images/icons/folderPlaceholder-rtl.svg"
+ } },
+ "history": { "file": "images/icons/history.svg" },
+ "info": { "file": "images/icons/info.svg" },
+ "journal": { "file": {
+ "ltr": "images/icons/journal-ltr.svg",
+ "rtl": "images/icons/journal-rtl.svg"
+ } },
+ "newspaper": { "file": {
+ "ltr": "images/icons/newspaper-ltr.svg",
+ "rtl": "images/icons/newspaper-rtl.svg"
+ } },
+ "tag": { "file": "images/icons/tag.svg", "variants": [ "destructive", "warning", "constructive" ] },
+ "upload": { "file": {
+ "ltr": "images/icons/upload-ltr.svg",
+ "rtl": "images/icons/upload-rtl.svg"
+ } },
+ "window": { "file": "images/icons/window.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-advanced.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-advanced.json
new file mode 100644
index 00000000..36301fc6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-advanced.json
@@ -0,0 +1,106 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "alignCentre": { "file": "images/icons/align-center.svg" },
+ "alignLeft": { "file": "images/icons/align-float-left.svg" },
+ "alignRight": { "file": "images/icons/align-float-right.svg" },
+ "attachment": { "file": {
+ "ltr": "images/icons/attachment-ltr.svg",
+ "rtl": "images/icons/attachment-rtl.svg"
+ } },
+ "calendar": { "file": {
+ "ltr": "images/icons/calendar-ltr.svg",
+ "rtl": "images/icons/calendar-rtl.svg"
+ } },
+ "code": { "file": "images/icons/code.svg" },
+ "find": { "file": {
+ "ltr": "images/icons/find-ltr.svg",
+ "rtl": "images/icons/find-rtl.svg"
+ } },
+ "language": { "file": {
+ "ltr": "images/icons/language-ltr.svg",
+ "rtl": "images/icons/language-rtl.svg"
+ } },
+ "layout": { "file": {
+ "ltr": "images/icons/layout-ltr.svg",
+ "rtl": "images/icons/layout-rtl.svg"
+ } },
+ "markup": { "file": "images/icons/markup.svg" },
+ "newline": { "file": {
+ "ltr": "images/icons/newline-ltr.svg",
+ "rtl": "images/icons/newline-rtl.svg"
+ } },
+ "noWikiText": { "file": {
+ "ltr": "images/icons/noWikiText-ltr.svg",
+ "rtl": "images/icons/noWikiText-rtl.svg"
+ } },
+ "outline": { "file": {
+ "ltr": "images/icons/outline-ltr.svg",
+ "rtl": "images/icons/outline-rtl.svg"
+ } },
+ "puzzle": { "file": "images/icons/puzzle.svg" },
+ "quotes": { "file": {
+ "ltr": "images/icons/quotes-ltr.svg",
+ "rtl": "images/icons/quotes-rtl.svg"
+ } },
+ "quotesAdd": { "file": {
+ "ltr": "images/icons/quotesAdd-ltr.svg",
+ "rtl": "images/icons/quotesAdd-rtl.svg"
+ } },
+ "redirect": { "file": {
+ "ltr": "images/icons/articleRedirect-ltr.svg",
+ "rtl": "images/icons/articleRedirect-rtl.svg"
+ } },
+ "searchCaseSensitive": { "file": "images/icons/case-sensitive.svg" },
+ "searchDiacritics": { "file": "images/icons/diacritic.svg" },
+ "searchRegularExpression": { "file": "images/icons/regular-expression.svg" },
+ "signature": { "file": {
+ "ltr": "images/icons/signature-ltr.svg",
+ "rtl": "images/icons/signature-rtl.svg"
+ } },
+ "specialCharacter": { "file": "images/icons/specialCharacter.svg" },
+ "table": { "file": "images/icons/table.svg" },
+ "tableAddColumnAfter": { "file": {
+ "ltr": "images/icons/table-insert-column-rtl.svg",
+ "rtl": "images/icons/table-insert-column-ltr.svg"
+ } },
+ "tableAddColumnBefore": { "file": {
+ "ltr": "images/icons/table-insert-column-ltr.svg",
+ "rtl": "images/icons/table-insert-column-rtl.svg"
+ } },
+ "tableAddRowAfter": { "file": "images/icons/table-insert-row-after.svg" },
+ "tableAddRowBefore": { "file": "images/icons/table-insert-row-before.svg" },
+ "tableCaption": { "file": "images/icons/table-caption.svg" },
+ "tableMergeCells": { "file": "images/icons/table-merge-cells.svg" },
+ "templateAdd": { "file": {
+ "ltr": "images/icons/templateAdd-ltr.svg",
+ "rtl": "images/icons/templateAdd-rtl.svg"
+ } },
+ "translation": { "file": {
+ "ltr": "images/icons/language-ltr.svg",
+ "rtl": "images/icons/language-rtl.svg"
+ } },
+ "wikiText": { "file": "images/icons/wikiText.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-core.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-core.json
new file mode 100644
index 00000000..4515405b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-core.json
@@ -0,0 +1,55 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "edit": { "file": {
+ "ltr": "images/icons/edit-ltr.svg",
+ "rtl": "images/icons/edit-rtl.svg"
+ }, "variants": [ "progressive" ] },
+ "editLock": { "file": {
+ "ltr": "images/icons/editLock-ltr.svg",
+ "rtl": "images/icons/editLock-rtl.svg"
+ } },
+ "editUndo": { "file": {
+ "ltr": "images/icons/editUndo-ltr.svg",
+ "rtl": "images/icons/editUndo-rtl.svg"
+ } },
+ "link": { "file": {
+ "ltr": "images/icons/link-ltr.svg",
+ "rtl": "images/icons/link-rtl.svg"
+ } },
+ "linkExternal": { "file": {
+ "ltr": "images/icons/external-link-ltr.svg",
+ "rtl": "images/icons/external-link-rtl.svg"
+ } },
+ "linkSecure": { "file": "images/icons/secure-link.svg" },
+ "redo": { "file": {
+ "ltr": "images/icons/arched-arrow-ltr.svg",
+ "rtl": "images/icons/arched-arrow-rtl.svg"
+ } },
+ "undo": { "file": {
+ "ltr": "images/icons/arched-arrow-rtl.svg",
+ "rtl": "images/icons/arched-arrow-ltr.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-list.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-list.json
new file mode 100644
index 00000000..3edb5454
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-list.json
@@ -0,0 +1,42 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "indent": { "file": {
+ "ltr": "images/icons/indent-ltr.svg",
+ "rtl": "images/icons/indent-rtl.svg"
+ } },
+ "listBullet": { "file": {
+ "ltr": "images/icons/listBullet-ltr.svg",
+ "rtl": "images/icons/listBullet-rtl.svg"
+ } },
+ "listNumbered": { "file": {
+ "ltr": "images/icons/listNumbered-ltr.svg",
+ "rtl": "images/icons/listNumbered-rtl.svg"
+ } },
+ "outdent": { "file": {
+ "ltr": "images/icons/outdent-ltr.svg",
+ "rtl": "images/icons/outdent-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-styling.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-styling.json
new file mode 100644
index 00000000..85e47ee9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-editing-styling.json
@@ -0,0 +1,99 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "bigger": { "file": {
+ "ltr": "images/icons/bigger-ltr.svg",
+ "rtl": "images/icons/bigger-rtl.svg"
+ } },
+ "smaller": { "file": {
+ "ltr": "images/icons/smaller-ltr.svg",
+ "rtl": "images/icons/smaller-rtl.svg"
+ } },
+ "subscript": { "file": {
+ "ltr": "images/icons/subscript-ltr.svg",
+ "rtl": "images/icons/subscript-rtl.svg"
+ } },
+ "superscript": { "file": {
+ "ltr": "images/icons/superscript-ltr.svg",
+ "rtl": "images/icons/superscript-rtl.svg"
+ } },
+ "bold": { "file": {
+ "default": "images/icons/bold-a.svg",
+ "lang": {
+ "ar": "images/icons/bold-arab-ain.svg",
+ "be": "images/icons/bold-cyrl-te.svg",
+ "cs,en,en-ca,en-gb,he,ml,pl,sco": "images/icons/bold-b.svg",
+ "da,de,hu,ksh,nn,no,sv": "images/icons/bold-f.svg",
+ "es,gl,pt": "images/icons/bold-n.svg",
+ "eu,fi": "images/icons/bold-l.svg",
+ "fa": "images/icons/bold-arab-dad.svg",
+ "fr,it": "images/icons/bold-g.svg",
+ "hy": "images/icons/bold-armn-to.svg",
+ "ka": "images/icons/bold-geor-man.svg",
+ "ky,ru,uk": "images/icons/bold-cyrl-zhe.svg",
+ "nl": "images/icons/bold-v.svg",
+ "os": "images/icons/bold-cyrl-be.svg"
+ }
+ } },
+ "highlight": { "file": {
+ "ltr": "images/icons/highlight-ltr.svg",
+ "rtl": "images/icons/highlight-rtl.svg"
+ } },
+ "italic": { "file": {
+ "default": "images/icons/italic-a.svg",
+ "lang": {
+ "ar": "images/icons/italic-arab-meem.svg",
+ "cs,en,en-ca,en-gb,fr,he,ml,pl,pt,sco": "images/icons/italic-i.svg",
+ "be,da,de,fi,ky,nn,no,os,sv,ru,uk": "images/icons/italic-k.svg",
+ "es,gl,it,nl": "images/icons/italic-c.svg",
+ "eu": "images/icons/italic-e.svg",
+ "fa": "images/icons/italic-arab-keheh-jeem.svg",
+ "hu": "images/icons/italic-d.svg",
+ "hy": "images/icons/italic-armn-sha.svg",
+ "ksh": "images/icons/italic-s.svg",
+ "ka": "images/icons/italic-geor-kan.svg"
+ }
+ } },
+ "strikethrough": { "file": {
+ "default": "images/icons/strikethrough-a.svg",
+ "lang": {
+ "en,en-ca,en-gb": "images/icons/strikethrough-s.svg",
+ "fi": "images/icons/strikethrough-y.svg"
+ }
+ } },
+ "underline": { "file": {
+ "default": "images/icons/underline-a.svg",
+ "lang": {
+ "en,en-ca,en-gb": "images/icons/underline-u.svg"
+ }
+ } },
+ "textLanguage": { "file": {
+ "ltr": "images/icons/language-ltr.svg",
+ "rtl": "images/icons/language-rtl.svg"
+ } },
+ "textDirLTR": { "file": "images/icons/text-dir-lefttoright.svg" },
+ "textDirRTL": { "file": "images/icons/text-dir-righttoleft.svg" },
+ "textStyle": { "file": "images/icons/text-style.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-interactions.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-interactions.json
new file mode 100644
index 00000000..ab0ecef6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-interactions.json
@@ -0,0 +1,94 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "add": { "file": "images/icons/add.svg", "variants": [ "constructive", "progressive" ] },
+ "advanced": { "file": "images/icons/advanced.svg" },
+ "browser": { "file": {
+ "ltr": "images/icons/browser-ltr.svg",
+ "rtl": "images/icons/browser-rtl.svg"
+ } },
+ "cancel": { "file": "images/icons/cancel.svg", "variants": [ "destructive" ] },
+ "check": { "file": "images/icons/check.svg", "variants": [ "constructive", "progressive", "destructive" ] },
+ "clear": { "file": "images/icons/clear.svg" },
+ "clock": { "file": "images/icons/clock.svg" },
+ "close": { "file": "images/icons/close.svg" },
+ "ellipsis": { "file": "images/icons/ellipsis.svg" },
+ "feedback": {
+ "file": {
+ "ltr": "images/icons/feedback-ltr.svg",
+ "rtl": "images/icons/feedback-rtl.svg"
+ },
+ "variants": [ "progressive" ]
+ },
+ "funnel": { "file": {
+ "ltr": "images/icons/funnel-ltr.svg",
+ "rtl": "images/icons/funnel-rtl.svg"
+ } },
+ "heart": { "file": "images/icons/heart.svg" },
+ "help": { "file": {
+ "ltr": "images/icons/help-ltr.svg",
+ "rtl": "images/icons/help-rtl.svg",
+ "lang": {
+ "he,yi": "images/icons/help-ltr.svg"
+ }
+ } },
+ "key": { "file": {
+ "ltr": "images/icons/key-ltr.svg",
+ "rtl": "images/icons/key-rtl.svg"
+ } },
+ "keyboard": { "file": {
+ "ltr": "images/icons/keyboard-ltr.svg",
+ "rtl": "images/icons/keyboard-rtl.svg"
+ } },
+ "logOut": { "file": {
+ "ltr": "images/icons/logOut-ltr.svg",
+ "rtl": "images/icons/logOut-rtl.svg"
+ } },
+ "newWindow": { "file": {
+ "ltr": "images/icons/newWindow-ltr.svg",
+ "rtl": "images/icons/newWindow-rtl.svg"
+ } },
+ "printer": { "file": {
+ "ltr": "images/icons/printer-ltr.svg",
+ "rtl": "images/icons/printer-rtl.svg"
+ } },
+ "search": { "file": {
+ "ltr": "images/icons/search-ltr.svg",
+ "rtl": "images/icons/search-rtl.svg"
+ }
+ },
+ "settings": { "file": "images/icons/settings.svg" },
+ "subtract": { "file": "images/icons/subtract.svg" },
+ "sun": { "file": {
+ "ltr": "images/icons/sun-ltr.svg",
+ "rtl": "images/icons/sun-rtl.svg"
+ },
+ "deprecated": "This will be removed in v0.24.0."
+ },
+ "watchlist": { "file": {
+ "ltr": "images/icons/watchlist-ltr.svg",
+ "rtl": "images/icons/watchlist-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-layout.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-layout.json
new file mode 100644
index 00000000..21b57ccf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-layout.json
@@ -0,0 +1,48 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "menu": { "file": "images/icons/menu.svg" },
+ "stripeFlow": { "file": {
+ "ltr": "images/icons/stripeFlow-ltr.svg",
+ "rtl": "images/icons/stripeFlow-rtl.svg"
+ } },
+ "stripeSideMenu": {
+ "file": "images/icons/draggable.svg",
+ "deprecated": "Replaced since v0.22.2, use 'draggable' from the 'movement' pack instead."
+ },
+ "stripeSummary": { "file": {
+ "ltr": "images/icons/stripeSummary-ltr.svg",
+ "rtl": "images/icons/stripeSummary-rtl.svg"
+ } },
+ "stripeToC": { "file": {
+ "ltr": "images/icons/stripeToC-ltr.svg",
+ "rtl": "images/icons/stripeToC-rtl.svg"
+ }, "variants": [ "progressive" ] },
+ "viewCompact": { "file": "images/icons/viewCompact.svg" },
+ "viewDetails": { "file": {
+ "ltr": "images/icons/viewDetails-ltr.svg",
+ "rtl": "images/icons/viewDetails-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-location.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-location.json
new file mode 100644
index 00000000..4ca66355
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-location.json
@@ -0,0 +1,39 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "map": { "file": {
+ "ltr": "images/icons/map-ltr.svg",
+ "rtl": "images/icons/map-rtl.svg"
+ } },
+ "mapPin": { "file": "images/icons/mapPin.svg" },
+ "mapPinAdd": { "file": {
+ "ltr": "images/icons/mapPinAdd-ltr.svg",
+ "rtl": "images/icons/mapPinAdd-rtl.svg"
+ } },
+ "mapTrail": { "file": {
+ "ltr": "images/icons/mapTrail-ltr.svg",
+ "rtl": "images/icons/mapTrail-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-media.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-media.json
new file mode 100644
index 00000000..afdb9e52
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-media.json
@@ -0,0 +1,48 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "fullScreen": { "file": "images/icons/fullScreen.svg" },
+ "image": { "file": {
+ "ltr": "images/icons/image-ltr.svg",
+ "rtl": "images/icons/image-rtl.svg"
+ } },
+ "imageAdd": { "file": {
+ "ltr": "images/icons/imageAdd-ltr.svg",
+ "rtl": "images/icons/imageAdd-rtl.svg"
+ } },
+ "imageLock": { "file": {
+ "ltr": "images/icons/imageLock-ltr.svg",
+ "rtl": "images/icons/imageLock-rtl.svg"
+ } },
+ "imageGallery": { "file": {
+ "ltr": "images/icons/imageGallery-ltr.svg",
+ "rtl": "images/icons/imageGallery-rtl.svg"
+ } },
+ "play": { "file": {
+ "ltr": "images/icons/play-ltr.svg",
+ "rtl": "images/icons/play-rtl.svg"
+ } },
+ "stop": { "file": "images/icons/stop.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-moderation.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-moderation.json
new file mode 100644
index 00000000..8f0ff154
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-moderation.json
@@ -0,0 +1,68 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "block": { "file": "images/icons/block.svg", "variants": [ "destructive" ] },
+ "unBlock": { "file": {
+ "ltr": "images/icons/unBlock-ltr.svg",
+ "rtl": "images/icons/unBlock-rtl.svg"
+ } },
+ "clip": { "file": "images/icons/clip.svg", "variants": [ "progressive" ] },
+ "unClip": { "file": "images/icons/unClip.svg", "variants": [ "progressive" ] },
+ "flag": { "file": {
+ "ltr": "images/icons/flag-ltr.svg",
+ "rtl": "images/icons/flag-rtl.svg"
+ } },
+ "unFlag": { "file": {
+ "ltr": "images/icons/unFlag-ltr.svg",
+ "rtl": "images/icons/unFlag-rtl.svg"
+ } },
+ "lock": { "file": {
+ "ltr": "images/icons/lock-ltr.svg",
+ "rtl": "images/icons/lock-rtl.svg"
+ }, "variants": [ "destructive" ] },
+ "unLock": { "file": {
+ "ltr": "images/icons/unLock-ltr.svg",
+ "rtl": "images/icons/unLock-rtl.svg"
+ }, "variants": [ "destructive" ] },
+ "star": { "file": "images/icons/star.svg", "variants": [ "constructive", "progressive" ] },
+ "halfStar": { "file": {
+ "ltr": "images/icons/halfStar-ltr.svg",
+ "rtl": "images/icons/halfStar-rtl.svg"
+ }, "variants": [ "constructive", "progressive" ] },
+ "unStar": { "file": "images/icons/unStar.svg", "variants": [ "constructive", "progressive" ] },
+ "trash": { "file": "images/icons/trash.svg", "variants": [ "destructive" ] },
+ "unTrash": { "file": {
+ "ltr": "images/icons/unTrash-ltr.svg",
+ "rtl": "images/icons/unTrash-rtl.svg"
+ } },
+ "pushPin": { "file": "images/icons/pushPin.svg", "variants": [ "progressive" ] },
+ "ongoingConversation": {
+ "file": {
+ "ltr": "images/icons/ongoingConversation-ltr.svg",
+ "rtl": "images/icons/ongoingConversation-rtl.svg"
+ },
+ "variants": [ "progressive" ]
+ }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-movement.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-movement.json
new file mode 100644
index 00000000..7ba002a5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-movement.json
@@ -0,0 +1,60 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "arrowNext": { "file": {
+ "ltr": "images/icons/arrow-ltr.svg",
+ "rtl": "images/icons/arrow-rtl.svg"
+ } },
+ "arrowLast": { "file": {
+ "ltr": "images/icons/arrow-rtl.svg",
+ "rtl": "images/icons/arrow-ltr.svg"
+ } },
+ "collapse": { "file": "images/icons/collapse.svg" },
+ "downTriangle": { "file": "images/icons/downTriangle.svg" },
+ "draggable": { "file": "images/icons/draggable.svg" },
+ "expand": { "file": "images/icons/expand.svg" },
+ "move": { "file": "images/icons/move.svg" },
+ "next": { "file": {
+ "ltr": "images/icons/move-ltr.svg",
+ "rtl": "images/icons/move-rtl.svg"
+ }
+ },
+ "previous": { "file": {
+ "ltr": "images/icons/move-rtl.svg",
+ "rtl": "images/icons/move-ltr.svg"
+ }
+ },
+ "last": { "file": {
+ "ltr": "images/icons/move-end-ltr.svg",
+ "rtl": "images/icons/move-end-rtl.svg"
+ }
+ },
+ "first": { "file": {
+ "ltr": "images/icons/move-end-rtl.svg",
+ "rtl": "images/icons/move-end-ltr.svg"
+ }
+ },
+ "upTriangle": { "file": "images/icons/upTriangle.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-user.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-user.json
new file mode 100644
index 00000000..5a70c5ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-user.json
@@ -0,0 +1,39 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ },
+ "constructive": {
+ "color": "#36c"
+ },
+ "destructive": {
+ "color": "#d33"
+ },
+ "warning": {
+ "color": "#ff5d00"
+ }
+ },
+ "images": {
+ "userActive": { "file": {
+ "ltr": "images/icons/userActive-ltr.svg",
+ "rtl": "images/icons/userActive-rtl.svg"
+ } },
+ "userAvatar": { "file": "images/icons/userAvatar.svg" },
+ "userInactive": { "file": {
+ "ltr": "images/icons/userInactive-ltr.svg",
+ "rtl": "images/icons/userInactive-rtl.svg"
+ } },
+ "userTalk": { "file": {
+ "ltr": "images/icons/userTalk-ltr.svg",
+ "rtl": "images/icons/userTalk-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-wikimedia.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-wikimedia.json
new file mode 100644
index 00000000..3bdecff4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/icons-wikimedia.json
@@ -0,0 +1,21 @@
+{
+ "selectorWithoutVariant": ".oo-ui-icon-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-icon-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ },
+ "progressive": {
+ "color": "#36c",
+ "global": true
+ }
+ },
+ "images": {
+ "logoCC": { "file": "images/icons/logo-cc.svg" },
+ "logoWikimediaCommons": { "file": "images/icons/logo-wikimediaCommons.svg" },
+ "logoWikimediaDiscovery": { "file": "images/icons/logo-wikimediaDiscovery.svg" },
+ "logoWikipedia": { "file": "images/icons/logo-wikipedia.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-constructive.png
new file mode 100644
index 00000000..42209e7d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-constructive.svg
new file mode 100644
index 00000000..60c74f53
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-constructive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="add">
+ <path id="plus" d="M13 6h-2v5H6v2h5v5h2v-5h5v-2h-5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-invert.png
new file mode 100644
index 00000000..8deeddf4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-invert.svg
new file mode 100644
index 00000000..dfbbc82f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="add">
+ <path id="plus" d="M13 6h-2v5H6v2h5v5h2v-5h5v-2h-5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-progressive.png
new file mode 100644
index 00000000..42209e7d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-progressive.svg
new file mode 100644
index 00000000..60c74f53
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="add">
+ <path id="plus" d="M13 6h-2v5H6v2h5v5h2v-5h5v-2h-5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add.png
new file mode 100644
index 00000000..4c70ee4a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add.svg
new file mode 100644
index 00000000..62e54965
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/add.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="add">
+ <path id="plus" d="M13 6h-2v5H6v2h5v5h2v-5h5v-2h-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-invert.png
new file mode 100644
index 00000000..67fec171
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-invert.svg
new file mode 100644
index 00000000..feb4dd4f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M20 13.44v-2.88l-1.8-.3c-.1-.397-.3-.794-.6-1.39l1.1-1.49-2.1-2.088-1.5 1.093c-.5-.298-1-.497-1.4-.596L13.5 4h-2.9l-.3 1.79c-.5.098-.9.297-1.4.595L7.4 5.292 5.3 7.38l1 1.49c-.3.496-.4.894-.6 1.39l-1.7.2v2.882l1.8.298c.1.497.3.894.6 1.39l-1 1.492 2.1 2.087 1.5-1c.4.2.9.395 1.4.594l.3 1.79h3l.3-1.79c.5-.1.9-.298 1.4-.596l1.5 1.092 2.1-2.08-1.1-1.49c.3-.496.5-.993.6-1.39l1.5-.3zm-8 1.492c-1.7 0-3-1.292-3-2.982 0-1.69 1.3-2.98 3-2.98s3 1.29 3 2.98-1.3 2.982-3 2.982z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-progressive.png
new file mode 100644
index 00000000..e64bd2a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-progressive.svg
new file mode 100644
index 00000000..6bb1b102
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M20 13.44v-2.88l-1.8-.3c-.1-.397-.3-.794-.6-1.39l1.1-1.49-2.1-2.088-1.5 1.093c-.5-.298-1-.497-1.4-.596L13.5 4h-2.9l-.3 1.79c-.5.098-.9.297-1.4.595L7.4 5.292 5.3 7.38l1 1.49c-.3.496-.4.894-.6 1.39l-1.7.2v2.882l1.8.298c.1.497.3.894.6 1.39l-1 1.492 2.1 2.087 1.5-1c.4.2.9.395 1.4.594l.3 1.79h3l.3-1.79c.5-.1.9-.298 1.4-.596l1.5 1.092 2.1-2.08-1.1-1.49c.3-.496.5-.993.6-1.39l1.5-.3zm-8 1.492c-1.7 0-3-1.292-3-2.982 0-1.69 1.3-2.98 3-2.98s3 1.29 3 2.98-1.3 2.982-3 2.982z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced.png
new file mode 100644
index 00000000..32892a59
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced.svg
new file mode 100644
index 00000000..95d72f97
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/advanced.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 13.44v-2.88l-1.8-.3c-.1-.397-.3-.794-.6-1.39l1.1-1.49-2.1-2.088-1.5 1.093c-.5-.298-1-.497-1.4-.596L13.5 4h-2.9l-.3 1.79c-.5.098-.9.297-1.4.595L7.4 5.292 5.3 7.38l1 1.49c-.3.496-.4.894-.6 1.39l-1.7.2v2.882l1.8.298c.1.497.3.894.6 1.39l-1 1.492 2.1 2.087 1.5-1c.4.2.9.395 1.4.594l.3 1.79h3l.3-1.79c.5-.1.9-.298 1.4-.596l1.5 1.092 2.1-2.08-1.1-1.49c.3-.496.5-.993.6-1.39l1.5-.3zm-8 1.492c-1.7 0-3-1.292-3-2.982 0-1.69 1.3-2.98 3-2.98s3 1.29 3 2.98-1.3 2.982-3 2.982z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-invert.png
new file mode 100644
index 00000000..2a66b030
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-invert.svg
new file mode 100644
index 00000000..0f641419
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-invert.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="alert">
+ <path id="point" d="M11 16h2v2h-2z"/>
+ <path id="stroke" d="M13.516 10h-3L11 15h2z"/>
+ <path id="triangle" d="M12.017 5.974L19.537 19H4.497l7.52-13.026m0-2.474c-.545 0-1.09.357-1.5 1.07L2.53 18.403C1.705 19.833 2.38 21 4.03 21H20c1.65 0 2.325-1.17 1.5-2.6L13.517 4.575c-.413-.715-.956-1.072-1.5-1.072z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-progressive.png
new file mode 100644
index 00000000..66973b8c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-progressive.svg
new file mode 100644
index 00000000..78c22cda
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-progressive.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="alert">
+ <path id="point" d="M11 16h2v2h-2z"/>
+ <path id="stroke" d="M13.516 10h-3L11 15h2z"/>
+ <path id="triangle" d="M12.017 5.974L19.537 19H4.497l7.52-13.026m0-2.474c-.545 0-1.09.357-1.5 1.07L2.53 18.403C1.705 19.833 2.38 21 4.03 21H20c1.65 0 2.325-1.17 1.5-2.6L13.517 4.575c-.413-.715-.956-1.072-1.5-1.072z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-warning.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-warning.png
new file mode 100644
index 00000000..6276502c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-warning.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-warning.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-warning.svg
new file mode 100644
index 00000000..6e96e137
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert-warning.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ff5d00">
+ <g id="alert">
+ <path id="point" d="M11 16h2v2h-2z"/>
+ <path id="stroke" d="M13.516 10h-3L11 15h2z"/>
+ <path id="triangle" d="M12.017 5.974L19.537 19H4.497l7.52-13.026m0-2.474c-.545 0-1.09.357-1.5 1.07L2.53 18.403C1.705 19.833 2.38 21 4.03 21H20c1.65 0 2.325-1.17 1.5-2.6L13.517 4.575c-.413-.715-.956-1.072-1.5-1.072z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert.png
new file mode 100644
index 00000000..73550841
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert.svg
new file mode 100644
index 00000000..8b601d5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/alert.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="alert">
+ <path id="point" d="M11 16h2v2h-2z"/>
+ <path id="stroke" d="M13.516 10h-3L11 15h2z"/>
+ <path id="triangle" d="M12.017 5.974L19.537 19H4.497l7.52-13.026m0-2.474c-.545 0-1.09.357-1.5 1.07L2.53 18.403C1.705 19.833 2.38 21 4.03 21H20c1.65 0 2.325-1.17 1.5-2.6L13.517 4.575c-.413-.715-.956-1.072-1.5-1.072z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-invert.png
new file mode 100644
index 00000000..a3495ebd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-invert.svg
new file mode 100644
index 00000000..b6db3929
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M9 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H9c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm-5.5 9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0-12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-center"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-progressive.png
new file mode 100644
index 00000000..9032e129
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-progressive.svg
new file mode 100644
index 00000000..e69f5420
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M9 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H9c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm-5.5 9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0-12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-center"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center.png
new file mode 100644
index 00000000..a912b033
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center.svg
new file mode 100644
index 00000000..6f479773
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-center.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H9c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm-5.5 9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0-12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-center"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-invert.png
new file mode 100644
index 00000000..e274be40
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-invert.svg
new file mode 100644
index 00000000..5232a48b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M4 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H4c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm9.5 0h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm-10-9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0 12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-float-left"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-progressive.png
new file mode 100644
index 00000000..d37112a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-progressive.svg
new file mode 100644
index 00000000..7e03b954
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M4 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H4c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm9.5 0h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm-10-9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0 12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-float-left"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left.png
new file mode 100644
index 00000000..e3950369
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left.svg
new file mode 100644
index 00000000..a577600d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-left.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 9h6c.554 0 1 .446 1 1v5c0 .554-.446 1-1 1H4c-.554 0-1-.446-1-1v-5c0-.554.446-1 1-1zm9.5 0h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm0 3h7a.5.5 0 0 1 0 1h-7a.5.5 0 0 1 0-1zm-10-9h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1zm0 12h17a.5.5 0 0 1 0 1h-17a.5.5 0 0 1 0-1z" id="align-float-left"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-invert.png
new file mode 100644
index 00000000..c6659fb9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-invert.svg
new file mode 100644
index 00000000..3395516e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M20 9h-6c-.554 0-1 .446-1 1v5c0 .554.446 1 1 1h6c.554 0 1-.446 1-1v-5c0-.554-.446-1-1-1zm-9.5 0h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm10-9h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1zm0 12h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1z" id="align-float-right"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-progressive.png
new file mode 100644
index 00000000..8d3f480e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-progressive.svg
new file mode 100644
index 00000000..f7f45e25
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M20 9h-6c-.554 0-1 .446-1 1v5c0 .554.446 1 1 1h6c.554 0 1-.446 1-1v-5c0-.554-.446-1-1-1zm-9.5 0h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm10-9h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1zm0 12h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1z" id="align-float-right"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right.png
new file mode 100644
index 00000000..c72a9560
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right.svg
new file mode 100644
index 00000000..0f46bc1f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/align-float-right.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 9h-6c-.554 0-1 .446-1 1v5c0 .554.446 1 1 1h6c.554 0 1-.446 1-1v-5c0-.554-.446-1-1-1zm-9.5 0h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm0 3h-7a.5.5 0 0 0 0 1h7a.5.5 0 0 0 0-1zm10-9h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1zm0 12h-17a.5.5 0 0 0 0 1h17a.5.5 0 0 0 0-1z" id="align-float-right"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-invert.png
new file mode 100644
index 00000000..d8d64f1a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-invert.svg
new file mode 100644
index 00000000..7a6c6a43
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M13.3 6.3l6.3 5.7-6.3 5.7v-3.8H12c-3.2 0-6.3 1.3-7.6 3.8 0-4.7 2.8-7.6 7.9-7.6h.9V6.3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-progressive.png
new file mode 100644
index 00000000..28f88355
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-progressive.svg
new file mode 100644
index 00000000..c17ebc7d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M13.3 6.3l6.3 5.7-6.3 5.7v-3.8H12c-3.2 0-6.3 1.3-7.6 3.8 0-4.7 2.8-7.6 7.9-7.6h.9V6.3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr.png
new file mode 100644
index 00000000..c2fae72d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr.svg
new file mode 100644
index 00000000..c2291200
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M13.3 6.3l6.3 5.7-6.3 5.7v-3.8H12c-3.2 0-6.3 1.3-7.6 3.8 0-4.7 2.8-7.6 7.9-7.6h.9V6.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-invert.png
new file mode 100644
index 00000000..21fa9abb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-invert.svg
new file mode 100644
index 00000000..b05aec3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M10.7 6.3L4.4 12l6.3 5.7v-3.8H12c3.2 0 6.3 1.3 7.6 3.8 0-4.7-2.8-7.6-7.9-7.6h-.9V6.3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-progressive.png
new file mode 100644
index 00000000..11f0c842
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-progressive.svg
new file mode 100644
index 00000000..cc7b2aa8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M10.7 6.3L4.4 12l6.3 5.7v-3.8H12c3.2 0 6.3 1.3 7.6 3.8 0-4.7-2.8-7.6-7.9-7.6h-.9V6.3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl.png
new file mode 100644
index 00000000..df22b7de
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl.svg
new file mode 100644
index 00000000..9f4bd135
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arched-arrow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10.7 6.3L4.4 12l6.3 5.7v-3.8H12c3.2 0 6.3 1.3 7.6 3.8 0-4.7-2.8-7.6-7.9-7.6h-.9V6.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-invert.png
new file mode 100644
index 00000000..6299e866
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-invert.svg
new file mode 100644
index 00000000..cfde7f5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M16 12H6c-1.7 0-3 1.3-3 3h13v3l5-4.5L16 9v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-progressive.png
new file mode 100644
index 00000000..119a8be5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-progressive.svg
new file mode 100644
index 00000000..020e740d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M16 12H6c-1.7 0-3 1.3-3 3h13v3l5-4.5L16 9v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr.png
new file mode 100644
index 00000000..24905bc4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr.svg
new file mode 100644
index 00000000..b4c0e0d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 12H6c-1.7 0-3 1.3-3 3h13v3l5-4.5L16 9v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-invert.png
new file mode 100644
index 00000000..fb375e48
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-invert.svg
new file mode 100644
index 00000000..b701b610
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M8 12h10c1.7 0 3 1.3 3 3H8v3l-5-4.5L8 9v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-progressive.png
new file mode 100644
index 00000000..3192d35c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-progressive.svg
new file mode 100644
index 00000000..476c443b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M8 12h10c1.7 0 3 1.3 3 3H8v3l-5-4.5L8 9v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl.png
new file mode 100644
index 00000000..1cd81cbb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl.svg
new file mode 100644
index 00000000..1087ff94
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/arrow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 12h10c1.7 0 3 1.3 3 3H8v3l-5-4.5L8 9v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-invert.png
new file mode 100644
index 00000000..231cb1b2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-invert.svg
new file mode 100644
index 00000000..3285cc73
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 10h4V5h-4v5zm-5 2h9v-1H7v1zm0 2h9v-1H7v1zm0 2h9v-1H7v1zm4-9H7v1h4V7zm0 2H7v1h4V9zm0-4H7v1h4V5zM5 3h13v16H8c-1.7 0-3-1.3-3-3V3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-progressive.png
new file mode 100644
index 00000000..db45541f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-progressive.svg
new file mode 100644
index 00000000..61dda31c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 10h4V5h-4v5zm-5 2h9v-1H7v1zm0 2h9v-1H7v1zm0 2h9v-1H7v1zm4-9H7v1h4V7zm0 2H7v1h4V9zm0-4H7v1h4V5zM5 3h13v16H8c-1.7 0-3-1.3-3-3V3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr.png
new file mode 100644
index 00000000..cf7de13a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr.svg
new file mode 100644
index 00000000..862bc2b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 10h4V5h-4v5zm-5 2h9v-1H7v1zm0 2h9v-1H7v1zm0 2h9v-1H7v1zm4-9H7v1h4V7zm0 2H7v1h4V9zm0-4H7v1h4V5zM5 3h13v16H8c-1.7 0-3-1.3-3-3V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-invert.png
new file mode 100644
index 00000000..7b83a3ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-invert.svg
new file mode 100644
index 00000000..b92172ae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M11 10H7V5h4v5zm5 2H7v-1h9v1zm0 2H7v-1h9v1zm0 2H7v-1h9v1zm-4-9h4v1h-4V7zm0 2h4v1h-4V9zm0-4h4v1h-4V5zm6-2H5v16h10c1.7 0 3-1.3 3-3V3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-progressive.png
new file mode 100644
index 00000000..aba3c0ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-progressive.svg
new file mode 100644
index 00000000..d0e6a7a5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M11 10H7V5h4v5zm5 2H7v-1h9v1zm0 2H7v-1h9v1zm0 2H7v-1h9v1zm-4-9h4v1h-4V7zm0 2h4v1h-4V9zm0-4h4v1h-4V5zm6-2H5v16h10c1.7 0 3-1.3 3-3V3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl.png
new file mode 100644
index 00000000..d0b0e70d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl.svg
new file mode 100644
index 00000000..3b16dcbc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/article-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 10H7V5h4v5zm5 2H7v-1h9v1zm0 2H7v-1h9v1zm0 2H7v-1h9v1zm-4-9h4v1h-4V7zm0 2h4v1h-4V9zm0-4h4v1h-4V5zm6-2H5v16h10c1.7 0 3-1.3 3-3V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-invert.png
new file mode 100644
index 00000000..5eed7170
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-invert.svg
new file mode 100644
index 00000000..9557c564
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M21 11l-6 7-4-4-1 1 5 5 7-8z"/>
+ <path d="M17 14V3H4v13c0 1.7 1.3 3 3 3h5l-3-3H6v-1h2.6l1-1H6v-1h9v1h-2l1 1h2l1-1zM6 5h4v1H6V5zm0 2h4v1H6V7zm0 2h4v1H6V9zm9 3H6v-1h9v1zm-4-2V5h4v5h-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-progressive.png
new file mode 100644
index 00000000..688ec050
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-progressive.svg
new file mode 100644
index 00000000..5802afd4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M21 11l-6 7-4-4-1 1 5 5 7-8z"/>
+ <path d="M17 14V3H4v13c0 1.7 1.3 3 3 3h5l-3-3H6v-1h2.6l1-1H6v-1h9v1h-2l1 1h2l1-1zM6 5h4v1H6V5zm0 2h4v1H6V7zm0 2h4v1H6V9zm9 3H6v-1h9v1zm-4-2V5h4v5h-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr.png
new file mode 100644
index 00000000..5b169e27
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr.svg
new file mode 100644
index 00000000..396e6a1e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 11l-6 7-4-4-1 1 5 5 7-8z"/>
+ <path d="M17 14V3H4v13c0 1.7 1.3 3 3 3h5l-3-3H6v-1h2.6l1-1H6v-1h9v1h-2l1 1h2l1-1zM6 5h4v1H6V5zm0 2h4v1H6V7zm0 2h4v1H6V9zm9 3H6v-1h9v1zm-4-2V5h4v5h-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-invert.png
new file mode 100644
index 00000000..cc9c9dee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-invert.svg
new file mode 100644
index 00000000..fba5a327
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M5 11l6 7 4-4 1 1-5 5-7-8z"/>
+ <path d="M9 14V3h13v13c0 1.7-1.3 3-3 3h-5l3-3h3v-1h-2.6l-1-1H20v-1h-9v1h2l-1 1h-2l-1-1zm11-9h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm-9 3h9v-1h-9v1zm4-2V5h-4v5h4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-progressive.png
new file mode 100644
index 00000000..b271ac5d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-progressive.svg
new file mode 100644
index 00000000..02155936
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M5 11l6 7 4-4 1 1-5 5-7-8z"/>
+ <path d="M9 14V3h13v13c0 1.7-1.3 3-3 3h-5l3-3h3v-1h-2.6l-1-1H20v-1h-9v1h2l-1 1h-2l-1-1zm11-9h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm-9 3h9v-1h-9v1zm4-2V5h-4v5h4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl.png
new file mode 100644
index 00000000..9f22672a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl.svg
new file mode 100644
index 00000000..604143bb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleCheck-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 11l6 7 4-4 1 1-5 5-7-8z"/>
+ <path d="M9 14V3h13v13c0 1.7-1.3 3-3 3h-5l3-3h3v-1h-2.6l-1-1H20v-1h-9v1h2l-1 1h-2l-1-1zm11-9h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9zm-9 3h9v-1h-9v1zm4-2V5h-4v5h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-invert.png
new file mode 100644
index 00000000..76cc11ff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-invert.svg
new file mode 100644
index 00000000..f68467fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="article-redirect">
+ <path id="arrow" d="M18.1 14.2L23 18l-4.9 4.8v-2.2c-1.7 0-2.9-.2-4.3-1.2-1.2-.8-2.5-2.6-2.3-4.1 1.4 1 2.9 1.5 4.4 1.5.7 0 1.4-.1 2.1-.3l.1-2.3"/>
+ <path id="page" d="M5 3v13c0 1.7 1.3 3 3 3h3.375c-.157-.205-.3-.43-.438-.656-.42-.688-.77-1.483-.843-2.344H7v-1h3.125l.125-1H7v-1h3.375l.03-.188.283.188H16v1h-3.906l.22.156c.523.375 1.065.64 1.592.844H16v.406c.208-.013.418-.07.625-.094.068-1.294.125-3.874.125-3.874l1.25.968V3H5zm2 2h4v1H7V5zm5 0h4v5h-4V5zM7 7h4v1H7V7zm0 2h4v1H7V9zm0 2h9v1H7v-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-progressive.png
new file mode 100644
index 00000000..7b22a848
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-progressive.svg
new file mode 100644
index 00000000..28e7a46e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="article-redirect">
+ <path id="arrow" d="M18.1 14.2L23 18l-4.9 4.8v-2.2c-1.7 0-2.9-.2-4.3-1.2-1.2-.8-2.5-2.6-2.3-4.1 1.4 1 2.9 1.5 4.4 1.5.7 0 1.4-.1 2.1-.3l.1-2.3"/>
+ <path id="page" d="M5 3v13c0 1.7 1.3 3 3 3h3.375c-.157-.205-.3-.43-.438-.656-.42-.688-.77-1.483-.843-2.344H7v-1h3.125l.125-1H7v-1h3.375l.03-.188.283.188H16v1h-3.906l.22.156c.523.375 1.065.64 1.592.844H16v.406c.208-.013.418-.07.625-.094.068-1.294.125-3.874.125-3.874l1.25.968V3H5zm2 2h4v1H7V5zm5 0h4v5h-4V5zM7 7h4v1H7V7zm0 2h4v1H7V9zm0 2h9v1H7v-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr.png
new file mode 100644
index 00000000..3dbe20ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr.svg
new file mode 100644
index 00000000..028c64c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="article-redirect">
+ <path id="arrow" d="M18.1 14.2L23 18l-4.9 4.8v-2.2c-1.7 0-2.9-.2-4.3-1.2-1.2-.8-2.5-2.6-2.3-4.1 1.4 1 2.9 1.5 4.4 1.5.7 0 1.4-.1 2.1-.3l.1-2.3"/>
+ <path id="page" d="M5 3v13c0 1.7 1.3 3 3 3h3.375c-.157-.205-.3-.43-.438-.656-.42-.688-.77-1.483-.843-2.344H7v-1h3.125l.125-1H7v-1h3.375l.03-.188.283.188H16v1h-3.906l.22.156c.523.375 1.065.64 1.592.844H16v.406c.208-.013.418-.07.625-.094.068-1.294.125-3.874.125-3.874l1.25.968V3H5zm2 2h4v1H7V5zm5 0h4v5h-4V5zM7 7h4v1H7V7zm0 2h4v1H7V9zm0 2h9v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-invert.png
new file mode 100644
index 00000000..b31e0f97
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-invert.svg
new file mode 100644
index 00000000..d70b35f8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="article-redirect">
+ <path id="arrow" d="M5.9 14.2L1 18l4.9 4.8v-2.2c1.7 0 2.9-.2 4.3-1.2 1.2-.8 2.5-2.6 2.3-4.1-1.4 1-2.9 1.5-4.4 1.5-.7 0-1.4-.1-2.1-.3l-.1-2.3"/>
+ <path id="page" d="M19 3v13c0 1.7-1.3 3-3 3h-3.375c.157-.205.3-.43.438-.656.42-.688.77-1.483.843-2.344H17v-1h-3.125l-.125-1H17v-1h-3.375l-.03-.188-.283.188H8v1h3.906l-.22.156a7.097 7.097 0 0 1-1.592.844H8v.406c-.208-.013-.418-.07-.625-.094a178.903 178.903 0 0 1-.125-3.874L6 12.405V3zm-2 2h-4v1h4zm-5 0H8v5h4zm5 2h-4v1h4zm0 2h-4v1h4zm0 2H8v1h9z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-progressive.png
new file mode 100644
index 00000000..464c3446
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-progressive.svg
new file mode 100644
index 00000000..d49b9bdb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="article-redirect">
+ <path id="arrow" d="M5.9 14.2L1 18l4.9 4.8v-2.2c1.7 0 2.9-.2 4.3-1.2 1.2-.8 2.5-2.6 2.3-4.1-1.4 1-2.9 1.5-4.4 1.5-.7 0-1.4-.1-2.1-.3l-.1-2.3"/>
+ <path id="page" d="M19 3v13c0 1.7-1.3 3-3 3h-3.375c.157-.205.3-.43.438-.656.42-.688.77-1.483.843-2.344H17v-1h-3.125l-.125-1H17v-1h-3.375l-.03-.188-.283.188H8v1h3.906l-.22.156a7.097 7.097 0 0 1-1.592.844H8v.406c-.208-.013-.418-.07-.625-.094a178.903 178.903 0 0 1-.125-3.874L6 12.405V3zm-2 2h-4v1h4zm-5 0H8v5h4zm5 2h-4v1h4zm0 2h-4v1h4zm0 2H8v1h9z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl.png
new file mode 100644
index 00000000..60beb6ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl.svg
new file mode 100644
index 00000000..316d36ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleRedirect-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="article-redirect">
+ <path id="arrow" d="M5.9 14.2L1 18l4.9 4.8v-2.2c1.7 0 2.9-.2 4.3-1.2 1.2-.8 2.5-2.6 2.3-4.1-1.4 1-2.9 1.5-4.4 1.5-.7 0-1.4-.1-2.1-.3l-.1-2.3"/>
+ <path id="page" d="M19 3v13c0 1.7-1.3 3-3 3h-3.375c.157-.205.3-.43.438-.656.42-.688.77-1.483.843-2.344H17v-1h-3.125l-.125-1H17v-1h-3.375l-.03-.188-.283.188H8v1h3.906l-.22.156a7.097 7.097 0 0 1-1.592.844H8v.406c-.208-.013-.418-.07-.625-.094a178.903 178.903 0 0 1-.125-3.874L6 12.405V3zm-2 2h-4v1h4zm-5 0H8v5h4zm5 2h-4v1h4zm0 2h-4v1h4zm0 2H8v1h9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-invert.png
new file mode 100644
index 00000000..1bd1587b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-invert.svg
new file mode 100644
index 00000000..c4dbcdea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M19.1 18.5c.6-.7.9-1.5.9-2.5 0-2.2-1.8-4-4-4s-4 1.8-4 4 1.8 4 4 4c.7 0 1.3-.1 1.8-.4l2.7 2.7 1.1-1.1-2.5-2.7zm-3.1-.3c-1.2 0-2.2-1-2.2-2.3 0-1.2 1-2.2 2.2-2.2 1.2 0 2.3 1 2.3 2.2-.1 1.3-1.1 2.3-2.3 2.3zM11.8 13c.3-.4.6-.7 1-1H7v-1h9s1.2 0 2 .6V3H5v13c0 1.7 1.3 3 3 3h3.8c-.6-.8-1-1.9-1-3H7v-1h3.9l.3-1H7v-1h4.8zm.2-8h4v5h-4V5zM7 5h4v1H7V5zm0 2h4v1H7V7zm0 2h4v1H7V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-progressive.png
new file mode 100644
index 00000000..d22174eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-progressive.svg
new file mode 100644
index 00000000..2d71a624
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M19.1 18.5c.6-.7.9-1.5.9-2.5 0-2.2-1.8-4-4-4s-4 1.8-4 4 1.8 4 4 4c.7 0 1.3-.1 1.8-.4l2.7 2.7 1.1-1.1-2.5-2.7zm-3.1-.3c-1.2 0-2.2-1-2.2-2.3 0-1.2 1-2.2 2.2-2.2 1.2 0 2.3 1 2.3 2.2-.1 1.3-1.1 2.3-2.3 2.3zM11.8 13c.3-.4.6-.7 1-1H7v-1h9s1.2 0 2 .6V3H5v13c0 1.7 1.3 3 3 3h3.8c-.6-.8-1-1.9-1-3H7v-1h3.9l.3-1H7v-1h4.8zm.2-8h4v5h-4V5zM7 5h4v1H7V5zm0 2h4v1H7V7zm0 2h4v1H7V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr.png
new file mode 100644
index 00000000..1802dfc7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr.svg
new file mode 100644
index 00000000..ac41c2b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19.1 18.5c.6-.7.9-1.5.9-2.5 0-2.2-1.8-4-4-4s-4 1.8-4 4 1.8 4 4 4c.7 0 1.3-.1 1.8-.4l2.7 2.7 1.1-1.1-2.5-2.7zm-3.1-.3c-1.2 0-2.2-1-2.2-2.3 0-1.2 1-2.2 2.2-2.2 1.2 0 2.3 1 2.3 2.2-.1 1.3-1.1 2.3-2.3 2.3zM11.8 13c.3-.4.6-.7 1-1H7v-1h9s1.2 0 2 .6V3H5v13c0 1.7 1.3 3 3 3h3.8c-.6-.8-1-1.9-1-3H7v-1h3.9l.3-1H7v-1h4.8zm.2-8h4v5h-4V5zM7 5h4v1H7V5zm0 2h4v1H7V7zm0 2h4v1H7V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-invert.png
new file mode 100644
index 00000000..a8e8a3aa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-invert.svg
new file mode 100644
index 00000000..ffd42858
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M7.5 18.5c-.6-.7-.9-1.5-.9-2.5 0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4c-.7 0-1.3-.1-1.8-.4l-2.7 2.7L5 21.2l2.5-2.7zm3.1-.3c1.2 0 2.2-1 2.2-2.3 0-1.2-1-2.2-2.2-2.2-1.2 0-2.3 1-2.3 2.2.1 1.3 1.1 2.3 2.3 2.3zm4.2-5.2c-.3-.4-.6-.7-1-1h5.8v-1h-9s-1.2 0-2 .6V3h13v13c0 1.7-1.3 3-3 3h-3.8c.6-.8 1-1.9 1-3h3.8v-1h-3.9l-.3-1h4.2v-1h-4.8zm-.2-8h-4v5h4V5zm5 0h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-progressive.png
new file mode 100644
index 00000000..e83f1ee6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-progressive.svg
new file mode 100644
index 00000000..48ae2222
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M7.5 18.5c-.6-.7-.9-1.5-.9-2.5 0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4c-.7 0-1.3-.1-1.8-.4l-2.7 2.7L5 21.2l2.5-2.7zm3.1-.3c1.2 0 2.2-1 2.2-2.3 0-1.2-1-2.2-2.2-2.2-1.2 0-2.3 1-2.3 2.2.1 1.3 1.1 2.3 2.3 2.3zm4.2-5.2c-.3-.4-.6-.7-1-1h5.8v-1h-9s-1.2 0-2 .6V3h13v13c0 1.7-1.3 3-3 3h-3.8c.6-.8 1-1.9 1-3h3.8v-1h-3.9l-.3-1h4.2v-1h-4.8zm-.2-8h-4v5h4V5zm5 0h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl.png
new file mode 100644
index 00000000..a2611daf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl.svg
new file mode 100644
index 00000000..ed43acf5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articleSearch-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7.5 18.5c-.6-.7-.9-1.5-.9-2.5 0-2.2 1.8-4 4-4s4 1.8 4 4-1.8 4-4 4c-.7 0-1.3-.1-1.8-.4l-2.7 2.7L5 21.2l2.5-2.7zm3.1-.3c1.2 0 2.2-1 2.2-2.3 0-1.2-1-2.2-2.2-2.2-1.2 0-2.3 1-2.3 2.2.1 1.3 1.1 2.3 2.3 2.3zm4.2-5.2c-.3-.4-.6-.7-1-1h5.8v-1h-9s-1.2 0-2 .6V3h13v13c0 1.7-1.3 3-3 3h-3.8c.6-.8 1-1.9 1-3h3.8v-1h-3.9l-.3-1h4.2v-1h-4.8zm-.2-8h-4v5h4V5zm5 0h-4v1h4V5zm0 2h-4v1h4V7zm0 2h-4v1h4V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-invert.png
new file mode 100644
index 00000000..3a418f40
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-invert.svg
new file mode 100644
index 00000000..86b004f8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M11 12h4V7h-4v5zm-5 2h9v-1H6v1zm0 2h9v-1H6v1zm0 2h9v-1H6v1zm4-9H6v1h4V9zm0 2H6v1h4v-1zm0-4H6v1h4V7zM4 5h13v16H7c-1.7 0-3-1.3-3-3V5z"/>
+ <path d="M18 4v14h2V2H7v2" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-progressive.png
new file mode 100644
index 00000000..af2b7f02
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-progressive.svg
new file mode 100644
index 00000000..838655ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M11 12h4V7h-4v5zm-5 2h9v-1H6v1zm0 2h9v-1H6v1zm0 2h9v-1H6v1zm4-9H6v1h4V9zm0 2H6v1h4v-1zm0-4H6v1h4V7zM4 5h13v16H7c-1.7 0-3-1.3-3-3V5z"/>
+ <path d="M18 4v14h2V2H7v2" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr.png
new file mode 100644
index 00000000..bd048c45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr.svg
new file mode 100644
index 00000000..c1944975
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 12h4V7h-4v5zm-5 2h9v-1H6v1zm0 2h9v-1H6v1zm0 2h9v-1H6v1zm4-9H6v1h4V9zm0 2H6v1h4v-1zm0-4H6v1h4V7zM4 5h13v16H7c-1.7 0-3-1.3-3-3V5z"/>
+ <path d="M18 4v14h2V2H7v2" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-invert.png
new file mode 100644
index 00000000..fe548a1b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-invert.svg
new file mode 100644
index 00000000..e2793b5a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M13 12H9V7h4v5zm5 2H9v-1h9v1zm0 2H9v-1h9v1zm0 2H9v-1h9v1zm-4-9h4v1h-4V9zm0 2h4v1h-4v-1zm0-4h4v1h-4V7zm6-2H7v16h10c1.7 0 3-1.3 3-3V5z"/>
+ <path d="M6 4v14H4V2h13v2" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-progressive.png
new file mode 100644
index 00000000..839f1355
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-progressive.svg
new file mode 100644
index 00000000..bf3d169f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M13 12H9V7h4v5zm5 2H9v-1h9v1zm0 2H9v-1h9v1zm0 2H9v-1h9v1zm-4-9h4v1h-4V9zm0 2h4v1h-4v-1zm0-4h4v1h-4V7zm6-2H7v16h10c1.7 0 3-1.3 3-3V5z"/>
+ <path d="M6 4v14H4V2h13v2" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl.png
new file mode 100644
index 00000000..3ebb1133
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl.svg
new file mode 100644
index 00000000..40a9348f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/articles-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M13 12H9V7h4v5zm5 2H9v-1h9v1zm0 2H9v-1h9v1zm0 2H9v-1h9v1zm-4-9h4v1h-4V9zm0 2h4v1h-4v-1zm0-4h4v1h-4V7zm6-2H7v16h10c1.7 0 3-1.3 3-3V5z"/>
+ <path d="M6 4v14H4V2h13v2" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-invert.png
new file mode 100644
index 00000000..aa1b38e7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-invert.svg
new file mode 100644
index 00000000..2ced027a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-293 385 24 24"><g fill="#fff">
+ <path d="M-274.3 390.9c-1.6-1.6-4.3-1.5-5.8.1l.2.2c.5.5 1.3.7 2.1.4.8-.3 1.7-.1 2.4.6 1 .9.9 2.4 0 3.4l-7.1 7.1c-.9 1-2.4.9-3.4 0s-.9-2.4 0-3.4l4.4-4.4c.3-.3.9-.5 1.3-.1s.2 1-.1 1.3l-3.4 3.4c-.6.6-.6 1.7.1 2.3l4.3-4.3c.8-.8 1.1-1.8.9-2.7-.2-.9-.9-1.6-1.7-1.9-.9-.2-1.9 0-2.6.7l-4.4 4.4c-1.6 1.6-1.6 4.3.1 5.8 1.5 1.6 4.3 1.5 5.8-.1l7-7c.8-.8 1.2-1.9 1.2-3s-.5-2.1-1.3-2.8c-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-1.5-1.6.8.7 0 0z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-progressive.png
new file mode 100644
index 00000000..9723ae9e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-progressive.svg
new file mode 100644
index 00000000..0f02b304
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-293 385 24 24"><g fill="#36c">
+ <path d="M-274.3 390.9c-1.6-1.6-4.3-1.5-5.8.1l.2.2c.5.5 1.3.7 2.1.4.8-.3 1.7-.1 2.4.6 1 .9.9 2.4 0 3.4l-7.1 7.1c-.9 1-2.4.9-3.4 0s-.9-2.4 0-3.4l4.4-4.4c.3-.3.9-.5 1.3-.1s.2 1-.1 1.3l-3.4 3.4c-.6.6-.6 1.7.1 2.3l4.3-4.3c.8-.8 1.1-1.8.9-2.7-.2-.9-.9-1.6-1.7-1.9-.9-.2-1.9 0-2.6.7l-4.4 4.4c-1.6 1.6-1.6 4.3.1 5.8 1.5 1.6 4.3 1.5 5.8-.1l7-7c.8-.8 1.2-1.9 1.2-3s-.5-2.1-1.3-2.8c-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-1.5-1.6.8.7 0 0z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr.png
new file mode 100644
index 00000000..92dfaf21
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr.svg
new file mode 100644
index 00000000..74a4d646
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-293 385 24 24">
+ <path d="M-274.3 390.9c-1.6-1.6-4.3-1.5-5.8.1l.2.2c.5.5 1.3.7 2.1.4.8-.3 1.7-.1 2.4.6 1 .9.9 2.4 0 3.4l-7.1 7.1c-.9 1-2.4.9-3.4 0s-.9-2.4 0-3.4l4.4-4.4c.3-.3.9-.5 1.3-.1s.2 1-.1 1.3l-3.4 3.4c-.6.6-.6 1.7.1 2.3l4.3-4.3c.8-.8 1.1-1.8.9-2.7-.2-.9-.9-1.6-1.7-1.9-.9-.2-1.9 0-2.6.7l-4.4 4.4c-1.6 1.6-1.6 4.3.1 5.8 1.5 1.6 4.3 1.5 5.8-.1l7-7c.8-.8 1.2-1.9 1.2-3s-.5-2.1-1.3-2.8c-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-.7-.7.8.7 0 0-1.5-1.6.8.7 0 0z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-invert.png
new file mode 100644
index 00000000..bba8db56
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-invert.svg
new file mode 100644
index 00000000..faa925c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-119 70 24 24"><g fill="#fff">
+ <path d="M-113.3 75.6c-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7-1.3 1.7-1.3 2.8 0 1.1.4 2.2 1.2 3l7 7c1.5 1.6 4.3 1.7 5.8.1 1.7-1.5 1.7-4.2.1-5.8l-4.4-4.4c-.7-.7-1.7-.9-2.6-.7-.8.3-1.5 1-1.7 1.9-.2.9.1 1.9.9 2.7l4.3 4.3c.7-.6.7-1.7.1-2.3l-3.4-3.4c-.3-.3-.5-.9-.1-1.3s1-.2 1.3.1l4.4 4.4c.9 1 1 2.5 0 3.4s-2.5 1-3.4 0l-7.1-7.1c-.9-1-1-2.5 0-3.4.7-.7 1.6-.9 2.4-.6.8.3 1.6.1 2.1-.4l.2-.2c-1.5-1.6-4.2-1.8-5.8-.1-.8.7 1.5-1.7 0 0z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-progressive.png
new file mode 100644
index 00000000..8786e5a1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-progressive.svg
new file mode 100644
index 00000000..5e234a08
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-119 70 24 24"><g fill="#36c">
+ <path d="M-113.3 75.6c-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7-1.3 1.7-1.3 2.8 0 1.1.4 2.2 1.2 3l7 7c1.5 1.6 4.3 1.7 5.8.1 1.7-1.5 1.7-4.2.1-5.8l-4.4-4.4c-.7-.7-1.7-.9-2.6-.7-.8.3-1.5 1-1.7 1.9-.2.9.1 1.9.9 2.7l4.3 4.3c.7-.6.7-1.7.1-2.3l-3.4-3.4c-.3-.3-.5-.9-.1-1.3s1-.2 1.3.1l4.4 4.4c.9 1 1 2.5 0 3.4s-2.5 1-3.4 0l-7.1-7.1c-.9-1-1-2.5 0-3.4.7-.7 1.6-.9 2.4-.6.8.3 1.6.1 2.1-.4l.2-.2c-1.5-1.6-4.2-1.8-5.8-.1-.8.7 1.5-1.7 0 0z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl.png
new file mode 100644
index 00000000..f793246d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl.svg
new file mode 100644
index 00000000..f53f5a47
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/attachment-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="-119 70 24 24">
+ <path d="M-113.3 75.6c-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7.7-.7 0 0-.8.7-1.3 1.7-1.3 2.8 0 1.1.4 2.2 1.2 3l7 7c1.5 1.6 4.3 1.7 5.8.1 1.7-1.5 1.7-4.2.1-5.8l-4.4-4.4c-.7-.7-1.7-.9-2.6-.7-.8.3-1.5 1-1.7 1.9-.2.9.1 1.9.9 2.7l4.3 4.3c.7-.6.7-1.7.1-2.3l-3.4-3.4c-.3-.3-.5-.9-.1-1.3s1-.2 1.3.1l4.4 4.4c.9 1 1 2.5 0 3.4s-2.5 1-3.4 0l-7.1-7.1c-.9-1-1-2.5 0-3.4.7-.7 1.6-.9 2.4-.6.8.3 1.6.1 2.1-.4l.2-.2c-1.5-1.6-4.2-1.8-5.8-.1-.8.7 1.5-1.7 0 0z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-invert.png
new file mode 100644
index 00000000..05911d32
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-invert.svg
new file mode 100644
index 00000000..61caba7e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M17.5 13V8c0-3-2.3-5-5.5-5S6.5 5 6.5 8v5c0 2 0 3-2 3v1h15v-1c-2 0-2-1-2-3zM12 19H9c0 1 1.6 2 3 2s3-1 3-2h-3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-progressive.png
new file mode 100644
index 00000000..81294ffd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-progressive.svg
new file mode 100644
index 00000000..157430b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M17.5 13V8c0-3-2.3-5-5.5-5S6.5 5 6.5 8v5c0 2 0 3-2 3v1h15v-1c-2 0-2-1-2-3zM12 19H9c0 1 1.6 2 3 2s3-1 3-2h-3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell.png
new file mode 100644
index 00000000..91e83972
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell.svg
new file mode 100644
index 00000000..09b65f29
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bell.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.5 13V8c0-3-2.3-5-5.5-5S6.5 5 6.5 8v5c0 2 0 3-2 3v1h15v-1c-2 0-2-1-2-3zM12 19H9c0 1 1.6 2 3 2s3-1 3-2h-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-invert.png
new file mode 100644
index 00000000..fb213703
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-invert.svg
new file mode 100644
index 00000000..49416aa0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M17.8 13.7L19.5 9c1-2.8-.5-5.5-3.5-6.6-3-1.1-5.9 0-6.9 2.8L7.4 9.9c-.7 1.9-1 2.8-2.9 2.1l-.3 1 14.1 5.1.3-.9c-1.9-.7-1.5-1.6-.8-3.5zM12 18.8l-2.8-1c-.3.9.8 2.4 2.1 2.9s3.2.1 3.5-.9l-2.8-1z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-progressive.png
new file mode 100644
index 00000000..91641ac1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-progressive.svg
new file mode 100644
index 00000000..d064356a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M17.8 13.7L19.5 9c1-2.8-.5-5.5-3.5-6.6-3-1.1-5.9 0-6.9 2.8L7.4 9.9c-.7 1.9-1 2.8-2.9 2.1l-.3 1 14.1 5.1.3-.9c-1.9-.7-1.5-1.6-.8-3.5zM12 18.8l-2.8-1c-.3.9.8 2.4 2.1 2.9s3.2.1 3.5-.9l-2.8-1z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr.png
new file mode 100644
index 00000000..fb13de1a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr.svg
new file mode 100644
index 00000000..855581b0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.8 13.7L19.5 9c1-2.8-.5-5.5-3.5-6.6-3-1.1-5.9 0-6.9 2.8L7.4 9.9c-.7 1.9-1 2.8-2.9 2.1l-.3 1 14.1 5.1.3-.9c-1.9-.7-1.5-1.6-.8-3.5zM12 18.8l-2.8-1c-.3.9.8 2.4 2.1 2.9s3.2.1 3.5-.9l-2.8-1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-invert.png
new file mode 100644
index 00000000..d0ebae56
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-invert.svg
new file mode 100644
index 00000000..b854834f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M6.21 13.7L4.51 9c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-progressive.png
new file mode 100644
index 00000000..eddcf737
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-progressive.svg
new file mode 100644
index 00000000..a9cdb3c6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M6.21 13.7L4.51 9c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl.png
new file mode 100644
index 00000000..b05fd4c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl.svg
new file mode 100644
index 00000000..e1f2961c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bellOn-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6.21 13.7L4.51 9c-1-2.8.5-5.5 3.5-6.6 3-1.1 5.9 0 6.9 2.8l1.7 4.7c.7 1.9 1 2.8 2.9 2.1l.3 1-14.1 5.1-.3-.9c1.9-.7 1.5-1.6.8-3.5zm5.8 5.1l2.8-1c.3.9-.8 2.4-2.1 2.9s-3.2.1-3.5-.9l2.8-1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-invert.png
new file mode 100644
index 00000000..ad247d35
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-invert.svg
new file mode 100644
index 00000000..60d7fd44
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path id="big-a" d="M14.334 6h1.372l4.48 12H18.48l-1.493-4h-4l-1.507 4H9.814zm2.28 7l-1.617-4.333L13.363 13h3.25z"/>
+ <path id="small-a" d="M6.172 12h.686l2.24 6h-.853L7.5 16H5.497l-.753 2h-.833zm1.14 3.5l-.81-2.166-.816 2.166h1.625z"/>
+ <path id="arrow" d="M9 9H4l2.5-3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-progressive.png
new file mode 100644
index 00000000..af290b96
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-progressive.svg
new file mode 100644
index 00000000..863fe926
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path id="big-a" d="M14.334 6h1.372l4.48 12H18.48l-1.493-4h-4l-1.507 4H9.814zm2.28 7l-1.617-4.333L13.363 13h3.25z"/>
+ <path id="small-a" d="M6.172 12h.686l2.24 6h-.853L7.5 16H5.497l-.753 2h-.833zm1.14 3.5l-.81-2.166-.816 2.166h1.625z"/>
+ <path id="arrow" d="M9 9H4l2.5-3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr.png
new file mode 100644
index 00000000..e8b2911d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr.svg
new file mode 100644
index 00000000..fffbcdd3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="big-a" d="M14.334 6h1.372l4.48 12H18.48l-1.493-4h-4l-1.507 4H9.814zm2.28 7l-1.617-4.333L13.363 13h3.25z"/>
+ <path id="small-a" d="M6.172 12h.686l2.24 6h-.853L7.5 16H5.497l-.753 2h-.833zm1.14 3.5l-.81-2.166-.816 2.166h1.625z"/>
+ <path id="arrow" d="M9 9H4l2.5-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-invert.png
new file mode 100644
index 00000000..f40c3032
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-invert.svg
new file mode 100644
index 00000000..b2fbe9e5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path id="big-a" d="M9.666 6H8.294l-4.48 12H5.52l1.493-4h4l1.507 4h1.666zm-2.28 7l1.617-4.333L10.637 13h-3.25z"/>
+ <path id="small-a" d="M17.828 12h-.686l-2.24 6h.853l.747-2h2l.753 2h.833zm-1.14 3.5l.81-2.167.816 2.167H16.69z"/>
+ <path id="arrow" d="M15 9h5l-2.5-3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-progressive.png
new file mode 100644
index 00000000..a5095a1a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-progressive.svg
new file mode 100644
index 00000000..46c5048a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path id="big-a" d="M9.666 6H8.294l-4.48 12H5.52l1.493-4h4l1.507 4h1.666zm-2.28 7l1.617-4.333L10.637 13h-3.25z"/>
+ <path id="small-a" d="M17.828 12h-.686l-2.24 6h.853l.747-2h2l.753 2h.833zm-1.14 3.5l.81-2.167.816 2.167H16.69z"/>
+ <path id="arrow" d="M15 9h5l-2.5-3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl.png
new file mode 100644
index 00000000..2f5e05df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl.svg
new file mode 100644
index 00000000..7b903c4b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bigger-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="big-a" d="M9.666 6H8.294l-4.48 12H5.52l1.493-4h4l1.507 4h1.666zm-2.28 7l1.617-4.333L10.637 13h-3.25z"/>
+ <path id="small-a" d="M17.828 12h-.686l-2.24 6h.853l.747-2h2l.753 2h.833zm-1.14 3.5l.81-2.167.816 2.167H16.69z"/>
+ <path id="arrow" d="M15 9h5l-2.5-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-destructive.png
new file mode 100644
index 00000000..54b9f62f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-destructive.svg
new file mode 100644
index 00000000..b7030949
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#d33">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm5 9H7v-2h10v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-invert.png
new file mode 100644
index 00000000..ca81ab7f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-invert.svg
new file mode 100644
index 00000000..97f21c3d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm5 9H7v-2h10v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-progressive.png
new file mode 100644
index 00000000..c82c3ebe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-progressive.svg
new file mode 100644
index 00000000..e3648cf3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm5 9H7v-2h10v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block.png
new file mode 100644
index 00000000..7f8eb2a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block.svg
new file mode 100644
index 00000000..b50bb618
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/block.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm5 9H7v-2h10v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-invert.png
new file mode 100644
index 00000000..8c11dadc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-invert.svg
new file mode 100644
index 00000000..b02b5c71
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M16 18h3L14 6h-3L6 18h3l1.25-3h4.5L16 18zm-4.917-5L12.5 9.6l1.417 3.4h-2.834z" id="bold-a"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-progressive.png
new file mode 100644
index 00000000..36f6920c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-progressive.svg
new file mode 100644
index 00000000..4f051bf7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M16 18h3L14 6h-3L6 18h3l1.25-3h4.5L16 18zm-4.917-5L12.5 9.6l1.417 3.4h-2.834z" id="bold-a"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a.png
new file mode 100644
index 00000000..2907677f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a.svg
new file mode 100644
index 00000000..ce9f4f84
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-a.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 18h3L14 6h-3L6 18h3l1.25-3h4.5L16 18zm-4.917-5L12.5 9.6l1.417 3.4h-2.834z" id="bold-a"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-invert.png
new file mode 100644
index 00000000..eac1ac74
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-invert.svg
new file mode 100644
index 00000000..ab901fb5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-arab-ain">
+ <path id="arab-ain" d="M9.337 13.616c0 1.35 1.386 2.1 4.16 2.258l2.186-.03.318.045c-.03.12-.25.34-.66.65l-.09.06c-1.233.93-2.42 1.394-3.56 1.394-1.14 0-2.043-.33-2.71-.99-.65-.66-.973-1.56-.973-2.7.006-1.353.567-2.572 1.685-3.657v-.044l-.606-.55a.952.952 0 0 1-.222-.63c0-.49.24-1.11.72-1.863.65-1.045 1.302-1.565 1.957-1.56.886.005 1.618.42 2.194 1.246.325.48-.03.55-1.064.22-.843-.33-1.528-.05-2.055.826l.016.074 1.125.866.05.005c1.405-.497 2.42-.74 3.044-.725-.06.116-.14.36-.244.732a27.75 27.75 0 0 1-.304.982l-.125.372-.386.05c-1.743.24-2.992.716-3.745 1.43-.465.463-.7.972-.704 1.524"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-progressive.png
new file mode 100644
index 00000000..0e9c1b0b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-progressive.svg
new file mode 100644
index 00000000..d905f22a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-arab-ain">
+ <path id="arab-ain" d="M9.337 13.616c0 1.35 1.386 2.1 4.16 2.258l2.186-.03.318.045c-.03.12-.25.34-.66.65l-.09.06c-1.233.93-2.42 1.394-3.56 1.394-1.14 0-2.043-.33-2.71-.99-.65-.66-.973-1.56-.973-2.7.006-1.353.567-2.572 1.685-3.657v-.044l-.606-.55a.952.952 0 0 1-.222-.63c0-.49.24-1.11.72-1.863.65-1.045 1.302-1.565 1.957-1.56.886.005 1.618.42 2.194 1.246.325.48-.03.55-1.064.22-.843-.33-1.528-.05-2.055.826l.016.074 1.125.866.05.005c1.405-.497 2.42-.74 3.044-.725-.06.116-.14.36-.244.732a27.75 27.75 0 0 1-.304.982l-.125.372-.386.05c-1.743.24-2.992.716-3.745 1.43-.465.463-.7.972-.704 1.524"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain.png
new file mode 100644
index 00000000..931b6cfd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain.svg
new file mode 100644
index 00000000..452c3d0c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-ain.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-arab-ain">
+ <path id="arab-ain" d="M9.337 13.616c0 1.35 1.386 2.1 4.16 2.258l2.186-.03.318.045c-.03.12-.25.34-.66.65l-.09.06c-1.233.93-2.42 1.394-3.56 1.394-1.14 0-2.043-.33-2.71-.99-.65-.66-.973-1.56-.973-2.7.006-1.353.567-2.572 1.685-3.657v-.044l-.606-.55a.952.952 0 0 1-.222-.63c0-.49.24-1.11.72-1.863.65-1.045 1.302-1.565 1.957-1.56.886.005 1.618.42 2.194 1.246.325.48-.03.55-1.064.22-.843-.33-1.528-.05-2.055.826l.016.074 1.125.866.05.005c1.405-.497 2.42-.74 3.044-.725-.06.116-.14.36-.244.732a27.75 27.75 0 0 1-.304.982l-.125.372-.386.05c-1.743.24-2.992.716-3.745 1.43-.465.463-.7.972-.704 1.524"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-invert.png
new file mode 100644
index 00000000..0973b1f4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-invert.svg
new file mode 100644
index 00000000..e02613e0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-arab-dad">
+ <path id="arab-dad" d="M16.41 8.232l-1.675-.665L15.43 6l1.687.64-.707 1.592m.775 3.078c-.51-.286-1-.427-1.476-.423-.478 0-.99.205-1.54.616l-.505.38.006.024c1.085.066 1.935.1 2.55.1h.315c.57-.022.994-.065 1.278-.132-.067-.17-.275-.36-.625-.566h-.006M10.38 14.6c-.016-.905-.33-1.87-.937-2.9l1.294-1.73.118.15c.267.337.504.925.713 1.767l.064.05c.496-.007.942-.17 1.338-.484v-.006l1.732-1.53c.68-.6 1.282-.9 1.807-.9.383.003.85.194 1.394.57.55.378.884.697 1 .96.063.15.094.385.094.71 0 .694-.11 1.227-.33 1.596-.193.31-.474.555-.845.734-.438.208-1.55.312-3.333.312-.8 0-1.794-.02-2.982-.064l-.142.43c-.254.67-.463 1.112-.625 1.323-.724.937-1.785 1.405-3.182 1.405-1.71-.006-2.56-.92-2.56-2.74.003-.94.278-1.814.824-2.618.15-.216.298-.367.444-.454.225-.133.288-.09.188.124-.396.862-.596 1.548-.6 2.058.008 1.177.752 1.768 2.232 1.772 1.038-.004 1.803-.182 2.295-.535"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-progressive.png
new file mode 100644
index 00000000..8158ca1d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-progressive.svg
new file mode 100644
index 00000000..bbf7a38c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-arab-dad">
+ <path id="arab-dad" d="M16.41 8.232l-1.675-.665L15.43 6l1.687.64-.707 1.592m.775 3.078c-.51-.286-1-.427-1.476-.423-.478 0-.99.205-1.54.616l-.505.38.006.024c1.085.066 1.935.1 2.55.1h.315c.57-.022.994-.065 1.278-.132-.067-.17-.275-.36-.625-.566h-.006M10.38 14.6c-.016-.905-.33-1.87-.937-2.9l1.294-1.73.118.15c.267.337.504.925.713 1.767l.064.05c.496-.007.942-.17 1.338-.484v-.006l1.732-1.53c.68-.6 1.282-.9 1.807-.9.383.003.85.194 1.394.57.55.378.884.697 1 .96.063.15.094.385.094.71 0 .694-.11 1.227-.33 1.596-.193.31-.474.555-.845.734-.438.208-1.55.312-3.333.312-.8 0-1.794-.02-2.982-.064l-.142.43c-.254.67-.463 1.112-.625 1.323-.724.937-1.785 1.405-3.182 1.405-1.71-.006-2.56-.92-2.56-2.74.003-.94.278-1.814.824-2.618.15-.216.298-.367.444-.454.225-.133.288-.09.188.124-.396.862-.596 1.548-.6 2.058.008 1.177.752 1.768 2.232 1.772 1.038-.004 1.803-.182 2.295-.535"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad.png
new file mode 100644
index 00000000..11212576
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad.svg
new file mode 100644
index 00000000..b90bb77a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-arab-dad.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-arab-dad">
+ <path id="arab-dad" d="M16.41 8.232l-1.675-.665L15.43 6l1.687.64-.707 1.592m.775 3.078c-.51-.286-1-.427-1.476-.423-.478 0-.99.205-1.54.616l-.505.38.006.024c1.085.066 1.935.1 2.55.1h.315c.57-.022.994-.065 1.278-.132-.067-.17-.275-.36-.625-.566h-.006M10.38 14.6c-.016-.905-.33-1.87-.937-2.9l1.294-1.73.118.15c.267.337.504.925.713 1.767l.064.05c.496-.007.942-.17 1.338-.484v-.006l1.732-1.53c.68-.6 1.282-.9 1.807-.9.383.003.85.194 1.394.57.55.378.884.697 1 .96.063.15.094.385.094.71 0 .694-.11 1.227-.33 1.596-.193.31-.474.555-.845.734-.438.208-1.55.312-3.333.312-.8 0-1.794-.02-2.982-.064l-.142.43c-.254.67-.463 1.112-.625 1.323-.724.937-1.785 1.405-3.182 1.405-1.71-.006-2.56-.92-2.56-2.74.003-.94.278-1.814.824-2.618.15-.216.298-.367.444-.454.225-.133.288-.09.188.124-.396.862-.596 1.548-.6 2.058.008 1.177.752 1.768 2.232 1.772 1.038-.004 1.803-.182 2.295-.535"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-invert.png
new file mode 100644
index 00000000..2ae27c21
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-invert.svg
new file mode 100644
index 00000000..1d9ea40a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-armn-to">
+ <path id="armn-to" d="M13.86 16.257c.124 0 .254-.026.39-.078.135-.06.257-.15.367-.28a1.43 1.43 0 0 0 .273-.517c.073-.214.11-.48.11-.798V13h-1.14c-.14 0-.284.026-.43.078a.905.905 0 0 0-.383.258c-.11.125-.2.294-.274.508-.067.213-.1.487-.1.82 0 .34.035.47.108.695.08.21.18.39.29.53.12.13.25.23.39.29.14.05.276.07.406.07m-2.97-7.84a2.67 2.67 0 0 0-.975.45 2.1 2.1 0 0 0-.672.813c-.16.342-.242.78-.242 1.31V18H6v-7.188c0-.776.15-1.455.453-2.04a4.227 4.227 0 0 1 1.234-1.467c.52-.39 1.13-.685 1.83-.883a8.114 8.114 0 0 1 2.225-.297c.526 0 1.04.044 1.54.133.504.088.98.22 1.43.398.447.172.858.388 1.233.65.375.26.698.564.97.913.275.34.49.73.64 1.17.15.43.226 1.09.226 1.61h1.36v2.04h-1.36v1.6c0 .58-.102 1.09-.31 1.54-.21.44-.49.81-.844 1.11-.35.302-.834.53-1.297.687-.465.15-.954.226-1.47.226-.51 0-.997-.08-1.46-.235a3.46 3.46 0 0 1-1.22-.703 3.452 3.452 0 0 1-.836-1.174c-.203-.472-.304-1.027-.304-1.662s.1-1.18.32-1.64c.21-.46.49-.684.85-.976.35-.297.76-.513 1.22-.648.452-.14.93-.21 1.43-.21h1.13c-.01-.49-.04-1.044-.24-1.36a2.26 2.26 0 0 0-.77-.767 3.234 3.234 0 0 0-.986-.427c-.375-.09-.578-.094-1.1-.094-.52 0-.64.02-1.01.102z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-progressive.png
new file mode 100644
index 00000000..66b22c5f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-progressive.svg
new file mode 100644
index 00000000..4bb91c99
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-armn-to">
+ <path id="armn-to" d="M13.86 16.257c.124 0 .254-.026.39-.078.135-.06.257-.15.367-.28a1.43 1.43 0 0 0 .273-.517c.073-.214.11-.48.11-.798V13h-1.14c-.14 0-.284.026-.43.078a.905.905 0 0 0-.383.258c-.11.125-.2.294-.274.508-.067.213-.1.487-.1.82 0 .34.035.47.108.695.08.21.18.39.29.53.12.13.25.23.39.29.14.05.276.07.406.07m-2.97-7.84a2.67 2.67 0 0 0-.975.45 2.1 2.1 0 0 0-.672.813c-.16.342-.242.78-.242 1.31V18H6v-7.188c0-.776.15-1.455.453-2.04a4.227 4.227 0 0 1 1.234-1.467c.52-.39 1.13-.685 1.83-.883a8.114 8.114 0 0 1 2.225-.297c.526 0 1.04.044 1.54.133.504.088.98.22 1.43.398.447.172.858.388 1.233.65.375.26.698.564.97.913.275.34.49.73.64 1.17.15.43.226 1.09.226 1.61h1.36v2.04h-1.36v1.6c0 .58-.102 1.09-.31 1.54-.21.44-.49.81-.844 1.11-.35.302-.834.53-1.297.687-.465.15-.954.226-1.47.226-.51 0-.997-.08-1.46-.235a3.46 3.46 0 0 1-1.22-.703 3.452 3.452 0 0 1-.836-1.174c-.203-.472-.304-1.027-.304-1.662s.1-1.18.32-1.64c.21-.46.49-.684.85-.976.35-.297.76-.513 1.22-.648.452-.14.93-.21 1.43-.21h1.13c-.01-.49-.04-1.044-.24-1.36a2.26 2.26 0 0 0-.77-.767 3.234 3.234 0 0 0-.986-.427c-.375-.09-.578-.094-1.1-.094-.52 0-.64.02-1.01.102z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to.png
new file mode 100644
index 00000000..6f6349b0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to.svg
new file mode 100644
index 00000000..c35979af
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-armn-to.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-armn-to">
+ <path id="armn-to" d="M13.86 16.257c.124 0 .254-.026.39-.078.135-.06.257-.15.367-.28a1.43 1.43 0 0 0 .273-.517c.073-.214.11-.48.11-.798V13h-1.14c-.14 0-.284.026-.43.078a.905.905 0 0 0-.383.258c-.11.125-.2.294-.274.508-.067.213-.1.487-.1.82 0 .34.035.47.108.695.08.21.18.39.29.53.12.13.25.23.39.29.14.05.276.07.406.07m-2.97-7.84a2.67 2.67 0 0 0-.975.45 2.1 2.1 0 0 0-.672.813c-.16.342-.242.78-.242 1.31V18H6v-7.188c0-.776.15-1.455.453-2.04a4.227 4.227 0 0 1 1.234-1.467c.52-.39 1.13-.685 1.83-.883a8.114 8.114 0 0 1 2.225-.297c.526 0 1.04.044 1.54.133.504.088.98.22 1.43.398.447.172.858.388 1.233.65.375.26.698.564.97.913.275.34.49.73.64 1.17.15.43.226 1.09.226 1.61h1.36v2.04h-1.36v1.6c0 .58-.102 1.09-.31 1.54-.21.44-.49.81-.844 1.11-.35.302-.834.53-1.297.687-.465.15-.954.226-1.47.226-.51 0-.997-.08-1.46-.235a3.46 3.46 0 0 1-1.22-.703 3.452 3.452 0 0 1-.836-1.174c-.203-.472-.304-1.027-.304-1.662s.1-1.18.32-1.64c.21-.46.49-.684.85-.976.35-.297.76-.513 1.22-.648.452-.14.93-.21 1.43-.21h1.13c-.01-.49-.04-1.044-.24-1.36a2.26 2.26 0 0 0-.77-.767 3.234 3.234 0 0 0-.986-.427c-.375-.09-.578-.094-1.1-.094-.52 0-.64.02-1.01.102z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-invert.png
new file mode 100644
index 00000000..e242b55d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-invert.svg
new file mode 100644
index 00000000..0a03c2ed
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-b">
+ <path id="b" d="M7 18h6c2 0 4-1 4-3 0-1.064.01-1.975-1.99-3 2-.975 1.99-1.935 1.99-3 0-2-2-3-4-3H7v12zm7-8c0 1 0 1-2 1h-2V8h2c2 0 2 0 2 1v1zm-2 6h-2v-3h2c2 0 2 0 2 1v1s0 1-2 1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-progressive.png
new file mode 100644
index 00000000..96f917a5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-progressive.svg
new file mode 100644
index 00000000..adf665e4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-b">
+ <path id="b" d="M7 18h6c2 0 4-1 4-3 0-1.064.01-1.975-1.99-3 2-.975 1.99-1.935 1.99-3 0-2-2-3-4-3H7v12zm7-8c0 1 0 1-2 1h-2V8h2c2 0 2 0 2 1v1zm-2 6h-2v-3h2c2 0 2 0 2 1v1s0 1-2 1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b.png
new file mode 100644
index 00000000..8d09636e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b.svg
new file mode 100644
index 00000000..1806709a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-b.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-b">
+ <path id="b" d="M7 18h6c2 0 4-1 4-3 0-1.064.01-1.975-1.99-3 2-.975 1.99-1.935 1.99-3 0-2-2-3-4-3H7v12zm7-8c0 1 0 1-2 1h-2V8h2c2 0 2 0 2 1v1zm-2 6h-2v-3h2c2 0 2 0 2 1v1s0 1-2 1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-invert.png
new file mode 100644
index 00000000..c131903a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-invert.svg
new file mode 100644
index 00000000..cd671074
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-cyrl-be">
+ <path id="cyrl-be" d="M7 6h9v2h-6v3h2.65c.892 0 1.632.11 2.22.327.587.218 1.087.622 1.5 1.21.42.59.63 1.188.63 1.98 0 .812-.21 1.397-.63 1.976-.418.578-.897.974-1.436 1.187-.533.213-1.295.32-2.286.32h-5.65m4.768-2c.75 0 1.28-.05 1.584-.12.305-.077.57-.247.792-.51.23-.26.343-.472.343-.854 0-.557-.2-.868-.596-1.12-.4-.255-1.07-.397-2.02-.397H10v3"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-progressive.png
new file mode 100644
index 00000000..4337f73a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-progressive.svg
new file mode 100644
index 00000000..22c3bf58
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-cyrl-be">
+ <path id="cyrl-be" d="M7 6h9v2h-6v3h2.65c.892 0 1.632.11 2.22.327.587.218 1.087.622 1.5 1.21.42.59.63 1.188.63 1.98 0 .812-.21 1.397-.63 1.976-.418.578-.897.974-1.436 1.187-.533.213-1.295.32-2.286.32h-5.65m4.768-2c.75 0 1.28-.05 1.584-.12.305-.077.57-.247.792-.51.23-.26.343-.472.343-.854 0-.557-.2-.868-.596-1.12-.4-.255-1.07-.397-2.02-.397H10v3"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be.png
new file mode 100644
index 00000000..de9e9d1b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be.svg
new file mode 100644
index 00000000..9d84cb04
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-be.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-cyrl-be">
+ <path id="cyrl-be" d="M7 6h9v2h-6v3h2.65c.892 0 1.632.11 2.22.327.587.218 1.087.622 1.5 1.21.42.59.63 1.188.63 1.98 0 .812-.21 1.397-.63 1.976-.418.578-.897.974-1.436 1.187-.533.213-1.295.32-2.286.32h-5.65m4.768-2c.75 0 1.28-.05 1.584-.12.305-.077.57-.247.792-.51.23-.26.343-.472.343-.854 0-.557-.2-.868-.596-1.12-.4-.255-1.07-.397-2.02-.397H10v3"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-invert.png
new file mode 100644
index 00000000..ce6f320e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-invert.svg
new file mode 100644
index 00000000..42ba1932
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-cyrl-te">
+ <path id="te" d="M11 18V8H7V6h11v2h-4v10"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-progressive.png
new file mode 100644
index 00000000..5e2073ac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-progressive.svg
new file mode 100644
index 00000000..73a76a3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-cyrl-te">
+ <path id="te" d="M11 18V8H7V6h11v2h-4v10"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te.png
new file mode 100644
index 00000000..281d7187
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te.svg
new file mode 100644
index 00000000..63aee3ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-te.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-cyrl-te">
+ <path id="te" d="M11 18V8H7V6h11v2h-4v10"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-invert.png
new file mode 100644
index 00000000..080e7316
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-invert.svg
new file mode 100644
index 00000000..4643345b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-cyrl-zhe">
+ <path id="cyrl-zhe" d="M13 6v5.154c.328-.033.537-.18.705-.447.168-.266.4-.873.698-1.82.39-1.242.79-2.034 1.197-2.375.403-.336 1.075-.504 2.014-.504L18 6v1.78l-.386-.008c-.4 0-.69.062-.878.187-.186.112-.337.3-.452.55-.115.25-.286.76-.512 1.533-.12.41-.25.755-.392 1.032-.137.275-.383.536-.738.78.44.156.8.465 1.084.926.288.455.603 1.103.944 1.943L18 18h-2.314l-1.17-3.08-.113-.253-.24-.56c-.247-.57-.45-.933-.61-1.09A.726.726 0 0 0 13 12.78V18h-2v-5.22c-.226 0-.382.077-.546.23-.164.15-.368.517-.612 1.097l-.246.56-.113.253L8.313 18H6l1.33-3.267c.327-.808.635-1.447.923-1.92.293-.476.663-.793 1.11-.95-.355-.244-.603-.5-.745-.772a6.357 6.357 0 0 1-.392-1.04c-.222-.76-.39-1.26-.505-1.52-.11-.25-.26-.44-.45-.57-.18-.12-.49-.18-.912-.18H6V6l.386.008c.953 0 1.63.17 2.034.512.4.347.79 1.136 1.177 2.366.3.954.534 1.564.698 1.83.168.26.377.405.705.438V6.002"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-progressive.png
new file mode 100644
index 00000000..86de0d41
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-progressive.svg
new file mode 100644
index 00000000..3b7fee9f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-cyrl-zhe">
+ <path id="cyrl-zhe" d="M13 6v5.154c.328-.033.537-.18.705-.447.168-.266.4-.873.698-1.82.39-1.242.79-2.034 1.197-2.375.403-.336 1.075-.504 2.014-.504L18 6v1.78l-.386-.008c-.4 0-.69.062-.878.187-.186.112-.337.3-.452.55-.115.25-.286.76-.512 1.533-.12.41-.25.755-.392 1.032-.137.275-.383.536-.738.78.44.156.8.465 1.084.926.288.455.603 1.103.944 1.943L18 18h-2.314l-1.17-3.08-.113-.253-.24-.56c-.247-.57-.45-.933-.61-1.09A.726.726 0 0 0 13 12.78V18h-2v-5.22c-.226 0-.382.077-.546.23-.164.15-.368.517-.612 1.097l-.246.56-.113.253L8.313 18H6l1.33-3.267c.327-.808.635-1.447.923-1.92.293-.476.663-.793 1.11-.95-.355-.244-.603-.5-.745-.772a6.357 6.357 0 0 1-.392-1.04c-.222-.76-.39-1.26-.505-1.52-.11-.25-.26-.44-.45-.57-.18-.12-.49-.18-.912-.18H6V6l.386.008c.953 0 1.63.17 2.034.512.4.347.79 1.136 1.177 2.366.3.954.534 1.564.698 1.83.168.26.377.405.705.438V6.002"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe.png
new file mode 100644
index 00000000..98387012
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe.svg
new file mode 100644
index 00000000..aab3f4c1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-cyrl-zhe.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-cyrl-zhe">
+ <path id="cyrl-zhe" d="M13 6v5.154c.328-.033.537-.18.705-.447.168-.266.4-.873.698-1.82.39-1.242.79-2.034 1.197-2.375.403-.336 1.075-.504 2.014-.504L18 6v1.78l-.386-.008c-.4 0-.69.062-.878.187-.186.112-.337.3-.452.55-.115.25-.286.76-.512 1.533-.12.41-.25.755-.392 1.032-.137.275-.383.536-.738.78.44.156.8.465 1.084.926.288.455.603 1.103.944 1.943L18 18h-2.314l-1.17-3.08-.113-.253-.24-.56c-.247-.57-.45-.933-.61-1.09A.726.726 0 0 0 13 12.78V18h-2v-5.22c-.226 0-.382.077-.546.23-.164.15-.368.517-.612 1.097l-.246.56-.113.253L8.313 18H6l1.33-3.267c.327-.808.635-1.447.923-1.92.293-.476.663-.793 1.11-.95-.355-.244-.603-.5-.745-.772a6.357 6.357 0 0 1-.392-1.04c-.222-.76-.39-1.26-.505-1.52-.11-.25-.26-.44-.45-.57-.18-.12-.49-.18-.912-.18H6V6l.386.008c.953 0 1.63.17 2.034.512.4.347.79 1.136 1.177 2.366.3.954.534 1.564.698 1.83.168.26.377.405.705.438V6.002"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-invert.png
new file mode 100644
index 00000000..ba2c9762
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-invert.svg
new file mode 100644
index 00000000..5cf18ffe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-f">
+ <path id="f" d="M16 8V6H8v12h3v-5h4v-2h-4V8z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-progressive.png
new file mode 100644
index 00000000..e2250172
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-progressive.svg
new file mode 100644
index 00000000..cce2c59b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-f">
+ <path id="f" d="M16 8V6H8v12h3v-5h4v-2h-4V8z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f.png
new file mode 100644
index 00000000..ad0d89b8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f.svg
new file mode 100644
index 00000000..89061f10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-f.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-f">
+ <path id="f" d="M16 8V6H8v12h3v-5h4v-2h-4V8z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-invert.png
new file mode 100644
index 00000000..2f1b7ac2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-invert.svg
new file mode 100644
index 00000000..2741c4f5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-g">
+ <path id="g" d="M12 14v-2h5v4.203c-.497.475-1.22.894-2.166 1.26A7.994 7.994 0 0 1 11.97 18c-1.23 0-2.303-.253-3.217-.76a4.908 4.908 0 0 1-2.062-2.185A7.008 7.008 0 0 1 6 11.96c0-1.208.26-2.282.77-3.222.518-.94 1.27-1.66 2.26-2.16.754-.386 1.693-.58 2.816-.58 1.46 0 2.6.304 3.418.91.825.603 1.354 1.436 1.59 2.502l-2.36.435a2.433 2.433 0 0 0-.94-1.346c-.454-.34-1.022-.5-1.707-.5-1.038 0-1.864.32-2.48.97-.61.65-.914 1.61-.914 2.89 0 1.375.31 2.41.93 3.1.62.687 1.434 1.03 2.44 1.03.497 0 .995-.095 1.49-.285.505-.196 1.334-.57 1.69-.846v-.868"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-progressive.png
new file mode 100644
index 00000000..8f3febed
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-progressive.svg
new file mode 100644
index 00000000..9e85e639
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-g">
+ <path id="g" d="M12 14v-2h5v4.203c-.497.475-1.22.894-2.166 1.26A7.994 7.994 0 0 1 11.97 18c-1.23 0-2.303-.253-3.217-.76a4.908 4.908 0 0 1-2.062-2.185A7.008 7.008 0 0 1 6 11.96c0-1.208.26-2.282.77-3.222.518-.94 1.27-1.66 2.26-2.16.754-.386 1.693-.58 2.816-.58 1.46 0 2.6.304 3.418.91.825.603 1.354 1.436 1.59 2.502l-2.36.435a2.433 2.433 0 0 0-.94-1.346c-.454-.34-1.022-.5-1.707-.5-1.038 0-1.864.32-2.48.97-.61.65-.914 1.61-.914 2.89 0 1.375.31 2.41.93 3.1.62.687 1.434 1.03 2.44 1.03.497 0 .995-.095 1.49-.285.505-.196 1.334-.57 1.69-.846v-.868"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g.png
new file mode 100644
index 00000000..55e766a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g.svg
new file mode 100644
index 00000000..3150d95c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-g.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-g">
+ <path id="g" d="M12 14v-2h5v4.203c-.497.475-1.22.894-2.166 1.26A7.994 7.994 0 0 1 11.97 18c-1.23 0-2.303-.253-3.217-.76a4.908 4.908 0 0 1-2.062-2.185A7.008 7.008 0 0 1 6 11.96c0-1.208.26-2.282.77-3.222.518-.94 1.27-1.66 2.26-2.16.754-.386 1.693-.58 2.816-.58 1.46 0 2.6.304 3.418.91.825.603 1.354 1.436 1.59 2.502l-2.36.435a2.433 2.433 0 0 0-.94-1.346c-.454-.34-1.022-.5-1.707-.5-1.038 0-1.864.32-2.48.97-.61.65-.914 1.61-.914 2.89 0 1.375.31 2.41.93 3.1.62.687 1.434 1.03 2.44 1.03.497 0 .995-.095 1.49-.285.505-.196 1.334-.57 1.69-.846v-.868"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-invert.png
new file mode 100644
index 00000000..ef2da34f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-invert.svg
new file mode 100644
index 00000000..c6eea499
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-geor-man">
+ <path id="geor-man" d="M13.832 14.06c0-1.714-.394-2.572-1.182-2.572-.868 0-1.302.78-1.302 2.338-.01 1.624.42 2.436 1.295 2.436.793 0 1.19-.734 1.19-2.2m2.167 0C16 16.686 14.884 18 12.65 18 10.218 18 9 16.614 9 13.84c0-2.737 1.217-4.105 3.65-4.105.842 0 1.183.63 1.183.63v-1.58c0-.788-.45-1.183-1.347-1.183-.572 0-.858.374-.858 1.123h-2.34C9.29 6.908 10.35 6 12.462 6 14.83 6 16.01 6.946 16 8.84"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-progressive.png
new file mode 100644
index 00000000..ad5c93fb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-progressive.svg
new file mode 100644
index 00000000..bca4a1a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-geor-man">
+ <path id="geor-man" d="M13.832 14.06c0-1.714-.394-2.572-1.182-2.572-.868 0-1.302.78-1.302 2.338-.01 1.624.42 2.436 1.295 2.436.793 0 1.19-.734 1.19-2.2m2.167 0C16 16.686 14.884 18 12.65 18 10.218 18 9 16.614 9 13.84c0-2.737 1.217-4.105 3.65-4.105.842 0 1.183.63 1.183.63v-1.58c0-.788-.45-1.183-1.347-1.183-.572 0-.858.374-.858 1.123h-2.34C9.29 6.908 10.35 6 12.462 6 14.83 6 16.01 6.946 16 8.84"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man.png
new file mode 100644
index 00000000..c0500747
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man.svg
new file mode 100644
index 00000000..deb95b70
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-geor-man.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-geor-man">
+ <path id="geor-man" d="M13.832 14.06c0-1.714-.394-2.572-1.182-2.572-.868 0-1.302.78-1.302 2.338-.01 1.624.42 2.436 1.295 2.436.793 0 1.19-.734 1.19-2.2m2.167 0C16 16.686 14.884 18 12.65 18 10.218 18 9 16.614 9 13.84c0-2.737 1.217-4.105 3.65-4.105.842 0 1.183.63 1.183.63v-1.58c0-.788-.45-1.183-1.347-1.183-.572 0-.858.374-.858 1.123h-2.34C9.29 6.908 10.35 6 12.462 6 14.83 6 16.01 6.946 16 8.84"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-invert.png
new file mode 100644
index 00000000..0736aab3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-invert.svg
new file mode 100644
index 00000000..a5516ed6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-l">
+ <path id="l" d="M8 18V6h3v10h5v2"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-progressive.png
new file mode 100644
index 00000000..7a1c4015
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-progressive.svg
new file mode 100644
index 00000000..44178b71
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-l">
+ <path id="l" d="M8 18V6h3v10h5v2"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l.png
new file mode 100644
index 00000000..11b67a1c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l.svg
new file mode 100644
index 00000000..76956234
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-l.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-l">
+ <path id="l" d="M8 18V6h3v10h5v2"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-invert.png
new file mode 100644
index 00000000..d57d0a58
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-invert.svg
new file mode 100644
index 00000000..528efe86
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-n">
+ <path id="n" d="M7 18V6h3l4 8V6h3v12h-3l-4-8v8H7"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-progressive.png
new file mode 100644
index 00000000..bb0299c8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-progressive.svg
new file mode 100644
index 00000000..d6869210
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-n">
+ <path id="n" d="M7 18V6h3l4 8V6h3v12h-3l-4-8v8H7"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n.png
new file mode 100644
index 00000000..708d421f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n.svg
new file mode 100644
index 00000000..62f66a2f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-n.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-n">
+ <path id="n" d="M7 18V6h3l4 8V6h3v12h-3l-4-8v8H7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-invert.png
new file mode 100644
index 00000000..ad990bec
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-invert.svg
new file mode 100644
index 00000000..c1549dc9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="bold-v">
+ <path id="v" d="M10.5 18L6 6h3l3 8 3-8h3l-4.5 12"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-progressive.png
new file mode 100644
index 00000000..d7c5eb02
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-progressive.svg
new file mode 100644
index 00000000..a94a50c8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="bold-v">
+ <path id="v" d="M10.5 18L6 6h3l3 8 3-8h3l-4.5 12"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v.png
new file mode 100644
index 00000000..a60786c9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v.svg
new file mode 100644
index 00000000..027db273
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bold-v.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="bold-v">
+ <path id="v" d="M10.5 18L6 6h3l3 8 3-8h3l-4.5 12"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-invert.png
new file mode 100644
index 00000000..a32272e6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-invert.svg
new file mode 100644
index 00000000..83265e46
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M15 7c-1.7 0-3 1.3-3 3 0-1.7-1.3-3-3-3H3v13h6c1.7 0 3 1 3 2 0-1 1.3-2 3-2h6V7h-6zm5 12h-5c-1.7 0-2 .4-2 .4v-8.9C13 9.1 14.1 8 15.5 8H20v11z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-progressive.png
new file mode 100644
index 00000000..9a63c72c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-progressive.svg
new file mode 100644
index 00000000..89fff500
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M15 7c-1.7 0-3 1.3-3 3 0-1.7-1.3-3-3-3H3v13h6c1.7 0 3 1 3 2 0-1 1.3-2 3-2h6V7h-6zm5 12h-5c-1.7 0-2 .4-2 .4v-8.9C13 9.1 14.1 8 15.5 8H20v11z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr.png
new file mode 100644
index 00000000..49ac06ae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr.svg
new file mode 100644
index 00000000..6a9a7488
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 7c-1.7 0-3 1.3-3 3 0-1.7-1.3-3-3-3H3v13h6c1.7 0 3 1 3 2 0-1 1.3-2 3-2h6V7h-6zm5 12h-5c-1.7 0-2 .4-2 .4v-8.9C13 9.1 14.1 8 15.5 8H20v11z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-invert.png
new file mode 100644
index 00000000..7258970d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-invert.svg
new file mode 100644
index 00000000..256ee414
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M9 7c1.7 0 3 1.3 3 3 0-1.7 1.3-3 3-3h6v13h-6c-1.7 0-3 1-3 2 0-1-1.3-2-3-2H3V7h6zM4 19h5c1.7 0 2 .4 2 .4v-8.9C11 9.1 9.9 8 8.5 8H4v11z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-progressive.png
new file mode 100644
index 00000000..6ff5355d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-progressive.svg
new file mode 100644
index 00000000..150fd95a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M9 7c1.7 0 3 1.3 3 3 0-1.7 1.3-3 3-3h6v13h-6c-1.7 0-3 1-3 2 0-1-1.3-2-3-2H3V7h6zM4 19h5c1.7 0 2 .4 2 .4v-8.9C11 9.1 9.9 8 8.5 8H4v11z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl.png
new file mode 100644
index 00000000..e0edc34b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl.svg
new file mode 100644
index 00000000..37973289
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/book-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 7c1.7 0 3 1.3 3 3 0-1.7 1.3-3 3-3h6v13h-6c-1.7 0-3 1-3 2 0-1-1.3-2-3-2H3V7h6zM4 19h5c1.7 0 2 .4 2 .4v-8.9C11 9.1 9.9 8 8.5 8H4v11z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright-invert.png
new file mode 100644
index 00000000..6194ed4a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright-invert.svg
new file mode 100644
index 00000000..8f41c1ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9-.3.3-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+ <path d="M12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright.png
new file mode 100644
index 00000000..788fc94b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright.svg
new file mode 100644
index 00000000..5a399fe2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/bright.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9-.3.3-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+ <path d="M12 8c1.7 0 3 1.3 3 3s-1.3 3-3 3-3-1.3-3-3 1.3-3 3-3m0-1c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-invert.png
new file mode 100644
index 00000000..027df2df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-invert.svg
new file mode 100644
index 00000000..3ee311a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M3 6v11c0 1.7 1.3 3 3 3h15V6H3zm2.5 1C6.3 7 7 7.7 7 8.5S6.3 10 5.5 10 4 9.3 4 8.5 4.7 7 5.5 7zM20 19H6c-1.1 0-2-.9-2-2v-6h16v8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-progressive.png
new file mode 100644
index 00000000..4ab9a1ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-progressive.svg
new file mode 100644
index 00000000..d3dd3fe1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M3 6v11c0 1.7 1.3 3 3 3h15V6H3zm2.5 1C6.3 7 7 7.7 7 8.5S6.3 10 5.5 10 4 9.3 4 8.5 4.7 7 5.5 7zM20 19H6c-1.1 0-2-.9-2-2v-6h16v8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr.png
new file mode 100644
index 00000000..ae059ad0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr.svg
new file mode 100644
index 00000000..e7be7e56
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 6v11c0 1.7 1.3 3 3 3h15V6H3zm2.5 1C6.3 7 7 7.7 7 8.5S6.3 10 5.5 10 4 9.3 4 8.5 4.7 7 5.5 7zM20 19H6c-1.1 0-2-.9-2-2v-6h16v8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-invert.png
new file mode 100644
index 00000000..51937b73
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-invert.svg
new file mode 100644
index 00000000..98238cfb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M21 6v11c0 1.7-1.3 3-3 3H3V6h18zm-2.5 1c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5S20 9.3 20 8.5 19.3 7 18.5 7zM4 19h14c1.1 0 2-.9 2-2v-6H4v8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-progressive.png
new file mode 100644
index 00000000..1f33d142
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-progressive.svg
new file mode 100644
index 00000000..e2ad0abf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M21 6v11c0 1.7-1.3 3-3 3H3V6h18zm-2.5 1c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5S20 9.3 20 8.5 19.3 7 18.5 7zM4 19h14c1.1 0 2-.9 2-2v-6H4v8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl.png
new file mode 100644
index 00000000..939a858a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl.svg
new file mode 100644
index 00000000..38807b5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/browser-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 6v11c0 1.7-1.3 3-3 3H3V6h18zm-2.5 1c-.8 0-1.5.7-1.5 1.5s.7 1.5 1.5 1.5S20 9.3 20 8.5 19.3 7 18.5 7zM4 19h14c1.1 0 2-.9 2-2v-6H4v8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-invert.png
new file mode 100644
index 00000000..14638742
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-invert.svg
new file mode 100644
index 00000000..f933a1e2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M4 5v10c0 1.7 1.3 3 3 3h14V8c0-1.7-1.3-3-3-3H4zm2 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zM5 9h3v2H5V9zm4 0h3v2H9V9zm4 0h3v2h-3V9zm4 0h3v2h-3V9zM5 12h3v2H5v-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2zM5 15h3v2H7c-1.195 0-2-.805-2-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-progressive.png
new file mode 100644
index 00000000..5f6143b4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-progressive.svg
new file mode 100644
index 00000000..97d6a582
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M4 5v10c0 1.7 1.3 3 3 3h14V8c0-1.7-1.3-3-3-3H4zm2 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zM5 9h3v2H5V9zm4 0h3v2H9V9zm4 0h3v2h-3V9zm4 0h3v2h-3V9zM5 12h3v2H5v-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2zM5 15h3v2H7c-1.195 0-2-.805-2-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr.png
new file mode 100644
index 00000000..0ab46dd6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr.svg
new file mode 100644
index 00000000..b0bc0e51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 5v10c0 1.7 1.3 3 3 3h14V8c0-1.7-1.3-3-3-3H4zm2 1a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zm4 0a1 1 0 1 1 0 2 1 1 0 0 1 0-2zM5 9h3v2H5V9zm4 0h3v2H9V9zm4 0h3v2h-3V9zm4 0h3v2h-3V9zM5 12h3v2H5v-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2zM5 15h3v2H7c-1.195 0-2-.805-2-2zm4 0h3v2H9v-2zm4 0h3v2h-3v-2zm4 0h3v2h-3v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-invert.png
new file mode 100644
index 00000000..806c55de
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-invert.svg
new file mode 100644
index 00000000..dccd818a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M21 5v10c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3h14zm-2 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zM7 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm13 3h-3v2h3V9zm-4 0h-3v2h3V9zm-4 0H9v2h3V9zM8 9H5v2h3V9zm12 3h-3v2h3v-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2zm12 3h-3v2h1c1.195 0 2-.805 2-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-progressive.png
new file mode 100644
index 00000000..1864f52a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-progressive.svg
new file mode 100644
index 00000000..3757322a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M21 5v10c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3h14zm-2 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zM7 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm13 3h-3v2h3V9zm-4 0h-3v2h3V9zm-4 0H9v2h3V9zM8 9H5v2h3V9zm12 3h-3v2h3v-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2zm12 3h-3v2h1c1.195 0 2-.805 2-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl.png
new file mode 100644
index 00000000..0236393b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl.svg
new file mode 100644
index 00000000..d8ff5a95
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/calendar-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 5v10c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3h14zm-2 1a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm-4 0a1 1 0 1 0 0 2 1 1 0 0 0 0-2zM7 6a1 1 0 1 0 0 2 1 1 0 0 0 0-2zm13 3h-3v2h3V9zm-4 0h-3v2h3V9zm-4 0H9v2h3V9zM8 9H5v2h3V9zm12 3h-3v2h3v-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2zm12 3h-3v2h1c1.195 0 2-.805 2-2zm-4 0h-3v2h3v-2zm-4 0H9v2h3v-2zm-4 0H5v2h3v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-destructive.png
new file mode 100644
index 00000000..f574a392
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-destructive.svg
new file mode 100644
index 00000000..c0f8dc09
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-destructive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#d33">
+ <g id="cancel">
+ <path id="circle-with-strike" d="M12 5.022a6.98 6.98 0 0 0-.003 13.956 6.98 6.98 0 0 0-.002-13.956zM6.885 12c0-1.092.572-3.25.93-2.93l7.113 7.114c.487.525-1.838.93-2.93.93A5.113 5.113 0 0 1 6.884 12zm9.298 2.93L9.07 7.815c-.445-.483 1.837-.93 2.93-.93a5.112 5.112 0 0 1 5.114 5.113c0 1.092-.364 3.542-.93 2.93z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-invert.png
new file mode 100644
index 00000000..b7529a24
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-invert.svg
new file mode 100644
index 00000000..893486d3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="cancel">
+ <path id="circle-with-strike" d="M12 5.022a6.98 6.98 0 0 0-.003 13.956 6.98 6.98 0 0 0-.002-13.956zM6.885 12c0-1.092.572-3.25.93-2.93l7.113 7.114c.487.525-1.838.93-2.93.93A5.113 5.113 0 0 1 6.884 12zm9.298 2.93L9.07 7.815c-.445-.483 1.837-.93 2.93-.93a5.112 5.112 0 0 1 5.114 5.113c0 1.092-.364 3.542-.93 2.93z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-progressive.png
new file mode 100644
index 00000000..04b8a081
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-progressive.svg
new file mode 100644
index 00000000..18698eb7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="cancel">
+ <path id="circle-with-strike" d="M12 5.022a6.98 6.98 0 0 0-.003 13.956 6.98 6.98 0 0 0-.002-13.956zM6.885 12c0-1.092.572-3.25.93-2.93l7.113 7.114c.487.525-1.838.93-2.93.93A5.113 5.113 0 0 1 6.884 12zm9.298 2.93L9.07 7.815c-.445-.483 1.837-.93 2.93-.93a5.112 5.112 0 0 1 5.114 5.113c0 1.092-.364 3.542-.93 2.93z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel.png
new file mode 100644
index 00000000..f9354e3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel.svg
new file mode 100644
index 00000000..04ff5c32
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/cancel.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="cancel">
+ <path id="circle-with-strike" d="M12 5.022a6.98 6.98 0 0 0-.003 13.956 6.98 6.98 0 0 0-.002-13.956zM6.885 12c0-1.092.572-3.25.93-2.93l7.113 7.114c.487.525-1.838.93-2.93.93A5.113 5.113 0 0 1 6.884 12zm9.298 2.93L9.07 7.815c-.445-.483 1.837-.93 2.93-.93a5.112 5.112 0 0 1 5.114 5.113c0 1.092-.364 3.542-.93 2.93z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-invert.png
new file mode 100644
index 00000000..6fe12607
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-invert.svg
new file mode 100644
index 00000000..e5590a34
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="case-sensitive">
+ <path id="upper-case" d="M7.53 7L4 17h2.063l.72-2.406h3.624l.72 2.406h2.062L9.65 7h-2.12zm1.064 1.53L9.938 13H7.25l1.344-4.47z"/>
+ <path id="lower-case" d="M18.55 17l-.184-1.035h-.055c-.35.44-.71.747-1.08.92-.37.167-.85.25-1.44.25-.564 0-.955-.208-1.377-.625-.42-.418-.627-1.012-.627-1.784 0-.808.283-1.403.846-1.784.568-.386 1.193-.607 2.208-.64l1.322-.04v-.335c0-.772-.396-1.158-1.187-1.158-.61 0-1.325.18-2.147.55l-.688-1.4c.877-.46 1.85-.69 2.916-.69 1.024 0 1.59.22 2.134.662.545.445.818 1.12.818 2.03V17h-1.45m-.394-3.527l-.802.027c-.604.018-1.054.127-1.35.327-.294.2-.442.504-.442.912 0 .58.336.87 1.008.87.48 0 .865-.137 1.152-.414.29-.277.436-.645.436-1.103v-.627"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-progressive.png
new file mode 100644
index 00000000..cc6f6659
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-progressive.svg
new file mode 100644
index 00000000..ff6e102e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="case-sensitive">
+ <path id="upper-case" d="M7.53 7L4 17h2.063l.72-2.406h3.624l.72 2.406h2.062L9.65 7h-2.12zm1.064 1.53L9.938 13H7.25l1.344-4.47z"/>
+ <path id="lower-case" d="M18.55 17l-.184-1.035h-.055c-.35.44-.71.747-1.08.92-.37.167-.85.25-1.44.25-.564 0-.955-.208-1.377-.625-.42-.418-.627-1.012-.627-1.784 0-.808.283-1.403.846-1.784.568-.386 1.193-.607 2.208-.64l1.322-.04v-.335c0-.772-.396-1.158-1.187-1.158-.61 0-1.325.18-2.147.55l-.688-1.4c.877-.46 1.85-.69 2.916-.69 1.024 0 1.59.22 2.134.662.545.445.818 1.12.818 2.03V17h-1.45m-.394-3.527l-.802.027c-.604.018-1.054.127-1.35.327-.294.2-.442.504-.442.912 0 .58.336.87 1.008.87.48 0 .865-.137 1.152-.414.29-.277.436-.645.436-1.103v-.627"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive.png
new file mode 100644
index 00000000..426c5de5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive.svg
new file mode 100644
index 00000000..749e38ff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/case-sensitive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="case-sensitive">
+ <path id="upper-case" d="M7.53 7L4 17h2.063l.72-2.406h3.624l.72 2.406h2.062L9.65 7h-2.12zm1.064 1.53L9.938 13H7.25l1.344-4.47z"/>
+ <path id="lower-case" d="M18.55 17l-.184-1.035h-.055c-.35.44-.71.747-1.08.92-.37.167-.85.25-1.44.25-.564 0-.955-.208-1.377-.625-.42-.418-.627-1.012-.627-1.784 0-.808.283-1.403.846-1.784.568-.386 1.193-.607 2.208-.64l1.322-.04v-.335c0-.772-.396-1.158-1.187-1.158-.61 0-1.325.18-2.147.55l-.688-1.4c.877-.46 1.85-.69 2.916-.69 1.024 0 1.59.22 2.134.662.545.445.818 1.12.818 2.03V17h-1.45m-.394-3.527l-.802.027c-.604.018-1.054.127-1.35.327-.294.2-.442.504-.442.912 0 .58.336.87 1.008.87.48 0 .865-.137 1.152-.414.29-.277.436-.645.436-1.103v-.627"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-constructive.png
new file mode 100644
index 00000000..1dc3ae45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-constructive.svg
new file mode 100644
index 00000000..4cea8a3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-constructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-destructive.png
new file mode 100644
index 00000000..305f41d5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-destructive.svg
new file mode 100644
index 00000000..3609a7b4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#d33">
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-invert.png
new file mode 100644
index 00000000..708bb396
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-invert.svg
new file mode 100644
index 00000000..7f3299a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-progressive.png
new file mode 100644
index 00000000..1dc3ae45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-progressive.svg
new file mode 100644
index 00000000..4cea8a3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check.png
new file mode 100644
index 00000000..65ab0e9c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check.svg
new file mode 100644
index 00000000..2fa9dfbe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/check.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-invert.png
new file mode 100644
index 00000000..442399aa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-invert.svg
new file mode 100644
index 00000000..9e2795e2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M7 12h9v-1H7v1zm0 2h9v-1H7v1zm0 2h9v-1H7v1zm4-9H7v1h4V7zm0 2H7v1h4V9zm0-4H7v1h4V5zm5-2h2v16H8c-1.7 0-3-1.3-3-3V3h8v7l1.5-2 1.5 2V3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-progressive.png
new file mode 100644
index 00000000..e27df808
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-progressive.svg
new file mode 100644
index 00000000..677ee810
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M7 12h9v-1H7v1zm0 2h9v-1H7v1zm0 2h9v-1H7v1zm4-9H7v1h4V7zm0 2H7v1h4V9zm0-4H7v1h4V5zm5-2h2v16H8c-1.7 0-3-1.3-3-3V3h8v7l1.5-2 1.5 2V3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr.png
new file mode 100644
index 00000000..ca0bdc4e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr.svg
new file mode 100644
index 00000000..6a55c053
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 12h9v-1H7v1zm0 2h9v-1H7v1zm0 2h9v-1H7v1zm4-9H7v1h4V7zm0 2H7v1h4V9zm0-4H7v1h4V5zm5-2h2v16H8c-1.7 0-3-1.3-3-3V3h8v7l1.5-2 1.5 2V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-invert.png
new file mode 100644
index 00000000..01596504
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-invert.svg
new file mode 100644
index 00000000..131a2711
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M16 12H7v-1h9v1zm0 2H7v-1h9v1zm0 2H7v-1h9v1zm-4-9h4v1h-4V7zm0 2h4v1h-4V9zm0-4h4v1h-4V5zM7 3H5v16h10c1.7 0 3-1.3 3-3V3h-8v7L8.5 8 7 10V3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-progressive.png
new file mode 100644
index 00000000..7fb92a73
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-progressive.svg
new file mode 100644
index 00000000..b19d6400
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M16 12H7v-1h9v1zm0 2H7v-1h9v1zm0 2H7v-1h9v1zm-4-9h4v1h-4V7zm0 2h4v1h-4V9zm0-4h4v1h-4V5zM7 3H5v16h10c1.7 0 3-1.3 3-3V3h-8v7L8.5 8 7 10V3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl.png
new file mode 100644
index 00000000..3eae6014
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl.svg
new file mode 100644
index 00000000..0c0c411a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/citeArticle-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 12H7v-1h9v1zm0 2H7v-1h9v1zm0 2H7v-1h9v1zm-4-9h4v1h-4V7zm0 2h4v1h-4V9zm0-4h4v1h-4V5zM7 3H5v16h10c1.7 0 3-1.3 3-3V3h-8v7L8.5 8 7 10V3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-invert.png
new file mode 100644
index 00000000..ec90ed93
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-invert.svg
new file mode 100644
index 00000000..b43d7947
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="clear">
+ <path id="circle-with-cross" d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 11l-1 1-3-3-3 3-1-1 3-3-3-3 1-1 3 3 3-3 1 1-3 3 3 3z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-progressive.png
new file mode 100644
index 00000000..fb0d269d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-progressive.svg
new file mode 100644
index 00000000..2fa1f2f9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="clear">
+ <path id="circle-with-cross" d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 11l-1 1-3-3-3 3-1-1 3-3-3-3 1-1 3 3 3-3 1 1-3 3 3 3z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear.png
new file mode 100644
index 00000000..973dc036
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear.svg
new file mode 100644
index 00000000..8689e770
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clear.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="clear">
+ <path id="circle-with-cross" d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm4 11l-1 1-3-3-3 3-1-1 3-3-3-3 1-1 3 3 3-3 1 1-3 3 3 3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-invert.png
new file mode 100644
index 00000000..eab89157
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-invert.svg
new file mode 100644
index 00000000..14b03f6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M17.5 4.5v13.2L12 13.5l-5.5 4.2V4.5zM5 21l7-6 7 6V3H5z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-progressive.png
new file mode 100644
index 00000000..633956db
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-progressive.svg
new file mode 100644
index 00000000..3744540c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M17.5 4.5v13.2L12 13.5l-5.5 4.2V4.5zM5 21l7-6 7 6V3H5z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip.png
new file mode 100644
index 00000000..ac254835
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip.svg
new file mode 100644
index 00000000..86d1dbfb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clip.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.5 4.5v13.2L12 13.5l-5.5 4.2V4.5zM5 21l7-6 7 6V3H5z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-invert.png
new file mode 100644
index 00000000..2f944d79
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-invert.svg
new file mode 100644
index 00000000..83762889
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3 12l-4-3V8h2v5l1.7 1.2c1.3.9 1 1.9.3 2.8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-progressive.png
new file mode 100644
index 00000000..f2683e53
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-progressive.svg
new file mode 100644
index 00000000..4c8accd6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3 12l-4-3V8h2v5l1.7 1.2c1.3.9 1 1.9.3 2.8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock.png
new file mode 100644
index 00000000..98b504e4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock.svg
new file mode 100644
index 00000000..85b0628a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/clock.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3 12l-4-3V8h2v5l1.7 1.2c1.3.9 1 1.9.3 2.8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-invert.png
new file mode 100644
index 00000000..92af7b6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-invert.svg
new file mode 100644
index 00000000..8027fffd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M18 7.6l-1.4-1.4-4.6 4.6-4.6-4.6L6 7.6l4.6 4.6L6 16.8l1.4 1.4 4.6-4.6 4.6 4.6 1.4-1.4-4.6-4.6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-progressive.png
new file mode 100644
index 00000000..06fcd5d4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-progressive.svg
new file mode 100644
index 00000000..37c960e4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M18 7.6l-1.4-1.4-4.6 4.6-4.6-4.6L6 7.6l4.6 4.6L6 16.8l1.4 1.4 4.6-4.6 4.6 4.6 1.4-1.4-4.6-4.6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close.png
new file mode 100644
index 00000000..cdb037ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close.svg
new file mode 100644
index 00000000..88ffb56d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/close.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18 7.6l-1.4-1.4-4.6 4.6-4.6-4.6L6 7.6l4.6 4.6L6 16.8l1.4 1.4 4.6-4.6 4.6 4.6 1.4-1.4-4.6-4.6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-invert.png
new file mode 100644
index 00000000..1804fb89
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-invert.svg
new file mode 100644
index 00000000..e9179bf5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="code">
+ <path id="left-bracket" d="M4 12v-1h1c1 0 1 0 1-1V7.614c0-.514.024-.896.073-1.142.054-.252.14-.463.257-.633.204-.28.473-.48.808-.59.335-.11.872-.25 1.835-.25H10v1h-.752c-.457 0-.77.19-.936.406-.167.216-.312.446-.312 1.07v1.856c0 .73-.04 1.18-.244 1.493-.2.307-.562.53-1.09.667.535.155.9.385 1.096.688.2.31.238.76.238 1.49v1.86c0 .62.145.85.312 1.06.166.22.48.41.936.41H10v1H8.973c-.963 0-1.5-.133-1.835-.248a1.578 1.578 0 0 1-.808-.59 1.68 1.68 0 0 1-.257-.626C6.023 16.283 6 15.9 6 15.386V13c0-1 0-1-1-1H4z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" width="24" height="24" xlink:href="#left-bracket"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-progressive.png
new file mode 100644
index 00000000..21656c4a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-progressive.svg
new file mode 100644
index 00000000..ce0e4921
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="code">
+ <path id="left-bracket" d="M4 12v-1h1c1 0 1 0 1-1V7.614c0-.514.024-.896.073-1.142.054-.252.14-.463.257-.633.204-.28.473-.48.808-.59.335-.11.872-.25 1.835-.25H10v1h-.752c-.457 0-.77.19-.936.406-.167.216-.312.446-.312 1.07v1.856c0 .73-.04 1.18-.244 1.493-.2.307-.562.53-1.09.667.535.155.9.385 1.096.688.2.31.238.76.238 1.49v1.86c0 .62.145.85.312 1.06.166.22.48.41.936.41H10v1H8.973c-.963 0-1.5-.133-1.835-.248a1.578 1.578 0 0 1-.808-.59 1.68 1.68 0 0 1-.257-.626C6.023 16.283 6 15.9 6 15.386V13c0-1 0-1-1-1H4z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" width="24" height="24" xlink:href="#left-bracket"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code.png
new file mode 100644
index 00000000..ba89e4ec
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code.svg
new file mode 100644
index 00000000..a00d1582
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/code.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="code">
+ <path id="left-bracket" d="M4 12v-1h1c1 0 1 0 1-1V7.614c0-.514.024-.896.073-1.142.054-.252.14-.463.257-.633.204-.28.473-.48.808-.59.335-.11.872-.25 1.835-.25H10v1h-.752c-.457 0-.77.19-.936.406-.167.216-.312.446-.312 1.07v1.856c0 .73-.04 1.18-.244 1.493-.2.307-.562.53-1.09.667.535.155.9.385 1.096.688.2.31.238.76.238 1.49v1.86c0 .62.145.85.312 1.06.166.22.48.41.936.41H10v1H8.973c-.963 0-1.5-.133-1.835-.248a1.578 1.578 0 0 1-.808-.59 1.68 1.68 0 0 1-.257-.626C6.023 16.283 6 15.9 6 15.386V13c0-1 0-1-1-1H4z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" width="24" height="24" xlink:href="#left-bracket"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-invert.png
new file mode 100644
index 00000000..951a8407
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-invert.svg
new file mode 100644
index 00000000..7b7305ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="collapse">
+ <path id="arrow" d="M6.697 15.714L12 10.412l5.303 5.302 1.414-1.414L12 7.583 5.283 14.3z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-progressive.png
new file mode 100644
index 00000000..8b4d5c78
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-progressive.svg
new file mode 100644
index 00000000..29157ae8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="collapse">
+ <path id="arrow" d="M6.697 15.714L12 10.412l5.303 5.302 1.414-1.414L12 7.583 5.283 14.3z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse.png
new file mode 100644
index 00000000..1d8c6db1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse.svg
new file mode 100644
index 00000000..645bfda5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/collapse.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="collapse">
+ <path id="arrow" d="M6.697 15.714L12 10.412l5.303 5.302 1.414-1.414L12 7.583 5.283 14.3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-invert.png
new file mode 100644
index 00000000..1de3b9db
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-invert.svg
new file mode 100644
index 00000000..e6f6bb10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="comment">
+ <path id="speech-bubble" d="M15 6H9a3 3 0 0 0-3 3v4a3 3 0 0 0 3 3v3l3-3h3a3 3 0 0 0 3-3V9a3 3 0 0 0-3-3z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-progressive.png
new file mode 100644
index 00000000..6bb0a730
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-progressive.svg
new file mode 100644
index 00000000..63bdad98
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="comment">
+ <path id="speech-bubble" d="M15 6H9a3 3 0 0 0-3 3v4a3 3 0 0 0 3 3v3l3-3h3a3 3 0 0 0 3-3V9a3 3 0 0 0-3-3z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment.png
new file mode 100644
index 00000000..dcaa8814
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment.svg
new file mode 100644
index 00000000..861611ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/comment.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="comment">
+ <path id="speech-bubble" d="M15 6H9a3 3 0 0 0-3 3v4a3 3 0 0 0 3 3v3l3-3h3a3 3 0 0 0 3-3V9a3 3 0 0 0-3-3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-invert.png
new file mode 100644
index 00000000..7bb19e31
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-invert.svg
new file mode 100644
index 00000000..b19dd0dc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="diacritic">
+ <path id="letter-a" d="M13.55 17l-.184-1.035h-.055c-.35.44-.71.747-1.08.92-.37.167-.85.25-1.44.25-.563 0-.954-.208-1.376-.625-.42-.418-.627-1.012-.627-1.784 0-.808.283-1.403.846-1.784.568-.386 1.193-.607 2.208-.64l1.323-.04v-.335c0-.772-.396-1.158-1.187-1.158-.61 0-1.325.18-2.147.55l-.69-1.4c.878-.46 1.85-.69 2.917-.69 1.024 0 1.59.22 2.134.66.546.446.82 1.12.82 2.03V17h-1.45m-.395-3.527l-.802.027c-.604.018-1.054.127-1.35.327-.294.2-.442.504-.442.912 0 .58.337.87 1.01.87.48 0 .864-.138 1.15-.415.29-.277.437-.645.437-1.103v-.627"/>
+ <path id="tilde" d="M12.012 7.527l-.466-.306a.832.832 0 0 1-.085-.048c-.264-.17-.467-.256-.608-.256a.518.518 0 0 0-.466.256c-.107.17-.16.418-.16.743v.066H9.047c0-.748.144-1.326.432-1.733.294-.407.703-.61 1.228-.61.203 0 .406.037.61.114.208.073.43.19.66.357l.517.355c.124.082.237.146.338.19a.77.77 0 0 0 .288.066c.204 0 .362-.088.475-.265.113-.176.17-.42.17-.735v-.066h1.177c0 .75-.147 1.327-.44 1.735-.29.407-.695.61-1.22.61-.203 0-.4-.032-.593-.098a3.107 3.107 0 0 1-.678-.373z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-progressive.png
new file mode 100644
index 00000000..eb76fd07
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-progressive.svg
new file mode 100644
index 00000000..fed1164a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="diacritic">
+ <path id="letter-a" d="M13.55 17l-.184-1.035h-.055c-.35.44-.71.747-1.08.92-.37.167-.85.25-1.44.25-.563 0-.954-.208-1.376-.625-.42-.418-.627-1.012-.627-1.784 0-.808.283-1.403.846-1.784.568-.386 1.193-.607 2.208-.64l1.323-.04v-.335c0-.772-.396-1.158-1.187-1.158-.61 0-1.325.18-2.147.55l-.69-1.4c.878-.46 1.85-.69 2.917-.69 1.024 0 1.59.22 2.134.66.546.446.82 1.12.82 2.03V17h-1.45m-.395-3.527l-.802.027c-.604.018-1.054.127-1.35.327-.294.2-.442.504-.442.912 0 .58.337.87 1.01.87.48 0 .864-.138 1.15-.415.29-.277.437-.645.437-1.103v-.627"/>
+ <path id="tilde" d="M12.012 7.527l-.466-.306a.832.832 0 0 1-.085-.048c-.264-.17-.467-.256-.608-.256a.518.518 0 0 0-.466.256c-.107.17-.16.418-.16.743v.066H9.047c0-.748.144-1.326.432-1.733.294-.407.703-.61 1.228-.61.203 0 .406.037.61.114.208.073.43.19.66.357l.517.355c.124.082.237.146.338.19a.77.77 0 0 0 .288.066c.204 0 .362-.088.475-.265.113-.176.17-.42.17-.735v-.066h1.177c0 .75-.147 1.327-.44 1.735-.29.407-.695.61-1.22.61-.203 0-.4-.032-.593-.098a3.107 3.107 0 0 1-.678-.373z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic.png
new file mode 100644
index 00000000..2359b196
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic.svg
new file mode 100644
index 00000000..45651013
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/diacritic.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="diacritic">
+ <path id="letter-a" d="M13.55 17l-.184-1.035h-.055c-.35.44-.71.747-1.08.92-.37.167-.85.25-1.44.25-.563 0-.954-.208-1.376-.625-.42-.418-.627-1.012-.627-1.784 0-.808.283-1.403.846-1.784.568-.386 1.193-.607 2.208-.64l1.323-.04v-.335c0-.772-.396-1.158-1.187-1.158-.61 0-1.325.18-2.147.55l-.69-1.4c.878-.46 1.85-.69 2.917-.69 1.024 0 1.59.22 2.134.66.546.446.82 1.12.82 2.03V17h-1.45m-.395-3.527l-.802.027c-.604.018-1.054.127-1.35.327-.294.2-.442.504-.442.912 0 .58.337.87 1.01.87.48 0 .864-.138 1.15-.415.29-.277.437-.645.437-1.103v-.627"/>
+ <path id="tilde" d="M12.012 7.527l-.466-.306a.832.832 0 0 1-.085-.048c-.264-.17-.467-.256-.608-.256a.518.518 0 0 0-.466.256c-.107.17-.16.418-.16.743v.066H9.047c0-.748.144-1.326.432-1.733.294-.407.703-.61 1.228-.61.203 0 .406.037.61.114.208.073.43.19.66.357l.517.355c.124.082.237.146.338.19a.77.77 0 0 0 .288.066c.204 0 .362-.088.475-.265.113-.176.17-.42.17-.735v-.066h1.177c0 .75-.147 1.327-.44 1.735-.29.407-.695.61-1.22.61-.203 0-.4-.032-.593-.098a3.107 3.107 0 0 1-.678-.373z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-invert.png
new file mode 100644
index 00000000..ea8beb98
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-invert.svg
new file mode 100644
index 00000000..a9ef3214
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M16 5H4v12c0 1.6 1.3 3 3 3h12V8c0-1.7-1.4-3-3-3zM7.5 17c-.8 0-1.5-.7-1.5-1.5S6.7 14 7.5 14s1.5.7 1.5 1.5S8.3 17 7.5 17zm0-6C6.7 11 6 10.3 6 9.5S6.7 8 7.5 8 9 8.7 9 9.5 8.3 11 7.5 11zm4 3c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm4 3c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm0-6c-.8 0-1.5-.7-1.5-1.5S14.7 8 15.5 8s1.5.7 1.5 1.5-.7 1.5-1.5 1.5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-progressive.png
new file mode 100644
index 00000000..8e7e83a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-progressive.svg
new file mode 100644
index 00000000..a63bf037
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M16 5H4v12c0 1.6 1.3 3 3 3h12V8c0-1.7-1.4-3-3-3zM7.5 17c-.8 0-1.5-.7-1.5-1.5S6.7 14 7.5 14s1.5.7 1.5 1.5S8.3 17 7.5 17zm0-6C6.7 11 6 10.3 6 9.5S6.7 8 7.5 8 9 8.7 9 9.5 8.3 11 7.5 11zm4 3c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm4 3c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm0-6c-.8 0-1.5-.7-1.5-1.5S14.7 8 15.5 8s1.5.7 1.5 1.5-.7 1.5-1.5 1.5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr.png
new file mode 100644
index 00000000..79f4497b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr.svg
new file mode 100644
index 00000000..2571d4dc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 5H4v12c0 1.6 1.3 3 3 3h12V8c0-1.7-1.4-3-3-3zM7.5 17c-.8 0-1.5-.7-1.5-1.5S6.7 14 7.5 14s1.5.7 1.5 1.5S8.3 17 7.5 17zm0-6C6.7 11 6 10.3 6 9.5S6.7 8 7.5 8 9 8.7 9 9.5 8.3 11 7.5 11zm4 3c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm4 3c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5zm0-6c-.8 0-1.5-.7-1.5-1.5S14.7 8 15.5 8s1.5.7 1.5 1.5-.7 1.5-1.5 1.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-invert.png
new file mode 100644
index 00000000..32bbeef7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-invert.svg
new file mode 100644
index 00000000..344e2fb2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M7 5h12v12c0 1.6-1.3 3-3 3H4V8c0-1.7 1.4-3 3-3zm8.5 12c.8 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5-1.5.7-1.5 1.5.7 1.5 1.5 1.5zm0-6c.8 0 1.5-.7 1.5-1.5S16.3 8 15.5 8 14 8.7 14 9.5s.7 1.5 1.5 1.5zm-4 3c.8 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5-1.5.7-1.5 1.5.7 1.5 1.5 1.5zm-4 3c.8 0 1.5-.7 1.5-1.5S8.3 14 7.5 14 6 14.7 6 15.5 6.7 17 7.5 17zm0-6c.8 0 1.5-.7 1.5-1.5S8.3 8 7.5 8 6 8.7 6 9.5 6.7 11 7.5 11z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-progressive.png
new file mode 100644
index 00000000..5edaf861
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-progressive.svg
new file mode 100644
index 00000000..fd4f13b2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M7 5h12v12c0 1.6-1.3 3-3 3H4V8c0-1.7 1.4-3 3-3zm8.5 12c.8 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5-1.5.7-1.5 1.5.7 1.5 1.5 1.5zm0-6c.8 0 1.5-.7 1.5-1.5S16.3 8 15.5 8 14 8.7 14 9.5s.7 1.5 1.5 1.5zm-4 3c.8 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5-1.5.7-1.5 1.5.7 1.5 1.5 1.5zm-4 3c.8 0 1.5-.7 1.5-1.5S8.3 14 7.5 14 6 14.7 6 15.5 6.7 17 7.5 17zm0-6c.8 0 1.5-.7 1.5-1.5S8.3 8 7.5 8 6 8.7 6 9.5 6.7 11 7.5 11z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl.png
new file mode 100644
index 00000000..c01002f1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl.svg
new file mode 100644
index 00000000..9be97f6b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/die-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 5h12v12c0 1.6-1.3 3-3 3H4V8c0-1.7 1.4-3 3-3zm8.5 12c.8 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5-1.5.7-1.5 1.5.7 1.5 1.5 1.5zm0-6c.8 0 1.5-.7 1.5-1.5S16.3 8 15.5 8 14 8.7 14 9.5s.7 1.5 1.5 1.5zm-4 3c.8 0 1.5-.7 1.5-1.5s-.7-1.5-1.5-1.5-1.5.7-1.5 1.5.7 1.5 1.5 1.5zm-4 3c.8 0 1.5-.7 1.5-1.5S8.3 14 7.5 14 6 14.7 6 15.5 6.7 17 7.5 17zm0-6c.8 0 1.5-.7 1.5-1.5S8.3 8 7.5 8 6 8.7 6 9.5 6.7 11 7.5 11z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-invert.png
new file mode 100644
index 00000000..b186eb0b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-invert.svg
new file mode 100644
index 00000000..9c64f50c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 18l8-10H4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-progressive.png
new file mode 100644
index 00000000..ebe6abfa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-progressive.svg
new file mode 100644
index 00000000..aaa6ec95
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 18l8-10H4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle.png
new file mode 100644
index 00000000..7df0592f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle.svg
new file mode 100644
index 00000000..e1fb989c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/downTriangle.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 18l8-10H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-invert.png
new file mode 100644
index 00000000..ce0f041c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-invert.svg
new file mode 100644
index 00000000..312b19ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M16 11h-3V4c-1.7 0-3 1.3-3 3v4H7l4.5 5 4.5-5zm1 2v5H7c-.6 0-1-.4-1-1v-4H4v4c0 1.9 1.3 3 3 3h12v-7h-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-progressive.png
new file mode 100644
index 00000000..28812d24
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-progressive.svg
new file mode 100644
index 00000000..8d694239
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M16 11h-3V4c-1.7 0-3 1.3-3 3v4H7l4.5 5 4.5-5zm1 2v5H7c-.6 0-1-.4-1-1v-4H4v4c0 1.9 1.3 3 3 3h12v-7h-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr.png
new file mode 100644
index 00000000..4d67c8da
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr.svg
new file mode 100644
index 00000000..dfb2bb6b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 11h-3V4c-1.7 0-3 1.3-3 3v4H7l4.5 5 4.5-5zm1 2v5H7c-.6 0-1-.4-1-1v-4H4v4c0 1.9 1.3 3 3 3h12v-7h-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-invert.png
new file mode 100644
index 00000000..09286f75
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-invert.svg
new file mode 100644
index 00000000..141ca5cf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M7 11h3V4c1.7 0 3 1.3 3 3v4h3l-4.5 5L7 11zm-1 2v5h10c.6 0 1-.4 1-1v-4h2v4c0 1.9-1.3 3-3 3H4v-7h2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-progressive.png
new file mode 100644
index 00000000..6ba5e29f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-progressive.svg
new file mode 100644
index 00000000..4767dc10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M7 11h3V4c1.7 0 3 1.3 3 3v4h3l-4.5 5L7 11zm-1 2v5h10c.6 0 1-.4 1-1v-4h2v4c0 1.9-1.3 3-3 3H4v-7h2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl.png
new file mode 100644
index 00000000..660d7d0e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl.svg
new file mode 100644
index 00000000..276b1536
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/download-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 11h3V4c1.7 0 3 1.3 3 3v4h3l-4.5 5L7 11zm-1 2v5h10c.6 0 1-.4 1-1v-4h2v4c0 1.9-1.3 3-3 3H4v-7h2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-invert.png
new file mode 100644
index 00000000..4dd5fd8b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-invert.svg
new file mode 100644
index 00000000..68085f97
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M20 19H4v-2h16v2zM20 15H4v-2h16v2zM20 11H4V9h16v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-progressive.png
new file mode 100644
index 00000000..6d0aa125
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-progressive.svg
new file mode 100644
index 00000000..7bb2d16f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M20 19H4v-2h16v2zM20 15H4v-2h16v2zM20 11H4V9h16v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable.png
new file mode 100644
index 00000000..e031527d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable.svg
new file mode 100644
index 00000000..e63a7d5c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/draggable.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 19H4v-2h16v2zM20 15H4v-2h16v2zM20 11H4V9h16v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-invert.png
new file mode 100644
index 00000000..682e18f9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-invert.svg
new file mode 100644
index 00000000..138f8e8e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M17 2L5 14l-1 5 5-1L21 6c0-2-2-4-4-4zM7.2 15.5c-.3-.3-.7-.6-1-.8C8.5 12.4 17.5 3.3 17.5 3.3c.4.1.7.3 1 .7L7.2 15.5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-progressive.png
new file mode 100644
index 00000000..92d625a1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-progressive.svg
new file mode 100644
index 00000000..40446e9f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M17 2L5 14l-1 5 5-1L21 6c0-2-2-4-4-4zM7.2 15.5c-.3-.3-.7-.6-1-.8C8.5 12.4 17.5 3.3 17.5 3.3c.4.1.7.3 1 .7L7.2 15.5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr.png
new file mode 100644
index 00000000..504f29bb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr.svg
new file mode 100644
index 00000000..02ab6e42
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 2L5 14l-1 5 5-1L21 6c0-2-2-4-4-4zM7.2 15.5c-.3-.3-.7-.6-1-.8C8.5 12.4 17.5 3.3 17.5 3.3c.4.1.7.3 1 .7L7.2 15.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-invert.png
new file mode 100644
index 00000000..2d23719c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-invert.svg
new file mode 100644
index 00000000..0b9a4afa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M8 2l12 12 1 5-5-1L4 6c0-2 2-4 4-4zm9.8 13.5c.3-.3.7-.6 1-.8C16.5 12.4 7.5 3.3 7.5 3.3c-.4.1-.7.3-1 .7l11.3 11.5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-progressive.png
new file mode 100644
index 00000000..90653f24
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-progressive.svg
new file mode 100644
index 00000000..8c0b879b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M8 2l12 12 1 5-5-1L4 6c0-2 2-4 4-4zm9.8 13.5c.3-.3.7-.6 1-.8C16.5 12.4 7.5 3.3 7.5 3.3c-.4.1-.7.3-1 .7l11.3 11.5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl.png
new file mode 100644
index 00000000..7ea3aee9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl.svg
new file mode 100644
index 00000000..83033c5a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/edit-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 2l12 12 1 5-5-1L4 6c0-2 2-4 4-4zm9.8 13.5c.3-.3.7-.6 1-.8C16.5 12.4 7.5 3.3 7.5 3.3c-.4.1-.7.3-1 .7l11.3 11.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-invert.png
new file mode 100644
index 00000000..c90c5933
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-invert.svg
new file mode 100644
index 00000000..82b39cd1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M21 4V3s0-3-3-3-3 3-3 3v1h-1v6h8V4zm-1.5 0h-3V3s0-1.5 1.5-1.5c1.48.06 1.5 1.5 1.5 1.5zM13 9.6l-6.8 6.9c-.3-.3-.7-.6-1-.8 1.4-1.4 5-5 7.8-7.9V6l-9 9-1 5 5-1 8-8h-3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-progressive.png
new file mode 100644
index 00000000..4b4c8b4f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-progressive.svg
new file mode 100644
index 00000000..618debea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M21 4V3s0-3-3-3-3 3-3 3v1h-1v6h8V4zm-1.5 0h-3V3s0-1.5 1.5-1.5c1.48.06 1.5 1.5 1.5 1.5zM13 9.6l-6.8 6.9c-.3-.3-.7-.6-1-.8 1.4-1.4 5-5 7.8-7.9V6l-9 9-1 5 5-1 8-8h-3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr.png
new file mode 100644
index 00000000..aa4b8c3b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr.svg
new file mode 100644
index 00000000..e06e5a05
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 4V3s0-3-3-3-3 3-3 3v1h-1v6h8V4zm-1.5 0h-3V3s0-1.5 1.5-1.5c1.48.06 1.5 1.5 1.5 1.5zM13 9.6l-6.8 6.9c-.3-.3-.7-.6-1-.8 1.4-1.4 5-5 7.8-7.9V6l-9 9-1 5 5-1 8-8h-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-invert.png
new file mode 100644
index 00000000..5a40486b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-invert.svg
new file mode 100644
index 00000000..9b9f7656
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M4 4V3s0-3 3-3 3 3 3 3v1h1v6H3V4zm1.5 0h3V3s0-1.5-1.5-1.5C5.52 1.56 5.5 3 5.5 3zM12 9.6l6.8 6.9c.3-.3.7-.6 1-.8-1.4-1.4-5-5-7.8-7.9V6l9 9 1 5-5-1-8-8h3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-progressive.png
new file mode 100644
index 00000000..720a501b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-progressive.svg
new file mode 100644
index 00000000..ad87acc7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M4 4V3s0-3 3-3 3 3 3 3v1h1v6H3V4zm1.5 0h3V3s0-1.5-1.5-1.5C5.52 1.56 5.5 3 5.5 3zM12 9.6l6.8 6.9c.3-.3.7-.6 1-.8-1.4-1.4-5-5-7.8-7.9V6l9 9 1 5-5-1-8-8h3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl.png
new file mode 100644
index 00000000..3d8b751f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl.svg
new file mode 100644
index 00000000..fb1001f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editLock-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 4V3s0-3 3-3 3 3 3 3v1h1v6H3V4zm1.5 0h3V3s0-1.5-1.5-1.5C5.52 1.56 5.5 3 5.5 3zM12 9.6l6.8 6.9c.3-.3.7-.6 1-.8-1.4-1.4-5-5-7.8-7.9V6l9 9 1 5-5-1-8-8h3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-invert.png
new file mode 100644
index 00000000..19726d14
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-invert.svg
new file mode 100644
index 00000000..a34235e2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M14.9 2.8c.9 0 1.8.2 2.7.6.9.4 1.6.9 1.9 1.6-2.8.1-5 1.1-6.6 3.1l1.3 2-6.7-.3L8 3l1.7 2c1.8-1.5 3.5-2.2 5.2-2.2z"/>
+ <path d="M15.2 11.1l-2.6-.1-5.4 5.5c-.3-.3-.7-.6-1-.8.9-.9 2.8-2.8 4.7-4.8H9.1L5 15l-1 5 5-1 7.8-7.8-1.6-.1zM20.6 6c-1.7 0-3.2.5-4.4 1.4l-.9.9.8 1.3.9 1.4 4-4c0-.3-.1-.7-.2-1h-.2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-progressive.png
new file mode 100644
index 00000000..7932aa50
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-progressive.svg
new file mode 100644
index 00000000..c7d9bbe2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M14.9 2.8c.9 0 1.8.2 2.7.6.9.4 1.6.9 1.9 1.6-2.8.1-5 1.1-6.6 3.1l1.3 2-6.7-.3L8 3l1.7 2c1.8-1.5 3.5-2.2 5.2-2.2z"/>
+ <path d="M15.2 11.1l-2.6-.1-5.4 5.5c-.3-.3-.7-.6-1-.8.9-.9 2.8-2.8 4.7-4.8H9.1L5 15l-1 5 5-1 7.8-7.8-1.6-.1zM20.6 6c-1.7 0-3.2.5-4.4 1.4l-.9.9.8 1.3.9 1.4 4-4c0-.3-.1-.7-.2-1h-.2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr.png
new file mode 100644
index 00000000..c1633605
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr.svg
new file mode 100644
index 00000000..50f4214d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14.9 2.8c.9 0 1.8.2 2.7.6.9.4 1.6.9 1.9 1.6-2.8.1-5 1.1-6.6 3.1l1.3 2-6.7-.3L8 3l1.7 2c1.8-1.5 3.5-2.2 5.2-2.2z"/>
+ <path d="M15.2 11.1l-2.6-.1-5.4 5.5c-.3-.3-.7-.6-1-.8.9-.9 2.8-2.8 4.7-4.8H9.1L5 15l-1 5 5-1 7.8-7.8-1.6-.1zM20.6 6c-1.7 0-3.2.5-4.4 1.4l-.9.9.8 1.3.9 1.4 4-4c0-.3-.1-.7-.2-1h-.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-invert.png
new file mode 100644
index 00000000..8e72010c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-invert.svg
new file mode 100644
index 00000000..1aea7a82
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M10.1 2.8c-.9 0-1.8.2-2.7.6-.9.4-1.6.9-1.9 1.6 2.8.1 5 1.1 6.6 3.1l-1.3 2 6.7-.3L17 3l-1.7 2c-1.8-1.5-3.5-2.2-5.2-2.2z"/>
+ <path d="M9.8 11.1l2.6-.1 5.4 5.5c.3-.3.7-.6 1-.8-.9-.9-2.8-2.8-4.7-4.8h1.8L20 15l1 5-5-1-7.8-7.8 1.6-.1zM4.4 6c1.7 0 3.2.5 4.4 1.4l.9.9-.8 1.3L8 11 4 7c0-.3.1-.7.2-1h.2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-progressive.png
new file mode 100644
index 00000000..f563ed83
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-progressive.svg
new file mode 100644
index 00000000..a7433416
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M10.1 2.8c-.9 0-1.8.2-2.7.6-.9.4-1.6.9-1.9 1.6 2.8.1 5 1.1 6.6 3.1l-1.3 2 6.7-.3L17 3l-1.7 2c-1.8-1.5-3.5-2.2-5.2-2.2z"/>
+ <path d="M9.8 11.1l2.6-.1 5.4 5.5c.3-.3.7-.6 1-.8-.9-.9-2.8-2.8-4.7-4.8h1.8L20 15l1 5-5-1-7.8-7.8 1.6-.1zM4.4 6c1.7 0 3.2.5 4.4 1.4l.9.9-.8 1.3L8 11 4 7c0-.3.1-.7.2-1h.2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl.png
new file mode 100644
index 00000000..fc989682
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl.svg
new file mode 100644
index 00000000..b7cfed78
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/editUndo-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10.1 2.8c-.9 0-1.8.2-2.7.6-.9.4-1.6.9-1.9 1.6 2.8.1 5 1.1 6.6 3.1l-1.3 2 6.7-.3L17 3l-1.7 2c-1.8-1.5-3.5-2.2-5.2-2.2z"/>
+ <path d="M9.8 11.1l2.6-.1 5.4 5.5c.3-.3.7-.6 1-.8-.9-.9-2.8-2.8-4.7-4.8h1.8L20 15l1 5-5-1-7.8-7.8 1.6-.1zM4.4 6c1.7 0 3.2.5 4.4 1.4l.9.9-.8 1.3L8 11 4 7c0-.3.1-.7.2-1h.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-invert.png
new file mode 100644
index 00000000..7d57d117
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-invert.svg
new file mode 100644
index 00000000..e5b0d243
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M8 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM14 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM20 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-progressive.png
new file mode 100644
index 00000000..ae7d0713
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-progressive.svg
new file mode 100644
index 00000000..0675f6e1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M8 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM14 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM20 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis.png
new file mode 100644
index 00000000..85fa4f36
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis.svg
new file mode 100644
index 00000000..ef7d485b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ellipsis.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM14 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4zM20 13c0 .6-.2 1-.6 1.4-.4.4-.9.6-1.4.6-.6 0-1-.2-1.4-.6-.4-.4-.6-.9-.6-1.4s.2-1 .6-1.4c.4-.4.9-.6 1.4-.6s1 .2 1.4.6c.4.4.6.9.6 1.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-invert.png
new file mode 100644
index 00000000..38a2c391
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-invert.svg
new file mode 100644
index 00000000..a8260aea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="expand">
+ <path id="arrow" d="M17.303 8.283L12 13.586 6.697 8.283 5.283 9.697 12 16.414l6.717-6.717z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-progressive.png
new file mode 100644
index 00000000..4a183b5a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-progressive.svg
new file mode 100644
index 00000000..e7f6aa53
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="expand">
+ <path id="arrow" d="M17.303 8.283L12 13.586 6.697 8.283 5.283 9.697 12 16.414l6.717-6.717z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand.png
new file mode 100644
index 00000000..f72b6f2e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand.svg
new file mode 100644
index 00000000..84b9e0a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/expand.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="expand">
+ <path id="arrow" d="M17.303 8.283L12 13.586 6.697 8.283 5.283 9.697 12 16.414l6.717-6.717z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-invert.png
new file mode 100644
index 00000000..18a18015
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-invert.svg
new file mode 100644
index 00000000..e9ddf2cb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="external">
+ <path id="box" d="M4 4h6v2H6v12h12v-4h2v6H4z"/>
+ <path id="arrow" d="M12.42 4H20v7.58l-2.84-2.846L12.892 13 11 11.106l4.264-4.266z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-progressive.png
new file mode 100644
index 00000000..00fd1785
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-progressive.svg
new file mode 100644
index 00000000..dcc29620
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="external">
+ <path id="box" d="M4 4h6v2H6v12h12v-4h2v6H4z"/>
+ <path id="arrow" d="M12.42 4H20v7.58l-2.84-2.846L12.892 13 11 11.106l4.264-4.266z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr.png
new file mode 100644
index 00000000..185ffc6a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr.svg
new file mode 100644
index 00000000..1d7980dc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="external">
+ <path id="box" d="M4 4h6v2H6v12h12v-4h2v6H4z"/>
+ <path id="arrow" d="M12.42 4H20v7.58l-2.84-2.846L12.892 13 11 11.106l4.264-4.266z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-invert.png
new file mode 100644
index 00000000..105fd0d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-invert.svg
new file mode 100644
index 00000000..59cd0aab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="external">
+ <path id="box" d="M20 4h-6v2h4v12H6v-4H4v6h16z"/>
+ <path id="arrow" d="M11.58 4H4v7.58l2.84-2.846L11.108 13 13 11.106 8.736 6.84z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-progressive.png
new file mode 100644
index 00000000..569492e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-progressive.svg
new file mode 100644
index 00000000..8d0cd256
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="external">
+ <path id="box" d="M20 4h-6v2h4v12H6v-4H4v6h16z"/>
+ <path id="arrow" d="M11.58 4H4v7.58l2.84-2.846L11.108 13 13 11.106 8.736 6.84z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl.png
new file mode 100644
index 00000000..7066001c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl.svg
new file mode 100644
index 00000000..7e25d034
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/external-link-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="external">
+ <path id="box" d="M20 4h-6v2h4v12H6v-4H4v6h16z"/>
+ <path id="arrow" d="M11.58 4H4v7.58l2.84-2.846L11.108 13 13 11.106 8.736 6.84z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-invert.png
new file mode 100644
index 00000000..4e11ebcb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-invert.svg
new file mode 100644
index 00000000..158860e2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path id="sclera" d="M12 6C7 6 1 12 1 12s6 6 11 6 11-6 11-6-6-6-11-6zm0 10c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+ <circle id="pupil" r="2" cy="12" cx="12"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-progressive.png
new file mode 100644
index 00000000..94524c04
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-progressive.svg
new file mode 100644
index 00000000..ae456857
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path id="sclera" d="M12 6C7 6 1 12 1 12s6 6 11 6 11-6 11-6-6-6-11-6zm0 10c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+ <circle id="pupil" r="2" cy="12" cx="12"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye.png
new file mode 100644
index 00000000..eb5f9635
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye.svg
new file mode 100644
index 00000000..cec85d0b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eye.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="sclera" d="M12 6C7 6 1 12 1 12s6 6 11 6 11-6 11-6-6-6-11-6zm0 10c-2.2 0-4-1.8-4-4s1.8-4 4-4 4 1.8 4 4-1.8 4-4 4z"/>
+ <circle id="pupil" r="2" cy="12" cx="12"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-invert.png
new file mode 100644
index 00000000..bd499f10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-invert.svg
new file mode 100644
index 00000000..7e1567df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M19.4 12.7c.7-.8 1.2-1.7 1.4-2.7h-1.6c-.9 2.5-3.9 4.4-7.7 4.6h-.1c-3.7-.2-6.8-2.1-7.7-4.6H2.2c.2 1 .8 1.9 1.4 2.7l-2 2 .7.7 2-2c.8.6 1.7 1.2 2.7 1.7l-1 2.8.9.3 1-2.8c1 .3 2 .6 3.1.6v3h1v-3c1.1-.1 2.2-.3 3.1-.6l1 2.8.9-.3-1-2.8c1-.4 1.9-1 2.6-1.7l2 2 .7-.7-1.9-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-progressive.png
new file mode 100644
index 00000000..9c228444
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-progressive.svg
new file mode 100644
index 00000000..5d0d44d5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M19.4 12.7c.7-.8 1.2-1.7 1.4-2.7h-1.6c-.9 2.5-3.9 4.4-7.7 4.6h-.1c-3.7-.2-6.8-2.1-7.7-4.6H2.2c.2 1 .8 1.9 1.4 2.7l-2 2 .7.7 2-2c.8.6 1.7 1.2 2.7 1.7l-1 2.8.9.3 1-2.8c1 .3 2 .6 3.1.6v3h1v-3c1.1-.1 2.2-.3 3.1-.6l1 2.8.9-.3-1-2.8c1-.4 1.9-1 2.6-1.7l2 2 .7-.7-1.9-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed.png
new file mode 100644
index 00000000..1ac37d6d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed.svg
new file mode 100644
index 00000000..d17f2c8a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/eyeClosed.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19.4 12.7c.7-.8 1.2-1.7 1.4-2.7h-1.6c-.9 2.5-3.9 4.4-7.7 4.6h-.1c-3.7-.2-6.8-2.1-7.7-4.6H2.2c.2 1 .8 1.9 1.4 2.7l-2 2 .7.7 2-2c.8.6 1.7 1.2 2.7 1.7l-1 2.8.9.3 1-2.8c1 .3 2 .6 3.1.6v3h1v-3c1.1-.1 2.2-.3 3.1-.6l1 2.8.9-.3-1-2.8c1-.4 1.9-1 2.6-1.7l2 2 .7-.7-1.9-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-invert.png
new file mode 100644
index 00000000..f49ebeb0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-invert.svg
new file mode 100644
index 00000000..8ed4be98
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M8.202 15.834l.568 2.101c.198.765 1.06 1.22 1.8 1.016.698-.193 1.125-.983.926-1.747l-.38-1.37H20L17.229 5 4.155 12.652c-.427.762.088 2.748.823 3.182h3.224z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-progressive.png
new file mode 100644
index 00000000..28405a8d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-progressive.svg
new file mode 100644
index 00000000..49425d08
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M8.202 15.834l.568 2.101c.198.765 1.06 1.22 1.8 1.016.698-.193 1.125-.983.926-1.747l-.38-1.37H20L17.229 5 4.155 12.652c-.427.762.088 2.748.823 3.182h3.224z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr.png
new file mode 100644
index 00000000..ac5787bd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr.svg
new file mode 100644
index 00000000..0fdeed9a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8.202 15.834l.568 2.101c.198.765 1.06 1.22 1.8 1.016.698-.193 1.125-.983.926-1.747l-.38-1.37H20L17.229 5 4.155 12.652c-.427.762.088 2.748.823 3.182h3.224z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-invert.png
new file mode 100644
index 00000000..efba220b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-invert.svg
new file mode 100644
index 00000000..f4e7932a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M15.798 15.834l-.568 2.101c-.198.765-1.06 1.22-1.8 1.016-.698-.193-1.125-.983-.926-1.747l.38-1.37H4L6.771 5l13.074 7.652c.427.762-.088 2.748-.823 3.182h-3.224z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-progressive.png
new file mode 100644
index 00000000..27bcc2d0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-progressive.svg
new file mode 100644
index 00000000..413ea34e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M15.798 15.834l-.568 2.101c-.198.765-1.06 1.22-1.8 1.016-.698-.193-1.125-.983-.926-1.747l.38-1.37H4L6.771 5l13.074 7.652c.427.762-.088 2.748-.823 3.182h-3.224z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl.png
new file mode 100644
index 00000000..fdbe5e1e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl.svg
new file mode 100644
index 00000000..022d86d1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/feedback-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15.798 15.834l-.568 2.101c-.198.765-1.06 1.22-1.8 1.016-.698-.193-1.125-.983-.926-1.747l.38-1.37H4L6.771 5l13.074 7.652c.427.762-.088 2.748-.823 3.182h-3.224z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-invert.png
new file mode 100644
index 00000000..e6602c96
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-invert.svg
new file mode 100644
index 00000000..928e9546
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="find">
+ <path id="magnifying-glass" d="M13.656 11c-1.92 0-3.5 1.548-3.5 3.47 0 1.92 1.58 3.5 3.5 3.5.75 0 1.432-.253 2-.657l.094.156 2.375 2.37c.19.19.534.15.78-.096s.315-.59.126-.78l-2.37-2.377-.185-.094a3.545 3.545 0 0 0 .655-2.03c0-1.92-1.55-3.47-3.47-3.47zm0 1.656a1.8 1.8 0 0 1 1.813 1.813 1.83 1.83 0 0 1-1.82 1.84c-1.01 0-1.844-.83-1.844-1.847s.832-1.814 1.844-1.814z"/>
+ <path id="text" d="M6 5v2h10V5H6zm0 3v2h11V8H6zm0 3v2h3.53a4.443 4.443 0 0 1 1.44-2H6zm0 3v2h3.53c-.177-.48-.28-.99-.28-1.53 0-.16.046-.315.063-.47H6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-progressive.png
new file mode 100644
index 00000000..0ca17c10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-progressive.svg
new file mode 100644
index 00000000..65fc2982
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="find">
+ <path id="magnifying-glass" d="M13.656 11c-1.92 0-3.5 1.548-3.5 3.47 0 1.92 1.58 3.5 3.5 3.5.75 0 1.432-.253 2-.657l.094.156 2.375 2.37c.19.19.534.15.78-.096s.315-.59.126-.78l-2.37-2.377-.185-.094a3.545 3.545 0 0 0 .655-2.03c0-1.92-1.55-3.47-3.47-3.47zm0 1.656a1.8 1.8 0 0 1 1.813 1.813 1.83 1.83 0 0 1-1.82 1.84c-1.01 0-1.844-.83-1.844-1.847s.832-1.814 1.844-1.814z"/>
+ <path id="text" d="M6 5v2h10V5H6zm0 3v2h11V8H6zm0 3v2h3.53a4.443 4.443 0 0 1 1.44-2H6zm0 3v2h3.53c-.177-.48-.28-.99-.28-1.53 0-.16.046-.315.063-.47H6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr.png
new file mode 100644
index 00000000..066d84a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr.svg
new file mode 100644
index 00000000..ef44f579
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="find">
+ <path id="magnifying-glass" d="M13.656 11c-1.92 0-3.5 1.548-3.5 3.47 0 1.92 1.58 3.5 3.5 3.5.75 0 1.432-.253 2-.657l.094.156 2.375 2.37c.19.19.534.15.78-.096s.315-.59.126-.78l-2.37-2.377-.185-.094a3.545 3.545 0 0 0 .655-2.03c0-1.92-1.55-3.47-3.47-3.47zm0 1.656a1.8 1.8 0 0 1 1.813 1.813 1.83 1.83 0 0 1-1.82 1.84c-1.01 0-1.844-.83-1.844-1.847s.832-1.814 1.844-1.814z"/>
+ <path id="text" d="M6 5v2h10V5H6zm0 3v2h11V8H6zm0 3v2h3.53a4.443 4.443 0 0 1 1.44-2H6zm0 3v2h3.53c-.177-.48-.28-.99-.28-1.53 0-.16.046-.315.063-.47H6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-invert.png
new file mode 100644
index 00000000..bd3e862e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-invert.svg
new file mode 100644
index 00000000..612c1dcf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="find">
+ <path id="magnifying-glass" d="M11.344 11c1.92 0 3.5 1.548 3.5 3.47 0 1.92-1.58 3.5-3.5 3.5-.75 0-1.432-.253-2-.657l-.094.156-2.375 2.37c-.19.19-.534.15-.78-.096s-.315-.59-.126-.78l2.37-2.377.185-.094a3.545 3.545 0 0 1-.655-2.03c0-1.92 1.55-3.47 3.47-3.47zm0 1.656A1.8 1.8 0 0 0 9.53 14.47c0 1.01.806 1.84 1.818 1.84 1.01 0 1.844-.83 1.844-1.845s-.832-1.814-1.844-1.814z"/>
+ <path id="text" d="M19 5v2H9V5zm0 3v2H8V8zm0 3v2h-3.53a4.443 4.443 0 0 0-1.44-2zm0 3v2h-3.53c.177-.48.28-.99.28-1.53 0-.16-.046-.315-.063-.47z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-progressive.png
new file mode 100644
index 00000000..142dbe45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-progressive.svg
new file mode 100644
index 00000000..f18e0add
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="find">
+ <path id="magnifying-glass" d="M11.344 11c1.92 0 3.5 1.548 3.5 3.47 0 1.92-1.58 3.5-3.5 3.5-.75 0-1.432-.253-2-.657l-.094.156-2.375 2.37c-.19.19-.534.15-.78-.096s-.315-.59-.126-.78l2.37-2.377.185-.094a3.545 3.545 0 0 1-.655-2.03c0-1.92 1.55-3.47 3.47-3.47zm0 1.656A1.8 1.8 0 0 0 9.53 14.47c0 1.01.806 1.84 1.818 1.84 1.01 0 1.844-.83 1.844-1.845s-.832-1.814-1.844-1.814z"/>
+ <path id="text" d="M19 5v2H9V5zm0 3v2H8V8zm0 3v2h-3.53a4.443 4.443 0 0 0-1.44-2zm0 3v2h-3.53c.177-.48.28-.99.28-1.53 0-.16-.046-.315-.063-.47z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl.png
new file mode 100644
index 00000000..ed834afe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl.svg
new file mode 100644
index 00000000..51fd39ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/find-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="find">
+ <path id="magnifying-glass" d="M11.344 11c1.92 0 3.5 1.548 3.5 3.47 0 1.92-1.58 3.5-3.5 3.5-.75 0-1.432-.253-2-.657l-.094.156-2.375 2.37c-.19.19-.534.15-.78-.096s-.315-.59-.126-.78l2.37-2.377.185-.094a3.545 3.545 0 0 1-.655-2.03c0-1.92 1.55-3.47 3.47-3.47zm0 1.656A1.8 1.8 0 0 0 9.53 14.47c0 1.01.806 1.84 1.818 1.84 1.01 0 1.844-.83 1.844-1.845s-.832-1.814-1.844-1.814z"/>
+ <path id="text" d="M19 5v2H9V5zm0 3v2H8V8zm0 3v2h-3.53a4.443 4.443 0 0 0-1.44-2zm0 3v2h-3.53c.177-.48.28-.99.28-1.53 0-.16-.046-.315-.063-.47z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-invert.png
new file mode 100644
index 00000000..ea79f46b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-invert.svg
new file mode 100644
index 00000000..f6c22133
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M14 6.5V5c-1.4-1.5-5.2-1.2-6 0V4H7v15h1v-7c.8-.8 3.4-.9 5-.5V13c1.2 1.5 4.3 1.2 5 0V6c-.7.7-2.7.9-4 .5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-progressive.png
new file mode 100644
index 00000000..4d76692e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-progressive.svg
new file mode 100644
index 00000000..c1f681ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M14 6.5V5c-1.4-1.5-5.2-1.2-6 0V4H7v15h1v-7c.8-.8 3.4-.9 5-.5V13c1.2 1.5 4.3 1.2 5 0V6c-.7.7-2.7.9-4 .5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr.png
new file mode 100644
index 00000000..bd19f2b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr.svg
new file mode 100644
index 00000000..10975612
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14 6.5V5c-1.4-1.5-5.2-1.2-6 0V4H7v15h1v-7c.8-.8 3.4-.9 5-.5V13c1.2 1.5 4.3 1.2 5 0V6c-.7.7-2.7.9-4 .5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-invert.png
new file mode 100644
index 00000000..159bdb9e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-invert.svg
new file mode 100644
index 00000000..ce147ec3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M10.3 7.5V6c1.4-1.5 5.2-1.2 6 0V5h1v15h-1v-7c-.8-.8-3.4-.9-5-.5V14c-1.2 1.5-4.3 1.2-5 0V7c.7.7 2.7.9 4 .5z"/>
+</g></svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-progressive.png
new file mode 100644
index 00000000..e88e0617
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-progressive.svg
new file mode 100644
index 00000000..661f2342
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M10.3 7.5V6c1.4-1.5 5.2-1.2 6 0V5h1v15h-1v-7c-.8-.8-3.4-.9-5-.5V14c-1.2 1.5-4.3 1.2-5 0V7c.7.7 2.7.9 4 .5z"/>
+</g></svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl.png
new file mode 100644
index 00000000..a9943cce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl.svg
new file mode 100644
index 00000000..397a3da2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/flag-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10.3 7.5V6c1.4-1.5 5.2-1.2 6 0V5h1v15h-1v-7c-.8-.8-3.4-.9-5-.5V14c-1.2 1.5-4.3 1.2-5 0V7c.7.7 2.7.9 4 .5z"/>
+</svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-invert.png
new file mode 100644
index 00000000..d7c6e288
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-invert.svg
new file mode 100644
index 00000000..4c6d4021
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M2 5v15h20V5H2zm15 11H8c-.6 0-1-.4-1-1V9h3l2 1h5v6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-progressive.png
new file mode 100644
index 00000000..39c58bef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-progressive.svg
new file mode 100644
index 00000000..e1f8be31
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M2 5v15h20V5H2zm15 11H8c-.6 0-1-.4-1-1V9h3l2 1h5v6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr.png
new file mode 100644
index 00000000..45c3ee9d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr.svg
new file mode 100644
index 00000000..7e60fb4b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M2 5v15h20V5H2zm15 11H8c-.6 0-1-.4-1-1V9h3l2 1h5v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-invert.png
new file mode 100644
index 00000000..46b3f945
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-invert.svg
new file mode 100644
index 00000000..d2bfb083
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M22 5v15H2V5h20zM7 16h9c.6 0 1-.4 1-1V9h-3l-2 1H7v6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-progressive.png
new file mode 100644
index 00000000..a384c8df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-progressive.svg
new file mode 100644
index 00000000..ba0eb3be
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M22 5v15H2V5h20zM7 16h9c.6 0 1-.4 1-1V9h-3l-2 1H7v6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl.png
new file mode 100644
index 00000000..8a624c19
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl.svg
new file mode 100644
index 00000000..e0a6f619
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/folderPlaceholder-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M22 5v15H2V5h20zM7 16h9c.6 0 1-.4 1-1V9h-3l-2 1H7v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-invert.png
new file mode 100644
index 00000000..b7a3cb51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-invert.svg
new file mode 100644
index 00000000..588bef07
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path id="arrow" d="M6 6v4l1.28-1.28 2 2 1.423-1.44-2-2L10 6z"/>
+ <use transform="rotate(90 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(180 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(-90 12 12)" xlink:href="#arrow"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-progressive.png
new file mode 100644
index 00000000..8b86269e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-progressive.svg
new file mode 100644
index 00000000..a9a0aa04
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path id="arrow" d="M6 6v4l1.28-1.28 2 2 1.423-1.44-2-2L10 6z"/>
+ <use transform="rotate(90 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(180 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(-90 12 12)" xlink:href="#arrow"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen.png
new file mode 100644
index 00000000..ced10354
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen.svg
new file mode 100644
index 00000000..06b709ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/fullScreen.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <path id="arrow" d="M6 6v4l1.28-1.28 2 2 1.423-1.44-2-2L10 6z"/>
+ <use transform="rotate(90 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(180 12 12)" xlink:href="#arrow"/>
+ <use transform="rotate(-90 12 12)" xlink:href="#arrow"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-invert.png
new file mode 100644
index 00000000..2949648d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-invert.svg
new file mode 100644
index 00000000..cffafb73
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M11 13L5 6h15l-6 7v7c-1.7 0-3-1.3-3-3v-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-progressive.png
new file mode 100644
index 00000000..a6079a41
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-progressive.svg
new file mode 100644
index 00000000..9ef43f01
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M11 13L5 6h15l-6 7v7c-1.7 0-3-1.3-3-3v-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr.png
new file mode 100644
index 00000000..9396cba0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr.svg
new file mode 100644
index 00000000..df863b9c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 13L5 6h15l-6 7v7c-1.7 0-3-1.3-3-3v-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-invert.png
new file mode 100644
index 00000000..c0f155ae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-invert.svg
new file mode 100644
index 00000000..64a71fac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M14 13l6-7H5l6 7v7c1.7 0 3-1.3 3-3v-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-progressive.png
new file mode 100644
index 00000000..5c576628
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-progressive.svg
new file mode 100644
index 00000000..b44b385d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M14 13l6-7H5l6 7v7c1.7 0 3-1.3 3-3v-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl.png
new file mode 100644
index 00000000..7aee05f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl.svg
new file mode 100644
index 00000000..4eade2d6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/funnel-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14 13l6-7H5l6 7v7c1.7 0 3-1.3 3-3v-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright-invert.png
new file mode 100644
index 00000000..2a4d5478
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright-invert.svg
new file mode 100644
index 00000000..82f466eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M11.4 5.4V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm-5.2-.5c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 7c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm-3 4c0-1.7 1.3-3 3-3v6c-1.7 0-3-1.3-3-3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright.png
new file mode 100644
index 00000000..f8432105
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright.svg
new file mode 100644
index 00000000..2745ec7f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfBright.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11.4 5.4V2.2c.3 0 .6.1.9.4.3.3.4.5.4.8v2h-1.3zm-5.2-.5c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4-.3-.3-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9.3-.3.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8 0-.3.1-.6.3-.8zM12 7c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm-3 4c0-1.7 1.3-3 3-3v6c-1.7 0-3-1.3-3-3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-constructive.png
new file mode 100644
index 00000000..57dfe530
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-constructive.svg
new file mode 100644
index 00000000..dbdacc6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-constructive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+ <path d="M10.1 11l-3.9.5L9 14.3l-.6 3.9 3.6-1.7-.1-9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-invert.png
new file mode 100644
index 00000000..f28e35d3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-invert.svg
new file mode 100644
index 00000000..febf5007
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+ <path d="M10.1 11l-3.9.5L9 14.3l-.6 3.9 3.6-1.7-.1-9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-progressive.png
new file mode 100644
index 00000000..57dfe530
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-progressive.svg
new file mode 100644
index 00000000..dbdacc6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+ <path d="M10.1 11l-3.9.5L9 14.3l-.6 3.9 3.6-1.7-.1-9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr.png
new file mode 100644
index 00000000..d52a9080
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr.svg
new file mode 100644
index 00000000..cfb17d8c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+ <path d="M10.1 11l-3.9.5L9 14.3l-.6 3.9 3.6-1.7-.1-9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-constructive.png
new file mode 100644
index 00000000..d24672a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-constructive.svg
new file mode 100644
index 00000000..2f458168
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-constructive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 7.4L10.3 11l-4 .5L9 14.3l-.5 3.9 3.5-1.7 3.6 1.7-.6-3.9 2.8-2.8-3.9-.5L12 7.4M12 4l2.8 5.6 6.2.9-4.5 4.4 1.1 6.1-5.6-3-5.5 3 1-6.2L3 10.4l6.3-.9L12 4z"/>
+ <path d="M12.1 7.5l1.8 3.5 3.9.5-2.8 2.8.6 3.9-3.6-1.7z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-invert.png
new file mode 100644
index 00000000..c9429ae3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-invert.svg
new file mode 100644
index 00000000..11b99dfe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 7.4L10.3 11l-4 .5L9 14.3l-.5 3.9 3.5-1.7 3.6 1.7-.6-3.9 2.8-2.8-3.9-.5L12 7.4M12 4l2.8 5.6 6.2.9-4.5 4.4 1.1 6.1-5.6-3-5.5 3 1-6.2L3 10.4l6.3-.9L12 4z"/>
+ <path d="M12.1 7.5l1.8 3.5 3.9.5-2.8 2.8.6 3.9-3.6-1.7z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-progressive.png
new file mode 100644
index 00000000..d24672a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-progressive.svg
new file mode 100644
index 00000000..2f458168
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 7.4L10.3 11l-4 .5L9 14.3l-.5 3.9 3.5-1.7 3.6 1.7-.6-3.9 2.8-2.8-3.9-.5L12 7.4M12 4l2.8 5.6 6.2.9-4.5 4.4 1.1 6.1-5.6-3-5.5 3 1-6.2L3 10.4l6.3-.9L12 4z"/>
+ <path d="M12.1 7.5l1.8 3.5 3.9.5-2.8 2.8.6 3.9-3.6-1.7z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl.png
new file mode 100644
index 00000000..4991b65c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl.svg
new file mode 100644
index 00000000..c649b505
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/halfStar-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 7.4L10.3 11l-4 .5L9 14.3l-.5 3.9 3.5-1.7 3.6 1.7-.6-3.9 2.8-2.8-3.9-.5L12 7.4M12 4l2.8 5.6 6.2.9-4.5 4.4 1.1 6.1-5.6-3-5.5 3 1-6.2L3 10.4l6.3-.9L12 4z"/>
+ <path d="M12.1 7.5l1.8 3.5 3.9.5-2.8 2.8.6 3.9-3.6-1.7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-invert.png
new file mode 100644
index 00000000..2070997e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-invert.svg
new file mode 100644
index 00000000..1607febd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M15 7c-2 0-3 2-3 2s-1-2-3-2c-2.5 0-4 2-4 4 0 4 5 5 7 8 2-3 7-4 7-8 0-2-1.5-4-4-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-progressive.png
new file mode 100644
index 00000000..87973210
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-progressive.svg
new file mode 100644
index 00000000..816e672d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M15 7c-2 0-3 2-3 2s-1-2-3-2c-2.5 0-4 2-4 4 0 4 5 5 7 8 2-3 7-4 7-8 0-2-1.5-4-4-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart.png
new file mode 100644
index 00000000..76d76d0a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart.svg
new file mode 100644
index 00000000..6433201a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/heart.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 7c-2 0-3 2-3 2s-1-2-3-2c-2.5 0-4 2-4 4 0 4 5 5 7 8 2-3 7-4 7-8 0-2-1.5-4-4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-invert.png
new file mode 100644
index 00000000..35d8f226
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-invert.svg
new file mode 100644
index 00000000..7e0a6581
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-invert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="help">
+ <path id="circle" d="M12 2.085c-5.477 0-9.915 4.438-9.915 9.916 0 5.48 4.438 9.92 9.916 9.92 5.48 0 9.92-4.44 9.92-9.913 0-5.477-4.44-9.915-9.913-9.915zm.002 18a8.084 8.084 0 1 1 0-16.168 8.084 8.084 0 0 1 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M11.766 6.688c-2.5 0-3.22 2.188-3.22 2.188l1.412.854s.298-.79.9-1.23c.517-.374 1.626-.624 2.22.126.7.885-.17 1.587-1.078 2.72C11.047 12.53 11 15 11 15h1.97s.134-2.318 1.04-3.38c.603-.708 1.443-1.34 1.443-2.495s-1.187-2.437-3.687-2.437z"/>
+ <path id="bottom" d="M11 16h2v2h-2z"/>
+ </g>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-progressive.png
new file mode 100644
index 00000000..87236a8e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-progressive.svg
new file mode 100644
index 00000000..8a2e3caf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr-progressive.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="help">
+ <path id="circle" d="M12 2.085c-5.477 0-9.915 4.438-9.915 9.916 0 5.48 4.438 9.92 9.916 9.92 5.48 0 9.92-4.44 9.92-9.913 0-5.477-4.44-9.915-9.913-9.915zm.002 18a8.084 8.084 0 1 1 0-16.168 8.084 8.084 0 0 1 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M11.766 6.688c-2.5 0-3.22 2.188-3.22 2.188l1.412.854s.298-.79.9-1.23c.517-.374 1.626-.624 2.22.126.7.885-.17 1.587-1.078 2.72C11.047 12.53 11 15 11 15h1.97s.134-2.318 1.04-3.38c.603-.708 1.443-1.34 1.443-2.495s-1.187-2.437-3.687-2.437z"/>
+ <path id="bottom" d="M11 16h2v2h-2z"/>
+ </g>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr.png
new file mode 100644
index 00000000..9bb1382a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr.svg
new file mode 100644
index 00000000..a77dca2c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-ltr.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="help">
+ <path id="circle" d="M12 2.085c-5.477 0-9.915 4.438-9.915 9.916 0 5.48 4.438 9.92 9.916 9.92 5.48 0 9.92-4.44 9.92-9.913 0-5.477-4.44-9.915-9.913-9.915zm.002 18a8.084 8.084 0 1 1 0-16.168 8.084 8.084 0 0 1 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M11.766 6.688c-2.5 0-3.22 2.188-3.22 2.188l1.412.854s.298-.79.9-1.23c.517-.374 1.626-.624 2.22.126.7.885-.17 1.587-1.078 2.72C11.047 12.53 11 15 11 15h1.97s.134-2.318 1.04-3.38c.603-.708 1.443-1.34 1.443-2.495s-1.187-2.437-3.687-2.437z"/>
+ <path id="bottom" d="M11 16h2v2h-2z"/>
+ </g>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-invert.png
new file mode 100644
index 00000000..9cb8cb28
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-invert.svg
new file mode 100644
index 00000000..2d78cb84
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-invert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="help">
+ <path id="circle" d="M12 2.085c5.477 0 9.915 4.438 9.915 9.916 0 5.48-4.438 9.92-9.916 9.92-5.48 0-9.92-4.44-9.92-9.913 0-5.477 4.44-9.915 9.913-9.915zm-.002 18a8.084 8.084 0 1 0 0-16.168 8.084 8.084 0 0 0 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M12.234 6.688c2.5 0 3.22 2.188 3.22 2.188l-1.412.854s-.298-.79-.9-1.23c-.517-.374-1.626-.624-2.22.126-.7.885.17 1.587 1.078 2.72C12.953 12.53 13 15 13 15h-1.97s-.134-2.318-1.04-3.38c-.603-.708-1.443-1.34-1.443-2.495 0-1.156 1.187-2.437 3.687-2.437z"/>
+ <path id="bottom" d="M13 16h-2v2h2z"/>
+ </g>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-progressive.png
new file mode 100644
index 00000000..72f95c26
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-progressive.svg
new file mode 100644
index 00000000..878c72c4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl-progressive.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="help">
+ <path id="circle" d="M12 2.085c5.477 0 9.915 4.438 9.915 9.916 0 5.48-4.438 9.92-9.916 9.92-5.48 0-9.92-4.44-9.92-9.913 0-5.477 4.44-9.915 9.913-9.915zm-.002 18a8.084 8.084 0 1 0 0-16.168 8.084 8.084 0 0 0 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M12.234 6.688c2.5 0 3.22 2.188 3.22 2.188l-1.412.854s-.298-.79-.9-1.23c-.517-.374-1.626-.624-2.22.126-.7.885.17 1.587 1.078 2.72C12.953 12.53 13 15 13 15h-1.97s-.134-2.318-1.04-3.38c-.603-.708-1.443-1.34-1.443-2.495 0-1.156 1.187-2.437 3.687-2.437z"/>
+ <path id="bottom" d="M13 16h-2v2h2z"/>
+ </g>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl.png
new file mode 100644
index 00000000..50899b0d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl.svg
new file mode 100644
index 00000000..278b906b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/help-rtl.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="help">
+ <path id="circle" d="M12 2.085c5.477 0 9.915 4.438 9.915 9.916 0 5.48-4.438 9.92-9.916 9.92-5.48 0-9.92-4.44-9.92-9.913 0-5.477 4.44-9.915 9.913-9.915zm-.002 18a8.084 8.084 0 1 0 0-16.168 8.084 8.084 0 0 0 0 16.168z"/>
+ <g id="question-mark">
+ <path id="top" d="M12.234 6.688c2.5 0 3.22 2.188 3.22 2.188l-1.412.854s-.298-.79-.9-1.23c-.517-.374-1.626-.624-2.22.126-.7.885.17 1.587 1.078 2.72C12.953 12.53 13 15 13 15h-1.97s-.134-2.318-1.04-3.38c-.603-.708-1.443-1.34-1.443-2.495 0-1.156 1.187-2.437 3.687-2.437z"/>
+ <path id="bottom" d="M13 16h-2v2h2z"/>
+ </g>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-invert.png
new file mode 100644
index 00000000..314d7acb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-invert.svg
new file mode 100644
index 00000000..e301deaf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24" width="24"><g fill="#fff">
+ <path d="M5.066 18.236l.14-.244c.976-1.69 1.341-4.587.815-6.469l-.14-.507.2-.365L11.074 2l9.011 5.203-4.994 8.65-.204.354-.522.134c-1.893.485-4.22 2.252-5.195 3.94l-.14.244-.721-.416-1.041 1.89H3.914l1.893-3.336z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-progressive.png
new file mode 100644
index 00000000..14bd7bec
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-progressive.svg
new file mode 100644
index 00000000..4cc90b52
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24" width="24"><g fill="#36c">
+ <path d="M5.066 18.236l.14-.244c.976-1.69 1.341-4.587.815-6.469l-.14-.507.2-.365L11.074 2l9.011 5.203-4.994 8.65-.204.354-.522.134c-1.893.485-4.22 2.252-5.195 3.94l-.14.244-.721-.416-1.041 1.89H3.914l1.893-3.336z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr.png
new file mode 100644
index 00000000..73dd6b9c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr.svg
new file mode 100644
index 00000000..eb42923d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24" width="24">
+ <path d="M5.066 18.236l.14-.244c.976-1.69 1.341-4.587.815-6.469l-.14-.507.2-.365L11.074 2l9.011 5.203-4.994 8.65-.204.354-.522.134c-1.893.485-4.22 2.252-5.195 3.94l-.14.244-.721-.416-1.041 1.89H3.914l1.893-3.336z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-invert.png
new file mode 100644
index 00000000..024595e2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-invert.svg
new file mode 100644
index 00000000..46d61c22
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24" width="24"><g fill="#fff">
+ <path d="M18.934 18.236l-.14-.244c-.976-1.69-1.341-4.587-.815-6.469l.14-.507-.2-.365L12.926 2 3.914 7.203l4.994 8.65.204.354.522.134c1.893.485 4.22 2.252 5.195 3.94l.14.244.721-.416 1.041 1.89h3.355l-1.893-3.336z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-progressive.png
new file mode 100644
index 00000000..039ccbe7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-progressive.svg
new file mode 100644
index 00000000..4f3997a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24" width="24"><g fill="#36c">
+ <path d="M18.934 18.236l-.14-.244c-.976-1.69-1.341-4.587-.815-6.469l.14-.507-.2-.365L12.926 2 3.914 7.203l4.994 8.65.204.354.522.134c1.893.485 4.22 2.252 5.195 3.94l.14.244.721-.416 1.041 1.89h3.355l-1.893-3.336z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl.png
new file mode 100644
index 00000000..2ea29830
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl.svg
new file mode 100644
index 00000000..9b1940eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/highlight-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" height="24" width="24">
+ <path d="M18.934 18.236l-.14-.244c-.976-1.69-1.341-4.587-.815-6.469l.14-.507-.2-.365L12.926 2 3.914 7.203l4.994 8.65.204.354.522.134c1.893.485 4.22 2.252 5.195 3.94l.14.244.721-.416 1.041 1.89h3.355l-1.893-3.336z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-invert.png
new file mode 100644
index 00000000..0bd8394f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-invert.svg
new file mode 100644
index 00000000..fa0a150f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="history">
+ <path id="clock-hands" d="M17.26 15.076s-2.385-1.935-4.005-3.062c.72-2.397 1.702-6.56 1.702-6.56s-4.35 5.364-4.877 6.7c-.463 1.168 1.46 2.21 2.346 1.678 1.9.55 4.834 1.244 4.834 1.244z"/>
+ <path id="arrow" d="M12.086 2.085C6.608 2.085 2.17 6.523 2.17 12a9.86 9.86 0 0 0 1.3 4.9l-2.22 2.04h5.688v-5.22L4.87 15.616A7.982 7.982 0 0 1 4.004 12a8.084 8.084 0 0 1 16.167.004 8.08 8.08 0 0 1-8.08 8.085 7.975 7.975 0 0 1-3.21-.68L8.05 21.04a9.81 9.81 0 0 0 4.045.874C17.563 21.914 22 17.476 22 12c0-5.477-4.438-9.915-9.914-9.915z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-progressive.png
new file mode 100644
index 00000000..ec635a14
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-progressive.svg
new file mode 100644
index 00000000..bd26dfb3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="history">
+ <path id="clock-hands" d="M17.26 15.076s-2.385-1.935-4.005-3.062c.72-2.397 1.702-6.56 1.702-6.56s-4.35 5.364-4.877 6.7c-.463 1.168 1.46 2.21 2.346 1.678 1.9.55 4.834 1.244 4.834 1.244z"/>
+ <path id="arrow" d="M12.086 2.085C6.608 2.085 2.17 6.523 2.17 12a9.86 9.86 0 0 0 1.3 4.9l-2.22 2.04h5.688v-5.22L4.87 15.616A7.982 7.982 0 0 1 4.004 12a8.084 8.084 0 0 1 16.167.004 8.08 8.08 0 0 1-8.08 8.085 7.975 7.975 0 0 1-3.21-.68L8.05 21.04a9.81 9.81 0 0 0 4.045.874C17.563 21.914 22 17.476 22 12c0-5.477-4.438-9.915-9.914-9.915z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history.png
new file mode 100644
index 00000000..417f5293
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history.svg
new file mode 100644
index 00000000..68beaa13
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/history.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="history">
+ <path id="clock-hands" d="M17.26 15.076s-2.385-1.935-4.005-3.062c.72-2.397 1.702-6.56 1.702-6.56s-4.35 5.364-4.877 6.7c-.463 1.168 1.46 2.21 2.346 1.678 1.9.55 4.834 1.244 4.834 1.244z"/>
+ <path id="arrow" d="M12.086 2.085C6.608 2.085 2.17 6.523 2.17 12a9.86 9.86 0 0 0 1.3 4.9l-2.22 2.04h5.688v-5.22L4.87 15.616A7.982 7.982 0 0 1 4.004 12a8.084 8.084 0 0 1 16.167.004 8.08 8.08 0 0 1-8.08 8.085 7.975 7.975 0 0 1-3.21-.68L8.05 21.04a9.81 9.81 0 0 0 4.045.874C17.563 21.914 22 17.476 22 12c0-5.477-4.438-9.915-9.914-9.915z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-invert.png
new file mode 100644
index 00000000..42797a25
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-invert.svg
new file mode 100644
index 00000000..04354ce3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="image">
+ <path id="mountains" d="M18 17l-3-3-2 1-3-3-4 5zm2-11v13H4V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-progressive.png
new file mode 100644
index 00000000..f5cefdf6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-progressive.svg
new file mode 100644
index 00000000..252099f7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="image">
+ <path id="mountains" d="M18 17l-3-3-2 1-3-3-4 5zm2-11v13H4V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr.png
new file mode 100644
index 00000000..f91dfa23
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr.svg
new file mode 100644
index 00000000..dfcbd8bb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="image">
+ <path id="mountains" d="M18 17l-3-3-2 1-3-3-4 5zm2-11v13H4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-invert.png
new file mode 100644
index 00000000..c33eed61
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-invert.svg
new file mode 100644
index 00000000..875fe66c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="image">
+ <path id="mountains" d="M6 17l3-3 2 1 3-3 4 5zM4 6v13h16V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-progressive.png
new file mode 100644
index 00000000..eadff85d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-progressive.svg
new file mode 100644
index 00000000..d015e8b4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="image">
+ <path id="mountains" d="M6 17l3-3 2 1 3-3 4 5zM4 6v13h16V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl.png
new file mode 100644
index 00000000..f33be17f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl.svg
new file mode 100644
index 00000000..2251c0e7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/image-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="image">
+ <path id="mountains" d="M6 17l3-3 2 1 3-3 4 5zM4 6v13h16V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-invert.png
new file mode 100644
index 00000000..422f8eab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-invert.svg
new file mode 100644
index 00000000..78c40b32
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="imageAdd">
+ <path id="mountains" d="M16 17l-3-3-2 1-3-3-4 5zm-1-8v4h3v6H2V6h9v3z"/>
+ <path id="add" d="M22 6h-4V2h-2v4h-4v2h4v4h2V8h4z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-progressive.png
new file mode 100644
index 00000000..e64819ca
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-progressive.svg
new file mode 100644
index 00000000..b8989564
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="imageAdd">
+ <path id="mountains" d="M16 17l-3-3-2 1-3-3-4 5zm-1-8v4h3v6H2V6h9v3z"/>
+ <path id="add" d="M22 6h-4V2h-2v4h-4v2h4v4h2V8h4z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr.png
new file mode 100644
index 00000000..f08883c4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr.svg
new file mode 100644
index 00000000..1b60cf00
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="imageAdd">
+ <path id="mountains" d="M16 17l-3-3-2 1-3-3-4 5zm-1-8v4h3v6H2V6h9v3z"/>
+ <path id="add" d="M22 6h-4V2h-2v4h-4v2h4v4h2V8h4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-invert.png
new file mode 100644
index 00000000..375a79f5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-invert.svg
new file mode 100644
index 00000000..e76b43fe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="imageAdd">
+ <path id="mountains" d="M8 17l3-3 2 1 3-3 4 5zm1-8v4H6v6h16V6h-9v3z"/>
+ <path id="add" d="M2 6h4V2h2v4h4v2H8v4H6V8H2z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-progressive.png
new file mode 100644
index 00000000..dec94010
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-progressive.svg
new file mode 100644
index 00000000..61e2ed4a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="imageAdd">
+ <path id="mountains" d="M8 17l3-3 2 1 3-3 4 5zm1-8v4H6v6h16V6h-9v3z"/>
+ <path id="add" d="M2 6h4V2h2v4h4v2H8v4H6V8H2z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl.png
new file mode 100644
index 00000000..dd60447c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl.svg
new file mode 100644
index 00000000..b86d4999
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageAdd-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="imageAdd">
+ <path id="mountains" d="M8 17l3-3 2 1 3-3 4 5zm1-8v4H6v6h16V6h-9v3z"/>
+ <path id="add" d="M2 6h4V2h2v4h4v2H8v4H6V8H2z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-invert.png
new file mode 100644
index 00000000..bd15ff00
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-invert.svg
new file mode 100644
index 00000000..c2d3d8a1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M2 4v14h2V6h15V4H2zm3 3v13h16V7H5zm6 6l3 3 2-1 3 3H7l4-5z" id="imageGallery"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-progressive.png
new file mode 100644
index 00000000..7e360aa0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-progressive.svg
new file mode 100644
index 00000000..4029c275
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M2 4v14h2V6h15V4H2zm3 3v13h16V7H5zm6 6l3 3 2-1 3 3H7l4-5z" id="imageGallery"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr.png
new file mode 100644
index 00000000..3934d14f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr.svg
new file mode 100644
index 00000000..2fa2e528
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M2 4v14h2V6h15V4H2zm3 3v13h16V7H5zm6 6l3 3 2-1 3 3H7l4-5z" id="imageGallery"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-invert.png
new file mode 100644
index 00000000..85b22c4b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-invert.svg
new file mode 100644
index 00000000..b32a86ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M21 4v14h-2V6H4V4h17zm-3 3v13H2V7h16zm-6 6l-3 3-2-1-3 3h12l-4-5z" id="imageGallery"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-progressive.png
new file mode 100644
index 00000000..3d014a54
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-progressive.svg
new file mode 100644
index 00000000..21f4a80a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M21 4v14h-2V6H4V4h17zm-3 3v13H2V7h16zm-6 6l-3 3-2-1-3 3h12l-4-5z" id="imageGallery"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl.png
new file mode 100644
index 00000000..f8af41f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl.svg
new file mode 100644
index 00000000..c705cecc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageGallery-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 4v14h-2V6H4V4h17zm-3 3v13H2V7h16zm-6 6l-3 3-2-1-3 3h12l-4-5z" id="imageGallery"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-invert.png
new file mode 100644
index 00000000..61b5d229
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-invert.svg
new file mode 100644
index 00000000..b726d4b2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="imageAdd">
+ <path id="mountains" d="M18 17l-3-3-2 1-3-3-4 5zm2-5v7H4V6h8v6z"/>
+ <path id="lock" d="M18.5 5h-3V4s0-1.5 1.5-1.5c1.5.06 1.5 1.5 1.5 1.5zM20 5V4s0-3-3-3-3 3-3 3v1h-1v6h8V5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-progressive.png
new file mode 100644
index 00000000..f5604bf8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-progressive.svg
new file mode 100644
index 00000000..e726c030
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="imageAdd">
+ <path id="mountains" d="M18 17l-3-3-2 1-3-3-4 5zm2-5v7H4V6h8v6z"/>
+ <path id="lock" d="M18.5 5h-3V4s0-1.5 1.5-1.5c1.5.06 1.5 1.5 1.5 1.5zM20 5V4s0-3-3-3-3 3-3 3v1h-1v6h8V5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr.png
new file mode 100644
index 00000000..a1a1e1ed
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr.svg
new file mode 100644
index 00000000..50a928a5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="imageAdd">
+ <path id="mountains" d="M18 17l-3-3-2 1-3-3-4 5zm2-5v7H4V6h8v6z"/>
+ <path id="lock" d="M18.5 5h-3V4s0-1.5 1.5-1.5c1.5.06 1.5 1.5 1.5 1.5zM20 5V4s0-3-3-3-3 3-3 3v1h-1v6h8V5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-invert.png
new file mode 100644
index 00000000..2223f5f9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-invert.svg
new file mode 100644
index 00000000..c92cd7fb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="imageAdd">
+ <path id="mountains" d="M7 17l3-3 2 1 3-3 4 5zm-2-5v7h16V6h-8v6z"/>
+ <path id="lock" d="M6.5 5h3V4s0-1.5-1.5-1.5C6.5 2.56 6.5 4 6.5 4zM5 5V4s0-3 3-3 3 3 3 3v1h1v6H4V5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-progressive.png
new file mode 100644
index 00000000..817e599e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-progressive.svg
new file mode 100644
index 00000000..83814436
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="imageAdd">
+ <path id="mountains" d="M7 17l3-3 2 1 3-3 4 5zm-2-5v7h16V6h-8v6z"/>
+ <path id="lock" d="M6.5 5h3V4s0-1.5-1.5-1.5C6.5 2.56 6.5 4 6.5 4zM5 5V4s0-3 3-3 3 3 3 3v1h1v6H4V5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl.png
new file mode 100644
index 00000000..f0ddda4d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl.svg
new file mode 100644
index 00000000..e8ac3ed8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/imageLock-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="imageAdd">
+ <path id="mountains" d="M7 17l3-3 2 1 3-3 4 5zm-2-5v7h16V6h-8v6z"/>
+ <path id="lock" d="M6.5 5h3V4s0-1.5-1.5-1.5C6.5 2.56 6.5 4 6.5 4zM5 5V4s0-3 3-3 3 3 3 3v1h1v6H4V5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-invert.png
new file mode 100644
index 00000000..af944e7f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-invert.svg
new file mode 100644
index 00000000..04768db2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M10 8h9v2h-9V8zm0 3h9v2h-9v-2zm0 3h6v2h-6v-2zm11-8H3V4h18v2zm0 14H3v-2h18v2zM3 8v8l5-4-5-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-progressive.png
new file mode 100644
index 00000000..eec51498
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-progressive.svg
new file mode 100644
index 00000000..27348796
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M10 8h9v2h-9V8zm0 3h9v2h-9v-2zm0 3h6v2h-6v-2zm11-8H3V4h18v2zm0 14H3v-2h18v2zM3 8v8l5-4-5-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr.png
new file mode 100644
index 00000000..b7663ae6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr.svg
new file mode 100644
index 00000000..37606969
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10 8h9v2h-9V8zm0 3h9v2h-9v-2zm0 3h6v2h-6v-2zm11-8H3V4h18v2zm0 14H3v-2h18v2zM3 8v8l5-4-5-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-invert.png
new file mode 100644
index 00000000..f52ff9b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-invert.svg
new file mode 100644
index 00000000..c70f9915
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M14 8H5v2h9V8zm0 3H5v2h9v-2zm0 3H8v2h6v-2zM3 6h18V4H3v2zm0 14h18v-2H3v2zM21 8v8l-5-4 5-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-progressive.png
new file mode 100644
index 00000000..b6edc33b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-progressive.svg
new file mode 100644
index 00000000..992ed827
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M14 8H5v2h9V8zm0 3H5v2h9v-2zm0 3H8v2h6v-2zM3 6h18V4H3v2zm0 14h18v-2H3v2zM21 8v8l-5-4 5-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl.png
new file mode 100644
index 00000000..63b2750c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl.svg
new file mode 100644
index 00000000..9648f34f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/indent-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14 8H5v2h9V8zm0 3H5v2h9v-2zm0 3H8v2h6v-2zM3 6h18V4H3v2zm0 14h18v-2H3v2zM21 8v8l-5-4 5-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-invert.png
new file mode 100644
index 00000000..78532def
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-invert.svg
new file mode 100644
index 00000000..f3519f3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="info">
+ <path id="circled-i" d="M11.5 17a5.5 5.5 0 1 1 0-11 5.5 5.5 0 0 1 0 11zm0-12a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zm.5 5v4h1v1h-3v-1h1v-3h-1v-1zm-1-2h1v1h-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-progressive.png
new file mode 100644
index 00000000..9a0f5d7e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-progressive.svg
new file mode 100644
index 00000000..1e2ecf89
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="info">
+ <path id="circled-i" d="M11.5 17a5.5 5.5 0 1 1 0-11 5.5 5.5 0 0 1 0 11zm0-12a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zm.5 5v4h1v1h-3v-1h1v-3h-1v-1zm-1-2h1v1h-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info.png
new file mode 100644
index 00000000..0b4270d6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info.svg
new file mode 100644
index 00000000..72a9b4c6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/info.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="info">
+ <path id="circled-i" d="M11.5 17a5.5 5.5 0 1 1 0-11 5.5 5.5 0 0 1 0 11zm0-12a6.5 6.5 0 1 0 0 13 6.5 6.5 0 0 0 0-13zm.5 5v4h1v1h-3v-1h1v-3h-1v-1zm-1-2h1v1h-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-invert.png
new file mode 100644
index 00000000..12dfc565
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-invert.svg
new file mode 100644
index 00000000..7a522421
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="italic-a">
+ <path id="a" d="M14.667 6h-1.372l-7 12H8l2.333-4h4L15 18h1.667l-2-12zm-3.75 7l2.527-4.333.723 4.333h-3.25z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-progressive.png
new file mode 100644
index 00000000..f8c25a96
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-progressive.svg
new file mode 100644
index 00000000..2431aeb4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="italic-a">
+ <path id="a" d="M14.667 6h-1.372l-7 12H8l2.333-4h4L15 18h1.667l-2-12zm-3.75 7l2.527-4.333.723 4.333h-3.25z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a.png
new file mode 100644
index 00000000..2f5fd187
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a.svg
new file mode 100644
index 00000000..a3a11c68
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-a.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-a">
+ <path id="a" d="M14.667 6h-1.372l-7 12H8l2.333-4h4L15 18h1.667l-2-12zm-3.75 7l2.527-4.333.723 4.333h-3.25z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-invert.png
new file mode 100644
index 00000000..567b290f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-invert.svg
new file mode 100644
index 00000000..4d68c385
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="italic-arab-keheh-jeem">
+ <path id="arab-keheh-jeem" d="M18.125 5.844c-1.695.555-3.297 1.162-4.594 1.938-.49.3-.77.712-.87 1.125a1.26 1.26 0 0 0 .065.78c.19.406.54.575.844.814l.093-.12.53.627c.14.165.345.514.47.94.138.462.08.724 0 1.124h-3.44c-.34 0-.592.007-.766-.02-.34-.053-.256-.21-.234-.34.33-.127.56-.173.934-.14.29-.495.593-.886.906-1.314-.98.037-1.877.015-2.687-.094-.346-.046-.698-.185-1.094-.155-.36.026-.77.24-1.03.72-.25.447-.436.838-.66 1.28l.75-.47c.23-.14.486-.226.72-.218.158.004.276.053.407.093-.234.204-.51.4-.72.56-.3.26-.704.69-.908 1-.403.617-.694 1.086-.875 1.78-.18.69.003 1.34.468 1.75.426.38.846.52 1.28.566.65.064 1.206.092 2-.19.658-.23 1.022-.552 1.5-.97-.882.11-1.816.09-2.53.033-.87-.07-1.268-.386-1.47-.596-.27-.283-.306-.64-.155-1.22a1.44 1.44 0 0 1 .25-.53c.17-.228.363-.435.593-.656.45-.436 1.01-.737 1.46-.94-.042.207-.104.444-.052.69.05.23.25.38.44.47.26.12.506.152.69.153 1.42.01 2.86 0 4.28 0 .246 0 .45-.163.593-.375.14-.21.25-.48.343-.845.13-.5.094-1.062-.094-1.625a4.812 4.812 0 0 0-.72-1.406c-.336-.444-.675-.83-1-1.22 1.256-.815 2.715-1.24 3.97-1.688.12-.452.222-.926.31-1.313zm-9.47 8.438c-.26.394-.583.69-.874 1 .38.286.75.556 1.1.813.336-.303.627-.674.876-.97-.39-.267-.77-.587-1.093-.843z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-progressive.png
new file mode 100644
index 00000000..3c3ed9fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-progressive.svg
new file mode 100644
index 00000000..8c23b305
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="italic-arab-keheh-jeem">
+ <path id="arab-keheh-jeem" d="M18.125 5.844c-1.695.555-3.297 1.162-4.594 1.938-.49.3-.77.712-.87 1.125a1.26 1.26 0 0 0 .065.78c.19.406.54.575.844.814l.093-.12.53.627c.14.165.345.514.47.94.138.462.08.724 0 1.124h-3.44c-.34 0-.592.007-.766-.02-.34-.053-.256-.21-.234-.34.33-.127.56-.173.934-.14.29-.495.593-.886.906-1.314-.98.037-1.877.015-2.687-.094-.346-.046-.698-.185-1.094-.155-.36.026-.77.24-1.03.72-.25.447-.436.838-.66 1.28l.75-.47c.23-.14.486-.226.72-.218.158.004.276.053.407.093-.234.204-.51.4-.72.56-.3.26-.704.69-.908 1-.403.617-.694 1.086-.875 1.78-.18.69.003 1.34.468 1.75.426.38.846.52 1.28.566.65.064 1.206.092 2-.19.658-.23 1.022-.552 1.5-.97-.882.11-1.816.09-2.53.033-.87-.07-1.268-.386-1.47-.596-.27-.283-.306-.64-.155-1.22a1.44 1.44 0 0 1 .25-.53c.17-.228.363-.435.593-.656.45-.436 1.01-.737 1.46-.94-.042.207-.104.444-.052.69.05.23.25.38.44.47.26.12.506.152.69.153 1.42.01 2.86 0 4.28 0 .246 0 .45-.163.593-.375.14-.21.25-.48.343-.845.13-.5.094-1.062-.094-1.625a4.812 4.812 0 0 0-.72-1.406c-.336-.444-.675-.83-1-1.22 1.256-.815 2.715-1.24 3.97-1.688.12-.452.222-.926.31-1.313zm-9.47 8.438c-.26.394-.583.69-.874 1 .38.286.75.556 1.1.813.336-.303.627-.674.876-.97-.39-.267-.77-.587-1.093-.843z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem.png
new file mode 100644
index 00000000..c8e03eea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem.svg
new file mode 100644
index 00000000..11b1458e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-keheh-jeem.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-arab-keheh-jeem">
+ <path id="arab-keheh-jeem" d="M18.125 5.844c-1.695.555-3.297 1.162-4.594 1.938-.49.3-.77.712-.87 1.125a1.26 1.26 0 0 0 .065.78c.19.406.54.575.844.814l.093-.12.53.627c.14.165.345.514.47.94.138.462.08.724 0 1.124h-3.44c-.34 0-.592.007-.766-.02-.34-.053-.256-.21-.234-.34.33-.127.56-.173.934-.14.29-.495.593-.886.906-1.314-.98.037-1.877.015-2.687-.094-.346-.046-.698-.185-1.094-.155-.36.026-.77.24-1.03.72-.25.447-.436.838-.66 1.28l.75-.47c.23-.14.486-.226.72-.218.158.004.276.053.407.093-.234.204-.51.4-.72.56-.3.26-.704.69-.908 1-.403.617-.694 1.086-.875 1.78-.18.69.003 1.34.468 1.75.426.38.846.52 1.28.566.65.064 1.206.092 2-.19.658-.23 1.022-.552 1.5-.97-.882.11-1.816.09-2.53.033-.87-.07-1.268-.386-1.47-.596-.27-.283-.306-.64-.155-1.22a1.44 1.44 0 0 1 .25-.53c.17-.228.363-.435.593-.656.45-.436 1.01-.737 1.46-.94-.042.207-.104.444-.052.69.05.23.25.38.44.47.26.12.506.152.69.153 1.42.01 2.86 0 4.28 0 .246 0 .45-.163.593-.375.14-.21.25-.48.343-.845.13-.5.094-1.062-.094-1.625a4.812 4.812 0 0 0-.72-1.406c-.336-.444-.675-.83-1-1.22 1.256-.815 2.715-1.24 3.97-1.688.12-.452.222-.926.31-1.313zm-9.47 8.438c-.26.394-.583.69-.874 1 .38.286.75.556 1.1.813.336-.303.627-.674.876-.97-.39-.267-.77-.587-1.093-.843z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-invert.png
new file mode 100644
index 00000000..03989d47
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-invert.svg
new file mode 100644
index 00000000..799a7859
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="italic-arab-meem">
+ <path id="arab-meem" d="M16 9.73l-.93 2.19h-4.663c-.48 0-.857.12-1.135.366l-.06.11c-.185 2.016-.503 3.558-.956 4.627a8.31 8.31 0 0 1-1.082 1.833c-.177.226-.22.186-.126-.12l.142-.503.17-.67.234-.87.002-.008.202-1.045.258-1.41.353-1.907c.19-.312.42-.638.692-.98a24.1 24.1 0 0 1 .94-1.09c.13-.092.697-.18 1.705-.266 1.05-.086 1.64-.183 1.765-.293l.065-.128c.01-.11-.01-.24-.052-.394a2.403 2.403 0 0 0-.232-.522c-.22-.428-.438-.64-.654-.64-.294 0-.915.268-1.864.805-.36.208-.378.125-.05-.247 1.555-1.71 2.705-2.566 3.45-2.566.38 0 .67.13.86.394.134.195.25.6.343 1.21l.202 1.2c.105.586.24.895.408.925"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-progressive.png
new file mode 100644
index 00000000..7179cb68
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-progressive.svg
new file mode 100644
index 00000000..b22bd456
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="italic-arab-meem">
+ <path id="arab-meem" d="M16 9.73l-.93 2.19h-4.663c-.48 0-.857.12-1.135.366l-.06.11c-.185 2.016-.503 3.558-.956 4.627a8.31 8.31 0 0 1-1.082 1.833c-.177.226-.22.186-.126-.12l.142-.503.17-.67.234-.87.002-.008.202-1.045.258-1.41.353-1.907c.19-.312.42-.638.692-.98a24.1 24.1 0 0 1 .94-1.09c.13-.092.697-.18 1.705-.266 1.05-.086 1.64-.183 1.765-.293l.065-.128c.01-.11-.01-.24-.052-.394a2.403 2.403 0 0 0-.232-.522c-.22-.428-.438-.64-.654-.64-.294 0-.915.268-1.864.805-.36.208-.378.125-.05-.247 1.555-1.71 2.705-2.566 3.45-2.566.38 0 .67.13.86.394.134.195.25.6.343 1.21l.202 1.2c.105.586.24.895.408.925"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem.png
new file mode 100644
index 00000000..409a4165
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem.svg
new file mode 100644
index 00000000..f15586e0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-arab-meem.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-arab-meem">
+ <path id="arab-meem" d="M16 9.73l-.93 2.19h-4.663c-.48 0-.857.12-1.135.366l-.06.11c-.185 2.016-.503 3.558-.956 4.627a8.31 8.31 0 0 1-1.082 1.833c-.177.226-.22.186-.126-.12l.142-.503.17-.67.234-.87.002-.008.202-1.045.258-1.41.353-1.907c.19-.312.42-.638.692-.98a24.1 24.1 0 0 1 .94-1.09c.13-.092.697-.18 1.705-.266 1.05-.086 1.64-.183 1.765-.293l.065-.128c.01-.11-.01-.24-.052-.394a2.403 2.403 0 0 0-.232-.522c-.22-.428-.438-.64-.654-.64-.294 0-.915.268-1.864.805-.36.208-.378.125-.05-.247 1.555-1.71 2.705-2.566 3.45-2.566.38 0 .67.13.86.394.134.195.25.6.343 1.21l.202 1.2c.105.586.24.895.408.925"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-invert.png
new file mode 100644
index 00000000..75dc339d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-invert.svg
new file mode 100644
index 00000000..6b56e371
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="italic-armn-sha">
+ <path id="armn-sha" d="M11.564 7.678a3.073 3.073 0 0 0-.93-.268c-.35-.047-.75-.07-1.197-.07h-1.11L8.587 6h1.723c.558 0 1.042.032 1.45.095.416.063.794.173 1.136.33l4.483 2.033-.33 1.67-2.625-1.165a1.867 1.867 0 0 0-.433-.134 2.45 2.45 0 0 0-.576-.06 4.88 4.88 0 0 0-1.663.28c-.526.19-1 .46-1.427.812-.42.35-.776.78-1.07 1.283a5.48 5.48 0 0 0-.63 1.71c-.24 1.255-.15 2.21.27 2.87.424.65 1.19.976 2.292.976.55 0 1.044-.08 1.48-.236a3.488 3.488 0 0 0 1.135-.66c.325-.29.59-.634.795-1.034.21-.4.363-.84.458-1.322l.11-.56h1.6l-.12.59a5.925 5.925 0 0 1-.676 1.844 5.19 5.19 0 0 1-1.214 1.423c-.488.395-1.053.7-1.694.923a6.573 6.573 0 0 1-2.106.324c-.767 0-1.434-.114-2-.34-.568-.226-1.025-.554-1.372-.985-.347-.437-.573-.97-.678-1.608-.105-.64-.078-1.366.08-2.186.125-.66.346-1.274.66-1.836A6.332 6.332 0 0 1 8.792 9.54a5.955 5.955 0 0 1 1.496-1.072 5.87 5.87 0 0 1 1.732-.57l-.465-.23"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-progressive.png
new file mode 100644
index 00000000..db31afa8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-progressive.svg
new file mode 100644
index 00000000..50ee0467
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="italic-armn-sha">
+ <path id="armn-sha" d="M11.564 7.678a3.073 3.073 0 0 0-.93-.268c-.35-.047-.75-.07-1.197-.07h-1.11L8.587 6h1.723c.558 0 1.042.032 1.45.095.416.063.794.173 1.136.33l4.483 2.033-.33 1.67-2.625-1.165a1.867 1.867 0 0 0-.433-.134 2.45 2.45 0 0 0-.576-.06 4.88 4.88 0 0 0-1.663.28c-.526.19-1 .46-1.427.812-.42.35-.776.78-1.07 1.283a5.48 5.48 0 0 0-.63 1.71c-.24 1.255-.15 2.21.27 2.87.424.65 1.19.976 2.292.976.55 0 1.044-.08 1.48-.236a3.488 3.488 0 0 0 1.135-.66c.325-.29.59-.634.795-1.034.21-.4.363-.84.458-1.322l.11-.56h1.6l-.12.59a5.925 5.925 0 0 1-.676 1.844 5.19 5.19 0 0 1-1.214 1.423c-.488.395-1.053.7-1.694.923a6.573 6.573 0 0 1-2.106.324c-.767 0-1.434-.114-2-.34-.568-.226-1.025-.554-1.372-.985-.347-.437-.573-.97-.678-1.608-.105-.64-.078-1.366.08-2.186.125-.66.346-1.274.66-1.836A6.332 6.332 0 0 1 8.792 9.54a5.955 5.955 0 0 1 1.496-1.072 5.87 5.87 0 0 1 1.732-.57l-.465-.23"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha.png
new file mode 100644
index 00000000..2dd80f7f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha.svg
new file mode 100644
index 00000000..c32ff494
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-armn-sha.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-armn-sha">
+ <path id="armn-sha" d="M11.564 7.678a3.073 3.073 0 0 0-.93-.268c-.35-.047-.75-.07-1.197-.07h-1.11L8.587 6h1.723c.558 0 1.042.032 1.45.095.416.063.794.173 1.136.33l4.483 2.033-.33 1.67-2.625-1.165a1.867 1.867 0 0 0-.433-.134 2.45 2.45 0 0 0-.576-.06 4.88 4.88 0 0 0-1.663.28c-.526.19-1 .46-1.427.812-.42.35-.776.78-1.07 1.283a5.48 5.48 0 0 0-.63 1.71c-.24 1.255-.15 2.21.27 2.87.424.65 1.19.976 2.292.976.55 0 1.044-.08 1.48-.236a3.488 3.488 0 0 0 1.135-.66c.325-.29.59-.634.795-1.034.21-.4.363-.84.458-1.322l.11-.56h1.6l-.12.59a5.925 5.925 0 0 1-.676 1.844 5.19 5.19 0 0 1-1.214 1.423c-.488.395-1.053.7-1.694.923a6.573 6.573 0 0 1-2.106.324c-.767 0-1.434-.114-2-.34-.568-.226-1.025-.554-1.372-.985-.347-.437-.573-.97-.678-1.608-.105-.64-.078-1.366.08-2.186.125-.66.346-1.274.66-1.836A6.332 6.332 0 0 1 8.792 9.54a5.955 5.955 0 0 1 1.496-1.072 5.87 5.87 0 0 1 1.732-.57l-.465-.23"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-invert.png
new file mode 100644
index 00000000..a1656575
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-invert.svg
new file mode 100644
index 00000000..01afe88f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="italic-c">
+ <path id="c" d="M15.008 13.718l1.48.214c-.467 1.34-1.15 2.354-2.045 3.04a4.835 4.835 0 0 1-3.015 1.03c-1.36 0-2.438-.43-3.237-1.29C7.4 15.85 7 14.618 7 13.012c0-2.09.606-3.817 1.817-5.184C9.897 6.61 11.237 6 12.84 6c1.186 0 2.145.33 2.878.99.738.66 1.165 1.546 1.282 2.66l-1.397.135c-.148-.84-.453-1.464-.916-1.876-.458-.42-1.05-.63-1.78-.63-1.368 0-2.475.63-3.32 1.89-.733 1.087-1.1 2.377-1.1 3.87 0 1.194.283 2.104.848 2.732.565.628 1.3.942 2.206.942.78 0 1.48-.26 2.1-.785.63-.52 1.08-1.26 1.37-2.216"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-progressive.png
new file mode 100644
index 00000000..5b360592
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-progressive.svg
new file mode 100644
index 00000000..03aa494a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="italic-c">
+ <path id="c" d="M15.008 13.718l1.48.214c-.467 1.34-1.15 2.354-2.045 3.04a4.835 4.835 0 0 1-3.015 1.03c-1.36 0-2.438-.43-3.237-1.29C7.4 15.85 7 14.618 7 13.012c0-2.09.606-3.817 1.817-5.184C9.897 6.61 11.237 6 12.84 6c1.186 0 2.145.33 2.878.99.738.66 1.165 1.546 1.282 2.66l-1.397.135c-.148-.84-.453-1.464-.916-1.876-.458-.42-1.05-.63-1.78-.63-1.368 0-2.475.63-3.32 1.89-.733 1.087-1.1 2.377-1.1 3.87 0 1.194.283 2.104.848 2.732.565.628 1.3.942 2.206.942.78 0 1.48-.26 2.1-.785.63-.52 1.08-1.26 1.37-2.216"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c.png
new file mode 100644
index 00000000..dc70ded4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c.svg
new file mode 100644
index 00000000..b85eb029
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-c.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-c">
+ <path id="c" d="M15.008 13.718l1.48.214c-.467 1.34-1.15 2.354-2.045 3.04a4.835 4.835 0 0 1-3.015 1.03c-1.36 0-2.438-.43-3.237-1.29C7.4 15.85 7 14.618 7 13.012c0-2.09.606-3.817 1.817-5.184C9.897 6.61 11.237 6 12.84 6c1.186 0 2.145.33 2.878.99.738.66 1.165 1.546 1.282 2.66l-1.397.135c-.148-.84-.453-1.464-.916-1.876-.458-.42-1.05-.63-1.78-.63-1.368 0-2.475.63-3.32 1.89-.733 1.087-1.1 2.377-1.1 3.87 0 1.194.283 2.104.848 2.732.565.628 1.3.942 2.206.942.78 0 1.48-.26 2.1-.785.63-.52 1.08-1.26 1.37-2.216"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-invert.png
new file mode 100644
index 00000000..b656d1c5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-invert.svg
new file mode 100644
index 00000000..dcd0d948
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="italic-d">
+ <path id="d" d="M7 18L9.462 6h3.557c.85 0 1.5.063 1.95.188.642.17 1.192.472 1.65.91.454.43.8.97 1.03 1.62.23.65.344 1.378.344 2.186 0 .966-.146 1.847-.436 2.644-.284.79-.66 1.49-1.127 2.095-.46.6-.946 1.072-1.455 1.416-.504.33-1.1.582-1.794.75-.525.122-1.17.19-1.94.19H7m1.86-1.36h1.866c.842 0 1.59-.08 2.245-.24a3.26 3.26 0 0 0 1.05-.436 4.19 4.19 0 0 0 1.04-.975 6.652 6.652 0 0 0 .975-1.825c.247-.687.37-1.467.37-2.34 0-.97-.166-1.716-.5-2.235-.332-.522-.755-.87-1.27-1.04-.38-.124-.974-.186-1.78-.186H11L9.095 16.64"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-progressive.png
new file mode 100644
index 00000000..73e45450
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-progressive.svg
new file mode 100644
index 00000000..ff61b371
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="italic-d">
+ <path id="d" d="M7 18L9.462 6h3.557c.85 0 1.5.063 1.95.188.642.17 1.192.472 1.65.91.454.43.8.97 1.03 1.62.23.65.344 1.378.344 2.186 0 .966-.146 1.847-.436 2.644-.284.79-.66 1.49-1.127 2.095-.46.6-.946 1.072-1.455 1.416-.504.33-1.1.582-1.794.75-.525.122-1.17.19-1.94.19H7m1.86-1.36h1.866c.842 0 1.59-.08 2.245-.24a3.26 3.26 0 0 0 1.05-.436 4.19 4.19 0 0 0 1.04-.975 6.652 6.652 0 0 0 .975-1.825c.247-.687.37-1.467.37-2.34 0-.97-.166-1.716-.5-2.235-.332-.522-.755-.87-1.27-1.04-.38-.124-.974-.186-1.78-.186H11L9.095 16.64"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d.png
new file mode 100644
index 00000000..cd5ac9d4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d.svg
new file mode 100644
index 00000000..dbc1d40f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-d.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-d">
+ <path id="d" d="M7 18L9.462 6h3.557c.85 0 1.5.063 1.95.188.642.17 1.192.472 1.65.91.454.43.8.97 1.03 1.62.23.65.344 1.378.344 2.186 0 .966-.146 1.847-.436 2.644-.284.79-.66 1.49-1.127 2.095-.46.6-.946 1.072-1.455 1.416-.504.33-1.1.582-1.794.75-.525.122-1.17.19-1.94.19H7m1.86-1.36h1.866c.842 0 1.59-.08 2.245-.24a3.26 3.26 0 0 0 1.05-.436 4.19 4.19 0 0 0 1.04-.975 6.652 6.652 0 0 0 .975-1.825c.247-.687.37-1.467.37-2.34 0-.97-.166-1.716-.5-2.235-.332-.522-.755-.87-1.27-1.04-.38-.124-.974-.186-1.78-.186H11L9.095 16.64"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-invert.png
new file mode 100644
index 00000000..2e0918d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-invert.svg
new file mode 100644
index 00000000..f91db71a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="italic-e">
+ <path id="e" d="M7 18L9.474 6H18l-.282 1.367H10.77L10.02 11h6.09l-.28 1.367H9.74l-.88 4.273h7.44L16.018 18H7"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-progressive.png
new file mode 100644
index 00000000..0444ac29
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-progressive.svg
new file mode 100644
index 00000000..c5ca7b12
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="italic-e">
+ <path id="e" d="M7 18L9.474 6H18l-.282 1.367H10.77L10.02 11h6.09l-.28 1.367H9.74l-.88 4.273h7.44L16.018 18H7"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e.png
new file mode 100644
index 00000000..bb51c22c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e.svg
new file mode 100644
index 00000000..f3851498
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-e.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-e">
+ <path id="e" d="M7 18L9.474 6H18l-.282 1.367H10.77L10.02 11h6.09l-.28 1.367H9.74l-.88 4.273h7.44L16.018 18H7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-invert.png
new file mode 100644
index 00000000..b0e5b2c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-invert.svg
new file mode 100644
index 00000000..fea68a5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="italic-geor-kan">
+ <path id="geor-kan" d="M15.057 14.663C14.617 16.888 13.223 18 10.88 18 8.96 18 8 17.213 8 15.64c0-.298.036-.624.108-.977.083-.43.245-.836.488-1.217l1.24.605-.206.62c-.055.26-.083.497-.083.71 0 .97.52 1.46 1.564 1.46 1.31 0 2.108-.724 2.39-2.17l.058-.33a3.17 3.17 0 0 0 .066-.615c0-.927-.546-1.39-1.64-1.39H10.87l.247-1.26h1.118c1.203-.004 1.91-.55 2.12-1.64.04-.18.057-.355.057-.52 0-1.144-.9-1.715-2.696-1.715L11.94 6C14.646 6 16 6.877 16 8.627c0 .248-.027.516-.082.803-.204 1.092-1.05 1.824-2.54 2.194l-.033.166c1.23.2 1.845.823 1.845 1.872 0 .21-.025.433-.074.67l-.058.332"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-progressive.png
new file mode 100644
index 00000000..ff933e2d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-progressive.svg
new file mode 100644
index 00000000..bacc38cc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="italic-geor-kan">
+ <path id="geor-kan" d="M15.057 14.663C14.617 16.888 13.223 18 10.88 18 8.96 18 8 17.213 8 15.64c0-.298.036-.624.108-.977.083-.43.245-.836.488-1.217l1.24.605-.206.62c-.055.26-.083.497-.083.71 0 .97.52 1.46 1.564 1.46 1.31 0 2.108-.724 2.39-2.17l.058-.33a3.17 3.17 0 0 0 .066-.615c0-.927-.546-1.39-1.64-1.39H10.87l.247-1.26h1.118c1.203-.004 1.91-.55 2.12-1.64.04-.18.057-.355.057-.52 0-1.144-.9-1.715-2.696-1.715L11.94 6C14.646 6 16 6.877 16 8.627c0 .248-.027.516-.082.803-.204 1.092-1.05 1.824-2.54 2.194l-.033.166c1.23.2 1.845.823 1.845 1.872 0 .21-.025.433-.074.67l-.058.332"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan.png
new file mode 100644
index 00000000..9750f428
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan.svg
new file mode 100644
index 00000000..9a54880e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-geor-kan.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-geor-kan">
+ <path id="geor-kan" d="M15.057 14.663C14.617 16.888 13.223 18 10.88 18 8.96 18 8 17.213 8 15.64c0-.298.036-.624.108-.977.083-.43.245-.836.488-1.217l1.24.605-.206.62c-.055.26-.083.497-.083.71 0 .97.52 1.46 1.564 1.46 1.31 0 2.108-.724 2.39-2.17l.058-.33a3.17 3.17 0 0 0 .066-.615c0-.927-.546-1.39-1.64-1.39H10.87l.247-1.26h1.118c1.203-.004 1.91-.55 2.12-1.64.04-.18.057-.355.057-.52 0-1.144-.9-1.715-2.696-1.715L11.94 6C14.646 6 16 6.877 16 8.627c0 .248-.027.516-.082.803-.204 1.092-1.05 1.824-2.54 2.194l-.033.166c1.23.2 1.845.823 1.845 1.872 0 .21-.025.433-.074.67l-.058.332"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-invert.png
new file mode 100644
index 00000000..cc8fee4e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-invert.svg
new file mode 100644
index 00000000..3919051e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="italic-i">
+ <path id="i" d="M12.5 18l.25-.995h-1.5l2.508-10.037h1.5L15.5 6h-5l-.242.968h1.5l-2.51 10.037h-1.5L7.5 18z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-progressive.png
new file mode 100644
index 00000000..5c78d59c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-progressive.svg
new file mode 100644
index 00000000..f71f6f7b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="italic-i">
+ <path id="i" d="M12.5 18l.25-.995h-1.5l2.508-10.037h1.5L15.5 6h-5l-.242.968h1.5l-2.51 10.037h-1.5L7.5 18z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i.png
new file mode 100644
index 00000000..a37620b7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i.svg
new file mode 100644
index 00000000..e670e9bf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-i.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-i">
+ <path id="i" d="M12.5 18l.25-.995h-1.5l2.508-10.037h1.5L15.5 6h-5l-.242.968h1.5l-2.51 10.037h-1.5L7.5 18z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-invert.png
new file mode 100644
index 00000000..5387c369
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-invert.svg
new file mode 100644
index 00000000..b6e87b43
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="italic-k">
+ <path id="k" d="M12.018 10.652L17 6h-2l-5.31 5.234L11 6H9.5l-3 12H8l1.173-4.693 1.54-1.438C11 16 14 18 14 18h2s-4-2-3.982-7.348z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-progressive.png
new file mode 100644
index 00000000..a2e715fc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-progressive.svg
new file mode 100644
index 00000000..7494e8f8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="italic-k">
+ <path id="k" d="M12.018 10.652L17 6h-2l-5.31 5.234L11 6H9.5l-3 12H8l1.173-4.693 1.54-1.438C11 16 14 18 14 18h2s-4-2-3.982-7.348z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k.png
new file mode 100644
index 00000000..9b156fd2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k.svg
new file mode 100644
index 00000000..38bcd73a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-k.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-k">
+ <path id="k" d="M12.018 10.652L17 6h-2l-5.31 5.234L11 6H9.5l-3 12H8l1.173-4.693 1.54-1.438C11 16 14 18 14 18h2s-4-2-3.982-7.348z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-invert.png
new file mode 100644
index 00000000..42b674e5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-invert.svg
new file mode 100644
index 00000000..ed2fe672
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="italic-s">
+ <path id="s" d="M16.474 6.59l-.302 1.525a7.36 7.36 0 0 0-1.557-.628 5.432 5.432 0 0 0-1.487-.217c-.935 0-1.68.204-2.23.612-.554.408-.83.95-.83 1.627 0 .37.1.65.302.86.207.19.733.4 1.58.63l.937.23c1.06.274 1.795.622 2.208 1.046.413.42.62 1.007.62 1.766 0 1.167-.46 2.117-1.38 2.85-.913.734-2.12 1.1-3.617 1.1-.615 0-1.232-.06-1.852-.185-.62-.12-1.242-.3-1.867-.55l.31-1.61a7.613 7.613 0 0 0 1.72.805c.58.18 1.155.27 1.73.27.976 0 1.76-.216 2.347-.65.59-.434.883-1 .883-1.697 0-.465-.12-.816-.354-1.054-.233-.242-.737-.46-1.512-.657l-.937-.24c-1.07-.28-1.8-.6-2.19-.964-.39-.368-.584-.88-.584-1.535 0-1.152.442-2.094 1.325-2.828.89-.74 2.043-1.108 3.463-1.108.555 0 1.1.05 1.644.146.542.1 1.085.245 1.627.442"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-progressive.png
new file mode 100644
index 00000000..d5173526
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-progressive.svg
new file mode 100644
index 00000000..0eeeb500
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="italic-s">
+ <path id="s" d="M16.474 6.59l-.302 1.525a7.36 7.36 0 0 0-1.557-.628 5.432 5.432 0 0 0-1.487-.217c-.935 0-1.68.204-2.23.612-.554.408-.83.95-.83 1.627 0 .37.1.65.302.86.207.19.733.4 1.58.63l.937.23c1.06.274 1.795.622 2.208 1.046.413.42.62 1.007.62 1.766 0 1.167-.46 2.117-1.38 2.85-.913.734-2.12 1.1-3.617 1.1-.615 0-1.232-.06-1.852-.185-.62-.12-1.242-.3-1.867-.55l.31-1.61a7.613 7.613 0 0 0 1.72.805c.58.18 1.155.27 1.73.27.976 0 1.76-.216 2.347-.65.59-.434.883-1 .883-1.697 0-.465-.12-.816-.354-1.054-.233-.242-.737-.46-1.512-.657l-.937-.24c-1.07-.28-1.8-.6-2.19-.964-.39-.368-.584-.88-.584-1.535 0-1.152.442-2.094 1.325-2.828.89-.74 2.043-1.108 3.463-1.108.555 0 1.1.05 1.644.146.542.1 1.085.245 1.627.442"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s.png
new file mode 100644
index 00000000..3213d6d8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s.svg
new file mode 100644
index 00000000..b3fb3403
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/italic-s.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="italic-s">
+ <path id="s" d="M16.474 6.59l-.302 1.525a7.36 7.36 0 0 0-1.557-.628 5.432 5.432 0 0 0-1.487-.217c-.935 0-1.68.204-2.23.612-.554.408-.83.95-.83 1.627 0 .37.1.65.302.86.207.19.733.4 1.58.63l.937.23c1.06.274 1.795.622 2.208 1.046.413.42.62 1.007.62 1.766 0 1.167-.46 2.117-1.38 2.85-.913.734-2.12 1.1-3.617 1.1-.615 0-1.232-.06-1.852-.185-.62-.12-1.242-.3-1.867-.55l.31-1.61a7.613 7.613 0 0 0 1.72.805c.58.18 1.155.27 1.73.27.976 0 1.76-.216 2.347-.65.59-.434.883-1 .883-1.697 0-.465-.12-.816-.354-1.054-.233-.242-.737-.46-1.512-.657l-.937-.24c-1.07-.28-1.8-.6-2.19-.964-.39-.368-.584-.88-.584-1.535 0-1.152.442-2.094 1.325-2.828.89-.74 2.043-1.108 3.463-1.108.555 0 1.1.05 1.644.146.542.1 1.085.245 1.627.442"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-invert.png
new file mode 100644
index 00000000..bc2e9cc6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-invert.svg
new file mode 100644
index 00000000..370d0a37
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M16 8V7h-6v1h6zm-2 2V9h-4v1h4zM6 4h1v16H6V4zm2 0h10v13c0 1.7-1.3 3-3 3H8V4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-progressive.png
new file mode 100644
index 00000000..19f17bdb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-progressive.svg
new file mode 100644
index 00000000..baf8a4a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M16 8V7h-6v1h6zm-2 2V9h-4v1h4zM6 4h1v16H6V4zm2 0h10v13c0 1.7-1.3 3-3 3H8V4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr.png
new file mode 100644
index 00000000..2af4eb0e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr.svg
new file mode 100644
index 00000000..8a83e417
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 8V7h-6v1h6zm-2 2V9h-4v1h4zM6 4h1v16H6V4zm2 0h10v13c0 1.7-1.3 3-3 3H8V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-invert.png
new file mode 100644
index 00000000..60b5f473
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-invert.svg
new file mode 100644
index 00000000..46602859
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M8 8V7h6v1H8zm2 2V9h4v1h-4zm8-6h-1v16h1V4zm-2 0H6v13c0 1.7 1.3 3 3 3h7V4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-progressive.png
new file mode 100644
index 00000000..b16badc6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-progressive.svg
new file mode 100644
index 00000000..17ccb82c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M8 8V7h6v1H8zm2 2V9h4v1h-4zm8-6h-1v16h1V4zm-2 0H6v13c0 1.7 1.3 3 3 3h7V4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl.png
new file mode 100644
index 00000000..033ede13
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl.svg
new file mode 100644
index 00000000..2a07a44a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/journal-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M8 8V7h6v1H8zm2 2V9h4v1h-4zm8-6h-1v16h1V4zm-2 0H6v13c0 1.7 1.3 3 3 3h7V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-invert.png
new file mode 100644
index 00000000..265da142
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-invert.svg
new file mode 100644
index 00000000..4b00ee7f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M14.5 4C11.5 4 9 6.5 9 9.5c0 1 .3 1.9.7 2.8L4 18v2h4v-2h2v-2h2l1.2-1.2c.4.1.9.2 1.3.2 3 0 5.5-2.5 5.5-5.5S17.5 4 14.5 4zM16 9c-.8 0-1.5-.7-1.5-1.5S15.2 6 16 6s1.5.7 1.5 1.5S16.8 9 16 9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-progressive.png
new file mode 100644
index 00000000..37b17884
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-progressive.svg
new file mode 100644
index 00000000..e079ac66
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M14.5 4C11.5 4 9 6.5 9 9.5c0 1 .3 1.9.7 2.8L4 18v2h4v-2h2v-2h2l1.2-1.2c.4.1.9.2 1.3.2 3 0 5.5-2.5 5.5-5.5S17.5 4 14.5 4zM16 9c-.8 0-1.5-.7-1.5-1.5S15.2 6 16 6s1.5.7 1.5 1.5S16.8 9 16 9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr.png
new file mode 100644
index 00000000..9a4dca83
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr.svg
new file mode 100644
index 00000000..fc0d3c34
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14.5 4C11.5 4 9 6.5 9 9.5c0 1 .3 1.9.7 2.8L4 18v2h4v-2h2v-2h2l1.2-1.2c.4.1.9.2 1.3.2 3 0 5.5-2.5 5.5-5.5S17.5 4 14.5 4zM16 9c-.8 0-1.5-.7-1.5-1.5S15.2 6 16 6s1.5.7 1.5 1.5S16.8 9 16 9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-invert.png
new file mode 100644
index 00000000..a5f29046
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-invert.svg
new file mode 100644
index 00000000..1777cec0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M9.5 4c3 0 5.5 2.5 5.5 5.5 0 1-.3 1.9-.7 2.8L20 18v2h-4v-2h-2v-2h-2l-1.2-1.2c-.4.1-.9.2-1.3.2-3 0-5.5-2.5-5.5-5.5S6.5 4 9.5 4zM8 9c.8 0 1.5-.7 1.5-1.5S8.8 6 8 6s-1.5.7-1.5 1.5S7.2 9 8 9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-progressive.png
new file mode 100644
index 00000000..69a032a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-progressive.svg
new file mode 100644
index 00000000..d070568e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M9.5 4c3 0 5.5 2.5 5.5 5.5 0 1-.3 1.9-.7 2.8L20 18v2h-4v-2h-2v-2h-2l-1.2-1.2c-.4.1-.9.2-1.3.2-3 0-5.5-2.5-5.5-5.5S6.5 4 9.5 4zM8 9c.8 0 1.5-.7 1.5-1.5S8.8 6 8 6s-1.5.7-1.5 1.5S7.2 9 8 9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl.png
new file mode 100644
index 00000000..f49e1125
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl.svg
new file mode 100644
index 00000000..6dedfe83
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/key-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9.5 4c3 0 5.5 2.5 5.5 5.5 0 1-.3 1.9-.7 2.8L20 18v2h-4v-2h-2v-2h-2l-1.2-1.2c-.4.1-.9.2-1.3.2-3 0-5.5-2.5-5.5-5.5S6.5 4 9.5 4zM8 9c.8 0 1.5-.7 1.5-1.5S8.8 6 8 6s-1.5.7-1.5 1.5S7.2 9 8 9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-invert.png
new file mode 100644
index 00000000..d7d1a0be
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-invert.svg
new file mode 100644
index 00000000..2230bf5d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M3 7v9c0 1.7 1.3 3 3 3h15V7H3zm8 2h2v2h-2V9zm0 3h2v2h-2v-2zM8 9h2v2H8V9zm0 3h2v2H8v-2zm-1 5H6c-.6 0-1-.4-1-1v-1h2v2zm0-3H5v-2h2v2zm0-3H5V9h2v2zm9 6H8v-2h8v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2zm3 6h-2v-2h2v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-progressive.png
new file mode 100644
index 00000000..49a0c4a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-progressive.svg
new file mode 100644
index 00000000..25f22c70
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M3 7v9c0 1.7 1.3 3 3 3h15V7H3zm8 2h2v2h-2V9zm0 3h2v2h-2v-2zM8 9h2v2H8V9zm0 3h2v2H8v-2zm-1 5H6c-.6 0-1-.4-1-1v-1h2v2zm0-3H5v-2h2v2zm0-3H5V9h2v2zm9 6H8v-2h8v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2zm3 6h-2v-2h2v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr.png
new file mode 100644
index 00000000..886d37a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr.svg
new file mode 100644
index 00000000..c4c442ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 7v9c0 1.7 1.3 3 3 3h15V7H3zm8 2h2v2h-2V9zm0 3h2v2h-2v-2zM8 9h2v2H8V9zm0 3h2v2H8v-2zm-1 5H6c-.6 0-1-.4-1-1v-1h2v2zm0-3H5v-2h2v2zm0-3H5V9h2v2zm9 6H8v-2h8v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2zm3 6h-2v-2h2v2zm0-3h-2v-2h2v2zm0-3h-2V9h2v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-invert.png
new file mode 100644
index 00000000..1b0275e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-invert.svg
new file mode 100644
index 00000000..df9d39d3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M21 7v9c0 1.7-1.3 3-3 3H3V7h18zm-8 2h-2v2h2V9zm0 3h-2v2h2v-2zm3-3h-2v2h2V9zm0 3h-2v2h2v-2zm1 5h1c.6 0 1-.4 1-1v-1h-2v2zm0-3h2v-2h-2v2zm0-3h2V9h-2v2zm-9 6h8v-2H8v2zm0-3h2v-2H8v2zm0-3h2V9H8v2zm-3 6h2v-2H5v2zm0-3h2v-2H5v2zm0-3h2V9H5v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-progressive.png
new file mode 100644
index 00000000..cf144b7b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-progressive.svg
new file mode 100644
index 00000000..1cff12c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M21 7v9c0 1.7-1.3 3-3 3H3V7h18zm-8 2h-2v2h2V9zm0 3h-2v2h2v-2zm3-3h-2v2h2V9zm0 3h-2v2h2v-2zm1 5h1c.6 0 1-.4 1-1v-1h-2v2zm0-3h2v-2h-2v2zm0-3h2V9h-2v2zm-9 6h8v-2H8v2zm0-3h2v-2H8v2zm0-3h2V9H8v2zm-3 6h2v-2H5v2zm0-3h2v-2H5v2zm0-3h2V9H5v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl.png
new file mode 100644
index 00000000..790a5e2d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl.svg
new file mode 100644
index 00000000..b37d7f4c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/keyboard-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 7v9c0 1.7-1.3 3-3 3H3V7h18zm-8 2h-2v2h2V9zm0 3h-2v2h2v-2zm3-3h-2v2h2V9zm0 3h-2v2h2v-2zm1 5h1c.6 0 1-.4 1-1v-1h-2v2zm0-3h2v-2h-2v2zm0-3h2V9h-2v2zm-9 6h8v-2H8v2zm0-3h2v-2H8v2zm0-3h2V9H8v2zm-3 6h2v-2H5v2zm0-3h2v-2H5v2zm0-3h2V9H5v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-invert.png
new file mode 100644
index 00000000..d9ac3481
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-invert.svg
new file mode 100644
index 00000000..9b8523f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-invert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="A">
+ <path d="M18.738 15.673l1.137 3.15h1.575L17.775 7.448h-2.188l-3.85 11.375h1.575l1.05-3.15h4.375zM16.55 8.76l1.837 5.427h-3.675l1.838-5.425z"/>
+ </g>
+ <g id="文">
+ <path d="M8.325 6.573h.787l-.875-1.75h-1.75l.438.875a1.56 1.56 0 0 0 1.4.875z"/>
+ <path d="m 9.202,12.874 c 0.7,0.525 1.486,0.963 2.45,1.225 l -0.438,1.31 A 9.17,9.17 0 0 1 8.151,13.835 c -1.49,1.137 -3.063,1.837 -4.813,2.363 L 2.9,14.885 C 4.386,14.36 5.874,13.835 7.1,12.872 5.962,11.648 5.174,10.335 4.65,8.758 l -1.663,0 0,-1.31 10.85,0 -0.438,1.312 -1.75,0 c -0.308,1.33 -1.255,2.957 -2.45,4.114 z m 1.05,-4.114 -4.114,0 c 0.35,1.226 1.138,2.363 2.013,3.238 0.926,-1 1.617,-1.957 2.1,-3.237 z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-progressive.png
new file mode 100644
index 00000000..cfc3a360
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-progressive.svg
new file mode 100644
index 00000000..1adc6aa1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr-progressive.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="A">
+ <path d="M18.738 15.673l1.137 3.15h1.575L17.775 7.448h-2.188l-3.85 11.375h1.575l1.05-3.15h4.375zM16.55 8.76l1.837 5.427h-3.675l1.838-5.425z"/>
+ </g>
+ <g id="文">
+ <path d="M8.325 6.573h.787l-.875-1.75h-1.75l.438.875a1.56 1.56 0 0 0 1.4.875z"/>
+ <path d="m 9.202,12.874 c 0.7,0.525 1.486,0.963 2.45,1.225 l -0.438,1.31 A 9.17,9.17 0 0 1 8.151,13.835 c -1.49,1.137 -3.063,1.837 -4.813,2.363 L 2.9,14.885 C 4.386,14.36 5.874,13.835 7.1,12.872 5.962,11.648 5.174,10.335 4.65,8.758 l -1.663,0 0,-1.31 10.85,0 -0.438,1.312 -1.75,0 c -0.308,1.33 -1.255,2.957 -2.45,4.114 z m 1.05,-4.114 -4.114,0 c 0.35,1.226 1.138,2.363 2.013,3.238 0.926,-1 1.617,-1.957 2.1,-3.237 z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr.png
new file mode 100644
index 00000000..f7b785c9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr.svg
new file mode 100644
index 00000000..d64b7343
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-ltr.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="A">
+ <path d="M18.738 15.673l1.137 3.15h1.575L17.775 7.448h-2.188l-3.85 11.375h1.575l1.05-3.15h4.375zM16.55 8.76l1.837 5.427h-3.675l1.838-5.425z"/>
+ </g>
+ <g id="文">
+ <path d="M8.325 6.573h.787l-.875-1.75h-1.75l.438.875a1.56 1.56 0 0 0 1.4.875z"/>
+ <path d="m 9.202,12.874 c 0.7,0.525 1.486,0.963 2.45,1.225 l -0.438,1.31 A 9.17,9.17 0 0 1 8.151,13.835 c -1.49,1.137 -3.063,1.837 -4.813,2.363 L 2.9,14.885 C 4.386,14.36 5.874,13.835 7.1,12.872 5.962,11.648 5.174,10.335 4.65,8.758 l -1.663,0 0,-1.31 10.85,0 -0.438,1.312 -1.75,0 c -0.308,1.33 -1.255,2.957 -2.45,4.114 z m 1.05,-4.114 -4.114,0 c 0.35,1.226 1.138,2.363 2.013,3.238 0.926,-1 1.617,-1.957 2.1,-3.237 z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-invert.png
new file mode 100644
index 00000000..80dad942
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-invert.svg
new file mode 100644
index 00000000..3ceea081
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-invert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="A">
+ <path d="M5.612 15.673l-1.137 3.15H2.9L6.575 7.448h2.188l3.85 11.375h-1.575l-1.05-3.15H5.613zM7.8 8.76l-1.837 5.427h3.675L7.8 8.762z" id="path5"/>
+ </g>
+ <g id="文">
+ <path d="M16.384 6.573h.787l-.873-1.75h-1.75l.438.875c.26.535.805.874 1.4.875z" id="path7"/>
+ <path d="M15.15 12.874c-.7.525-1.486.963-2.45 1.225l.438 1.31a9.17 9.17 0 0 0 3.063-1.575c1.49 1.137 3.064 1.837 4.814 2.363l.438-1.313c-1.486-.525-2.974-1.05-4.2-2.013 1.138-1.224 1.926-2.537 2.45-4.114h1.663v-1.31h-10.85l.438 1.312h1.75c.308 1.33 1.255 2.957 2.45 4.114zM14.1 8.76h4.114c-.35 1.226-1.138 2.363-2.013 3.238-.925-1-1.616-1.957-2.1-3.237z" id="path11-7"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-progressive.png
new file mode 100644
index 00000000..51d8ecfd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-progressive.svg
new file mode 100644
index 00000000..050fe1e0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl-progressive.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="A">
+ <path d="M5.612 15.673l-1.137 3.15H2.9L6.575 7.448h2.188l3.85 11.375h-1.575l-1.05-3.15H5.613zM7.8 8.76l-1.837 5.427h3.675L7.8 8.762z" id="path5"/>
+ </g>
+ <g id="文">
+ <path d="M16.384 6.573h.787l-.873-1.75h-1.75l.438.875c.26.535.805.874 1.4.875z" id="path7"/>
+ <path d="M15.15 12.874c-.7.525-1.486.963-2.45 1.225l.438 1.31a9.17 9.17 0 0 0 3.063-1.575c1.49 1.137 3.064 1.837 4.814 2.363l.438-1.313c-1.486-.525-2.974-1.05-4.2-2.013 1.138-1.224 1.926-2.537 2.45-4.114h1.663v-1.31h-10.85l.438 1.312h1.75c.308 1.33 1.255 2.957 2.45 4.114zM14.1 8.76h4.114c-.35 1.226-1.138 2.363-2.013 3.238-.925-1-1.616-1.957-2.1-3.237z" id="path11-7"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl.png
new file mode 100644
index 00000000..c78f2cd6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl.svg
new file mode 100644
index 00000000..cf6c1d51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/language-rtl.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="A">
+ <path d="M5.612 15.673l-1.137 3.15H2.9L6.575 7.448h2.188l3.85 11.375h-1.575l-1.05-3.15H5.613zM7.8 8.76l-1.837 5.427h3.675L7.8 8.762z" id="path5"/>
+ </g>
+ <g id="文">
+ <path d="M16.384 6.573h.787l-.873-1.75h-1.75l.438.875c.26.535.805.874 1.4.875z" id="path7"/>
+ <path d="M15.15 12.874c-.7.525-1.486.963-2.45 1.225l.438 1.31a9.17 9.17 0 0 0 3.063-1.575c1.49 1.137 3.064 1.837 4.814 2.363l.438-1.313c-1.486-.525-2.974-1.05-4.2-2.013 1.138-1.224 1.926-2.537 2.45-4.114h1.663v-1.31h-10.85l.438 1.312h1.75c.308 1.33 1.255 2.957 2.45 4.114zM14.1 8.76h4.114c-.35 1.226-1.138 2.363-2.013 3.238-.925-1-1.616-1.957-2.1-3.237z" id="path11-7"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr-invert.png
new file mode 100644
index 00000000..264811bc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr-invert.svg
new file mode 100644
index 00000000..491adb53
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M20.8 20h-8.1v-.8c.4 0 .8-.1 1.3-.2s.8-.2.8-.4v-.2c0-.1 0-.2-.1-.3L13.4 15H8.3c-.1.3-.2.6-.4 1-.1.4-.3.7-.4 1-.1.4-.2.7-.2.8v.4c0 .2.2.4.5.6.3.2.9.3 1.7.3v.9H3.4v-.8c.2 0 .5-.1.8-.1.3-.1.5-.1.7-.2.3-.2.5-.4.7-.6.2-.3.4-.6.5-.9.8-2 1.6-3.9 2.4-5.9.8-2 1.7-4.1 2.7-6.5h2.1c1.4 3.3 2.4 6 3.2 7.9.8 1.9 1.4 3.6 2 4.8l.3.6c.1.2.3.3.6.5.2.1.4.2.7.3.3.1.5.1.7.1v.8zM13 14l-2.1-5.3L8.8 14H13z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr.png
new file mode 100644
index 00000000..4b6d298f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr.svg
new file mode 100644
index 00000000..4b01d742
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20.8 20h-8.1v-.8c.4 0 .8-.1 1.3-.2s.8-.2.8-.4v-.2c0-.1 0-.2-.1-.3L13.4 15H8.3c-.1.3-.2.6-.4 1-.1.4-.3.7-.4 1-.1.4-.2.7-.2.8v.4c0 .2.2.4.5.6.3.2.9.3 1.7.3v.9H3.4v-.8c.2 0 .5-.1.8-.1.3-.1.5-.1.7-.2.3-.2.5-.4.7-.6.2-.3.4-.6.5-.9.8-2 1.6-3.9 2.4-5.9.8-2 1.7-4.1 2.7-6.5h2.1c1.4 3.3 2.4 6 3.2 7.9.8 1.9 1.4 3.6 2 4.8l.3.6c.1.2.3.3.6.5.2.1.4.2.7.3.3.1.5.1.7.1v.8zM13 14l-2.1-5.3L8.8 14H13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl-invert.png
new file mode 100644
index 00000000..b91b35c8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl-invert.svg
new file mode 100644
index 00000000..4842411a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M3.4 20h8.1v-.8c-.4 0-.8-.1-1.3-.2s-.8-.2-.8-.4v-.2c0-.1 0-.2.1-.3l1.3-3.1h5.1c.1.3.2.6.4 1 .1.4.3.7.4 1 .1.4.2.7.2.8v.4c0 .2-.2.4-.5.6-.3.2-.9.3-1.7.3v.9h6.1v-.8c-.2 0-.5-.1-.8-.1-.3-.1-.5-.1-.7-.2-.3-.2-.5-.4-.7-.6-.2-.3-.4-.6-.5-.9-.8-2-1.6-3.9-2.4-5.9-.8-2-1.7-4.1-2.7-6.5h-2.1c-1.4 3.3-2.4 6-3.2 7.9-.8 1.9-1.4 3.6-2 4.8l-.3.6c-.1.2-.3.3-.6.5-.2.1-.4.2-.7.3-.3.1-.5.1-.7.1v.8zm7.8-6l2.1-5.3 2.1 5.3h-4.2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl.png
new file mode 100644
index 00000000..77d77968
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl.svg
new file mode 100644
index 00000000..6ac62dc9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/largerText-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3.4 20h8.1v-.8c-.4 0-.8-.1-1.3-.2s-.8-.2-.8-.4v-.2c0-.1 0-.2.1-.3l1.3-3.1h5.1c.1.3.2.6.4 1 .1.4.3.7.4 1 .1.4.2.7.2.8v.4c0 .2-.2.4-.5.6-.3.2-.9.3-1.7.3v.9h6.1v-.8c-.2 0-.5-.1-.8-.1-.3-.1-.5-.1-.7-.2-.3-.2-.5-.4-.7-.6-.2-.3-.4-.6-.5-.9-.8-2-1.6-3.9-2.4-5.9-.8-2-1.7-4.1-2.7-6.5h-2.1c-1.4 3.3-2.4 6-3.2 7.9-.8 1.9-1.4 3.6-2 4.8l-.3.6c-.1.2-.3.3-.6.5-.2.1-.4.2-.7.3-.3.1-.5.1-.7.1v.8zm7.8-6l2.1-5.3 2.1 5.3h-4.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-invert.png
new file mode 100644
index 00000000..844b6f90
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-invert.svg
new file mode 100644
index 00000000..a12fc5ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="layout-ltr">
+ <path id="text" d="M5 19V5h6v8h8v6H5z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm5 5h-4V6h4v4z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-progressive.png
new file mode 100644
index 00000000..8dc8a318
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-progressive.svg
new file mode 100644
index 00000000..8243e340
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="layout-ltr">
+ <path id="text" d="M5 19V5h6v8h8v6H5z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm5 5h-4V6h4v4z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr.png
new file mode 100644
index 00000000..ea6d2f5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr.svg
new file mode 100644
index 00000000..c3be66cc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="layout-ltr">
+ <path id="text" d="M5 19V5h6v8h8v6H5z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm5 5h-4V6h4v4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-invert.png
new file mode 100644
index 00000000..1ef7734d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-invert.svg
new file mode 100644
index 00000000..165c9960
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="layout-rtl">
+ <path id="text" d="M5 19v-6h8V5h6v14H5z"/>
+ <path id="float" d="M5 5v6h6V5H5zm1 1h4v4H6V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-progressive.png
new file mode 100644
index 00000000..2c190ce5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-progressive.svg
new file mode 100644
index 00000000..db1081c5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="layout-rtl">
+ <path id="text" d="M5 19v-6h8V5h6v14H5z"/>
+ <path id="float" d="M5 5v6h6V5H5zm1 1h4v4H6V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl.png
new file mode 100644
index 00000000..46bf59b1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl.svg
new file mode 100644
index 00000000..ce7feb8d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/layout-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="layout-rtl">
+ <path id="text" d="M5 19v-6h8V5h6v14H5z"/>
+ <path id="float" d="M5 5v6h6V5H5zm1 1h4v4H6V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-invert.png
new file mode 100644
index 00000000..7c9195e7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-invert.svg
new file mode 100644
index 00000000..7c365353
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M15.387 4.33c-2.1 0-3.6 1.9-5.1 3.3.2 0 .5-.1.8-.1.5 0 1 .1 1.5.3.8-.8 1.6-1.7 2.8-1.7.6 0 1.3.3 1.8.7 1 1 1 2.6 0 3.6l-2.6 2.6c-.4.4-1.2.7-1.8.7-1.4 0-2.1-.9-2.6-2l-1.3 1.3c.8 1.5 2 2.6 3.8 2.6 1.2 0 2.3-.5 3-1.3l2.6-2.6c.9-.9 1.5-2 1.5-3.3-.2-2.2-2.2-4.1-4.4-4.1zm-4.3 12.1l-.9.9c-.4.4-1.2.7-1.8.7-.6 0-1.3-.3-1.8-.7-1-1-1-2.7 0-3.6l2.6-2.6c.4-.4 1.2-.7 1.8-.7 1.4 0 2.1 1 2.6 2l1.3-1.3c-.8-1.5-2-2.6-3.8-2.6-1.2 0-2.3.5-3 1.3l-2.6 2.6c-1.7 1.7-1.7 4.4 0 6 1.6 1.6 4.4 1.7 5.9 0l1.9-1.9c-.3.1-.6.1-.9.1-.5 0-.9 0-1.3-.2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-progressive.png
new file mode 100644
index 00000000..fb88cdf1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-progressive.svg
new file mode 100644
index 00000000..22228cd7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M15.387 4.33c-2.1 0-3.6 1.9-5.1 3.3.2 0 .5-.1.8-.1.5 0 1 .1 1.5.3.8-.8 1.6-1.7 2.8-1.7.6 0 1.3.3 1.8.7 1 1 1 2.6 0 3.6l-2.6 2.6c-.4.4-1.2.7-1.8.7-1.4 0-2.1-.9-2.6-2l-1.3 1.3c.8 1.5 2 2.6 3.8 2.6 1.2 0 2.3-.5 3-1.3l2.6-2.6c.9-.9 1.5-2 1.5-3.3-.2-2.2-2.2-4.1-4.4-4.1zm-4.3 12.1l-.9.9c-.4.4-1.2.7-1.8.7-.6 0-1.3-.3-1.8-.7-1-1-1-2.7 0-3.6l2.6-2.6c.4-.4 1.2-.7 1.8-.7 1.4 0 2.1 1 2.6 2l1.3-1.3c-.8-1.5-2-2.6-3.8-2.6-1.2 0-2.3.5-3 1.3l-2.6 2.6c-1.7 1.7-1.7 4.4 0 6 1.6 1.6 4.4 1.7 5.9 0l1.9-1.9c-.3.1-.6.1-.9.1-.5 0-.9 0-1.3-.2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr.png
new file mode 100644
index 00000000..617d3257
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr.svg
new file mode 100644
index 00000000..aaaee540
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15.387 4.33c-2.1 0-3.6 1.9-5.1 3.3.2 0 .5-.1.8-.1.5 0 1 .1 1.5.3.8-.8 1.6-1.7 2.8-1.7.6 0 1.3.3 1.8.7 1 1 1 2.6 0 3.6l-2.6 2.6c-.4.4-1.2.7-1.8.7-1.4 0-2.1-.9-2.6-2l-1.3 1.3c.8 1.5 2 2.6 3.8 2.6 1.2 0 2.3-.5 3-1.3l2.6-2.6c.9-.9 1.5-2 1.5-3.3-.2-2.2-2.2-4.1-4.4-4.1zm-4.3 12.1l-.9.9c-.4.4-1.2.7-1.8.7-.6 0-1.3-.3-1.8-.7-1-1-1-2.7 0-3.6l2.6-2.6c.4-.4 1.2-.7 1.8-.7 1.4 0 2.1 1 2.6 2l1.3-1.3c-.8-1.5-2-2.6-3.8-2.6-1.2 0-2.3.5-3 1.3l-2.6 2.6c-1.7 1.7-1.7 4.4 0 6 1.6 1.6 4.4 1.7 5.9 0l1.9-1.9c-.3.1-.6.1-.9.1-.5 0-.9 0-1.3-.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-invert.png
new file mode 100644
index 00000000..ece611a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-invert.svg
new file mode 100644
index 00000000..1ea19e87
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M9.025 3.6c2.1 0 3.6 1.9 5.1 3.3-.2 0-.5-.1-.8-.1-.5 0-1 .1-1.5.3-.8-.8-1.6-1.7-2.8-1.7-.6 0-1.3.3-1.8.7-1 1-1 2.6 0 3.6l2.6 2.6c.4.4 1.2.7 1.8.7 1.4 0 2.1-.9 2.6-2l1.3 1.3c-.8 1.5-2 2.6-3.8 2.6-1.2 0-2.3-.5-3-1.3l-2.6-2.6c-.9-.9-1.5-2-1.5-3.3.2-2.2 2.2-4.1 4.4-4.1zm4.3 12.1l.9.9c.4.4 1.2.7 1.8.7.6 0 1.3-.3 1.8-.7 1-1 1-2.7 0-3.6l-2.6-2.6c-.4-.4-1.2-.7-1.8-.7-1.4 0-2.1 1-2.6 2l-1.3-1.3c.8-1.5 2-2.6 3.8-2.6 1.2 0 2.3.5 3 1.3l2.6 2.6c1.7 1.7 1.7 4.4 0 6-1.6 1.6-4.4 1.7-5.9 0l-1.9-1.9c.3.1.6.1.9.1.5 0 .9 0 1.3-.2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-progressive.png
new file mode 100644
index 00000000..c030b01a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-progressive.svg
new file mode 100644
index 00000000..3af16119
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M9.025 3.6c2.1 0 3.6 1.9 5.1 3.3-.2 0-.5-.1-.8-.1-.5 0-1 .1-1.5.3-.8-.8-1.6-1.7-2.8-1.7-.6 0-1.3.3-1.8.7-1 1-1 2.6 0 3.6l2.6 2.6c.4.4 1.2.7 1.8.7 1.4 0 2.1-.9 2.6-2l1.3 1.3c-.8 1.5-2 2.6-3.8 2.6-1.2 0-2.3-.5-3-1.3l-2.6-2.6c-.9-.9-1.5-2-1.5-3.3.2-2.2 2.2-4.1 4.4-4.1zm4.3 12.1l.9.9c.4.4 1.2.7 1.8.7.6 0 1.3-.3 1.8-.7 1-1 1-2.7 0-3.6l-2.6-2.6c-.4-.4-1.2-.7-1.8-.7-1.4 0-2.1 1-2.6 2l-1.3-1.3c.8-1.5 2-2.6 3.8-2.6 1.2 0 2.3.5 3 1.3l2.6 2.6c1.7 1.7 1.7 4.4 0 6-1.6 1.6-4.4 1.7-5.9 0l-1.9-1.9c.3.1.6.1.9.1.5 0 .9 0 1.3-.2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl.png
new file mode 100644
index 00000000..ef484134
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl.svg
new file mode 100644
index 00000000..82a8e634
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/link-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9.025 3.6c2.1 0 3.6 1.9 5.1 3.3-.2 0-.5-.1-.8-.1-.5 0-1 .1-1.5.3-.8-.8-1.6-1.7-2.8-1.7-.6 0-1.3.3-1.8.7-1 1-1 2.6 0 3.6l2.6 2.6c.4.4 1.2.7 1.8.7 1.4 0 2.1-.9 2.6-2l1.3 1.3c-.8 1.5-2 2.6-3.8 2.6-1.2 0-2.3-.5-3-1.3l-2.6-2.6c-.9-.9-1.5-2-1.5-3.3.2-2.2 2.2-4.1 4.4-4.1zm4.3 12.1l.9.9c.4.4 1.2.7 1.8.7.6 0 1.3-.3 1.8-.7 1-1 1-2.7 0-3.6l-2.6-2.6c-.4-.4-1.2-.7-1.8-.7-1.4 0-2.1 1-2.6 2l-1.3-1.3c.8-1.5 2-2.6 3.8-2.6 1.2 0 2.3.5 3 1.3l2.6 2.6c1.7 1.7 1.7 4.4 0 6-1.6 1.6-4.4 1.7-5.9 0l-1.9-1.9c.3.1.6.1.9.1.5 0 .9 0 1.3-.2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-invert.png
new file mode 100644
index 00000000..88cdd9d6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-invert.svg
new file mode 100644
index 00000000..cb63d506
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M21 7H9V5h12v2zM7 6c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm14 7H9v-2h12v2zM7 12c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm14 7H9v-2h12v2zM7 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-progressive.png
new file mode 100644
index 00000000..350c7088
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-progressive.svg
new file mode 100644
index 00000000..0417a945
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M21 7H9V5h12v2zM7 6c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm14 7H9v-2h12v2zM7 12c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm14 7H9v-2h12v2zM7 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr.png
new file mode 100644
index 00000000..7796dd15
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr.svg
new file mode 100644
index 00000000..5f0b15f8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 7H9V5h12v2zM7 6c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm14 7H9v-2h12v2zM7 12c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2zm14 7H9v-2h12v2zM7 18c0 1.1-.9 2-2 2s-2-.9-2-2 .9-2 2-2 2 .9 2 2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-invert.png
new file mode 100644
index 00000000..6aeed4c8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-invert.svg
new file mode 100644
index 00000000..081fee42
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M3 7h12V5H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2zM3 13h12v-2H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2zM3 19h12v-2H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-progressive.png
new file mode 100644
index 00000000..9a9e5cac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-progressive.svg
new file mode 100644
index 00000000..c8610c9d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M3 7h12V5H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2zM3 13h12v-2H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2zM3 19h12v-2H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl.png
new file mode 100644
index 00000000..2c727b17
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl.svg
new file mode 100644
index 00000000..c9c94ebf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listBullet-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 7h12V5H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2zM3 13h12v-2H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2zM3 19h12v-2H3v2zm14-1c0 1.1.9 2 2 2s2-.9 2-2-.9-2-2-2-2 .9-2 2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-invert.png
new file mode 100644
index 00000000..13810b2c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-invert.svg
new file mode 100644
index 00000000..c752585e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M21 7H8V5h13v2zm0 6H8v-2h13v2zm0 6H8v-2h13v2zM4 4h2v4H5V5H4zm-1 6V9h3v3H4v1h2v1H3v-3h2v-1zm3 10H3v-1h2v-1H4v-1h1v-1H3v-1h3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-progressive.png
new file mode 100644
index 00000000..bf3c311f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-progressive.svg
new file mode 100644
index 00000000..150723fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M21 7H8V5h13v2zm0 6H8v-2h13v2zm0 6H8v-2h13v2zM4 4h2v4H5V5H4zm-1 6V9h3v3H4v1h2v1H3v-3h2v-1zm3 10H3v-1h2v-1H4v-1h1v-1H3v-1h3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr.png
new file mode 100644
index 00000000..631c2665
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr.svg
new file mode 100644
index 00000000..8e849a76
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 7H8V5h13v2zm0 6H8v-2h13v2zm0 6H8v-2h13v2zM4 4h2v4H5V5H4zm-1 6V9h3v3H4v1h2v1H3v-3h2v-1zm3 10H3v-1h2v-1H4v-1h1v-1H3v-1h3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-invert.png
new file mode 100644
index 00000000..9b2e8211
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-invert.svg
new file mode 100644
index 00000000..493654d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M3 7h13V5H3zm0 6h13v-2H3zm0 6h13v-2H3zM18 4h2v4h-1V5h-1zm0 6V9h3v3h-2v1h2v1h-3v-3h2v-1zm3 10h-3v-1h2v-1h-1v-1h1v-1h-2v-1h3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-progressive.png
new file mode 100644
index 00000000..7e1df5da
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-progressive.svg
new file mode 100644
index 00000000..469f949b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M3 7h13V5H3zm0 6h13v-2H3zm0 6h13v-2H3zM18 4h2v4h-1V5h-1zm0 6V9h3v3h-2v1h2v1h-3v-3h2v-1zm3 10h-3v-1h2v-1h-1v-1h1v-1h-2v-1h3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl.png
new file mode 100644
index 00000000..2c3b9d07
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl.svg
new file mode 100644
index 00000000..9ec48012
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/listNumbered-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 7h13V5H3zm0 6h13v-2H3zm0 6h13v-2H3zM18 4h2v4h-1V5h-1zm0 6V9h3v3h-2v1h2v1h-3v-3h2v-1zm3 10h-3v-1h2v-1h-1v-1h1v-1h-2v-1h3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-destructive.png
new file mode 100644
index 00000000..e16f0429
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-destructive.svg
new file mode 100644
index 00000000..9e4aee09
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#d33">
+ <path d="M15 8s0-3-2.5-3S10 8 10 8v1h5zm2 0v1h2v10H9c-1.7 0-3-1.3-3-3V9h2V8s0-5 4.5-5S17 8 17 8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-invert.png
new file mode 100644
index 00000000..a81a2a17
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-invert.svg
new file mode 100644
index 00000000..7e11b413
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M15 8s0-3-2.5-3S10 8 10 8v1h5zm2 0v1h2v10H9c-1.7 0-3-1.3-3-3V9h2V8s0-5 4.5-5S17 8 17 8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-progressive.png
new file mode 100644
index 00000000..181c0cbf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-progressive.svg
new file mode 100644
index 00000000..a90a981e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M15 8s0-3-2.5-3S10 8 10 8v1h5zm2 0v1h2v10H9c-1.7 0-3-1.3-3-3V9h2V8s0-5 4.5-5S17 8 17 8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr.png
new file mode 100644
index 00000000..a87541f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr.svg
new file mode 100644
index 00000000..a18b2c46
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 8s0-3-2.5-3S10 8 10 8v1h5zm2 0v1h2v10H9c-1.7 0-3-1.3-3-3V9h2V8s0-5 4.5-5S17 8 17 8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-destructive.png
new file mode 100644
index 00000000..29cd2b57
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-destructive.svg
new file mode 100644
index 00000000..1eea0ed9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#d33">
+ <path d="M10 8s0-3 2.5-3S15 8 15 8v1h-5zM8 8v1H6v10h10c1.7 0 3-1.3 3-3V9h-2V8s0-5-4.5-5S8 8 8 8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-invert.png
new file mode 100644
index 00000000..ab62257a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-invert.svg
new file mode 100644
index 00000000..9396317b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M10 8s0-3 2.5-3S15 8 15 8v1h-5zM8 8v1H6v10h10c1.7 0 3-1.3 3-3V9h-2V8s0-5-4.5-5S8 8 8 8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-progressive.png
new file mode 100644
index 00000000..d17e790f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-progressive.svg
new file mode 100644
index 00000000..6d2fa9ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M10 8s0-3 2.5-3S15 8 15 8v1h-5zM8 8v1H6v10h10c1.7 0 3-1.3 3-3V9h-2V8s0-5-4.5-5S8 8 8 8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl.png
new file mode 100644
index 00000000..55f2d224
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl.svg
new file mode 100644
index 00000000..6c4a3c51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/lock-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10 8s0-3 2.5-3S15 8 15 8v1h-5zM8 8v1H6v10h10c1.7 0 3-1.3 3-3V9h-2V8s0-5-4.5-5S8 8 8 8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-invert.png
new file mode 100644
index 00000000..fb1bb0c9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-invert.svg
new file mode 100644
index 00000000..da6a634f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M15 14v3l5-4.5L15 8v3H8c0 1.7 1.3 3 3 3h4zm-1-9H4v15h10v-2H6V7h8V5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-progressive.png
new file mode 100644
index 00000000..8ede1738
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-progressive.svg
new file mode 100644
index 00000000..bdf23f4d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M15 14v3l5-4.5L15 8v3H8c0 1.7 1.3 3 3 3h4zm-1-9H4v15h10v-2H6V7h8V5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr.png
new file mode 100644
index 00000000..18f82eb8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr.svg
new file mode 100644
index 00000000..f2be068b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 14v3l5-4.5L15 8v3H8c0 1.7 1.3 3 3 3h4zm-1-9H4v15h10v-2H6V7h8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-invert.png
new file mode 100644
index 00000000..dcd2f15e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-invert.svg
new file mode 100644
index 00000000..ea358035
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M9 14v3l-5-4.5L9 8v3h7c0 1.7-1.3 3-3 3H9zm1-9h10v15H10v-2h8V7h-8V5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-progressive.png
new file mode 100644
index 00000000..642db7d5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-progressive.svg
new file mode 100644
index 00000000..403bfc90
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M9 14v3l-5-4.5L9 8v3h7c0 1.7-1.3 3-3 3H9zm1-9h10v15H10v-2h8V7h-8V5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl.png
new file mode 100644
index 00000000..0ffb7235
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl.svg
new file mode 100644
index 00000000..5f5ebb90
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logOut-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 14v3l-5-4.5L9 8v3h7c0 1.7-1.3 3-3 3H9zm1-9h10v15H10v-2h8V7h-8V5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-invert.png
new file mode 100644
index 00000000..7f04a806
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-invert.svg
new file mode 100644
index 00000000..6d95c873
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 6c-3.9 0-7 3.1-7 7s3.1 7 7 7 7-3.1 7-7-3.1-7-7-7zm0 13c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6zm-1.7-4.6c-.7 0-1-.4-1-1.2s.3-1.2 1-1.2c.4 0 .6.2.8.6l.9-.5c-.4-.7-1-1-1.9-1-.6 0-1.1.2-1.5.6s-.6.8-.6 1.5.2 1.2.6 1.6c.4.4.9.6 1.5.6.8 0 1.4-.4 1.9-1.1l-.9-.4c-.2.3-.5.5-.8.5zm4 0c-.7 0-1-.4-1-1.2s.3-1.2 1-1.2c.4 0 .6.2.8.6l.9-.5c-.4-.7-1-1-1.9-1-.6 0-1.1.2-1.5.6s-.6.8-.6 1.5.2 1.2.6 1.6c.4.4.9.6 1.5.6.8 0 1.4-.4 1.9-1.1l-.9-.4c-.2.3-.5.5-.8.5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-progressive.png
new file mode 100644
index 00000000..2e37da79
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-progressive.svg
new file mode 100644
index 00000000..ee162200
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 6c-3.9 0-7 3.1-7 7s3.1 7 7 7 7-3.1 7-7-3.1-7-7-7zm0 13c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6zm-1.7-4.6c-.7 0-1-.4-1-1.2s.3-1.2 1-1.2c.4 0 .6.2.8.6l.9-.5c-.4-.7-1-1-1.9-1-.6 0-1.1.2-1.5.6s-.6.8-.6 1.5.2 1.2.6 1.6c.4.4.9.6 1.5.6.8 0 1.4-.4 1.9-1.1l-.9-.4c-.2.3-.5.5-.8.5zm4 0c-.7 0-1-.4-1-1.2s.3-1.2 1-1.2c.4 0 .6.2.8.6l.9-.5c-.4-.7-1-1-1.9-1-.6 0-1.1.2-1.5.6s-.6.8-.6 1.5.2 1.2.6 1.6c.4.4.9.6 1.5.6.8 0 1.4-.4 1.9-1.1l-.9-.4c-.2.3-.5.5-.8.5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc.png
new file mode 100644
index 00000000..80ef2a62
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc.svg
new file mode 100644
index 00000000..00af35db
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-cc.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 6c-3.9 0-7 3.1-7 7s3.1 7 7 7 7-3.1 7-7-3.1-7-7-7zm0 13c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6-2.7 6-6 6zm-1.7-4.6c-.7 0-1-.4-1-1.2s.3-1.2 1-1.2c.4 0 .6.2.8.6l.9-.5c-.4-.7-1-1-1.9-1-.6 0-1.1.2-1.5.6s-.6.8-.6 1.5.2 1.2.6 1.6c.4.4.9.6 1.5.6.8 0 1.4-.4 1.9-1.1l-.9-.4c-.2.3-.5.5-.8.5zm4 0c-.7 0-1-.4-1-1.2s.3-1.2 1-1.2c.4 0 .6.2.8.6l.9-.5c-.4-.7-1-1-1.9-1-.6 0-1.1.2-1.5.6s-.6.8-.6 1.5.2 1.2.6 1.6c.4.4.9.6 1.5.6.8 0 1.4-.4 1.9-1.1l-.9-.4c-.2.3-.5.5-.8.5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-invert.png
new file mode 100644
index 00000000..0f8d9a62
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-invert.svg
new file mode 100644
index 00000000..27513cc2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M15.4 7.8c-2-.9-2.3-2.5-2.4-2.8.1.1 2 1 2 1l-3-5-3 5 2-1s0 .8.6 2.1c.8 1.5 2.2 2.2 2.2 2.2s1.6.7 2.2 1.3l-.7.7-.5-.5-.4 1.8 1.8-.4-.5-.5.7-.7c.9 1 1.5 2.3 1.6 3.8h-1V14l-1.5 1 1.5 1v-.8h1c-.1 1.5-.6 2.8-1.6 3.8l-.7-.7.5-.5-1.8-.4.4 1.8.5-.5.7.7c-1 .9-2.3 1.5-3.8 1.6v-1h.8l-1-1.5-1 1.5h.8v1c-1.5-.1-2.8-.6-3.8-1.6l.7-.7.5.5.4-1.8-1.8.4.5.5-.7.7c-.9-1-1.5-2.3-1.6-3.8h1v.8l1.5-1L7 14v.8H6c.1-1.5.6-2.8 1.6-3.8l.7.7-.5.5 1.8.4-.4-1.8-.5.5-.7-.7-1.5-1.4A7.99 7.99 0 0 0 4 15c0 4.4 3.6 8 8 8s8-3.6 8-8c0-3.2-1.9-5.9-4.6-7.2z"/>
+ <circle cx="12" cy="15" r="3"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-progressive.png
new file mode 100644
index 00000000..6aa047c5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-progressive.svg
new file mode 100644
index 00000000..bb82d1f9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M15.4 7.8c-2-.9-2.3-2.5-2.4-2.8.1.1 2 1 2 1l-3-5-3 5 2-1s0 .8.6 2.1c.8 1.5 2.2 2.2 2.2 2.2s1.6.7 2.2 1.3l-.7.7-.5-.5-.4 1.8 1.8-.4-.5-.5.7-.7c.9 1 1.5 2.3 1.6 3.8h-1V14l-1.5 1 1.5 1v-.8h1c-.1 1.5-.6 2.8-1.6 3.8l-.7-.7.5-.5-1.8-.4.4 1.8.5-.5.7.7c-1 .9-2.3 1.5-3.8 1.6v-1h.8l-1-1.5-1 1.5h.8v1c-1.5-.1-2.8-.6-3.8-1.6l.7-.7.5.5.4-1.8-1.8.4.5.5-.7.7c-.9-1-1.5-2.3-1.6-3.8h1v.8l1.5-1L7 14v.8H6c.1-1.5.6-2.8 1.6-3.8l.7.7-.5.5 1.8.4-.4-1.8-.5.5-.7-.7-1.5-1.4A7.99 7.99 0 0 0 4 15c0 4.4 3.6 8 8 8s8-3.6 8-8c0-3.2-1.9-5.9-4.6-7.2z"/>
+ <circle cx="12" cy="15" r="3"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons.png
new file mode 100644
index 00000000..c41c2470
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons.svg
new file mode 100644
index 00000000..f2492ce1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaCommons.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15.4 7.8c-2-.9-2.3-2.5-2.4-2.8.1.1 2 1 2 1l-3-5-3 5 2-1s0 .8.6 2.1c.8 1.5 2.2 2.2 2.2 2.2s1.6.7 2.2 1.3l-.7.7-.5-.5-.4 1.8 1.8-.4-.5-.5.7-.7c.9 1 1.5 2.3 1.6 3.8h-1V14l-1.5 1 1.5 1v-.8h1c-.1 1.5-.6 2.8-1.6 3.8l-.7-.7.5-.5-1.8-.4.4 1.8.5-.5.7.7c-1 .9-2.3 1.5-3.8 1.6v-1h.8l-1-1.5-1 1.5h.8v1c-1.5-.1-2.8-.6-3.8-1.6l.7-.7.5.5.4-1.8-1.8.4.5.5-.7.7c-.9-1-1.5-2.3-1.6-3.8h1v.8l1.5-1L7 14v.8H6c.1-1.5.6-2.8 1.6-3.8l.7.7-.5.5 1.8.4-.4-1.8-.5.5-.7-.7-1.5-1.4A7.99 7.99 0 0 0 4 15c0 4.4 3.6 8 8 8s8-3.6 8-8c0-3.2-1.9-5.9-4.6-7.2z"/>
+ <circle cx="12" cy="15" r="3"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-invert.png
new file mode 100644
index 00000000..09635383
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-invert.svg
new file mode 100644
index 00000000..9c4a9550
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M15.3 14.7C16.1 10.9 14.7 4 12 4c-2.7 0-4.2 6.7-3.4 10.5L7 18h2.7l.3 1h4c.2-.3.1-.5.3-1H17l-1.7-3.3zM12 10c-.8 0-1.5-.7-1.5-1.5S11.2 7 12 7s1.5.7 1.5 1.5S12.8 10 12 10zm2 10c0 1.1-2 2-2 2s-2-.9-2-2"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-progressive.png
new file mode 100644
index 00000000..6afb2bde
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-progressive.svg
new file mode 100644
index 00000000..594cdfbd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M15.3 14.7C16.1 10.9 14.7 4 12 4c-2.7 0-4.2 6.7-3.4 10.5L7 18h2.7l.3 1h4c.2-.3.1-.5.3-1H17l-1.7-3.3zM12 10c-.8 0-1.5-.7-1.5-1.5S11.2 7 12 7s1.5.7 1.5 1.5S12.8 10 12 10zm2 10c0 1.1-2 2-2 2s-2-.9-2-2"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery.png
new file mode 100644
index 00000000..6d3c067c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery.svg
new file mode 100644
index 00000000..c3f99d6a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikimediaDiscovery.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15.3 14.7C16.1 10.9 14.7 4 12 4c-2.7 0-4.2 6.7-3.4 10.5L7 18h2.7l.3 1h4c.2-.3.1-.5.3-1H17l-1.7-3.3zM12 10c-.8 0-1.5-.7-1.5-1.5S11.2 7 12 7s1.5.7 1.5 1.5S12.8 10 12 10zm2 10c0 1.1-2 2-2 2s-2-.9-2-2"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-invert.png
new file mode 100644
index 00000000..9d576d08
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-invert.svg
new file mode 100644
index 00000000..fb304f6b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M22.3 6.3c0 .2 0 .3-.1.3-.7.1-1.2.5-1.6 1.1-.1.2-.2.4-.3.7l-4.6 10.1c-.1.2-.2.3-.2.3s-.1.1-.2.1c-.2 0-.4-.1-.5-.4L12.2 13l-2.8 5.5c-.1.3-.3.4-.5.4s-.4-.1-.5-.4L4.1 8.4c-.3-.8-.6-1.2-.8-1.4-.2-.2-.5-.3-1-.4-.1-.1-.1-.2-.1-.3 0-.2 0-.3.1-.3h4.3c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.6.1-1 .2-1.1.4-.1.2 0 .6.3 1.2l3.6 8.2h.1l2.2-4.4L10 8.4c-.3-.7-.6-1.2-.8-1.4s-.5-.3-.9-.4c-.1-.1-.1-.2-.1-.3 0-.2 0-.3.1-.3h3.6c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.4.1-.6.2-.6.4s.1.6.4 1.2l1 1.9 1-1.9c.3-.6.5-.9.5-1.1 0-.2 0-.3-.1-.4-.1-.1-.3-.1-.5-.1l-.1-.3c0-.2 0-.3.1-.3h3c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.5.1-.8.2-1.1.5-.3.3-.6.7-.8 1.3l-1.3 2.8 2.5 5.2h.1l3.7-8.1c.3-.5.3-.9.2-1.2-.1-.3-.5-.4-1.1-.5-.1-.1-.1-.2-.1-.3s0-.3.1-.3h3.7c-.2.1-.2.2-.2.3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-progressive.png
new file mode 100644
index 00000000..bc141edc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-progressive.svg
new file mode 100644
index 00000000..4c7864bb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M22.3 6.3c0 .2 0 .3-.1.3-.7.1-1.2.5-1.6 1.1-.1.2-.2.4-.3.7l-4.6 10.1c-.1.2-.2.3-.2.3s-.1.1-.2.1c-.2 0-.4-.1-.5-.4L12.2 13l-2.8 5.5c-.1.3-.3.4-.5.4s-.4-.1-.5-.4L4.1 8.4c-.3-.8-.6-1.2-.8-1.4-.2-.2-.5-.3-1-.4-.1-.1-.1-.2-.1-.3 0-.2 0-.3.1-.3h4.3c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.6.1-1 .2-1.1.4-.1.2 0 .6.3 1.2l3.6 8.2h.1l2.2-4.4L10 8.4c-.3-.7-.6-1.2-.8-1.4s-.5-.3-.9-.4c-.1-.1-.1-.2-.1-.3 0-.2 0-.3.1-.3h3.6c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.4.1-.6.2-.6.4s.1.6.4 1.2l1 1.9 1-1.9c.3-.6.5-.9.5-1.1 0-.2 0-.3-.1-.4-.1-.1-.3-.1-.5-.1l-.1-.3c0-.2 0-.3.1-.3h3c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.5.1-.8.2-1.1.5-.3.3-.6.7-.8 1.3l-1.3 2.8 2.5 5.2h.1l3.7-8.1c.3-.5.3-.9.2-1.2-.1-.3-.5-.4-1.1-.5-.1-.1-.1-.2-.1-.3s0-.3.1-.3h3.7c-.2.1-.2.2-.2.3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia.png
new file mode 100644
index 00000000..f1d8330f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia.svg
new file mode 100644
index 00000000..9208f3b6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/logo-wikipedia.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M22.3 6.3c0 .2 0 .3-.1.3-.7.1-1.2.5-1.6 1.1-.1.2-.2.4-.3.7l-4.6 10.1c-.1.2-.2.3-.2.3s-.1.1-.2.1c-.2 0-.4-.1-.5-.4L12.2 13l-2.8 5.5c-.1.3-.3.4-.5.4s-.4-.1-.5-.4L4.1 8.4c-.3-.8-.6-1.2-.8-1.4-.2-.2-.5-.3-1-.4-.1-.1-.1-.2-.1-.3 0-.2 0-.3.1-.3h4.3c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.6.1-1 .2-1.1.4-.1.2 0 .6.3 1.2l3.6 8.2h.1l2.2-4.4L10 8.4c-.3-.7-.6-1.2-.8-1.4s-.5-.3-.9-.4c-.1-.1-.1-.2-.1-.3 0-.2 0-.3.1-.3h3.6c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.4.1-.6.2-.6.4s.1.6.4 1.2l1 1.9 1-1.9c.3-.6.5-.9.5-1.1 0-.2 0-.3-.1-.4-.1-.1-.3-.1-.5-.1l-.1-.3c0-.2 0-.3.1-.3h3c.1.1.1.2.1.3 0 .2 0 .3-.1.3-.5.1-.8.2-1.1.5-.3.3-.6.7-.8 1.3l-1.3 2.8 2.5 5.2h.1l3.7-8.1c.3-.5.3-.9.2-1.2-.1-.3-.5-.4-1.1-.5-.1-.1-.1-.2-.1-.3s0-.3.1-.3h3.7c-.2.1-.2.2-.2.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-invert.png
new file mode 100644
index 00000000..6e0cd017
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-invert.svg
new file mode 100644
index 00000000..59bb24ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M15 6L9 4 3 6v15l6-2 6 2 6-2V4l-6 2zM8.7 18.1L4 19.6V6.7L9 5v12.9l-.3.2zm11.3.2L15 20V7.1l.3-.1L20 5.4v12.9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-progressive.png
new file mode 100644
index 00000000..e856237e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-progressive.svg
new file mode 100644
index 00000000..bebac9cf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M15 6L9 4 3 6v15l6-2 6 2 6-2V4l-6 2zM8.7 18.1L4 19.6V6.7L9 5v12.9l-.3.2zm11.3.2L15 20V7.1l.3-.1L20 5.4v12.9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr.png
new file mode 100644
index 00000000..43a97d29
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr.svg
new file mode 100644
index 00000000..0e5a52e4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 6L9 4 3 6v15l6-2 6 2 6-2V4l-6 2zM8.7 18.1L4 19.6V6.7L9 5v12.9l-.3.2zm11.3.2L15 20V7.1l.3-.1L20 5.4v12.9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-invert.png
new file mode 100644
index 00000000..4993f575
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-invert.svg
new file mode 100644
index 00000000..06c3d106
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M9 6l6-2 6 2v15l-6-2-6 2-6-2V4l6 2zm6.3 12.1l4.7 1.5V6.7L15 5v12.9l.3.2zM4 18.3L9 20V7.1L8.7 7 4 5.4v12.9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-progressive.png
new file mode 100644
index 00000000..6dbb6c55
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-progressive.svg
new file mode 100644
index 00000000..a969ee6c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M9 6l6-2 6 2v15l-6-2-6 2-6-2V4l6 2zm6.3 12.1l4.7 1.5V6.7L15 5v12.9l.3.2zM4 18.3L9 20V7.1L8.7 7 4 5.4v12.9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl.png
new file mode 100644
index 00000000..36e9cad9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl.svg
new file mode 100644
index 00000000..835781d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/map-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 6l6-2 6 2v15l-6-2-6 2-6-2V4l6 2zm6.3 12.1l4.7 1.5V6.7L15 5v12.9l.3.2zM4 18.3L9 20V7.1L8.7 7 4 5.4v12.9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-invert.png
new file mode 100644
index 00000000..40f9ee3d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-invert.svg
new file mode 100644
index 00000000..99a1c6d1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M19 10c0-3.9-3.1-7-7-7s-7 3.1-7 7c0 1.4.4 2.6 1.1 3.7L12 21l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7zm-7 3c-1.6 0-3-1.4-3-3s1.4-3 3-3 3 1.4 3 3-1.4 3-3 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-progressive.png
new file mode 100644
index 00000000..73a0cf2c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-progressive.svg
new file mode 100644
index 00000000..f7d33234
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M19 10c0-3.9-3.1-7-7-7s-7 3.1-7 7c0 1.4.4 2.6 1.1 3.7L12 21l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7zm-7 3c-1.6 0-3-1.4-3-3s1.4-3 3-3 3 1.4 3 3-1.4 3-3 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin.png
new file mode 100644
index 00000000..27833cff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin.svg
new file mode 100644
index 00000000..8d87943b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPin.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19 10c0-3.9-3.1-7-7-7s-7 3.1-7 7c0 1.4.4 2.6 1.1 3.7L12 21l5.9-7.3c.7-1.1 1.1-2.3 1.1-3.7zm-7 3c-1.6 0-3-1.4-3-3s1.4-3 3-3 3 1.4 3 3-1.4 3-3 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-invert.png
new file mode 100644
index 00000000..ee5de90d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-invert.svg
new file mode 100644
index 00000000..eb5e6244
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M24 4h-4V0h-2v4h-4v2h4v4h2V6h4V4z"/>
+ <path d="M18.9 11c.1.3.1.7.1 1 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-3.9 3.1-7 7-7 .3 0 .7 0 1 .1V7h3.9l.1.1V11h1.9zM15 12c0-1.6-1.4-3-3-3s-3 1.4-3 3 1.4 3 3 3 3-1.4 3-3z"/>
+</g></svg>
+
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-progressive.png
new file mode 100644
index 00000000..036a31dc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-progressive.svg
new file mode 100644
index 00000000..3e0ea6c5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M24 4h-4V0h-2v4h-4v2h4v4h2V6h4V4z"/>
+ <path d="M18.9 11c.1.3.1.7.1 1 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-3.9 3.1-7 7-7 .3 0 .7 0 1 .1V7h3.9l.1.1V11h1.9zM15 12c0-1.6-1.4-3-3-3s-3 1.4-3 3 1.4 3 3 3 3-1.4 3-3z"/>
+</g></svg>
+
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr.png
new file mode 100644
index 00000000..d8c1691e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr.svg
new file mode 100644
index 00000000..9d71335a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M24 4h-4V0h-2v4h-4v2h4v4h2V6h4V4z"/>
+ <path d="M18.9 11c.1.3.1.7.1 1 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-3.9 3.1-7 7-7 .3 0 .7 0 1 .1V7h3.9l.1.1V11h1.9zM15 12c0-1.6-1.4-3-3-3s-3 1.4-3 3 1.4 3 3 3 3-1.4 3-3z"/>
+</svg>
+
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-invert.png
new file mode 100644
index 00000000..934d5ccc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-invert.svg
new file mode 100644
index 00000000..a7a14e91
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M0 4h4V0h2v4h4v2H6v4H4V6H0"/>
+ <path d="M6 11h1V7.1l.1-.1H11V5.1c.3-.1.7-.1 1-.1 3.9 0 7 3.1 7 7 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-.3 0-.7.1-1H6zm6 4c1.65 0 3-1.35 3-3s-1.35-3-3-3-3 1.35-3 3 1.35 3 3 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-progressive.png
new file mode 100644
index 00000000..be7c51e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-progressive.svg
new file mode 100644
index 00000000..9bcc4365
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M0 4h4V0h2v4h4v2H6v4H4V6H0"/>
+ <path d="M6 11h1V7.1l.1-.1H11V5.1c.3-.1.7-.1 1-.1 3.9 0 7 3.1 7 7 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-.3 0-.7.1-1H6zm6 4c1.65 0 3-1.35 3-3s-1.35-3-3-3-3 1.35-3 3 1.35 3 3 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl.png
new file mode 100644
index 00000000..7cc1f74c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl.svg
new file mode 100644
index 00000000..03c484ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapPinAdd-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M0 4h4V0h2v4h4v2H6v4H4V6H0"/>
+ <path d="M6 11h1V7.1l.1-.1H11V5.1c.3-.1.7-.1 1-.1 3.9 0 7 3.1 7 7 0 1.4-.4 2.6-1.1 3.7L12 23l-5.9-7.3C5.4 14.6 5 13.4 5 12c0-.3 0-.7.1-1H6zm6 4c1.65 0 3-1.35 3-3s-1.35-3-3-3-3 1.35-3 3 1.35 3 3 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-invert.png
new file mode 100644
index 00000000..075f84e0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-invert.svg
new file mode 100644
index 00000000..17d3645b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M15 9l.7-1.8c.9.4 1.8.7 2.4.9l-.6 1.7v.2L15 9zm-4.3-1.9l.8-1.8c1.2.5 2.6 1.1 3 1.4l-.8 1.8-3-1.4zm-5.9-1c-.8 0-1.4.2-2 .6L1.7 5c.9-.6 1.9-.9 3.1-.9v2zm-4.3.7l1.8.8c-.3.7-.3 1.3-.1 1.8l-1.9.7C0 8.9 0 7.8.5 6.8zm4.2 5.4l-1.3 1.5c-1-1-1.7-1.6-2-2l1.5-1.3c.7.8 1.3 1.4 1.8 1.8zm7.3 4.3c0 1.9-1.6 3.5-3.5 3.5S5 18.4 5 16.5 6.6 13 8.5 13s3.5 1.6 3.5 3.5zM24 8l-1-1-1.5 1.5L20 7l-1 1 1.5 1.5L19 11l1 1 1.5-1.5L23 12l1-1-1.5-1.5z"/>
+ <circle cx="8" cy="5" r="2"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-progressive.png
new file mode 100644
index 00000000..2b26e155
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-progressive.svg
new file mode 100644
index 00000000..2b49b990
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M15 9l.7-1.8c.9.4 1.8.7 2.4.9l-.6 1.7v.2L15 9zm-4.3-1.9l.8-1.8c1.2.5 2.6 1.1 3 1.4l-.8 1.8-3-1.4zm-5.9-1c-.8 0-1.4.2-2 .6L1.7 5c.9-.6 1.9-.9 3.1-.9v2zm-4.3.7l1.8.8c-.3.7-.3 1.3-.1 1.8l-1.9.7C0 8.9 0 7.8.5 6.8zm4.2 5.4l-1.3 1.5c-1-1-1.7-1.6-2-2l1.5-1.3c.7.8 1.3 1.4 1.8 1.8zm7.3 4.3c0 1.9-1.6 3.5-3.5 3.5S5 18.4 5 16.5 6.6 13 8.5 13s3.5 1.6 3.5 3.5zM24 8l-1-1-1.5 1.5L20 7l-1 1 1.5 1.5L19 11l1 1 1.5-1.5L23 12l1-1-1.5-1.5z"/>
+ <circle cx="8" cy="5" r="2"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr.png
new file mode 100644
index 00000000..331fd595
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr.svg
new file mode 100644
index 00000000..cb073b9d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 9l.7-1.8c.9.4 1.8.7 2.4.9l-.6 1.7v.2L15 9zm-4.3-1.9l.8-1.8c1.2.5 2.6 1.1 3 1.4l-.8 1.8-3-1.4zm-5.9-1c-.8 0-1.4.2-2 .6L1.7 5c.9-.6 1.9-.9 3.1-.9v2zm-4.3.7l1.8.8c-.3.7-.3 1.3-.1 1.8l-1.9.7C0 8.9 0 7.8.5 6.8zm4.2 5.4l-1.3 1.5c-1-1-1.7-1.6-2-2l1.5-1.3c.7.8 1.3 1.4 1.8 1.8zm7.3 4.3c0 1.9-1.6 3.5-3.5 3.5S5 18.4 5 16.5 6.6 13 8.5 13s3.5 1.6 3.5 3.5zM24 8l-1-1-1.5 1.5L20 7l-1 1 1.5 1.5L19 11l1 1 1.5-1.5L23 12l1-1-1.5-1.5z"/>
+ <circle cx="8" cy="5" r="2"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-invert.png
new file mode 100644
index 00000000..75c8dcfc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-invert.svg
new file mode 100644
index 00000000..fbb9cabd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M9.095 9l-.7-1.8c-.9.4-1.8.7-2.4.9l.6 1.7v.2l2.5-1zm4.3-1.9l-.8-1.8c-1.2.5-2.6 1.1-3 1.4l.8 1.8 3-1.4zm5.9-1c.8 0 1.4.2 2 .6l1.1-1.7c-.9-.6-1.9-.9-3.1-.9v2zm4.3.7l-1.8.8c.3.7.3 1.3.1 1.8l1.9.7c.3-1.2.3-2.3-.2-3.3zm-4.2 5.4l1.3 1.5c1-1 1.7-1.6 2-2l-1.5-1.3c-.7.8-1.3 1.4-1.8 1.8zm-7.3 4.3c0 1.9 1.6 3.5 3.5 3.5s3.5-1.6 3.5-3.5-1.6-3.5-3.5-3.5-3.5 1.6-3.5 3.5zM.095 8l1-1 1.5 1.5 1.5-1.5 1 1-1.5 1.5 1.5 1.5-1 1-1.5-1.5-1.5 1.5-1-1 1.5-1.5z"/>
+ <circle cx="8" cy="5" r="2" transform="matrix(-1 0 0 1 24.095 0)"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-progressive.png
new file mode 100644
index 00000000..fc0b2d92
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-progressive.svg
new file mode 100644
index 00000000..a2f62ff0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M9.095 9l-.7-1.8c-.9.4-1.8.7-2.4.9l.6 1.7v.2l2.5-1zm4.3-1.9l-.8-1.8c-1.2.5-2.6 1.1-3 1.4l.8 1.8 3-1.4zm5.9-1c.8 0 1.4.2 2 .6l1.1-1.7c-.9-.6-1.9-.9-3.1-.9v2zm4.3.7l-1.8.8c.3.7.3 1.3.1 1.8l1.9.7c.3-1.2.3-2.3-.2-3.3zm-4.2 5.4l1.3 1.5c1-1 1.7-1.6 2-2l-1.5-1.3c-.7.8-1.3 1.4-1.8 1.8zm-7.3 4.3c0 1.9 1.6 3.5 3.5 3.5s3.5-1.6 3.5-3.5-1.6-3.5-3.5-3.5-3.5 1.6-3.5 3.5zM.095 8l1-1 1.5 1.5 1.5-1.5 1 1-1.5 1.5 1.5 1.5-1 1-1.5-1.5-1.5 1.5-1-1 1.5-1.5z"/>
+ <circle cx="8" cy="5" r="2" transform="matrix(-1 0 0 1 24.095 0)"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl.png
new file mode 100644
index 00000000..62f1fe91
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl.svg
new file mode 100644
index 00000000..e8b1a08c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/mapTrail-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9.095 9l-.7-1.8c-.9.4-1.8.7-2.4.9l.6 1.7v.2l2.5-1zm4.3-1.9l-.8-1.8c-1.2.5-2.6 1.1-3 1.4l.8 1.8 3-1.4zm5.9-1c.8 0 1.4.2 2 .6l1.1-1.7c-.9-.6-1.9-.9-3.1-.9v2zm4.3.7l-1.8.8c.3.7.3 1.3.1 1.8l1.9.7c.3-1.2.3-2.3-.2-3.3zm-4.2 5.4l1.3 1.5c1-1 1.7-1.6 2-2l-1.5-1.3c-.7.8-1.3 1.4-1.8 1.8zm-7.3 4.3c0 1.9 1.6 3.5 3.5 3.5s3.5-1.6 3.5-3.5-1.6-3.5-3.5-3.5-3.5 1.6-3.5 3.5zM.095 8l1-1 1.5 1.5 1.5-1.5 1 1-1.5 1.5 1.5 1.5-1 1-1.5-1.5-1.5 1.5-1-1 1.5-1.5z"/>
+ <circle cx="8" cy="5" r="2" transform="matrix(-1 0 0 1 24.095 0)"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-invert.png
new file mode 100644
index 00000000..0f64c023
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-invert.svg
new file mode 100644
index 00000000..cb54763a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="markup">
+ <path id="left-bracket" d="M9.665 6.32l-4.259 4.274-1.406 1.406 1.406 1.406 4.259 4.274 1.406-1.438-4.259-4.243 4.259-4.243z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" xlink:href="#left-bracket"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-progressive.png
new file mode 100644
index 00000000..47ac7309
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-progressive.svg
new file mode 100644
index 00000000..af2f0ff1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="markup">
+ <path id="left-bracket" d="M9.665 6.32l-4.259 4.274-1.406 1.406 1.406 1.406 4.259 4.274 1.406-1.438-4.259-4.243 4.259-4.243z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" xlink:href="#left-bracket"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup.png
new file mode 100644
index 00000000..c78f4185
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup.svg
new file mode 100644
index 00000000..7f8c2535
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/markup.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="markup">
+ <path id="left-bracket" d="M9.665 6.32l-4.259 4.274-1.406 1.406 1.406 1.406 4.259 4.274 1.406-1.438-4.259-4.243 4.259-4.243z"/>
+ <use transform="matrix(-1 0 0 1 24 0)" id="right-bracket" xlink:href="#left-bracket"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-invert.png
new file mode 100644
index 00000000..b61db4a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-invert.svg
new file mode 100644
index 00000000..e87b9bf5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="menu">
+ <path id="lines" d="M6 15h12a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1zm-1-4v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1zm0-5v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-progressive.png
new file mode 100644
index 00000000..f395e3a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-progressive.svg
new file mode 100644
index 00000000..6d9edd17
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="menu">
+ <path id="lines" d="M6 15h12a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1zm-1-4v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1zm0-5v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu.png
new file mode 100644
index 00000000..d2278db8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu.svg
new file mode 100644
index 00000000..a33c21ca
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/menu.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="menu">
+ <path id="lines" d="M6 15h12a1 1 0 0 1 1 1v1a1 1 0 0 1-1 1H6a1 1 0 0 1-1-1v-1a1 1 0 0 1 1-1zm-1-4v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-1a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1zm0-5v1a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1H6a1 1 0 0 0-1 1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-invert.png
new file mode 100644
index 00000000..33a98009
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-invert.svg
new file mode 100644
index 00000000..a3aae219
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M21 9c0-1.7-1.3-3-3-3H3v3l9 4 9-4zM3 11v6c0 1.7 1.3 3 3 3h15v-9l-9 4-9-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-progressive.png
new file mode 100644
index 00000000..fb11ff29
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-progressive.svg
new file mode 100644
index 00000000..36bfd0c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M21 9c0-1.7-1.3-3-3-3H3v3l9 4 9-4zM3 11v6c0 1.7 1.3 3 3 3h15v-9l-9 4-9-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr.png
new file mode 100644
index 00000000..2171c1f3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr.svg
new file mode 100644
index 00000000..842d312c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 9c0-1.7-1.3-3-3-3H3v3l9 4 9-4zM3 11v6c0 1.7 1.3 3 3 3h15v-9l-9 4-9-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-invert.png
new file mode 100644
index 00000000..c2d617b4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-invert.svg
new file mode 100644
index 00000000..0a52eecb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M3 9c0-1.7 1.3-3 3-3h15v3l-9 4-9-4zm18 2v6c0 1.7-1.3 3-3 3H3v-9l9 4 9-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-progressive.png
new file mode 100644
index 00000000..a6975d73
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-progressive.svg
new file mode 100644
index 00000000..0beb5ee3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M3 9c0-1.7 1.3-3 3-3h15v3l-9 4-9-4zm18 2v6c0 1.7-1.3 3-3 3H3v-9l9 4 9-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl.png
new file mode 100644
index 00000000..fba79205
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl.svg
new file mode 100644
index 00000000..0a22c751
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/message-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 9c0-1.7 1.3-3 3-3h15v3l-9 4-9-4zm18 2v6c0 1.7-1.3 3-3 3H3v-9l9 4 9-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon-invert.png
new file mode 100644
index 00000000..38bcc0ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon-invert.svg
new file mode 100644
index 00000000..7ecd512b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M19.1 17.5c-3.3 1.4-7.1-.2-8.5-3.5-1.4-3.3.2-7.1 3.5-8.5.2-.1.5-.2.7-.3-1.6-.4-3.2-.3-4.8.4C6 7.3 4 12 5.7 16c1.7 4.1 6.4 6 10.5 4.3 1.7-.7 3-1.9 3.8-3.4-.3.3-.6.4-.9.6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon.png
new file mode 100644
index 00000000..7aef8bd8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon.svg
new file mode 100644
index 00000000..bdbf2346
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/moon.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19.1 17.5c-3.3 1.4-7.1-.2-8.5-3.5-1.4-3.3.2-7.1 3.5-8.5.2-.1.5-.2.7-.3-1.6-.4-3.2-.3-4.8.4C6 7.3 4 12 5.7 16c1.7 4.1 6.4 6 10.5 4.3 1.7-.7 3-1.9 3.8-3.4-.3.3-.6.4-.9.6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-invert.png
new file mode 100644
index 00000000..43f819ff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-invert.svg
new file mode 100644
index 00000000..f5b4b228
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="move-end-ltr">
+ <path id="arrow" d="M7.935 7.18l5.302 5.303-5.302 5.303L9.35 19.2l6.715-6.717L9.35 5.767z"/>
+ <path id="bar" d="M16 7h2v11h-2z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-progressive.png
new file mode 100644
index 00000000..cbbfa795
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-progressive.svg
new file mode 100644
index 00000000..d55fc517
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="move-end-ltr">
+ <path id="arrow" d="M7.935 7.18l5.302 5.303-5.302 5.303L9.35 19.2l6.715-6.717L9.35 5.767z"/>
+ <path id="bar" d="M16 7h2v11h-2z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr.png
new file mode 100644
index 00000000..9d35b9ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr.svg
new file mode 100644
index 00000000..98adcf7a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="move-end-ltr">
+ <path id="arrow" d="M7.935 7.18l5.302 5.303-5.302 5.303L9.35 19.2l6.715-6.717L9.35 5.767z"/>
+ <path id="bar" d="M16 7h2v11h-2z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-invert.png
new file mode 100644
index 00000000..a745af24
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-invert.svg
new file mode 100644
index 00000000..121b08d4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-invert.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="move-end-ltr">
+ <path id="arrow" d="M16.065 17.786l-5.302-5.303 5.302-5.302-1.415-1.41-6.714 6.72 6.714 6.71z"/>
+ <path id="bar" d="M6 7h2v11H6z"/>
+ </g>
+</g></svg>
+
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-progressive.png
new file mode 100644
index 00000000..b999538c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-progressive.svg
new file mode 100644
index 00000000..11ed9343
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl-progressive.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="move-end-ltr">
+ <path id="arrow" d="M16.065 17.786l-5.302-5.303 5.302-5.302-1.415-1.41-6.714 6.72 6.714 6.71z"/>
+ <path id="bar" d="M6 7h2v11H6z"/>
+ </g>
+</g></svg>
+
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl.png
new file mode 100644
index 00000000..bcd8a0c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl.svg
new file mode 100644
index 00000000..ee09f7c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-end-rtl.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="move-end-ltr">
+ <path id="arrow" d="M16.065 17.786l-5.302-5.303 5.302-5.302-1.415-1.41-6.714 6.72 6.714 6.71z"/>
+ <path id="bar" d="M6 7h2v11H6z"/>
+ </g>
+</svg>
+
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-invert.png
new file mode 100644
index 00000000..6d7e5eca
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-invert.svg
new file mode 100644
index 00000000..2da24a5f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M20 11l-4-3v2h-3V7h2l-3-4-3 4h2v3H8V8l-4 3 4 3v-2h3v3H9l3 4 3-4h-2v-3h3v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-invert.png
new file mode 100644
index 00000000..fe5f614c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-invert.svg
new file mode 100644
index 00000000..468ad1bd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="move-ltr">
+ <path id="arrow" d="M8.935 7.18l5.302 5.303-5.302 5.303L10.35 19.2l6.715-6.717-6.716-6.716z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-progressive.png
new file mode 100644
index 00000000..5f37c254
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-progressive.svg
new file mode 100644
index 00000000..dd478817
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="move-ltr">
+ <path id="arrow" d="M8.935 7.18l5.302 5.303-5.302 5.303L10.35 19.2l6.715-6.717-6.716-6.716z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr.png
new file mode 100644
index 00000000..b57d8daa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr.svg
new file mode 100644
index 00000000..670d84d1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="move-ltr">
+ <path id="arrow" d="M8.935 7.18l5.302 5.303-5.302 5.303L10.35 19.2l6.715-6.717-6.716-6.716z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-progressive.png
new file mode 100644
index 00000000..c2d6a849
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-progressive.svg
new file mode 100644
index 00000000..6274f6f5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M20 11l-4-3v2h-3V7h2l-3-4-3 4h2v3H8V8l-4 3 4 3v-2h3v3H9l3 4 3-4h-2v-3h3v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-invert.png
new file mode 100644
index 00000000..cfca1e24
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-invert.svg
new file mode 100644
index 00000000..264f3b6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="move-rtl">
+ <path id="arrow" d="M15.065 17.786l-5.302-5.303 5.302-5.302-1.415-1.41-6.714 6.72 6.714 6.71z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-progressive.png
new file mode 100644
index 00000000..3dbedd59
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-progressive.svg
new file mode 100644
index 00000000..32aee25d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="move-rtl">
+ <path id="arrow" d="M15.065 17.786l-5.302-5.303 5.302-5.302-1.415-1.41-6.714 6.72 6.714 6.71z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl.png
new file mode 100644
index 00000000..e401a8f8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl.svg
new file mode 100644
index 00000000..ce5b444f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="move-rtl">
+ <path id="arrow" d="M15.065 17.786l-5.302-5.303 5.302-5.302-1.415-1.41-6.714 6.72 6.714 6.71z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move.png
new file mode 100644
index 00000000..7071499f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move.svg
new file mode 100644
index 00000000..b04ecdd4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/move.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 11l-4-3v2h-3V7h2l-3-4-3 4h2v3H8V8l-4 3 4 3v-2h3v3H9l3 4 3-4h-2v-3h3v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-invert.png
new file mode 100644
index 00000000..5e432b04
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-invert.svg
new file mode 100644
index 00000000..bc7fedc0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 5l2.5 2.5L11 11c-1.2 1.2-1.2 2.8 0 4l5.5-5.5L19 12V5h-7zm5 12H8c-.6 0-1-.4-1-1V7h3L8 5H5v11c0 1.7 1.3 3 3 3h11v-3l-2-2v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-progressive.png
new file mode 100644
index 00000000..26be088b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-progressive.svg
new file mode 100644
index 00000000..1ef309ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 5l2.5 2.5L11 11c-1.2 1.2-1.2 2.8 0 4l5.5-5.5L19 12V5h-7zm5 12H8c-.6 0-1-.4-1-1V7h3L8 5H5v11c0 1.7 1.3 3 3 3h11v-3l-2-2v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr.png
new file mode 100644
index 00000000..29563d87
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr.svg
new file mode 100644
index 00000000..2d19a78f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5l2.5 2.5L11 11c-1.2 1.2-1.2 2.8 0 4l5.5-5.5L19 12V5h-7zm5 12H8c-.6 0-1-.4-1-1V7h3L8 5H5v11c0 1.7 1.3 3 3 3h11v-3l-2-2v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-invert.png
new file mode 100644
index 00000000..f9a742e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-invert.svg
new file mode 100644
index 00000000..41e0401d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 5L9.5 7.5 13 11c1.2 1.2 1.2 2.8 0 4L7.5 9.5 5 12V5h7zM7 17h9c.6 0 1-.4 1-1V7h-3l2-2h3v11c0 1.7-1.3 3-3 3H5v-3l2-2v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-progressive.png
new file mode 100644
index 00000000..10e2735a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-progressive.svg
new file mode 100644
index 00000000..a877db8e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 5L9.5 7.5 13 11c1.2 1.2 1.2 2.8 0 4L7.5 9.5 5 12V5h7zM7 17h9c.6 0 1-.4 1-1V7h-3l2-2h3v11c0 1.7-1.3 3-3 3H5v-3l2-2v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl.png
new file mode 100644
index 00000000..c49609f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl.svg
new file mode 100644
index 00000000..133442ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newWindow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5L9.5 7.5 13 11c1.2 1.2 1.2 2.8 0 4L7.5 9.5 5 12V5h7zM7 17h9c.6 0 1-.4 1-1V7h-3l2-2h3v11c0 1.7-1.3 3-3 3H5v-3l2-2v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-invert.png
new file mode 100644
index 00000000..874ff294
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-invert.svg
new file mode 100644
index 00000000..6ec89721
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M17.8 5.7c-.5 0-.9.2-1.2.5s-.5.7-.5 1.2v4.3H11v-4l-6 5.5 6 5.5v-4h8v-9h-1.2z" id="line_return"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-progressive.png
new file mode 100644
index 00000000..67ec9694
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-progressive.svg
new file mode 100644
index 00000000..b0e6aafe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M17.8 5.7c-.5 0-.9.2-1.2.5s-.5.7-.5 1.2v4.3H11v-4l-6 5.5 6 5.5v-4h8v-9h-1.2z" id="line_return"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr.png
new file mode 100644
index 00000000..f41eb0c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr.svg
new file mode 100644
index 00000000..a7e5b126
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.8 5.7c-.5 0-.9.2-1.2.5s-.5.7-.5 1.2v4.3H11v-4l-6 5.5 6 5.5v-4h8v-9h-1.2z" id="line_return"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-invert.png
new file mode 100644
index 00000000..99be840f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-invert.svg
new file mode 100644
index 00000000..c9196080
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M6.2 5.7c.5 0 .9.2 1.2.5.3.3.5.7.5 1.2v4.3H13v-4l6 5.5-6 5.5v-4H5v-9h1.2z" id="line_return"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-progressive.png
new file mode 100644
index 00000000..8e748e51
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-progressive.svg
new file mode 100644
index 00000000..1547e824
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M6.2 5.7c.5 0 .9.2 1.2.5.3.3.5.7.5 1.2v4.3H13v-4l6 5.5-6 5.5v-4H5v-9h1.2z" id="line_return"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl.png
new file mode 100644
index 00000000..93c7e52c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl.svg
new file mode 100644
index 00000000..40752fa7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newline-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6.2 5.7c.5 0 .9.2 1.2.5.3.3.5.7.5 1.2v4.3H13v-4l6 5.5-6 5.5v-4H5v-9h1.2z" id="line_return"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-invert.png
new file mode 100644
index 00000000..3f48ede6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-invert.svg
new file mode 100644
index 00000000..69b737a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M6 7v12c-.6 0-1-.4-1-1V9H4v9c0 1.1.9 2 2 2h15V7H6zm9 11H8v-1h7v1zm0-2H8v-1h7v1zm0-2H8v-1h7v1zm4 4h-3v-5h3v5zm0-7H8V9h11v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-progressive.png
new file mode 100644
index 00000000..182f3162
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-progressive.svg
new file mode 100644
index 00000000..df59aacc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M6 7v12c-.6 0-1-.4-1-1V9H4v9c0 1.1.9 2 2 2h15V7H6zm9 11H8v-1h7v1zm0-2H8v-1h7v1zm0-2H8v-1h7v1zm4 4h-3v-5h3v5zm0-7H8V9h11v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr.png
new file mode 100644
index 00000000..ccd64748
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr.svg
new file mode 100644
index 00000000..4ff58564
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6 7v12c-.6 0-1-.4-1-1V9H4v9c0 1.1.9 2 2 2h15V7H6zm9 11H8v-1h7v1zm0-2H8v-1h7v1zm0-2H8v-1h7v1zm4 4h-3v-5h3v5zm0-7H8V9h11v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-invert.png
new file mode 100644
index 00000000..85cfa839
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-invert.svg
new file mode 100644
index 00000000..74fa337c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M19 7v12c.6 0 1-.4 1-1V9h1v9c0 1.1-.9 2-2 2H4V7h15zm-9 11h7v-1h-7v1zm0-2h7v-1h-7v1zm0-2h7v-1h-7v1zm-4 4h3v-5H6v5zm0-7h11V9H6v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-progressive.png
new file mode 100644
index 00000000..8a6d99cf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-progressive.svg
new file mode 100644
index 00000000..5533c83d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M19 7v12c.6 0 1-.4 1-1V9h1v9c0 1.1-.9 2-2 2H4V7h15zm-9 11h7v-1h-7v1zm0-2h7v-1h-7v1zm0-2h7v-1h-7v1zm-4 4h3v-5H6v5zm0-7h11V9H6v2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl.png
new file mode 100644
index 00000000..b5df1df6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl.svg
new file mode 100644
index 00000000..f9d4e557
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/newspaper-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19 7v12c.6 0 1-.4 1-1V9h1v9c0 1.1-.9 2-2 2H4V7h15zm-9 11h7v-1h-7v1zm0-2h7v-1h-7v1zm0-2h7v-1h-7v1zm-4 4h3v-5H6v5zm0-7h11V9H6v2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-invert.png
new file mode 100644
index 00000000..a17092ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-invert.svg
new file mode 100644
index 00000000..d4cad393
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M15 13l2 2V5h-3v2h1zM3 3L2 4l1 1v14h3v-2H5V7l2 2v10h3v-2H9v-6l6 6h-1v2h3l3 3 1-1-3-3zm7 4V5H7l2 2zm8-2v2h1v10l2 2V5z" id="noWikiText-rtl"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-progressive.png
new file mode 100644
index 00000000..2ac38b36
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-progressive.svg
new file mode 100644
index 00000000..3fb2dd9d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M15 13l2 2V5h-3v2h1zM3 3L2 4l1 1v14h3v-2H5V7l2 2v10h3v-2H9v-6l6 6h-1v2h3l3 3 1-1-3-3zm7 4V5H7l2 2zm8-2v2h1v10l2 2V5z" id="noWikiText-rtl"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr.png
new file mode 100644
index 00000000..2623b845
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr.svg
new file mode 100644
index 00000000..2dfa2c73
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M15 13l2 2V5h-3v2h1zM3 3L2 4l1 1v14h3v-2H5V7l2 2v10h3v-2H9v-6l6 6h-1v2h3l3 3 1-1-3-3zm7 4V5H7l2 2zm8-2v2h1v10l2 2V5z" id="noWikiText-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-invert.png
new file mode 100644
index 00000000..1f7ed87c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-invert.svg
new file mode 100644
index 00000000..346c5826
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M9 13l-2 2V5h3v2H9zM21 3l1 1-1 1v14h-3v-2h1V7l-2 2v10h-3v-2h1v-6l-6 6h1v2H7l-3 3-1-1 3-3zm-7 4V5h3l-2 2zM6 5v2H5v10l-2 2V5z" id="noWikiText-rtl"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-progressive.png
new file mode 100644
index 00000000..aba76c89
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-progressive.svg
new file mode 100644
index 00000000..9915009c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M9 13l-2 2V5h3v2H9zM21 3l1 1-1 1v14h-3v-2h1V7l-2 2v10h-3v-2h1v-6l-6 6h1v2H7l-3 3-1-1 3-3zm-7 4V5h3l-2 2zM6 5v2H5v10l-2 2V5z" id="noWikiText-rtl"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl.png
new file mode 100644
index 00000000..4d0ce869
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl.svg
new file mode 100644
index 00000000..4f275fd6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/noWikiText-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M9 13l-2 2V5h3v2H9zM21 3l1 1-1 1v14h-3v-2h1V7l-2 2v10h-3v-2h1v-6l-6 6h1v2H7l-3 3-1-1 3-3zm-7 4V5h3l-2 2zM6 5v2H5v10l-2 2V5z" id="noWikiText-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright-invert.png
new file mode 100644
index 00000000..de7e5297
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright-invert.svg
new file mode 100644
index 00000000..ca20b5ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright.png
new file mode 100644
index 00000000..5273b4c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright.svg
new file mode 100644
index 00000000..af87ff9f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notBright.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 5c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-invert.png
new file mode 100644
index 00000000..e18795b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-invert.svg
new file mode 100644
index 00000000..a0f8ddc4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="svg3116"><g fill="#fff">
+ <path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm-1-5h2V8h-2zm0 3h2v-2h-2z" id="alert"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-progressive.png
new file mode 100644
index 00000000..52e8b87e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-progressive.svg
new file mode 100644
index 00000000..d8281217
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="svg3116"><g fill="#36c">
+ <path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm-1-5h2V8h-2zm0 3h2v-2h-2z" id="alert"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice.png
new file mode 100644
index 00000000..114020ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice.svg
new file mode 100644
index 00000000..8dc4fec7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/notice.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" id="svg3116">
+ <path d="M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm-1-5h2V8h-2zm0 3h2v-2h-2z" id="alert"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-invert.png
new file mode 100644
index 00000000..9bfc1a66
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-invert.svg
new file mode 100644
index 00000000..0e9b26a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g fill="#fff">
+ <path id="ongoing-conversation" d="M17.3 18h-15L5 15.3V6h15v9.3c0 1.53-1.17 2.7-2.7 2.7zm-7.474-4.35c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-progressive.png
new file mode 100644
index 00000000..97f976e4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-progressive.svg
new file mode 100644
index 00000000..727aa2b8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g fill="#36c">
+ <path id="ongoing-conversation" d="M17.3 18h-15L5 15.3V6h15v9.3c0 1.53-1.17 2.7-2.7 2.7zm-7.474-4.35c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr.png
new file mode 100644
index 00000000..f48650b6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr.svg
new file mode 100644
index 00000000..e1c92811
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
+ <path id="ongoing-conversation" d="M17.3 18h-15L5 15.3V6h15v9.3c0 1.53-1.17 2.7-2.7 2.7zm-7.474-4.35c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945zm4.05 0c0 .405-.135.675-.405.945-.27.27-.607.405-.945.405-.405 0-.675-.135-.945-.405a1.332 1.332 0 0 1-.405-.945c0-.338.135-.675.405-.945.27-.27.608-.405.945-.405.338 0 .675.135.945.405.27.27.405.607.405.945z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-invert.png
new file mode 100644
index 00000000..5518dd5a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-invert.svg
new file mode 100644
index 00000000..96db3a9e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g fill="#fff">
+ <path id="ongoing-conversation" d="M6.7 18h15L19 15.3V6H4v9.3C4 16.83 5.17 18 6.7 18zm7.474-4.35c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.256-.248.402-.588.405-.945 0-.338-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.256-.248.402-.588.405-.945 0-.338-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.256-.248.402-.588.405-.945 0-.338-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-progressive.png
new file mode 100644
index 00000000..0404c871
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-progressive.svg
new file mode 100644
index 00000000..1c99c34d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><g fill="#36c">
+ <path id="ongoing-conversation" d="M6.7 18h15L19 15.3V6H4v9.3C4 16.83 5.17 18 6.7 18zm7.474-4.35c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.256-.248.402-.588.405-.945 0-.338-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.256-.248.402-.588.405-.945 0-.338-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.256-.248.402-.588.405-.945 0-.338-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl.png
new file mode 100644
index 00000000..7ef8cc46
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl.svg
new file mode 100644
index 00000000..ac756ef6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/ongoingConversation-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg width="24" height="24" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
+ <path id="ongoing-conversation" d="M6.7 18h15L19 15.3V6H4v9.3C4 16.83 5.17 18 6.7 18zm7.474-4.35c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.256-.248.402-.588.405-.945 0-.338-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.256-.248.402-.588.405-.945 0-.338-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945zm-4.05 0c0 .405.135.675.405.945.27.27.607.405.945.405.405 0 .675-.135.945-.405.256-.248.402-.588.405-.945 0-.338-.135-.675-.405-.945a1.334 1.334 0 0 0-.945-.405c-.338 0-.675.135-.945.405-.27.27-.405.607-.405.945z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-invert.png
new file mode 100644
index 00000000..6bb2f992
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-invert.svg
new file mode 100644
index 00000000..efdbe9a5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M10 8h9v2h-9V8zm0 3h9v2h-9v-2zm0 3h6v2h-6v-2zm11-8H3V4h18v2zm0 14H3v-2h18v2zM3 12l5 4V8l-5 4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-progressive.png
new file mode 100644
index 00000000..00e8a093
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-progressive.svg
new file mode 100644
index 00000000..29e5f421
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M10 8h9v2h-9V8zm0 3h9v2h-9v-2zm0 3h6v2h-6v-2zm11-8H3V4h18v2zm0 14H3v-2h18v2zM3 12l5 4V8l-5 4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr.png
new file mode 100644
index 00000000..c1cd66a1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr.svg
new file mode 100644
index 00000000..c004db0f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10 8h9v2h-9V8zm0 3h9v2h-9v-2zm0 3h6v2h-6v-2zm11-8H3V4h18v2zm0 14H3v-2h18v2zM3 12l5 4V8l-5 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-invert.png
new file mode 100644
index 00000000..eb3d7005
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-invert.svg
new file mode 100644
index 00000000..3a9d2b53
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M14 8H5v2h9V8zm0 3H5v2h9v-2zm0 3H8v2h6v-2zM3 6h18V4H3v2zm0 14h18v-2H3v2zm18-8l-5 4V8l5 4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-progressive.png
new file mode 100644
index 00000000..b0223bf4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-progressive.svg
new file mode 100644
index 00000000..560abbb9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M14 8H5v2h9V8zm0 3H5v2h9v-2zm0 3H8v2h6v-2zM3 6h18V4H3v2zm0 14h18v-2H3v2zm18-8l-5 4V8l5 4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl.png
new file mode 100644
index 00000000..a1d94545
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl.svg
new file mode 100644
index 00000000..a71bfdc6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outdent-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M14 8H5v2h9V8zm0 3H5v2h9v-2zm0 3H8v2h6v-2zM3 6h18V4H3v2zm0 14h18v-2H3v2zm18-8l-5 4V8l5 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-invert.png
new file mode 100644
index 00000000..eceedbdd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-invert.svg
new file mode 100644
index 00000000..e9fb8180
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="outline-ltr">
+ <path id="text" d="M5 13h14v6H5v-6z"/>
+ <path id="float" d="M5 5v6h6V5H5zm5 5H6V6h4v4z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-progressive.png
new file mode 100644
index 00000000..df70c26d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-progressive.svg
new file mode 100644
index 00000000..662409a5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="outline-ltr">
+ <path id="text" d="M5 13h14v6H5v-6z"/>
+ <path id="float" d="M5 5v6h6V5H5zm5 5H6V6h4v4z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr.png
new file mode 100644
index 00000000..bcbfa5ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr.svg
new file mode 100644
index 00000000..44c1591d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="outline-ltr">
+ <path id="text" d="M5 13h14v6H5v-6z"/>
+ <path id="float" d="M5 5v6h6V5H5zm5 5H6V6h4v4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-invert.png
new file mode 100644
index 00000000..96c4719a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-invert.svg
new file mode 100644
index 00000000..74689d16
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="outline-rtl">
+ <path id="text" d="M19 19H5v-6h14v6z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm1 1h4v4h-4V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-progressive.png
new file mode 100644
index 00000000..f5af3f30
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-progressive.svg
new file mode 100644
index 00000000..b579315d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="outline-rtl">
+ <path id="text" d="M19 19H5v-6h14v6z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm1 1h4v4h-4V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl.png
new file mode 100644
index 00000000..d89e06e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl.svg
new file mode 100644
index 00000000..c5b19c8f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/outline-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="outline-rtl">
+ <path id="text" d="M19 19H5v-6h14v6z"/>
+ <path id="float" d="M13 5v6h6V5h-6zm1 1h4v4h-4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-invert.png
new file mode 100644
index 00000000..ce979ac4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-invert.svg
new file mode 100644
index 00000000..f5a1a926
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm-2 12V8l6 4-6 4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-progressive.png
new file mode 100644
index 00000000..c3e1dd84
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-progressive.svg
new file mode 100644
index 00000000..e8aa2966
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm-2 12V8l6 4-6 4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr.png
new file mode 100644
index 00000000..ef332517
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr.svg
new file mode 100644
index 00000000..e9704fdf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm-2 12V8l6 4-6 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-invert.png
new file mode 100644
index 00000000..028afa30
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-invert.svg
new file mode 100644
index 00000000..5904dcb8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 4c4.4 0 8 3.6 8 8s-3.6 8-8 8-8-3.6-8-8 3.6-8 8-8zm2 12V8l-6 4 6 4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-progressive.png
new file mode 100644
index 00000000..8a6f4dd5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-progressive.svg
new file mode 100644
index 00000000..13e17653
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 4c4.4 0 8 3.6 8 8s-3.6 8-8 8-8-3.6-8-8 3.6-8 8-8zm2 12V8l-6 4 6 4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl.png
new file mode 100644
index 00000000..a8c59a95
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl.svg
new file mode 100644
index 00000000..ec0dcf21
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/play-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 4c4.4 0 8 3.6 8 8s-3.6 8-8 8-8-3.6-8-8 3.6-8 8-8zm2 12V8l-6 4 6 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-invert.png
new file mode 100644
index 00000000..ca07bcc1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-invert.svg
new file mode 100644
index 00000000..ae4352f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M18 8h-1V4H7v4H3v6c0 1.7 1.3 3 3 3h1v3h10v-3h4v-6c0-1.7-1.3-3-3-3zM8 5h8v3H8V5zm8 14H8v-6h8v6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-progressive.png
new file mode 100644
index 00000000..e37b3ea8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-progressive.svg
new file mode 100644
index 00000000..fb372de6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M18 8h-1V4H7v4H3v6c0 1.7 1.3 3 3 3h1v3h10v-3h4v-6c0-1.7-1.3-3-3-3zM8 5h8v3H8V5zm8 14H8v-6h8v6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr.png
new file mode 100644
index 00000000..a7f67176
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr.svg
new file mode 100644
index 00000000..7081606b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18 8h-1V4H7v4H3v6c0 1.7 1.3 3 3 3h1v3h10v-3h4v-6c0-1.7-1.3-3-3-3zM8 5h8v3H8V5zm8 14H8v-6h8v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-invert.png
new file mode 100644
index 00000000..95ef54a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-invert.svg
new file mode 100644
index 00000000..d045ff95
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M6 8h1V4h10v4h4v6c0 1.7-1.3 3-3 3h-1v3H7v-3H3v-6c0-1.7 1.3-3 3-3zm10-3H8v3h8V5zM8 19h8v-6H8v6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-progressive.png
new file mode 100644
index 00000000..0a0a1983
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-progressive.svg
new file mode 100644
index 00000000..91ccc6fa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M6 8h1V4h10v4h4v6c0 1.7-1.3 3-3 3h-1v3H7v-3H3v-6c0-1.7 1.3-3 3-3zm10-3H8v3h8V5zM8 19h8v-6H8v6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl.png
new file mode 100644
index 00000000..6e5b1756
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl.svg
new file mode 100644
index 00000000..d6188ebb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/printer-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6 8h1V4h10v4h4v6c0 1.7-1.3 3-3 3h-1v3H7v-3H3v-6c0-1.7 1.3-3 3-3zm10-3H8v3h8V5zM8 19h8v-6H8v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-invert.png
new file mode 100644
index 00000000..10c46ef9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-invert.svg
new file mode 100644
index 00000000..9bee56b8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M17.445 12.225c-.813-.935-1.775-.739-2.883-1.768-.55-.511-.498-2.36-.498-2.36s-.041-1.836.524-2.401c.39-.39 1.076-.49 1.475-.883a.973.973 0 0 0 .217-.317c.007-.013.014-.023.018-.035.035-.092.054-.2.064-.316.003-.03.017-.055.017-.085 0-.005-.003-.01-.004-.015.001-.008.004-.014.004-.022 0-.02-.015-.03-.017-.048a1.052 1.052 0 0 0-1.043-.974H8.681c-.555 0-.997.43-1.043.974-.002.018-.017.028-.017.048 0 .008.003.014.003.022 0 .006-.003.01-.003.015 0 .03.014.055.017.085.01.116.029.224.064.316.004.012.012.022.018.035a.965.965 0 0 0 .217.317c.399.393 1.084.493 1.475.883.565.565.523 2.401.523 2.401s.053 1.849-.497 2.36c-1.108 1.03-2.07.833-2.883 1.768C5.979 12.887 6 14 6 14h5.333v4.578L12 21l.668-2.422V14H18s.02-1.113-.555-1.775z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-progressive.png
new file mode 100644
index 00000000..ea2ec8c6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-progressive.svg
new file mode 100644
index 00000000..1cc4d607
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M17.445 12.225c-.813-.935-1.775-.739-2.883-1.768-.55-.511-.498-2.36-.498-2.36s-.041-1.836.524-2.401c.39-.39 1.076-.49 1.475-.883a.973.973 0 0 0 .217-.317c.007-.013.014-.023.018-.035.035-.092.054-.2.064-.316.003-.03.017-.055.017-.085 0-.005-.003-.01-.004-.015.001-.008.004-.014.004-.022 0-.02-.015-.03-.017-.048a1.052 1.052 0 0 0-1.043-.974H8.681c-.555 0-.997.43-1.043.974-.002.018-.017.028-.017.048 0 .008.003.014.003.022 0 .006-.003.01-.003.015 0 .03.014.055.017.085.01.116.029.224.064.316.004.012.012.022.018.035a.965.965 0 0 0 .217.317c.399.393 1.084.493 1.475.883.565.565.523 2.401.523 2.401s.053 1.849-.497 2.36c-1.108 1.03-2.07.833-2.883 1.768C5.979 12.887 6 14 6 14h5.333v4.578L12 21l.668-2.422V14H18s.02-1.113-.555-1.775z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin.png
new file mode 100644
index 00000000..27d49e21
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin.svg
new file mode 100644
index 00000000..b852cd06
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/pushPin.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.445 12.225c-.813-.935-1.775-.739-2.883-1.768-.55-.511-.498-2.36-.498-2.36s-.041-1.836.524-2.401c.39-.39 1.076-.49 1.475-.883a.973.973 0 0 0 .217-.317c.007-.013.014-.023.018-.035.035-.092.054-.2.064-.316.003-.03.017-.055.017-.085 0-.005-.003-.01-.004-.015.001-.008.004-.014.004-.022 0-.02-.015-.03-.017-.048a1.052 1.052 0 0 0-1.043-.974H8.681c-.555 0-.997.43-1.043.974-.002.018-.017.028-.017.048 0 .008.003.014.003.022 0 .006-.003.01-.003.015 0 .03.014.055.017.085.01.116.029.224.064.316.004.012.012.022.018.035a.965.965 0 0 0 .217.317c.399.393 1.084.493 1.475.883.565.565.523 2.401.523 2.401s.053 1.849-.497 2.36c-1.108 1.03-2.07.833-2.883 1.768C5.979 12.887 6 14 6 14h5.333v4.578L12 21l.668-2.422V14H18s.02-1.113-.555-1.775z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-invert.png
new file mode 100644
index 00000000..0c5f4b29
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-invert.svg
new file mode 100644
index 00000000..659f4fea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path id="puzzle-piece" d="M19.46 10.417c-.351-.404-1.641-.501-1.983-.162-.769.758-1.926 1.308-1.952.162.088-2.081.818-3.743.818-3.743a.46.46 0 0 0-.463-.456s-1.586-.111-3.59-.164l-1.25-.001c-.127.406.274 1.09.782 1.604.339.344.242 1.633-.162 1.984-.393.34-1.197.539-1.662.539-.445 0-1.222-.158-1.612-.479-.438-.356-.332-1.686.02-2.044.47-.476.838-1.185.721-1.606h-.483c-2.074.05-3.514.167-3.514.167a.46.46 0 0 0-.463.456s-.558 2.58-.558 5.348c0 2.762.558 5.331.558 5.331a.46.46 0 0 0 .463.457s2.615.19 5.493.19c2.723 0 5.258-.19 5.258-.19a.46.46 0 0 0 .463-.457s-.739-1.73-.824-3.869c.031-1.004 1.255-.506 1.958.188.356.353 1.688.458 2.045.021.318-.392.477-1.169.477-1.614 0-.465-.199-1.269-.54-1.662z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-progressive.png
new file mode 100644
index 00000000..45d48457
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-progressive.svg
new file mode 100644
index 00000000..de9f1624
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path id="puzzle-piece" d="M19.46 10.417c-.351-.404-1.641-.501-1.983-.162-.769.758-1.926 1.308-1.952.162.088-2.081.818-3.743.818-3.743a.46.46 0 0 0-.463-.456s-1.586-.111-3.59-.164l-1.25-.001c-.127.406.274 1.09.782 1.604.339.344.242 1.633-.162 1.984-.393.34-1.197.539-1.662.539-.445 0-1.222-.158-1.612-.479-.438-.356-.332-1.686.02-2.044.47-.476.838-1.185.721-1.606h-.483c-2.074.05-3.514.167-3.514.167a.46.46 0 0 0-.463.456s-.558 2.58-.558 5.348c0 2.762.558 5.331.558 5.331a.46.46 0 0 0 .463.457s2.615.19 5.493.19c2.723 0 5.258-.19 5.258-.19a.46.46 0 0 0 .463-.457s-.739-1.73-.824-3.869c.031-1.004 1.255-.506 1.958.188.356.353 1.688.458 2.045.021.318-.392.477-1.169.477-1.614 0-.465-.199-1.269-.54-1.662z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle.png
new file mode 100644
index 00000000..6ce22fe5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle.svg
new file mode 100644
index 00000000..cfcbbcc5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/puzzle.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="puzzle-piece" d="M19.46 10.417c-.351-.404-1.641-.501-1.983-.162-.769.758-1.926 1.308-1.952.162.088-2.081.818-3.743.818-3.743a.46.46 0 0 0-.463-.456s-1.586-.111-3.59-.164l-1.25-.001c-.127.406.274 1.09.782 1.604.339.344.242 1.633-.162 1.984-.393.34-1.197.539-1.662.539-.445 0-1.222-.158-1.612-.479-.438-.356-.332-1.686.02-2.044.47-.476.838-1.185.721-1.606h-.483c-2.074.05-3.514.167-3.514.167a.46.46 0 0 0-.463.456s-.558 2.58-.558 5.348c0 2.762.558 5.331.558 5.331a.46.46 0 0 0 .463.457s2.615.19 5.493.19c2.723 0 5.258-.19 5.258-.19a.46.46 0 0 0 .463-.457s-.739-1.73-.824-3.869c.031-1.004 1.255-.506 1.958.188.356.353 1.688.458 2.045.021.318-.392.477-1.169.477-1.614 0-.465-.199-1.269-.54-1.662z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-invert.png
new file mode 100644
index 00000000..46ac1813
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-invert.svg
new file mode 100644
index 00000000..7c9feea7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="quotes">
+ <path id="quote" d="M6.9 8.4c-.446.55-1.974 2.6-1.9 5.7V17h4.7c.9 0 1.6-.7 1.6-1.6V11H8.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ </g>
+ <use transform="translate(8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-progressive.png
new file mode 100644
index 00000000..ce64429d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-progressive.svg
new file mode 100644
index 00000000..c64995d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="quotes">
+ <path id="quote" d="M6.9 8.4c-.446.55-1.974 2.6-1.9 5.7V17h4.7c.9 0 1.6-.7 1.6-1.6V11H8.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ </g>
+ <use transform="translate(8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr.png
new file mode 100644
index 00000000..0252b746
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr.svg
new file mode 100644
index 00000000..dc366b7d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes">
+ <path id="quote" d="M6.9 8.4c-.446.55-1.974 2.6-1.9 5.7V17h4.7c.9 0 1.6-.7 1.6-1.6V11H8.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ </g>
+ <use transform="translate(8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-invert.png
new file mode 100644
index 00000000..6637ca22
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-invert.svg
new file mode 100644
index 00000000..baae1faf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="quotes">
+ <path id="quote" d="M17.1 8.4c.446.55 1.9 2.6 1.9 5.7V17h-4.7c-.9 0-1.6-.7-1.6-1.6V11h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ </g>
+ <use transform="translate(-8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-progressive.png
new file mode 100644
index 00000000..dff8962c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-progressive.svg
new file mode 100644
index 00000000..255faad4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="quotes">
+ <path id="quote" d="M17.1 8.4c.446.55 1.9 2.6 1.9 5.7V17h-4.7c-.9 0-1.6-.7-1.6-1.6V11h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ </g>
+ <use transform="translate(-8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl.png
new file mode 100644
index 00000000..7bcc7c7b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl.svg
new file mode 100644
index 00000000..e652b317
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotes-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes">
+ <path id="quote" d="M17.1 8.4c.446.55 1.9 2.6 1.9 5.7V17h-4.7c-.9 0-1.6-.7-1.6-1.6V11h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ </g>
+ <use transform="translate(-8)" id="quote2" width="24" height="24" xlink:href="#quote"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-invert.png
new file mode 100644
index 00000000..40e3a064
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-invert.svg
new file mode 100644
index 00000000..0d79616c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-invert.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="quotes-add">
+ <path id="quote" d="M5.9 10.4c-.446.55-1.974 2.6-1.9 5.7V19h4.7c.9 0 1.593-.7 1.6-1.6V13H7.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ <path id="quote2" d="M15 9.344c-.476.32-.78.677-1.094 1.062A8.76 8.76 0 0 0 12 16.094V19h4.688a1.6 1.6 0 0 0 1.625-1.594V13H15V9.344z"/>
+ <path id="add" d="M18 6V2h-2v4h-4v2h4v4h2V8h4V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-progressive.png
new file mode 100644
index 00000000..f36a0cab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-progressive.svg
new file mode 100644
index 00000000..755708d8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr-progressive.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="quotes-add">
+ <path id="quote" d="M5.9 10.4c-.446.55-1.974 2.6-1.9 5.7V19h4.7c.9 0 1.593-.7 1.6-1.6V13H7.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ <path id="quote2" d="M15 9.344c-.476.32-.78.677-1.094 1.062A8.76 8.76 0 0 0 12 16.094V19h4.688a1.6 1.6 0 0 0 1.625-1.594V13H15V9.344z"/>
+ <path id="add" d="M18 6V2h-2v4h-4v2h4v4h2V8h4V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr.png
new file mode 100644
index 00000000..e1a0c4ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr.svg
new file mode 100644
index 00000000..6704c516
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-ltr.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes-add">
+ <path id="quote" d="M5.9 10.4c-.446.55-1.974 2.6-1.9 5.7V19h4.7c.9 0 1.593-.7 1.6-1.6V13H7.2s.05-.74.6-1.4c.453-.543 1-.9 1.6-1.2.2-.1.47-.212.6-.5.127-.282.2-.5.2-.9v-.6c-1 .2-1.744.197-2.6.6-.856.403-1.272.873-1.7 1.4z"/>
+ <path id="quote2" d="M15 9.344c-.476.32-.78.677-1.094 1.062A8.76 8.76 0 0 0 12 16.094V19h4.688a1.6 1.6 0 0 0 1.625-1.594V13H15V9.344z"/>
+ <path id="add" d="M18 6V2h-2v4h-4v2h4v4h2V8h4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-invert.png
new file mode 100644
index 00000000..e15cc905
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-invert.svg
new file mode 100644
index 00000000..2a839f01
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-invert.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="quotes-add">
+ <path id="quote" d="M18.097 10.4c.446.55 1.974 2.6 1.9 5.7V19h-4.7c-.9 0-1.593-.7-1.6-1.6V13h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ <path id="quote2" d="M8.997 9.344c.476.32.782.677 1.094 1.062A8.758 8.758 0 0 1 12 16.094V19H7.31c-.9 0-1.618-.694-1.625-1.594V13h3.312V9.344z"/>
+ <path id="add" d="M5.997 6V2h2v4h4v2h-4v4h-2V8h-4V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-progressive.png
new file mode 100644
index 00000000..f8242592
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-progressive.svg
new file mode 100644
index 00000000..a5c10b4f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl-progressive.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="quotes-add">
+ <path id="quote" d="M18.097 10.4c.446.55 1.974 2.6 1.9 5.7V19h-4.7c-.9 0-1.593-.7-1.6-1.6V13h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ <path id="quote2" d="M8.997 9.344c.476.32.782.677 1.094 1.062A8.758 8.758 0 0 1 12 16.094V19H7.31c-.9 0-1.618-.694-1.625-1.594V13h3.312V9.344z"/>
+ <path id="add" d="M5.997 6V2h2v4h4v2h-4v4h-2V8h-4V6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl.png
new file mode 100644
index 00000000..0ef9d016
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl.svg
new file mode 100644
index 00000000..d972ad3a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/quotesAdd-rtl.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="quotes-add">
+ <path id="quote" d="M18.097 10.4c.446.55 1.974 2.6 1.9 5.7V19h-4.7c-.9 0-1.593-.7-1.6-1.6V13h3.1s-.05-.74-.6-1.4c-.453-.543-1-.9-1.6-1.2-.2-.1-.47-.212-.6-.5-.127-.282-.2-.5-.2-.9v-.6c1 .2 1.744.197 2.6.6.856.403 1.272.873 1.7 1.4z"/>
+ <path id="quote2" d="M8.997 9.344c.476.32.782.677 1.094 1.062A8.758 8.758 0 0 1 12 16.094V19H7.31c-.9 0-1.618-.694-1.625-1.594V13h3.312V9.344z"/>
+ <path id="add" d="M5.997 6V2h2v4h4v2h-4v4h-2V8h-4V6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-invert.png
new file mode 100644
index 00000000..0206be91
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-invert.svg
new file mode 100644
index 00000000..0cb419e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-invert.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="regular-expression">
+ <path id="left-bracket" d="M3 12.045c0-.99.15-1.915.45-2.777A6.886 6.886 0 0 1 4.764 7H6.23a7.923 7.923 0 0 0-1.25 2.374 8.563 8.563 0 0 0 .007 5.314c.29.85.7 1.622 1.23 2.312h-1.45a6.53 6.53 0 0 1-1.314-2.223 8.126 8.126 0 0 1-.45-2.732"/>
+ <path id="dot" d="M10 16a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
+ <path id="star" d="M14.25 7.013l-.24 2.156 2.187-.61.193 1.47-1.992.14 1.307 1.74-1.33.71-.914-1.833-.8 1.822-1.38-.698 1.296-1.74-1.98-.152.23-1.464 2.14.61-.24-2.158h1.534"/>
+ <path id="right-bracket" d="M21 12.045c0 .982-.152 1.896-.457 2.744A6.51 6.51 0 0 1 19.236 17h-1.453a8.017 8.017 0 0 0 1.225-2.31c.29-.855.434-1.74.434-2.66 0-.91-.14-1.797-.422-2.66a7.913 7.913 0 0 0-1.248-2.374h1.465a6.764 6.764 0 0 1 1.313 2.28c.3.86.45 1.782.45 2.764"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-progressive.png
new file mode 100644
index 00000000..af85e032
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-progressive.svg
new file mode 100644
index 00000000..5e2894b3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression-progressive.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="regular-expression">
+ <path id="left-bracket" d="M3 12.045c0-.99.15-1.915.45-2.777A6.886 6.886 0 0 1 4.764 7H6.23a7.923 7.923 0 0 0-1.25 2.374 8.563 8.563 0 0 0 .007 5.314c.29.85.7 1.622 1.23 2.312h-1.45a6.53 6.53 0 0 1-1.314-2.223 8.126 8.126 0 0 1-.45-2.732"/>
+ <path id="dot" d="M10 16a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
+ <path id="star" d="M14.25 7.013l-.24 2.156 2.187-.61.193 1.47-1.992.14 1.307 1.74-1.33.71-.914-1.833-.8 1.822-1.38-.698 1.296-1.74-1.98-.152.23-1.464 2.14.61-.24-2.158h1.534"/>
+ <path id="right-bracket" d="M21 12.045c0 .982-.152 1.896-.457 2.744A6.51 6.51 0 0 1 19.236 17h-1.453a8.017 8.017 0 0 0 1.225-2.31c.29-.855.434-1.74.434-2.66 0-.91-.14-1.797-.422-2.66a7.913 7.913 0 0 0-1.248-2.374h1.465a6.764 6.764 0 0 1 1.313 2.28c.3.86.45 1.782.45 2.764"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression.png
new file mode 100644
index 00000000..f27e4212
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression.svg
new file mode 100644
index 00000000..d5fcfcf0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/regular-expression.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="regular-expression">
+ <path id="left-bracket" d="M3 12.045c0-.99.15-1.915.45-2.777A6.886 6.886 0 0 1 4.764 7H6.23a7.923 7.923 0 0 0-1.25 2.374 8.563 8.563 0 0 0 .007 5.314c.29.85.7 1.622 1.23 2.312h-1.45a6.53 6.53 0 0 1-1.314-2.223 8.126 8.126 0 0 1-.45-2.732"/>
+ <path id="dot" d="M10 16a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
+ <path id="star" d="M14.25 7.013l-.24 2.156 2.187-.61.193 1.47-1.992.14 1.307 1.74-1.33.71-.914-1.833-.8 1.822-1.38-.698 1.296-1.74-1.98-.152.23-1.464 2.14.61-.24-2.158h1.534"/>
+ <path id="right-bracket" d="M21 12.045c0 .982-.152 1.896-.457 2.744A6.51 6.51 0 0 1 19.236 17h-1.453a8.017 8.017 0 0 0 1.225-2.31c.29-.855.434-1.74.434-2.66 0-.91-.14-1.797-.422-2.66a7.913 7.913 0 0 0-1.248-2.374h1.465a6.764 6.764 0 0 1 1.313 2.28c.3.86.45 1.782.45 2.764"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-invert.png
new file mode 100644
index 00000000..4b2913bc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-invert.svg
new file mode 100644
index 00000000..3c02eb47
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="search">
+ <path id="magnifying-glass" d="M10.5 4a6.5 6.5 0 1 0 2.844 12.344L16 19c1.4 1.4 2.5 1.5 4 0l-4.438-4.438A6.426 6.426 0 0 0 17 10.5 6.5 6.5 0 0 0 10.5 4zm0 2a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-progressive.png
new file mode 100644
index 00000000..50a73055
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-progressive.svg
new file mode 100644
index 00000000..efc8223a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="search">
+ <path id="magnifying-glass" d="M10.5 4a6.5 6.5 0 1 0 2.844 12.344L16 19c1.4 1.4 2.5 1.5 4 0l-4.438-4.438A6.426 6.426 0 0 0 17 10.5 6.5 6.5 0 0 0 10.5 4zm0 2a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr.png
new file mode 100644
index 00000000..e8e99f84
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr.svg
new file mode 100644
index 00000000..ebc654a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="search">
+ <path id="magnifying-glass" d="M10.5 4a6.5 6.5 0 1 0 2.844 12.344L16 19c1.4 1.4 2.5 1.5 4 0l-4.438-4.438A6.426 6.426 0 0 0 17 10.5 6.5 6.5 0 0 0 10.5 4zm0 2a4.5 4.5 0 1 1 0 9 4.5 4.5 0 0 1 0-9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-invert.png
new file mode 100644
index 00000000..0409aa49
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-invert.svg
new file mode 100644
index 00000000..8df7b168
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="search">
+ <path id="magnifying-glass" d="M13.5 4a6.5 6.5 0 1 1-2.844 12.344L8 19c-1.4 1.4-2.5 1.5-4 0l4.438-4.438A6.426 6.426 0 0 1 7 10.5 6.5 6.5 0 0 1 13.5 4zm0 2a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-progressive.png
new file mode 100644
index 00000000..4f49e182
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-progressive.svg
new file mode 100644
index 00000000..07f23a8c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="search">
+ <path id="magnifying-glass" d="M13.5 4a6.5 6.5 0 1 1-2.844 12.344L8 19c-1.4 1.4-2.5 1.5-4 0l4.438-4.438A6.426 6.426 0 0 1 7 10.5 6.5 6.5 0 0 1 13.5 4zm0 2a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl.png
new file mode 100644
index 00000000..3ab96bec
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl.svg
new file mode 100644
index 00000000..c51d4cb0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/search-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="search">
+ <path id="magnifying-glass" d="M13.5 4a6.5 6.5 0 1 1-2.844 12.344L8 19c-1.4 1.4-2.5 1.5-4 0l4.438-4.438A6.426 6.426 0 0 1 7 10.5 6.5 6.5 0 0 1 13.5 4zm0 2a4.5 4.5 0 1 0 0 9 4.5 4.5 0 0 0 0-9z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-invert.png
new file mode 100644
index 00000000..a74063d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-invert.svg
new file mode 100644
index 00000000..1b24dbb0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><g fill="#fff">
+ <g id="secure">
+ <path id="lock" d="M8 5h.02v-.997c0-.057.003-1.41-.833-2.255-.434-.438-.998-.66-1.68-.66s-1.244.222-1.677.66c-.837.846-.833 2.198-.832 2.25V5H3a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h5a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1zM3.998 5V3.993c0-.01.005-1 .543-1.543.49-.485 1.45-.487 1.94-.002.543.546.545 1.536.545 1.55V5H3.998z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-progressive.png
new file mode 100644
index 00000000..f29d8560
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-progressive.svg
new file mode 100644
index 00000000..ee69fc4e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><g fill="#36c">
+ <g id="secure">
+ <path id="lock" d="M8 5h.02v-.997c0-.057.003-1.41-.833-2.255-.434-.438-.998-.66-1.68-.66s-1.244.222-1.677.66c-.837.846-.833 2.198-.832 2.25V5H3a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h5a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1zM3.998 5V3.993c0-.01.005-1 .543-1.543.49-.485 1.45-.487 1.94-.002.543.546.545 1.536.545 1.55V5H3.998z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link.png
new file mode 100644
index 00000000..8a44a929
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link.svg
new file mode 100644
index 00000000..453d1663
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/secure-link.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="secure">
+ <path id="lock" d="M8 5h.02v-.997c0-.057.003-1.41-.833-2.255-.434-.438-.998-.66-1.68-.66s-1.244.222-1.677.66c-.837.846-.833 2.198-.832 2.25V5H3a1 1 0 0 0-1 1v3a1 1 0 0 0 1 1h5a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1zM3.998 5V3.993c0-.01.005-1 .543-1.543.49-.485 1.45-.487 1.94-.002.543.546.545 1.536.545 1.55V5H3.998z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-invert.png
new file mode 100644
index 00000000..34c6afe5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-invert.svg
new file mode 100644
index 00000000..630835a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="settings">
+ <path id="gear" d="M3 4h3v2H3zm9 0h9v2h-9zM8 3h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm-5 8h9v2H3zm15 0h3v2h-3zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zM3 18h6v2H3zm12 0h6v2h-6zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-progressive.png
new file mode 100644
index 00000000..46011d2a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-progressive.svg
new file mode 100644
index 00000000..a93d3125
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="settings">
+ <path id="gear" d="M3 4h3v2H3zm9 0h9v2h-9zM8 3h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm-5 8h9v2H3zm15 0h3v2h-3zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zM3 18h6v2H3zm12 0h6v2h-6zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings.png
new file mode 100644
index 00000000..1c8e5874
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings.svg
new file mode 100644
index 00000000..3245dbe3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/settings.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="settings">
+ <path id="gear" d="M3 4h3v2H3zm9 0h9v2h-9zM8 3h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1H8a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1zm-5 8h9v2H3zm15 0h3v2h-3zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1zM3 18h6v2H3zm12 0h6v2h-6zm-4-1h2a1 1 0 0 1 1 1v2a1 1 0 0 1-1 1h-2a1 1 0 0 1-1-1v-2a1 1 0 0 1 1-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-invert.png
new file mode 100644
index 00000000..4538011a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-invert.svg
new file mode 100644
index 00000000..b7837796
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M0 20h24v1H0v-1zm6-8l-1-1-2 2-2-2-1 1 2 2-2 2 1 1 2-2 2 2 1-1-2-2zm15.6 3.7c-.9-.5-1.9-.5-2.7 0-1.5.9-3.1.4-3.1.4-.4-.2-.8-.4-1.1-.6 2.2-.6 4.4-1.8 6-3.9 1.1-1.2 2.5-3.9.4-6-.7-.7-1.6-1.1-2.7-1-1.4.1-2.8.9-3.9 2.1-.9 1.1-3.1 4.5-2.3 7.5 0 .1 0 .2.1.3-2.3.3-4.2.2-4.4.1v1.5c.7.1 2.7.2 5.1-.2.5.7 1.3 1.2 2.3 1.6.1 0 2.4.8 4.5-.6.5-.3.9-.1 1.1 0 .4.2.7.6.7 1H23c0-.8-.6-1.7-1.4-2.2zm-8-1.7c-.5-2.2 1.1-5.1 2-6.2.8-.9 1.8-1.5 2.8-1.6h.1c.6 0 1.1.2 1.5.6 1.6 1.6-.4 3.9-.5 4-1.5 2-3.7 3-5.8 3.5l-.1-.3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-progressive.png
new file mode 100644
index 00000000..f7d6da80
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-progressive.svg
new file mode 100644
index 00000000..366aafb9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M0 20h24v1H0v-1zm6-8l-1-1-2 2-2-2-1 1 2 2-2 2 1 1 2-2 2 2 1-1-2-2zm15.6 3.7c-.9-.5-1.9-.5-2.7 0-1.5.9-3.1.4-3.1.4-.4-.2-.8-.4-1.1-.6 2.2-.6 4.4-1.8 6-3.9 1.1-1.2 2.5-3.9.4-6-.7-.7-1.6-1.1-2.7-1-1.4.1-2.8.9-3.9 2.1-.9 1.1-3.1 4.5-2.3 7.5 0 .1 0 .2.1.3-2.3.3-4.2.2-4.4.1v1.5c.7.1 2.7.2 5.1-.2.5.7 1.3 1.2 2.3 1.6.1 0 2.4.8 4.5-.6.5-.3.9-.1 1.1 0 .4.2.7.6.7 1H23c0-.8-.6-1.7-1.4-2.2zm-8-1.7c-.5-2.2 1.1-5.1 2-6.2.8-.9 1.8-1.5 2.8-1.6h.1c.6 0 1.1.2 1.5.6 1.6 1.6-.4 3.9-.5 4-1.5 2-3.7 3-5.8 3.5l-.1-.3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr.png
new file mode 100644
index 00000000..f68a7bf2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr.svg
new file mode 100644
index 00000000..03b34cf8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M0 20h24v1H0v-1zm6-8l-1-1-2 2-2-2-1 1 2 2-2 2 1 1 2-2 2 2 1-1-2-2zm15.6 3.7c-.9-.5-1.9-.5-2.7 0-1.5.9-3.1.4-3.1.4-.4-.2-.8-.4-1.1-.6 2.2-.6 4.4-1.8 6-3.9 1.1-1.2 2.5-3.9.4-6-.7-.7-1.6-1.1-2.7-1-1.4.1-2.8.9-3.9 2.1-.9 1.1-3.1 4.5-2.3 7.5 0 .1 0 .2.1.3-2.3.3-4.2.2-4.4.1v1.5c.7.1 2.7.2 5.1-.2.5.7 1.3 1.2 2.3 1.6.1 0 2.4.8 4.5-.6.5-.3.9-.1 1.1 0 .4.2.7.6.7 1H23c0-.8-.6-1.7-1.4-2.2zm-8-1.7c-.5-2.2 1.1-5.1 2-6.2.8-.9 1.8-1.5 2.8-1.6h.1c.6 0 1.1.2 1.5.6 1.6 1.6-.4 3.9-.5 4-1.5 2-3.7 3-5.8 3.5l-.1-.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-invert.png
new file mode 100644
index 00000000..a99fe522
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-invert.svg
new file mode 100644
index 00000000..ffbf1894
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M24 20H0v1h24v-1zm-6-8l1-1 2 2 2-2 1 1-2 2 2 2-1 1-2-2-2 2-1-1 2-2zM2.4 15.7c.9-.5 1.9-.5 2.7 0 1.5.9 3.1.4 3.1.4.4-.2.8-.4 1.1-.6-2.2-.6-4.4-1.8-6-3.9-1.1-1.2-2.5-3.9-.4-6 .7-.7 1.6-1.1 2.7-1 1.4.1 2.8.9 3.9 2.1.9 1.1 3.1 4.5 2.3 7.5 0 .1 0 .2-.1.3 2.3.3 4.2.2 4.4.1v1.5c-.7.1-2.7.2-5.1-.2-.5.7-1.3 1.2-2.3 1.6-.1 0-2.4.8-4.5-.6-.5-.3-.9-.1-1.1 0-.4.2-.7.6-.7 1H1c0-.8.6-1.7 1.4-2.2zm8-1.7c.5-2.2-1.1-5.1-2-6.2-.8-.9-1.8-1.5-2.8-1.6h-.1c-.6 0-1.1.2-1.5.6-1.6 1.6.4 3.9.5 4 1.5 2 3.7 3 5.8 3.5l.1-.3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-progressive.png
new file mode 100644
index 00000000..b5e08cae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-progressive.svg
new file mode 100644
index 00000000..3131849b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M24 20H0v1h24v-1zm-6-8l1-1 2 2 2-2 1 1-2 2 2 2-1 1-2-2-2 2-1-1 2-2zM2.4 15.7c.9-.5 1.9-.5 2.7 0 1.5.9 3.1.4 3.1.4.4-.2.8-.4 1.1-.6-2.2-.6-4.4-1.8-6-3.9-1.1-1.2-2.5-3.9-.4-6 .7-.7 1.6-1.1 2.7-1 1.4.1 2.8.9 3.9 2.1.9 1.1 3.1 4.5 2.3 7.5 0 .1 0 .2-.1.3 2.3.3 4.2.2 4.4.1v1.5c-.7.1-2.7.2-5.1-.2-.5.7-1.3 1.2-2.3 1.6-.1 0-2.4.8-4.5-.6-.5-.3-.9-.1-1.1 0-.4.2-.7.6-.7 1H1c0-.8.6-1.7 1.4-2.2zm8-1.7c.5-2.2-1.1-5.1-2-6.2-.8-.9-1.8-1.5-2.8-1.6h-.1c-.6 0-1.1.2-1.5.6-1.6 1.6.4 3.9.5 4 1.5 2 3.7 3 5.8 3.5l.1-.3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl.png
new file mode 100644
index 00000000..9166e8dd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl.svg
new file mode 100644
index 00000000..326281a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/signature-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M24 20H0v1h24v-1zm-6-8l1-1 2 2 2-2 1 1-2 2 2 2-1 1-2-2-2 2-1-1 2-2zM2.4 15.7c.9-.5 1.9-.5 2.7 0 1.5.9 3.1.4 3.1.4.4-.2.8-.4 1.1-.6-2.2-.6-4.4-1.8-6-3.9-1.1-1.2-2.5-3.9-.4-6 .7-.7 1.6-1.1 2.7-1 1.4.1 2.8.9 3.9 2.1.9 1.1 3.1 4.5 2.3 7.5 0 .1 0 .2-.1.3 2.3.3 4.2.2 4.4.1v1.5c-.7.1-2.7.2-5.1-.2-.5.7-1.3 1.2-2.3 1.6-.1 0-2.4.8-4.5-.6-.5-.3-.9-.1-1.1 0-.4.2-.7.6-.7 1H1c0-.8.6-1.7 1.4-2.2zm8-1.7c.5-2.2-1.1-5.1-2-6.2-.8-.9-1.8-1.5-2.8-1.6h-.1c-.6 0-1.1.2-1.5.6-1.6 1.6.4 3.9.5 4 1.5 2 3.7 3 5.8 3.5l.1-.3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-invert.png
new file mode 100644
index 00000000..1b597da5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-invert.svg
new file mode 100644
index 00000000..3f82d69e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path id="big-a" d="M9.666 6H8.294l-4.48 12H5.52l1.493-4h4l1.507 4h1.666zm-2.28 7l1.617-4.333L10.637 13h-3.25z"/>
+ <path id="small-a" d="M17.828 12h-.686l-2.24 6h.853l.747-2h2l.753 2h.833zm-1.14 3.5l.81-2.167.816 2.167H16.69z"/>
+ <path id="arrow" d="M15 6h5l-2.5 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-progressive.png
new file mode 100644
index 00000000..2878f235
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-progressive.svg
new file mode 100644
index 00000000..67bf3a96
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path id="big-a" d="M9.666 6H8.294l-4.48 12H5.52l1.493-4h4l1.507 4h1.666zm-2.28 7l1.617-4.333L10.637 13h-3.25z"/>
+ <path id="small-a" d="M17.828 12h-.686l-2.24 6h.853l.747-2h2l.753 2h.833zm-1.14 3.5l.81-2.167.816 2.167H16.69z"/>
+ <path id="arrow" d="M15 6h5l-2.5 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr.png
new file mode 100644
index 00000000..a9b29d88
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr.svg
new file mode 100644
index 00000000..94312522
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="big-a" d="M9.666 6H8.294l-4.48 12H5.52l1.493-4h4l1.507 4h1.666zm-2.28 7l1.617-4.333L10.637 13h-3.25z"/>
+ <path id="small-a" d="M17.828 12h-.686l-2.24 6h.853l.747-2h2l.753 2h.833zm-1.14 3.5l.81-2.167.816 2.167H16.69z"/>
+ <path id="arrow" d="M15 6h5l-2.5 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-invert.png
new file mode 100644
index 00000000..f94184a4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-invert.svg
new file mode 100644
index 00000000..3d99520c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path id="big-a" d="M14.334 6h1.372l4.48 12H18.48l-1.493-4h-4l-1.507 4H9.814zm2.28 7l-1.617-4.333L13.363 13h3.25z"/>
+ <path id="small-a" d="M6.172 12h.686l2.24 6h-.853L7.5 16H5.497l-.753 2h-.833zm1.14 3.5l-.81-2.166-.816 2.166h1.625z"/>
+ <path id="arrow" d="M9 6H4l2.5 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-progressive.png
new file mode 100644
index 00000000..99abfdbe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-progressive.svg
new file mode 100644
index 00000000..2ca52006
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path id="big-a" d="M14.334 6h1.372l4.48 12H18.48l-1.493-4h-4l-1.507 4H9.814zm2.28 7l-1.617-4.333L13.363 13h3.25z"/>
+ <path id="small-a" d="M6.172 12h.686l2.24 6h-.853L7.5 16H5.497l-.753 2h-.833zm1.14 3.5l-.81-2.166-.816 2.166h1.625z"/>
+ <path id="arrow" d="M9 6H4l2.5 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl.png
new file mode 100644
index 00000000..006bd2bd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl.svg
new file mode 100644
index 00000000..d2d28587
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smaller-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="big-a" d="M14.334 6h1.372l4.48 12H18.48l-1.493-4h-4l-1.507 4H9.814zm2.28 7l-1.617-4.333L13.363 13h3.25z"/>
+ <path id="small-a" d="M6.172 12h.686l2.24 6h-.853L7.5 16H5.497l-.753 2h-.833zm1.14 3.5l-.81-2.166-.816 2.166h1.625z"/>
+ <path id="arrow" d="M9 6H4l2.5 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr-invert.png
new file mode 100644
index 00000000..dec125ef
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr-invert.svg
new file mode 100644
index 00000000..146a2126
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M17.6 20h-5.4v-.5c.2 0 .5-.1.9-.1.3-.1.5-.2.5-.3V19s0-.1-.1-.2l-.8-2H9.3c-.1.2-.2.4-.3.7-.1.3-.2.5-.2.7-.1.3-.1.4-.2.6v.2c0 .1.1.3.3.4.2.1.6.2 1.1.2v.4H6v-.5c.2 0 .3 0 .5-.1.2 0 .3-.1.5-.2s.4-.2.5-.4l.3-.6c.5-1.3 1.1-2.6 1.6-3.9.5-1.3 1.1-2.7 1.8-4.3h1.4c.9 2.2 1.6 4 2.1 5.3.5 1.3 1 2.4 1.3 3.2.1.1.1.3.2.4.1.1.2.2.4.3.1.1.3.1.5.2s.3.1.5.1v.5zm-5.2-4L11 12.4 9.6 16h2.8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr.png
new file mode 100644
index 00000000..b38dca38
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr.svg
new file mode 100644
index 00000000..446d10a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.6 20h-5.4v-.5c.2 0 .5-.1.9-.1.3-.1.5-.2.5-.3V19s0-.1-.1-.2l-.8-2H9.3c-.1.2-.2.4-.3.7-.1.3-.2.5-.2.7-.1.3-.1.4-.2.6v.2c0 .1.1.3.3.4.2.1.6.2 1.1.2v.4H6v-.5c.2 0 .3 0 .5-.1.2 0 .3-.1.5-.2s.4-.2.5-.4l.3-.6c.5-1.3 1.1-2.6 1.6-3.9.5-1.3 1.1-2.7 1.8-4.3h1.4c.9 2.2 1.6 4 2.1 5.3.5 1.3 1 2.4 1.3 3.2.1.1.1.3.2.4.1.1.2.2.4.3.1.1.3.1.5.2s.3.1.5.1v.5zm-5.2-4L11 12.4 9.6 16h2.8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl-invert.png
new file mode 100644
index 00000000..9aba2460
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl-invert.svg
new file mode 100644
index 00000000..960793c5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M6 19.5c.1 0 .3 0 .5-.1s.3-.1.5-.2.3-.2.4-.3c.1-.1.2-.2.2-.4.4-.9.8-1.9 1.3-3.2.5-1.3 1.2-3.1 2.1-5.3h1.4c.7 1.6 1.2 3 1.8 4.3.5 1.3 1.1 2.6 1.6 3.9l.3.6c.1.2.3.3.5.4.1.1.3.1.5.2.2 0 .4.1.5.1v.5h-4v-.5c.5 0 .9-.1 1.1-.2.2-.1.3-.2.3-.4v-.2c0-.1-.1-.3-.2-.6-.1-.2-.2-.4-.2-.7-.1-.3-.2-.5-.3-.7h-3.4l-.8 2c0 .1-.1.1-.1.2v.1c0 .1.2.2.5.3.3.1.6.1.9.1v.6H6v-.5zm8-3.5l-1.4-3.6-1.4 3.6H14z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl.png
new file mode 100644
index 00000000..b9864efb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl.svg
new file mode 100644
index 00000000..ebcea4df
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/smallerText-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6 19.5c.1 0 .3 0 .5-.1s.3-.1.5-.2.3-.2.4-.3c.1-.1.2-.2.2-.4.4-.9.8-1.9 1.3-3.2.5-1.3 1.2-3.1 2.1-5.3h1.4c.7 1.6 1.2 3 1.8 4.3.5 1.3 1.1 2.6 1.6 3.9l.3.6c.1.2.3.3.5.4.1.1.3.1.5.2.2 0 .4.1.5.1v.5h-4v-.5c.5 0 .9-.1 1.1-.2.2-.1.3-.2.3-.4v-.2c0-.1-.1-.3-.2-.6-.1-.2-.2-.4-.2-.7-.1-.3-.2-.5-.3-.7h-3.4l-.8 2c0 .1-.1.1-.1.2v.1c0 .1.2.2.5.3.3.1.6.1.9.1v.6H6v-.5zm8-3.5l-1.4-3.6-1.4 3.6H14z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-invert.png
new file mode 100644
index 00000000..b7c99967
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-invert.svg
new file mode 100644
index 00000000..b234e63a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="special-character">
+ <path id="omega" d="M12 6.708c-.794 0-1.368.103-1.894.31-.525.207-.944.496-1.255.867-.31.366-.53.808-.66 1.327a7.232 7.232 0 0 0-.19 1.7c0 .512.06 1 .18 1.46.12.46.31.87.567 1.23.63.862 1.156 1.138 2.012 1.362L11 18H6v-3h.604l.53 1.353.395.053.6.044.75.035.455.01H10l-.09-.895c-.63-.094-.812-.268-1.337-.522-.525-.26-.98-.59-1.365-.99a4.428 4.428 0 0 1-.89-1.4 4.78 4.78 0 0 1-.32-1.778c0-.82.13-1.537.394-2.15a3.97 3.97 0 0 1 1.163-1.54c.507-.407 1.133-.71 1.878-.912.745-.206 1.6-.31 2.565-.31.96 0 1.81.103 2.556.31.75.2 1.38.504 1.887.912.51.407.9.92 1.16 1.54.27.614.404 1.33.404 2.15a4.79 4.79 0 0 1-.32 1.78 4.35 4.35 0 0 1-.9 1.397c-.38.4-.83.732-1.355.99-.526.255-.708.43-1.337.523l-.092.894h.66l.448-.01.75-.034.606-.044.4-.053.534-1.354H18v3h-5l.246-3.04c1.066-.11 1.337-.698 2.002-1.365.263-.36.452-.77.568-1.23.122-.46.183-.947.183-1.46 0-.62-.07-1.186-.198-1.7a3.175 3.175 0 0 0-.66-1.326c-.31-.37-.73-.66-1.255-.867-.525-.206-1.1-.31-1.894-.31"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-progressive.png
new file mode 100644
index 00000000..1ce45490
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-progressive.svg
new file mode 100644
index 00000000..091063f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="special-character">
+ <path id="omega" d="M12 6.708c-.794 0-1.368.103-1.894.31-.525.207-.944.496-1.255.867-.31.366-.53.808-.66 1.327a7.232 7.232 0 0 0-.19 1.7c0 .512.06 1 .18 1.46.12.46.31.87.567 1.23.63.862 1.156 1.138 2.012 1.362L11 18H6v-3h.604l.53 1.353.395.053.6.044.75.035.455.01H10l-.09-.895c-.63-.094-.812-.268-1.337-.522-.525-.26-.98-.59-1.365-.99a4.428 4.428 0 0 1-.89-1.4 4.78 4.78 0 0 1-.32-1.778c0-.82.13-1.537.394-2.15a3.97 3.97 0 0 1 1.163-1.54c.507-.407 1.133-.71 1.878-.912.745-.206 1.6-.31 2.565-.31.96 0 1.81.103 2.556.31.75.2 1.38.504 1.887.912.51.407.9.92 1.16 1.54.27.614.404 1.33.404 2.15a4.79 4.79 0 0 1-.32 1.78 4.35 4.35 0 0 1-.9 1.397c-.38.4-.83.732-1.355.99-.526.255-.708.43-1.337.523l-.092.894h.66l.448-.01.75-.034.606-.044.4-.053.534-1.354H18v3h-5l.246-3.04c1.066-.11 1.337-.698 2.002-1.365.263-.36.452-.77.568-1.23.122-.46.183-.947.183-1.46 0-.62-.07-1.186-.198-1.7a3.175 3.175 0 0 0-.66-1.326c-.31-.37-.73-.66-1.255-.867-.525-.206-1.1-.31-1.894-.31"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter.png
new file mode 100644
index 00000000..9b02a410
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter.svg
new file mode 100644
index 00000000..5cba0801
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/specialCharacter.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="special-character">
+ <path id="omega" d="M12 6.708c-.794 0-1.368.103-1.894.31-.525.207-.944.496-1.255.867-.31.366-.53.808-.66 1.327a7.232 7.232 0 0 0-.19 1.7c0 .512.06 1 .18 1.46.12.46.31.87.567 1.23.63.862 1.156 1.138 2.012 1.362L11 18H6v-3h.604l.53 1.353.395.053.6.044.75.035.455.01H10l-.09-.895c-.63-.094-.812-.268-1.337-.522-.525-.26-.98-.59-1.365-.99a4.428 4.428 0 0 1-.89-1.4 4.78 4.78 0 0 1-.32-1.778c0-.82.13-1.537.394-2.15a3.97 3.97 0 0 1 1.163-1.54c.507-.407 1.133-.71 1.878-.912.745-.206 1.6-.31 2.565-.31.96 0 1.81.103 2.556.31.75.2 1.38.504 1.887.912.51.407.9.92 1.16 1.54.27.614.404 1.33.404 2.15a4.79 4.79 0 0 1-.32 1.78 4.35 4.35 0 0 1-.9 1.397c-.38.4-.83.732-1.355.99-.526.255-.708.43-1.337.523l-.092.894h.66l.448-.01.75-.034.606-.044.4-.053.534-1.354H18v3h-5l.246-3.04c1.066-.11 1.337-.698 2.002-1.365.263-.36.452-.77.568-1.23.122-.46.183-.947.183-1.46 0-.62-.07-1.186-.198-1.7a3.175 3.175 0 0 0-.66-1.326c-.31-.37-.73-.66-1.255-.867-.525-.206-1.1-.31-1.894-.31"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-invert.png
new file mode 100644
index 00000000..6409de22
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-invert.svg
new file mode 100644
index 00000000..5fa3f49c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M19 20H2l3-3V6h17v11c0 1.7-1.3 3-3 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-progressive.png
new file mode 100644
index 00000000..049b6ca9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-progressive.svg
new file mode 100644
index 00000000..d196d552
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M19 20H2l3-3V6h17v11c0 1.7-1.3 3-3 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr.png
new file mode 100644
index 00000000..2eedf9f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr.svg
new file mode 100644
index 00000000..83d47c1d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19 20H2l3-3V6h17v11c0 1.7-1.3 3-3 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-invert.png
new file mode 100644
index 00000000..e85fd440
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-invert.svg
new file mode 100644
index 00000000..2da483c4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M5 20h17l-3-3V6H2v11c0 1.7 1.3 3 3 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-progressive.png
new file mode 100644
index 00000000..05246491
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-progressive.svg
new file mode 100644
index 00000000..43b23644
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M5 20h17l-3-3V6H2v11c0 1.7 1.3 3 3 3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl.png
new file mode 100644
index 00000000..0d144431
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl.svg
new file mode 100644
index 00000000..e7dd6681
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubble-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 20h17l-3-3V6H2v11c0 1.7 1.3 3 3 3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-invert.png
new file mode 100644
index 00000000..9575bdb5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-invert.svg
new file mode 100644
index 00000000..843469e1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm8 3h1v3h3v1h-3v3h-1v-3h-3v-1h3V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-progressive.png
new file mode 100644
index 00000000..19a88b5f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-progressive.svg
new file mode 100644
index 00000000..bd4128b2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm8 3h1v3h3v1h-3v3h-1v-3h-3v-1h3V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr.png
new file mode 100644
index 00000000..aafac18f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr.svg
new file mode 100644
index 00000000..c7134c33
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm8 3h1v3h3v1h-3v3h-1v-3h-3v-1h3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-invert.png
new file mode 100644
index 00000000..0520123f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-invert.svg
new file mode 100644
index 00000000..d0e2cc4c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M2 6v11c0 1.7 1.3 3 3 3h17l-3-3V6H2zm8 3h1v3h3v1h-3v3h-1v-3H7v-1h3V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-progressive.png
new file mode 100644
index 00000000..2140a278
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-progressive.svg
new file mode 100644
index 00000000..a35ff20b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M2 6v11c0 1.7 1.3 3 3 3h17l-3-3V6H2zm8 3h1v3h3v1h-3v3h-1v-3H7v-1h3V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl.png
new file mode 100644
index 00000000..feff2ba7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl.svg
new file mode 100644
index 00000000..08462e0c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbleAdd-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M2 6v11c0 1.7 1.3 3 3 3h17l-3-3V6H2zm8 3h1v3h3v1h-3v3h-1v-3H7v-1h3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-invert.png
new file mode 100644
index 00000000..24a8e4e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-invert.svg
new file mode 100644
index 00000000..a9ea6c82
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M20 9v9l2 2H8V9h12zM3 4h12v4H7v7H1l2-2V4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-progressive.png
new file mode 100644
index 00000000..8b7029b6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-progressive.svg
new file mode 100644
index 00000000..1c79ef61
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M20 9v9l2 2H8V9h12zM3 4h12v4H7v7H1l2-2V4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr.png
new file mode 100644
index 00000000..f2e0564d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr.svg
new file mode 100644
index 00000000..d6832183
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 9v9l2 2H8V9h12zM3 4h12v4H7v7H1l2-2V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-invert.png
new file mode 100644
index 00000000..4b9ca3a7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-invert.svg
new file mode 100644
index 00000000..c8b684a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M3 9v9l-2 2h14V9H3zm17-5H8v4h8v7h6l-2-2V4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-progressive.png
new file mode 100644
index 00000000..856fd7bf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-progressive.svg
new file mode 100644
index 00000000..fe65227c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M3 9v9l-2 2h14V9H3zm17-5H8v4h8v7h6l-2-2V4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl.png
new file mode 100644
index 00000000..9c67f3fe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl.svg
new file mode 100644
index 00000000..db548a45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/speechBubbles-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 9v9l-2 2h14V9H3zm17-5H8v4h8v7h6l-2-2V4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-constructive.png
new file mode 100644
index 00000000..1cdcf99e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-constructive.svg
new file mode 100644
index 00000000..407d2dab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-constructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-invert.png
new file mode 100644
index 00000000..7c949a68
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-invert.svg
new file mode 100644
index 00000000..0cbd1d0d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-progressive.png
new file mode 100644
index 00000000..1cdcf99e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-progressive.svg
new file mode 100644
index 00000000..407d2dab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star.png
new file mode 100644
index 00000000..36b6a1ff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star.svg
new file mode 100644
index 00000000..54ba77ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/star.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 7.4l1.7 3.6 4 .5-2.7 2.8.5 3.9-3.5-1.7-3.6 1.7.6-3.9-2.8-2.8 3.9-.5L12 7.4M12 4L9.2 9.6l-6.2.9 4.5 4.4L6.4 21l5.6-3 5.5 3-1-6.2 4.5-4.4-6.3-.9L12 4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-invert.png
new file mode 100644
index 00000000..2a7d0817
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-invert.svg
new file mode 100644
index 00000000..c57bd4ad
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3 11.1H9v-6h6v6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-progressive.png
new file mode 100644
index 00000000..20e375d5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-progressive.svg
new file mode 100644
index 00000000..e4d2fca0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3 11.1H9v-6h6v6z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop.png
new file mode 100644
index 00000000..e57bede8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop.svg
new file mode 100644
index 00000000..3fa3128a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stop.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 4c-4.4 0-8 3.6-8 8s3.6 8 8 8 8-3.6 8-8-3.6-8-8-8zm3 11.1H9v-6h6v6z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-invert.png
new file mode 100644
index 00000000..ebabd3b2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-invert.svg
new file mode 100644
index 00000000..e277ae3e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="strikethrough-a">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-progressive.png
new file mode 100644
index 00000000..a3189f45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-progressive.svg
new file mode 100644
index 00000000..a957e808
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="strikethrough-a">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a.png
new file mode 100644
index 00000000..279d1f72
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a.svg
new file mode 100644
index 00000000..070d7853
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-a.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="strikethrough-a">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M12.666 6h-1.372l-4.48 12H8.52l1.493-4h4l1.507 4h1.666l-4.52-12zm-2.28 7l1.617-4.333L13.637 13h-3.25z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-invert.png
new file mode 100644
index 00000000..2a29a6ea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-invert.svg
new file mode 100644
index 00000000..a8301f2f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="strikethrough-s">
+ <path id="strikethrough" d="M6 12h12v1H6v-1z"/>
+ <path id="s" d="M12.094 6c-1.133 0-2.076.287-2.75.9-.67.613-1 1.49-1 2.52 0 .89.22 1.602.72 2.13.497.528 1.278.91 2.31 1.14l.813.182v-.03c.656.147 1.128.375 1.375.63.252.256.375.607.375 1.11 0 .573-.172.97-.53 1.26-.36.29-.895.45-1.626.45-.47 0-.962-.074-1.462-.24a7.288 7.288 0 0 1-1.562-.75l-.374-.238v2.158l.156.062c.58.237 1.144.417 1.69.54.548.12 1.07.18 1.56.18 1.287 0 2.298-.293 3-.9.71-.605 1.063-1.486 1.063-2.608 0-.943-.256-1.726-.78-2.312-.522-.592-1.306-1-2.345-1.23l-.812-.18c-.714-.148-1.202-.352-1.404-.54-.206-.202-.313-.484-.313-.934 0-.533.162-.9.5-1.17.342-.27.836-.42 1.53-.42.396 0 .82.052 1.25.18.434.128.91.334 1.407.6l.375.18V6.63s-1.19-.383-1.69-.48c-.5-.097-.983-.15-1.467-.15z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-progressive.png
new file mode 100644
index 00000000..0b215bde
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-progressive.svg
new file mode 100644
index 00000000..f6f53312
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="strikethrough-s">
+ <path id="strikethrough" d="M6 12h12v1H6v-1z"/>
+ <path id="s" d="M12.094 6c-1.133 0-2.076.287-2.75.9-.67.613-1 1.49-1 2.52 0 .89.22 1.602.72 2.13.497.528 1.278.91 2.31 1.14l.813.182v-.03c.656.147 1.128.375 1.375.63.252.256.375.607.375 1.11 0 .573-.172.97-.53 1.26-.36.29-.895.45-1.626.45-.47 0-.962-.074-1.462-.24a7.288 7.288 0 0 1-1.562-.75l-.374-.238v2.158l.156.062c.58.237 1.144.417 1.69.54.548.12 1.07.18 1.56.18 1.287 0 2.298-.293 3-.9.71-.605 1.063-1.486 1.063-2.608 0-.943-.256-1.726-.78-2.312-.522-.592-1.306-1-2.345-1.23l-.812-.18c-.714-.148-1.202-.352-1.404-.54-.206-.202-.313-.484-.313-.934 0-.533.162-.9.5-1.17.342-.27.836-.42 1.53-.42.396 0 .82.052 1.25.18.434.128.91.334 1.407.6l.375.18V6.63s-1.19-.383-1.69-.48c-.5-.097-.983-.15-1.467-.15z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s.png
new file mode 100644
index 00000000..21b9baaf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s.svg
new file mode 100644
index 00000000..171f8f38
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-s.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="strikethrough-s">
+ <path id="strikethrough" d="M6 12h12v1H6v-1z"/>
+ <path id="s" d="M12.094 6c-1.133 0-2.076.287-2.75.9-.67.613-1 1.49-1 2.52 0 .89.22 1.602.72 2.13.497.528 1.278.91 2.31 1.14l.813.182v-.03c.656.147 1.128.375 1.375.63.252.256.375.607.375 1.11 0 .573-.172.97-.53 1.26-.36.29-.895.45-1.626.45-.47 0-.962-.074-1.462-.24a7.288 7.288 0 0 1-1.562-.75l-.374-.238v2.158l.156.062c.58.237 1.144.417 1.69.54.548.12 1.07.18 1.56.18 1.287 0 2.298-.293 3-.9.71-.605 1.063-1.486 1.063-2.608 0-.943-.256-1.726-.78-2.312-.522-.592-1.306-1-2.345-1.23l-.812-.18c-.714-.148-1.202-.352-1.404-.54-.206-.202-.313-.484-.313-.934 0-.533.162-.9.5-1.17.342-.27.836-.42 1.53-.42.396 0 .82.052 1.25.18.434.128.91.334 1.407.6l.375.18V6.63s-1.19-.383-1.69-.48c-.5-.097-.983-.15-1.467-.15z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-invert.png
new file mode 100644
index 00000000..5ed90976
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-invert.svg
new file mode 100644
index 00000000..f34be15c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="strikethrough-y">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M7 6h1.724l3.288 4.935L15.276 6H17l-4.194 6.285V18h-1.612v-5.715L7 6"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-progressive.png
new file mode 100644
index 00000000..a96d9064
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-progressive.svg
new file mode 100644
index 00000000..778a941e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="strikethrough-y">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M7 6h1.724l3.288 4.935L15.276 6H17l-4.194 6.285V18h-1.612v-5.715L7 6"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y.png
new file mode 100644
index 00000000..d7694682
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y.svg
new file mode 100644
index 00000000..2fdbc871
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/strikethrough-y.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="strikethrough-y">
+ <path id="strikethrough" d="M6 11h12v1H6v-1z"/>
+ <path id="a" d="M7 6h1.724l3.288 4.935L15.276 6H17l-4.194 6.285V18h-1.612v-5.715L7 6"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-invert.png
new file mode 100644
index 00000000..41fabd9f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-invert.svg
new file mode 100644
index 00000000..4b2040c7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M4 9h12v2H4V9zm0 3h8v2H4v-2zm0-7h16v3H4V5zm16 14H4v-3h16v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-progressive.png
new file mode 100644
index 00000000..7f4954c4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-progressive.svg
new file mode 100644
index 00000000..a7ddaac3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M4 9h12v2H4V9zm0 3h8v2H4v-2zm0-7h16v3H4V5zm16 14H4v-3h16v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr.png
new file mode 100644
index 00000000..5423b36e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr.svg
new file mode 100644
index 00000000..2112bb2d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 9h12v2H4V9zm0 3h8v2H4v-2zm0-7h16v3H4V5zm16 14H4v-3h16v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-invert.png
new file mode 100644
index 00000000..fc723a6e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-invert.svg
new file mode 100644
index 00000000..af6e715a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M20 9H8v2h12V9zm0 3h-8v2h8v-2zm0-7H4v3h16V5zM4 19h16v-3H4v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-progressive.png
new file mode 100644
index 00000000..5e82b68d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-progressive.svg
new file mode 100644
index 00000000..e835c21e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M20 9H8v2h12V9zm0 3h-8v2h8v-2zm0-7H4v3h16V5zM4 19h16v-3H4v3z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl.png
new file mode 100644
index 00000000..0ff3d7cf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl.svg
new file mode 100644
index 00000000..39790a9a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeFlow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 9H8v2h12V9zm0 3h-8v2h8v-2zm0-7H4v3h16V5zM4 19h16v-3H4v3z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-invert.png
new file mode 100644
index 00000000..453cb73e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-invert.svg
new file mode 100644
index 00000000..91fcd8ff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M20 11H4V9h16v2zM4 12h8v2H4v-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-progressive.png
new file mode 100644
index 00000000..cc2cd8cc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-progressive.svg
new file mode 100644
index 00000000..59342a5c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M20 11H4V9h16v2zM4 12h8v2H4v-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr.png
new file mode 100644
index 00000000..ce15bd87
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr.svg
new file mode 100644
index 00000000..767d6cda
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20 11H4V9h16v2zM4 12h8v2H4v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-invert.png
new file mode 100644
index 00000000..458015cd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-invert.svg
new file mode 100644
index 00000000..dae554e7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M4 11h16V9H4v2zm16 1h-8v2h8v-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-progressive.png
new file mode 100644
index 00000000..9180978c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-progressive.svg
new file mode 100644
index 00000000..6b946638
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M4 11h16V9H4v2zm16 1h-8v2h8v-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl.png
new file mode 100644
index 00000000..82ca2bf5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl.svg
new file mode 100644
index 00000000..4d16337e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeSummary-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 11h16V9H4v2zm16 1h-8v2h8v-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-invert.png
new file mode 100644
index 00000000..629ea356
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-invert.svg
new file mode 100644
index 00000000..7b2ec172
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M17 13H4v-3h13v3zm-5 6H4v-3h8v3zM4 7V4h16v3H4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-progressive.png
new file mode 100644
index 00000000..cee45e89
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-progressive.svg
new file mode 100644
index 00000000..d0275392
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M17 13H4v-3h13v3zm-5 6H4v-3h8v3zM4 7V4h16v3H4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr.png
new file mode 100644
index 00000000..b482d3e6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr.svg
new file mode 100644
index 00000000..d7c202e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 13H4v-3h13v3zm-5 6H4v-3h8v3zM4 7V4h16v3H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-invert.png
new file mode 100644
index 00000000..f81e503c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-invert.svg
new file mode 100644
index 00000000..2e75158b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M7 13h13v-3H7v3zm5 6h8v-3h-8v3zm8-12V4H4v3h16z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-progressive.png
new file mode 100644
index 00000000..424aa991
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-progressive.svg
new file mode 100644
index 00000000..3c27eafa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M7 13h13v-3H7v3zm5 6h8v-3h-8v3zm8-12V4H4v3h16z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl.png
new file mode 100644
index 00000000..516bc2c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl.svg
new file mode 100644
index 00000000..0859be6b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/stripeToC-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 13h13v-3H7v3zm5 6h8v-3h-8v3zm8-12V4H4v3h16z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-invert.png
new file mode 100644
index 00000000..f7f291e5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-invert.svg
new file mode 100644
index 00000000..b6f5d6d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 13l-1 1v3l1 1h-1l-.527-.46L16 18h-1l1-1v-3l-1-1h1l.485.497L17 13z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-progressive.png
new file mode 100644
index 00000000..55df817f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-progressive.svg
new file mode 100644
index 00000000..11dc32f7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 13l-1 1v3l1 1h-1l-.527-.46L16 18h-1l1-1v-3l-1-1h1l.485.497L17 13z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr.png
new file mode 100644
index 00000000..c2cf4cf5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr.svg
new file mode 100644
index 00000000..fbb0c3c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 13l-1 1v3l1 1h-1l-.527-.46L16 18h-1l1-1v-3l-1-1h1l.485.497L17 13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-invert.png
new file mode 100644
index 00000000..56ad252a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-invert.svg
new file mode 100644
index 00000000..b1608f9b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 13l1 1v3l-1 1h1l.527-.46L10 18h1l-1-1v-3l1-1h-1l-.485.497L9 13z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-progressive.png
new file mode 100644
index 00000000..bf343f1f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-progressive.svg
new file mode 100644
index 00000000..f0c5d313
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 13l1 1v3l-1 1h1l.527-.46L10 18h1l-1-1v-3l1-1h-1l-.485.497L9 13z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl.png
new file mode 100644
index 00000000..b1ee51b6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl.svg
new file mode 100644
index 00000000..91a71ecc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subscript-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 13l1 1v3l-1 1h1l.527-.46L10 18h1l-1-1v-3l1-1h-1l-.485.497L9 13z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-invert.png
new file mode 100644
index 00000000..4e58b70a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-invert.svg
new file mode 100644
index 00000000..d76eb3c7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M18 13H6v-2h12"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-progressive.png
new file mode 100644
index 00000000..17329720
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-progressive.svg
new file mode 100644
index 00000000..24795ac2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M18 13H6v-2h12"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract.png
new file mode 100644
index 00000000..bd719cb6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract.svg
new file mode 100644
index 00000000..a79f0b50
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/subtract.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18 13H6v-2h12"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-invert.png
new file mode 100644
index 00000000..2bc944a2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-invert.svg
new file mode 100644
index 00000000..498df822
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9s-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4s.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9s.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8s.1-.6.3-.8z"/>
+ <circle cx="12" cy="11" r="4"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-progressive.png
new file mode 100644
index 00000000..dbe14b5c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-progressive.svg
new file mode 100644
index 00000000..afd390c1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9s-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4s.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9s.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8s.1-.6.3-.8z"/>
+ <circle cx="12" cy="11" r="4"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr.png
new file mode 100644
index 00000000..0c00745b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr.svg
new file mode 100644
index 00000000..4bde1836
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.1 5.1c0 .3-.1.6-.3.9l-1.4 1.4-.9-.8 2.2-2.2c.3.1.4.4.4.7zm-.5 5.3h3.2c0 .3-.1.6-.4.9s-.5.4-.8.4h-2v-1.3zm-6.2-5V2.2c.3 0 .6.1.9.4s.4.5.4.8v2h-1.3zm6.4 11.7c-.3 0-.6-.1-.8-.3l-1.4-1.4.8-.8 2.2 2.2c-.2.2-.5.3-.8.3zM6.2 4.9c.3 0 .6.1.8.3l1.4 1.4-.8.9-2.2-2.3c.2-.2.5-.3.8-.3zm5.2 11.7h1.2v3.2c-.3 0-.6-.1-.9-.4s-.4-.5-.4-.8l.1-2zm-7-6.2h2v1.2H3.2c0-.3.1-.6.4-.9s.5-.3.8-.3zM6.2 16l1.4-1.4.8.8-2.2 2.2c-.2-.2-.3-.5-.3-.8s.1-.6.3-.8z"/>
+ <circle cx="12" cy="11" r="4"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-invert.png
new file mode 100644
index 00000000..7ac54ff4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-invert.svg
new file mode 100644
index 00000000..f932701f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M5.9 5.1c0 .3.1.6.3.9l1.4 1.4.9-.8-2.2-2.2c-.3.1-.4.4-.4.7zm.5 5.3H3.2c0 .3.1.6.4.9.3.3.5.4.8.4h2v-1.3zm6.2-5V2.2c-.3 0-.6.1-.9.4-.3.3-.4.5-.4.8v2h1.3zM6.2 17.1c.3 0 .6-.1.8-.3l1.4-1.4-.8-.8-2.2 2.2c.2.2.5.3.8.3zM17.8 4.9c-.3 0-.6.1-.8.3l-1.4 1.4.8.9 2.2-2.3c-.2-.2-.5-.3-.8-.3zm-5.2 11.7h-1.2v3.2c.3 0 .6-.1.9-.4.3-.3.4-.5.4-.8l-.1-2zm7-6.2h-2v1.2h3.2c0-.3-.1-.6-.4-.9-.3-.3-.5-.3-.8-.3zM17.8 16l-1.4-1.4-.8.8 2.2 2.2c.2-.2.3-.5.3-.8 0-.3-.1-.6-.3-.8z"/>
+ <circle cx="12" cy="11" r="4" transform="matrix(-1 0 0 1 24 0)"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-progressive.png
new file mode 100644
index 00000000..5ee10ee3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-progressive.svg
new file mode 100644
index 00000000..72754d48
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M5.9 5.1c0 .3.1.6.3.9l1.4 1.4.9-.8-2.2-2.2c-.3.1-.4.4-.4.7zm.5 5.3H3.2c0 .3.1.6.4.9.3.3.5.4.8.4h2v-1.3zm6.2-5V2.2c-.3 0-.6.1-.9.4-.3.3-.4.5-.4.8v2h1.3zM6.2 17.1c.3 0 .6-.1.8-.3l1.4-1.4-.8-.8-2.2 2.2c.2.2.5.3.8.3zM17.8 4.9c-.3 0-.6.1-.8.3l-1.4 1.4.8.9 2.2-2.3c-.2-.2-.5-.3-.8-.3zm-5.2 11.7h-1.2v3.2c.3 0 .6-.1.9-.4.3-.3.4-.5.4-.8l-.1-2zm7-6.2h-2v1.2h3.2c0-.3-.1-.6-.4-.9-.3-.3-.5-.3-.8-.3zM17.8 16l-1.4-1.4-.8.8 2.2 2.2c.2-.2.3-.5.3-.8 0-.3-.1-.6-.3-.8z"/>
+ <circle cx="12" cy="11" r="4" transform="matrix(-1 0 0 1 24 0)"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl.png
new file mode 100644
index 00000000..77c78060
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl.svg
new file mode 100644
index 00000000..868334e4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/sun-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5.9 5.1c0 .3.1.6.3.9l1.4 1.4.9-.8-2.2-2.2c-.3.1-.4.4-.4.7zm.5 5.3H3.2c0 .3.1.6.4.9.3.3.5.4.8.4h2v-1.3zm6.2-5V2.2c-.3 0-.6.1-.9.4-.3.3-.4.5-.4.8v2h1.3zM6.2 17.1c.3 0 .6-.1.8-.3l1.4-1.4-.8-.8-2.2 2.2c.2.2.5.3.8.3zM17.8 4.9c-.3 0-.6.1-.8.3l-1.4 1.4.8.9 2.2-2.3c-.2-.2-.5-.3-.8-.3zm-5.2 11.7h-1.2v3.2c.3 0 .6-.1.9-.4.3-.3.4-.5.4-.8l-.1-2zm7-6.2h-2v1.2h3.2c0-.3-.1-.6-.4-.9-.3-.3-.5-.3-.8-.3zM17.8 16l-1.4-1.4-.8.8 2.2 2.2c.2-.2.3-.5.3-.8 0-.3-.1-.6-.3-.8z"/>
+ <circle cx="12" cy="11" r="4" transform="matrix(-1 0 0 1 24 0)"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-invert.png
new file mode 100644
index 00000000..abb7229e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-invert.svg
new file mode 100644
index 00000000..430abf0c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 7l-1 1v3l1 1h-1l-.527-.46L16 12h-1l1-1V8l-1-1h1l.485.497L17 7z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-progressive.png
new file mode 100644
index 00000000..37c45c0d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-progressive.svg
new file mode 100644
index 00000000..80495b8c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 7l-1 1v3l1 1h-1l-.527-.46L16 12h-1l1-1V8l-1-1h1l.485.497L17 7z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr.png
new file mode 100644
index 00000000..8df46091
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr.svg
new file mode 100644
index 00000000..45abfda2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M14 9l-2.354 3.406L14 16h-1.2L11 13.25 9.2 16H8l2.403-3.662L8 9h1.188l1.857 2.494L12.797 9H14z"/>
+ <path d="M18 7l-1 1v3l1 1h-1l-.527-.46L16 12h-1l1-1V8l-1-1h1l.485.497L17 7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-invert.png
new file mode 100644
index 00000000..ee76ff42
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-invert.svg
new file mode 100644
index 00000000..ea8ea9cf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-invert.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 7l1 1v3l-1 1h1l.527-.46L10 12h1l-1-1V8l1-1h-1l-.485.497L9 7z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-progressive.png
new file mode 100644
index 00000000..2c63a82d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-progressive.svg
new file mode 100644
index 00000000..e7429902
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl-progressive.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 7l1 1v3l-1 1h1l.527-.46L10 12h1l-1-1V8l1-1h-1l-.485.497L9 7z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl.png
new file mode 100644
index 00000000..48bfd688
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl.svg
new file mode 100644
index 00000000..33b5814b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/superscript-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path id="x" d="M12 9l2.354 3.406L12 16h1.2l1.8-2.75L16.8 16H18l-2.403-3.662L18 9h-1.188l-1.857 2.494L13.203 9H12z"/>
+ <path d="M8 7l1 1v3l-1 1h1l.527-.46L10 12h1l-1-1V8l1-1h-1l-.485.497L9 7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-invert.png
new file mode 100644
index 00000000..9d50a427
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-invert.svg
new file mode 100644
index 00000000..360fbe1c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="table-caption">
+ <path id="caption" d="M6 6h12v3H6z"/>
+ <path id="table" d="M4 10v7h16v-7H4zm1 1h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2zM5 14h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-progressive.png
new file mode 100644
index 00000000..ef657ee2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-progressive.svg
new file mode 100644
index 00000000..02faf857
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="table-caption">
+ <path id="caption" d="M6 6h12v3H6z"/>
+ <path id="table" d="M4 10v7h16v-7H4zm1 1h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2zM5 14h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption.png
new file mode 100644
index 00000000..80b474d4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption.svg
new file mode 100644
index 00000000..6b7edc6f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-caption.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-caption">
+ <path id="caption" d="M6 6h12v3H6z"/>
+ <path id="table" d="M4 10v7h16v-7H4zm1 1h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2zM5 14h4v2H5v-2zm5 0h4v2h-4v-2zm5 0h4v2h-4v-2z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-invert.png
new file mode 100644
index 00000000..b97ac0ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-invert.svg
new file mode 100644
index 00000000..9a93e246
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="table-insert-column-ltr">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h2v14H5z" id="column"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-progressive.png
new file mode 100644
index 00000000..5565c151
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-progressive.svg
new file mode 100644
index 00000000..1f560bb6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="table-insert-column-ltr">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h2v14H5z" id="column"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr.png
new file mode 100644
index 00000000..fe3eb18f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr.svg
new file mode 100644
index 00000000..a67ed201
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-column-ltr">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h2v14H5z" id="column"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-invert.png
new file mode 100644
index 00000000..c10abc56
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-invert.svg
new file mode 100644
index 00000000..7c54e2cf
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="table-insert-column-rtl">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M17 5h2v14h-2z" id="column"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-progressive.png
new file mode 100644
index 00000000..d974a07e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-progressive.svg
new file mode 100644
index 00000000..3e178eed
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="table-insert-column-rtl">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M17 5h2v14h-2z" id="column"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl.png
new file mode 100644
index 00000000..ddaafe9a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl.svg
new file mode 100644
index 00000000..dee782e9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-column-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-column-rtl">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M17 5h2v14h-2z" id="column"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-invert.png
new file mode 100644
index 00000000..ea1a5d8e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-invert.svg
new file mode 100644
index 00000000..2df3cfc8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="table-insert-row-after">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 17h14v2H5z" id="row"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-progressive.png
new file mode 100644
index 00000000..ba1e54cc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-progressive.svg
new file mode 100644
index 00000000..f85c5a37
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="table-insert-row-after">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 17h14v2H5z" id="row"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after.png
new file mode 100644
index 00000000..31a23066
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after.svg
new file mode 100644
index 00000000..ad9d86db
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-after.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-row-after">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 17h14v2H5z" id="row"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-invert.png
new file mode 100644
index 00000000..a54f05c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-invert.svg
new file mode 100644
index 00000000..5d529f1a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="table-insert-row-before">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h14v2H5z" id="row"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-progressive.png
new file mode 100644
index 00000000..0a54444a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-progressive.svg
new file mode 100644
index 00000000..f26feefd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="table-insert-row-before">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h14v2H5z" id="row"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before.png
new file mode 100644
index 00000000..24774750
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before.svg
new file mode 100644
index 00000000..e9dfe048
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-insert-row-before.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert-row-before">
+ <path d="M13 9h-2v2H9v2h2v2h2v-2h2v-2h-2z" id="plus"/>
+ <path d="M5 5h14v2H5z" id="row"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-invert.png
new file mode 100644
index 00000000..4c192030
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-invert.svg
new file mode 100644
index 00000000..85a3f973
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="table-insert">
+ <path id="table" d="M4 6v11h15V6zm1 3h6v3H5zm7 0h6v3h-6zm-7 4h6v3H5zm7 0h6v3h-6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-invert.png
new file mode 100644
index 00000000..b24537d2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-invert.svg
new file mode 100644
index 00000000..102a6869
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-invert.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="table-merge-cells">
+ <g id="merge-cell-left">
+ <path id="cell-border" d="M4 7v9h7v-3l-1 .834V15H5V8h5v1.167L11 10V7z"/>
+ <path id="arrow" d="M8 9v2H6v1h2v2l3-2.5z"/>
+ </g>
+ <use id="merge-cell-right" xlink:href="#merge-cell-left" transform="matrix(-1 0 0 1 24 0)"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-progressive.png
new file mode 100644
index 00000000..a75b2a0f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-progressive.svg
new file mode 100644
index 00000000..c2c5a7e2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells-progressive.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="table-merge-cells">
+ <g id="merge-cell-left">
+ <path id="cell-border" d="M4 7v9h7v-3l-1 .834V15H5V8h5v1.167L11 10V7z"/>
+ <path id="arrow" d="M8 9v2H6v1h2v2l3-2.5z"/>
+ </g>
+ <use id="merge-cell-right" xlink:href="#merge-cell-left" transform="matrix(-1 0 0 1 24 0)"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells.png
new file mode 100644
index 00000000..e6b2da3e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells.svg
new file mode 100644
index 00000000..3ffb9e5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-merge-cells.svg
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-merge-cells">
+ <g id="merge-cell-left">
+ <path id="cell-border" d="M4 7v9h7v-3l-1 .834V15H5V8h5v1.167L11 10V7z"/>
+ <path id="arrow" d="M8 9v2H6v1h2v2l3-2.5z"/>
+ </g>
+ <use id="merge-cell-right" xlink:href="#merge-cell-left" transform="matrix(-1 0 0 1 24 0)"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-progressive.png
new file mode 100644
index 00000000..b364a8fe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-progressive.svg
new file mode 100644
index 00000000..3441e651
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table-progressive.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="table-insert">
+ <path id="table" d="M4 6v11h15V6zm1 3h6v3H5zm7 0h6v3h-6zm-7 4h6v3H5zm7 0h6v3h-6z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table.png
new file mode 100644
index 00000000..f4008f6b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table.svg
new file mode 100644
index 00000000..b5733fba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/table.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="table-insert">
+ <path id="table" d="M4 6v11h15V6zm1 3h6v3H5zm7 0h6v3h-6zm-7 4h6v3H5zm7 0h6v3h-6z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-constructive.png
new file mode 100644
index 00000000..6372f39d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-constructive.svg
new file mode 100644
index 00000000..ce046877
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-constructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-destructive.png
new file mode 100644
index 00000000..cf85c4d0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-destructive.svg
new file mode 100644
index 00000000..cb00c1c9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#d33">
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-invert.png
new file mode 100644
index 00000000..fd5956cb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-invert.svg
new file mode 100644
index 00000000..a4f38b45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-progressive.png
new file mode 100644
index 00000000..6372f39d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-progressive.svg
new file mode 100644
index 00000000..ce046877
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-warning.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-warning.png
new file mode 100644
index 00000000..24dff071
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-warning.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-warning.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-warning.svg
new file mode 100644
index 00000000..bf31a978
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag-warning.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ff5d00">
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag.png
new file mode 100644
index 00000000..82461ef7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag.svg
new file mode 100644
index 00000000..7a211a3f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tag.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.748 11.717a1 1 0 0 1 0 1.414l-4.95 4.95a1 1 0 0 1-1.413 0l-6.01-6.01c-.39-.382-.707-1.15-.707-1.7V6c0-.55.45-1 1-1h4.363c.55 0 1.32.318 1.71.707l6.01 6.01zM8.104 7.457a1.477 1.477 0 0 0 0 2.092 1.49 1.49 0 0 0 2.094 0 1.49 1.49 0 0 0 0-2.1 1.484 1.484 0 0 0-2.094 0z" id="tag"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-invert.png
new file mode 100644
index 00000000..cba38d26
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-invert.svg
new file mode 100644
index 00000000..4d0e4a5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="template-add">
+ <path id="add" d="M23 7h-4V3h-2v4h-4v2h4v4h2V9h4z"/>
+ <path id="template" d="M18 14v4H6c-1.1 0-2-.9-2-2V8h8V7H3v9c0 1.7 1.3 3 3 3h13v-5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-progressive.png
new file mode 100644
index 00000000..70341108
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-progressive.svg
new file mode 100644
index 00000000..8b6325e3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="template-add">
+ <path id="add" d="M23 7h-4V3h-2v4h-4v2h4v4h2V9h4z"/>
+ <path id="template" d="M18 14v4H6c-1.1 0-2-.9-2-2V8h8V7H3v9c0 1.7 1.3 3 3 3h13v-5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr.png
new file mode 100644
index 00000000..f3ce49ee
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr.svg
new file mode 100644
index 00000000..8cd95e0a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="template-add">
+ <path id="add" d="M23 7h-4V3h-2v4h-4v2h4v4h2V9h4z"/>
+ <path id="template" d="M18 14v4H6c-1.1 0-2-.9-2-2V8h8V7H3v9c0 1.7 1.3 3 3 3h13v-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-invert.png
new file mode 100644
index 00000000..eb8d08d8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-invert.svg
new file mode 100644
index 00000000..32779864
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="template-add">
+ <path id="add" d="M1 7h4V3h2v4h4v2H7v4H5V9H1z"/>
+ <path id="template" d="M6 14v4h12c1.1 0 2-.9 2-2V8h-8V7h9v9c0 1.7-1.3 3-3 3H5v-5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-progressive.png
new file mode 100644
index 00000000..7514278c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-progressive.svg
new file mode 100644
index 00000000..ea7a4ced
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="template-add">
+ <path id="add" d="M1 7h4V3h2v4h4v2H7v4H5V9H1z"/>
+ <path id="template" d="M6 14v4h12c1.1 0 2-.9 2-2V8h-8V7h9v9c0 1.7-1.3 3-3 3H5v-5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl.png
new file mode 100644
index 00000000..448caf4f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl.svg
new file mode 100644
index 00000000..62b30f5e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/templateAdd-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="template-add">
+ <path id="add" d="M1 7h4V3h2v4h4v2H7v4H5V9H1z"/>
+ <path id="template" d="M6 14v4h12c1.1 0 2-.9 2-2V8h-8V7h9v9c0 1.7-1.3 3-3 3H5v-5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-invert.png
new file mode 100644
index 00000000..44394d9e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-invert.svg
new file mode 100644
index 00000000..8824e9c1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M7 7H5V6h2l.47.5L8 6h2v1H8v10h2v1H8l-.5-.53L7 18H5v-1h2zm6.976 9v-2H11v-4h2.976V8.044L20 12.022z" id="text-dir-ltr"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-progressive.png
new file mode 100644
index 00000000..4e9b0fc1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-progressive.svg
new file mode 100644
index 00000000..968e13b0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M7 7H5V6h2l.47.5L8 6h2v1H8v10h2v1H8l-.5-.53L7 18H5v-1h2zm6.976 9v-2H11v-4h2.976V8.044L20 12.022z" id="text-dir-ltr"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright.png
new file mode 100644
index 00000000..fede39a8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright.svg
new file mode 100644
index 00000000..83dd7697
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-lefttoright.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 7H5V6h2l.47.5L8 6h2v1H8v10h2v1H8l-.5-.53L7 18H5v-1h2zm6.976 9v-2H11v-4h2.976V8.044L20 12.022z" id="text-dir-ltr"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-invert.png
new file mode 100644
index 00000000..d5b78c24
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-invert.svg
new file mode 100644
index 00000000..12544d9c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M17 17h2v1h-2l-.47-.5-.53.5h-2v-1h2V7h-2V6h2l.5.53L17 6h2v1h-2zm-6.976-9v2H13v4h-2.976v1.956L4 11.978z" id="text-dir-rtl"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-progressive.png
new file mode 100644
index 00000000..955a65fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-progressive.svg
new file mode 100644
index 00000000..73ebe603
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M17 17h2v1h-2l-.47-.5-.53.5h-2v-1h2V7h-2V6h2l.5.53L17 6h2v1h-2zm-6.976-9v2H13v4h-2.976v1.956L4 11.978z" id="text-dir-rtl"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft.png
new file mode 100644
index 00000000..9f60ed5a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft.svg
new file mode 100644
index 00000000..78cb85b3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-dir-righttoleft.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 17h2v1h-2l-.47-.5-.53.5h-2v-1h2V7h-2V6h2l.5.53L17 6h2v1h-2zm-6.976-9v2H13v4h-2.976v1.956L4 11.978z" id="text-dir-rtl"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-invert.png
new file mode 100644
index 00000000..f173ad7c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-invert.svg
new file mode 100644
index 00000000..318c168c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="text-style">
+ <path id="a" d="M15.296 18h2.79l-1.14-12h-2.79L6 18h2.79l2.038-3h4.183l.29 3zm-3.11-5L14.5 9.6l.323 3.4H12.19z"/>
+ <path id="underline" d="M6 19h12v1H6v-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-progressive.png
new file mode 100644
index 00000000..5cbdfa41
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-progressive.svg
new file mode 100644
index 00000000..6f179201
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="text-style">
+ <path id="a" d="M15.296 18h2.79l-1.14-12h-2.79L6 18h2.79l2.038-3h4.183l.29 3zm-3.11-5L14.5 9.6l.323 3.4H12.19z"/>
+ <path id="underline" d="M6 19h12v1H6v-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style.png
new file mode 100644
index 00000000..65ab476a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style.svg
new file mode 100644
index 00000000..466672eb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/text-style.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="text-style">
+ <path id="a" d="M15.296 18h2.79l-1.14-12h-2.79L6 18h2.79l2.038-3h4.183l.29 3zm-3.11-5L14.5 9.6l.323 3.4H12.19z"/>
+ <path id="underline" d="M6 19h12v1H6v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-destructive.png
new file mode 100644
index 00000000..c367e77b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-destructive.svg
new file mode 100644
index 00000000..eb52343c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#d33">
+ <path d="M6 8c0-1.1.9-2 2-2h2l1-1h2l1 1h2c1.1 0 2 .9 2 2H6zm1 1h10l-1 11H8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-invert.png
new file mode 100644
index 00000000..04eaa413
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-invert.svg
new file mode 100644
index 00000000..f84bfe90
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M6 8c0-1.1.9-2 2-2h2l1-1h2l1 1h2c1.1 0 2 .9 2 2H6zm1 1h10l-1 11H8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-progressive.png
new file mode 100644
index 00000000..478c7020
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-progressive.svg
new file mode 100644
index 00000000..1099f6aa
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M6 8c0-1.1.9-2 2-2h2l1-1h2l1 1h2c1.1 0 2 .9 2 2H6zm1 1h10l-1 11H8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash.png
new file mode 100644
index 00000000..b3e899d8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash.svg
new file mode 100644
index 00000000..76502dce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/trash.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M6 8c0-1.1.9-2 2-2h2l1-1h2l1 1h2c1.1 0 2 .9 2 2H6zm1 1h10l-1 11H8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-invert.png
new file mode 100644
index 00000000..6196d390
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-invert.svg
new file mode 100644
index 00000000..28442a3d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M3 13.35l1.8-7.2c.2-.996.81-1.8 1.8-1.8h10.8c.99 0 1.6.867 1.8 1.8l1.8 7.2v4.5c0 .99-.81 1.8-1.8 1.8H4.8c-.99 0-1.8-.81-1.8-1.8v-4.5zm6.96 1.8h4.08c-.49.557-1.212.9-2.04.9a2.68 2.68 0 0 1-2.04-.9h4.08c.414-.472.66-1.098.66-1.8h4.14l-1.44-7.2H6.6l-1.44 7.2H9.3c0 .702.246 1.328.66 1.8z" id="tray"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-progressive.png
new file mode 100644
index 00000000..f6554496
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-progressive.svg
new file mode 100644
index 00000000..7b079ea8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M3 13.35l1.8-7.2c.2-.996.81-1.8 1.8-1.8h10.8c.99 0 1.6.867 1.8 1.8l1.8 7.2v4.5c0 .99-.81 1.8-1.8 1.8H4.8c-.99 0-1.8-.81-1.8-1.8v-4.5zm6.96 1.8h4.08c-.49.557-1.212.9-2.04.9a2.68 2.68 0 0 1-2.04-.9h4.08c.414-.472.66-1.098.66-1.8h4.14l-1.44-7.2H6.6l-1.44 7.2H9.3c0 .702.246 1.328.66 1.8z" id="tray"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray.png
new file mode 100644
index 00000000..e5c5e8fc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray.svg
new file mode 100644
index 00000000..d7ab69b9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/tray.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3 13.35l1.8-7.2c.2-.996.81-1.8 1.8-1.8h10.8c.99 0 1.6.867 1.8 1.8l1.8 7.2v4.5c0 .99-.81 1.8-1.8 1.8H4.8c-.99 0-1.8-.81-1.8-1.8v-4.5zm6.96 1.8h4.08c-.49.557-1.212.9-2.04.9a2.68 2.68 0 0 1-2.04-.9h4.08c.414-.472.66-1.098.66-1.8h4.14l-1.44-7.2H6.6l-1.44 7.2H9.3c0 .702.246 1.328.66 1.8z" id="tray"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-invert.png
new file mode 100644
index 00000000..7426f564
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-invert.svg
new file mode 100644
index 00000000..148da470
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M17 11v2h-2l3.6 3.6c.9-1.3 1.4-2.9 1.4-4.6 0-4.4-3.6-8-8-8-1.7 0-3.3.5-4.6 1.4L13 11h4zM4 4L3 5l2.4 2.4C4.5 8.7 4 10.3 4 12c0 4.4 3.6 8 8 8 1.7 0 3.3-.5 4.6-1.4L19 21l1-1L4 4zm3 9v-2h2l2 2H7z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-progressive.png
new file mode 100644
index 00000000..d797f3e8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-progressive.svg
new file mode 100644
index 00000000..e80e6ae1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M17 11v2h-2l3.6 3.6c.9-1.3 1.4-2.9 1.4-4.6 0-4.4-3.6-8-8-8-1.7 0-3.3.5-4.6 1.4L13 11h4zM4 4L3 5l2.4 2.4C4.5 8.7 4 10.3 4 12c0 4.4 3.6 8 8 8 1.7 0 3.3-.5 4.6-1.4L19 21l1-1L4 4zm3 9v-2h2l2 2H7z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr.png
new file mode 100644
index 00000000..640bb2a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr.svg
new file mode 100644
index 00000000..160219c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17 11v2h-2l3.6 3.6c.9-1.3 1.4-2.9 1.4-4.6 0-4.4-3.6-8-8-8-1.7 0-3.3.5-4.6 1.4L13 11h4zM4 4L3 5l2.4 2.4C4.5 8.7 4 10.3 4 12c0 4.4 3.6 8 8 8 1.7 0 3.3-.5 4.6-1.4L19 21l1-1L4 4zm3 9v-2h2l2 2H7z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-invert.png
new file mode 100644
index 00000000..a02e2e0d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-invert.svg
new file mode 100644
index 00000000..8aace964
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M7 11v2h2l-3.6 3.6C4.5 15.3 4 13.7 4 12c0-4.4 3.6-8 8-8 1.7 0 3.3.5 4.6 1.4L11 11H7zm13-7l1 1-2.4 2.4c.9 1.3 1.4 2.9 1.4 4.6 0 4.4-3.6 8-8 8-1.7 0-3.3-.5-4.6-1.4L5 21l-1-1L20 4zm-3 9v-2h-2l-2 2h4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-progressive.png
new file mode 100644
index 00000000..4d062cbe
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-progressive.svg
new file mode 100644
index 00000000..1337e16d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M7 11v2h2l-3.6 3.6C4.5 15.3 4 13.7 4 12c0-4.4 3.6-8 8-8 1.7 0 3.3.5 4.6 1.4L11 11H7zm13-7l1 1-2.4 2.4c.9 1.3 1.4 2.9 1.4 4.6 0 4.4-3.6 8-8 8-1.7 0-3.3-.5-4.6-1.4L5 21l-1-1L20 4zm-3 9v-2h-2l-2 2h4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl.png
new file mode 100644
index 00000000..2475b061
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl.svg
new file mode 100644
index 00000000..90fe46ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unBlock-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 11v2h2l-3.6 3.6C4.5 15.3 4 13.7 4 12c0-4.4 3.6-8 8-8 1.7 0 3.3.5 4.6 1.4L11 11H7zm13-7l1 1-2.4 2.4c.9 1.3 1.4 2.9 1.4 4.6 0 4.4-3.6 8-8 8-1.7 0-3.3-.5-4.6-1.4L5 21l-1-1L20 4zm-3 9v-2h-2l-2 2h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-invert.png
new file mode 100644
index 00000000..6535d439
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-invert.svg
new file mode 100644
index 00000000..dcc4ebff
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M5 21l7-6 7 6V3H5z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-progressive.png
new file mode 100644
index 00000000..6177f6b0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-progressive.svg
new file mode 100644
index 00000000..92e965b0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M5 21l7-6 7 6V3H5z" fill-rule="evenodd"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip.png
new file mode 100644
index 00000000..37916ef2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip.svg
new file mode 100644
index 00000000..68459db6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unClip.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 21l7-6 7 6V3H5z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-invert.png
new file mode 100644
index 00000000..83380171
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-invert.svg
new file mode 100644
index 00000000..dba18af4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M19.9 19.6l-16-16-1.1 1.1L6 7.9V20h1v-7c.6-.6 2-.8 3.4-.7l8.4 8.4 1.1-1.1zM17 14V7c-.7.7-2.7.9-4 .5V6c-1.2-1.3-3.9-1.3-5.4-.5l8.9 9c.3-.2.4-.3.5-.5z"/>
+</g></svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-progressive.png
new file mode 100644
index 00000000..bf1a6e02
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-progressive.svg
new file mode 100644
index 00000000..e84befe5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M19.9 19.6l-16-16-1.1 1.1L6 7.9V20h1v-7c.6-.6 2-.8 3.4-.7l8.4 8.4 1.1-1.1zM17 14V7c-.7.7-2.7.9-4 .5V6c-1.2-1.3-3.9-1.3-5.4-.5l8.9 9c.3-.2.4-.3.5-.5z"/>
+</g></svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr.png
new file mode 100644
index 00000000..780cb87f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr.svg
new file mode 100644
index 00000000..4bbd61ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19.9 19.6l-16-16-1.1 1.1L6 7.9V20h1v-7c.6-.6 2-.8 3.4-.7l8.4 8.4 1.1-1.1zM17 14V7c-.7.7-2.7.9-4 .5V6c-1.2-1.3-3.9-1.3-5.4-.5l8.9 9c.3-.2.4-.3.5-.5z"/>
+</svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-invert.png
new file mode 100644
index 00000000..4f9c3adc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-invert.svg
new file mode 100644
index 00000000..88256ec3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M3.5 19.6l16-16 1.1 1.1-3.2 3.2V20h-1v-7c-.6-.6-2-.8-3.4-.7l-8.4 8.4-1.1-1.1zM6.3 14V7c.7.7 2.7.9 4 .5V6c1.2-1.3 3.9-1.3 5.4-.5l-8.9 9c-.3-.2-.4-.3-.5-.5z"/>
+</g></svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-progressive.png
new file mode 100644
index 00000000..4abe9c83
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-progressive.svg
new file mode 100644
index 00000000..fcb4d11c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M3.5 19.6l16-16 1.1 1.1-3.2 3.2V20h-1v-7c-.6-.6-2-.8-3.4-.7l-8.4 8.4-1.1-1.1zM6.3 14V7c.7.7 2.7.9 4 .5V6c1.2-1.3 3.9-1.3 5.4-.5l-8.9 9c-.3-.2-.4-.3-.5-.5z"/>
+</g></svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl.png
new file mode 100644
index 00000000..fa3696ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl.svg
new file mode 100644
index 00000000..5d944258
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unFlag-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M3.5 19.6l16-16 1.1 1.1-3.2 3.2V20h-1v-7c-.6-.6-2-.8-3.4-.7l-8.4 8.4-1.1-1.1zM6.3 14V7c.7.7 2.7.9 4 .5V6c1.2-1.3 3.9-1.3 5.4-.5l-8.9 9c-.3-.2-.4-.3-.5-.5z"/>
+</svg> \ No newline at end of file
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-destructive.png
new file mode 100644
index 00000000..2cb27f15
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-destructive.svg
new file mode 100644
index 00000000..cf82e1fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#d33">
+ <path d="M12 9V7s0-5-4.5-5S3 7 3 7h2s0-3 2.5-3S10 7 10 7v2H7v7c0 1.7 1.3 3 3 3h10V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-invert.png
new file mode 100644
index 00000000..68c14374
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-invert.svg
new file mode 100644
index 00000000..3c6f966a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 9V7s0-5-4.5-5S3 7 3 7h2s0-3 2.5-3S10 7 10 7v2H7v7c0 1.7 1.3 3 3 3h10V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-progressive.png
new file mode 100644
index 00000000..6f6a5d4c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-progressive.svg
new file mode 100644
index 00000000..55b8cc3c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 9V7s0-5-4.5-5S3 7 3 7h2s0-3 2.5-3S10 7 10 7v2H7v7c0 1.7 1.3 3 3 3h10V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr.png
new file mode 100644
index 00000000..e6d9aae4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr.svg
new file mode 100644
index 00000000..25e08600
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 9V7s0-5-4.5-5S3 7 3 7h2s0-3 2.5-3S10 7 10 7v2H7v7c0 1.7 1.3 3 3 3h10V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-destructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-destructive.png
new file mode 100644
index 00000000..fac51b9f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-destructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-destructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-destructive.svg
new file mode 100644
index 00000000..d70f3a96
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-destructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#d33">
+ <path d="M11 9V7s0-5 4.5-5S20 7 20 7h-2s0-3-2.5-3S13 7 13 7v2h3v7c0 1.7-1.3 3-3 3H3V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-invert.png
new file mode 100644
index 00000000..d50b4c70
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-invert.svg
new file mode 100644
index 00000000..bfe53ad2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M11 9V7s0-5 4.5-5S20 7 20 7h-2s0-3-2.5-3S13 7 13 7v2h3v7c0 1.7-1.3 3-3 3H3V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-progressive.png
new file mode 100644
index 00000000..a7e7d32e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-progressive.svg
new file mode 100644
index 00000000..20e4afa0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M11 9V7s0-5 4.5-5S20 7 20 7h-2s0-3-2.5-3S13 7 13 7v2h3v7c0 1.7-1.3 3-3 3H3V9z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl.png
new file mode 100644
index 00000000..0529c16c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl.svg
new file mode 100644
index 00000000..577b5705
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unLock-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 9V7s0-5 4.5-5S20 7 20 7h-2s0-3-2.5-3S13 7 13 7v2h3v7c0 1.7-1.3 3-3 3H3V9z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-constructive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-constructive.png
new file mode 100644
index 00000000..580d6943
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-constructive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-constructive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-constructive.svg
new file mode 100644
index 00000000..7265f4a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-constructive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M21 11l-6-1-3-6-3 6-6 1 4 4-1 6 6-3 6 3-1-6 4-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-invert.png
new file mode 100644
index 00000000..20ce036d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-invert.svg
new file mode 100644
index 00000000..b34f49ba
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M21 11l-6-1-3-6-3 6-6 1 4 4-1 6 6-3 6 3-1-6 4-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-progressive.png
new file mode 100644
index 00000000..580d6943
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-progressive.svg
new file mode 100644
index 00000000..7265f4a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M21 11l-6-1-3-6-3 6-6 1 4 4-1 6 6-3 6 3-1-6 4-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar.png
new file mode 100644
index 00000000..2329af3e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar.svg
new file mode 100644
index 00000000..724d1901
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unStar.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M21 11l-6-1-3-6-3 6-6 1 4 4-1 6 6-3 6 3-1-6 4-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-invert.png
new file mode 100644
index 00000000..af3f0e98
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-invert.svg
new file mode 100644
index 00000000..efa8e835
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M20.5 20.5L5 5 4 6l3 3 1 11h8l.2-1.8 3.3 3.3zM17 9h-6l5.5 5.5zm1-1c0-1.1-.9-2-2-2h-2l-1-1h-2l-1 1H8l2 2h8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-progressive.png
new file mode 100644
index 00000000..2f09eb65
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-progressive.svg
new file mode 100644
index 00000000..c5bf2ccd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M20.5 20.5L5 5 4 6l3 3 1 11h8l.2-1.8 3.3 3.3zM17 9h-6l5.5 5.5zm1-1c0-1.1-.9-2-2-2h-2l-1-1h-2l-1 1H8l2 2h8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr.png
new file mode 100644
index 00000000..3b5231fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr.svg
new file mode 100644
index 00000000..64b3b71e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M20.5 20.5L5 5 4 6l3 3 1 11h8l.2-1.8 3.3 3.3zM17 9h-6l5.5 5.5zm1-1c0-1.1-.9-2-2-2h-2l-1-1h-2l-1 1H8l2 2h8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-invert.png
new file mode 100644
index 00000000..1cb54499
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-invert.svg
new file mode 100644
index 00000000..3fb20857
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M4 20.5L19.5 5l1 1-3 3-1 11h-8l-.2-1.8L5 21.5zM7.5 9h6L8 14.5zm-1-1c0-1.1.9-2 2-2h2l1-1h2l1 1h2l-2 2h-8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-progressive.png
new file mode 100644
index 00000000..e828b362
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-progressive.svg
new file mode 100644
index 00000000..0a67774b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M4 20.5L19.5 5l1 1-3 3-1 11h-8l-.2-1.8L5 21.5zM7.5 9h6L8 14.5zm-1-1c0-1.1.9-2 2-2h2l1-1h2l1 1h2l-2 2h-8z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl.png
new file mode 100644
index 00000000..a1d23882
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl.svg
new file mode 100644
index 00000000..e5e40322
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/unTrash-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M4 20.5L19.5 5l1 1-3 3-1 11h-8l-.2-1.8L5 21.5zM7.5 9h6L8 14.5zm-1-1c0-1.1.9-2 2-2h2l1-1h2l1 1h2l-2 2h-8z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-invert.png
new file mode 100644
index 00000000..8a6ca429
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-invert.svg
new file mode 100644
index 00000000..3078617d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="underline-a">
+ <path id="a" d="M14.424 16H16.5L13.037 6H10.96L7.5 16h2.077l.627-2h3.604l.616 2zm-3.92-3.623L12 7.997l1.51 4.38h-3z"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-progressive.png
new file mode 100644
index 00000000..f84ad6c1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-progressive.svg
new file mode 100644
index 00000000..99d9dadc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="underline-a">
+ <path id="a" d="M14.424 16H16.5L13.037 6H10.96L7.5 16h2.077l.627-2h3.604l.616 2zm-3.92-3.623L12 7.997l1.51 4.38h-3z"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a.png
new file mode 100644
index 00000000..78a3c3f0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a.svg
new file mode 100644
index 00000000..1ddae104
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-a.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="underline-a">
+ <path id="a" d="M14.424 16H16.5L13.037 6H10.96L7.5 16h2.077l.627-2h3.604l.616 2zm-3.92-3.623L12 7.997l1.51 4.38h-3z"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-invert.png
new file mode 100644
index 00000000..9f0af6c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-invert.svg
new file mode 100644
index 00000000..8136276d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="underline-u">
+ <path id="u" d="M8 6h2v5.96c-.104 1.706.695 2 2 2.04 1.777.062 2.002-.88 2-2.04V6h2v6.123c0 1.28-.338 2.245-1.016 2.898-.672.658-1.666.98-2.98.98-1.32 0-2.32-.32-2.996-.98C8.336 14.37 8 13.41 8 12.13V6"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-progressive.png
new file mode 100644
index 00000000..a8bcf2da
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-progressive.svg
new file mode 100644
index 00000000..29532130
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="underline-u">
+ <path id="u" d="M8 6h2v5.96c-.104 1.706.695 2 2 2.04 1.777.062 2.002-.88 2-2.04V6h2v6.123c0 1.28-.338 2.245-1.016 2.898-.672.658-1.666.98-2.98.98-1.32 0-2.32-.32-2.996-.98C8.336 14.37 8 13.41 8 12.13V6"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u.png
new file mode 100644
index 00000000..0dbeb80c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u.svg
new file mode 100644
index 00000000..ff47e2ce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/underline-u.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="underline-u">
+ <path id="u" d="M8 6h2v5.96c-.104 1.706.695 2 2 2.04 1.777.062 2.002-.88 2-2.04V6h2v6.123c0 1.28-.338 2.245-1.016 2.898-.672.658-1.666.98-2.98.98-1.32 0-2.32-.32-2.996-.98C8.336 14.37 8 13.41 8 12.13V6"/>
+ <path id="underline" d="M7 17h10v1H7v-1z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-invert.png
new file mode 100644
index 00000000..9fcea7f3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-invert.svg
new file mode 100644
index 00000000..e5c84a9f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M12 8l8 10H4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-progressive.png
new file mode 100644
index 00000000..5cc7e791
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-progressive.svg
new file mode 100644
index 00000000..b6bbc972
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M12 8l8 10H4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle.png
new file mode 100644
index 00000000..f1aca31a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle.svg
new file mode 100644
index 00000000..9f0efc59
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upTriangle.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M12 8l8 10H4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-invert.png
new file mode 100644
index 00000000..aa26066b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-invert.svg
new file mode 100644
index 00000000..4a7cf26a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M10 13c0 1.7 1.3 3 3 3V9h3l-4.5-5L7 9h3v4zm7 0v5H7c-.6 0-1-.4-1-1v-4H4v4c0 1.9 1.3 3 3 3h12v-7h-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-progressive.png
new file mode 100644
index 00000000..7ec3b647
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-progressive.svg
new file mode 100644
index 00000000..85bb62f4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M10 13c0 1.7 1.3 3 3 3V9h3l-4.5-5L7 9h3v4zm7 0v5H7c-.6 0-1-.4-1-1v-4H4v4c0 1.9 1.3 3 3 3h12v-7h-2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr.png
new file mode 100644
index 00000000..08e31e9e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr.svg
new file mode 100644
index 00000000..dc4676fb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M10 13c0 1.7 1.3 3 3 3V9h3l-4.5-5L7 9h3v4zm7 0v5H7c-.6 0-1-.4-1-1v-4H4v4c0 1.9 1.3 3 3 3h12v-7h-2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-invert.png
new file mode 100644
index 00000000..602ae423
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-invert.svg
new file mode 100644
index 00000000..d347e6ac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M13 13c0 1.7-1.3 3-3 3V9H7l4.5-5L16 9h-3v4zm-7 0v5h10c.6 0 1-.4 1-1v-4h2v4c0 1.9-1.3 3-3 3H4v-7h2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-progressive.png
new file mode 100644
index 00000000..42fb647d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-progressive.svg
new file mode 100644
index 00000000..d367074a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M13 13c0 1.7-1.3 3-3 3V9H7l4.5-5L16 9h-3v4zm-7 0v5h10c.6 0 1-.4 1-1v-4h2v4c0 1.9-1.3 3-3 3H4v-7h2z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl.png
new file mode 100644
index 00000000..ccabf989
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl.svg
new file mode 100644
index 00000000..ed3fe772
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/upload-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M13 13c0 1.7-1.3 3-3 3V9H7l4.5-5L16 9h-3v4zm-7 0v5h10c.6 0 1-.4 1-1v-4h2v4c0 1.9-1.3 3-3 3H4v-7h2z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-invert.png
new file mode 100644
index 00000000..98083bea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-invert.svg
new file mode 100644
index 00000000..beefd8d7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M16 5H4v12c0 1.7 1.3 3 3 3h12V8c0-1.7-1.3-3-3-3zm-2 4c.7 0 1.2.6 1.2 1.2s-.6 1.2-1.2 1.2-1.2-.6-1.2-1.2S13.3 9 14 9zM9 9c.7 0 1.2.6 1.2 1.2s-.5 1.3-1.2 1.3-1.2-.6-1.2-1.2S8.3 9 9 9zm7 5.4c0 .2-.1.3-.3.5-.7.6-1.6 1-2.6 1.3s-2.1.2-3.1 0-2-.9-2.7-1.5c-.1-.1-.2-.3-.2-.4s.1-.3.2-.4c.1-.1.3-.2.4-.2.2 0 .3.1.4.2.5.5 1.2.9 2.1 1.1s1.7.2 2.6 0 1.6-.5 2.1-1c.1-.1.3-.2.4-.2s.3.1.5.2.2.2.2.4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-progressive.png
new file mode 100644
index 00000000..decc2ca3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-progressive.svg
new file mode 100644
index 00000000..3232e97a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M16 5H4v12c0 1.7 1.3 3 3 3h12V8c0-1.7-1.3-3-3-3zm-2 4c.7 0 1.2.6 1.2 1.2s-.6 1.2-1.2 1.2-1.2-.6-1.2-1.2S13.3 9 14 9zM9 9c.7 0 1.2.6 1.2 1.2s-.5 1.3-1.2 1.3-1.2-.6-1.2-1.2S8.3 9 9 9zm7 5.4c0 .2-.1.3-.3.5-.7.6-1.6 1-2.6 1.3s-2.1.2-3.1 0-2-.9-2.7-1.5c-.1-.1-.2-.3-.2-.4s.1-.3.2-.4c.1-.1.3-.2.4-.2.2 0 .3.1.4.2.5.5 1.2.9 2.1 1.1s1.7.2 2.6 0 1.6-.5 2.1-1c.1-.1.3-.2.4-.2s.3.1.5.2.2.2.2.4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr.png
new file mode 100644
index 00000000..ce385f97
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr.svg
new file mode 100644
index 00000000..7f526e52
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 5H4v12c0 1.7 1.3 3 3 3h12V8c0-1.7-1.3-3-3-3zm-2 4c.7 0 1.2.6 1.2 1.2s-.6 1.2-1.2 1.2-1.2-.6-1.2-1.2S13.3 9 14 9zM9 9c.7 0 1.2.6 1.2 1.2s-.5 1.3-1.2 1.3-1.2-.6-1.2-1.2S8.3 9 9 9zm7 5.4c0 .2-.1.3-.3.5-.7.6-1.6 1-2.6 1.3s-2.1.2-3.1 0-2-.9-2.7-1.5c-.1-.1-.2-.3-.2-.4s.1-.3.2-.4c.1-.1.3-.2.4-.2.2 0 .3.1.4.2.5.5 1.2.9 2.1 1.1s1.7.2 2.6 0 1.6-.5 2.1-1c.1-.1.3-.2.4-.2s.3.1.5.2.2.2.2.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-invert.png
new file mode 100644
index 00000000..3dc0f442
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-invert.svg
new file mode 100644
index 00000000..08a382a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M7 5h12v12c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3zm2 4c-.7 0-1.2.6-1.2 1.2s.6 1.2 1.2 1.2 1.2-.6 1.2-1.2S9.7 9 9 9zm5 0c-.7 0-1.2.6-1.2 1.2s.5 1.3 1.2 1.3 1.2-.6 1.2-1.2S14.7 9 14 9zm-7 5.4c0 .2.1.3.3.5.7.6 1.6 1 2.6 1.3 1 .3 2.1.2 3.1 0s2-.9 2.7-1.5c.1-.1.2-.3.2-.4 0-.1-.1-.3-.2-.4-.1-.1-.3-.2-.4-.2-.2 0-.3.1-.4.2-.5.5-1.2.9-2.1 1.1-.9.2-1.7.2-2.6 0-.9-.2-1.6-.5-2.1-1-.1-.1-.3-.2-.4-.2-.1 0-.3.1-.5.2s-.2.2-.2.4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-progressive.png
new file mode 100644
index 00000000..fde69b83
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-progressive.svg
new file mode 100644
index 00000000..c38292ec
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M7 5h12v12c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3zm2 4c-.7 0-1.2.6-1.2 1.2s.6 1.2 1.2 1.2 1.2-.6 1.2-1.2S9.7 9 9 9zm5 0c-.7 0-1.2.6-1.2 1.2s.5 1.3 1.2 1.3 1.2-.6 1.2-1.2S14.7 9 14 9zm-7 5.4c0 .2.1.3.3.5.7.6 1.6 1 2.6 1.3 1 .3 2.1.2 3.1 0s2-.9 2.7-1.5c.1-.1.2-.3.2-.4 0-.1-.1-.3-.2-.4-.1-.1-.3-.2-.4-.2-.2 0-.3.1-.4.2-.5.5-1.2.9-2.1 1.1-.9.2-1.7.2-2.6 0-.9-.2-1.6-.5-2.1-1-.1-.1-.3-.2-.4-.2-.1 0-.3.1-.5.2s-.2.2-.2.4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl.png
new file mode 100644
index 00000000..ee1afbce
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl.svg
new file mode 100644
index 00000000..838ae31c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userActive-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 5h12v12c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3zm2 4c-.7 0-1.2.6-1.2 1.2s.6 1.2 1.2 1.2 1.2-.6 1.2-1.2S9.7 9 9 9zm5 0c-.7 0-1.2.6-1.2 1.2s.5 1.3 1.2 1.3 1.2-.6 1.2-1.2S14.7 9 14 9zm-7 5.4c0 .2.1.3.3.5.7.6 1.6 1 2.6 1.3 1 .3 2.1.2 3.1 0s2-.9 2.7-1.5c.1-.1.2-.3.2-.4 0-.1-.1-.3-.2-.4-.1-.1-.3-.2-.4-.2-.2 0-.3.1-.4.2-.5.5-1.2.9-2.1 1.1-.9.2-1.7.2-2.6 0-.9-.2-1.6-.5-2.1-1-.1-.1-.3-.2-.4-.2-.1 0-.3.1-.5.2s-.2.2-.2.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-invert.png
new file mode 100644
index 00000000..1f4d3a4d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-invert.svg
new file mode 100644
index 00000000..5f4e1369
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M18.75 17.4c-1.08-.36-3.6-1.35-3.6-1.35-.81-.27-.81-.99-.9-1.8v-.09c1.26-1.08 2.25-2.88 2.25-4.86 0-4.23-1.8-5.85-4.5-5.85-1.89 0-4.5 1.08-4.5 5.85 0 1.89.99 3.69 2.25 4.86v.09c0 .81-.09 1.53-.9 1.8 0 0-2.61.99-3.6 1.35-1.17.36-2.25.9-2.25 2.25v.9h18v-.9c0-1.08-.72-1.8-2.25-2.25z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-progressive.png
new file mode 100644
index 00000000..74b699bc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-progressive.svg
new file mode 100644
index 00000000..26ae8b64
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M18.75 17.4c-1.08-.36-3.6-1.35-3.6-1.35-.81-.27-.81-.99-.9-1.8v-.09c1.26-1.08 2.25-2.88 2.25-4.86 0-4.23-1.8-5.85-4.5-5.85-1.89 0-4.5 1.08-4.5 5.85 0 1.89.99 3.69 2.25 4.86v.09c0 .81-.09 1.53-.9 1.8 0 0-2.61.99-3.6 1.35-1.17.36-2.25.9-2.25 2.25v.9h18v-.9c0-1.08-.72-1.8-2.25-2.25z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar.png
new file mode 100644
index 00000000..81900956
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar.svg
new file mode 100644
index 00000000..ce714e60
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userAvatar.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M18.75 17.4c-1.08-.36-3.6-1.35-3.6-1.35-.81-.27-.81-.99-.9-1.8v-.09c1.26-1.08 2.25-2.88 2.25-4.86 0-4.23-1.8-5.85-4.5-5.85-1.89 0-4.5 1.08-4.5 5.85 0 1.89.99 3.69 2.25 4.86v.09c0 .81-.09 1.53-.9 1.8 0 0-2.61.99-3.6 1.35-1.17.36-2.25.9-2.25 2.25v.9h18v-.9c0-1.08-.72-1.8-2.25-2.25z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-invert.png
new file mode 100644
index 00000000..db34f591
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-invert.svg
new file mode 100644
index 00000000..075ea5c3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M16 5H4v12c0 1.7 1.3 3 3 3h12V8c0-1.7-1.3-3-3-3zm-9.3 5.4C6.2 10 6 9.6 6 9c.6.6 1.5.9 2.5.9s1.9-.3 2.5-.9c0 .6-.2 1-.7 1.4-.5.4-1.1.6-1.8.6s-1.3-.2-1.8-.6zm8.4 4.3c0 .2-.1.3-.3.4-1 .6-2.2.9-3.5.9-1.2 0-2.3-.3-3.3-1-.2-.1-.2-.2-.3-.4s0-.3.1-.5.2-.2.4-.3.3 0 .5.1c.8.5 1.7.8 2.8.8s2-.2 2.8-.7c.1-.1.3-.1.5-.1s.3.1.4.3l-.1.5zm1.2-4.3c-.5.4-1.1.6-1.8.6s-1.3-.2-1.8-.6S12 9.6 12 9c.6.6 1.5.9 2.5.9s1.9-.3 2.5-.9c0 .6-.2 1-.7 1.4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-progressive.png
new file mode 100644
index 00000000..4d7f0ebc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-progressive.svg
new file mode 100644
index 00000000..f48929d1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M16 5H4v12c0 1.7 1.3 3 3 3h12V8c0-1.7-1.3-3-3-3zm-9.3 5.4C6.2 10 6 9.6 6 9c.6.6 1.5.9 2.5.9s1.9-.3 2.5-.9c0 .6-.2 1-.7 1.4-.5.4-1.1.6-1.8.6s-1.3-.2-1.8-.6zm8.4 4.3c0 .2-.1.3-.3.4-1 .6-2.2.9-3.5.9-1.2 0-2.3-.3-3.3-1-.2-.1-.2-.2-.3-.4s0-.3.1-.5.2-.2.4-.3.3 0 .5.1c.8.5 1.7.8 2.8.8s2-.2 2.8-.7c.1-.1.3-.1.5-.1s.3.1.4.3l-.1.5zm1.2-4.3c-.5.4-1.1.6-1.8.6s-1.3-.2-1.8-.6S12 9.6 12 9c.6.6 1.5.9 2.5.9s1.9-.3 2.5-.9c0 .6-.2 1-.7 1.4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr.png
new file mode 100644
index 00000000..05170e12
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr.svg
new file mode 100644
index 00000000..e58bbc3f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M16 5H4v12c0 1.7 1.3 3 3 3h12V8c0-1.7-1.3-3-3-3zm-9.3 5.4C6.2 10 6 9.6 6 9c.6.6 1.5.9 2.5.9s1.9-.3 2.5-.9c0 .6-.2 1-.7 1.4-.5.4-1.1.6-1.8.6s-1.3-.2-1.8-.6zm8.4 4.3c0 .2-.1.3-.3.4-1 .6-2.2.9-3.5.9-1.2 0-2.3-.3-3.3-1-.2-.1-.2-.2-.3-.4s0-.3.1-.5.2-.2.4-.3.3 0 .5.1c.8.5 1.7.8 2.8.8s2-.2 2.8-.7c.1-.1.3-.1.5-.1s.3.1.4.3l-.1.5zm1.2-4.3c-.5.4-1.1.6-1.8.6s-1.3-.2-1.8-.6S12 9.6 12 9c.6.6 1.5.9 2.5.9s1.9-.3 2.5-.9c0 .6-.2 1-.7 1.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-invert.png
new file mode 100644
index 00000000..8fe830a4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-invert.svg
new file mode 100644
index 00000000..0b3aa4d5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M7 5h12v12c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3zm9.3 5.4c.5-.4.7-.8.7-1.4-.6.6-1.5.9-2.5.9S12.6 9.6 12 9c0 .6.2 1 .7 1.4.5.4 1.1.6 1.8.6s1.3-.2 1.8-.6zm-8.4 4.3c0 .2.1.3.3.4 1 .6 2.2.9 3.5.9 1.2 0 2.3-.3 3.3-1 .2-.1.2-.2.3-.4.1-.2 0-.3-.1-.5s-.2-.2-.4-.3c-.2-.1-.3 0-.5.1-.8.5-1.7.8-2.8.8-1.1 0-2-.2-2.8-.7-.1-.1-.3-.1-.5-.1s-.3.1-.4.3l.1.5zm-1.2-4.3c.5.4 1.1.6 1.8.6s1.3-.2 1.8-.6c.5-.4.7-.8.7-1.4-.6.6-1.5.9-2.5.9S6.6 9.6 6 9c0 .6.2 1 .7 1.4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-progressive.png
new file mode 100644
index 00000000..10ebac4e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-progressive.svg
new file mode 100644
index 00000000..76d950c2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M7 5h12v12c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3zm9.3 5.4c.5-.4.7-.8.7-1.4-.6.6-1.5.9-2.5.9S12.6 9.6 12 9c0 .6.2 1 .7 1.4.5.4 1.1.6 1.8.6s1.3-.2 1.8-.6zm-8.4 4.3c0 .2.1.3.3.4 1 .6 2.2.9 3.5.9 1.2 0 2.3-.3 3.3-1 .2-.1.2-.2.3-.4.1-.2 0-.3-.1-.5s-.2-.2-.4-.3c-.2-.1-.3 0-.5.1-.8.5-1.7.8-2.8.8-1.1 0-2-.2-2.8-.7-.1-.1-.3-.1-.5-.1s-.3.1-.4.3l.1.5zm-1.2-4.3c.5.4 1.1.6 1.8.6s1.3-.2 1.8-.6c.5-.4.7-.8.7-1.4-.6.6-1.5.9-2.5.9S6.6 9.6 6 9c0 .6.2 1 .7 1.4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl.png
new file mode 100644
index 00000000..bf953f1d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl.svg
new file mode 100644
index 00000000..039e6627
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userInactive-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M7 5h12v12c0 1.7-1.3 3-3 3H4V8c0-1.7 1.3-3 3-3zm9.3 5.4c.5-.4.7-.8.7-1.4-.6.6-1.5.9-2.5.9S12.6 9.6 12 9c0 .6.2 1 .7 1.4.5.4 1.1.6 1.8.6s1.3-.2 1.8-.6zm-8.4 4.3c0 .2.1.3.3.4 1 .6 2.2.9 3.5.9 1.2 0 2.3-.3 3.3-1 .2-.1.2-.2.3-.4.1-.2 0-.3-.1-.5s-.2-.2-.4-.3c-.2-.1-.3 0-.5.1-.8.5-1.7.8-2.8.8-1.1 0-2-.2-2.8-.7-.1-.1-.3-.1-.5-.1s-.3.1-.4.3l.1.5zm-1.2-4.3c.5.4 1.1.6 1.8.6s1.3-.2 1.8-.6c.5-.4.7-.8.7-1.4-.6.6-1.5.9-2.5.9S6.6 9.6 6 9c0 .6.2 1 .7 1.4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-invert.png
new file mode 100644
index 00000000..332bcba6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-invert.svg
new file mode 100644
index 00000000..934128fd
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm11.2 2.5c.7 0 1.2.6 1.2 1.2s-.5 1.3-1.2 1.3-1.2-.6-1.2-1.2.6-1.3 1.2-1.3zm-5.4 0c.7 0 1.2.6 1.2 1.2s-.6 1.3-1.2 1.3-1.2-.6-1.2-1.2.5-1.3 1.2-1.3zm2.7 8.5c-5.1 0-6-5-6-5s2 1 6 1l6-1s-1 5-6 5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-progressive.png
new file mode 100644
index 00000000..2ef91f0b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-progressive.svg
new file mode 100644
index 00000000..232a04a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm11.2 2.5c.7 0 1.2.6 1.2 1.2s-.5 1.3-1.2 1.3-1.2-.6-1.2-1.2.6-1.3 1.2-1.3zm-5.4 0c.7 0 1.2.6 1.2 1.2s-.6 1.3-1.2 1.3-1.2-.6-1.2-1.2.5-1.3 1.2-1.3zm2.7 8.5c-5.1 0-6-5-6-5s2 1 6 1l6-1s-1 5-6 5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr.png
new file mode 100644
index 00000000..18981fd9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr.svg
new file mode 100644
index 00000000..f277ce4d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 6v11l-3 3h17c1.7 0 3-1.3 3-3V6H5zm11.2 2.5c.7 0 1.2.6 1.2 1.2s-.5 1.3-1.2 1.3-1.2-.6-1.2-1.2.6-1.3 1.2-1.3zm-5.4 0c.7 0 1.2.6 1.2 1.2s-.6 1.3-1.2 1.3-1.2-.6-1.2-1.2.5-1.3 1.2-1.3zm2.7 8.5c-5.1 0-6-5-6-5s2 1 6 1l6-1s-1 5-6 5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-invert.png
new file mode 100644
index 00000000..187f3e68
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-invert.svg
new file mode 100644
index 00000000..5c48db2e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M19 6v11l3 3H5c-1.7 0-3-1.3-3-3V6h17zM7.8 8.5c-.7 0-1.2.6-1.2 1.2S7.1 11 7.8 11 9 10.4 9 9.8s-.6-1.3-1.2-1.3zm5.4 0c-.7 0-1.2.6-1.2 1.2s.6 1.3 1.2 1.3 1.2-.6 1.2-1.2-.5-1.3-1.2-1.3zM10.5 17c5.1 0 6-5 6-5s-2 1-6 1l-6-1s1 5 6 5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-progressive.png
new file mode 100644
index 00000000..91c703d5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-progressive.svg
new file mode 100644
index 00000000..2a2b17b8
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M19 6v11l3 3H5c-1.7 0-3-1.3-3-3V6h17zM7.8 8.5c-.7 0-1.2.6-1.2 1.2S7.1 11 7.8 11 9 10.4 9 9.8s-.6-1.3-1.2-1.3zm5.4 0c-.7 0-1.2.6-1.2 1.2s.6 1.3 1.2 1.3 1.2-.6 1.2-1.2-.5-1.3-1.2-1.3zM10.5 17c5.1 0 6-5 6-5s-2 1-6 1l-6-1s1 5 6 5z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl.png
new file mode 100644
index 00000000..7122efa5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl.svg
new file mode 100644
index 00000000..0f9a6fb3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/userTalk-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M19 6v11l3 3H5c-1.7 0-3-1.3-3-3V6h17zM7.8 8.5c-.7 0-1.2.6-1.2 1.2S7.1 11 7.8 11 9 10.4 9 9.8s-.6-1.3-1.2-1.3zm5.4 0c-.7 0-1.2.6-1.2 1.2s.6 1.3 1.2 1.3 1.2-.6 1.2-1.2-.5-1.3-1.2-1.3zM10.5 17c5.1 0 6-5 6-5s-2 1-6 1l-6-1s1 5 6 5z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-invert.png
new file mode 100644
index 00000000..e716ba54
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-invert.svg
new file mode 100644
index 00000000..b70f4f90
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-invert.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="viewCompact">
+ <circle cx="6" cy="6" r="2"/>
+ <circle cx="12" cy="6" r="2"/>
+ <circle cx="18" cy="6" r="2"/>
+ <circle cx="6" cy="12" r="2"/>
+ <circle cx="12" cy="12" r="2"/>
+ <circle cx="18" cy="12" r="2"/>
+ <circle cx="6" cy="18" r="2"/>
+ <circle cx="12" cy="18" r="2"/>
+ <circle cx="18" cy="18" r="2"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-progressive.png
new file mode 100644
index 00000000..545814b4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-progressive.svg
new file mode 100644
index 00000000..a7edfc55
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact-progressive.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="viewCompact">
+ <circle cx="6" cy="6" r="2"/>
+ <circle cx="12" cy="6" r="2"/>
+ <circle cx="18" cy="6" r="2"/>
+ <circle cx="6" cy="12" r="2"/>
+ <circle cx="12" cy="12" r="2"/>
+ <circle cx="18" cy="12" r="2"/>
+ <circle cx="6" cy="18" r="2"/>
+ <circle cx="12" cy="18" r="2"/>
+ <circle cx="18" cy="18" r="2"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact.png
new file mode 100644
index 00000000..13fe4207
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact.svg
new file mode 100644
index 00000000..d96a2e3f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewCompact.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="viewCompact">
+ <circle cx="6" cy="6" r="2"/>
+ <circle cx="12" cy="6" r="2"/>
+ <circle cx="18" cy="6" r="2"/>
+ <circle cx="6" cy="12" r="2"/>
+ <circle cx="12" cy="12" r="2"/>
+ <circle cx="18" cy="12" r="2"/>
+ <circle cx="6" cy="18" r="2"/>
+ <circle cx="12" cy="18" r="2"/>
+ <circle cx="18" cy="18" r="2"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-invert.png
new file mode 100644
index 00000000..3ea093a9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-invert.svg
new file mode 100644
index 00000000..1e349b3f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-invert.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="viewDetails">
+ <circle cx="5.5" cy="8.5" r="2.5"/>
+ <path d="M10 6h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ <circle cx="5.5" cy="16.5" r="2.5"/>
+ <path d="M10 14h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-progressive.png
new file mode 100644
index 00000000..9cef2837
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-progressive.svg
new file mode 100644
index 00000000..c6588c2f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr-progressive.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="viewDetails">
+ <circle cx="5.5" cy="8.5" r="2.5"/>
+ <path d="M10 6h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ <circle cx="5.5" cy="16.5" r="2.5"/>
+ <path d="M10 14h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr.png
new file mode 100644
index 00000000..4341f0e6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr.svg
new file mode 100644
index 00000000..1a5092a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-ltr.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="viewDetails">
+ <circle cx="5.5" cy="8.5" r="2.5"/>
+ <path d="M10 6h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ <circle cx="5.5" cy="16.5" r="2.5"/>
+ <path d="M10 14h12v1H10zm0 2h9v1h-9zm0 2h4v1h-4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-invert.png
new file mode 100644
index 00000000..ea861d82
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-invert.svg
new file mode 100644
index 00000000..f2d6a874
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-invert.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="viewDetails">
+ <circle cx="18.5" cy="8.5" r="2.5"/>
+ <path d="M14 6H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ <circle cx="18.5" cy="16.5" r="2.5"/>
+ <path d="M14 14H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-progressive.png
new file mode 100644
index 00000000..03178200
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-progressive.svg
new file mode 100644
index 00000000..9b7b78dc
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl-progressive.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="viewDetails">
+ <circle cx="18.5" cy="8.5" r="2.5"/>
+ <path d="M14 6H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ <circle cx="18.5" cy="16.5" r="2.5"/>
+ <path d="M14 14H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl.png
new file mode 100644
index 00000000..338294c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl.svg
new file mode 100644
index 00000000..f43b05f1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/viewDetails-rtl.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="viewDetails">
+ <circle cx="18.5" cy="8.5" r="2.5"/>
+ <path d="M14 6H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ <circle cx="18.5" cy="16.5" r="2.5"/>
+ <path d="M14 14H2v1h12zm0 2H5v1h9zm0 2h-4v1h4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator-invert.png
new file mode 100644
index 00000000..e18ee176
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator-invert.svg
new file mode 100644
index 00000000..10edb0f6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#ffffff">
+ <path d="M0 10v8h2.3c.3.6 1 1 1.7 1h4c1.5 0 2.7-.8 3-2h2c.3 1.2 1.5 2 3 2h4c.7 0 1.4 0 1.7-1H24v-8zm10 6c0 1-.4 2-2 2H4c-.6 0-1-.4-1-1v-3c0-.6.4-1 1-1h5c.6 0 1 .4 1 1zm11 1c0 .6-.4 1-1 1h-4c-1.6 0-2-1-2-2v-2c0-.6.4-1 1-1h5c.6 0 1 .4 1 1z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator.png
new file mode 100644
index 00000000..afa56528
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator.svg
new file mode 100644
index 00000000..ae6ba27a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/visionSimulator.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M0 10v8h2.3c.3.6 1 1 1.7 1h4c1.5 0 2.7-.8 3-2h2c.3 1.2 1.5 2 3 2h4c.7 0 1.4 0 1.7-1H24v-8zm10 6c0 1-.4 2-2 2H4c-.6 0-1-.4-1-1v-3c0-.6.4-1 1-1h5c.6 0 1 .4 1 1zm11 1c0 .6-.4 1-1 1h-4c-1.6 0-2-1-2-2v-2c0-.6.4-1 1-1h5c.6 0 1 .4 1 1z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-invert.png
new file mode 100644
index 00000000..70189688
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-invert.svg
new file mode 100644
index 00000000..ff99d08e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M13 14h5v1h-5v-1zm0 3h5v-1h-5v1zm0 1h5v1h-5v-1zm-1-5v3l-5 3 1-6-4-3 6-1 2-5s1.9 5 2 5l6 1-4 3h-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-progressive.png
new file mode 100644
index 00000000..17676145
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-progressive.svg
new file mode 100644
index 00000000..6d06edea
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M13 14h5v1h-5v-1zm0 3h5v-1h-5v1zm0 1h5v1h-5v-1zm-1-5v3l-5 3 1-6-4-3 6-1 2-5s1.9 5 2 5l6 1-4 3h-4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr.png
new file mode 100644
index 00000000..53e70116
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr.svg
new file mode 100644
index 00000000..b13df22d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M13 14h5v1h-5v-1zm0 3h5v-1h-5v1zm0 1h5v1h-5v-1zm-1-5v3l-5 3 1-6-4-3 6-1 2-5s1.9 5 2 5l6 1-4 3h-4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-invert.png
new file mode 100644
index 00000000..28008b5b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-invert.svg
new file mode 100644
index 00000000..50224d0e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M11 14H6v1h5v-1zm0 3H6v-1h5v1zm0 1H6v1h5v-1zm1-5v3l5 3-1-6 4-3-6-1-2-5s-1.9 5-2 5l-6 1 4 3h4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-progressive.png
new file mode 100644
index 00000000..53c59833
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-progressive.svg
new file mode 100644
index 00000000..a2589bd1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl-progressive.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <path d="M11 14H6v1h5v-1zm0 3H6v-1h5v1zm0 1H6v1h5v-1zm1-5v3l5 3-1-6 4-3-6-1-2-5s-1.9 5-2 5l-6 1 4 3h4z"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl.png
new file mode 100644
index 00000000..8fc4df52
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl.svg
new file mode 100644
index 00000000..a4ec49a3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/watchlist-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M11 14H6v1h5v-1zm0 3H6v-1h5v1zm0 1H6v1h5v-1zm1-5v3l5 3-1-6 4-3-6-1-2-5s-1.9 5-2 5l-6 1 4 3h4z"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-invert.png
new file mode 100644
index 00000000..30ef53ed
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-invert.svg
new file mode 100644
index 00000000..72601da4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-invert.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="wikiText">
+ <path id="opening-bracket-inner" d="M7 19h3v-2H9V7h1V5H7z"/>
+ <path id="closing-bracket-inner" d="M17 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="closing-bracket-outer" d="M21 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="opening-bracket-outer" d="M3 19h3v-2H5V7h1V5H3z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-progressive.png
new file mode 100644
index 00000000..e1f516c0
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-progressive.svg
new file mode 100644
index 00000000..f7ba89d6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText-progressive.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="wikiText">
+ <path id="opening-bracket-inner" d="M7 19h3v-2H9V7h1V5H7z"/>
+ <path id="closing-bracket-inner" d="M17 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="closing-bracket-outer" d="M21 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="opening-bracket-outer" d="M3 19h3v-2H5V7h1V5H3z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText.png
new file mode 100644
index 00000000..40309aac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText.svg
new file mode 100644
index 00000000..4512cf56
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/wikiText.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="wikiText">
+ <path id="opening-bracket-inner" d="M7 19h3v-2H9V7h1V5H7z"/>
+ <path id="closing-bracket-inner" d="M17 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="closing-bracket-outer" d="M21 19h-3v-2h1V7h-1V5h3z"/>
+ <path id="opening-bracket-outer" d="M3 19h3v-2H5V7h1V5H3z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-invert.png
new file mode 100644
index 00000000..74c54ff7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-invert.svg
new file mode 100644
index 00000000..bebd3a83
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-invert.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <g id="window">
+ <path id="title" d="M7 10h10v1H7z"/>
+ <path id="frame" d="M16 19H8c-2.206 0-4-1.794-4-4V9c0-2.206 1.794-4 4-4h8c2.206 0 4 1.794 4 4v6c0 2.206-1.794 4-4 4zM8 7c-1.103 0-2 .897-2 2v6c0 1.103.897 2 2 2h8c1.103 0 2-.897 2-2V9c0-1.103-.897-2-2-2H8z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-progressive.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-progressive.png
new file mode 100644
index 00000000..2a18bea1
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-progressive.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-progressive.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-progressive.svg
new file mode 100644
index 00000000..9204afe7
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window-progressive.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#36c">
+ <g id="window">
+ <path id="title" d="M7 10h10v1H7z"/>
+ <path id="frame" d="M16 19H8c-2.206 0-4-1.794-4-4V9c0-2.206 1.794-4 4-4h8c2.206 0 4 1.794 4 4v6c0 2.206-1.794 4-4 4zM8 7c-1.103 0-2 .897-2 2v6c0 1.103.897 2 2 2h8c1.103 0 2-.897 2-2V9c0-1.103-.897-2-2-2H8z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window.png
new file mode 100644
index 00000000..bae13d71
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window.svg
new file mode 100644
index 00000000..093c8228
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/icons/window.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <g id="window">
+ <path id="title" d="M7 10h10v1H7z"/>
+ <path id="frame" d="M16 19H8c-2.206 0-4-1.794-4-4V9c0-2.206 1.794-4 4-4h8c2.206 0 4 1.794 4 4v6c0 2.206-1.794 4-4 4zM8 7c-1.103 0-2 .897-2 2v6c0 1.103.897 2 2 2h8c1.103 0 2-.897 2-2V9c0-1.103-.897-2-2-2H8z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert-invert.png
new file mode 100644
index 00000000..035b6269
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert-invert.svg
new file mode 100644
index 00000000..a5201751
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><g fill="#fff">
+ <path d="M6 12A6 6 0 1 1 6 0a6 6 0 0 1 0 12zM5 7h2V2H5zm0 3h2V8H5z" id="alert"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert.png
new file mode 100644
index 00000000..9d25a24e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert.svg
new file mode 100644
index 00000000..f94346ac
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/alert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <path d="M6 12A6 6 0 1 1 6 0a6 6 0 0 1 0 12zM5 7h2V2H5zm0 3h2V8H5z" id="alert"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down-invert.png
new file mode 100644
index 00000000..ae66af48
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down-invert.svg
new file mode 100644
index 00000000..b5e61440
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><g fill="#fff">
+ <path d="M11.05 3.996l-.965-1.053-4.035 3.86-3.947-3.86L1.05 3.996l5 5 5-5"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down.png
new file mode 100644
index 00000000..34f50419
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down.svg
new file mode 100644
index 00000000..d3e55d1c
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-down.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <path d="M11.05 3.996l-.965-1.053-4.035 3.86-3.947-3.86L1.05 3.996l5 5 5-5"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr-invert.png
new file mode 100644
index 00000000..68bf4750
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr-invert.svg
new file mode 100644
index 00000000..78f4b511
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><g fill="#fff">
+ <path d="M4.026 11l-1.052-.965L6.832 6 2.974 2.053 4.026 1l5 5-5 5"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr.png
new file mode 100644
index 00000000..cadc38f2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr.svg
new file mode 100644
index 00000000..e99855b3
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-ltr.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <path d="M4.026 11l-1.052-.965L6.832 6 2.974 2.053 4.026 1l5 5-5 5"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl-invert.png
new file mode 100644
index 00000000..fae56f1a
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl-invert.svg
new file mode 100644
index 00000000..bc0ff6f5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><g fill="#fff">
+ <path d="M7.974 11l1.052-.965L5.168 6l3.858-3.947L7.974 1l-5 5 5 5"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl.png
new file mode 100644
index 00000000..5a4c0b69
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl.svg
new file mode 100644
index 00000000..16475014
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-rtl.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <path d="M7.974 11l1.052-.965L5.168 6l3.858-3.947L7.974 1l-5 5 5 5"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up-invert.png
new file mode 100644
index 00000000..56eeea45
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up-invert.svg
new file mode 100644
index 00000000..3c81ae5d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><g fill="#fff">
+ <path d="M11 7.974l-.965 1.052L6 5.168 2.053 9.026 1 7.974l5-5 5 5"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up.png
new file mode 100644
index 00000000..672b7f37
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up.svg
new file mode 100644
index 00000000..ca93281d
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/arrow-up.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <path d="M11 7.974l-.965 1.052L6 5.168 2.053 9.026 1 7.974l5-5 5 5"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear-invert.png
new file mode 100644
index 00000000..82f5bf11
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear-invert.svg
new file mode 100644
index 00000000..eb45dfc9
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><g fill="#fff">
+ <g id="clear">
+ <path id="circle-with-cross" d="M6 0C2.7 0 0 2.7 0 6s2.7 6 6 6 6-2.7 6-6-2.7-6-6-6zM3.5 2.5L6 5l2.5-2.5 1 1L7 6l2.5 2.5-1 1L6 7 3.5 9.5l-1-1L5 6 2.5 3.5z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear.png
new file mode 100644
index 00000000..a858a031
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear.svg
new file mode 100644
index 00000000..3c010c10
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/clear.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="clear">
+ <path id="circle-with-cross" d="M6 0C2.7 0 0 2.7 0 6s2.7 6 6 6 6-2.7 6-6-2.7-6-6-6zM3.5 2.5L6 5l2.5-2.5 1 1L7 6l2.5 2.5-1 1L6 7 3.5 9.5l-1-1L5 6 2.5 3.5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required-invert.png
new file mode 100644
index 00000000..d9ff42fb
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required-invert.svg
new file mode 100644
index 00000000..efd08400
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required-invert.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><g fill="#fff">
+ <path d="M5 1h2v10H5zm4.83 1.634l1 1.732-8.66 5-1-1.732zM1.17 4.366l1-1.732 8.66 5-1 1.732z" id="required"/>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required.png
new file mode 100644
index 00000000..aca92390
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required.svg
new file mode 100644
index 00000000..94b0066e
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/required.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <path d="M5 1h2v10H5zm4.83 1.634l1 1.732-8.66 5-1-1.732zM1.17 4.366l1-1.732 8.66 5-1 1.732z" id="required"/>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr-invert.png
new file mode 100644
index 00000000..95298032
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr-invert.svg
new file mode 100644
index 00000000..cc383ee5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><g fill="#fff">
+ <g id="search">
+ <path id="magnifying-glass" d="M10.37 9.474L7.994 7.1l-.17-.1a3.45 3.45 0 0 0 .644-2.01A3.478 3.478 0 1 0 4.99 8.47c.75 0 1.442-.24 2.01-.648l.098.17 2.375 2.373c.19.188.543.142.79-.105s.293-.6.104-.79zm-5.38-2.27a2.21 2.21 0 1 1 2.21-2.21A2.21 2.21 0 0 1 4.99 7.21z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr.png
new file mode 100644
index 00000000..123fbfa2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr.svg
new file mode 100644
index 00000000..80c72bb5
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="search">
+ <path id="magnifying-glass" d="M10.37 9.474L7.994 7.1l-.17-.1a3.45 3.45 0 0 0 .644-2.01A3.478 3.478 0 1 0 4.99 8.47c.75 0 1.442-.24 2.01-.648l.098.17 2.375 2.373c.19.188.543.142.79-.105s.293-.6.104-.79zm-5.38-2.27a2.21 2.21 0 1 1 2.21-2.21A2.21 2.21 0 0 1 4.99 7.21z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl-invert.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl-invert.png
new file mode 100644
index 00000000..a7270579
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl-invert.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl-invert.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl-invert.svg
new file mode 100644
index 00000000..19114d8b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl-invert.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12"><g fill="#fff">
+ <g id="search">
+ <path id="magnifying-glass" d="M1.63 9.474L4.006 7.1l.17-.1a3.45 3.45 0 0 1-.644-2.01A3.478 3.478 0 1 1 7.01 8.47 3.43 3.43 0 0 1 5 7.822l-.098.17-2.375 2.373c-.19.188-.543.142-.79-.105s-.293-.6-.104-.79zm5.378-2.27A2.21 2.21 0 1 0 4.8 4.994 2.21 2.21 0 0 0 7.01 7.21z"/>
+ </g>
+</g></svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl.png
new file mode 100644
index 00000000..db740615
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl.svg
new file mode 100644
index 00000000..4b3cff42
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/indicators/search-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="12" height="12" viewBox="0 0 12 12">
+ <g id="search">
+ <path id="magnifying-glass" d="M1.63 9.474L4.006 7.1l.17-.1a3.45 3.45 0 0 1-.644-2.01A3.478 3.478 0 1 1 7.01 8.47 3.43 3.43 0 0 1 5 7.822l-.098.17-2.375 2.373c-.19.188-.543.142-.79-.105s-.293-.6-.104-.79zm5.378-2.27A2.21 2.21 0 1 0 4.8 4.994 2.21 2.21 0 0 0 7.01 7.21z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/pending.gif b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/pending.gif
new file mode 100644
index 00000000..1194eed2
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/pending.gif
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/transparency.png b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/transparency.png
new file mode 100644
index 00000000..dbf69b93
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/transparency.png
Binary files differ
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/transparency.svg b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/transparency.svg
new file mode 100644
index 00000000..cadec2a6
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/images/textures/transparency.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+ <g id="transparency">
+ <path d="M0 0h8v8H0zm8 8h8v8H8z" fill="#ccc"/>
+ <path d="M8 0h8v8H8zM0 8h8v8H0z" fill="#fff"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/indicators.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/indicators.json
new file mode 100644
index 00000000..1b993654
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/indicators.json
@@ -0,0 +1,30 @@
+{
+ "selectorWithoutVariant": ".oo-ui-indicator-{name}",
+ "selectorWithVariant": ".oo-ui-image-{variant}.oo-ui-indicator-{name}",
+ "intro": "@import '../../../../src/styles/common';",
+ "variants": {
+ "invert": {
+ "color": "#fff",
+ "global": true
+ }
+ },
+ "images": {
+ "alert": { "file": "images/indicators/alert.svg" },
+ "clear": { "file": "images/indicators/clear.svg" },
+ "up": { "file": "images/indicators/arrow-up.svg" },
+ "down": { "file": "images/indicators/arrow-down.svg" },
+ "next": { "file": {
+ "ltr": "images/indicators/arrow-ltr.svg",
+ "rtl": "images/indicators/arrow-rtl.svg"
+ } },
+ "previous": { "file": {
+ "ltr": "images/indicators/arrow-rtl.svg",
+ "rtl": "images/indicators/arrow-ltr.svg"
+ } },
+ "required": { "file": "images/indicators/required.svg" },
+ "search": { "file": {
+ "ltr": "images/indicators/search-ltr.svg",
+ "rtl": "images/indicators/search-rtl.svg"
+ } }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/textures.json b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/textures.json
new file mode 100644
index 00000000..e90730ab
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/themes/wikimediaui/textures.json
@@ -0,0 +1,8 @@
+{
+ "prefix": "oo-ui-texture",
+ "intro": "@import '../../../../src/styles/common';",
+ "images": {
+ "pending": { "file": "images/textures/pending.gif" },
+ "transparency": { "file": "images/textures/transparency.svg" }
+ }
+}
diff --git a/www/wiki/resources/lib/oojs-ui/wikimedia-ui-base.less b/www/wiki/resources/lib/oojs-ui/wikimedia-ui-base.less
new file mode 100644
index 00000000..d450dbc4
--- /dev/null
+++ b/www/wiki/resources/lib/oojs-ui/wikimedia-ui-base.less
@@ -0,0 +1,153 @@
+/**
+ * WikimediaUI Base v0.9.2
+ * Wikimedia Foundation user interface base variables
+ */
+
+/* Colors */
+// WikimediaUI (WMUI) color palette
+@wmui-color-base0: #000; // = HSB 0°, 0%, 0%
+@wmui-color-base10: #222; // = HSB 0°, 0%, 13%
+@wmui-color-base20: #54595d; // = HSB 207°, 10%, 36%; WCAG 2.0 level AAA 7.09:1 contrast ratio on `#fff`
+@wmui-color-base30: #72777d; // = HSB 210°, 9%, 49%; WCAG 2.0 level AA at 4.52:1 contrast ratio on `#fff`
+@wmui-color-base50: #a2a9b1; // = HSB 212°, 8%, 69%
+@wmui-color-base70: #c8ccd1; // = HSB 213°, 4%, 82%
+@wmui-color-base80: #eaecf0; // = HSB 220°, 3%, 94%
+@wmui-color-base90: #f8f9fa; // = HSB 210°, 1%, 98%
+@wmui-color-base100: #fff; // = HSB 0°, 0%, 100%
+
+@wmui-color-accent30: #2a4b8d; // = HSB 220°, 70%, 55%
+@wmui-color-accent50: #36c; // = HSB 220°, 75%, 80%
+@wmui-color-accent90: #eaf3ff; // = HSB 214°, 8%, 100%
+
+@wmui-color-red30: #b32424; // = HSB 360°, 80%, 70%
+@wmui-color-red50: #d33; // = HSB 360°, 77%, 87%
+@wmui-color-red90: #fee7e6; // = HSB 3°, 9%, 100%
+
+@wmui-color-yellow30: #ac6600; // = HSB 36°, 100%, 67%
+@wmui-color-yellow50: #fc3; // = HSB 45°, 80%, 100%
+@wmui-color-yellow90: #fef6e7; // = HSB 39°, 9%, 100%
+
+@wmui-color-green30: #14866d; // = HSB 167°, 85%, 53%
+@wmui-color-green50: #00af89; // = HSB 167°, 100%, 69%
+@wmui-color-green90: #d5fdf4; // = HSB 166°, 16%, 99%
+
+// Background Colors
+@background-color-base: @wmui-color-base100;
+@background-color-code: @wmui-color-base90;
+// 'Framed' UI elements (Framed Buttons, Dropdowns, ToggleSwitches...)
+@background-color-framed: @wmui-color-base90;
+@background-color-framed--hover: @wmui-color-base100;
+@background-color-framed--active: @wmui-color-base70;
+// Tabs Navigation Background Color
+@background-color-tabs: @wmui-color-base80;
+// Highlight Colors, RGBA Colors include hex fallback on `#fff` for IE 6/7/8
+@background-color-highlight: rgba( 255, 182, 13, 0.4 );
+@background-color-highlight--fallback: #ffe29e;
+
+// Foreground Colors
+@color-base: @wmui-color-base10;
+@color-base--hover: #444;
+@color-base--active: @wmui-color-base0;
+@color-base--inverted: @wmui-color-base100;
+@color-base--emphasized: @wmui-color-base0;
+@color-base--subtle: @wmui-color-base30;
+@color-base--disabled: @wmui-color-base30;
+@color-filled--disabled: @color-base--inverted;
+@color-placeholder: @wmui-color-base30;
+// Primary 'Progressive' Color, Background Color and states
+@background-color-primary: @wmui-color-accent90;
+@background-color-primary--hover: rgba( 41, 98, 204, 0.1 );
+@color-primary: @wmui-color-accent50;
+@color-primary--hover: #447ff5; // = `lighten( @color-primary, 3 )`
+@color-primary--active: @wmui-color-accent30;
+@color-primary--focus: @color-primary;
+// 'Destructive' Color, Background Color and states
+@background-color-destructive: @wmui-color-red90;
+@color-destructive: @wmui-color-red50;
+@color-destructive--hover: #ff4242;
+@color-destructive--active: @wmui-color-red30;
+@color-destructive--focus: @color-destructive;
+// Secondary Color and states (links only)
+@color-secondary: @wmui-color-green50;
+@color-secondary--hover: #1c6665;
+@color-secondary--active: @wmui-color-green30;
+@color-secondary--focus: @color-secondary;
+// Validation error feedback
+@color-erroneous: @wmui-color-red50;
+
+
+// Opacity
+@opacity-base: 1;
+@opacity-base--disabled: 0.51; // = `#7d7d7d` on `background-color: #fff`; HSB 0°, 0%, 49%
+@opacity-icon-base: 0.87; // = `#222` on `background-color: #fff`
+@opacity-icon-base--hover: 0.73; // = `#454545` on `background-color: #fff`, closest to `#444`
+@opacity-icon-base--selected: 1;
+
+
+/* Positioning */
+// Z-Index
+@z-index-base: 0;
+
+
+/* Box Model properties */
+/* Max Widths */
+@max-width-button: 28.75em; // = `460px` at `16px` base, see T95367
+@max-width-input-inline: 100%;
+
+// Border
+@border-base: @border-width-base solid @border-color-base;
+@border-dialog: @border-base;
+@border-menu: @border-base;
+// Border Colors
+@border-color-base: @wmui-color-base50;
+@border-color-base--hover: @wmui-color-base50;
+@border-color-base--active: @wmui-color-base30;
+@border-color-base--disabled: @color-base--disabled;
+@border-color-filled--disabled: @color-filled--disabled;
+@border-color-primary--active: #859dcc;
+@border-color-destructive--active: #b77c79;
+@border-color-inset--focus: @color-base--inverted;
+@border-color-heading: @wmui-color-base70;
+// Border Widths
+@border-width-base: 1px;
+// Border Radius
+@border-radius-base: 2px;
+
+// Box Shadows
+@box-shadow-base--focus: inset 0 0 0 1px @wmui-color-accent50;
+@box-shadow-primary--focus: inset 0 0 0 1px @color-primary, inset 0 0 0 2px @color-base--inverted;
+@box-shadow-inset--inverted: inset 0 0 0 1px @color-base--inverted;
+@box-shadow-filled--disabled: inset 0 0 0 1px @color-filled--disabled;
+@box-shadow-dialog: 0 2px 2px 0 rgba( 0, 0, 0, 0.25 );
+@box-shadow-menu: @box-shadow-dialog;
+
+
+/* Typography incl. print properties */
+// Font Families
+@font-family-base: @font-family-sans;
+@font-family-heading-main: @font-family-serif;
+@font-family-sans: 'Helvetica Neue', 'Helvetica', 'Nimbus Sans L', 'Arial', 'Liberation Sans', sans-serif;
+@font-family-sans--fallback: sans-serif;
+@font-family-serif: 'Linux Libertine', 'Georgia', 'Times', serif;
+@font-family-serif--fallback: serif;
+// Line Heights
+@line-height-base: 1.6;
+@line-height-heading: 1.25;
+@text-decoration-link--hover: none;
+// Text Shadows
+@text-shadow-base: 0 1px 1px @color-base--inverted; // 'coined' effect
+@text-shadow-base--disabled: @text-shadow-base;
+
+
+/* Other Properties */
+// Cursors
+@cursor-base--disabled: default;
+
+
+/* Animation & Transition */
+// Transitions
+@transition-base: @transition-duration-base;
+@transition-medium: @transition-duration-medium;
+// Transitions > Durations
+@transition-duration-base: 100ms;
+@transition-duration-medium: 250ms;
diff --git a/www/wiki/resources/lib/oojs/AUTHORS.txt b/www/wiki/resources/lib/oojs/AUTHORS.txt
new file mode 100644
index 00000000..97fee0ae
--- /dev/null
+++ b/www/wiki/resources/lib/oojs/AUTHORS.txt
@@ -0,0 +1,10 @@
+Bartosz Dziewoński <matmarex@wikimedia.org>
+C. Scott Ananian <cscott@cscott.net>
+David Chan <dchan@wikimedia.org>
+Ed Sanders <ejsanders@gmail.com>
+James D. Forrester <jforrester@wikimedia.org>
+Moriel Schottlender <moriel@gmail.com>
+Ori Livneh <ori@wikimedia.org>
+Roan Kattouw <roan.kattouw@gmail.com>
+Timo Tijhof <krinklemail@gmail.com>
+Trevor Parscal <trevorparscal@gmail.com>
diff --git a/www/wiki/resources/lib/oojs/LICENSE-MIT b/www/wiki/resources/lib/oojs/LICENSE-MIT
new file mode 100644
index 00000000..c6bbee2b
--- /dev/null
+++ b/www/wiki/resources/lib/oojs/LICENSE-MIT
@@ -0,0 +1,20 @@
+Copyright 2011-2017 OOjs Team and other contributors.
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/www/wiki/resources/lib/oojs/README.md b/www/wiki/resources/lib/oojs/README.md
new file mode 100644
index 00000000..ec14576f
--- /dev/null
+++ b/www/wiki/resources/lib/oojs/README.md
@@ -0,0 +1,98 @@
+[![npm](https://img.shields.io/npm/v/oojs.svg?style=flat)](https://www.npmjs.com/package/oojs) [![David](https://img.shields.io/david/dev/wikimedia/oojs.svg?style=flat)](https://david-dm.org/wikimedia/oojs#info=devDependencies)
+
+OOjs
+=================
+
+OOjs is a JavaScript library for working with objects.
+
+Key features include inheritance, mixins and utilities for working with objects.
+
+<pre lang="javascript">
+/* Example */
+( function ( oo ) {
+ function Animal() {}
+ function Magic() {}
+ function Unicorn() {
+ Animal.call( this );
+ Magic.call( this );
+ }
+ oo.inheritClass( Unicorn, Animal );
+ oo.mixinClass( Unicorn, Magic );
+}( OO ) );
+</pre>
+
+Quick start
+----------
+
+This library is available as an [npm](https://npmjs.org/) package! Install it right away:
+<pre lang="bash">
+npm install oojs
+</pre>
+
+Or clone the repo, `git clone https://phabricator.wikimedia.org/diffusion/GOJS/oojs.git`.
+
+ECMAScript 5
+----------
+
+OOjs requires a modern ECMAScript 5 environment. It is not necessarily compatible with ES3 engines (such as for IE 6-8). For ES3 environments, the old 1.x releases are available but not recommended.
+
+jQuery
+----------
+
+If your project uses jQuery, use the optimised `oojs.jquery.js` build instead.
+
+This build assumes jQuery is present and omits various chunks of code in favour of references to jQuery.
+
+jQuery 3.0.0 or higher is required.
+
+Versioning
+----------
+
+We use the Semantic Versioning guidelines as much as possible.
+
+Releases will be numbered in the following format:
+
+`<major>.<minor>.<patch>`
+
+For more information on SemVer, please visit http://semver.org/.
+
+Bug tracker
+-----------
+
+Found a bug? Please report it in the [issue tracker](https://phabricator.wikimedia.org/maniphest/task/edit/form/1/?projects=OOjs)!
+
+Release
+----------
+
+Release process:
+<pre lang="bash">
+$ cd path/to/oojs/
+$ git remote update
+$ git checkout -B release -t origin/master
+
+# Ensure tests pass
+$ npm install && npm test
+
+# Avoid using "npm version patch" because that creates
+# both a commit and a tag, and we shouldn't tag until after
+# the commit is merged.
+
+# Update release notes
+# Copy the resulting list into a new section on History.md
+$ git log --format='* %s (%aN)' --no-merges --reverse v$(node -e 'console.log(require("./package.json").version);')...HEAD
+$ edit History.md
+
+# Update the version number
+$ edit package.json
+
+$ git add -p
+$ git commit -m "Tag vX.X.X"
+$ git review
+
+# After merging:
+$ git remote update
+$ git checkout origin/master
+$ git tag "vX.X.X"
+$ git push --tags
+$ npm publish
+</pre>
diff --git a/www/wiki/resources/lib/oojs/oojs.jquery.js b/www/wiki/resources/lib/oojs/oojs.jquery.js
new file mode 100644
index 00000000..8cc6f118
--- /dev/null
+++ b/www/wiki/resources/lib/oojs/oojs.jquery.js
@@ -0,0 +1,1610 @@
+/*!
+ * OOjs v2.1.0 optimised for jQuery
+ * https://www.mediawiki.org/wiki/OOjs
+ *
+ * Copyright 2011-2017 OOjs Team and other contributors.
+ * Released under the MIT license
+ * https://oojs.mit-license.org
+ *
+ * Date: 2017-05-30T22:56:52Z
+ */
+( function ( global ) {
+
+'use strict';
+
+/* exported toString */
+var
+ /**
+ * Namespace for all classes, static methods and static properties.
+ * @class OO
+ * @singleton
+ */
+ oo = {},
+ // Optimisation: Local reference to Object.prototype.hasOwnProperty
+ hasOwn = oo.hasOwnProperty,
+ toString = oo.toString;
+
+/* Class Methods */
+
+/**
+ * Utility to initialize a class for OO inheritance.
+ *
+ * Currently this just initializes an empty static object.
+ *
+ * @param {Function} fn
+ */
+oo.initClass = function ( fn ) {
+ fn.static = fn.static || {};
+};
+
+/**
+ * Inherit from prototype to another using Object#create.
+ *
+ * Beware: This redefines the prototype, call before setting your prototypes.
+ *
+ * Beware: This redefines the prototype, can only be called once on a function.
+ * If called multiple times on the same function, the previous prototype is lost.
+ * This is how prototypal inheritance works, it can only be one straight chain
+ * (just like classical inheritance in PHP for example). If you need to work with
+ * multiple constructors consider storing an instance of the other constructor in a
+ * property instead, or perhaps use a mixin (see OO.mixinClass).
+ *
+ * function Thing() {}
+ * Thing.prototype.exists = function () {};
+ *
+ * function Person() {
+ * Person.super.apply( this, arguments );
+ * }
+ * OO.inheritClass( Person, Thing );
+ * Person.static.defaultEyeCount = 2;
+ * Person.prototype.walk = function () {};
+ *
+ * function Jumper() {
+ * Jumper.super.apply( this, arguments );
+ * }
+ * OO.inheritClass( Jumper, Person );
+ * Jumper.prototype.jump = function () {};
+ *
+ * Jumper.static.defaultEyeCount === 2;
+ * var x = new Jumper();
+ * x.jump();
+ * x.walk();
+ * x instanceof Thing && x instanceof Person && x instanceof Jumper;
+ *
+ * @param {Function} targetFn
+ * @param {Function} originFn
+ * @throws {Error} If target already inherits from origin
+ */
+oo.inheritClass = function ( targetFn, originFn ) {
+ var targetConstructor;
+
+ if ( !originFn ) {
+ throw new Error( 'inheritClass: Origin is not a function (actually ' + originFn + ')' );
+ }
+ if ( targetFn.prototype instanceof originFn ) {
+ throw new Error( 'inheritClass: Target already inherits from origin' );
+ }
+
+ targetConstructor = targetFn.prototype.constructor;
+
+ // Using ['super'] instead of .super because 'super' is not supported
+ // by IE 8 and below (bug 63303).
+ // Provide .parent as alias for code supporting older browsers which
+ // allows people to comply with their style guide.
+ // eslint-disable-next-line dot-notation
+ targetFn[ 'super' ] = targetFn.parent = originFn;
+
+ targetFn.prototype = Object.create( originFn.prototype, {
+ // Restore constructor property of targetFn
+ constructor: {
+ value: targetConstructor,
+ enumerable: false,
+ writable: true,
+ configurable: true
+ }
+ } );
+
+ // Extend static properties - always initialize both sides
+ oo.initClass( originFn );
+ targetFn.static = Object.create( originFn.static );
+};
+
+/**
+ * Copy over *own* prototype properties of a mixin.
+ *
+ * The 'constructor' (whether implicit or explicit) is not copied over.
+ *
+ * This does not create inheritance to the origin. If you need inheritance,
+ * use OO.inheritClass instead.
+ *
+ * Beware: This can redefine a prototype property, call before setting your prototypes.
+ *
+ * Beware: Don't call before OO.inheritClass.
+ *
+ * function Foo() {}
+ * function Context() {}
+ *
+ * // Avoid repeating this code
+ * function ContextLazyLoad() {}
+ * ContextLazyLoad.prototype.getContext = function () {
+ * if ( !this.context ) {
+ * this.context = new Context();
+ * }
+ * return this.context;
+ * };
+ *
+ * function FooBar() {}
+ * OO.inheritClass( FooBar, Foo );
+ * OO.mixinClass( FooBar, ContextLazyLoad );
+ *
+ * @param {Function} targetFn
+ * @param {Function} originFn
+ */
+oo.mixinClass = function ( targetFn, originFn ) {
+ var key;
+
+ if ( !originFn ) {
+ throw new Error( 'mixinClass: Origin is not a function (actually ' + originFn + ')' );
+ }
+
+ // Copy prototype properties
+ for ( key in originFn.prototype ) {
+ if ( key !== 'constructor' && hasOwn.call( originFn.prototype, key ) ) {
+ targetFn.prototype[ key ] = originFn.prototype[ key ];
+ }
+ }
+
+ // Copy static properties - always initialize both sides
+ oo.initClass( targetFn );
+ if ( originFn.static ) {
+ for ( key in originFn.static ) {
+ if ( hasOwn.call( originFn.static, key ) ) {
+ targetFn.static[ key ] = originFn.static[ key ];
+ }
+ }
+ } else {
+ oo.initClass( originFn );
+ }
+};
+
+/**
+ * Test whether one class is a subclass of another, without instantiating it.
+ *
+ * Every class is considered a subclass of Object and of itself.
+ *
+ * @param {Function} testFn The class to be tested
+ * @param {Function} baseFn The base class
+ * @return {boolean} Whether testFn is a subclass of baseFn (or equal to it)
+ */
+oo.isSubclass = function ( testFn, baseFn ) {
+ return testFn === baseFn || testFn.prototype instanceof baseFn;
+};
+
+/* Object Methods */
+
+/**
+ * Get a deeply nested property of an object using variadic arguments, protecting against
+ * undefined property errors.
+ *
+ * `quux = OO.getProp( obj, 'foo', 'bar', 'baz' );` is equivalent to `quux = obj.foo.bar.baz;`
+ * except that the former protects against JS errors if one of the intermediate properties
+ * is undefined. Instead of throwing an error, this function will return undefined in
+ * that case.
+ *
+ * @param {Object} obj
+ * @param {...Mixed} [keys]
+ * @return {Object|undefined} obj[arguments[1]][arguments[2]].... or undefined
+ */
+oo.getProp = function ( obj ) {
+ var i,
+ retval = obj;
+ for ( i = 1; i < arguments.length; i++ ) {
+ if ( retval === undefined || retval === null ) {
+ // Trying to access a property of undefined or null causes an error
+ return undefined;
+ }
+ retval = retval[ arguments[ i ] ];
+ }
+ return retval;
+};
+
+/**
+ * Set a deeply nested property of an object using variadic arguments, protecting against
+ * undefined property errors.
+ *
+ * `oo.setProp( obj, 'foo', 'bar', 'baz' );` is equivalent to `obj.foo.bar = baz;` except that
+ * the former protects against JS errors if one of the intermediate properties is
+ * undefined. Instead of throwing an error, undefined intermediate properties will be
+ * initialized to an empty object. If an intermediate property is not an object, or if obj itself
+ * is not an object, this function will silently abort.
+ *
+ * @param {Object} obj
+ * @param {...Mixed} [keys]
+ * @param {Mixed} [value]
+ */
+oo.setProp = function ( obj ) {
+ var i,
+ prop = obj;
+ if ( Object( obj ) !== obj || arguments.length < 2 ) {
+ return;
+ }
+ for ( i = 1; i < arguments.length - 2; i++ ) {
+ if ( prop[ arguments[ i ] ] === undefined ) {
+ prop[ arguments[ i ] ] = {};
+ }
+ if ( Object( prop[ arguments[ i ] ] ) !== prop[ arguments[ i ] ] ) {
+ return;
+ }
+ prop = prop[ arguments[ i ] ];
+ }
+ prop[ arguments[ arguments.length - 2 ] ] = arguments[ arguments.length - 1 ];
+};
+
+/**
+ * Delete a deeply nested property of an object using variadic arguments, protecting against
+ * undefined property errors, and deleting resulting empty objects.
+ *
+ * @param {Object} obj
+ * @param {...Mixed} [keys]
+ */
+oo.deleteProp = function ( obj ) {
+ var i,
+ prop = obj,
+ props = [ prop ];
+ if ( Object( obj ) !== obj || arguments.length < 2 ) {
+ return;
+ }
+ for ( i = 1; i < arguments.length - 1; i++ ) {
+ if ( prop[ arguments[ i ] ] === undefined || Object( prop[ arguments[ i ] ] ) !== prop[ arguments[ i ] ] ) {
+ return;
+ }
+ prop = prop[ arguments[ i ] ];
+ props.push( prop );
+ }
+ delete prop[ arguments[ i ] ];
+ // Walk back through props removing any plain empty objects
+ while ( ( prop = props.pop() ) && oo.isPlainObject( prop ) && !Object.keys( prop ).length ) {
+ delete props[ props.length - 1 ][ arguments[ props.length ] ];
+ }
+};
+
+/**
+ * Create a new object that is an instance of the same
+ * constructor as the input, inherits from the same object
+ * and contains the same own properties.
+ *
+ * This makes a shallow non-recursive copy of own properties.
+ * To create a recursive copy of plain objects, use #copy.
+ *
+ * var foo = new Person( mom, dad );
+ * foo.setAge( 21 );
+ * var foo2 = OO.cloneObject( foo );
+ * foo.setAge( 22 );
+ *
+ * // Then
+ * foo2 !== foo; // true
+ * foo2 instanceof Person; // true
+ * foo2.getAge(); // 21
+ * foo.getAge(); // 22
+ *
+ * @param {Object} origin
+ * @return {Object} Clone of origin
+ */
+oo.cloneObject = function ( origin ) {
+ var key, r;
+
+ r = Object.create( origin.constructor.prototype );
+
+ for ( key in origin ) {
+ if ( hasOwn.call( origin, key ) ) {
+ r[ key ] = origin[ key ];
+ }
+ }
+
+ return r;
+};
+
+/**
+ * Get an array of all property values in an object.
+ *
+ * @param {Object} obj Object to get values from
+ * @return {Array} List of object values
+ */
+oo.getObjectValues = function ( obj ) {
+ var key, values;
+
+ if ( obj !== Object( obj ) ) {
+ throw new TypeError( 'Called on non-object' );
+ }
+
+ values = [];
+ for ( key in obj ) {
+ if ( hasOwn.call( obj, key ) ) {
+ values[ values.length ] = obj[ key ];
+ }
+ }
+
+ return values;
+};
+
+/**
+ * Use binary search to locate an element in a sorted array.
+ *
+ * searchFunc is given an element from the array. `searchFunc(elem)` must return a number
+ * above 0 if the element we're searching for is to the right of (has a higher index than) elem,
+ * below 0 if it is to the left of elem, or zero if it's equal to elem.
+ *
+ * To search for a specific value with a comparator function (a `function cmp(a,b)` that returns
+ * above 0 if `a > b`, below 0 if `a < b`, and 0 if `a == b`), you can use
+ * `searchFunc = cmp.bind( null, value )`.
+ *
+ * @param {Array} arr Array to search in
+ * @param {Function} searchFunc Search function
+ * @param {boolean} [forInsertion] If not found, return index where val could be inserted
+ * @return {number|null} Index where val was found, or null if not found
+ */
+oo.binarySearch = function ( arr, searchFunc, forInsertion ) {
+ var mid, cmpResult,
+ left = 0,
+ right = arr.length;
+ while ( left < right ) {
+ // Equivalent to Math.floor( ( left + right ) / 2 ) but much faster
+ // eslint-disable-next-line no-bitwise
+ mid = ( left + right ) >> 1;
+ cmpResult = searchFunc( arr[ mid ] );
+ if ( cmpResult < 0 ) {
+ right = mid;
+ } else if ( cmpResult > 0 ) {
+ left = mid + 1;
+ } else {
+ return mid;
+ }
+ }
+ return forInsertion ? right : null;
+};
+
+/**
+ * Recursively compare properties between two objects.
+ *
+ * A false result may be caused by property inequality or by properties in one object missing from
+ * the other. An asymmetrical test may also be performed, which checks only that properties in the
+ * first object are present in the second object, but not the inverse.
+ *
+ * If either a or b is null or undefined it will be treated as an empty object.
+ *
+ * @param {Object|undefined|null} a First object to compare
+ * @param {Object|undefined|null} b Second object to compare
+ * @param {boolean} [asymmetrical] Whether to check only that a's values are equal to b's
+ * (i.e. a is a subset of b)
+ * @return {boolean} If the objects contain the same values as each other
+ */
+oo.compare = function ( a, b, asymmetrical ) {
+ var aValue, bValue, aType, bType, k;
+
+ if ( a === b ) {
+ return true;
+ }
+
+ a = a || {};
+ b = b || {};
+
+ if ( typeof a.nodeType === 'number' && typeof a.isEqualNode === 'function' ) {
+ return a.isEqualNode( b );
+ }
+
+ for ( k in a ) {
+ if ( !hasOwn.call( a, k ) || a[ k ] === undefined || a[ k ] === b[ k ] ) {
+ // Support es3-shim: Without the hasOwn filter, comparing [] to {} will be false in ES3
+ // because the shimmed "forEach" is enumerable and shows up in Array but not Object.
+ // Also ignore undefined values, because there is no conceptual difference between
+ // a key that is absent and a key that is present but whose value is undefined.
+ continue;
+ }
+
+ aValue = a[ k ];
+ bValue = b[ k ];
+ aType = typeof aValue;
+ bType = typeof bValue;
+ if ( aType !== bType ||
+ (
+ ( aType === 'string' || aType === 'number' || aType === 'boolean' ) &&
+ aValue !== bValue
+ ) ||
+ ( aValue === Object( aValue ) && !oo.compare( aValue, bValue, true ) ) ) {
+ return false;
+ }
+ }
+ // If the check is not asymmetrical, recursing with the arguments swapped will verify our result
+ return asymmetrical ? true : oo.compare( b, a, true );
+};
+
+/**
+ * Create a plain deep copy of any kind of object.
+ *
+ * Copies are deep, and will either be an object or an array depending on `source`.
+ *
+ * @param {Object} source Object to copy
+ * @param {Function} [leafCallback] Applied to leaf values after they are cloned but before they are added to the clone
+ * @param {Function} [nodeCallback] Applied to all values before they are cloned. If the nodeCallback returns a value other than undefined, the returned value is used instead of attempting to clone.
+ * @return {Object} Copy of source object
+ */
+oo.copy = function ( source, leafCallback, nodeCallback ) {
+ var key, destination;
+
+ if ( nodeCallback ) {
+ // Extensibility: check before attempting to clone source.
+ destination = nodeCallback( source );
+ if ( destination !== undefined ) {
+ return destination;
+ }
+ }
+
+ if ( Array.isArray( source ) ) {
+ // Array (fall through)
+ destination = new Array( source.length );
+ } else if ( source && typeof source.clone === 'function' ) {
+ // Duck type object with custom clone method
+ return leafCallback ? leafCallback( source.clone() ) : source.clone();
+ } else if ( source && typeof source.cloneNode === 'function' ) {
+ // DOM Node
+ return leafCallback ?
+ leafCallback( source.cloneNode( true ) ) :
+ source.cloneNode( true );
+ } else if ( oo.isPlainObject( source ) ) {
+ // Plain objects (fall through)
+ destination = {};
+ } else {
+ // Non-plain objects (incl. functions) and primitive values
+ return leafCallback ? leafCallback( source ) : source;
+ }
+
+ // source is an array or a plain object
+ for ( key in source ) {
+ destination[ key ] = oo.copy( source[ key ], leafCallback, nodeCallback );
+ }
+
+ // This is an internal node, so we don't apply the leafCallback.
+ return destination;
+};
+
+/**
+ * Generate a hash of an object based on its name and data.
+ *
+ * Performance optimization: <http://jsperf.com/ve-gethash-201208#/toJson_fnReplacerIfAoForElse>
+ *
+ * To avoid two objects with the same values generating different hashes, we utilize the replacer
+ * argument of JSON.stringify and sort the object by key as it's being serialized. This may or may
+ * not be the fastest way to do this; we should investigate this further.
+ *
+ * Objects and arrays are hashed recursively. When hashing an object that has a .getHash()
+ * function, we call that function and use its return value rather than hashing the object
+ * ourselves. This allows classes to define custom hashing.
+ *
+ * @param {Object} val Object to generate hash for
+ * @return {string} Hash of object
+ */
+oo.getHash = function ( val ) {
+ return JSON.stringify( val, oo.getHash.keySortReplacer );
+};
+
+/**
+ * Sort objects by key (helper function for OO.getHash).
+ *
+ * This is a callback passed into JSON.stringify.
+ *
+ * @method getHash_keySortReplacer
+ * @param {string} key Property name of value being replaced
+ * @param {Mixed} val Property value to replace
+ * @return {Mixed} Replacement value
+ */
+oo.getHash.keySortReplacer = function ( key, val ) {
+ var normalized, keys, i, len;
+ if ( val && typeof val.getHashObject === 'function' ) {
+ // This object has its own custom hash function, use it
+ val = val.getHashObject();
+ }
+ if ( !Array.isArray( val ) && Object( val ) === val ) {
+ // Only normalize objects when the key-order is ambiguous
+ // (e.g. any object not an array).
+ normalized = {};
+ keys = Object.keys( val ).sort();
+ i = 0;
+ len = keys.length;
+ for ( ; i < len; i += 1 ) {
+ normalized[ keys[ i ] ] = val[ keys[ i ] ];
+ }
+ return normalized;
+ } else {
+ // Primitive values and arrays get stable hashes
+ // by default. Lets those be stringified as-is.
+ return val;
+ }
+};
+
+/**
+ * Get the unique values of an array, removing duplicates
+ *
+ * @param {Array} arr Array
+ * @return {Array} Unique values in array
+ */
+oo.unique = function ( arr ) {
+ return arr.reduce( function ( result, current ) {
+ if ( result.indexOf( current ) === -1 ) {
+ result.push( current );
+ }
+ return result;
+ }, [] );
+};
+
+/**
+ * Compute the union (duplicate-free merge) of a set of arrays.
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * By building an object (with the values for keys) in parallel with
+ * the array, a new item's existence in the union can be computed faster.
+ *
+ * @param {...Array} arrays Arrays to union
+ * @return {Array} Union of the arrays
+ */
+oo.simpleArrayUnion = function () {
+ var i, ilen, arr, j, jlen,
+ obj = {},
+ result = [];
+
+ for ( i = 0, ilen = arguments.length; i < ilen; i++ ) {
+ arr = arguments[ i ];
+ for ( j = 0, jlen = arr.length; j < jlen; j++ ) {
+ if ( !obj[ arr[ j ] ] ) {
+ obj[ arr[ j ] ] = true;
+ result.push( arr[ j ] );
+ }
+ }
+ }
+
+ return result;
+};
+
+/**
+ * Combine arrays (intersection or difference).
+ *
+ * An intersection checks the item exists in 'b' while difference checks it doesn't.
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * By building an object (with the values for keys) of 'b' we can
+ * compute the result faster.
+ *
+ * @private
+ * @param {Array} a First array
+ * @param {Array} b Second array
+ * @param {boolean} includeB Whether to items in 'b'
+ * @return {Array} Combination (intersection or difference) of arrays
+ */
+function simpleArrayCombine( a, b, includeB ) {
+ var i, ilen, isInB,
+ bObj = {},
+ result = [];
+
+ for ( i = 0, ilen = b.length; i < ilen; i++ ) {
+ bObj[ b[ i ] ] = true;
+ }
+
+ for ( i = 0, ilen = a.length; i < ilen; i++ ) {
+ isInB = !!bObj[ a[ i ] ];
+ if ( isInB === includeB ) {
+ result.push( a[ i ] );
+ }
+ }
+
+ return result;
+}
+
+/**
+ * Compute the intersection of two arrays (items in both arrays).
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * @param {Array} a First array
+ * @param {Array} b Second array
+ * @return {Array} Intersection of arrays
+ */
+oo.simpleArrayIntersection = function ( a, b ) {
+ return simpleArrayCombine( a, b, true );
+};
+
+/**
+ * Compute the difference of two arrays (items in 'a' but not 'b').
+ *
+ * Arrays values must be convertable to object keys (strings).
+ *
+ * @param {Array} a First array
+ * @param {Array} b Second array
+ * @return {Array} Intersection of arrays
+ */
+oo.simpleArrayDifference = function ( a, b ) {
+ return simpleArrayCombine( a, b, false );
+};
+
+/* global $ */
+
+oo.isPlainObject = $.isPlainObject;
+
+/* global hasOwn */
+
+( function () {
+
+ /**
+ * @class OO.EventEmitter
+ *
+ * @constructor
+ */
+ oo.EventEmitter = function OoEventEmitter() {
+ // Properties
+
+ /**
+ * Storage of bound event handlers by event name.
+ *
+ * @property
+ */
+ this.bindings = {};
+ };
+
+ oo.initClass( oo.EventEmitter );
+
+ /* Private helper functions */
+
+ /**
+ * Validate a function or method call in a context
+ *
+ * For a method name, check that it names a function in the context object
+ *
+ * @private
+ * @param {Function|string} method Function or method name
+ * @param {Mixed} context The context of the call
+ * @throws {Error} A method name is given but there is no context
+ * @throws {Error} In the context object, no property exists with the given name
+ * @throws {Error} In the context object, the named property is not a function
+ */
+ function validateMethod( method, context ) {
+ // Validate method and context
+ if ( typeof method === 'string' ) {
+ // Validate method
+ if ( context === undefined || context === null ) {
+ throw new Error( 'Method name "' + method + '" has no context.' );
+ }
+ if ( typeof context[ method ] !== 'function' ) {
+ // Technically the property could be replaced by a function before
+ // call time. But this probably signals a typo.
+ throw new Error( 'Property "' + method + '" is not a function' );
+ }
+ } else if ( typeof method !== 'function' ) {
+ throw new Error( 'Invalid callback. Function or method name expected.' );
+ }
+ }
+
+ /**
+ * @private
+ * @param {OO.EventEmitter} ee
+ * @param {Function|string} method Function or method name
+ * @param {Object} binding
+ */
+ function addBinding( ee, event, binding ) {
+ var bindings;
+ // Auto-initialize bindings list
+ if ( hasOwn.call( ee.bindings, event ) ) {
+ bindings = ee.bindings[ event ];
+ } else {
+ bindings = ee.bindings[ event ] = [];
+ }
+ // Add binding
+ bindings.push( binding );
+ }
+
+ /* Methods */
+
+ /**
+ * Add a listener to events of a specific event.
+ *
+ * The listener can be a function or the string name of a method; if the latter, then the
+ * name lookup happens at the time the listener is called.
+ *
+ * @param {string} event Type of event to listen to
+ * @param {Function|string} method Function or method name to call when event occurs
+ * @param {Array} [args] Arguments to pass to listener, will be prepended to emitted arguments
+ * @param {Object} [context=null] Context object for function or method call
+ * @throws {Error} Listener argument is not a function or a valid method name
+ * @chainable
+ */
+ oo.EventEmitter.prototype.on = function ( event, method, args, context ) {
+ validateMethod( method, context );
+
+ // Ensure consistent object shape (optimisation)
+ addBinding( this, event, {
+ method: method,
+ args: args,
+ context: ( arguments.length < 4 ) ? null : context,
+ once: false
+ } );
+ return this;
+ };
+
+ /**
+ * Add a one-time listener to a specific event.
+ *
+ * @param {string} event Type of event to listen to
+ * @param {Function} listener Listener to call when event occurs
+ * @chainable
+ */
+ oo.EventEmitter.prototype.once = function ( event, listener ) {
+ validateMethod( listener );
+
+ // Ensure consistent object shape (optimisation)
+ addBinding( this, event, {
+ method: listener,
+ args: undefined,
+ context: null,
+ once: true
+ } );
+ return this;
+ };
+
+ /**
+ * Remove a specific listener from a specific event.
+ *
+ * @param {string} event Type of event to remove listener from
+ * @param {Function|string} [method] Listener to remove. Must be in the same form as was passed
+ * to "on". Omit to remove all listeners.
+ * @param {Object} [context=null] Context object function or method call
+ * @chainable
+ * @throws {Error} Listener argument is not a function or a valid method name
+ */
+ oo.EventEmitter.prototype.off = function ( event, method, context ) {
+ var i, bindings;
+
+ if ( arguments.length === 1 ) {
+ // Remove all bindings for event
+ delete this.bindings[ event ];
+ return this;
+ }
+
+ validateMethod( method, context );
+
+ if ( !hasOwn.call( this.bindings, event ) || !this.bindings[ event ].length ) {
+ // No matching bindings
+ return this;
+ }
+
+ // Default to null context
+ if ( arguments.length < 3 ) {
+ context = null;
+ }
+
+ // Remove matching handlers
+ bindings = this.bindings[ event ];
+ i = bindings.length;
+ while ( i-- ) {
+ if ( bindings[ i ].method === method && bindings[ i ].context === context ) {
+ bindings.splice( i, 1 );
+ }
+ }
+
+ // Cleanup if now empty
+ if ( bindings.length === 0 ) {
+ delete this.bindings[ event ];
+ }
+ return this;
+ };
+
+ /**
+ * Emit an event.
+ *
+ * @param {string} event Type of event
+ * @param {...Mixed} args First in a list of variadic arguments passed to event handler (optional)
+ * @return {boolean} Whether the event was handled by at least one listener
+ */
+ oo.EventEmitter.prototype.emit = function ( event ) {
+ var args = [],
+ i, len, binding, bindings, method;
+
+ if ( hasOwn.call( this.bindings, event ) ) {
+ // Slicing ensures that we don't get tripped up by event handlers that add/remove bindings
+ bindings = this.bindings[ event ].slice();
+ for ( i = 1, len = arguments.length; i < len; i++ ) {
+ args.push( arguments[ i ] );
+ }
+ for ( i = 0, len = bindings.length; i < len; i++ ) {
+ binding = bindings[ i ];
+ if ( typeof binding.method === 'string' ) {
+ // Lookup method by name (late binding)
+ method = binding.context[ binding.method ];
+ } else {
+ method = binding.method;
+ }
+ if ( binding.once ) {
+ // Must unbind before calling method to avoid
+ // any nested triggers.
+ this.off( event, method );
+ }
+ method.apply(
+ binding.context,
+ binding.args ? binding.args.concat( args ) : args
+ );
+ }
+ return true;
+ }
+ return false;
+ };
+
+ /**
+ * Connect event handlers to an object.
+ *
+ * @param {Object} context Object to call methods on when events occur
+ * @param {Object.<string,string>|Object.<string,Function>|Object.<string,Array>} methods List of
+ * event bindings keyed by event name containing either method names, functions or arrays containing
+ * method name or function followed by a list of arguments to be passed to callback before emitted
+ * arguments.
+ * @chainable
+ */
+ oo.EventEmitter.prototype.connect = function ( context, methods ) {
+ var method, args, event;
+
+ for ( event in methods ) {
+ method = methods[ event ];
+ // Allow providing additional args
+ if ( Array.isArray( method ) ) {
+ args = method.slice( 1 );
+ method = method[ 0 ];
+ } else {
+ args = [];
+ }
+ // Add binding
+ this.on( event, method, args, context );
+ }
+ return this;
+ };
+
+ /**
+ * Disconnect event handlers from an object.
+ *
+ * @param {Object} context Object to disconnect methods from
+ * @param {Object.<string,string>|Object.<string,Function>|Object.<string,Array>} [methods] List of
+ * event bindings keyed by event name. Values can be either method names, functions or arrays
+ * containing a method name.
+ * NOTE: To allow matching call sites with connect(), array values are allowed to contain the
+ * parameters as well, but only the method name is used to find bindings. Tt is discouraged to
+ * have multiple bindings for the same event to the same listener, but if used (and only the
+ * parameters vary), disconnecting one variation of (event name, event listener, parameters)
+ * will disconnect other variations as well.
+ * @chainable
+ */
+ oo.EventEmitter.prototype.disconnect = function ( context, methods ) {
+ var i, event, method, bindings;
+
+ if ( methods ) {
+ // Remove specific connections to the context
+ for ( event in methods ) {
+ method = methods[ event ];
+ if ( Array.isArray( method ) ) {
+ method = method[ 0 ];
+ }
+ this.off( event, method, context );
+ }
+ } else {
+ // Remove all connections to the context
+ for ( event in this.bindings ) {
+ bindings = this.bindings[ event ];
+ i = bindings.length;
+ while ( i-- ) {
+ // bindings[i] may have been removed by the previous step's
+ // this.off so check it still exists
+ if ( bindings[ i ] && bindings[ i ].context === context ) {
+ this.off( event, bindings[ i ].method, context );
+ }
+ }
+ }
+ }
+
+ return this;
+ };
+
+}() );
+
+( function () {
+
+ /**
+ * Contain and manage a list of OO.EventEmitter items.
+ *
+ * Aggregates and manages their events collectively.
+ *
+ * This mixin must be used in a class that also mixes in OO.EventEmitter.
+ *
+ * @abstract
+ * @class OO.EmitterList
+ * @constructor
+ */
+ oo.EmitterList = function OoEmitterList() {
+ this.items = [];
+ this.aggregateItemEvents = {};
+ };
+
+ /* Events */
+
+ /**
+ * Item has been added
+ *
+ * @event add
+ * @param {OO.EventEmitter} item Added item
+ * @param {number} index Index items were added at
+ */
+
+ /**
+ * Item has been moved to a new index
+ *
+ * @event move
+ * @param {OO.EventEmitter} item Moved item
+ * @param {number} index Index item was moved to
+ * @param {number} oldIndex The original index the item was in
+ */
+
+ /**
+ * Item has been removed
+ *
+ * @event remove
+ * @param {OO.EventEmitter} item Removed item
+ * @param {number} index Index the item was removed from
+ */
+
+ /**
+ * @event clear The list has been cleared of items
+ */
+
+ /* Methods */
+
+ /**
+ * Normalize requested index to fit into the bounds of the given array.
+ *
+ * @private
+ * @static
+ * @param {Array} arr Given array
+ * @param {number|undefined} index Requested index
+ * @return {number} Normalized index
+ */
+ function normalizeArrayIndex( arr, index ) {
+ return ( index === undefined || index < 0 || index >= arr.length ) ?
+ arr.length :
+ index;
+ }
+
+ /**
+ * Get all items.
+ *
+ * @return {OO.EventEmitter[]} Items in the list
+ */
+ oo.EmitterList.prototype.getItems = function () {
+ return this.items.slice( 0 );
+ };
+
+ /**
+ * Get the index of a specific item.
+ *
+ * @param {OO.EventEmitter} item Requested item
+ * @return {number} Index of the item
+ */
+ oo.EmitterList.prototype.getItemIndex = function ( item ) {
+ return this.items.indexOf( item );
+ };
+
+ /**
+ * Get number of items.
+ *
+ * @return {number} Number of items in the list
+ */
+ oo.EmitterList.prototype.getItemCount = function () {
+ return this.items.length;
+ };
+
+ /**
+ * Check if a list contains no items.
+ *
+ * @return {boolean} Group is empty
+ */
+ oo.EmitterList.prototype.isEmpty = function () {
+ return !this.items.length;
+ };
+
+ /**
+ * Aggregate the events emitted by the group.
+ *
+ * When events are aggregated, the group will listen to all contained items for the event,
+ * and then emit the event under a new name. The new event will contain an additional leading
+ * parameter containing the item that emitted the original event. Other arguments emitted from
+ * the original event are passed through.
+ *
+ * @param {Object.<string,string|null>} events An object keyed by the name of the event that should be
+ * aggregated (e.g., ‘click’) and the value of the new name to use (e.g., ‘groupClick’).
+ * A `null` value will remove aggregated events.
+
+ * @throws {Error} If aggregation already exists
+ */
+ oo.EmitterList.prototype.aggregate = function ( events ) {
+ var i, item, add, remove, itemEvent, groupEvent;
+
+ for ( itemEvent in events ) {
+ groupEvent = events[ itemEvent ];
+
+ // Remove existing aggregated event
+ if ( Object.prototype.hasOwnProperty.call( this.aggregateItemEvents, itemEvent ) ) {
+ // Don't allow duplicate aggregations
+ if ( groupEvent ) {
+ throw new Error( 'Duplicate item event aggregation for ' + itemEvent );
+ }
+ // Remove event aggregation from existing items
+ for ( i = 0; i < this.items.length; i++ ) {
+ item = this.items[ i ];
+ if ( item.connect && item.disconnect ) {
+ remove = {};
+ remove[ itemEvent ] = [ 'emit', this.aggregateItemEvents[ itemEvent ], item ];
+ item.disconnect( this, remove );
+ }
+ }
+ // Prevent future items from aggregating event
+ delete this.aggregateItemEvents[ itemEvent ];
+ }
+
+ // Add new aggregate event
+ if ( groupEvent ) {
+ // Make future items aggregate event
+ this.aggregateItemEvents[ itemEvent ] = groupEvent;
+ // Add event aggregation to existing items
+ for ( i = 0; i < this.items.length; i++ ) {
+ item = this.items[ i ];
+ if ( item.connect && item.disconnect ) {
+ add = {};
+ add[ itemEvent ] = [ 'emit', groupEvent, item ];
+ item.connect( this, add );
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * Add items to the list.
+ *
+ * @param {OO.EventEmitter|OO.EventEmitter[]} items Item to add or
+ * an array of items to add
+ * @param {number} [index] Index to add items at. If no index is
+ * given, or if the index that is given is invalid, the item
+ * will be added at the end of the list.
+ * @chainable
+ * @fires add
+ * @fires move
+ */
+ oo.EmitterList.prototype.addItems = function ( items, index ) {
+ var i, oldIndex;
+
+ if ( !Array.isArray( items ) ) {
+ items = [ items ];
+ }
+
+ if ( items.length === 0 ) {
+ return this;
+ }
+
+ index = normalizeArrayIndex( this.items, index );
+ for ( i = 0; i < items.length; i++ ) {
+ oldIndex = this.items.indexOf( items[ i ] );
+ if ( oldIndex !== -1 ) {
+ // Move item to new index
+ index = this.moveItem( items[ i ], index );
+ this.emit( 'move', items[ i ], index, oldIndex );
+ } else {
+ // insert item at index
+ index = this.insertItem( items[ i ], index );
+ this.emit( 'add', items[ i ], index );
+ }
+ index++;
+ }
+
+ return this;
+ };
+
+ /**
+ * Move an item from its current position to a new index.
+ *
+ * The item is expected to exist in the list. If it doesn't,
+ * the method will throw an exception.
+ *
+ * @private
+ * @param {OO.EventEmitter} item Items to add
+ * @param {number} newIndex Index to move the item to
+ * @return {number} The index the item was moved to
+ * @throws {Error} If item is not in the list
+ */
+ oo.EmitterList.prototype.moveItem = function ( item, newIndex ) {
+ var existingIndex = this.items.indexOf( item );
+
+ if ( existingIndex === -1 ) {
+ throw new Error( 'Item cannot be moved, because it is not in the list.' );
+ }
+
+ newIndex = normalizeArrayIndex( this.items, newIndex );
+
+ // Remove the item from the current index
+ this.items.splice( existingIndex, 1 );
+
+ // If necessary, adjust new index after removal
+ if ( existingIndex < newIndex ) {
+ newIndex--;
+ }
+
+ // Move the item to the new index
+ this.items.splice( newIndex, 0, item );
+
+ return newIndex;
+ };
+
+ /**
+ * Utility method to insert an item into the list, and
+ * connect it to aggregate events.
+ *
+ * Don't call this directly unless you know what you're doing.
+ * Use #addItems instead.
+ *
+ * This method can be extended in child classes to produce
+ * different behavior when an item is inserted. For example,
+ * inserted items may also be attached to the DOM or may
+ * interact with some other nodes in certain ways. Extending
+ * this method is allowed, but if overriden, the aggregation
+ * of events must be preserved, or behavior of emitted events
+ * will be broken.
+ *
+ * If you are extending this method, please make sure the
+ * parent method is called.
+ *
+ * @protected
+ * @param {OO.EventEmitter} item Items to add
+ * @param {number} index Index to add items at
+ * @return {number} The index the item was added at
+ */
+ oo.EmitterList.prototype.insertItem = function ( item, index ) {
+ var events, event;
+
+ // Add the item to event aggregation
+ if ( item.connect && item.disconnect ) {
+ events = {};
+ for ( event in this.aggregateItemEvents ) {
+ events[ event ] = [ 'emit', this.aggregateItemEvents[ event ], item ];
+ }
+ item.connect( this, events );
+ }
+
+ index = normalizeArrayIndex( this.items, index );
+
+ // Insert into items array
+ this.items.splice( index, 0, item );
+ return index;
+ };
+
+ /**
+ * Remove items.
+ *
+ * @param {OO.EventEmitter[]} items Items to remove
+ * @chainable
+ * @fires remove
+ */
+ oo.EmitterList.prototype.removeItems = function ( items ) {
+ var i, item, index;
+
+ if ( !Array.isArray( items ) ) {
+ items = [ items ];
+ }
+
+ if ( items.length === 0 ) {
+ return this;
+ }
+
+ // Remove specific items
+ for ( i = 0; i < items.length; i++ ) {
+ item = items[ i ];
+ index = this.items.indexOf( item );
+ if ( index !== -1 ) {
+ if ( item.connect && item.disconnect ) {
+ // Disconnect all listeners from the item
+ item.disconnect( this );
+ }
+ this.items.splice( index, 1 );
+ this.emit( 'remove', item, index );
+ }
+ }
+
+ return this;
+ };
+
+ /**
+ * Clear all items
+ *
+ * @chainable
+ * @fires clear
+ */
+ oo.EmitterList.prototype.clearItems = function () {
+ var i, item,
+ cleared = this.items.splice( 0, this.items.length );
+
+ // Disconnect all items
+ for ( i = 0; i < cleared.length; i++ ) {
+ item = cleared[ i ];
+ if ( item.connect && item.disconnect ) {
+ item.disconnect( this );
+ }
+ }
+
+ this.emit( 'clear' );
+
+ return this;
+ };
+
+}() );
+
+/**
+ * Manage a sorted list of OO.EmitterList objects.
+ *
+ * The sort order is based on a callback that compares two items. The return value of
+ * callback( a, b ) must be less than zero if a < b, greater than zero if a > b, and zero
+ * if a is equal to b. The callback should only return zero if the two objects are
+ * considered equal.
+ *
+ * When an item changes in a way that could affect their sorting behavior, it must
+ * emit the itemSortChange event. This will cause it to be re-sorted automatically.
+ *
+ * This mixin must be used in a class that also mixes in OO.EventEmitter.
+ *
+ * @abstract
+ * @class OO.SortedEmitterList
+ * @mixins OO.EmitterList
+ * @constructor
+ * @param {Function} sortingCallback Callback that compares two items.
+ */
+oo.SortedEmitterList = function OoSortedEmitterList( sortingCallback ) {
+ // Mixin constructors
+ oo.EmitterList.call( this );
+
+ this.sortingCallback = sortingCallback;
+
+ // Listen to sortChange event and make sure
+ // we re-sort the changed item when that happens
+ this.aggregate( {
+ sortChange: 'itemSortChange'
+ } );
+
+ this.connect( this, {
+ itemSortChange: 'onItemSortChange'
+ } );
+};
+
+oo.mixinClass( oo.SortedEmitterList, oo.EmitterList );
+
+/* Events */
+
+/**
+ * An item has changed properties that affect its sort positioning
+ * inside the list.
+ *
+ * @private
+ * @event itemSortChange
+ */
+
+/* Methods */
+
+/**
+ * Handle a case where an item changed a property that relates
+ * to its sorted order
+ *
+ * @param {OO.EventEmitter} item Item in the list
+ */
+oo.SortedEmitterList.prototype.onItemSortChange = function ( item ) {
+ // Remove the item
+ this.removeItems( item );
+ // Re-add the item so it is in the correct place
+ this.addItems( item );
+};
+
+/**
+ * Change the sorting callback for this sorted list.
+ *
+ * The callback receives two items. The return value of callback(a, b) must be less than zero
+ * if a < b, greater than zero if a > b, and zero if a is equal to b.
+ *
+ * @param {Function} sortingCallback Sorting callback
+ */
+oo.SortedEmitterList.prototype.setSortingCallback = function ( sortingCallback ) {
+ var items = this.getItems();
+
+ this.sortingCallback = sortingCallback;
+
+ // Empty the list
+ this.clearItems();
+ // Re-add the items in the new order
+ this.addItems( items );
+};
+
+/**
+ * Add items to the sorted list.
+ *
+ * @chainable
+ * @param {OO.EventEmitter|OO.EventEmitter[]} items Item to add or
+ * an array of items to add
+ */
+oo.SortedEmitterList.prototype.addItems = function ( items ) {
+ var index, i, insertionIndex;
+
+ if ( !Array.isArray( items ) ) {
+ items = [ items ];
+ }
+
+ if ( items.length === 0 ) {
+ return this;
+ }
+
+ for ( i = 0; i < items.length; i++ ) {
+ // Find insertion index
+ insertionIndex = this.findInsertionIndex( items[ i ] );
+
+ // Check if the item exists using the sorting callback
+ // and remove it first if it exists
+ if (
+ // First make sure the insertion index is not at the end
+ // of the list (which means it does not point to any actual
+ // items)
+ insertionIndex <= this.items.length &&
+ // Make sure there actually is an item in this index
+ this.items[ insertionIndex ] &&
+ // The callback returns 0 if the items are equal
+ this.sortingCallback( this.items[ insertionIndex ], items[ i ] ) === 0
+ ) {
+ // Remove the existing item
+ this.removeItems( this.items[ insertionIndex ] );
+ }
+
+ // Insert item at the insertion index
+ index = this.insertItem( items[ i ], insertionIndex );
+ this.emit( 'add', items[ i ], index );
+ }
+
+ return this;
+};
+
+/**
+ * Find the index a given item should be inserted at. If the item is already
+ * in the list, this will return the index where the item currently is.
+ *
+ * @param {OO.EventEmitter} item Items to insert
+ * @return {number} The index the item should be inserted at
+ */
+oo.SortedEmitterList.prototype.findInsertionIndex = function ( item ) {
+ var list = this;
+
+ return oo.binarySearch(
+ this.items,
+ // Fake a this.sortingCallback.bind( null, item ) call here
+ // otherwise this doesn't pass tests in phantomJS
+ function ( otherItem ) {
+ return list.sortingCallback( item, otherItem );
+ },
+ true
+ );
+
+};
+
+/* global hasOwn */
+
+/**
+ * @class OO.Registry
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ */
+oo.Registry = function OoRegistry() {
+ // Mixin constructors
+ oo.EventEmitter.call( this );
+
+ // Properties
+ this.registry = {};
+};
+
+/* Inheritance */
+
+oo.mixinClass( oo.Registry, oo.EventEmitter );
+
+/* Events */
+
+/**
+ * @event register
+ * @param {string} name
+ * @param {Mixed} data
+ */
+
+/**
+ * @event unregister
+ * @param {string} name
+ * @param {Mixed} data Data removed from registry
+ */
+
+/* Methods */
+
+/**
+ * Associate one or more symbolic names with some data.
+ *
+ * Any existing entry with the same name will be overridden.
+ *
+ * @param {string|string[]} name Symbolic name or list of symbolic names
+ * @param {Mixed} data Data to associate with symbolic name
+ * @fires register
+ * @throws {Error} Name argument must be a string or array
+ */
+oo.Registry.prototype.register = function ( name, data ) {
+ var i, len;
+ if ( typeof name === 'string' ) {
+ this.registry[ name ] = data;
+ this.emit( 'register', name, data );
+ } else if ( Array.isArray( name ) ) {
+ for ( i = 0, len = name.length; i < len; i++ ) {
+ this.register( name[ i ], data );
+ }
+ } else {
+ throw new Error( 'Name must be a string or array, cannot be a ' + typeof name );
+ }
+};
+
+/**
+ * Remove one or more symbolic names from the registry
+ *
+ * @param {string|string[]} name Symbolic name or list of symbolic names
+ * @fires unregister
+ * @throws {Error} Name argument must be a string or array
+ */
+oo.Registry.prototype.unregister = function ( name ) {
+ var i, len, data;
+ if ( typeof name === 'string' ) {
+ data = this.lookup( name );
+ if ( data !== undefined ) {
+ delete this.registry[ name ];
+ this.emit( 'unregister', name, data );
+ }
+ } else if ( Array.isArray( name ) ) {
+ for ( i = 0, len = name.length; i < len; i++ ) {
+ this.unregister( name[ i ] );
+ }
+ } else {
+ throw new Error( 'Name must be a string or array, cannot be a ' + typeof name );
+ }
+};
+
+/**
+ * Get data for a given symbolic name.
+ *
+ * @param {string} name Symbolic name
+ * @return {Mixed|undefined} Data associated with symbolic name
+ */
+oo.Registry.prototype.lookup = function ( name ) {
+ if ( hasOwn.call( this.registry, name ) ) {
+ return this.registry[ name ];
+ }
+};
+
+/**
+ * @class OO.Factory
+ * @extends OO.Registry
+ *
+ * @constructor
+ */
+oo.Factory = function OoFactory() {
+ // Parent constructor
+ oo.Factory.super.call( this );
+};
+
+/* Inheritance */
+
+oo.inheritClass( oo.Factory, oo.Registry );
+
+/* Methods */
+
+/**
+ * Register a constructor with the factory.
+ *
+ * Classes must have a static `name` property to be registered.
+ *
+ * function MyClass() {};
+ * OO.initClass( MyClass );
+ * // Adds a static property to the class defining a symbolic name
+ * MyClass.static.name = 'mine';
+ * // Registers class with factory, available via symbolic name 'mine'
+ * factory.register( MyClass );
+ *
+ * @param {Function} constructor Constructor to use when creating object
+ * @throws {Error} Name must be a string and must not be empty
+ * @throws {Error} Constructor must be a function
+ */
+oo.Factory.prototype.register = function ( constructor ) {
+ var name;
+
+ if ( typeof constructor !== 'function' ) {
+ throw new Error( 'constructor must be a function, cannot be a ' + typeof constructor );
+ }
+ name = constructor.static && constructor.static.name;
+ if ( typeof name !== 'string' || name === '' ) {
+ throw new Error( 'Name must be a string and must not be empty' );
+ }
+
+ // Parent method
+ oo.Factory.super.prototype.register.call( this, name, constructor );
+};
+
+/**
+ * Unregister a constructor from the factory.
+ *
+ * @param {Function} constructor Constructor to unregister
+ * @throws {Error} Name must be a string and must not be empty
+ * @throws {Error} Constructor must be a function
+ */
+oo.Factory.prototype.unregister = function ( constructor ) {
+ var name;
+
+ if ( typeof constructor !== 'function' ) {
+ throw new Error( 'constructor must be a function, cannot be a ' + typeof constructor );
+ }
+ name = constructor.static && constructor.static.name;
+ if ( typeof name !== 'string' || name === '' ) {
+ throw new Error( 'Name must be a string and must not be empty' );
+ }
+
+ // Parent method
+ oo.Factory.super.prototype.unregister.call( this, name );
+};
+
+/**
+ * Create an object based on a name.
+ *
+ * Name is used to look up the constructor to use, while all additional arguments are passed to the
+ * constructor directly, so leaving one out will pass an undefined to the constructor.
+ *
+ * @param {string} name Object name
+ * @param {...Mixed} [args] Arguments to pass to the constructor
+ * @return {Object} The new object
+ * @throws {Error} Unknown object name
+ */
+oo.Factory.prototype.create = function ( name ) {
+ var obj, i,
+ args = [],
+ constructor = this.lookup( name );
+
+ if ( !constructor ) {
+ throw new Error( 'No class registered by that name: ' + name );
+ }
+
+ // Convert arguments to array and shift the first argument (name) off
+ for ( i = 1; i < arguments.length; i++ ) {
+ args.push( arguments[ i ] );
+ }
+
+ // We can't use the "new" operator with .apply directly because apply needs a
+ // context. So instead just do what "new" does: create an object that inherits from
+ // the constructor's prototype (which also makes it an "instanceof" the constructor),
+ // then invoke the constructor with the object as context, and return it (ignoring
+ // the constructor's return value).
+ obj = Object.create( constructor.prototype );
+ constructor.apply( obj, args );
+ return obj;
+};
+
+/* eslint-env node */
+
+/* istanbul ignore next */
+if ( typeof module !== 'undefined' && module.exports ) {
+ module.exports = oo;
+} else {
+ global.OO = oo;
+}
+
+}( this ) );
diff --git a/www/wiki/resources/lib/phpjs-sha1/LICENSE.txt b/www/wiki/resources/lib/phpjs-sha1/LICENSE.txt
new file mode 100644
index 00000000..04caf536
--- /dev/null
+++ b/www/wiki/resources/lib/phpjs-sha1/LICENSE.txt
@@ -0,0 +1,20 @@
+Copyright (c) 2013 Kevin van Zonneveld (http://kvz.io)
+and Contributors (http://phpjs.org/authors)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/www/wiki/resources/lib/phpjs-sha1/sha1.js b/www/wiki/resources/lib/phpjs-sha1/sha1.js
new file mode 100644
index 00000000..93c533d7
--- /dev/null
+++ b/www/wiki/resources/lib/phpjs-sha1/sha1.js
@@ -0,0 +1,147 @@
+function sha1(str) {
+ // discuss at: http://phpjs.org/functions/sha1/
+ // original by: Webtoolkit.info (http://www.webtoolkit.info/)
+ // improved by: Michael White (http://getsprink.com)
+ // improved by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
+ // input by: Brett Zamir (http://brett-zamir.me)
+ // example 1: sha1('Kevin van Zonneveld');
+ // returns 1: '54916d2e62f65b3afa6e192e6a601cdbe5cb5897'
+
+ var rotate_left = function (n, s) {
+ var t4 = (n << s) | (n >>> (32 - s));
+ return t4;
+ };
+
+ /*var lsb_hex = function (val) {
+ // Not in use; needed?
+ var str="";
+ var i;
+ var vh;
+ var vl;
+
+ for ( i=0; i<=6; i+=2 ) {
+ vh = (val>>>(i*4+4))&0x0f;
+ vl = (val>>>(i*4))&0x0f;
+ str += vh.toString(16) + vl.toString(16);
+ }
+ return str;
+ };*/
+
+ var cvt_hex = function (val) {
+ var str = '';
+ var i;
+ var v;
+
+ for (i = 7; i >= 0; i--) {
+ v = (val >>> (i * 4)) & 0x0f;
+ str += v.toString(16);
+ }
+ return str;
+ };
+
+ var blockstart;
+ var i, j;
+ var W = new Array(80);
+ var H0 = 0x67452301;
+ var H1 = 0xEFCDAB89;
+ var H2 = 0x98BADCFE;
+ var H3 = 0x10325476;
+ var H4 = 0xC3D2E1F0;
+ var A, B, C, D, E;
+ var temp;
+
+ // utf8_encode
+ str = unescape(encodeURIComponent(str));
+ var str_len = str.length;
+
+ var word_array = [];
+ for (i = 0; i < str_len - 3; i += 4) {
+ j = str.charCodeAt(i) << 24 | str.charCodeAt(i + 1) << 16 | str.charCodeAt(i + 2) << 8 | str.charCodeAt(i + 3);
+ word_array.push(j);
+ }
+
+ switch (str_len % 4) {
+ case 0:
+ i = 0x080000000;
+ break;
+ case 1:
+ i = str.charCodeAt(str_len - 1) << 24 | 0x0800000;
+ break;
+ case 2:
+ i = str.charCodeAt(str_len - 2) << 24 | str.charCodeAt(str_len - 1) << 16 | 0x08000;
+ break;
+ case 3:
+ i = str.charCodeAt(str_len - 3) << 24 | str.charCodeAt(str_len - 2) << 16 | str.charCodeAt(str_len - 1) <<
+ 8 | 0x80;
+ break;
+ }
+
+ word_array.push(i);
+
+ while ((word_array.length % 16) != 14) {
+ word_array.push(0);
+ }
+
+ word_array.push(str_len >>> 29);
+ word_array.push((str_len << 3) & 0x0ffffffff);
+
+ for (blockstart = 0; blockstart < word_array.length; blockstart += 16) {
+ for (i = 0; i < 16; i++) {
+ W[i] = word_array[blockstart + i];
+ }
+ for (i = 16; i <= 79; i++) {
+ W[i] = rotate_left(W[i - 3] ^ W[i - 8] ^ W[i - 14] ^ W[i - 16], 1);
+ }
+
+ A = H0;
+ B = H1;
+ C = H2;
+ D = H3;
+ E = H4;
+
+ for (i = 0; i <= 19; i++) {
+ temp = (rotate_left(A, 5) + ((B & C) | (~B & D)) + E + W[i] + 0x5A827999) & 0x0ffffffff;
+ E = D;
+ D = C;
+ C = rotate_left(B, 30);
+ B = A;
+ A = temp;
+ }
+
+ for (i = 20; i <= 39; i++) {
+ temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0x6ED9EBA1) & 0x0ffffffff;
+ E = D;
+ D = C;
+ C = rotate_left(B, 30);
+ B = A;
+ A = temp;
+ }
+
+ for (i = 40; i <= 59; i++) {
+ temp = (rotate_left(A, 5) + ((B & C) | (B & D) | (C & D)) + E + W[i] + 0x8F1BBCDC) & 0x0ffffffff;
+ E = D;
+ D = C;
+ C = rotate_left(B, 30);
+ B = A;
+ A = temp;
+ }
+
+ for (i = 60; i <= 79; i++) {
+ temp = (rotate_left(A, 5) + (B ^ C ^ D) + E + W[i] + 0xCA62C1D6) & 0x0ffffffff;
+ E = D;
+ D = C;
+ C = rotate_left(B, 30);
+ B = A;
+ A = temp;
+ }
+
+ H0 = (H0 + A) & 0x0ffffffff;
+ H1 = (H1 + B) & 0x0ffffffff;
+ H2 = (H2 + C) & 0x0ffffffff;
+ H3 = (H3 + D) & 0x0ffffffff;
+ H4 = (H4 + E) & 0x0ffffffff;
+ }
+
+ temp = cvt_hex(H0) + cvt_hex(H1) + cvt_hex(H2) + cvt_hex(H3) + cvt_hex(H4);
+ return temp.toLowerCase();
+}
diff --git a/www/wiki/resources/lib/qunitjs/qunit.css b/www/wiki/resources/lib/qunitjs/qunit.css
new file mode 100644
index 00000000..47492221
--- /dev/null
+++ b/www/wiki/resources/lib/qunitjs/qunit.css
@@ -0,0 +1,436 @@
+/*!
+ * QUnit 2.4.0
+ * https://qunitjs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2017-07-08T15:20Z
+ */
+
+/** Font Family and Sizes */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult {
+ font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
+}
+
+#qunit-testrunner-toolbar, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
+#qunit-tests { font-size: smaller; }
+
+
+/** Resets */
+
+#qunit-tests, #qunit-header, #qunit-banner, #qunit-filteredTest, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
+ margin: 0;
+ padding: 0;
+}
+
+
+/** Header (excluding toolbar) */
+
+#qunit-header {
+ padding: 0.5em 0 0.5em 1em;
+
+ color: #8699A4;
+ background-color: #0D3349;
+
+ font-size: 1.5em;
+ line-height: 1em;
+ font-weight: 400;
+
+ border-radius: 5px 5px 0 0;
+}
+
+#qunit-header a {
+ text-decoration: none;
+ color: #C2CCD1;
+}
+
+#qunit-header a:hover,
+#qunit-header a:focus {
+ color: #FFF;
+}
+
+#qunit-banner {
+ height: 5px;
+}
+
+#qunit-filteredTest {
+ padding: 0.5em 1em 0.5em 1em;
+ color: #366097;
+ background-color: #F4FF77;
+}
+
+#qunit-userAgent {
+ padding: 0.5em 1em 0.5em 1em;
+ color: #FFF;
+ background-color: #2B81AF;
+ text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
+}
+
+
+/** Toolbar */
+
+#qunit-testrunner-toolbar {
+ padding: 0.5em 1em 0.5em 1em;
+ color: #5E740B;
+ background-color: #EEE;
+}
+
+#qunit-testrunner-toolbar .clearfix {
+ height: 0;
+ clear: both;
+}
+
+#qunit-testrunner-toolbar label {
+ display: inline-block;
+}
+
+#qunit-testrunner-toolbar input[type=checkbox],
+#qunit-testrunner-toolbar input[type=radio] {
+ margin: 3px;
+ vertical-align: -2px;
+}
+
+#qunit-testrunner-toolbar input[type=text] {
+ box-sizing: border-box;
+ height: 1.6em;
+}
+
+.qunit-url-config,
+.qunit-filter,
+#qunit-modulefilter {
+ display: inline-block;
+ line-height: 2.1em;
+}
+
+.qunit-filter,
+#qunit-modulefilter {
+ float: right;
+ position: relative;
+ margin-left: 1em;
+}
+
+.qunit-url-config label {
+ margin-right: 0.5em;
+}
+
+#qunit-modulefilter-search {
+ box-sizing: border-box;
+ width: 400px;
+}
+
+#qunit-modulefilter-search-container:after {
+ position: absolute;
+ right: 0.3em;
+ content: "\25bc";
+ color: black;
+}
+
+#qunit-modulefilter-dropdown {
+ /* align with #qunit-modulefilter-search */
+ box-sizing: border-box;
+ width: 400px;
+ position: absolute;
+ right: 0;
+ top: 50%;
+ margin-top: 0.8em;
+
+ border: 1px solid #D3D3D3;
+ border-top: none;
+ border-radius: 0 0 .25em .25em;
+ color: #000;
+ background-color: #F5F5F5;
+ z-index: 99;
+}
+
+#qunit-modulefilter-dropdown a {
+ color: inherit;
+ text-decoration: none;
+}
+
+#qunit-modulefilter-dropdown .clickable.checked {
+ font-weight: bold;
+ color: #000;
+ background-color: #D2E0E6;
+}
+
+#qunit-modulefilter-dropdown .clickable:hover {
+ color: #FFF;
+ background-color: #0D3349;
+}
+
+#qunit-modulefilter-actions {
+ display: block;
+ overflow: auto;
+
+ /* align with #qunit-modulefilter-dropdown-list */
+ font: smaller/1.5em sans-serif;
+}
+
+#qunit-modulefilter-dropdown #qunit-modulefilter-actions > * {
+ box-sizing: border-box;
+ max-height: 2.8em;
+ display: block;
+ padding: 0.4em;
+}
+
+#qunit-modulefilter-dropdown #qunit-modulefilter-actions > button {
+ float: right;
+ font: inherit;
+}
+
+#qunit-modulefilter-dropdown #qunit-modulefilter-actions > :last-child {
+ /* insert padding to align with checkbox margins */
+ padding-left: 3px;
+}
+
+#qunit-modulefilter-dropdown-list {
+ max-height: 200px;
+ overflow-y: auto;
+ margin: 0;
+ border-top: 2px groove threedhighlight;
+ padding: 0.4em 0 0;
+ font: smaller/1.5em sans-serif;
+}
+
+#qunit-modulefilter-dropdown-list li {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+#qunit-modulefilter-dropdown-list .clickable {
+ display: block;
+ padding-left: 0.15em;
+}
+
+
+/** Tests: Pass/Fail */
+
+#qunit-tests {
+ list-style-position: inside;
+}
+
+#qunit-tests li {
+ padding: 0.4em 1em 0.4em 1em;
+ border-bottom: 1px solid #FFF;
+ list-style-position: inside;
+}
+
+#qunit-tests > li {
+ display: none;
+}
+
+#qunit-tests li.running,
+#qunit-tests li.pass,
+#qunit-tests li.fail,
+#qunit-tests li.skipped,
+#qunit-tests li.aborted {
+ display: list-item;
+}
+
+#qunit-tests.hidepass {
+ position: relative;
+}
+
+#qunit-tests.hidepass li.running,
+#qunit-tests.hidepass li.pass:not(.todo) {
+ visibility: hidden;
+ position: absolute;
+ width: 0;
+ height: 0;
+ padding: 0;
+ border: 0;
+ margin: 0;
+}
+
+#qunit-tests li strong {
+ cursor: pointer;
+}
+
+#qunit-tests li.skipped strong {
+ cursor: default;
+}
+
+#qunit-tests li a {
+ padding: 0.5em;
+ color: #C2CCD1;
+ text-decoration: none;
+}
+
+#qunit-tests li p a {
+ padding: 0.25em;
+ color: #6B6464;
+}
+#qunit-tests li a:hover,
+#qunit-tests li a:focus {
+ color: #000;
+}
+
+#qunit-tests li .runtime {
+ float: right;
+ font-size: smaller;
+}
+
+.qunit-assert-list {
+ margin-top: 0.5em;
+ padding: 0.5em;
+
+ background-color: #FFF;
+
+ border-radius: 5px;
+}
+
+.qunit-source {
+ margin: 0.6em 0 0.3em;
+}
+
+.qunit-collapsed {
+ display: none;
+}
+
+#qunit-tests table {
+ border-collapse: collapse;
+ margin-top: 0.2em;
+}
+
+#qunit-tests th {
+ text-align: right;
+ vertical-align: top;
+ padding: 0 0.5em 0 0;
+}
+
+#qunit-tests td {
+ vertical-align: top;
+}
+
+#qunit-tests pre {
+ margin: 0;
+ white-space: pre-wrap;
+ word-wrap: break-word;
+}
+
+#qunit-tests del {
+ color: #374E0C;
+ background-color: #E0F2BE;
+ text-decoration: none;
+}
+
+#qunit-tests ins {
+ color: #500;
+ background-color: #FFCACA;
+ text-decoration: none;
+}
+
+/*** Test Counts */
+
+#qunit-tests b.counts { color: #000; }
+#qunit-tests b.passed { color: #5E740B; }
+#qunit-tests b.failed { color: #710909; }
+
+#qunit-tests li li {
+ padding: 5px;
+ background-color: #FFF;
+ border-bottom: none;
+ list-style-position: inside;
+}
+
+/*** Passing Styles */
+
+#qunit-tests li li.pass {
+ color: #3C510C;
+ background-color: #FFF;
+ border-left: 10px solid #C6E746;
+}
+
+#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
+#qunit-tests .pass .test-name { color: #366097; }
+
+#qunit-tests .pass .test-actual,
+#qunit-tests .pass .test-expected { color: #999; }
+
+#qunit-banner.qunit-pass { background-color: #C6E746; }
+
+/*** Failing Styles */
+
+#qunit-tests li li.fail {
+ color: #710909;
+ background-color: #FFF;
+ border-left: 10px solid #EE5757;
+ white-space: pre;
+}
+
+#qunit-tests > li:last-child {
+ border-radius: 0 0 5px 5px;
+}
+
+#qunit-tests .fail { color: #000; background-color: #EE5757; }
+#qunit-tests .fail .test-name,
+#qunit-tests .fail .module-name { color: #000; }
+
+#qunit-tests .fail .test-actual { color: #EE5757; }
+#qunit-tests .fail .test-expected { color: #008000; }
+
+#qunit-banner.qunit-fail { background-color: #EE5757; }
+
+
+/*** Aborted tests */
+#qunit-tests .aborted { color: #000; background-color: orange; }
+/*** Skipped tests */
+
+#qunit-tests .skipped {
+ background-color: #EBECE9;
+}
+
+#qunit-tests .qunit-todo-label,
+#qunit-tests .qunit-skipped-label {
+ background-color: #F4FF77;
+ display: inline-block;
+ font-style: normal;
+ color: #366097;
+ line-height: 1.8em;
+ padding: 0 0.5em;
+ margin: -0.4em 0.4em -0.4em 0;
+}
+
+#qunit-tests .qunit-todo-label {
+ background-color: #EEE;
+}
+
+/** Result */
+
+#qunit-testresult {
+ color: #2B81AF;
+ background-color: #D2E0E6;
+
+ border-bottom: 1px solid #FFF;
+}
+#qunit-testresult .clearfix {
+ height: 0;
+ clear: both;
+}
+#qunit-testresult .module-name {
+ font-weight: 700;
+}
+#qunit-testresult-display {
+ padding: 0.5em 1em 0.5em 1em;
+ width: 85%;
+ float:left;
+}
+#qunit-testresult-controls {
+ padding: 0.5em 1em 0.5em 1em;
+ width: 10%;
+ float:left;
+}
+
+/** Fixture */
+
+#qunit-fixture {
+ position: absolute;
+ top: -10000px;
+ left: -10000px;
+ width: 1000px;
+ height: 1000px;
+}
diff --git a/www/wiki/resources/lib/qunitjs/qunit.js b/www/wiki/resources/lib/qunitjs/qunit.js
new file mode 100644
index 00000000..bb8f31d6
--- /dev/null
+++ b/www/wiki/resources/lib/qunitjs/qunit.js
@@ -0,0 +1,5048 @@
+/*!
+ * QUnit 2.4.0
+ * https://qunitjs.com/
+ *
+ * Copyright jQuery Foundation and other contributors
+ * Released under the MIT license
+ * https://jquery.org/license
+ *
+ * Date: 2017-07-08T15:20Z
+ */
+(function (global$1) {
+ 'use strict';
+
+ global$1 = global$1 && 'default' in global$1 ? global$1['default'] : global$1;
+
+ var window = global$1.window;
+ var self$1 = global$1.self;
+ var console = global$1.console;
+ var setTimeout = global$1.setTimeout;
+ var clearTimeout = global$1.clearTimeout;
+
+ var document = window && window.document;
+ var navigator = window && window.navigator;
+
+ var localSessionStorage = function () {
+ var x = "qunit-test-string";
+ try {
+ global$1.sessionStorage.setItem(x, x);
+ global$1.sessionStorage.removeItem(x);
+ return global$1.sessionStorage;
+ } catch (e) {
+ return undefined;
+ }
+ }();
+
+ var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {
+ return typeof obj;
+ } : function (obj) {
+ return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj;
+ };
+
+
+
+
+
+
+
+
+
+
+
+ var classCallCheck = function (instance, Constructor) {
+ if (!(instance instanceof Constructor)) {
+ throw new TypeError("Cannot call a class as a function");
+ }
+ };
+
+ var createClass = function () {
+ function defineProperties(target, props) {
+ for (var i = 0; i < props.length; i++) {
+ var descriptor = props[i];
+ descriptor.enumerable = descriptor.enumerable || false;
+ descriptor.configurable = true;
+ if ("value" in descriptor) descriptor.writable = true;
+ Object.defineProperty(target, descriptor.key, descriptor);
+ }
+ }
+
+ return function (Constructor, protoProps, staticProps) {
+ if (protoProps) defineProperties(Constructor.prototype, protoProps);
+ if (staticProps) defineProperties(Constructor, staticProps);
+ return Constructor;
+ };
+ }();
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ var toConsumableArray = function (arr) {
+ if (Array.isArray(arr)) {
+ for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i];
+
+ return arr2;
+ } else {
+ return Array.from(arr);
+ }
+ };
+
+ var toString = Object.prototype.toString;
+ var hasOwn = Object.prototype.hasOwnProperty;
+ var now = Date.now || function () {
+ return new Date().getTime();
+ };
+
+ var defined = {
+ document: window && window.document !== undefined,
+ setTimeout: setTimeout !== undefined
+ };
+
+ // Returns a new Array with the elements that are in a but not in b
+ function diff(a, b) {
+ var i,
+ j,
+ result = a.slice();
+
+ for (i = 0; i < result.length; i++) {
+ for (j = 0; j < b.length; j++) {
+ if (result[i] === b[j]) {
+ result.splice(i, 1);
+ i--;
+ break;
+ }
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Determines whether an element exists in a given array or not.
+ *
+ * @method inArray
+ * @param {Any} elem
+ * @param {Array} array
+ * @return {Boolean}
+ */
+ function inArray(elem, array) {
+ return array.indexOf(elem) !== -1;
+ }
+
+ /**
+ * Makes a clone of an object using only Array or Object as base,
+ * and copies over the own enumerable properties.
+ *
+ * @param {Object} obj
+ * @return {Object} New object with only the own properties (recursively).
+ */
+ function objectValues(obj) {
+ var key,
+ val,
+ vals = is("array", obj) ? [] : {};
+ for (key in obj) {
+ if (hasOwn.call(obj, key)) {
+ val = obj[key];
+ vals[key] = val === Object(val) ? objectValues(val) : val;
+ }
+ }
+ return vals;
+ }
+
+ function extend(a, b, undefOnly) {
+ for (var prop in b) {
+ if (hasOwn.call(b, prop)) {
+ if (b[prop] === undefined) {
+ delete a[prop];
+ } else if (!(undefOnly && typeof a[prop] !== "undefined")) {
+ a[prop] = b[prop];
+ }
+ }
+ }
+
+ return a;
+ }
+
+ function objectType(obj) {
+ if (typeof obj === "undefined") {
+ return "undefined";
+ }
+
+ // Consider: typeof null === object
+ if (obj === null) {
+ return "null";
+ }
+
+ var match = toString.call(obj).match(/^\[object\s(.*)\]$/),
+ type = match && match[1];
+
+ switch (type) {
+ case "Number":
+ if (isNaN(obj)) {
+ return "nan";
+ }
+ return "number";
+ case "String":
+ case "Boolean":
+ case "Array":
+ case "Set":
+ case "Map":
+ case "Date":
+ case "RegExp":
+ case "Function":
+ case "Symbol":
+ return type.toLowerCase();
+ default:
+ return typeof obj === "undefined" ? "undefined" : _typeof(obj);
+ }
+ }
+
+ // Safe object type checking
+ function is(type, obj) {
+ return objectType(obj) === type;
+ }
+
+ // Based on Java's String.hashCode, a simple but not
+ // rigorously collision resistant hashing function
+ function generateHash(module, testName) {
+ var str = module + "\x1C" + testName;
+ var hash = 0;
+
+ for (var i = 0; i < str.length; i++) {
+ hash = (hash << 5) - hash + str.charCodeAt(i);
+ hash |= 0;
+ }
+
+ // Convert the possibly negative integer hash code into an 8 character hex string, which isn't
+ // strictly necessary but increases user understanding that the id is a SHA-like hash
+ var hex = (0x100000000 + hash).toString(16);
+ if (hex.length < 8) {
+ hex = "0000000" + hex;
+ }
+
+ return hex.slice(-8);
+ }
+
+ // Test for equality any JavaScript type.
+ // Authors: Philippe Rathé <prathe@gmail.com>, David Chan <david@troi.org>
+ var equiv = (function () {
+
+ // Value pairs queued for comparison. Used for breadth-first processing order, recursion
+ // detection and avoiding repeated comparison (see below for details).
+ // Elements are { a: val, b: val }.
+ var pairs = [];
+
+ var getProto = Object.getPrototypeOf || function (obj) {
+ return obj.__proto__;
+ };
+
+ function useStrictEquality(a, b) {
+
+ // This only gets called if a and b are not strict equal, and is used to compare on
+ // the primitive values inside object wrappers. For example:
+ // `var i = 1;`
+ // `var j = new Number(1);`
+ // Neither a nor b can be null, as a !== b and they have the same type.
+ if ((typeof a === "undefined" ? "undefined" : _typeof(a)) === "object") {
+ a = a.valueOf();
+ }
+ if ((typeof b === "undefined" ? "undefined" : _typeof(b)) === "object") {
+ b = b.valueOf();
+ }
+
+ return a === b;
+ }
+
+ function compareConstructors(a, b) {
+ var protoA = getProto(a);
+ var protoB = getProto(b);
+
+ // Comparing constructors is more strict than using `instanceof`
+ if (a.constructor === b.constructor) {
+ return true;
+ }
+
+ // Ref #851
+ // If the obj prototype descends from a null constructor, treat it
+ // as a null prototype.
+ if (protoA && protoA.constructor === null) {
+ protoA = null;
+ }
+ if (protoB && protoB.constructor === null) {
+ protoB = null;
+ }
+
+ // Allow objects with no prototype to be equivalent to
+ // objects with Object as their constructor.
+ if (protoA === null && protoB === Object.prototype || protoB === null && protoA === Object.prototype) {
+ return true;
+ }
+
+ return false;
+ }
+
+ function getRegExpFlags(regexp) {
+ return "flags" in regexp ? regexp.flags : regexp.toString().match(/[gimuy]*$/)[0];
+ }
+
+ function isContainer(val) {
+ return ["object", "array", "map", "set"].indexOf(objectType(val)) !== -1;
+ }
+
+ function breadthFirstCompareChild(a, b) {
+
+ // If a is a container not reference-equal to b, postpone the comparison to the
+ // end of the pairs queue -- unless (a, b) has been seen before, in which case skip
+ // over the pair.
+ if (a === b) {
+ return true;
+ }
+ if (!isContainer(a)) {
+ return typeEquiv(a, b);
+ }
+ if (pairs.every(function (pair) {
+ return pair.a !== a || pair.b !== b;
+ })) {
+
+ // Not yet started comparing this pair
+ pairs.push({ a: a, b: b });
+ }
+ return true;
+ }
+
+ var callbacks = {
+ "string": useStrictEquality,
+ "boolean": useStrictEquality,
+ "number": useStrictEquality,
+ "null": useStrictEquality,
+ "undefined": useStrictEquality,
+ "symbol": useStrictEquality,
+ "date": useStrictEquality,
+
+ "nan": function nan() {
+ return true;
+ },
+
+ "regexp": function regexp(a, b) {
+ return a.source === b.source &&
+
+ // Include flags in the comparison
+ getRegExpFlags(a) === getRegExpFlags(b);
+ },
+
+ // abort (identical references / instance methods were skipped earlier)
+ "function": function _function() {
+ return false;
+ },
+
+ "array": function array(a, b) {
+ var i, len;
+
+ len = a.length;
+ if (len !== b.length) {
+
+ // Safe and faster
+ return false;
+ }
+
+ for (i = 0; i < len; i++) {
+
+ // Compare non-containers; queue non-reference-equal containers
+ if (!breadthFirstCompareChild(a[i], b[i])) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ // Define sets a and b to be equivalent if for each element aVal in a, there
+ // is some element bVal in b such that aVal and bVal are equivalent. Element
+ // repetitions are not counted, so these are equivalent:
+ // a = new Set( [ {}, [], [] ] );
+ // b = new Set( [ {}, {}, [] ] );
+ "set": function set$$1(a, b) {
+ var innerEq,
+ outerEq = true;
+
+ if (a.size !== b.size) {
+
+ // This optimization has certain quirks because of the lack of
+ // repetition counting. For instance, adding the same
+ // (reference-identical) element to two equivalent sets can
+ // make them non-equivalent.
+ return false;
+ }
+
+ a.forEach(function (aVal) {
+
+ // Short-circuit if the result is already known. (Using for...of
+ // with a break clause would be cleaner here, but it would cause
+ // a syntax error on older Javascript implementations even if
+ // Set is unused)
+ if (!outerEq) {
+ return;
+ }
+
+ innerEq = false;
+
+ b.forEach(function (bVal) {
+ var parentPairs;
+
+ // Likewise, short-circuit if the result is already known
+ if (innerEq) {
+ return;
+ }
+
+ // Swap out the global pairs list, as the nested call to
+ // innerEquiv will clobber its contents
+ parentPairs = pairs;
+ if (innerEquiv(bVal, aVal)) {
+ innerEq = true;
+ }
+
+ // Replace the global pairs list
+ pairs = parentPairs;
+ });
+
+ if (!innerEq) {
+ outerEq = false;
+ }
+ });
+
+ return outerEq;
+ },
+
+ // Define maps a and b to be equivalent if for each key-value pair (aKey, aVal)
+ // in a, there is some key-value pair (bKey, bVal) in b such that
+ // [ aKey, aVal ] and [ bKey, bVal ] are equivalent. Key repetitions are not
+ // counted, so these are equivalent:
+ // a = new Map( [ [ {}, 1 ], [ {}, 1 ], [ [], 1 ] ] );
+ // b = new Map( [ [ {}, 1 ], [ [], 1 ], [ [], 1 ] ] );
+ "map": function map(a, b) {
+ var innerEq,
+ outerEq = true;
+
+ if (a.size !== b.size) {
+
+ // This optimization has certain quirks because of the lack of
+ // repetition counting. For instance, adding the same
+ // (reference-identical) key-value pair to two equivalent maps
+ // can make them non-equivalent.
+ return false;
+ }
+
+ a.forEach(function (aVal, aKey) {
+
+ // Short-circuit if the result is already known. (Using for...of
+ // with a break clause would be cleaner here, but it would cause
+ // a syntax error on older Javascript implementations even if
+ // Map is unused)
+ if (!outerEq) {
+ return;
+ }
+
+ innerEq = false;
+
+ b.forEach(function (bVal, bKey) {
+ var parentPairs;
+
+ // Likewise, short-circuit if the result is already known
+ if (innerEq) {
+ return;
+ }
+
+ // Swap out the global pairs list, as the nested call to
+ // innerEquiv will clobber its contents
+ parentPairs = pairs;
+ if (innerEquiv([bVal, bKey], [aVal, aKey])) {
+ innerEq = true;
+ }
+
+ // Replace the global pairs list
+ pairs = parentPairs;
+ });
+
+ if (!innerEq) {
+ outerEq = false;
+ }
+ });
+
+ return outerEq;
+ },
+
+ "object": function object(a, b) {
+ var i,
+ aProperties = [],
+ bProperties = [];
+
+ if (compareConstructors(a, b) === false) {
+ return false;
+ }
+
+ // Be strict: don't ensure hasOwnProperty and go deep
+ for (i in a) {
+
+ // Collect a's properties
+ aProperties.push(i);
+
+ // Skip OOP methods that look the same
+ if (a.constructor !== Object && typeof a.constructor !== "undefined" && typeof a[i] === "function" && typeof b[i] === "function" && a[i].toString() === b[i].toString()) {
+ continue;
+ }
+
+ // Compare non-containers; queue non-reference-equal containers
+ if (!breadthFirstCompareChild(a[i], b[i])) {
+ return false;
+ }
+ }
+
+ for (i in b) {
+
+ // Collect b's properties
+ bProperties.push(i);
+ }
+
+ // Ensures identical properties name
+ return typeEquiv(aProperties.sort(), bProperties.sort());
+ }
+ };
+
+ function typeEquiv(a, b) {
+ var type = objectType(a);
+
+ // Callbacks for containers will append to the pairs queue to achieve breadth-first
+ // search order. The pairs queue is also used to avoid reprocessing any pair of
+ // containers that are reference-equal to a previously visited pair (a special case
+ // this being recursion detection).
+ //
+ // Because of this approach, once typeEquiv returns a false value, it should not be
+ // called again without clearing the pair queue else it may wrongly report a visited
+ // pair as being equivalent.
+ return objectType(b) === type && callbacks[type](a, b);
+ }
+
+ function innerEquiv(a, b) {
+ var i, pair;
+
+ // We're done when there's nothing more to compare
+ if (arguments.length < 2) {
+ return true;
+ }
+
+ // Clear the global pair queue and add the top-level values being compared
+ pairs = [{ a: a, b: b }];
+
+ for (i = 0; i < pairs.length; i++) {
+ pair = pairs[i];
+
+ // Perform type-specific comparison on any pairs that are not strictly
+ // equal. For container types, that comparison will postpone comparison
+ // of any sub-container pair to the end of the pair queue. This gives
+ // breadth-first search order. It also avoids the reprocessing of
+ // reference-equal siblings, cousins etc, which can have a significant speed
+ // impact when comparing a container of small objects each of which has a
+ // reference to the same (singleton) large object.
+ if (pair.a !== pair.b && !typeEquiv(pair.a, pair.b)) {
+ return false;
+ }
+ }
+
+ // ...across all consecutive argument pairs
+ return arguments.length === 2 || innerEquiv.apply(this, [].slice.call(arguments, 1));
+ }
+
+ return function () {
+ var result = innerEquiv.apply(undefined, arguments);
+
+ // Release any retained objects
+ pairs.length = 0;
+ return result;
+ };
+ })();
+
+ /**
+ * Config object: Maintain internal state
+ * Later exposed as QUnit.config
+ * `config` initialized at top of scope
+ */
+ var config = {
+
+ // The queue of tests to run
+ queue: [],
+
+ // Block until document ready
+ blocking: true,
+
+ // By default, run previously failed tests first
+ // very useful in combination with "Hide passed tests" checked
+ reorder: true,
+
+ // By default, modify document.title when suite is done
+ altertitle: true,
+
+ // HTML Reporter: collapse every test except the first failing test
+ // If false, all failing tests will be expanded
+ collapse: true,
+
+ // By default, scroll to top of the page when suite is done
+ scrolltop: true,
+
+ // Depth up-to which object will be dumped
+ maxDepth: 5,
+
+ // When enabled, all tests must call expect()
+ requireExpects: false,
+
+ // Placeholder for user-configurable form-exposed URL parameters
+ urlConfig: [],
+
+ // Set of all modules.
+ modules: [],
+
+ // The first unnamed module
+ currentModule: {
+ name: "",
+ tests: [],
+ childModules: [],
+ testsRun: 0,
+ unskippedTestsRun: 0,
+ hooks: {
+ before: [],
+ beforeEach: [],
+ afterEach: [],
+ after: []
+ }
+ },
+
+ callbacks: {},
+
+ // The storage module to use for reordering tests
+ storage: localSessionStorage
+ };
+
+ // take a predefined QUnit.config and extend the defaults
+ var globalConfig = window && window.QUnit && window.QUnit.config;
+
+ // only extend the global config if there is no QUnit overload
+ if (window && window.QUnit && !window.QUnit.version) {
+ extend(config, globalConfig);
+ }
+
+ // Push a loose unnamed module to the modules collection
+ config.modules.push(config.currentModule);
+
+ // Based on jsDump by Ariel Flesler
+ // http://flesler.blogspot.com/2008/05/jsdump-pretty-dump-of-any-javascript.html
+ var dump = (function () {
+ function quote(str) {
+ return "\"" + str.toString().replace(/\\/g, "\\\\").replace(/"/g, "\\\"") + "\"";
+ }
+ function literal(o) {
+ return o + "";
+ }
+ function join(pre, arr, post) {
+ var s = dump.separator(),
+ base = dump.indent(),
+ inner = dump.indent(1);
+ if (arr.join) {
+ arr = arr.join("," + s + inner);
+ }
+ if (!arr) {
+ return pre + post;
+ }
+ return [pre, inner + arr, base + post].join(s);
+ }
+ function array(arr, stack) {
+ var i = arr.length,
+ ret = new Array(i);
+
+ if (dump.maxDepth && dump.depth > dump.maxDepth) {
+ return "[object Array]";
+ }
+
+ this.up();
+ while (i--) {
+ ret[i] = this.parse(arr[i], undefined, stack);
+ }
+ this.down();
+ return join("[", ret, "]");
+ }
+
+ function isArray(obj) {
+ return (
+
+ //Native Arrays
+ toString.call(obj) === "[object Array]" ||
+
+ // NodeList objects
+ typeof obj.length === "number" && obj.item !== undefined && (obj.length ? obj.item(0) === obj[0] : obj.item(0) === null && obj[0] === undefined)
+ );
+ }
+
+ var reName = /^function (\w+)/,
+ dump = {
+
+ // The objType is used mostly internally, you can fix a (custom) type in advance
+ parse: function parse(obj, objType, stack) {
+ stack = stack || [];
+ var res,
+ parser,
+ parserType,
+ objIndex = stack.indexOf(obj);
+
+ if (objIndex !== -1) {
+ return "recursion(" + (objIndex - stack.length) + ")";
+ }
+
+ objType = objType || this.typeOf(obj);
+ parser = this.parsers[objType];
+ parserType = typeof parser === "undefined" ? "undefined" : _typeof(parser);
+
+ if (parserType === "function") {
+ stack.push(obj);
+ res = parser.call(this, obj, stack);
+ stack.pop();
+ return res;
+ }
+ return parserType === "string" ? parser : this.parsers.error;
+ },
+ typeOf: function typeOf(obj) {
+ var type;
+
+ if (obj === null) {
+ type = "null";
+ } else if (typeof obj === "undefined") {
+ type = "undefined";
+ } else if (is("regexp", obj)) {
+ type = "regexp";
+ } else if (is("date", obj)) {
+ type = "date";
+ } else if (is("function", obj)) {
+ type = "function";
+ } else if (obj.setInterval !== undefined && obj.document !== undefined && obj.nodeType === undefined) {
+ type = "window";
+ } else if (obj.nodeType === 9) {
+ type = "document";
+ } else if (obj.nodeType) {
+ type = "node";
+ } else if (isArray(obj)) {
+ type = "array";
+ } else if (obj.constructor === Error.prototype.constructor) {
+ type = "error";
+ } else {
+ type = typeof obj === "undefined" ? "undefined" : _typeof(obj);
+ }
+ return type;
+ },
+
+ separator: function separator() {
+ if (this.multiline) {
+ return this.HTML ? "<br />" : "\n";
+ } else {
+ return this.HTML ? "&#160;" : " ";
+ }
+ },
+
+ // Extra can be a number, shortcut for increasing-calling-decreasing
+ indent: function indent(extra) {
+ if (!this.multiline) {
+ return "";
+ }
+ var chr = this.indentChar;
+ if (this.HTML) {
+ chr = chr.replace(/\t/g, " ").replace(/ /g, "&#160;");
+ }
+ return new Array(this.depth + (extra || 0)).join(chr);
+ },
+ up: function up(a) {
+ this.depth += a || 1;
+ },
+ down: function down(a) {
+ this.depth -= a || 1;
+ },
+ setParser: function setParser(name, parser) {
+ this.parsers[name] = parser;
+ },
+
+ // The next 3 are exposed so you can use them
+ quote: quote,
+ literal: literal,
+ join: join,
+ depth: 1,
+ maxDepth: config.maxDepth,
+
+ // This is the list of parsers, to modify them, use dump.setParser
+ parsers: {
+ window: "[Window]",
+ document: "[Document]",
+ error: function error(_error) {
+ return "Error(\"" + _error.message + "\")";
+ },
+ unknown: "[Unknown]",
+ "null": "null",
+ "undefined": "undefined",
+ "function": function _function(fn) {
+ var ret = "function",
+
+
+ // Functions never have name in IE
+ name = "name" in fn ? fn.name : (reName.exec(fn) || [])[1];
+
+ if (name) {
+ ret += " " + name;
+ }
+ ret += "(";
+
+ ret = [ret, dump.parse(fn, "functionArgs"), "){"].join("");
+ return join(ret, dump.parse(fn, "functionCode"), "}");
+ },
+ array: array,
+ nodelist: array,
+ "arguments": array,
+ object: function object(map, stack) {
+ var keys,
+ key,
+ val,
+ i,
+ nonEnumerableProperties,
+ ret = [];
+
+ if (dump.maxDepth && dump.depth > dump.maxDepth) {
+ return "[object Object]";
+ }
+
+ dump.up();
+ keys = [];
+ for (key in map) {
+ keys.push(key);
+ }
+
+ // Some properties are not always enumerable on Error objects.
+ nonEnumerableProperties = ["message", "name"];
+ for (i in nonEnumerableProperties) {
+ key = nonEnumerableProperties[i];
+ if (key in map && !inArray(key, keys)) {
+ keys.push(key);
+ }
+ }
+ keys.sort();
+ for (i = 0; i < keys.length; i++) {
+ key = keys[i];
+ val = map[key];
+ ret.push(dump.parse(key, "key") + ": " + dump.parse(val, undefined, stack));
+ }
+ dump.down();
+ return join("{", ret, "}");
+ },
+ node: function node(_node) {
+ var len,
+ i,
+ val,
+ open = dump.HTML ? "&lt;" : "<",
+ close = dump.HTML ? "&gt;" : ">",
+ tag = _node.nodeName.toLowerCase(),
+ ret = open + tag,
+ attrs = _node.attributes;
+
+ if (attrs) {
+ for (i = 0, len = attrs.length; i < len; i++) {
+ val = attrs[i].nodeValue;
+
+ // IE6 includes all attributes in .attributes, even ones not explicitly
+ // set. Those have values like undefined, null, 0, false, "" or
+ // "inherit".
+ if (val && val !== "inherit") {
+ ret += " " + attrs[i].nodeName + "=" + dump.parse(val, "attribute");
+ }
+ }
+ }
+ ret += close;
+
+ // Show content of TextNode or CDATASection
+ if (_node.nodeType === 3 || _node.nodeType === 4) {
+ ret += _node.nodeValue;
+ }
+
+ return ret + open + "/" + tag + close;
+ },
+
+ // Function calls it internally, it's the arguments part of the function
+ functionArgs: function functionArgs(fn) {
+ var args,
+ l = fn.length;
+
+ if (!l) {
+ return "";
+ }
+
+ args = new Array(l);
+ while (l--) {
+
+ // 97 is 'a'
+ args[l] = String.fromCharCode(97 + l);
+ }
+ return " " + args.join(", ") + " ";
+ },
+
+ // Object calls it internally, the key part of an item in a map
+ key: quote,
+
+ // Function calls it internally, it's the content of the function
+ functionCode: "[code]",
+
+ // Node calls it internally, it's a html attribute value
+ attribute: quote,
+ string: quote,
+ date: quote,
+ regexp: literal,
+ number: literal,
+ "boolean": literal,
+ symbol: function symbol(sym) {
+ return sym.toString();
+ }
+ },
+
+ // If true, entities are escaped ( <, >, \t, space and \n )
+ HTML: false,
+
+ // Indentation unit
+ indentChar: " ",
+
+ // If true, items in a collection, are separated by a \n, else just a space.
+ multiline: true
+ };
+
+ return dump;
+ })();
+
+ var LISTENERS = Object.create(null);
+ var SUPPORTED_EVENTS = ["runStart", "suiteStart", "testStart", "assertion", "testEnd", "suiteEnd", "runEnd"];
+
+ /**
+ * Emits an event with the specified data to all currently registered listeners.
+ * Callbacks will fire in the order in which they are registered (FIFO). This
+ * function is not exposed publicly; it is used by QUnit internals to emit
+ * logging events.
+ *
+ * @private
+ * @method emit
+ * @param {String} eventName
+ * @param {Object} data
+ * @return {Void}
+ */
+ function emit(eventName, data) {
+ if (objectType(eventName) !== "string") {
+ throw new TypeError("eventName must be a string when emitting an event");
+ }
+
+ // Clone the callbacks in case one of them registers a new callback
+ var originalCallbacks = LISTENERS[eventName];
+ var callbacks = originalCallbacks ? [].concat(toConsumableArray(originalCallbacks)) : [];
+
+ for (var i = 0; i < callbacks.length; i++) {
+ callbacks[i](data);
+ }
+ }
+
+ /**
+ * Registers a callback as a listener to the specified event.
+ *
+ * @public
+ * @method on
+ * @param {String} eventName
+ * @param {Function} callback
+ * @return {Void}
+ */
+ function on(eventName, callback) {
+ if (objectType(eventName) !== "string") {
+ throw new TypeError("eventName must be a string when registering a listener");
+ } else if (!inArray(eventName, SUPPORTED_EVENTS)) {
+ var events = SUPPORTED_EVENTS.join(", ");
+ throw new Error("\"" + eventName + "\" is not a valid event; must be one of: " + events + ".");
+ } else if (objectType(callback) !== "function") {
+ throw new TypeError("callback must be a function when registering a listener");
+ }
+
+ if (!LISTENERS[eventName]) {
+ LISTENERS[eventName] = [];
+ }
+
+ // Don't register the same callback more than once
+ if (!inArray(callback, LISTENERS[eventName])) {
+ LISTENERS[eventName].push(callback);
+ }
+ }
+
+ // Register logging callbacks
+ function registerLoggingCallbacks(obj) {
+ var i,
+ l,
+ key,
+ callbackNames = ["begin", "done", "log", "testStart", "testDone", "moduleStart", "moduleDone"];
+
+ function registerLoggingCallback(key) {
+ var loggingCallback = function loggingCallback(callback) {
+ if (objectType(callback) !== "function") {
+ throw new Error("QUnit logging methods require a callback function as their first parameters.");
+ }
+
+ config.callbacks[key].push(callback);
+ };
+
+ return loggingCallback;
+ }
+
+ for (i = 0, l = callbackNames.length; i < l; i++) {
+ key = callbackNames[i];
+
+ // Initialize key collection of logging callback
+ if (objectType(config.callbacks[key]) === "undefined") {
+ config.callbacks[key] = [];
+ }
+
+ obj[key] = registerLoggingCallback(key);
+ }
+ }
+
+ function runLoggingCallbacks(key, args) {
+ var i, l, callbacks;
+
+ callbacks = config.callbacks[key];
+ for (i = 0, l = callbacks.length; i < l; i++) {
+ callbacks[i](args);
+ }
+ }
+
+ // Doesn't support IE9, it will return undefined on these browsers
+ // See also https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Error/Stack
+ var fileName = (sourceFromStacktrace(0) || "").replace(/(:\d+)+\)?/, "").replace(/.+\//, "");
+
+ function extractStacktrace(e, offset) {
+ offset = offset === undefined ? 4 : offset;
+
+ var stack, include, i;
+
+ if (e && e.stack) {
+ stack = e.stack.split("\n");
+ if (/^error$/i.test(stack[0])) {
+ stack.shift();
+ }
+ if (fileName) {
+ include = [];
+ for (i = offset; i < stack.length; i++) {
+ if (stack[i].indexOf(fileName) !== -1) {
+ break;
+ }
+ include.push(stack[i]);
+ }
+ if (include.length) {
+ return include.join("\n");
+ }
+ }
+ return stack[offset];
+ }
+ }
+
+ function sourceFromStacktrace(offset) {
+ var error = new Error();
+
+ // Support: Safari <=7 only, IE <=10 - 11 only
+ // Not all browsers generate the `stack` property for `new Error()`, see also #636
+ if (!error.stack) {
+ try {
+ throw error;
+ } catch (err) {
+ error = err;
+ }
+ }
+
+ return extractStacktrace(error, offset);
+ }
+
+ var priorityCount = 0;
+ var unitSampler = void 0;
+
+ /**
+ * Advances the ProcessingQueue to the next item if it is ready.
+ * @param {Boolean} last
+ */
+ function advance() {
+ var start = now();
+ config.depth = (config.depth || 0) + 1;
+
+ while (config.queue.length && !config.blocking) {
+ var elapsedTime = now() - start;
+
+ if (!defined.setTimeout || config.updateRate <= 0 || elapsedTime < config.updateRate) {
+ if (priorityCount > 0) {
+ priorityCount--;
+ }
+
+ config.queue.shift()();
+ } else {
+ setTimeout(advance, 13);
+ break;
+ }
+ }
+
+ config.depth--;
+
+ if (!config.blocking && !config.queue.length && config.depth === 0) {
+ done();
+ }
+ }
+
+ function addToQueueImmediate(callback) {
+ if (objectType(callback) === "array") {
+ while (callback.length) {
+ addToQueueImmediate(callback.pop());
+ }
+
+ return;
+ }
+
+ config.queue.unshift(callback);
+ priorityCount++;
+ }
+
+ /**
+ * Adds a function to the ProcessingQueue for execution.
+ * @param {Function|Array} callback
+ * @param {Boolean} priority
+ * @param {String} seed
+ */
+ function addToQueue(callback, prioritize, seed) {
+ if (prioritize) {
+ config.queue.splice(priorityCount++, 0, callback);
+ } else if (seed) {
+ if (!unitSampler) {
+ unitSampler = unitSamplerGenerator(seed);
+ }
+
+ // Insert into a random position after all prioritized items
+ var index = Math.floor(unitSampler() * (config.queue.length - priorityCount + 1));
+ config.queue.splice(priorityCount + index, 0, callback);
+ } else {
+ config.queue.push(callback);
+ }
+ }
+
+ /**
+ * Creates a seeded "sample" generator which is used for randomizing tests.
+ */
+ function unitSamplerGenerator(seed) {
+
+ // 32-bit xorshift, requires only a nonzero seed
+ // http://excamera.com/sphinx/article-xorshift.html
+ var sample = parseInt(generateHash(seed), 16) || -1;
+ return function () {
+ sample ^= sample << 13;
+ sample ^= sample >>> 17;
+ sample ^= sample << 5;
+
+ // ECMAScript has no unsigned number type
+ if (sample < 0) {
+ sample += 0x100000000;
+ }
+
+ return sample / 0x100000000;
+ };
+ }
+
+ /**
+ * This function is called when the ProcessingQueue is done processing all
+ * items. It handles emitting the final run events.
+ */
+ function done() {
+ var storage = config.storage;
+
+ ProcessingQueue.finished = true;
+
+ var runtime = now() - config.started;
+ var passed = config.stats.all - config.stats.bad;
+
+ emit("runEnd", globalSuite.end(true));
+ runLoggingCallbacks("done", {
+ passed: passed,
+ failed: config.stats.bad,
+ total: config.stats.all,
+ runtime: runtime
+ });
+
+ // Clear own storage items if all tests passed
+ if (storage && config.stats.bad === 0) {
+ for (var i = storage.length - 1; i >= 0; i--) {
+ var key = storage.key(i);
+
+ if (key.indexOf("qunit-test-") === 0) {
+ storage.removeItem(key);
+ }
+ }
+ }
+ }
+
+ var ProcessingQueue = {
+ finished: false,
+ add: addToQueue,
+ addImmediate: addToQueueImmediate,
+ advance: advance
+ };
+
+ var TestReport = function () {
+ function TestReport(name, suite, options) {
+ classCallCheck(this, TestReport);
+
+ this.name = name;
+ this.suiteName = suite.name;
+ this.fullName = suite.fullName.concat(name);
+ this.runtime = 0;
+ this.assertions = [];
+
+ this.skipped = !!options.skip;
+ this.todo = !!options.todo;
+
+ this.valid = options.valid;
+
+ this._startTime = 0;
+ this._endTime = 0;
+
+ suite.pushTest(this);
+ }
+
+ createClass(TestReport, [{
+ key: "start",
+ value: function start(recordTime) {
+ if (recordTime) {
+ this._startTime = Date.now();
+ }
+
+ return {
+ name: this.name,
+ suiteName: this.suiteName,
+ fullName: this.fullName.slice()
+ };
+ }
+ }, {
+ key: "end",
+ value: function end(recordTime) {
+ if (recordTime) {
+ this._endTime = Date.now();
+ }
+
+ return extend(this.start(), {
+ runtime: this.getRuntime(),
+ status: this.getStatus(),
+ errors: this.getFailedAssertions(),
+ assertions: this.getAssertions()
+ });
+ }
+ }, {
+ key: "pushAssertion",
+ value: function pushAssertion(assertion) {
+ this.assertions.push(assertion);
+ }
+ }, {
+ key: "getRuntime",
+ value: function getRuntime() {
+ return this._endTime - this._startTime;
+ }
+ }, {
+ key: "getStatus",
+ value: function getStatus() {
+ if (this.skipped) {
+ return "skipped";
+ }
+
+ var testPassed = this.getFailedAssertions().length > 0 ? this.todo : !this.todo;
+
+ if (!testPassed) {
+ return "failed";
+ } else if (this.todo) {
+ return "todo";
+ } else {
+ return "passed";
+ }
+ }
+ }, {
+ key: "getFailedAssertions",
+ value: function getFailedAssertions() {
+ return this.assertions.filter(function (assertion) {
+ return !assertion.passed;
+ });
+ }
+ }, {
+ key: "getAssertions",
+ value: function getAssertions() {
+ return this.assertions.slice();
+ }
+
+ // Remove actual and expected values from assertions. This is to prevent
+ // leaking memory throughout a test suite.
+
+ }, {
+ key: "slimAssertions",
+ value: function slimAssertions() {
+ this.assertions = this.assertions.map(function (assertion) {
+ delete assertion.actual;
+ delete assertion.expected;
+ return assertion;
+ });
+ }
+ }]);
+ return TestReport;
+ }();
+
+ var focused$1 = false;
+
+ function Test(settings) {
+ var i, l;
+
+ ++Test.count;
+
+ this.expected = null;
+ this.assertions = [];
+ this.semaphore = 0;
+ this.module = config.currentModule;
+ this.stack = sourceFromStacktrace(3);
+ this.steps = [];
+ this.timeout = undefined;
+
+ // If a module is skipped, all its tests and the tests of the child suites
+ // should be treated as skipped even if they are defined as `only` or `todo`.
+ // As for `todo` module, all its tests will be treated as `todo` except for
+ // tests defined as `skip` which will be left intact.
+ //
+ // So, if a test is defined as `todo` and is inside a skipped module, we should
+ // then treat that test as if was defined as `skip`.
+ if (this.module.skip) {
+ settings.skip = true;
+ settings.todo = false;
+
+ // Skipped tests should be left intact
+ } else if (this.module.todo && !settings.skip) {
+ settings.todo = true;
+ }
+
+ extend(this, settings);
+
+ this.testReport = new TestReport(settings.testName, this.module.suiteReport, {
+ todo: settings.todo,
+ skip: settings.skip,
+ valid: this.valid()
+ });
+
+ // Register unique strings
+ for (i = 0, l = this.module.tests; i < l.length; i++) {
+ if (this.module.tests[i].name === this.testName) {
+ this.testName += " ";
+ }
+ }
+
+ this.testId = generateHash(this.module.name, this.testName);
+
+ this.module.tests.push({
+ name: this.testName,
+ testId: this.testId,
+ skip: !!settings.skip
+ });
+
+ if (settings.skip) {
+
+ // Skipped tests will fully ignore any sent callback
+ this.callback = function () {};
+ this.async = false;
+ this.expected = 0;
+ } else {
+ this.assert = new Assert(this);
+ }
+ }
+
+ Test.count = 0;
+
+ function getNotStartedModules(startModule) {
+ var module = startModule,
+ modules = [];
+
+ while (module && module.testsRun === 0) {
+ modules.push(module);
+ module = module.parentModule;
+ }
+
+ return modules;
+ }
+
+ Test.prototype = {
+ before: function before() {
+ var i,
+ startModule,
+ module = this.module,
+ notStartedModules = getNotStartedModules(module);
+
+ for (i = notStartedModules.length - 1; i >= 0; i--) {
+ startModule = notStartedModules[i];
+ startModule.stats = { all: 0, bad: 0, started: now() };
+ emit("suiteStart", startModule.suiteReport.start(true));
+ runLoggingCallbacks("moduleStart", {
+ name: startModule.name,
+ tests: startModule.tests
+ });
+ }
+
+ config.current = this;
+
+ this.testEnvironment = extend({}, module.testEnvironment);
+
+ this.started = now();
+ emit("testStart", this.testReport.start(true));
+ runLoggingCallbacks("testStart", {
+ name: this.testName,
+ module: module.name,
+ testId: this.testId,
+ previousFailure: this.previousFailure
+ });
+
+ if (!config.pollution) {
+ saveGlobal();
+ }
+ },
+
+ run: function run() {
+ var promise;
+
+ config.current = this;
+
+ this.callbackStarted = now();
+
+ if (config.notrycatch) {
+ runTest(this);
+ return;
+ }
+
+ try {
+ runTest(this);
+ } catch (e) {
+ this.pushFailure("Died on test #" + (this.assertions.length + 1) + " " + this.stack + ": " + (e.message || e), extractStacktrace(e, 0));
+
+ // Else next test will carry the responsibility
+ saveGlobal();
+
+ // Restart the tests if they're blocking
+ if (config.blocking) {
+ internalRecover(this);
+ }
+ }
+
+ function runTest(test) {
+ promise = test.callback.call(test.testEnvironment, test.assert);
+ test.resolvePromise(promise);
+
+ // If the test has a "lock" on it, but the timeout is 0, then we push a
+ // failure as the test should be synchronous.
+ if (test.timeout === 0 && test.semaphore !== 0) {
+ pushFailure("Test did not finish synchronously even though assert.timeout( 0 ) was used.", sourceFromStacktrace(2));
+ }
+ }
+ },
+
+ after: function after() {
+ checkPollution();
+ },
+
+ queueHook: function queueHook(hook, hookName, hookOwner) {
+ var _this = this;
+
+ var callHook = function callHook() {
+ var promise = hook.call(_this.testEnvironment, _this.assert);
+ _this.resolvePromise(promise, hookName);
+ };
+
+ var runHook = function runHook() {
+ if (hookName === "before") {
+ if (hookOwner.unskippedTestsRun !== 0) {
+ return;
+ }
+
+ _this.preserveEnvironment = true;
+ }
+
+ if (hookName === "after" && hookOwner.unskippedTestsRun !== numberOfUnskippedTests(hookOwner) - 1 && config.queue.length > 2) {
+ return;
+ }
+
+ config.current = _this;
+ if (config.notrycatch) {
+ callHook();
+ return;
+ }
+ try {
+ callHook();
+ } catch (error) {
+ _this.pushFailure(hookName + " failed on " + _this.testName + ": " + (error.message || error), extractStacktrace(error, 0));
+ }
+ };
+
+ return runHook;
+ },
+
+
+ // Currently only used for module level hooks, can be used to add global level ones
+ hooks: function hooks(handler) {
+ var hooks = [];
+
+ function processHooks(test, module) {
+ if (module.parentModule) {
+ processHooks(test, module.parentModule);
+ }
+
+ if (module.hooks[handler].length) {
+ for (var i = 0; i < module.hooks[handler].length; i++) {
+ hooks.push(test.queueHook(module.hooks[handler][i], handler, module));
+ }
+ }
+ }
+
+ // Hooks are ignored on skipped tests
+ if (!this.skip) {
+ processHooks(this, this.module);
+ }
+
+ return hooks;
+ },
+
+
+ finish: function finish() {
+ config.current = this;
+ if (config.requireExpects && this.expected === null) {
+ this.pushFailure("Expected number of assertions to be defined, but expect() was " + "not called.", this.stack);
+ } else if (this.expected !== null && this.expected !== this.assertions.length) {
+ this.pushFailure("Expected " + this.expected + " assertions, but " + this.assertions.length + " were run", this.stack);
+ } else if (this.expected === null && !this.assertions.length) {
+ this.pushFailure("Expected at least one assertion, but none were run - call " + "expect(0) to accept zero assertions.", this.stack);
+ }
+
+ var i,
+ module = this.module,
+ moduleName = module.name,
+ testName = this.testName,
+ skipped = !!this.skip,
+ todo = !!this.todo,
+ bad = 0,
+ storage = config.storage;
+
+ this.runtime = now() - this.started;
+
+ config.stats.all += this.assertions.length;
+ module.stats.all += this.assertions.length;
+
+ for (i = 0; i < this.assertions.length; i++) {
+ if (!this.assertions[i].result) {
+ bad++;
+ config.stats.bad++;
+ module.stats.bad++;
+ }
+ }
+
+ notifyTestsRan(module, skipped);
+
+ // Store result when possible
+ if (storage) {
+ if (bad) {
+ storage.setItem("qunit-test-" + moduleName + "-" + testName, bad);
+ } else {
+ storage.removeItem("qunit-test-" + moduleName + "-" + testName);
+ }
+ }
+
+ // After emitting the js-reporters event we cleanup the assertion data to
+ // avoid leaking it. It is not used by the legacy testDone callbacks.
+ emit("testEnd", this.testReport.end(true));
+ this.testReport.slimAssertions();
+
+ runLoggingCallbacks("testDone", {
+ name: testName,
+ module: moduleName,
+ skipped: skipped,
+ todo: todo,
+ failed: bad,
+ passed: this.assertions.length - bad,
+ total: this.assertions.length,
+ runtime: skipped ? 0 : this.runtime,
+
+ // HTML Reporter use
+ assertions: this.assertions,
+ testId: this.testId,
+
+ // Source of Test
+ source: this.stack
+ });
+
+ if (module.testsRun === numberOfTests(module)) {
+ logSuiteEnd(module);
+
+ // Check if the parent modules, iteratively, are done. If that the case,
+ // we emit the `suiteEnd` event and trigger `moduleDone` callback.
+ var parent = module.parentModule;
+ while (parent && parent.testsRun === numberOfTests(parent)) {
+ logSuiteEnd(parent);
+ parent = parent.parentModule;
+ }
+ }
+
+ config.current = undefined;
+
+ function logSuiteEnd(module) {
+ emit("suiteEnd", module.suiteReport.end(true));
+ runLoggingCallbacks("moduleDone", {
+ name: module.name,
+ tests: module.tests,
+ failed: module.stats.bad,
+ passed: module.stats.all - module.stats.bad,
+ total: module.stats.all,
+ runtime: now() - module.stats.started
+ });
+ }
+ },
+
+ preserveTestEnvironment: function preserveTestEnvironment() {
+ if (this.preserveEnvironment) {
+ this.module.testEnvironment = this.testEnvironment;
+ this.testEnvironment = extend({}, this.module.testEnvironment);
+ }
+ },
+
+ queue: function queue() {
+ var test = this;
+
+ if (!this.valid()) {
+ return;
+ }
+
+ function runTest() {
+
+ // Each of these can by async
+ ProcessingQueue.addImmediate([function () {
+ test.before();
+ }, test.hooks("before"), function () {
+ test.preserveTestEnvironment();
+ }, test.hooks("beforeEach"), function () {
+ test.run();
+ }, test.hooks("afterEach").reverse(), test.hooks("after").reverse(), function () {
+ test.after();
+ }, function () {
+ test.finish();
+ }]);
+ }
+
+ var previousFailCount = config.storage && +config.storage.getItem("qunit-test-" + this.module.name + "-" + this.testName);
+
+ // Prioritize previously failed tests, detected from storage
+ var prioritize = config.reorder && !!previousFailCount;
+
+ this.previousFailure = !!previousFailCount;
+
+ ProcessingQueue.add(runTest, prioritize, config.seed);
+
+ // If the queue has already finished, we manually process the new test
+ if (ProcessingQueue.finished) {
+ ProcessingQueue.advance();
+ }
+ },
+
+
+ pushResult: function pushResult(resultInfo) {
+ if (this !== config.current) {
+ throw new Error("Assertion occured after test had finished.");
+ }
+
+ // Destructure of resultInfo = { result, actual, expected, message, negative }
+ var source,
+ details = {
+ module: this.module.name,
+ name: this.testName,
+ result: resultInfo.result,
+ message: resultInfo.message,
+ actual: resultInfo.actual,
+ expected: resultInfo.expected,
+ testId: this.testId,
+ negative: resultInfo.negative || false,
+ runtime: now() - this.started,
+ todo: !!this.todo
+ };
+
+ if (!resultInfo.result) {
+ source = resultInfo.source || sourceFromStacktrace();
+
+ if (source) {
+ details.source = source;
+ }
+ }
+
+ this.logAssertion(details);
+
+ this.assertions.push({
+ result: !!resultInfo.result,
+ message: resultInfo.message
+ });
+ },
+
+ pushFailure: function pushFailure(message, source, actual) {
+ if (!(this instanceof Test)) {
+ throw new Error("pushFailure() assertion outside test context, was " + sourceFromStacktrace(2));
+ }
+
+ this.pushResult({
+ result: false,
+ message: message || "error",
+ actual: actual || null,
+ expected: null,
+ source: source
+ });
+ },
+
+ /**
+ * Log assertion details using both the old QUnit.log interface and
+ * QUnit.on( "assertion" ) interface.
+ *
+ * @private
+ */
+ logAssertion: function logAssertion(details) {
+ runLoggingCallbacks("log", details);
+
+ var assertion = {
+ passed: details.result,
+ actual: details.actual,
+ expected: details.expected,
+ message: details.message,
+ stack: details.source,
+ todo: details.todo
+ };
+ this.testReport.pushAssertion(assertion);
+ emit("assertion", assertion);
+ },
+
+
+ resolvePromise: function resolvePromise(promise, phase) {
+ var then,
+ resume,
+ message,
+ test = this;
+ if (promise != null) {
+ then = promise.then;
+ if (objectType(then) === "function") {
+ resume = internalStop(test);
+ then.call(promise, function () {
+ resume();
+ }, function (error) {
+ message = "Promise rejected " + (!phase ? "during" : phase.replace(/Each$/, "")) + " \"" + test.testName + "\": " + (error && error.message || error);
+ test.pushFailure(message, extractStacktrace(error, 0));
+
+ // Else next test will carry the responsibility
+ saveGlobal();
+
+ // Unblock
+ resume();
+ });
+ }
+ }
+ },
+
+ valid: function valid() {
+ var filter = config.filter,
+ regexFilter = /^(!?)\/([\w\W]*)\/(i?$)/.exec(filter),
+ module = config.module && config.module.toLowerCase(),
+ fullName = this.module.name + ": " + this.testName;
+
+ function moduleChainNameMatch(testModule) {
+ var testModuleName = testModule.name ? testModule.name.toLowerCase() : null;
+ if (testModuleName === module) {
+ return true;
+ } else if (testModule.parentModule) {
+ return moduleChainNameMatch(testModule.parentModule);
+ } else {
+ return false;
+ }
+ }
+
+ function moduleChainIdMatch(testModule) {
+ return inArray(testModule.moduleId, config.moduleId) || testModule.parentModule && moduleChainIdMatch(testModule.parentModule);
+ }
+
+ // Internally-generated tests are always valid
+ if (this.callback && this.callback.validTest) {
+ return true;
+ }
+
+ if (config.moduleId && config.moduleId.length > 0 && !moduleChainIdMatch(this.module)) {
+
+ return false;
+ }
+
+ if (config.testId && config.testId.length > 0 && !inArray(this.testId, config.testId)) {
+
+ return false;
+ }
+
+ if (module && !moduleChainNameMatch(this.module)) {
+ return false;
+ }
+
+ if (!filter) {
+ return true;
+ }
+
+ return regexFilter ? this.regexFilter(!!regexFilter[1], regexFilter[2], regexFilter[3], fullName) : this.stringFilter(filter, fullName);
+ },
+
+ regexFilter: function regexFilter(exclude, pattern, flags, fullName) {
+ var regex = new RegExp(pattern, flags);
+ var match = regex.test(fullName);
+
+ return match !== exclude;
+ },
+
+ stringFilter: function stringFilter(filter, fullName) {
+ filter = filter.toLowerCase();
+ fullName = fullName.toLowerCase();
+
+ var include = filter.charAt(0) !== "!";
+ if (!include) {
+ filter = filter.slice(1);
+ }
+
+ // If the filter matches, we need to honour include
+ if (fullName.indexOf(filter) !== -1) {
+ return include;
+ }
+
+ // Otherwise, do the opposite
+ return !include;
+ }
+ };
+
+ function pushFailure() {
+ if (!config.current) {
+ throw new Error("pushFailure() assertion outside test context, in " + sourceFromStacktrace(2));
+ }
+
+ // Gets current test obj
+ var currentTest = config.current;
+
+ return currentTest.pushFailure.apply(currentTest, arguments);
+ }
+
+ function saveGlobal() {
+ config.pollution = [];
+
+ if (config.noglobals) {
+ for (var key in global$1) {
+ if (hasOwn.call(global$1, key)) {
+
+ // In Opera sometimes DOM element ids show up here, ignore them
+ if (/^qunit-test-output/.test(key)) {
+ continue;
+ }
+ config.pollution.push(key);
+ }
+ }
+ }
+ }
+
+ function checkPollution() {
+ var newGlobals,
+ deletedGlobals,
+ old = config.pollution;
+
+ saveGlobal();
+
+ newGlobals = diff(config.pollution, old);
+ if (newGlobals.length > 0) {
+ pushFailure("Introduced global variable(s): " + newGlobals.join(", "));
+ }
+
+ deletedGlobals = diff(old, config.pollution);
+ if (deletedGlobals.length > 0) {
+ pushFailure("Deleted global variable(s): " + deletedGlobals.join(", "));
+ }
+ }
+
+ // Will be exposed as QUnit.test
+ function test(testName, callback) {
+ if (focused$1) {
+ return;
+ }
+
+ var newTest = new Test({
+ testName: testName,
+ callback: callback
+ });
+
+ newTest.queue();
+ }
+
+ function todo(testName, callback) {
+ if (focused$1) {
+ return;
+ }
+
+ var newTest = new Test({
+ testName: testName,
+ callback: callback,
+ todo: true
+ });
+
+ newTest.queue();
+ }
+
+ // Will be exposed as QUnit.skip
+ function skip(testName) {
+ if (focused$1) {
+ return;
+ }
+
+ var test = new Test({
+ testName: testName,
+ skip: true
+ });
+
+ test.queue();
+ }
+
+ // Will be exposed as QUnit.only
+ function only(testName, callback) {
+ if (focused$1) {
+ return;
+ }
+
+ config.queue.length = 0;
+ focused$1 = true;
+
+ var newTest = new Test({
+ testName: testName,
+ callback: callback
+ });
+
+ newTest.queue();
+ }
+
+ // Put a hold on processing and return a function that will release it.
+ function internalStop(test) {
+ test.semaphore += 1;
+ config.blocking = true;
+
+ // Set a recovery timeout, if so configured.
+ if (defined.setTimeout) {
+ var timeoutDuration = void 0;
+
+ if (typeof test.timeout === "number") {
+ timeoutDuration = test.timeout;
+ } else if (typeof config.testTimeout === "number") {
+ timeoutDuration = config.testTimeout;
+ }
+
+ if (typeof timeoutDuration === "number" && timeoutDuration > 0) {
+ clearTimeout(config.timeout);
+ config.timeout = setTimeout(function () {
+ pushFailure("Test took longer than " + timeoutDuration + "ms; test timed out.", sourceFromStacktrace(2));
+ internalRecover(test);
+ }, timeoutDuration);
+ }
+ }
+
+ var released = false;
+ return function resume() {
+ if (released) {
+ return;
+ }
+
+ released = true;
+ test.semaphore -= 1;
+ internalStart(test);
+ };
+ }
+
+ // Forcefully release all processing holds.
+ function internalRecover(test) {
+ test.semaphore = 0;
+ internalStart(test);
+ }
+
+ // Release a processing hold, scheduling a resumption attempt if no holds remain.
+ function internalStart(test) {
+
+ // If semaphore is non-numeric, throw error
+ if (isNaN(test.semaphore)) {
+ test.semaphore = 0;
+
+ pushFailure("Invalid value on test.semaphore", sourceFromStacktrace(2));
+ return;
+ }
+
+ // Don't start until equal number of stop-calls
+ if (test.semaphore > 0) {
+ return;
+ }
+
+ // Throw an Error if start is called more often than stop
+ if (test.semaphore < 0) {
+ test.semaphore = 0;
+
+ pushFailure("Tried to restart test while already started (test's semaphore was 0 already)", sourceFromStacktrace(2));
+ return;
+ }
+
+ // Add a slight delay to allow more assertions etc.
+ if (defined.setTimeout) {
+ if (config.timeout) {
+ clearTimeout(config.timeout);
+ }
+ config.timeout = setTimeout(function () {
+ if (test.semaphore > 0) {
+ return;
+ }
+
+ if (config.timeout) {
+ clearTimeout(config.timeout);
+ }
+
+ begin();
+ }, 13);
+ } else {
+ begin();
+ }
+ }
+
+ function collectTests(module) {
+ var tests = [].concat(module.tests);
+ var modules = [].concat(toConsumableArray(module.childModules));
+
+ // Do a breadth-first traversal of the child modules
+ while (modules.length) {
+ var nextModule = modules.shift();
+ tests.push.apply(tests, nextModule.tests);
+ modules.push.apply(modules, toConsumableArray(nextModule.childModules));
+ }
+
+ return tests;
+ }
+
+ function numberOfTests(module) {
+ return collectTests(module).length;
+ }
+
+ function numberOfUnskippedTests(module) {
+ return collectTests(module).filter(function (test) {
+ return !test.skip;
+ }).length;
+ }
+
+ function notifyTestsRan(module, skipped) {
+ module.testsRun++;
+ if (!skipped) {
+ module.unskippedTestsRun++;
+ }
+ while (module = module.parentModule) {
+ module.testsRun++;
+ if (!skipped) {
+ module.unskippedTestsRun++;
+ }
+ }
+ }
+
+ /**
+ * Returns a function that proxies to the given method name on the globals
+ * console object. The proxy will also detect if the console doesn't exist and
+ * will appropriately no-op. This allows support for IE9, which doesn't have a
+ * console if the developer tools are not open.
+ */
+ function consoleProxy(method) {
+ return function () {
+ if (console) {
+ console[method].apply(console, arguments);
+ }
+ };
+ }
+
+ var Logger = {
+ warn: consoleProxy("warn")
+ };
+
+ var Assert = function () {
+ function Assert(testContext) {
+ classCallCheck(this, Assert);
+
+ this.test = testContext;
+ }
+
+ // Assert helpers
+
+ createClass(Assert, [{
+ key: "timeout",
+ value: function timeout(duration) {
+ if (typeof duration !== "number") {
+ throw new Error("You must pass a number as the duration to assert.timeout");
+ }
+
+ this.test.timeout = duration;
+ }
+
+ // Documents a "step", which is a string value, in a test as a passing assertion
+
+ }, {
+ key: "step",
+ value: function step(message) {
+ var result = !!message;
+
+ this.test.steps.push(message);
+
+ return this.pushResult({
+ result: result,
+ message: message || "You must provide a message to assert.step"
+ });
+ }
+
+ // Verifies the steps in a test match a given array of string values
+
+ }, {
+ key: "verifySteps",
+ value: function verifySteps(steps, message) {
+ this.deepEqual(this.test.steps, steps, message);
+ }
+
+ // Specify the number of expected assertions to guarantee that failed test
+ // (no assertions are run at all) don't slip through.
+
+ }, {
+ key: "expect",
+ value: function expect(asserts) {
+ if (arguments.length === 1) {
+ this.test.expected = asserts;
+ } else {
+ return this.test.expected;
+ }
+ }
+
+ // Put a hold on processing and return a function that will release it a maximum of once.
+
+ }, {
+ key: "async",
+ value: function async(count) {
+ var test$$1 = this.test;
+
+ var popped = false,
+ acceptCallCount = count;
+
+ if (typeof acceptCallCount === "undefined") {
+ acceptCallCount = 1;
+ }
+
+ var resume = internalStop(test$$1);
+
+ return function done() {
+ if (config.current !== test$$1) {
+ throw Error("assert.async callback called after test finished.");
+ }
+
+ if (popped) {
+ test$$1.pushFailure("Too many calls to the `assert.async` callback", sourceFromStacktrace(2));
+ return;
+ }
+
+ acceptCallCount -= 1;
+ if (acceptCallCount > 0) {
+ return;
+ }
+
+ popped = true;
+ resume();
+ };
+ }
+
+ // Exports test.push() to the user API
+ // Alias of pushResult.
+
+ }, {
+ key: "push",
+ value: function push(result, actual, expected, message, negative) {
+ Logger.warn("assert.push is deprecated and will be removed in QUnit 3.0." + " Please use assert.pushResult instead (https://api.qunitjs.com/assert/pushResult).");
+
+ var currentAssert = this instanceof Assert ? this : config.current.assert;
+ return currentAssert.pushResult({
+ result: result,
+ actual: actual,
+ expected: expected,
+ message: message,
+ negative: negative
+ });
+ }
+ }, {
+ key: "pushResult",
+ value: function pushResult(resultInfo) {
+
+ // Destructure of resultInfo = { result, actual, expected, message, negative }
+ var assert = this;
+ var currentTest = assert instanceof Assert && assert.test || config.current;
+
+ // Backwards compatibility fix.
+ // Allows the direct use of global exported assertions and QUnit.assert.*
+ // Although, it's use is not recommended as it can leak assertions
+ // to other tests from async tests, because we only get a reference to the current test,
+ // not exactly the test where assertion were intended to be called.
+ if (!currentTest) {
+ throw new Error("assertion outside test context, in " + sourceFromStacktrace(2));
+ }
+
+ if (!(assert instanceof Assert)) {
+ assert = currentTest.assert;
+ }
+
+ return assert.test.pushResult(resultInfo);
+ }
+ }, {
+ key: "ok",
+ value: function ok(result, message) {
+ if (!message) {
+ message = result ? "okay" : "failed, expected argument to be truthy, was: " + dump.parse(result);
+ }
+
+ this.pushResult({
+ result: !!result,
+ actual: result,
+ expected: true,
+ message: message
+ });
+ }
+ }, {
+ key: "notOk",
+ value: function notOk(result, message) {
+ if (!message) {
+ message = !result ? "okay" : "failed, expected argument to be falsy, was: " + dump.parse(result);
+ }
+
+ this.pushResult({
+ result: !result,
+ actual: result,
+ expected: false,
+ message: message
+ });
+ }
+ }, {
+ key: "equal",
+ value: function equal(actual, expected, message) {
+
+ // eslint-disable-next-line eqeqeq
+ var result = expected == actual;
+
+ this.pushResult({
+ result: result,
+ actual: actual,
+ expected: expected,
+ message: message
+ });
+ }
+ }, {
+ key: "notEqual",
+ value: function notEqual(actual, expected, message) {
+
+ // eslint-disable-next-line eqeqeq
+ var result = expected != actual;
+
+ this.pushResult({
+ result: result,
+ actual: actual,
+ expected: expected,
+ message: message,
+ negative: true
+ });
+ }
+ }, {
+ key: "propEqual",
+ value: function propEqual(actual, expected, message) {
+ actual = objectValues(actual);
+ expected = objectValues(expected);
+
+ this.pushResult({
+ result: equiv(actual, expected),
+ actual: actual,
+ expected: expected,
+ message: message
+ });
+ }
+ }, {
+ key: "notPropEqual",
+ value: function notPropEqual(actual, expected, message) {
+ actual = objectValues(actual);
+ expected = objectValues(expected);
+
+ this.pushResult({
+ result: !equiv(actual, expected),
+ actual: actual,
+ expected: expected,
+ message: message,
+ negative: true
+ });
+ }
+ }, {
+ key: "deepEqual",
+ value: function deepEqual(actual, expected, message) {
+ this.pushResult({
+ result: equiv(actual, expected),
+ actual: actual,
+ expected: expected,
+ message: message
+ });
+ }
+ }, {
+ key: "notDeepEqual",
+ value: function notDeepEqual(actual, expected, message) {
+ this.pushResult({
+ result: !equiv(actual, expected),
+ actual: actual,
+ expected: expected,
+ message: message,
+ negative: true
+ });
+ }
+ }, {
+ key: "strictEqual",
+ value: function strictEqual(actual, expected, message) {
+ this.pushResult({
+ result: expected === actual,
+ actual: actual,
+ expected: expected,
+ message: message
+ });
+ }
+ }, {
+ key: "notStrictEqual",
+ value: function notStrictEqual(actual, expected, message) {
+ this.pushResult({
+ result: expected !== actual,
+ actual: actual,
+ expected: expected,
+ message: message,
+ negative: true
+ });
+ }
+ }, {
+ key: "throws",
+ value: function throws(block, expected, message) {
+ var actual = void 0,
+ result = false;
+
+ var currentTest = this instanceof Assert && this.test || config.current;
+
+ // 'expected' is optional unless doing string comparison
+ if (objectType(expected) === "string") {
+ if (message == null) {
+ message = expected;
+ expected = null;
+ } else {
+ throw new Error("throws/raises does not accept a string value for the expected argument.\n" + "Use a non-string object value (e.g. regExp) instead if it's necessary.");
+ }
+ }
+
+ currentTest.ignoreGlobalErrors = true;
+ try {
+ block.call(currentTest.testEnvironment);
+ } catch (e) {
+ actual = e;
+ }
+ currentTest.ignoreGlobalErrors = false;
+
+ if (actual) {
+ var expectedType = objectType(expected);
+
+ // We don't want to validate thrown error
+ if (!expected) {
+ result = true;
+ expected = null;
+
+ // Expected is a regexp
+ } else if (expectedType === "regexp") {
+ result = expected.test(errorString(actual));
+
+ // Expected is a constructor, maybe an Error constructor
+ } else if (expectedType === "function" && actual instanceof expected) {
+ result = true;
+
+ // Expected is an Error object
+ } else if (expectedType === "object") {
+ result = actual instanceof expected.constructor && actual.name === expected.name && actual.message === expected.message;
+
+ // Expected is a validation function which returns true if validation passed
+ } else if (expectedType === "function" && expected.call({}, actual) === true) {
+ expected = null;
+ result = true;
+ }
+ }
+
+ currentTest.assert.pushResult({
+ result: result,
+ actual: actual,
+ expected: expected,
+ message: message
+ });
+ }
+ }]);
+ return Assert;
+ }();
+
+ // Provide an alternative to assert.throws(), for environments that consider throws a reserved word
+ // Known to us are: Closure Compiler, Narwhal
+ // eslint-disable-next-line dot-notation
+
+
+ Assert.prototype.raises = Assert.prototype["throws"];
+
+ /**
+ * Converts an error into a simple string for comparisons.
+ *
+ * @param {Error} error
+ * @return {String}
+ */
+ function errorString(error) {
+ var resultErrorString = error.toString();
+
+ if (resultErrorString.substring(0, 7) === "[object") {
+ var name = error.name ? error.name.toString() : "Error";
+ var message = error.message ? error.message.toString() : "";
+
+ if (name && message) {
+ return name + ": " + message;
+ } else if (name) {
+ return name;
+ } else if (message) {
+ return message;
+ } else {
+ return "Error";
+ }
+ } else {
+ return resultErrorString;
+ }
+ }
+
+ /* global module, exports, define */
+ function exportQUnit(QUnit) {
+
+ if (defined.document) {
+
+ // QUnit may be defined when it is preconfigured but then only QUnit and QUnit.config may be defined.
+ if (window.QUnit && window.QUnit.version) {
+ throw new Error("QUnit has already been defined.");
+ }
+
+ window.QUnit = QUnit;
+ }
+
+ // For nodejs
+ if (typeof module !== "undefined" && module && module.exports) {
+ module.exports = QUnit;
+
+ // For consistency with CommonJS environments' exports
+ module.exports.QUnit = QUnit;
+ }
+
+ // For CommonJS with exports, but without module.exports, like Rhino
+ if (typeof exports !== "undefined" && exports) {
+ exports.QUnit = QUnit;
+ }
+
+ if (typeof define === "function" && define.amd) {
+ define(function () {
+ return QUnit;
+ });
+ QUnit.config.autostart = false;
+ }
+
+ // For Web/Service Workers
+ if (self$1 && self$1.WorkerGlobalScope && self$1 instanceof self$1.WorkerGlobalScope) {
+ self$1.QUnit = QUnit;
+ }
+ }
+
+ var SuiteReport = function () {
+ function SuiteReport(name, parentSuite) {
+ classCallCheck(this, SuiteReport);
+
+ this.name = name;
+ this.fullName = parentSuite ? parentSuite.fullName.concat(name) : [];
+
+ this.tests = [];
+ this.childSuites = [];
+
+ if (parentSuite) {
+ parentSuite.pushChildSuite(this);
+ }
+ }
+
+ createClass(SuiteReport, [{
+ key: "start",
+ value: function start(recordTime) {
+ if (recordTime) {
+ this._startTime = Date.now();
+ }
+
+ return {
+ name: this.name,
+ fullName: this.fullName.slice(),
+ tests: this.tests.map(function (test) {
+ return test.start();
+ }),
+ childSuites: this.childSuites.map(function (suite) {
+ return suite.start();
+ }),
+ testCounts: {
+ total: this.getTestCounts().total
+ }
+ };
+ }
+ }, {
+ key: "end",
+ value: function end(recordTime) {
+ if (recordTime) {
+ this._endTime = Date.now();
+ }
+
+ return {
+ name: this.name,
+ fullName: this.fullName.slice(),
+ tests: this.tests.map(function (test) {
+ return test.end();
+ }),
+ childSuites: this.childSuites.map(function (suite) {
+ return suite.end();
+ }),
+ testCounts: this.getTestCounts(),
+ runtime: this.getRuntime(),
+ status: this.getStatus()
+ };
+ }
+ }, {
+ key: "pushChildSuite",
+ value: function pushChildSuite(suite) {
+ this.childSuites.push(suite);
+ }
+ }, {
+ key: "pushTest",
+ value: function pushTest(test) {
+ this.tests.push(test);
+ }
+ }, {
+ key: "getRuntime",
+ value: function getRuntime() {
+ return this._endTime - this._startTime;
+ }
+ }, {
+ key: "getTestCounts",
+ value: function getTestCounts() {
+ var counts = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : { passed: 0, failed: 0, skipped: 0, todo: 0, total: 0 };
+
+ counts = this.tests.reduce(function (counts, test) {
+ if (test.valid) {
+ counts[test.getStatus()]++;
+ counts.total++;
+ }
+
+ return counts;
+ }, counts);
+
+ return this.childSuites.reduce(function (counts, suite) {
+ return suite.getTestCounts(counts);
+ }, counts);
+ }
+ }, {
+ key: "getStatus",
+ value: function getStatus() {
+ var _getTestCounts = this.getTestCounts(),
+ total = _getTestCounts.total,
+ failed = _getTestCounts.failed,
+ skipped = _getTestCounts.skipped,
+ todo = _getTestCounts.todo;
+
+ if (failed) {
+ return "failed";
+ } else {
+ if (skipped === total) {
+ return "skipped";
+ } else if (todo === total) {
+ return "todo";
+ } else {
+ return "passed";
+ }
+ }
+ }
+ }]);
+ return SuiteReport;
+ }();
+
+ // Handle an unhandled exception. By convention, returns true if further
+ // error handling should be suppressed and false otherwise.
+ // In this case, we will only suppress further error handling if the
+ // "ignoreGlobalErrors" configuration option is enabled.
+ function onError(error) {
+ for (var _len = arguments.length, args = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
+ args[_key - 1] = arguments[_key];
+ }
+
+ if (config.current) {
+ if (config.current.ignoreGlobalErrors) {
+ return true;
+ }
+ pushFailure.apply(undefined, [error.message, error.fileName + ":" + error.lineNumber].concat(args));
+ } else {
+ test("global failure", extend(function () {
+ pushFailure.apply(undefined, [error.message, error.fileName + ":" + error.lineNumber].concat(args));
+ }, { validTest: true }));
+ }
+
+ return false;
+ }
+
+ var focused = false;
+ var QUnit = {};
+ var globalSuite = new SuiteReport();
+
+ // The initial "currentModule" represents the global (or top-level) module that
+ // is not explicitly defined by the user, therefore we add the "globalSuite" to
+ // it since each module has a suiteReport associated with it.
+ config.currentModule.suiteReport = globalSuite;
+
+ var moduleStack = [];
+ var globalStartCalled = false;
+ var runStarted = false;
+
+ // Figure out if we're running the tests from a server or not
+ QUnit.isLocal = !(defined.document && window.location.protocol !== "file:");
+
+ // Expose the current QUnit version
+ QUnit.version = "2.4.0";
+
+ function createModule(name, testEnvironment, modifiers) {
+ var parentModule = moduleStack.length ? moduleStack.slice(-1)[0] : null;
+ var moduleName = parentModule !== null ? [parentModule.name, name].join(" > ") : name;
+ var parentSuite = parentModule ? parentModule.suiteReport : globalSuite;
+
+ var skip$$1 = parentModule !== null && parentModule.skip || modifiers.skip;
+ var todo$$1 = parentModule !== null && parentModule.todo || modifiers.todo;
+
+ var module = {
+ name: moduleName,
+ parentModule: parentModule,
+ tests: [],
+ moduleId: generateHash(moduleName),
+ testsRun: 0,
+ unskippedTestsRun: 0,
+ childModules: [],
+ suiteReport: new SuiteReport(name, parentSuite),
+
+ // Pass along `skip` and `todo` properties from parent module, in case
+ // there is one, to childs. And use own otherwise.
+ // This property will be used to mark own tests and tests of child suites
+ // as either `skipped` or `todo`.
+ skip: skip$$1,
+ todo: skip$$1 ? false : todo$$1
+ };
+
+ var env = {};
+ if (parentModule) {
+ parentModule.childModules.push(module);
+ extend(env, parentModule.testEnvironment);
+ }
+ extend(env, testEnvironment);
+ module.testEnvironment = env;
+
+ config.modules.push(module);
+ return module;
+ }
+
+ function processModule(name, options, executeNow) {
+ var modifiers = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
+
+ var module = createModule(name, options, modifiers);
+
+ // Move any hooks to a 'hooks' object
+ var testEnvironment = module.testEnvironment;
+ var hooks = module.hooks = {};
+
+ setHookFromEnvironment(hooks, testEnvironment, "before");
+ setHookFromEnvironment(hooks, testEnvironment, "beforeEach");
+ setHookFromEnvironment(hooks, testEnvironment, "afterEach");
+ setHookFromEnvironment(hooks, testEnvironment, "after");
+
+ function setHookFromEnvironment(hooks, environment, name) {
+ var potentialHook = environment[name];
+ hooks[name] = typeof potentialHook === "function" ? [potentialHook] : [];
+ delete environment[name];
+ }
+
+ var moduleFns = {
+ before: setHookFunction(module, "before"),
+ beforeEach: setHookFunction(module, "beforeEach"),
+ afterEach: setHookFunction(module, "afterEach"),
+ after: setHookFunction(module, "after")
+ };
+
+ var currentModule = config.currentModule;
+ if (objectType(executeNow) === "function") {
+ moduleStack.push(module);
+ config.currentModule = module;
+ executeNow.call(module.testEnvironment, moduleFns);
+ moduleStack.pop();
+ module = module.parentModule || currentModule;
+ }
+
+ config.currentModule = module;
+ }
+
+ // TODO: extract this to a new file alongside its related functions
+ function module$1(name, options, executeNow) {
+ if (focused) {
+ return;
+ }
+
+ if (arguments.length === 2) {
+ if (objectType(options) === "function") {
+ executeNow = options;
+ options = undefined;
+ }
+ }
+
+ processModule(name, options, executeNow);
+ }
+
+ module$1.only = function () {
+ if (focused) {
+ return;
+ }
+
+ config.modules.length = 0;
+ config.queue.length = 0;
+
+ module$1.apply(undefined, arguments);
+
+ focused = true;
+ };
+
+ module$1.skip = function (name, options, executeNow) {
+ if (focused) {
+ return;
+ }
+
+ if (arguments.length === 2) {
+ if (objectType(options) === "function") {
+ executeNow = options;
+ options = undefined;
+ }
+ }
+
+ processModule(name, options, executeNow, { skip: true });
+ };
+
+ module$1.todo = function (name, options, executeNow) {
+ if (focused) {
+ return;
+ }
+
+ if (arguments.length === 2) {
+ if (objectType(options) === "function") {
+ executeNow = options;
+ options = undefined;
+ }
+ }
+
+ processModule(name, options, executeNow, { todo: true });
+ };
+
+ extend(QUnit, {
+ on: on,
+
+ module: module$1,
+
+ test: test,
+
+ todo: todo,
+
+ skip: skip,
+
+ only: only,
+
+ start: function start(count) {
+ var globalStartAlreadyCalled = globalStartCalled;
+
+ if (!config.current) {
+ globalStartCalled = true;
+
+ if (runStarted) {
+ throw new Error("Called start() while test already started running");
+ } else if (globalStartAlreadyCalled || count > 1) {
+ throw new Error("Called start() outside of a test context too many times");
+ } else if (config.autostart) {
+ throw new Error("Called start() outside of a test context when " + "QUnit.config.autostart was true");
+ } else if (!config.pageLoaded) {
+
+ // The page isn't completely loaded yet, so we set autostart and then
+ // load if we're in Node or wait for the browser's load event.
+ config.autostart = true;
+
+ // Starts from Node even if .load was not previously called. We still return
+ // early otherwise we'll wind up "beginning" twice.
+ if (!defined.document) {
+ QUnit.load();
+ }
+
+ return;
+ }
+ } else {
+ throw new Error("QUnit.start cannot be called inside a test context.");
+ }
+
+ scheduleBegin();
+ },
+
+ config: config,
+
+ is: is,
+
+ objectType: objectType,
+
+ extend: extend,
+
+ load: function load() {
+ config.pageLoaded = true;
+
+ // Initialize the configuration options
+ extend(config, {
+ stats: { all: 0, bad: 0 },
+ started: 0,
+ updateRate: 1000,
+ autostart: true,
+ filter: ""
+ }, true);
+
+ if (!runStarted) {
+ config.blocking = false;
+
+ if (config.autostart) {
+ scheduleBegin();
+ }
+ }
+ },
+
+ stack: function stack(offset) {
+ offset = (offset || 0) + 2;
+ return sourceFromStacktrace(offset);
+ },
+
+ onError: onError
+ });
+
+ QUnit.pushFailure = pushFailure;
+ QUnit.assert = Assert.prototype;
+ QUnit.equiv = equiv;
+ QUnit.dump = dump;
+
+ registerLoggingCallbacks(QUnit);
+
+ function scheduleBegin() {
+
+ runStarted = true;
+
+ // Add a slight delay to allow definition of more modules and tests.
+ if (defined.setTimeout) {
+ setTimeout(function () {
+ begin();
+ }, 13);
+ } else {
+ begin();
+ }
+ }
+
+ function begin() {
+ var i,
+ l,
+ modulesLog = [];
+
+ // If the test run hasn't officially begun yet
+ if (!config.started) {
+
+ // Record the time of the test run's beginning
+ config.started = now();
+
+ // Delete the loose unnamed module if unused.
+ if (config.modules[0].name === "" && config.modules[0].tests.length === 0) {
+ config.modules.shift();
+ }
+
+ // Avoid unnecessary information by not logging modules' test environments
+ for (i = 0, l = config.modules.length; i < l; i++) {
+ modulesLog.push({
+ name: config.modules[i].name,
+ tests: config.modules[i].tests
+ });
+ }
+
+ // The test run is officially beginning now
+ emit("runStart", globalSuite.start(true));
+ runLoggingCallbacks("begin", {
+ totalTests: Test.count,
+ modules: modulesLog
+ });
+ }
+
+ config.blocking = false;
+ ProcessingQueue.advance();
+ }
+
+ function setHookFunction(module, hookName) {
+ return function setHook(callback) {
+ module.hooks[hookName].push(callback);
+ };
+ }
+
+ exportQUnit(QUnit);
+
+ (function () {
+
+ if (typeof window === "undefined" || typeof document === "undefined") {
+ return;
+ }
+
+ var config = QUnit.config,
+ hasOwn = Object.prototype.hasOwnProperty;
+
+ // Stores fixture HTML for resetting later
+ function storeFixture() {
+
+ // Avoid overwriting user-defined values
+ if (hasOwn.call(config, "fixture")) {
+ return;
+ }
+
+ var fixture = document.getElementById("qunit-fixture");
+ if (fixture) {
+ config.fixture = fixture.innerHTML;
+ }
+ }
+
+ QUnit.begin(storeFixture);
+
+ // Resets the fixture DOM element if available.
+ function resetFixture() {
+ if (config.fixture == null) {
+ return;
+ }
+
+ var fixture = document.getElementById("qunit-fixture");
+ if (fixture) {
+ fixture.innerHTML = config.fixture;
+ }
+ }
+
+ QUnit.testStart(resetFixture);
+ })();
+
+ (function () {
+
+ // Only interact with URLs via window.location
+ var location = typeof window !== "undefined" && window.location;
+ if (!location) {
+ return;
+ }
+
+ var urlParams = getUrlParams();
+
+ QUnit.urlParams = urlParams;
+
+ // Match module/test by inclusion in an array
+ QUnit.config.moduleId = [].concat(urlParams.moduleId || []);
+ QUnit.config.testId = [].concat(urlParams.testId || []);
+
+ // Exact case-insensitive match of the module name
+ QUnit.config.module = urlParams.module;
+
+ // Regular expression or case-insenstive substring match against "moduleName: testName"
+ QUnit.config.filter = urlParams.filter;
+
+ // Test order randomization
+ if (urlParams.seed === true) {
+
+ // Generate a random seed if the option is specified without a value
+ QUnit.config.seed = Math.random().toString(36).slice(2);
+ } else if (urlParams.seed) {
+ QUnit.config.seed = urlParams.seed;
+ }
+
+ // Add URL-parameter-mapped config values with UI form rendering data
+ QUnit.config.urlConfig.push({
+ id: "hidepassed",
+ label: "Hide passed tests",
+ tooltip: "Only show tests and assertions that fail. Stored as query-strings."
+ }, {
+ id: "noglobals",
+ label: "Check for Globals",
+ tooltip: "Enabling this will test if any test introduces new properties on the " + "global object (`window` in Browsers). Stored as query-strings."
+ }, {
+ id: "notrycatch",
+ label: "No try-catch",
+ tooltip: "Enabling this will run tests outside of a try-catch block. Makes debugging " + "exceptions in IE reasonable. Stored as query-strings."
+ });
+
+ QUnit.begin(function () {
+ var i,
+ option,
+ urlConfig = QUnit.config.urlConfig;
+
+ for (i = 0; i < urlConfig.length; i++) {
+
+ // Options can be either strings or objects with nonempty "id" properties
+ option = QUnit.config.urlConfig[i];
+ if (typeof option !== "string") {
+ option = option.id;
+ }
+
+ if (QUnit.config[option] === undefined) {
+ QUnit.config[option] = urlParams[option];
+ }
+ }
+ });
+
+ function getUrlParams() {
+ var i, param, name, value;
+ var urlParams = Object.create(null);
+ var params = location.search.slice(1).split("&");
+ var length = params.length;
+
+ for (i = 0; i < length; i++) {
+ if (params[i]) {
+ param = params[i].split("=");
+ name = decodeQueryParam(param[0]);
+
+ // Allow just a key to turn on a flag, e.g., test.html?noglobals
+ value = param.length === 1 || decodeQueryParam(param.slice(1).join("="));
+ if (name in urlParams) {
+ urlParams[name] = [].concat(urlParams[name], value);
+ } else {
+ urlParams[name] = value;
+ }
+ }
+ }
+
+ return urlParams;
+ }
+
+ function decodeQueryParam(param) {
+ return decodeURIComponent(param.replace(/\+/g, "%20"));
+ }
+ })();
+
+ var stats = {
+ passedTests: 0,
+ failedTests: 0,
+ skippedTests: 0,
+ todoTests: 0
+ };
+
+ // Escape text for attribute or text content.
+ function escapeText(s) {
+ if (!s) {
+ return "";
+ }
+ s = s + "";
+
+ // Both single quotes and double quotes (for attributes)
+ return s.replace(/['"<>&]/g, function (s) {
+ switch (s) {
+ case "'":
+ return "&#039;";
+ case "\"":
+ return "&quot;";
+ case "<":
+ return "&lt;";
+ case ">":
+ return "&gt;";
+ case "&":
+ return "&amp;";
+ }
+ });
+ }
+
+ (function () {
+
+ // Don't load the HTML Reporter on non-browser environments
+ if (typeof window === "undefined" || !window.document) {
+ return;
+ }
+
+ var config = QUnit.config,
+ document$$1 = window.document,
+ collapseNext = false,
+ hasOwn = Object.prototype.hasOwnProperty,
+ unfilteredUrl = setUrl({ filter: undefined, module: undefined,
+ moduleId: undefined, testId: undefined }),
+ modulesList = [];
+
+ function addEvent(elem, type, fn) {
+ elem.addEventListener(type, fn, false);
+ }
+
+ function removeEvent(elem, type, fn) {
+ elem.removeEventListener(type, fn, false);
+ }
+
+ function addEvents(elems, type, fn) {
+ var i = elems.length;
+ while (i--) {
+ addEvent(elems[i], type, fn);
+ }
+ }
+
+ function hasClass(elem, name) {
+ return (" " + elem.className + " ").indexOf(" " + name + " ") >= 0;
+ }
+
+ function addClass(elem, name) {
+ if (!hasClass(elem, name)) {
+ elem.className += (elem.className ? " " : "") + name;
+ }
+ }
+
+ function toggleClass(elem, name, force) {
+ if (force || typeof force === "undefined" && !hasClass(elem, name)) {
+ addClass(elem, name);
+ } else {
+ removeClass(elem, name);
+ }
+ }
+
+ function removeClass(elem, name) {
+ var set = " " + elem.className + " ";
+
+ // Class name may appear multiple times
+ while (set.indexOf(" " + name + " ") >= 0) {
+ set = set.replace(" " + name + " ", " ");
+ }
+
+ // Trim for prettiness
+ elem.className = typeof set.trim === "function" ? set.trim() : set.replace(/^\s+|\s+$/g, "");
+ }
+
+ function id(name) {
+ return document$$1.getElementById && document$$1.getElementById(name);
+ }
+
+ function abortTests() {
+ var abortButton = id("qunit-abort-tests-button");
+ if (abortButton) {
+ abortButton.disabled = true;
+ abortButton.innerHTML = "Aborting...";
+ }
+ QUnit.config.queue.length = 0;
+ return false;
+ }
+
+ function interceptNavigation(ev) {
+ applyUrlParams();
+
+ if (ev && ev.preventDefault) {
+ ev.preventDefault();
+ }
+
+ return false;
+ }
+
+ function getUrlConfigHtml() {
+ var i,
+ j,
+ val,
+ escaped,
+ escapedTooltip,
+ selection = false,
+ urlConfig = config.urlConfig,
+ urlConfigHtml = "";
+
+ for (i = 0; i < urlConfig.length; i++) {
+
+ // Options can be either strings or objects with nonempty "id" properties
+ val = config.urlConfig[i];
+ if (typeof val === "string") {
+ val = {
+ id: val,
+ label: val
+ };
+ }
+
+ escaped = escapeText(val.id);
+ escapedTooltip = escapeText(val.tooltip);
+
+ if (!val.value || typeof val.value === "string") {
+ urlConfigHtml += "<label for='qunit-urlconfig-" + escaped + "' title='" + escapedTooltip + "'><input id='qunit-urlconfig-" + escaped + "' name='" + escaped + "' type='checkbox'" + (val.value ? " value='" + escapeText(val.value) + "'" : "") + (config[val.id] ? " checked='checked'" : "") + " title='" + escapedTooltip + "' />" + escapeText(val.label) + "</label>";
+ } else {
+ urlConfigHtml += "<label for='qunit-urlconfig-" + escaped + "' title='" + escapedTooltip + "'>" + val.label + ": </label><select id='qunit-urlconfig-" + escaped + "' name='" + escaped + "' title='" + escapedTooltip + "'><option></option>";
+
+ if (QUnit.is("array", val.value)) {
+ for (j = 0; j < val.value.length; j++) {
+ escaped = escapeText(val.value[j]);
+ urlConfigHtml += "<option value='" + escaped + "'" + (config[val.id] === val.value[j] ? (selection = true) && " selected='selected'" : "") + ">" + escaped + "</option>";
+ }
+ } else {
+ for (j in val.value) {
+ if (hasOwn.call(val.value, j)) {
+ urlConfigHtml += "<option value='" + escapeText(j) + "'" + (config[val.id] === j ? (selection = true) && " selected='selected'" : "") + ">" + escapeText(val.value[j]) + "</option>";
+ }
+ }
+ }
+ if (config[val.id] && !selection) {
+ escaped = escapeText(config[val.id]);
+ urlConfigHtml += "<option value='" + escaped + "' selected='selected' disabled='disabled'>" + escaped + "</option>";
+ }
+ urlConfigHtml += "</select>";
+ }
+ }
+
+ return urlConfigHtml;
+ }
+
+ // Handle "click" events on toolbar checkboxes and "change" for select menus.
+ // Updates the URL with the new state of `config.urlConfig` values.
+ function toolbarChanged() {
+ var updatedUrl,
+ value,
+ tests,
+ field = this,
+ params = {};
+
+ // Detect if field is a select menu or a checkbox
+ if ("selectedIndex" in field) {
+ value = field.options[field.selectedIndex].value || undefined;
+ } else {
+ value = field.checked ? field.defaultValue || true : undefined;
+ }
+
+ params[field.name] = value;
+ updatedUrl = setUrl(params);
+
+ // Check if we can apply the change without a page refresh
+ if ("hidepassed" === field.name && "replaceState" in window.history) {
+ QUnit.urlParams[field.name] = value;
+ config[field.name] = value || false;
+ tests = id("qunit-tests");
+ if (tests) {
+ toggleClass(tests, "hidepass", value || false);
+ }
+ window.history.replaceState(null, "", updatedUrl);
+ } else {
+ window.location = updatedUrl;
+ }
+ }
+
+ function setUrl(params) {
+ var key,
+ arrValue,
+ i,
+ querystring = "?",
+ location = window.location;
+
+ params = QUnit.extend(QUnit.extend({}, QUnit.urlParams), params);
+
+ for (key in params) {
+
+ // Skip inherited or undefined properties
+ if (hasOwn.call(params, key) && params[key] !== undefined) {
+
+ // Output a parameter for each value of this key (but usually just one)
+ arrValue = [].concat(params[key]);
+ for (i = 0; i < arrValue.length; i++) {
+ querystring += encodeURIComponent(key);
+ if (arrValue[i] !== true) {
+ querystring += "=" + encodeURIComponent(arrValue[i]);
+ }
+ querystring += "&";
+ }
+ }
+ }
+ return location.protocol + "//" + location.host + location.pathname + querystring.slice(0, -1);
+ }
+
+ function applyUrlParams() {
+ var i,
+ selectedModules = [],
+ modulesList = id("qunit-modulefilter-dropdown-list").getElementsByTagName("input"),
+ filter = id("qunit-filter-input").value;
+
+ for (i = 0; i < modulesList.length; i++) {
+ if (modulesList[i].checked) {
+ selectedModules.push(modulesList[i].value);
+ }
+ }
+
+ window.location = setUrl({
+ filter: filter === "" ? undefined : filter,
+ moduleId: selectedModules.length === 0 ? undefined : selectedModules,
+
+ // Remove module and testId filter
+ module: undefined,
+ testId: undefined
+ });
+ }
+
+ function toolbarUrlConfigContainer() {
+ var urlConfigContainer = document$$1.createElement("span");
+
+ urlConfigContainer.innerHTML = getUrlConfigHtml();
+ addClass(urlConfigContainer, "qunit-url-config");
+
+ addEvents(urlConfigContainer.getElementsByTagName("input"), "change", toolbarChanged);
+ addEvents(urlConfigContainer.getElementsByTagName("select"), "change", toolbarChanged);
+
+ return urlConfigContainer;
+ }
+
+ function abortTestsButton() {
+ var button = document$$1.createElement("button");
+ button.id = "qunit-abort-tests-button";
+ button.innerHTML = "Abort";
+ addEvent(button, "click", abortTests);
+ return button;
+ }
+
+ function toolbarLooseFilter() {
+ var filter = document$$1.createElement("form"),
+ label = document$$1.createElement("label"),
+ input = document$$1.createElement("input"),
+ button = document$$1.createElement("button");
+
+ addClass(filter, "qunit-filter");
+
+ label.innerHTML = "Filter: ";
+
+ input.type = "text";
+ input.value = config.filter || "";
+ input.name = "filter";
+ input.id = "qunit-filter-input";
+
+ button.innerHTML = "Go";
+
+ label.appendChild(input);
+
+ filter.appendChild(label);
+ filter.appendChild(document$$1.createTextNode(" "));
+ filter.appendChild(button);
+ addEvent(filter, "submit", interceptNavigation);
+
+ return filter;
+ }
+
+ function moduleListHtml() {
+ var i,
+ checked,
+ html = "";
+
+ for (i = 0; i < config.modules.length; i++) {
+ if (config.modules[i].name !== "") {
+ checked = config.moduleId.indexOf(config.modules[i].moduleId) > -1;
+ html += "<li><label class='clickable" + (checked ? " checked" : "") + "'><input type='checkbox' " + "value='" + config.modules[i].moduleId + "'" + (checked ? " checked='checked'" : "") + " />" + escapeText(config.modules[i].name) + "</label></li>";
+ }
+ }
+
+ return html;
+ }
+
+ function toolbarModuleFilter() {
+ var allCheckbox,
+ commit,
+ reset,
+ moduleFilter = document$$1.createElement("form"),
+ label = document$$1.createElement("label"),
+ moduleSearch = document$$1.createElement("input"),
+ dropDown = document$$1.createElement("div"),
+ actions = document$$1.createElement("span"),
+ dropDownList = document$$1.createElement("ul"),
+ dirty = false;
+
+ moduleSearch.id = "qunit-modulefilter-search";
+ addEvent(moduleSearch, "input", searchInput);
+ addEvent(moduleSearch, "input", searchFocus);
+ addEvent(moduleSearch, "focus", searchFocus);
+ addEvent(moduleSearch, "click", searchFocus);
+
+ label.id = "qunit-modulefilter-search-container";
+ label.innerHTML = "Module: ";
+ label.appendChild(moduleSearch);
+
+ actions.id = "qunit-modulefilter-actions";
+ actions.innerHTML = "<button style='display:none'>Apply</button>" + "<button type='reset' style='display:none'>Reset</button>" + "<label class='clickable" + (config.moduleId.length ? "" : " checked") + "'><input type='checkbox'" + (config.moduleId.length ? "" : " checked='checked'") + ">All modules</label>";
+ allCheckbox = actions.lastChild.firstChild;
+ commit = actions.firstChild;
+ reset = commit.nextSibling;
+ addEvent(commit, "click", applyUrlParams);
+
+ dropDownList.id = "qunit-modulefilter-dropdown-list";
+ dropDownList.innerHTML = moduleListHtml();
+
+ dropDown.id = "qunit-modulefilter-dropdown";
+ dropDown.style.display = "none";
+ dropDown.appendChild(actions);
+ dropDown.appendChild(dropDownList);
+ addEvent(dropDown, "change", selectionChange);
+ selectionChange();
+
+ moduleFilter.id = "qunit-modulefilter";
+ moduleFilter.appendChild(label);
+ moduleFilter.appendChild(dropDown);
+ addEvent(moduleFilter, "submit", interceptNavigation);
+ addEvent(moduleFilter, "reset", function () {
+
+ // Let the reset happen, then update styles
+ window.setTimeout(selectionChange);
+ });
+
+ // Enables show/hide for the dropdown
+ function searchFocus() {
+ if (dropDown.style.display !== "none") {
+ return;
+ }
+
+ dropDown.style.display = "block";
+ addEvent(document$$1, "click", hideHandler);
+ addEvent(document$$1, "keydown", hideHandler);
+
+ // Hide on Escape keydown or outside-container click
+ function hideHandler(e) {
+ var inContainer = moduleFilter.contains(e.target);
+
+ if (e.keyCode === 27 || !inContainer) {
+ if (e.keyCode === 27 && inContainer) {
+ moduleSearch.focus();
+ }
+ dropDown.style.display = "none";
+ removeEvent(document$$1, "click", hideHandler);
+ removeEvent(document$$1, "keydown", hideHandler);
+ moduleSearch.value = "";
+ searchInput();
+ }
+ }
+ }
+
+ // Processes module search box input
+ function searchInput() {
+ var i,
+ item,
+ searchText = moduleSearch.value.toLowerCase(),
+ listItems = dropDownList.children;
+
+ for (i = 0; i < listItems.length; i++) {
+ item = listItems[i];
+ if (!searchText || item.textContent.toLowerCase().indexOf(searchText) > -1) {
+ item.style.display = "";
+ } else {
+ item.style.display = "none";
+ }
+ }
+ }
+
+ // Processes selection changes
+ function selectionChange(evt) {
+ var i,
+ item,
+ checkbox = evt && evt.target || allCheckbox,
+ modulesList = dropDownList.getElementsByTagName("input"),
+ selectedNames = [];
+
+ toggleClass(checkbox.parentNode, "checked", checkbox.checked);
+
+ dirty = false;
+ if (checkbox.checked && checkbox !== allCheckbox) {
+ allCheckbox.checked = false;
+ removeClass(allCheckbox.parentNode, "checked");
+ }
+ for (i = 0; i < modulesList.length; i++) {
+ item = modulesList[i];
+ if (!evt) {
+ toggleClass(item.parentNode, "checked", item.checked);
+ } else if (checkbox === allCheckbox && checkbox.checked) {
+ item.checked = false;
+ removeClass(item.parentNode, "checked");
+ }
+ dirty = dirty || item.checked !== item.defaultChecked;
+ if (item.checked) {
+ selectedNames.push(item.parentNode.textContent);
+ }
+ }
+
+ commit.style.display = reset.style.display = dirty ? "" : "none";
+ moduleSearch.placeholder = selectedNames.join(", ") || allCheckbox.parentNode.textContent;
+ moduleSearch.title = "Type to filter list. Current selection:\n" + (selectedNames.join("\n") || allCheckbox.parentNode.textContent);
+ }
+
+ return moduleFilter;
+ }
+
+ function appendToolbar() {
+ var toolbar = id("qunit-testrunner-toolbar");
+
+ if (toolbar) {
+ toolbar.appendChild(toolbarUrlConfigContainer());
+ toolbar.appendChild(toolbarModuleFilter());
+ toolbar.appendChild(toolbarLooseFilter());
+ toolbar.appendChild(document$$1.createElement("div")).className = "clearfix";
+ }
+ }
+
+ function appendHeader() {
+ var header = id("qunit-header");
+
+ if (header) {
+ header.innerHTML = "<a href='" + escapeText(unfilteredUrl) + "'>" + header.innerHTML + "</a> ";
+ }
+ }
+
+ function appendBanner() {
+ var banner = id("qunit-banner");
+
+ if (banner) {
+ banner.className = "";
+ }
+ }
+
+ function appendTestResults() {
+ var tests = id("qunit-tests"),
+ result = id("qunit-testresult"),
+ controls;
+
+ if (result) {
+ result.parentNode.removeChild(result);
+ }
+
+ if (tests) {
+ tests.innerHTML = "";
+ result = document$$1.createElement("p");
+ result.id = "qunit-testresult";
+ result.className = "result";
+ tests.parentNode.insertBefore(result, tests);
+ result.innerHTML = "<div id=\"qunit-testresult-display\">Running...<br />&#160;</div>" + "<div id=\"qunit-testresult-controls\"></div>" + "<div class=\"clearfix\"></div>";
+ controls = id("qunit-testresult-controls");
+ }
+
+ if (controls) {
+ controls.appendChild(abortTestsButton());
+ }
+ }
+
+ function appendFilteredTest() {
+ var testId = QUnit.config.testId;
+ if (!testId || testId.length <= 0) {
+ return "";
+ }
+ return "<div id='qunit-filteredTest'>Rerunning selected tests: " + escapeText(testId.join(", ")) + " <a id='qunit-clearFilter' href='" + escapeText(unfilteredUrl) + "'>Run all tests</a></div>";
+ }
+
+ function appendUserAgent() {
+ var userAgent = id("qunit-userAgent");
+
+ if (userAgent) {
+ userAgent.innerHTML = "";
+ userAgent.appendChild(document$$1.createTextNode("QUnit " + QUnit.version + "; " + navigator.userAgent));
+ }
+ }
+
+ function appendInterface() {
+ var qunit = id("qunit");
+
+ if (qunit) {
+ qunit.innerHTML = "<h1 id='qunit-header'>" + escapeText(document$$1.title) + "</h1>" + "<h2 id='qunit-banner'></h2>" + "<div id='qunit-testrunner-toolbar'></div>" + appendFilteredTest() + "<h2 id='qunit-userAgent'></h2>" + "<ol id='qunit-tests'></ol>";
+ }
+
+ appendHeader();
+ appendBanner();
+ appendTestResults();
+ appendUserAgent();
+ appendToolbar();
+ }
+
+ function appendTestsList(modules) {
+ var i, l, x, z, test, moduleObj;
+
+ for (i = 0, l = modules.length; i < l; i++) {
+ moduleObj = modules[i];
+
+ for (x = 0, z = moduleObj.tests.length; x < z; x++) {
+ test = moduleObj.tests[x];
+
+ appendTest(test.name, test.testId, moduleObj.name);
+ }
+ }
+ }
+
+ function appendTest(name, testId, moduleName) {
+ var title,
+ rerunTrigger,
+ testBlock,
+ assertList,
+ tests = id("qunit-tests");
+
+ if (!tests) {
+ return;
+ }
+
+ title = document$$1.createElement("strong");
+ title.innerHTML = getNameHtml(name, moduleName);
+
+ rerunTrigger = document$$1.createElement("a");
+ rerunTrigger.innerHTML = "Rerun";
+ rerunTrigger.href = setUrl({ testId: testId });
+
+ testBlock = document$$1.createElement("li");
+ testBlock.appendChild(title);
+ testBlock.appendChild(rerunTrigger);
+ testBlock.id = "qunit-test-output-" + testId;
+
+ assertList = document$$1.createElement("ol");
+ assertList.className = "qunit-assert-list";
+
+ testBlock.appendChild(assertList);
+
+ tests.appendChild(testBlock);
+ }
+
+ // HTML Reporter initialization and load
+ QUnit.begin(function (details) {
+ var i, moduleObj, tests;
+
+ // Sort modules by name for the picker
+ for (i = 0; i < details.modules.length; i++) {
+ moduleObj = details.modules[i];
+ if (moduleObj.name) {
+ modulesList.push(moduleObj.name);
+ }
+ }
+ modulesList.sort(function (a, b) {
+ return a.localeCompare(b);
+ });
+
+ // Initialize QUnit elements
+ appendInterface();
+ appendTestsList(details.modules);
+ tests = id("qunit-tests");
+ if (tests && config.hidepassed) {
+ addClass(tests, "hidepass");
+ }
+ });
+
+ QUnit.done(function (details) {
+ var banner = id("qunit-banner"),
+ tests = id("qunit-tests"),
+ abortButton = id("qunit-abort-tests-button"),
+ totalTests = stats.passedTests + stats.skippedTests + stats.todoTests + stats.failedTests,
+ html = [totalTests, " tests completed in ", details.runtime, " milliseconds, with ", stats.failedTests, " failed, ", stats.skippedTests, " skipped, and ", stats.todoTests, " todo.<br />", "<span class='passed'>", details.passed, "</span> assertions of <span class='total'>", details.total, "</span> passed, <span class='failed'>", details.failed, "</span> failed."].join(""),
+ test,
+ assertLi,
+ assertList;
+
+ // Update remaing tests to aborted
+ if (abortButton && abortButton.disabled) {
+ html = "Tests aborted after " + details.runtime + " milliseconds.";
+
+ for (var i = 0; i < tests.children.length; i++) {
+ test = tests.children[i];
+ if (test.className === "" || test.className === "running") {
+ test.className = "aborted";
+ assertList = test.getElementsByTagName("ol")[0];
+ assertLi = document$$1.createElement("li");
+ assertLi.className = "fail";
+ assertLi.innerHTML = "Test aborted.";
+ assertList.appendChild(assertLi);
+ }
+ }
+ }
+
+ if (banner && (!abortButton || abortButton.disabled === false)) {
+ banner.className = stats.failedTests ? "qunit-fail" : "qunit-pass";
+ }
+
+ if (abortButton) {
+ abortButton.parentNode.removeChild(abortButton);
+ }
+
+ if (tests) {
+ id("qunit-testresult-display").innerHTML = html;
+ }
+
+ if (config.altertitle && document$$1.title) {
+
+ // Show ✖ for good, ✔ for bad suite result in title
+ // use escape sequences in case file gets loaded with non-utf-8-charset
+ document$$1.title = [stats.failedTests ? "\u2716" : "\u2714", document$$1.title.replace(/^[\u2714\u2716] /i, "")].join(" ");
+ }
+
+ // Scroll back to top to show results
+ if (config.scrolltop && window.scrollTo) {
+ window.scrollTo(0, 0);
+ }
+ });
+
+ function getNameHtml(name, module) {
+ var nameHtml = "";
+
+ if (module) {
+ nameHtml = "<span class='module-name'>" + escapeText(module) + "</span>: ";
+ }
+
+ nameHtml += "<span class='test-name'>" + escapeText(name) + "</span>";
+
+ return nameHtml;
+ }
+
+ QUnit.testStart(function (details) {
+ var running, testBlock, bad;
+
+ testBlock = id("qunit-test-output-" + details.testId);
+ if (testBlock) {
+ testBlock.className = "running";
+ } else {
+
+ // Report later registered tests
+ appendTest(details.name, details.testId, details.module);
+ }
+
+ running = id("qunit-testresult-display");
+ if (running) {
+ bad = QUnit.config.reorder && details.previousFailure;
+
+ running.innerHTML = (bad ? "Rerunning previously failed test: <br />" : "Running: <br />") + getNameHtml(details.name, details.module);
+ }
+ });
+
+ function stripHtml(string) {
+
+ // Strip tags, html entity and whitespaces
+ return string.replace(/<\/?[^>]+(>|$)/g, "").replace(/\&quot;/g, "").replace(/\s+/g, "");
+ }
+
+ QUnit.log(function (details) {
+ var assertList,
+ assertLi,
+ message,
+ expected,
+ actual,
+ diff,
+ showDiff = false,
+ testItem = id("qunit-test-output-" + details.testId);
+
+ if (!testItem) {
+ return;
+ }
+
+ message = escapeText(details.message) || (details.result ? "okay" : "failed");
+ message = "<span class='test-message'>" + message + "</span>";
+ message += "<span class='runtime'>@ " + details.runtime + " ms</span>";
+
+ // The pushFailure doesn't provide details.expected
+ // when it calls, it's implicit to also not show expected and diff stuff
+ // Also, we need to check details.expected existence, as it can exist and be undefined
+ if (!details.result && hasOwn.call(details, "expected")) {
+ if (details.negative) {
+ expected = "NOT " + QUnit.dump.parse(details.expected);
+ } else {
+ expected = QUnit.dump.parse(details.expected);
+ }
+
+ actual = QUnit.dump.parse(details.actual);
+ message += "<table><tr class='test-expected'><th>Expected: </th><td><pre>" + escapeText(expected) + "</pre></td></tr>";
+
+ if (actual !== expected) {
+
+ message += "<tr class='test-actual'><th>Result: </th><td><pre>" + escapeText(actual) + "</pre></td></tr>";
+
+ if (typeof details.actual === "number" && typeof details.expected === "number") {
+ if (!isNaN(details.actual) && !isNaN(details.expected)) {
+ showDiff = true;
+ diff = details.actual - details.expected;
+ diff = (diff > 0 ? "+" : "") + diff;
+ }
+ } else if (typeof details.actual !== "boolean" && typeof details.expected !== "boolean") {
+ diff = QUnit.diff(expected, actual);
+
+ // don't show diff if there is zero overlap
+ showDiff = stripHtml(diff).length !== stripHtml(expected).length + stripHtml(actual).length;
+ }
+
+ if (showDiff) {
+ message += "<tr class='test-diff'><th>Diff: </th><td><pre>" + diff + "</pre></td></tr>";
+ }
+ } else if (expected.indexOf("[object Array]") !== -1 || expected.indexOf("[object Object]") !== -1) {
+ message += "<tr class='test-message'><th>Message: </th><td>" + "Diff suppressed as the depth of object is more than current max depth (" + QUnit.config.maxDepth + ").<p>Hint: Use <code>QUnit.dump.maxDepth</code> to " + " run with a higher max depth or <a href='" + escapeText(setUrl({ maxDepth: -1 })) + "'>" + "Rerun</a> without max depth.</p></td></tr>";
+ } else {
+ message += "<tr class='test-message'><th>Message: </th><td>" + "Diff suppressed as the expected and actual results have an equivalent" + " serialization</td></tr>";
+ }
+
+ if (details.source) {
+ message += "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText(details.source) + "</pre></td></tr>";
+ }
+
+ message += "</table>";
+
+ // This occurs when pushFailure is set and we have an extracted stack trace
+ } else if (!details.result && details.source) {
+ message += "<table>" + "<tr class='test-source'><th>Source: </th><td><pre>" + escapeText(details.source) + "</pre></td></tr>" + "</table>";
+ }
+
+ assertList = testItem.getElementsByTagName("ol")[0];
+
+ assertLi = document$$1.createElement("li");
+ assertLi.className = details.result ? "pass" : "fail";
+ assertLi.innerHTML = message;
+ assertList.appendChild(assertLi);
+ });
+
+ QUnit.testDone(function (details) {
+ var testTitle,
+ time,
+ testItem,
+ assertList,
+ good,
+ bad,
+ testCounts,
+ skipped,
+ sourceName,
+ tests = id("qunit-tests");
+
+ if (!tests) {
+ return;
+ }
+
+ testItem = id("qunit-test-output-" + details.testId);
+
+ assertList = testItem.getElementsByTagName("ol")[0];
+
+ good = details.passed;
+ bad = details.failed;
+
+ // This test passed if it has no unexpected failed assertions
+ var testPassed = details.failed > 0 ? details.todo : !details.todo;
+
+ if (testPassed) {
+
+ // Collapse the passing tests
+ addClass(assertList, "qunit-collapsed");
+ } else if (config.collapse) {
+ if (!collapseNext) {
+
+ // Skip collapsing the first failing test
+ collapseNext = true;
+ } else {
+
+ // Collapse remaining tests
+ addClass(assertList, "qunit-collapsed");
+ }
+ }
+
+ // The testItem.firstChild is the test name
+ testTitle = testItem.firstChild;
+
+ testCounts = bad ? "<b class='failed'>" + bad + "</b>, " + "<b class='passed'>" + good + "</b>, " : "";
+
+ testTitle.innerHTML += " <b class='counts'>(" + testCounts + details.assertions.length + ")</b>";
+
+ if (details.skipped) {
+ stats.skippedTests++;
+
+ testItem.className = "skipped";
+ skipped = document$$1.createElement("em");
+ skipped.className = "qunit-skipped-label";
+ skipped.innerHTML = "skipped";
+ testItem.insertBefore(skipped, testTitle);
+ } else {
+ addEvent(testTitle, "click", function () {
+ toggleClass(assertList, "qunit-collapsed");
+ });
+
+ testItem.className = testPassed ? "pass" : "fail";
+
+ if (details.todo) {
+ var todoLabel = document$$1.createElement("em");
+ todoLabel.className = "qunit-todo-label";
+ todoLabel.innerHTML = "todo";
+ testItem.className += " todo";
+ testItem.insertBefore(todoLabel, testTitle);
+ }
+
+ time = document$$1.createElement("span");
+ time.className = "runtime";
+ time.innerHTML = details.runtime + " ms";
+ testItem.insertBefore(time, assertList);
+
+ if (!testPassed) {
+ stats.failedTests++;
+ } else if (details.todo) {
+ stats.todoTests++;
+ } else {
+ stats.passedTests++;
+ }
+ }
+
+ // Show the source of the test when showing assertions
+ if (details.source) {
+ sourceName = document$$1.createElement("p");
+ sourceName.innerHTML = "<strong>Source: </strong>" + details.source;
+ addClass(sourceName, "qunit-source");
+ if (testPassed) {
+ addClass(sourceName, "qunit-collapsed");
+ }
+ addEvent(testTitle, "click", function () {
+ toggleClass(sourceName, "qunit-collapsed");
+ });
+ testItem.appendChild(sourceName);
+ }
+ });
+
+ // Avoid readyState issue with phantomjs
+ // Ref: #818
+ var notPhantom = function (p) {
+ return !(p && p.version && p.version.major > 0);
+ }(window.phantom);
+
+ if (notPhantom && document$$1.readyState === "complete") {
+ QUnit.load();
+ } else {
+ addEvent(window, "load", QUnit.load);
+ }
+
+ // Wrap window.onerror. We will call the original window.onerror to see if
+ // the existing handler fully handles the error; if not, we will call the
+ // QUnit.onError function.
+ var originalWindowOnError = window.onerror;
+
+ // Cover uncaught exceptions
+ // Returning true will suppress the default browser handler,
+ // returning false will let it run.
+ window.onerror = function (message, fileName, lineNumber) {
+ var ret = false;
+ if (originalWindowOnError) {
+ for (var _len = arguments.length, args = Array(_len > 3 ? _len - 3 : 0), _key = 3; _key < _len; _key++) {
+ args[_key - 3] = arguments[_key];
+ }
+
+ ret = originalWindowOnError.call.apply(originalWindowOnError, [this, message, fileName, lineNumber].concat(args));
+ }
+
+ // Treat return value as window.onerror itself does,
+ // Only do our handling if not suppressed.
+ if (ret !== true) {
+ var error = {
+ message: message,
+ fileName: fileName,
+ lineNumber: lineNumber
+ };
+
+ ret = QUnit.onError(error);
+ }
+
+ return ret;
+ };
+ })();
+
+ /*
+ * This file is a modified version of google-diff-match-patch's JavaScript implementation
+ * (https://code.google.com/p/google-diff-match-patch/source/browse/trunk/javascript/diff_match_patch_uncompressed.js),
+ * modifications are licensed as more fully set forth in LICENSE.txt.
+ *
+ * The original source of google-diff-match-patch is attributable and licensed as follows:
+ *
+ * Copyright 2006 Google Inc.
+ * https://code.google.com/p/google-diff-match-patch/
+ *
+ * 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
+ *
+ * https://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.
+ *
+ * More Info:
+ * https://code.google.com/p/google-diff-match-patch/
+ *
+ * Usage: QUnit.diff(expected, actual)
+ *
+ */
+ QUnit.diff = function () {
+ function DiffMatchPatch() {}
+
+ // DIFF FUNCTIONS
+
+ /**
+ * The data structure representing a diff is an array of tuples:
+ * [[DIFF_DELETE, 'Hello'], [DIFF_INSERT, 'Goodbye'], [DIFF_EQUAL, ' world.']]
+ * which means: delete 'Hello', add 'Goodbye' and keep ' world.'
+ */
+ var DIFF_DELETE = -1,
+ DIFF_INSERT = 1,
+ DIFF_EQUAL = 0;
+
+ /**
+ * Find the differences between two texts. Simplifies the problem by stripping
+ * any common prefix or suffix off the texts before diffing.
+ * @param {string} text1 Old string to be diffed.
+ * @param {string} text2 New string to be diffed.
+ * @param {boolean=} optChecklines Optional speedup flag. If present and false,
+ * then don't run a line-level diff first to identify the changed areas.
+ * Defaults to true, which does a faster, slightly less optimal diff.
+ * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+ */
+ DiffMatchPatch.prototype.DiffMain = function (text1, text2, optChecklines) {
+ var deadline, checklines, commonlength, commonprefix, commonsuffix, diffs;
+
+ // The diff must be complete in up to 1 second.
+ deadline = new Date().getTime() + 1000;
+
+ // Check for null inputs.
+ if (text1 === null || text2 === null) {
+ throw new Error("Null input. (DiffMain)");
+ }
+
+ // Check for equality (speedup).
+ if (text1 === text2) {
+ if (text1) {
+ return [[DIFF_EQUAL, text1]];
+ }
+ return [];
+ }
+
+ if (typeof optChecklines === "undefined") {
+ optChecklines = true;
+ }
+
+ checklines = optChecklines;
+
+ // Trim off common prefix (speedup).
+ commonlength = this.diffCommonPrefix(text1, text2);
+ commonprefix = text1.substring(0, commonlength);
+ text1 = text1.substring(commonlength);
+ text2 = text2.substring(commonlength);
+
+ // Trim off common suffix (speedup).
+ commonlength = this.diffCommonSuffix(text1, text2);
+ commonsuffix = text1.substring(text1.length - commonlength);
+ text1 = text1.substring(0, text1.length - commonlength);
+ text2 = text2.substring(0, text2.length - commonlength);
+
+ // Compute the diff on the middle block.
+ diffs = this.diffCompute(text1, text2, checklines, deadline);
+
+ // Restore the prefix and suffix.
+ if (commonprefix) {
+ diffs.unshift([DIFF_EQUAL, commonprefix]);
+ }
+ if (commonsuffix) {
+ diffs.push([DIFF_EQUAL, commonsuffix]);
+ }
+ this.diffCleanupMerge(diffs);
+ return diffs;
+ };
+
+ /**
+ * Reduce the number of edits by eliminating operationally trivial equalities.
+ * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+ */
+ DiffMatchPatch.prototype.diffCleanupEfficiency = function (diffs) {
+ var changes, equalities, equalitiesLength, lastequality, pointer, preIns, preDel, postIns, postDel;
+ changes = false;
+ equalities = []; // Stack of indices where equalities are found.
+ equalitiesLength = 0; // Keeping our own length var is faster in JS.
+ /** @type {?string} */
+ lastequality = null;
+
+ // Always equal to diffs[equalities[equalitiesLength - 1]][1]
+ pointer = 0; // Index of current position.
+
+ // Is there an insertion operation before the last equality.
+ preIns = false;
+
+ // Is there a deletion operation before the last equality.
+ preDel = false;
+
+ // Is there an insertion operation after the last equality.
+ postIns = false;
+
+ // Is there a deletion operation after the last equality.
+ postDel = false;
+ while (pointer < diffs.length) {
+
+ // Equality found.
+ if (diffs[pointer][0] === DIFF_EQUAL) {
+ if (diffs[pointer][1].length < 4 && (postIns || postDel)) {
+
+ // Candidate found.
+ equalities[equalitiesLength++] = pointer;
+ preIns = postIns;
+ preDel = postDel;
+ lastequality = diffs[pointer][1];
+ } else {
+
+ // Not a candidate, and can never become one.
+ equalitiesLength = 0;
+ lastequality = null;
+ }
+ postIns = postDel = false;
+
+ // An insertion or deletion.
+ } else {
+
+ if (diffs[pointer][0] === DIFF_DELETE) {
+ postDel = true;
+ } else {
+ postIns = true;
+ }
+
+ /*
+ * Five types to be split:
+ * <ins>A</ins><del>B</del>XY<ins>C</ins><del>D</del>
+ * <ins>A</ins>X<ins>C</ins><del>D</del>
+ * <ins>A</ins><del>B</del>X<ins>C</ins>
+ * <ins>A</del>X<ins>C</ins><del>D</del>
+ * <ins>A</ins><del>B</del>X<del>C</del>
+ */
+ if (lastequality && (preIns && preDel && postIns && postDel || lastequality.length < 2 && preIns + preDel + postIns + postDel === 3)) {
+
+ // Duplicate record.
+ diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastequality]);
+
+ // Change second copy to insert.
+ diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
+ equalitiesLength--; // Throw away the equality we just deleted;
+ lastequality = null;
+ if (preIns && preDel) {
+
+ // No changes made which could affect previous entry, keep going.
+ postIns = postDel = true;
+ equalitiesLength = 0;
+ } else {
+ equalitiesLength--; // Throw away the previous equality.
+ pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
+ postIns = postDel = false;
+ }
+ changes = true;
+ }
+ }
+ pointer++;
+ }
+
+ if (changes) {
+ this.diffCleanupMerge(diffs);
+ }
+ };
+
+ /**
+ * Convert a diff array into a pretty HTML report.
+ * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+ * @param {integer} string to be beautified.
+ * @return {string} HTML representation.
+ */
+ DiffMatchPatch.prototype.diffPrettyHtml = function (diffs) {
+ var op,
+ data,
+ x,
+ html = [];
+ for (x = 0; x < diffs.length; x++) {
+ op = diffs[x][0]; // Operation (insert, delete, equal)
+ data = diffs[x][1]; // Text of change.
+ switch (op) {
+ case DIFF_INSERT:
+ html[x] = "<ins>" + escapeText(data) + "</ins>";
+ break;
+ case DIFF_DELETE:
+ html[x] = "<del>" + escapeText(data) + "</del>";
+ break;
+ case DIFF_EQUAL:
+ html[x] = "<span>" + escapeText(data) + "</span>";
+ break;
+ }
+ }
+ return html.join("");
+ };
+
+ /**
+ * Determine the common prefix of two strings.
+ * @param {string} text1 First string.
+ * @param {string} text2 Second string.
+ * @return {number} The number of characters common to the start of each
+ * string.
+ */
+ DiffMatchPatch.prototype.diffCommonPrefix = function (text1, text2) {
+ var pointermid, pointermax, pointermin, pointerstart;
+
+ // Quick check for common null cases.
+ if (!text1 || !text2 || text1.charAt(0) !== text2.charAt(0)) {
+ return 0;
+ }
+
+ // Binary search.
+ // Performance analysis: https://neil.fraser.name/news/2007/10/09/
+ pointermin = 0;
+ pointermax = Math.min(text1.length, text2.length);
+ pointermid = pointermax;
+ pointerstart = 0;
+ while (pointermin < pointermid) {
+ if (text1.substring(pointerstart, pointermid) === text2.substring(pointerstart, pointermid)) {
+ pointermin = pointermid;
+ pointerstart = pointermin;
+ } else {
+ pointermax = pointermid;
+ }
+ pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
+ }
+ return pointermid;
+ };
+
+ /**
+ * Determine the common suffix of two strings.
+ * @param {string} text1 First string.
+ * @param {string} text2 Second string.
+ * @return {number} The number of characters common to the end of each string.
+ */
+ DiffMatchPatch.prototype.diffCommonSuffix = function (text1, text2) {
+ var pointermid, pointermax, pointermin, pointerend;
+
+ // Quick check for common null cases.
+ if (!text1 || !text2 || text1.charAt(text1.length - 1) !== text2.charAt(text2.length - 1)) {
+ return 0;
+ }
+
+ // Binary search.
+ // Performance analysis: https://neil.fraser.name/news/2007/10/09/
+ pointermin = 0;
+ pointermax = Math.min(text1.length, text2.length);
+ pointermid = pointermax;
+ pointerend = 0;
+ while (pointermin < pointermid) {
+ if (text1.substring(text1.length - pointermid, text1.length - pointerend) === text2.substring(text2.length - pointermid, text2.length - pointerend)) {
+ pointermin = pointermid;
+ pointerend = pointermin;
+ } else {
+ pointermax = pointermid;
+ }
+ pointermid = Math.floor((pointermax - pointermin) / 2 + pointermin);
+ }
+ return pointermid;
+ };
+
+ /**
+ * Find the differences between two texts. Assumes that the texts do not
+ * have any common prefix or suffix.
+ * @param {string} text1 Old string to be diffed.
+ * @param {string} text2 New string to be diffed.
+ * @param {boolean} checklines Speedup flag. If false, then don't run a
+ * line-level diff first to identify the changed areas.
+ * If true, then run a faster, slightly less optimal diff.
+ * @param {number} deadline Time when the diff should be complete by.
+ * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+ * @private
+ */
+ DiffMatchPatch.prototype.diffCompute = function (text1, text2, checklines, deadline) {
+ var diffs, longtext, shorttext, i, hm, text1A, text2A, text1B, text2B, midCommon, diffsA, diffsB;
+
+ if (!text1) {
+
+ // Just add some text (speedup).
+ return [[DIFF_INSERT, text2]];
+ }
+
+ if (!text2) {
+
+ // Just delete some text (speedup).
+ return [[DIFF_DELETE, text1]];
+ }
+
+ longtext = text1.length > text2.length ? text1 : text2;
+ shorttext = text1.length > text2.length ? text2 : text1;
+ i = longtext.indexOf(shorttext);
+ if (i !== -1) {
+
+ // Shorter text is inside the longer text (speedup).
+ diffs = [[DIFF_INSERT, longtext.substring(0, i)], [DIFF_EQUAL, shorttext], [DIFF_INSERT, longtext.substring(i + shorttext.length)]];
+
+ // Swap insertions for deletions if diff is reversed.
+ if (text1.length > text2.length) {
+ diffs[0][0] = diffs[2][0] = DIFF_DELETE;
+ }
+ return diffs;
+ }
+
+ if (shorttext.length === 1) {
+
+ // Single character string.
+ // After the previous speedup, the character can't be an equality.
+ return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
+ }
+
+ // Check to see if the problem can be split in two.
+ hm = this.diffHalfMatch(text1, text2);
+ if (hm) {
+
+ // A half-match was found, sort out the return data.
+ text1A = hm[0];
+ text1B = hm[1];
+ text2A = hm[2];
+ text2B = hm[3];
+ midCommon = hm[4];
+
+ // Send both pairs off for separate processing.
+ diffsA = this.DiffMain(text1A, text2A, checklines, deadline);
+ diffsB = this.DiffMain(text1B, text2B, checklines, deadline);
+
+ // Merge the results.
+ return diffsA.concat([[DIFF_EQUAL, midCommon]], diffsB);
+ }
+
+ if (checklines && text1.length > 100 && text2.length > 100) {
+ return this.diffLineMode(text1, text2, deadline);
+ }
+
+ return this.diffBisect(text1, text2, deadline);
+ };
+
+ /**
+ * Do the two texts share a substring which is at least half the length of the
+ * longer text?
+ * This speedup can produce non-minimal diffs.
+ * @param {string} text1 First string.
+ * @param {string} text2 Second string.
+ * @return {Array.<string>} Five element Array, containing the prefix of
+ * text1, the suffix of text1, the prefix of text2, the suffix of
+ * text2 and the common middle. Or null if there was no match.
+ * @private
+ */
+ DiffMatchPatch.prototype.diffHalfMatch = function (text1, text2) {
+ var longtext, shorttext, dmp, text1A, text2B, text2A, text1B, midCommon, hm1, hm2, hm;
+
+ longtext = text1.length > text2.length ? text1 : text2;
+ shorttext = text1.length > text2.length ? text2 : text1;
+ if (longtext.length < 4 || shorttext.length * 2 < longtext.length) {
+ return null; // Pointless.
+ }
+ dmp = this; // 'this' becomes 'window' in a closure.
+
+ /**
+ * Does a substring of shorttext exist within longtext such that the substring
+ * is at least half the length of longtext?
+ * Closure, but does not reference any external variables.
+ * @param {string} longtext Longer string.
+ * @param {string} shorttext Shorter string.
+ * @param {number} i Start index of quarter length substring within longtext.
+ * @return {Array.<string>} Five element Array, containing the prefix of
+ * longtext, the suffix of longtext, the prefix of shorttext, the suffix
+ * of shorttext and the common middle. Or null if there was no match.
+ * @private
+ */
+ function diffHalfMatchI(longtext, shorttext, i) {
+ var seed, j, bestCommon, prefixLength, suffixLength, bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB;
+
+ // Start with a 1/4 length substring at position i as a seed.
+ seed = longtext.substring(i, i + Math.floor(longtext.length / 4));
+ j = -1;
+ bestCommon = "";
+ while ((j = shorttext.indexOf(seed, j + 1)) !== -1) {
+ prefixLength = dmp.diffCommonPrefix(longtext.substring(i), shorttext.substring(j));
+ suffixLength = dmp.diffCommonSuffix(longtext.substring(0, i), shorttext.substring(0, j));
+ if (bestCommon.length < suffixLength + prefixLength) {
+ bestCommon = shorttext.substring(j - suffixLength, j) + shorttext.substring(j, j + prefixLength);
+ bestLongtextA = longtext.substring(0, i - suffixLength);
+ bestLongtextB = longtext.substring(i + prefixLength);
+ bestShorttextA = shorttext.substring(0, j - suffixLength);
+ bestShorttextB = shorttext.substring(j + prefixLength);
+ }
+ }
+ if (bestCommon.length * 2 >= longtext.length) {
+ return [bestLongtextA, bestLongtextB, bestShorttextA, bestShorttextB, bestCommon];
+ } else {
+ return null;
+ }
+ }
+
+ // First check if the second quarter is the seed for a half-match.
+ hm1 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 4));
+
+ // Check again based on the third quarter.
+ hm2 = diffHalfMatchI(longtext, shorttext, Math.ceil(longtext.length / 2));
+ if (!hm1 && !hm2) {
+ return null;
+ } else if (!hm2) {
+ hm = hm1;
+ } else if (!hm1) {
+ hm = hm2;
+ } else {
+
+ // Both matched. Select the longest.
+ hm = hm1[4].length > hm2[4].length ? hm1 : hm2;
+ }
+
+ // A half-match was found, sort out the return data.
+ if (text1.length > text2.length) {
+ text1A = hm[0];
+ text1B = hm[1];
+ text2A = hm[2];
+ text2B = hm[3];
+ } else {
+ text2A = hm[0];
+ text2B = hm[1];
+ text1A = hm[2];
+ text1B = hm[3];
+ }
+ midCommon = hm[4];
+ return [text1A, text1B, text2A, text2B, midCommon];
+ };
+
+ /**
+ * Do a quick line-level diff on both strings, then rediff the parts for
+ * greater accuracy.
+ * This speedup can produce non-minimal diffs.
+ * @param {string} text1 Old string to be diffed.
+ * @param {string} text2 New string to be diffed.
+ * @param {number} deadline Time when the diff should be complete by.
+ * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+ * @private
+ */
+ DiffMatchPatch.prototype.diffLineMode = function (text1, text2, deadline) {
+ var a, diffs, linearray, pointer, countInsert, countDelete, textInsert, textDelete, j;
+
+ // Scan the text on a line-by-line basis first.
+ a = this.diffLinesToChars(text1, text2);
+ text1 = a.chars1;
+ text2 = a.chars2;
+ linearray = a.lineArray;
+
+ diffs = this.DiffMain(text1, text2, false, deadline);
+
+ // Convert the diff back to original text.
+ this.diffCharsToLines(diffs, linearray);
+
+ // Eliminate freak matches (e.g. blank lines)
+ this.diffCleanupSemantic(diffs);
+
+ // Rediff any replacement blocks, this time character-by-character.
+ // Add a dummy entry at the end.
+ diffs.push([DIFF_EQUAL, ""]);
+ pointer = 0;
+ countDelete = 0;
+ countInsert = 0;
+ textDelete = "";
+ textInsert = "";
+ while (pointer < diffs.length) {
+ switch (diffs[pointer][0]) {
+ case DIFF_INSERT:
+ countInsert++;
+ textInsert += diffs[pointer][1];
+ break;
+ case DIFF_DELETE:
+ countDelete++;
+ textDelete += diffs[pointer][1];
+ break;
+ case DIFF_EQUAL:
+
+ // Upon reaching an equality, check for prior redundancies.
+ if (countDelete >= 1 && countInsert >= 1) {
+
+ // Delete the offending records and add the merged ones.
+ diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert);
+ pointer = pointer - countDelete - countInsert;
+ a = this.DiffMain(textDelete, textInsert, false, deadline);
+ for (j = a.length - 1; j >= 0; j--) {
+ diffs.splice(pointer, 0, a[j]);
+ }
+ pointer = pointer + a.length;
+ }
+ countInsert = 0;
+ countDelete = 0;
+ textDelete = "";
+ textInsert = "";
+ break;
+ }
+ pointer++;
+ }
+ diffs.pop(); // Remove the dummy entry at the end.
+
+ return diffs;
+ };
+
+ /**
+ * Find the 'middle snake' of a diff, split the problem in two
+ * and return the recursively constructed diff.
+ * See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations.
+ * @param {string} text1 Old string to be diffed.
+ * @param {string} text2 New string to be diffed.
+ * @param {number} deadline Time at which to bail if not yet complete.
+ * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+ * @private
+ */
+ DiffMatchPatch.prototype.diffBisect = function (text1, text2, deadline) {
+ var text1Length, text2Length, maxD, vOffset, vLength, v1, v2, x, delta, front, k1start, k1end, k2start, k2end, k2Offset, k1Offset, x1, x2, y1, y2, d, k1, k2;
+
+ // Cache the text lengths to prevent multiple calls.
+ text1Length = text1.length;
+ text2Length = text2.length;
+ maxD = Math.ceil((text1Length + text2Length) / 2);
+ vOffset = maxD;
+ vLength = 2 * maxD;
+ v1 = new Array(vLength);
+ v2 = new Array(vLength);
+
+ // Setting all elements to -1 is faster in Chrome & Firefox than mixing
+ // integers and undefined.
+ for (x = 0; x < vLength; x++) {
+ v1[x] = -1;
+ v2[x] = -1;
+ }
+ v1[vOffset + 1] = 0;
+ v2[vOffset + 1] = 0;
+ delta = text1Length - text2Length;
+
+ // If the total number of characters is odd, then the front path will collide
+ // with the reverse path.
+ front = delta % 2 !== 0;
+
+ // Offsets for start and end of k loop.
+ // Prevents mapping of space beyond the grid.
+ k1start = 0;
+ k1end = 0;
+ k2start = 0;
+ k2end = 0;
+ for (d = 0; d < maxD; d++) {
+
+ // Bail out if deadline is reached.
+ if (new Date().getTime() > deadline) {
+ break;
+ }
+
+ // Walk the front path one step.
+ for (k1 = -d + k1start; k1 <= d - k1end; k1 += 2) {
+ k1Offset = vOffset + k1;
+ if (k1 === -d || k1 !== d && v1[k1Offset - 1] < v1[k1Offset + 1]) {
+ x1 = v1[k1Offset + 1];
+ } else {
+ x1 = v1[k1Offset - 1] + 1;
+ }
+ y1 = x1 - k1;
+ while (x1 < text1Length && y1 < text2Length && text1.charAt(x1) === text2.charAt(y1)) {
+ x1++;
+ y1++;
+ }
+ v1[k1Offset] = x1;
+ if (x1 > text1Length) {
+
+ // Ran off the right of the graph.
+ k1end += 2;
+ } else if (y1 > text2Length) {
+
+ // Ran off the bottom of the graph.
+ k1start += 2;
+ } else if (front) {
+ k2Offset = vOffset + delta - k1;
+ if (k2Offset >= 0 && k2Offset < vLength && v2[k2Offset] !== -1) {
+
+ // Mirror x2 onto top-left coordinate system.
+ x2 = text1Length - v2[k2Offset];
+ if (x1 >= x2) {
+
+ // Overlap detected.
+ return this.diffBisectSplit(text1, text2, x1, y1, deadline);
+ }
+ }
+ }
+ }
+
+ // Walk the reverse path one step.
+ for (k2 = -d + k2start; k2 <= d - k2end; k2 += 2) {
+ k2Offset = vOffset + k2;
+ if (k2 === -d || k2 !== d && v2[k2Offset - 1] < v2[k2Offset + 1]) {
+ x2 = v2[k2Offset + 1];
+ } else {
+ x2 = v2[k2Offset - 1] + 1;
+ }
+ y2 = x2 - k2;
+ while (x2 < text1Length && y2 < text2Length && text1.charAt(text1Length - x2 - 1) === text2.charAt(text2Length - y2 - 1)) {
+ x2++;
+ y2++;
+ }
+ v2[k2Offset] = x2;
+ if (x2 > text1Length) {
+
+ // Ran off the left of the graph.
+ k2end += 2;
+ } else if (y2 > text2Length) {
+
+ // Ran off the top of the graph.
+ k2start += 2;
+ } else if (!front) {
+ k1Offset = vOffset + delta - k2;
+ if (k1Offset >= 0 && k1Offset < vLength && v1[k1Offset] !== -1) {
+ x1 = v1[k1Offset];
+ y1 = vOffset + x1 - k1Offset;
+
+ // Mirror x2 onto top-left coordinate system.
+ x2 = text1Length - x2;
+ if (x1 >= x2) {
+
+ // Overlap detected.
+ return this.diffBisectSplit(text1, text2, x1, y1, deadline);
+ }
+ }
+ }
+ }
+ }
+
+ // Diff took too long and hit the deadline or
+ // number of diffs equals number of characters, no commonality at all.
+ return [[DIFF_DELETE, text1], [DIFF_INSERT, text2]];
+ };
+
+ /**
+ * Given the location of the 'middle snake', split the diff in two parts
+ * and recurse.
+ * @param {string} text1 Old string to be diffed.
+ * @param {string} text2 New string to be diffed.
+ * @param {number} x Index of split point in text1.
+ * @param {number} y Index of split point in text2.
+ * @param {number} deadline Time at which to bail if not yet complete.
+ * @return {!Array.<!DiffMatchPatch.Diff>} Array of diff tuples.
+ * @private
+ */
+ DiffMatchPatch.prototype.diffBisectSplit = function (text1, text2, x, y, deadline) {
+ var text1a, text1b, text2a, text2b, diffs, diffsb;
+ text1a = text1.substring(0, x);
+ text2a = text2.substring(0, y);
+ text1b = text1.substring(x);
+ text2b = text2.substring(y);
+
+ // Compute both diffs serially.
+ diffs = this.DiffMain(text1a, text2a, false, deadline);
+ diffsb = this.DiffMain(text1b, text2b, false, deadline);
+
+ return diffs.concat(diffsb);
+ };
+
+ /**
+ * Reduce the number of edits by eliminating semantically trivial equalities.
+ * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+ */
+ DiffMatchPatch.prototype.diffCleanupSemantic = function (diffs) {
+ var changes, equalities, equalitiesLength, lastequality, pointer, lengthInsertions2, lengthDeletions2, lengthInsertions1, lengthDeletions1, deletion, insertion, overlapLength1, overlapLength2;
+ changes = false;
+ equalities = []; // Stack of indices where equalities are found.
+ equalitiesLength = 0; // Keeping our own length var is faster in JS.
+ /** @type {?string} */
+ lastequality = null;
+
+ // Always equal to diffs[equalities[equalitiesLength - 1]][1]
+ pointer = 0; // Index of current position.
+
+ // Number of characters that changed prior to the equality.
+ lengthInsertions1 = 0;
+ lengthDeletions1 = 0;
+
+ // Number of characters that changed after the equality.
+ lengthInsertions2 = 0;
+ lengthDeletions2 = 0;
+ while (pointer < diffs.length) {
+ if (diffs[pointer][0] === DIFF_EQUAL) {
+ // Equality found.
+ equalities[equalitiesLength++] = pointer;
+ lengthInsertions1 = lengthInsertions2;
+ lengthDeletions1 = lengthDeletions2;
+ lengthInsertions2 = 0;
+ lengthDeletions2 = 0;
+ lastequality = diffs[pointer][1];
+ } else {
+ // An insertion or deletion.
+ if (diffs[pointer][0] === DIFF_INSERT) {
+ lengthInsertions2 += diffs[pointer][1].length;
+ } else {
+ lengthDeletions2 += diffs[pointer][1].length;
+ }
+
+ // Eliminate an equality that is smaller or equal to the edits on both
+ // sides of it.
+ if (lastequality && lastequality.length <= Math.max(lengthInsertions1, lengthDeletions1) && lastequality.length <= Math.max(lengthInsertions2, lengthDeletions2)) {
+
+ // Duplicate record.
+ diffs.splice(equalities[equalitiesLength - 1], 0, [DIFF_DELETE, lastequality]);
+
+ // Change second copy to insert.
+ diffs[equalities[equalitiesLength - 1] + 1][0] = DIFF_INSERT;
+
+ // Throw away the equality we just deleted.
+ equalitiesLength--;
+
+ // Throw away the previous equality (it needs to be reevaluated).
+ equalitiesLength--;
+ pointer = equalitiesLength > 0 ? equalities[equalitiesLength - 1] : -1;
+
+ // Reset the counters.
+ lengthInsertions1 = 0;
+ lengthDeletions1 = 0;
+ lengthInsertions2 = 0;
+ lengthDeletions2 = 0;
+ lastequality = null;
+ changes = true;
+ }
+ }
+ pointer++;
+ }
+
+ // Normalize the diff.
+ if (changes) {
+ this.diffCleanupMerge(diffs);
+ }
+
+ // Find any overlaps between deletions and insertions.
+ // e.g: <del>abcxxx</del><ins>xxxdef</ins>
+ // -> <del>abc</del>xxx<ins>def</ins>
+ // e.g: <del>xxxabc</del><ins>defxxx</ins>
+ // -> <ins>def</ins>xxx<del>abc</del>
+ // Only extract an overlap if it is as big as the edit ahead or behind it.
+ pointer = 1;
+ while (pointer < diffs.length) {
+ if (diffs[pointer - 1][0] === DIFF_DELETE && diffs[pointer][0] === DIFF_INSERT) {
+ deletion = diffs[pointer - 1][1];
+ insertion = diffs[pointer][1];
+ overlapLength1 = this.diffCommonOverlap(deletion, insertion);
+ overlapLength2 = this.diffCommonOverlap(insertion, deletion);
+ if (overlapLength1 >= overlapLength2) {
+ if (overlapLength1 >= deletion.length / 2 || overlapLength1 >= insertion.length / 2) {
+
+ // Overlap found. Insert an equality and trim the surrounding edits.
+ diffs.splice(pointer, 0, [DIFF_EQUAL, insertion.substring(0, overlapLength1)]);
+ diffs[pointer - 1][1] = deletion.substring(0, deletion.length - overlapLength1);
+ diffs[pointer + 1][1] = insertion.substring(overlapLength1);
+ pointer++;
+ }
+ } else {
+ if (overlapLength2 >= deletion.length / 2 || overlapLength2 >= insertion.length / 2) {
+
+ // Reverse overlap found.
+ // Insert an equality and swap and trim the surrounding edits.
+ diffs.splice(pointer, 0, [DIFF_EQUAL, deletion.substring(0, overlapLength2)]);
+
+ diffs[pointer - 1][0] = DIFF_INSERT;
+ diffs[pointer - 1][1] = insertion.substring(0, insertion.length - overlapLength2);
+ diffs[pointer + 1][0] = DIFF_DELETE;
+ diffs[pointer + 1][1] = deletion.substring(overlapLength2);
+ pointer++;
+ }
+ }
+ pointer++;
+ }
+ pointer++;
+ }
+ };
+
+ /**
+ * Determine if the suffix of one string is the prefix of another.
+ * @param {string} text1 First string.
+ * @param {string} text2 Second string.
+ * @return {number} The number of characters common to the end of the first
+ * string and the start of the second string.
+ * @private
+ */
+ DiffMatchPatch.prototype.diffCommonOverlap = function (text1, text2) {
+ var text1Length, text2Length, textLength, best, length, pattern, found;
+
+ // Cache the text lengths to prevent multiple calls.
+ text1Length = text1.length;
+ text2Length = text2.length;
+
+ // Eliminate the null case.
+ if (text1Length === 0 || text2Length === 0) {
+ return 0;
+ }
+
+ // Truncate the longer string.
+ if (text1Length > text2Length) {
+ text1 = text1.substring(text1Length - text2Length);
+ } else if (text1Length < text2Length) {
+ text2 = text2.substring(0, text1Length);
+ }
+ textLength = Math.min(text1Length, text2Length);
+
+ // Quick check for the worst case.
+ if (text1 === text2) {
+ return textLength;
+ }
+
+ // Start by looking for a single character match
+ // and increase length until no match is found.
+ // Performance analysis: https://neil.fraser.name/news/2010/11/04/
+ best = 0;
+ length = 1;
+ while (true) {
+ pattern = text1.substring(textLength - length);
+ found = text2.indexOf(pattern);
+ if (found === -1) {
+ return best;
+ }
+ length += found;
+ if (found === 0 || text1.substring(textLength - length) === text2.substring(0, length)) {
+ best = length;
+ length++;
+ }
+ }
+ };
+
+ /**
+ * Split two texts into an array of strings. Reduce the texts to a string of
+ * hashes where each Unicode character represents one line.
+ * @param {string} text1 First string.
+ * @param {string} text2 Second string.
+ * @return {{chars1: string, chars2: string, lineArray: !Array.<string>}}
+ * An object containing the encoded text1, the encoded text2 and
+ * the array of unique strings.
+ * The zeroth element of the array of unique strings is intentionally blank.
+ * @private
+ */
+ DiffMatchPatch.prototype.diffLinesToChars = function (text1, text2) {
+ var lineArray, lineHash, chars1, chars2;
+ lineArray = []; // E.g. lineArray[4] === 'Hello\n'
+ lineHash = {}; // E.g. lineHash['Hello\n'] === 4
+
+ // '\x00' is a valid character, but various debuggers don't like it.
+ // So we'll insert a junk entry to avoid generating a null character.
+ lineArray[0] = "";
+
+ /**
+ * Split a text into an array of strings. Reduce the texts to a string of
+ * hashes where each Unicode character represents one line.
+ * Modifies linearray and linehash through being a closure.
+ * @param {string} text String to encode.
+ * @return {string} Encoded string.
+ * @private
+ */
+ function diffLinesToCharsMunge(text) {
+ var chars, lineStart, lineEnd, lineArrayLength, line;
+ chars = "";
+
+ // Walk the text, pulling out a substring for each line.
+ // text.split('\n') would would temporarily double our memory footprint.
+ // Modifying text would create many large strings to garbage collect.
+ lineStart = 0;
+ lineEnd = -1;
+
+ // Keeping our own length variable is faster than looking it up.
+ lineArrayLength = lineArray.length;
+ while (lineEnd < text.length - 1) {
+ lineEnd = text.indexOf("\n", lineStart);
+ if (lineEnd === -1) {
+ lineEnd = text.length - 1;
+ }
+ line = text.substring(lineStart, lineEnd + 1);
+ lineStart = lineEnd + 1;
+
+ if (lineHash.hasOwnProperty ? lineHash.hasOwnProperty(line) : lineHash[line] !== undefined) {
+ chars += String.fromCharCode(lineHash[line]);
+ } else {
+ chars += String.fromCharCode(lineArrayLength);
+ lineHash[line] = lineArrayLength;
+ lineArray[lineArrayLength++] = line;
+ }
+ }
+ return chars;
+ }
+
+ chars1 = diffLinesToCharsMunge(text1);
+ chars2 = diffLinesToCharsMunge(text2);
+ return {
+ chars1: chars1,
+ chars2: chars2,
+ lineArray: lineArray
+ };
+ };
+
+ /**
+ * Rehydrate the text in a diff from a string of line hashes to real lines of
+ * text.
+ * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+ * @param {!Array.<string>} lineArray Array of unique strings.
+ * @private
+ */
+ DiffMatchPatch.prototype.diffCharsToLines = function (diffs, lineArray) {
+ var x, chars, text, y;
+ for (x = 0; x < diffs.length; x++) {
+ chars = diffs[x][1];
+ text = [];
+ for (y = 0; y < chars.length; y++) {
+ text[y] = lineArray[chars.charCodeAt(y)];
+ }
+ diffs[x][1] = text.join("");
+ }
+ };
+
+ /**
+ * Reorder and merge like edit sections. Merge equalities.
+ * Any edit section can move as long as it doesn't cross an equality.
+ * @param {!Array.<!DiffMatchPatch.Diff>} diffs Array of diff tuples.
+ */
+ DiffMatchPatch.prototype.diffCleanupMerge = function (diffs) {
+ var pointer, countDelete, countInsert, textInsert, textDelete, commonlength, changes, diffPointer, position;
+ diffs.push([DIFF_EQUAL, ""]); // Add a dummy entry at the end.
+ pointer = 0;
+ countDelete = 0;
+ countInsert = 0;
+ textDelete = "";
+ textInsert = "";
+
+ while (pointer < diffs.length) {
+ switch (diffs[pointer][0]) {
+ case DIFF_INSERT:
+ countInsert++;
+ textInsert += diffs[pointer][1];
+ pointer++;
+ break;
+ case DIFF_DELETE:
+ countDelete++;
+ textDelete += diffs[pointer][1];
+ pointer++;
+ break;
+ case DIFF_EQUAL:
+
+ // Upon reaching an equality, check for prior redundancies.
+ if (countDelete + countInsert > 1) {
+ if (countDelete !== 0 && countInsert !== 0) {
+
+ // Factor out any common prefixes.
+ commonlength = this.diffCommonPrefix(textInsert, textDelete);
+ if (commonlength !== 0) {
+ if (pointer - countDelete - countInsert > 0 && diffs[pointer - countDelete - countInsert - 1][0] === DIFF_EQUAL) {
+ diffs[pointer - countDelete - countInsert - 1][1] += textInsert.substring(0, commonlength);
+ } else {
+ diffs.splice(0, 0, [DIFF_EQUAL, textInsert.substring(0, commonlength)]);
+ pointer++;
+ }
+ textInsert = textInsert.substring(commonlength);
+ textDelete = textDelete.substring(commonlength);
+ }
+
+ // Factor out any common suffixies.
+ commonlength = this.diffCommonSuffix(textInsert, textDelete);
+ if (commonlength !== 0) {
+ diffs[pointer][1] = textInsert.substring(textInsert.length - commonlength) + diffs[pointer][1];
+ textInsert = textInsert.substring(0, textInsert.length - commonlength);
+ textDelete = textDelete.substring(0, textDelete.length - commonlength);
+ }
+ }
+
+ // Delete the offending records and add the merged ones.
+ if (countDelete === 0) {
+ diffs.splice(pointer - countInsert, countDelete + countInsert, [DIFF_INSERT, textInsert]);
+ } else if (countInsert === 0) {
+ diffs.splice(pointer - countDelete, countDelete + countInsert, [DIFF_DELETE, textDelete]);
+ } else {
+ diffs.splice(pointer - countDelete - countInsert, countDelete + countInsert, [DIFF_DELETE, textDelete], [DIFF_INSERT, textInsert]);
+ }
+ pointer = pointer - countDelete - countInsert + (countDelete ? 1 : 0) + (countInsert ? 1 : 0) + 1;
+ } else if (pointer !== 0 && diffs[pointer - 1][0] === DIFF_EQUAL) {
+
+ // Merge this equality with the previous one.
+ diffs[pointer - 1][1] += diffs[pointer][1];
+ diffs.splice(pointer, 1);
+ } else {
+ pointer++;
+ }
+ countInsert = 0;
+ countDelete = 0;
+ textDelete = "";
+ textInsert = "";
+ break;
+ }
+ }
+ if (diffs[diffs.length - 1][1] === "") {
+ diffs.pop(); // Remove the dummy entry at the end.
+ }
+
+ // Second pass: look for single edits surrounded on both sides by equalities
+ // which can be shifted sideways to eliminate an equality.
+ // e.g: A<ins>BA</ins>C -> <ins>AB</ins>AC
+ changes = false;
+ pointer = 1;
+
+ // Intentionally ignore the first and last element (don't need checking).
+ while (pointer < diffs.length - 1) {
+ if (diffs[pointer - 1][0] === DIFF_EQUAL && diffs[pointer + 1][0] === DIFF_EQUAL) {
+
+ diffPointer = diffs[pointer][1];
+ position = diffPointer.substring(diffPointer.length - diffs[pointer - 1][1].length);
+
+ // This is a single edit surrounded by equalities.
+ if (position === diffs[pointer - 1][1]) {
+
+ // Shift the edit over the previous equality.
+ diffs[pointer][1] = diffs[pointer - 1][1] + diffs[pointer][1].substring(0, diffs[pointer][1].length - diffs[pointer - 1][1].length);
+ diffs[pointer + 1][1] = diffs[pointer - 1][1] + diffs[pointer + 1][1];
+ diffs.splice(pointer - 1, 1);
+ changes = true;
+ } else if (diffPointer.substring(0, diffs[pointer + 1][1].length) === diffs[pointer + 1][1]) {
+
+ // Shift the edit over the next equality.
+ diffs[pointer - 1][1] += diffs[pointer + 1][1];
+ diffs[pointer][1] = diffs[pointer][1].substring(diffs[pointer + 1][1].length) + diffs[pointer + 1][1];
+ diffs.splice(pointer + 1, 1);
+ changes = true;
+ }
+ }
+ pointer++;
+ }
+
+ // If shifts were made, the diff needs reordering and another shift sweep.
+ if (changes) {
+ this.diffCleanupMerge(diffs);
+ }
+ };
+
+ return function (o, n) {
+ var diff, output, text;
+ diff = new DiffMatchPatch();
+ output = diff.DiffMain(o, n);
+ diff.diffCleanupEfficiency(output);
+ text = diff.diffPrettyHtml(output);
+
+ return text;
+ };
+ }();
+
+}((function() { return this; }())));
diff --git a/www/wiki/resources/lib/sinonjs/sinon-1.17.3.js b/www/wiki/resources/lib/sinonjs/sinon-1.17.3.js
new file mode 100644
index 00000000..d77b3175
--- /dev/null
+++ b/www/wiki/resources/lib/sinonjs/sinon-1.17.3.js
@@ -0,0 +1,6437 @@
+/**
+ * Sinon.JS 1.17.3, 2016/01/27
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @author Contributors: https://github.com/cjohansen/Sinon.JS/blob/master/AUTHORS
+ *
+ * (The BSD License)
+ *
+ * Copyright (c) 2010-2014, Christian Johansen, christian@cjohansen.no
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * * Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ * * Neither the name of Christian Johansen nor the names of his contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+(function (root, factory) {
+ 'use strict';
+ if (typeof define === 'function' && define.amd) {
+ define('sinon', [], function () {
+ return (root.sinon = factory());
+ });
+ } else if (typeof exports === 'object') {
+ module.exports = factory();
+ } else {
+ root.sinon = factory();
+ }
+}(this, function () {
+ 'use strict';
+ var samsam, formatio, lolex;
+ (function () {
+ function define(mod, deps, fn) {
+ if (mod == "samsam") {
+ samsam = deps();
+ } else if (typeof deps === "function" && mod.length === 0) {
+ lolex = deps();
+ } else if (typeof fn === "function") {
+ formatio = fn(samsam);
+ }
+ }
+ define.amd = {};
+((typeof define === "function" && define.amd && function (m) { define("samsam", m); }) ||
+ (typeof module === "object" &&
+ function (m) { module.exports = m(); }) || // Node
+ function (m) { this.samsam = m(); } // Browser globals
+)(function () {
+ var o = Object.prototype;
+ var div = typeof document !== "undefined" && document.createElement("div");
+
+ function isNaN(value) {
+ // Unlike global isNaN, this avoids type coercion
+ // typeof check avoids IE host object issues, hat tip to
+ // lodash
+ var val = value; // JsLint thinks value !== value is "weird"
+ return typeof value === "number" && value !== val;
+ }
+
+ function getClass(value) {
+ // Returns the internal [[Class]] by calling Object.prototype.toString
+ // with the provided value as this. Return value is a string, naming the
+ // internal class, e.g. "Array"
+ return o.toString.call(value).split(/[ \]]/)[1];
+ }
+
+ /**
+ * @name samsam.isArguments
+ * @param Object object
+ *
+ * Returns ``true`` if ``object`` is an ``arguments`` object,
+ * ``false`` otherwise.
+ */
+ function isArguments(object) {
+ if (getClass(object) === 'Arguments') { return true; }
+ if (typeof object !== "object" || typeof object.length !== "number" ||
+ getClass(object) === "Array") {
+ return false;
+ }
+ if (typeof object.callee == "function") { return true; }
+ try {
+ object[object.length] = 6;
+ delete object[object.length];
+ } catch (e) {
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * @name samsam.isElement
+ * @param Object object
+ *
+ * Returns ``true`` if ``object`` is a DOM element node. Unlike
+ * Underscore.js/lodash, this function will return ``false`` if ``object``
+ * is an *element-like* object, i.e. a regular object with a ``nodeType``
+ * property that holds the value ``1``.
+ */
+ function isElement(object) {
+ if (!object || object.nodeType !== 1 || !div) { return false; }
+ try {
+ object.appendChild(div);
+ object.removeChild(div);
+ } catch (e) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * @name samsam.keys
+ * @param Object object
+ *
+ * Return an array of own property names.
+ */
+ function keys(object) {
+ var ks = [], prop;
+ for (prop in object) {
+ if (o.hasOwnProperty.call(object, prop)) { ks.push(prop); }
+ }
+ return ks;
+ }
+
+ /**
+ * @name samsam.isDate
+ * @param Object value
+ *
+ * Returns true if the object is a ``Date``, or *date-like*. Duck typing
+ * of date objects work by checking that the object has a ``getTime``
+ * function whose return value equals the return value from the object's
+ * ``valueOf``.
+ */
+ function isDate(value) {
+ return typeof value.getTime == "function" &&
+ value.getTime() == value.valueOf();
+ }
+
+ /**
+ * @name samsam.isNegZero
+ * @param Object value
+ *
+ * Returns ``true`` if ``value`` is ``-0``.
+ */
+ function isNegZero(value) {
+ return value === 0 && 1 / value === -Infinity;
+ }
+
+ /**
+ * @name samsam.equal
+ * @param Object obj1
+ * @param Object obj2
+ *
+ * Returns ``true`` if two objects are strictly equal. Compared to
+ * ``===`` there are two exceptions:
+ *
+ * - NaN is considered equal to NaN
+ * - -0 and +0 are not considered equal
+ */
+ function identical(obj1, obj2) {
+ if (obj1 === obj2 || (isNaN(obj1) && isNaN(obj2))) {
+ return obj1 !== 0 || isNegZero(obj1) === isNegZero(obj2);
+ }
+ }
+
+
+ /**
+ * @name samsam.deepEqual
+ * @param Object obj1
+ * @param Object obj2
+ *
+ * Deep equal comparison. Two values are "deep equal" if:
+ *
+ * - They are equal, according to samsam.identical
+ * - They are both date objects representing the same time
+ * - They are both arrays containing elements that are all deepEqual
+ * - They are objects with the same set of properties, and each property
+ * in ``obj1`` is deepEqual to the corresponding property in ``obj2``
+ *
+ * Supports cyclic objects.
+ */
+ function deepEqualCyclic(obj1, obj2) {
+
+ // used for cyclic comparison
+ // contain already visited objects
+ var objects1 = [],
+ objects2 = [],
+ // contain pathes (position in the object structure)
+ // of the already visited objects
+ // indexes same as in objects arrays
+ paths1 = [],
+ paths2 = [],
+ // contains combinations of already compared objects
+ // in the manner: { "$1['ref']$2['ref']": true }
+ compared = {};
+
+ /**
+ * used to check, if the value of a property is an object
+ * (cyclic logic is only needed for objects)
+ * only needed for cyclic logic
+ */
+ function isObject(value) {
+
+ if (typeof value === 'object' && value !== null &&
+ !(value instanceof Boolean) &&
+ !(value instanceof Date) &&
+ !(value instanceof Number) &&
+ !(value instanceof RegExp) &&
+ !(value instanceof String)) {
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * returns the index of the given object in the
+ * given objects array, -1 if not contained
+ * only needed for cyclic logic
+ */
+ function getIndex(objects, obj) {
+
+ var i;
+ for (i = 0; i < objects.length; i++) {
+ if (objects[i] === obj) {
+ return i;
+ }
+ }
+
+ return -1;
+ }
+
+ // does the recursion for the deep equal check
+ return (function deepEqual(obj1, obj2, path1, path2) {
+ var type1 = typeof obj1;
+ var type2 = typeof obj2;
+
+ // == null also matches undefined
+ if (obj1 === obj2 ||
+ isNaN(obj1) || isNaN(obj2) ||
+ obj1 == null || obj2 == null ||
+ type1 !== "object" || type2 !== "object") {
+
+ return identical(obj1, obj2);
+ }
+
+ // Elements are only equal if identical(expected, actual)
+ if (isElement(obj1) || isElement(obj2)) { return false; }
+
+ var isDate1 = isDate(obj1), isDate2 = isDate(obj2);
+ if (isDate1 || isDate2) {
+ if (!isDate1 || !isDate2 || obj1.getTime() !== obj2.getTime()) {
+ return false;
+ }
+ }
+
+ if (obj1 instanceof RegExp && obj2 instanceof RegExp) {
+ if (obj1.toString() !== obj2.toString()) { return false; }
+ }
+
+ var class1 = getClass(obj1);
+ var class2 = getClass(obj2);
+ var keys1 = keys(obj1);
+ var keys2 = keys(obj2);
+
+ if (isArguments(obj1) || isArguments(obj2)) {
+ if (obj1.length !== obj2.length) { return false; }
+ } else {
+ if (type1 !== type2 || class1 !== class2 ||
+ keys1.length !== keys2.length) {
+ return false;
+ }
+ }
+
+ var key, i, l,
+ // following vars are used for the cyclic logic
+ value1, value2,
+ isObject1, isObject2,
+ index1, index2,
+ newPath1, newPath2;
+
+ for (i = 0, l = keys1.length; i < l; i++) {
+ key = keys1[i];
+ if (!o.hasOwnProperty.call(obj2, key)) {
+ return false;
+ }
+
+ // Start of the cyclic logic
+
+ value1 = obj1[key];
+ value2 = obj2[key];
+
+ isObject1 = isObject(value1);
+ isObject2 = isObject(value2);
+
+ // determine, if the objects were already visited
+ // (it's faster to check for isObject first, than to
+ // get -1 from getIndex for non objects)
+ index1 = isObject1 ? getIndex(objects1, value1) : -1;
+ index2 = isObject2 ? getIndex(objects2, value2) : -1;
+
+ // determine the new pathes of the objects
+ // - for non cyclic objects the current path will be extended
+ // by current property name
+ // - for cyclic objects the stored path is taken
+ newPath1 = index1 !== -1
+ ? paths1[index1]
+ : path1 + '[' + JSON.stringify(key) + ']';
+ newPath2 = index2 !== -1
+ ? paths2[index2]
+ : path2 + '[' + JSON.stringify(key) + ']';
+
+ // stop recursion if current objects are already compared
+ if (compared[newPath1 + newPath2]) {
+ return true;
+ }
+
+ // remember the current objects and their pathes
+ if (index1 === -1 && isObject1) {
+ objects1.push(value1);
+ paths1.push(newPath1);
+ }
+ if (index2 === -1 && isObject2) {
+ objects2.push(value2);
+ paths2.push(newPath2);
+ }
+
+ // remember that the current objects are already compared
+ if (isObject1 && isObject2) {
+ compared[newPath1 + newPath2] = true;
+ }
+
+ // End of cyclic logic
+
+ // neither value1 nor value2 is a cycle
+ // continue with next level
+ if (!deepEqual(value1, value2, newPath1, newPath2)) {
+ return false;
+ }
+ }
+
+ return true;
+
+ }(obj1, obj2, '$1', '$2'));
+ }
+
+ var match;
+
+ function arrayContains(array, subset) {
+ if (subset.length === 0) { return true; }
+ var i, l, j, k;
+ for (i = 0, l = array.length; i < l; ++i) {
+ if (match(array[i], subset[0])) {
+ for (j = 0, k = subset.length; j < k; ++j) {
+ if (!match(array[i + j], subset[j])) { return false; }
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * @name samsam.match
+ * @param Object object
+ * @param Object matcher
+ *
+ * Compare arbitrary value ``object`` with matcher.
+ */
+ match = function match(object, matcher) {
+ if (matcher && typeof matcher.test === "function") {
+ return matcher.test(object);
+ }
+
+ if (typeof matcher === "function") {
+ return matcher(object) === true;
+ }
+
+ if (typeof matcher === "string") {
+ matcher = matcher.toLowerCase();
+ var notNull = typeof object === "string" || !!object;
+ return notNull &&
+ (String(object)).toLowerCase().indexOf(matcher) >= 0;
+ }
+
+ if (typeof matcher === "number") {
+ return matcher === object;
+ }
+
+ if (typeof matcher === "boolean") {
+ return matcher === object;
+ }
+
+ if (typeof(matcher) === "undefined") {
+ return typeof(object) === "undefined";
+ }
+
+ if (matcher === null) {
+ return object === null;
+ }
+
+ if (getClass(object) === "Array" && getClass(matcher) === "Array") {
+ return arrayContains(object, matcher);
+ }
+
+ if (matcher && typeof matcher === "object") {
+ if (matcher === object) {
+ return true;
+ }
+ var prop;
+ for (prop in matcher) {
+ var value = object[prop];
+ if (typeof value === "undefined" &&
+ typeof object.getAttribute === "function") {
+ value = object.getAttribute(prop);
+ }
+ if (matcher[prop] === null || typeof matcher[prop] === 'undefined') {
+ if (value !== matcher[prop]) {
+ return false;
+ }
+ } else if (typeof value === "undefined" || !match(value, matcher[prop])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ throw new Error("Matcher was not a string, a number, a " +
+ "function, a boolean or an object");
+ };
+
+ return {
+ isArguments: isArguments,
+ isElement: isElement,
+ isDate: isDate,
+ isNegZero: isNegZero,
+ identical: identical,
+ deepEqual: deepEqualCyclic,
+ match: match,
+ keys: keys
+ };
+});
+((typeof define === "function" && define.amd && function (m) {
+ define("formatio", ["samsam"], m);
+}) || (typeof module === "object" && function (m) {
+ module.exports = m(require("samsam"));
+}) || function (m) { this.formatio = m(this.samsam); }
+)(function (samsam) {
+
+ var formatio = {
+ excludeConstructors: ["Object", /^.$/],
+ quoteStrings: true,
+ limitChildrenCount: 0
+ };
+
+ var hasOwn = Object.prototype.hasOwnProperty;
+
+ var specialObjects = [];
+ if (typeof global !== "undefined") {
+ specialObjects.push({ object: global, value: "[object global]" });
+ }
+ if (typeof document !== "undefined") {
+ specialObjects.push({
+ object: document,
+ value: "[object HTMLDocument]"
+ });
+ }
+ if (typeof window !== "undefined") {
+ specialObjects.push({ object: window, value: "[object Window]" });
+ }
+
+ function functionName(func) {
+ if (!func) { return ""; }
+ if (func.displayName) { return func.displayName; }
+ if (func.name) { return func.name; }
+ var matches = func.toString().match(/function\s+([^\(]+)/m);
+ return (matches && matches[1]) || "";
+ }
+
+ function constructorName(f, object) {
+ var name = functionName(object && object.constructor);
+ var excludes = f.excludeConstructors ||
+ formatio.excludeConstructors || [];
+
+ var i, l;
+ for (i = 0, l = excludes.length; i < l; ++i) {
+ if (typeof excludes[i] === "string" && excludes[i] === name) {
+ return "";
+ } else if (excludes[i].test && excludes[i].test(name)) {
+ return "";
+ }
+ }
+
+ return name;
+ }
+
+ function isCircular(object, objects) {
+ if (typeof object !== "object") { return false; }
+ var i, l;
+ for (i = 0, l = objects.length; i < l; ++i) {
+ if (objects[i] === object) { return true; }
+ }
+ return false;
+ }
+
+ function ascii(f, object, processed, indent) {
+ if (typeof object === "string") {
+ var qs = f.quoteStrings;
+ var quote = typeof qs !== "boolean" || qs;
+ return processed || quote ? '"' + object + '"' : object;
+ }
+
+ if (typeof object === "function" && !(object instanceof RegExp)) {
+ return ascii.func(object);
+ }
+
+ processed = processed || [];
+
+ if (isCircular(object, processed)) { return "[Circular]"; }
+
+ if (Object.prototype.toString.call(object) === "[object Array]") {
+ return ascii.array.call(f, object, processed);
+ }
+
+ if (!object) { return String((1/object) === -Infinity ? "-0" : object); }
+ if (samsam.isElement(object)) { return ascii.element(object); }
+
+ if (typeof object.toString === "function" &&
+ object.toString !== Object.prototype.toString) {
+ return object.toString();
+ }
+
+ var i, l;
+ for (i = 0, l = specialObjects.length; i < l; i++) {
+ if (object === specialObjects[i].object) {
+ return specialObjects[i].value;
+ }
+ }
+
+ return ascii.object.call(f, object, processed, indent);
+ }
+
+ ascii.func = function (func) {
+ return "function " + functionName(func) + "() {}";
+ };
+
+ ascii.array = function (array, processed) {
+ processed = processed || [];
+ processed.push(array);
+ var pieces = [];
+ var i, l;
+ l = (this.limitChildrenCount > 0) ?
+ Math.min(this.limitChildrenCount, array.length) : array.length;
+
+ for (i = 0; i < l; ++i) {
+ pieces.push(ascii(this, array[i], processed));
+ }
+
+ if(l < array.length)
+ pieces.push("[... " + (array.length - l) + " more elements]");
+
+ return "[" + pieces.join(", ") + "]";
+ };
+
+ ascii.object = function (object, processed, indent) {
+ processed = processed || [];
+ processed.push(object);
+ indent = indent || 0;
+ var pieces = [], properties = samsam.keys(object).sort();
+ var length = 3;
+ var prop, str, obj, i, k, l;
+ l = (this.limitChildrenCount > 0) ?
+ Math.min(this.limitChildrenCount, properties.length) : properties.length;
+
+ for (i = 0; i < l; ++i) {
+ prop = properties[i];
+ obj = object[prop];
+
+ if (isCircular(obj, processed)) {
+ str = "[Circular]";
+ } else {
+ str = ascii(this, obj, processed, indent + 2);
+ }
+
+ str = (/\s/.test(prop) ? '"' + prop + '"' : prop) + ": " + str;
+ length += str.length;
+ pieces.push(str);
+ }
+
+ var cons = constructorName(this, object);
+ var prefix = cons ? "[" + cons + "] " : "";
+ var is = "";
+ for (i = 0, k = indent; i < k; ++i) { is += " "; }
+
+ if(l < properties.length)
+ pieces.push("[... " + (properties.length - l) + " more elements]");
+
+ if (length + indent > 80) {
+ return prefix + "{\n " + is + pieces.join(",\n " + is) + "\n" +
+ is + "}";
+ }
+ return prefix + "{ " + pieces.join(", ") + " }";
+ };
+
+ ascii.element = function (element) {
+ var tagName = element.tagName.toLowerCase();
+ var attrs = element.attributes, attr, pairs = [], attrName, i, l, val;
+
+ for (i = 0, l = attrs.length; i < l; ++i) {
+ attr = attrs.item(i);
+ attrName = attr.nodeName.toLowerCase().replace("html:", "");
+ val = attr.nodeValue;
+ if (attrName !== "contenteditable" || val !== "inherit") {
+ if (!!val) { pairs.push(attrName + "=\"" + val + "\""); }
+ }
+ }
+
+ var formatted = "<" + tagName + (pairs.length > 0 ? " " : "");
+ var content = element.innerHTML;
+
+ if (content.length > 20) {
+ content = content.substr(0, 20) + "[...]";
+ }
+
+ var res = formatted + pairs.join(" ") + ">" + content +
+ "</" + tagName + ">";
+
+ return res.replace(/ contentEditable="inherit"/, "");
+ };
+
+ function Formatio(options) {
+ for (var opt in options) {
+ this[opt] = options[opt];
+ }
+ }
+
+ Formatio.prototype = {
+ functionName: functionName,
+
+ configure: function (options) {
+ return new Formatio(options);
+ },
+
+ constructorName: function (object) {
+ return constructorName(this, object);
+ },
+
+ ascii: function (object, processed, indent) {
+ return ascii(this, object, processed, indent);
+ }
+ };
+
+ return Formatio.prototype;
+});
+!function(e){if("object"==typeof exports&&"undefined"!=typeof module)module.exports=e();else if("function"==typeof define&&define.amd)define([],e);else{var f;"undefined"!=typeof window?f=window:"undefined"!=typeof global?f=global:"undefined"!=typeof self&&(f=self),f.lolex=e()}}(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
+(function (global){
+/*global global, window*/
+/**
+ * @author Christian Johansen (christian@cjohansen.no) and contributors
+ * @license BSD
+ *
+ * Copyright (c) 2010-2014 Christian Johansen
+ */
+
+(function (global) {
+
+ // Make properties writable in IE, as per
+ // http://www.adequatelygood.com/Replacing-setTimeout-Globally.html
+ // JSLint being anal
+ var glbl = global;
+
+ global.setTimeout = glbl.setTimeout;
+ global.clearTimeout = glbl.clearTimeout;
+ global.setInterval = glbl.setInterval;
+ global.clearInterval = glbl.clearInterval;
+ global.Date = glbl.Date;
+
+ // setImmediate is not a standard function
+ // avoid adding the prop to the window object if not present
+ if('setImmediate' in global) {
+ global.setImmediate = glbl.setImmediate;
+ global.clearImmediate = glbl.clearImmediate;
+ }
+
+ // node expects setTimeout/setInterval to return a fn object w/ .ref()/.unref()
+ // browsers, a number.
+ // see https://github.com/cjohansen/Sinon.JS/pull/436
+
+ var NOOP = function () { return undefined; };
+ var timeoutResult = setTimeout(NOOP, 0);
+ var addTimerReturnsObject = typeof timeoutResult === "object";
+ clearTimeout(timeoutResult);
+
+ var NativeDate = Date;
+ var uniqueTimerId = 1;
+
+ /**
+ * Parse strings like "01:10:00" (meaning 1 hour, 10 minutes, 0 seconds) into
+ * number of milliseconds. This is used to support human-readable strings passed
+ * to clock.tick()
+ */
+ function parseTime(str) {
+ if (!str) {
+ return 0;
+ }
+
+ var strings = str.split(":");
+ var l = strings.length, i = l;
+ var ms = 0, parsed;
+
+ if (l > 3 || !/^(\d\d:){0,2}\d\d?$/.test(str)) {
+ throw new Error("tick only understands numbers, 'm:s' and 'h:m:s'. Each part must be two digits");
+ }
+
+ while (i--) {
+ parsed = parseInt(strings[i], 10);
+
+ if (parsed >= 60) {
+ throw new Error("Invalid time " + str);
+ }
+
+ ms += parsed * Math.pow(60, (l - i - 1));
+ }
+
+ return ms * 1000;
+ }
+
+ /**
+ * Used to grok the `now` parameter to createClock.
+ */
+ function getEpoch(epoch) {
+ if (!epoch) { return 0; }
+ if (typeof epoch.getTime === "function") { return epoch.getTime(); }
+ if (typeof epoch === "number") { return epoch; }
+ throw new TypeError("now should be milliseconds since UNIX epoch");
+ }
+
+ function inRange(from, to, timer) {
+ return timer && timer.callAt >= from && timer.callAt <= to;
+ }
+
+ function mirrorDateProperties(target, source) {
+ var prop;
+ for (prop in source) {
+ if (source.hasOwnProperty(prop)) {
+ target[prop] = source[prop];
+ }
+ }
+
+ // set special now implementation
+ if (source.now) {
+ target.now = function now() {
+ return target.clock.now;
+ };
+ } else {
+ delete target.now;
+ }
+
+ // set special toSource implementation
+ if (source.toSource) {
+ target.toSource = function toSource() {
+ return source.toSource();
+ };
+ } else {
+ delete target.toSource;
+ }
+
+ // set special toString implementation
+ target.toString = function toString() {
+ return source.toString();
+ };
+
+ target.prototype = source.prototype;
+ target.parse = source.parse;
+ target.UTC = source.UTC;
+ target.prototype.toUTCString = source.prototype.toUTCString;
+
+ return target;
+ }
+
+ function createDate() {
+ function ClockDate(year, month, date, hour, minute, second, ms) {
+ // Defensive and verbose to avoid potential harm in passing
+ // explicit undefined when user does not pass argument
+ switch (arguments.length) {
+ case 0:
+ return new NativeDate(ClockDate.clock.now);
+ case 1:
+ return new NativeDate(year);
+ case 2:
+ return new NativeDate(year, month);
+ case 3:
+ return new NativeDate(year, month, date);
+ case 4:
+ return new NativeDate(year, month, date, hour);
+ case 5:
+ return new NativeDate(year, month, date, hour, minute);
+ case 6:
+ return new NativeDate(year, month, date, hour, minute, second);
+ default:
+ return new NativeDate(year, month, date, hour, minute, second, ms);
+ }
+ }
+
+ return mirrorDateProperties(ClockDate, NativeDate);
+ }
+
+ function addTimer(clock, timer) {
+ if (timer.func === undefined) {
+ throw new Error("Callback must be provided to timer calls");
+ }
+
+ if (!clock.timers) {
+ clock.timers = {};
+ }
+
+ timer.id = uniqueTimerId++;
+ timer.createdAt = clock.now;
+ timer.callAt = clock.now + (timer.delay || (clock.duringTick ? 1 : 0));
+
+ clock.timers[timer.id] = timer;
+
+ if (addTimerReturnsObject) {
+ return {
+ id: timer.id,
+ ref: NOOP,
+ unref: NOOP
+ };
+ }
+
+ return timer.id;
+ }
+
+
+ function compareTimers(a, b) {
+ // Sort first by absolute timing
+ if (a.callAt < b.callAt) {
+ return -1;
+ }
+ if (a.callAt > b.callAt) {
+ return 1;
+ }
+
+ // Sort next by immediate, immediate timers take precedence
+ if (a.immediate && !b.immediate) {
+ return -1;
+ }
+ if (!a.immediate && b.immediate) {
+ return 1;
+ }
+
+ // Sort next by creation time, earlier-created timers take precedence
+ if (a.createdAt < b.createdAt) {
+ return -1;
+ }
+ if (a.createdAt > b.createdAt) {
+ return 1;
+ }
+
+ // Sort next by id, lower-id timers take precedence
+ if (a.id < b.id) {
+ return -1;
+ }
+ if (a.id > b.id) {
+ return 1;
+ }
+
+ // As timer ids are unique, no fallback `0` is necessary
+ }
+
+ function firstTimerInRange(clock, from, to) {
+ var timers = clock.timers,
+ timer = null,
+ id,
+ isInRange;
+
+ for (id in timers) {
+ if (timers.hasOwnProperty(id)) {
+ isInRange = inRange(from, to, timers[id]);
+
+ if (isInRange && (!timer || compareTimers(timer, timers[id]) === 1)) {
+ timer = timers[id];
+ }
+ }
+ }
+
+ return timer;
+ }
+
+ function firstTimer(clock) {
+ var timers = clock.timers,
+ timer = null,
+ id;
+
+ for (id in timers) {
+ if (timers.hasOwnProperty(id)) {
+ if (!timer || compareTimers(timer, timers[id]) === 1) {
+ timer = timers[id];
+ }
+ }
+ }
+
+ return timer;
+ }
+
+ function callTimer(clock, timer) {
+ var exception;
+
+ if (typeof timer.interval === "number") {
+ clock.timers[timer.id].callAt += timer.interval;
+ } else {
+ delete clock.timers[timer.id];
+ }
+
+ try {
+ if (typeof timer.func === "function") {
+ timer.func.apply(null, timer.args);
+ } else {
+ eval(timer.func);
+ }
+ } catch (e) {
+ exception = e;
+ }
+
+ if (!clock.timers[timer.id]) {
+ if (exception) {
+ throw exception;
+ }
+ return;
+ }
+
+ if (exception) {
+ throw exception;
+ }
+ }
+
+ function timerType(timer) {
+ if (timer.immediate) {
+ return "Immediate";
+ } else if (typeof timer.interval !== "undefined") {
+ return "Interval";
+ } else {
+ return "Timeout";
+ }
+ }
+
+ function clearTimer(clock, timerId, ttype) {
+ if (!timerId) {
+ // null appears to be allowed in most browsers, and appears to be
+ // relied upon by some libraries, like Bootstrap carousel
+ return;
+ }
+
+ if (!clock.timers) {
+ clock.timers = [];
+ }
+
+ // in Node, timerId is an object with .ref()/.unref(), and
+ // its .id field is the actual timer id.
+ if (typeof timerId === "object") {
+ timerId = timerId.id;
+ }
+
+ if (clock.timers.hasOwnProperty(timerId)) {
+ // check that the ID matches a timer of the correct type
+ var timer = clock.timers[timerId];
+ if (timerType(timer) === ttype) {
+ delete clock.timers[timerId];
+ } else {
+ throw new Error("Cannot clear timer: timer created with set" + ttype + "() but cleared with clear" + timerType(timer) + "()");
+ }
+ }
+ }
+
+ function uninstall(clock, target) {
+ var method,
+ i,
+ l;
+
+ for (i = 0, l = clock.methods.length; i < l; i++) {
+ method = clock.methods[i];
+
+ if (target[method].hadOwnProperty) {
+ target[method] = clock["_" + method];
+ } else {
+ try {
+ delete target[method];
+ } catch (ignore) {}
+ }
+ }
+
+ // Prevent multiple executions which will completely remove these props
+ clock.methods = [];
+ }
+
+ function hijackMethod(target, method, clock) {
+ var prop;
+
+ clock[method].hadOwnProperty = Object.prototype.hasOwnProperty.call(target, method);
+ clock["_" + method] = target[method];
+
+ if (method === "Date") {
+ var date = mirrorDateProperties(clock[method], target[method]);
+ target[method] = date;
+ } else {
+ target[method] = function () {
+ return clock[method].apply(clock, arguments);
+ };
+
+ for (prop in clock[method]) {
+ if (clock[method].hasOwnProperty(prop)) {
+ target[method][prop] = clock[method][prop];
+ }
+ }
+ }
+
+ target[method].clock = clock;
+ }
+
+ var timers = {
+ setTimeout: setTimeout,
+ clearTimeout: clearTimeout,
+ setImmediate: global.setImmediate,
+ clearImmediate: global.clearImmediate,
+ setInterval: setInterval,
+ clearInterval: clearInterval,
+ Date: Date
+ };
+
+ var keys = Object.keys || function (obj) {
+ var ks = [],
+ key;
+
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) {
+ ks.push(key);
+ }
+ }
+
+ return ks;
+ };
+
+ exports.timers = timers;
+
+ function createClock(now) {
+ var clock = {
+ now: getEpoch(now),
+ timeouts: {},
+ Date: createDate()
+ };
+
+ clock.Date.clock = clock;
+
+ clock.setTimeout = function setTimeout(func, timeout) {
+ return addTimer(clock, {
+ func: func,
+ args: Array.prototype.slice.call(arguments, 2),
+ delay: timeout
+ });
+ };
+
+ clock.clearTimeout = function clearTimeout(timerId) {
+ return clearTimer(clock, timerId, "Timeout");
+ };
+
+ clock.setInterval = function setInterval(func, timeout) {
+ return addTimer(clock, {
+ func: func,
+ args: Array.prototype.slice.call(arguments, 2),
+ delay: timeout,
+ interval: timeout
+ });
+ };
+
+ clock.clearInterval = function clearInterval(timerId) {
+ return clearTimer(clock, timerId, "Interval");
+ };
+
+ clock.setImmediate = function setImmediate(func) {
+ return addTimer(clock, {
+ func: func,
+ args: Array.prototype.slice.call(arguments, 1),
+ immediate: true
+ });
+ };
+
+ clock.clearImmediate = function clearImmediate(timerId) {
+ return clearTimer(clock, timerId, "Immediate");
+ };
+
+ clock.tick = function tick(ms) {
+ ms = typeof ms === "number" ? ms : parseTime(ms);
+ var tickFrom = clock.now, tickTo = clock.now + ms, previous = clock.now;
+ var timer = firstTimerInRange(clock, tickFrom, tickTo);
+ var oldNow;
+
+ clock.duringTick = true;
+
+ var firstException;
+ while (timer && tickFrom <= tickTo) {
+ if (clock.timers[timer.id]) {
+ tickFrom = clock.now = timer.callAt;
+ try {
+ oldNow = clock.now;
+ callTimer(clock, timer);
+ // compensate for any setSystemTime() call during timer callback
+ if (oldNow !== clock.now) {
+ tickFrom += clock.now - oldNow;
+ tickTo += clock.now - oldNow;
+ previous += clock.now - oldNow;
+ }
+ } catch (e) {
+ firstException = firstException || e;
+ }
+ }
+
+ timer = firstTimerInRange(clock, previous, tickTo);
+ previous = tickFrom;
+ }
+
+ clock.duringTick = false;
+ clock.now = tickTo;
+
+ if (firstException) {
+ throw firstException;
+ }
+
+ return clock.now;
+ };
+
+ clock.next = function next() {
+ var timer = firstTimer(clock);
+ if (!timer) {
+ return clock.now;
+ }
+
+ clock.duringTick = true;
+ try {
+ clock.now = timer.callAt;
+ callTimer(clock, timer);
+ return clock.now;
+ } finally {
+ clock.duringTick = false;
+ }
+ };
+
+ clock.reset = function reset() {
+ clock.timers = {};
+ };
+
+ clock.setSystemTime = function setSystemTime(now) {
+ // determine time difference
+ var newNow = getEpoch(now);
+ var difference = newNow - clock.now;
+
+ // update 'system clock'
+ clock.now = newNow;
+
+ // update timers and intervals to keep them stable
+ for (var id in clock.timers) {
+ if (clock.timers.hasOwnProperty(id)) {
+ var timer = clock.timers[id];
+ timer.createdAt += difference;
+ timer.callAt += difference;
+ }
+ }
+ };
+
+ return clock;
+ }
+ exports.createClock = createClock;
+
+ exports.install = function install(target, now, toFake) {
+ var i,
+ l;
+
+ if (typeof target === "number") {
+ toFake = now;
+ now = target;
+ target = null;
+ }
+
+ if (!target) {
+ target = global;
+ }
+
+ var clock = createClock(now);
+
+ clock.uninstall = function () {
+ uninstall(clock, target);
+ };
+
+ clock.methods = toFake || [];
+
+ if (clock.methods.length === 0) {
+ clock.methods = keys(timers);
+ }
+
+ for (i = 0, l = clock.methods.length; i < l; i++) {
+ hijackMethod(target, clock.methods[i], clock);
+ }
+
+ return clock;
+ };
+
+}(global || this));
+
+}).call(this,typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : typeof window !== "undefined" ? window : {})
+},{}]},{},[1])(1)
+});
+ })();
+ var define;
+/**
+ * Sinon core utilities. For internal use only.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+var sinon = (function () {
+"use strict";
+ // eslint-disable-line no-unused-vars
+
+ var sinonModule;
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ sinonModule = module.exports = require("./sinon/util/core");
+ require("./sinon/extend");
+ require("./sinon/walk");
+ require("./sinon/typeOf");
+ require("./sinon/times_in_words");
+ require("./sinon/spy");
+ require("./sinon/call");
+ require("./sinon/behavior");
+ require("./sinon/stub");
+ require("./sinon/mock");
+ require("./sinon/collection");
+ require("./sinon/assert");
+ require("./sinon/sandbox");
+ require("./sinon/test");
+ require("./sinon/test_case");
+ require("./sinon/match");
+ require("./sinon/format");
+ require("./sinon/log_error");
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ } else if (isNode) {
+ loadDependencies(require, module.exports, module);
+ sinonModule = module.exports;
+ } else {
+ sinonModule = {};
+ }
+
+ return sinonModule;
+}());
+
+/**
+ * @depend ../../sinon.js
+ */
+/**
+ * Sinon core utilities. For internal use only.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+
+ var div = typeof document !== "undefined" && document.createElement("div");
+ var hasOwn = Object.prototype.hasOwnProperty;
+
+ function isDOMNode(obj) {
+ var success = false;
+
+ try {
+ obj.appendChild(div);
+ success = div.parentNode === obj;
+ } catch (e) {
+ return false;
+ } finally {
+ try {
+ obj.removeChild(div);
+ } catch (e) {
+ // Remove failed, not much we can do about that
+ }
+ }
+
+ return success;
+ }
+
+ function isElement(obj) {
+ return div && obj && obj.nodeType === 1 && isDOMNode(obj);
+ }
+
+ function isFunction(obj) {
+ return typeof obj === "function" || !!(obj && obj.constructor && obj.call && obj.apply);
+ }
+
+ function isReallyNaN(val) {
+ return typeof val === "number" && isNaN(val);
+ }
+
+ function mirrorProperties(target, source) {
+ for (var prop in source) {
+ if (!hasOwn.call(target, prop)) {
+ target[prop] = source[prop];
+ }
+ }
+ }
+
+ function isRestorable(obj) {
+ return typeof obj === "function" && typeof obj.restore === "function" && obj.restore.sinon;
+ }
+
+ // Cheap way to detect if we have ES5 support.
+ var hasES5Support = "keys" in Object;
+
+ function makeApi(sinon) {
+ sinon.wrapMethod = function wrapMethod(object, property, method) {
+ if (!object) {
+ throw new TypeError("Should wrap property of object");
+ }
+
+ if (typeof method !== "function" && typeof method !== "object") {
+ throw new TypeError("Method wrapper should be a function or a property descriptor");
+ }
+
+ function checkWrappedMethod(wrappedMethod) {
+ var error;
+
+ if (!isFunction(wrappedMethod)) {
+ error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
+ property + " as function");
+ } else if (wrappedMethod.restore && wrappedMethod.restore.sinon) {
+ error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
+ } else if (wrappedMethod.calledBefore) {
+ var verb = wrappedMethod.returns ? "stubbed" : "spied on";
+ error = new TypeError("Attempted to wrap " + property + " which is already " + verb);
+ }
+
+ if (error) {
+ if (wrappedMethod && wrappedMethod.stackTrace) {
+ error.stack += "\n--------------\n" + wrappedMethod.stackTrace;
+ }
+ throw error;
+ }
+ }
+
+ var error, wrappedMethod, i;
+
+ // IE 8 does not support hasOwnProperty on the window object and Firefox has a problem
+ // when using hasOwn.call on objects from other frames.
+ var owned = object.hasOwnProperty ? object.hasOwnProperty(property) : hasOwn.call(object, property);
+
+ if (hasES5Support) {
+ var methodDesc = (typeof method === "function") ? {value: method} : method;
+ var wrappedMethodDesc = sinon.getPropertyDescriptor(object, property);
+
+ if (!wrappedMethodDesc) {
+ error = new TypeError("Attempted to wrap " + (typeof wrappedMethod) + " property " +
+ property + " as function");
+ } else if (wrappedMethodDesc.restore && wrappedMethodDesc.restore.sinon) {
+ error = new TypeError("Attempted to wrap " + property + " which is already wrapped");
+ }
+ if (error) {
+ if (wrappedMethodDesc && wrappedMethodDesc.stackTrace) {
+ error.stack += "\n--------------\n" + wrappedMethodDesc.stackTrace;
+ }
+ throw error;
+ }
+
+ var types = sinon.objectKeys(methodDesc);
+ for (i = 0; i < types.length; i++) {
+ wrappedMethod = wrappedMethodDesc[types[i]];
+ checkWrappedMethod(wrappedMethod);
+ }
+
+ mirrorProperties(methodDesc, wrappedMethodDesc);
+ for (i = 0; i < types.length; i++) {
+ mirrorProperties(methodDesc[types[i]], wrappedMethodDesc[types[i]]);
+ }
+ Object.defineProperty(object, property, methodDesc);
+ } else {
+ wrappedMethod = object[property];
+ checkWrappedMethod(wrappedMethod);
+ object[property] = method;
+ method.displayName = property;
+ }
+
+ method.displayName = property;
+
+ // Set up a stack trace which can be used later to find what line of
+ // code the original method was created on.
+ method.stackTrace = (new Error("Stack Trace for original")).stack;
+
+ method.restore = function () {
+ // For prototype properties try to reset by delete first.
+ // If this fails (ex: localStorage on mobile safari) then force a reset
+ // via direct assignment.
+ if (!owned) {
+ // In some cases `delete` may throw an error
+ try {
+ delete object[property];
+ } catch (e) {} // eslint-disable-line no-empty
+ // For native code functions `delete` fails without throwing an error
+ // on Chrome < 43, PhantomJS, etc.
+ } else if (hasES5Support) {
+ Object.defineProperty(object, property, wrappedMethodDesc);
+ }
+
+ // Use strict equality comparison to check failures then force a reset
+ // via direct assignment.
+ if (object[property] === method) {
+ object[property] = wrappedMethod;
+ }
+ };
+
+ method.restore.sinon = true;
+
+ if (!hasES5Support) {
+ mirrorProperties(method, wrappedMethod);
+ }
+
+ return method;
+ };
+
+ sinon.create = function create(proto) {
+ var F = function () {};
+ F.prototype = proto;
+ return new F();
+ };
+
+ sinon.deepEqual = function deepEqual(a, b) {
+ if (sinon.match && sinon.match.isMatcher(a)) {
+ return a.test(b);
+ }
+
+ if (typeof a !== "object" || typeof b !== "object") {
+ return isReallyNaN(a) && isReallyNaN(b) || a === b;
+ }
+
+ if (isElement(a) || isElement(b)) {
+ return a === b;
+ }
+
+ if (a === b) {
+ return true;
+ }
+
+ if ((a === null && b !== null) || (a !== null && b === null)) {
+ return false;
+ }
+
+ if (a instanceof RegExp && b instanceof RegExp) {
+ return (a.source === b.source) && (a.global === b.global) &&
+ (a.ignoreCase === b.ignoreCase) && (a.multiline === b.multiline);
+ }
+
+ var aString = Object.prototype.toString.call(a);
+ if (aString !== Object.prototype.toString.call(b)) {
+ return false;
+ }
+
+ if (aString === "[object Date]") {
+ return a.valueOf() === b.valueOf();
+ }
+
+ var prop;
+ var aLength = 0;
+ var bLength = 0;
+
+ if (aString === "[object Array]" && a.length !== b.length) {
+ return false;
+ }
+
+ for (prop in a) {
+ if (a.hasOwnProperty(prop)) {
+ aLength += 1;
+
+ if (!(prop in b)) {
+ return false;
+ }
+
+ if (!deepEqual(a[prop], b[prop])) {
+ return false;
+ }
+ }
+ }
+
+ for (prop in b) {
+ if (b.hasOwnProperty(prop)) {
+ bLength += 1;
+ }
+ }
+
+ return aLength === bLength;
+ };
+
+ sinon.functionName = function functionName(func) {
+ var name = func.displayName || func.name;
+
+ // Use function decomposition as a last resort to get function
+ // name. Does not rely on function decomposition to work - if it
+ // doesn't debugging will be slightly less informative
+ // (i.e. toString will say 'spy' rather than 'myFunc').
+ if (!name) {
+ var matches = func.toString().match(/function ([^\s\(]+)/);
+ name = matches && matches[1];
+ }
+
+ return name;
+ };
+
+ sinon.functionToString = function toString() {
+ if (this.getCall && this.callCount) {
+ var thisValue,
+ prop;
+ var i = this.callCount;
+
+ while (i--) {
+ thisValue = this.getCall(i).thisValue;
+
+ for (prop in thisValue) {
+ if (thisValue[prop] === this) {
+ return prop;
+ }
+ }
+ }
+ }
+
+ return this.displayName || "sinon fake";
+ };
+
+ sinon.objectKeys = function objectKeys(obj) {
+ if (obj !== Object(obj)) {
+ throw new TypeError("sinon.objectKeys called on a non-object");
+ }
+
+ var keys = [];
+ var key;
+ for (key in obj) {
+ if (hasOwn.call(obj, key)) {
+ keys.push(key);
+ }
+ }
+
+ return keys;
+ };
+
+ sinon.getPropertyDescriptor = function getPropertyDescriptor(object, property) {
+ var proto = object;
+ var descriptor;
+
+ while (proto && !(descriptor = Object.getOwnPropertyDescriptor(proto, property))) {
+ proto = Object.getPrototypeOf(proto);
+ }
+ return descriptor;
+ };
+
+ sinon.getConfig = function (custom) {
+ var config = {};
+ custom = custom || {};
+ var defaults = sinon.defaultConfig;
+
+ for (var prop in defaults) {
+ if (defaults.hasOwnProperty(prop)) {
+ config[prop] = custom.hasOwnProperty(prop) ? custom[prop] : defaults[prop];
+ }
+ }
+
+ return config;
+ };
+
+ sinon.defaultConfig = {
+ injectIntoThis: true,
+ injectInto: null,
+ properties: ["spy", "stub", "mock", "clock", "server", "requests"],
+ useFakeTimers: true,
+ useFakeServer: true
+ };
+
+ sinon.timesInWords = function timesInWords(count) {
+ return count === 1 && "once" ||
+ count === 2 && "twice" ||
+ count === 3 && "thrice" ||
+ (count || 0) + " times";
+ };
+
+ sinon.calledInOrder = function (spies) {
+ for (var i = 1, l = spies.length; i < l; i++) {
+ if (!spies[i - 1].calledBefore(spies[i]) || !spies[i].called) {
+ return false;
+ }
+ }
+
+ return true;
+ };
+
+ sinon.orderByFirstCall = function (spies) {
+ return spies.sort(function (a, b) {
+ // uuid, won't ever be equal
+ var aCall = a.getCall(0);
+ var bCall = b.getCall(0);
+ var aId = aCall && aCall.callId || -1;
+ var bId = bCall && bCall.callId || -1;
+
+ return aId < bId ? -1 : 1;
+ });
+ };
+
+ sinon.createStubInstance = function (constructor) {
+ if (typeof constructor !== "function") {
+ throw new TypeError("The constructor should be a function.");
+ }
+ return sinon.stub(sinon.create(constructor.prototype));
+ };
+
+ sinon.restore = function (object) {
+ if (object !== null && typeof object === "object") {
+ for (var prop in object) {
+ if (isRestorable(object[prop])) {
+ object[prop].restore();
+ }
+ }
+ } else if (isRestorable(object)) {
+ object.restore();
+ }
+ };
+
+ return sinon;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports) {
+ makeApi(exports);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ */
+(function (sinonGlobal) {
+
+ function makeApi(sinon) {
+
+ // Adapted from https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
+ var hasDontEnumBug = (function () {
+ var obj = {
+ constructor: function () {
+ return "0";
+ },
+ toString: function () {
+ return "1";
+ },
+ valueOf: function () {
+ return "2";
+ },
+ toLocaleString: function () {
+ return "3";
+ },
+ prototype: function () {
+ return "4";
+ },
+ isPrototypeOf: function () {
+ return "5";
+ },
+ propertyIsEnumerable: function () {
+ return "6";
+ },
+ hasOwnProperty: function () {
+ return "7";
+ },
+ length: function () {
+ return "8";
+ },
+ unique: function () {
+ return "9";
+ }
+ };
+
+ var result = [];
+ for (var prop in obj) {
+ if (obj.hasOwnProperty(prop)) {
+ result.push(obj[prop]());
+ }
+ }
+ return result.join("") !== "0123456789";
+ })();
+
+ /* Public: Extend target in place with all (own) properties from sources in-order. Thus, last source will
+ * override properties in previous sources.
+ *
+ * target - The Object to extend
+ * sources - Objects to copy properties from.
+ *
+ * Returns the extended target
+ */
+ function extend(target /*, sources */) {
+ var sources = Array.prototype.slice.call(arguments, 1);
+ var source, i, prop;
+
+ for (i = 0; i < sources.length; i++) {
+ source = sources[i];
+
+ for (prop in source) {
+ if (source.hasOwnProperty(prop)) {
+ target[prop] = source[prop];
+ }
+ }
+
+ // Make sure we copy (own) toString method even when in JScript with DontEnum bug
+ // See https://developer.mozilla.org/en/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
+ if (hasDontEnumBug && source.hasOwnProperty("toString") && source.toString !== target.toString) {
+ target.toString = source.toString;
+ }
+ }
+
+ return target;
+ }
+
+ sinon.extend = extend;
+ return sinon.extend;
+ }
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./util/core");
+ module.exports = makeApi(sinon);
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ */
+(function (sinonGlobal) {
+
+ function makeApi(sinon) {
+
+ function timesInWords(count) {
+ switch (count) {
+ case 1:
+ return "once";
+ case 2:
+ return "twice";
+ case 3:
+ return "thrice";
+ default:
+ return (count || 0) + " times";
+ }
+ }
+
+ sinon.timesInWords = timesInWords;
+ return sinon.timesInWords;
+ }
+
+ function loadDependencies(require, exports, module) {
+ var core = require("./util/core");
+ module.exports = makeApi(core);
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ */
+/**
+ * Format functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2014 Christian Johansen
+ */
+(function (sinonGlobal) {
+
+ function makeApi(sinon) {
+ function typeOf(value) {
+ if (value === null) {
+ return "null";
+ } else if (value === undefined) {
+ return "undefined";
+ }
+ var string = Object.prototype.toString.call(value);
+ return string.substring(8, string.length - 1).toLowerCase();
+ }
+
+ sinon.typeOf = typeOf;
+ return sinon.typeOf;
+ }
+
+ function loadDependencies(require, exports, module) {
+ var core = require("./util/core");
+ module.exports = makeApi(core);
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ * @depend typeOf.js
+ */
+/*jslint eqeqeq: false, onevar: false, plusplus: false*/
+/*global module, require, sinon*/
+/**
+ * Match functions
+ *
+ * @author Maximilian Antoni (mail@maxantoni.de)
+ * @license BSD
+ *
+ * Copyright (c) 2012 Maximilian Antoni
+ */
+(function (sinonGlobal) {
+
+ function makeApi(sinon) {
+ function assertType(value, type, name) {
+ var actual = sinon.typeOf(value);
+ if (actual !== type) {
+ throw new TypeError("Expected type of " + name + " to be " +
+ type + ", but was " + actual);
+ }
+ }
+
+ var matcher = {
+ toString: function () {
+ return this.message;
+ }
+ };
+
+ function isMatcher(object) {
+ return matcher.isPrototypeOf(object);
+ }
+
+ function matchObject(expectation, actual) {
+ if (actual === null || actual === undefined) {
+ return false;
+ }
+ for (var key in expectation) {
+ if (expectation.hasOwnProperty(key)) {
+ var exp = expectation[key];
+ var act = actual[key];
+ if (isMatcher(exp)) {
+ if (!exp.test(act)) {
+ return false;
+ }
+ } else if (sinon.typeOf(exp) === "object") {
+ if (!matchObject(exp, act)) {
+ return false;
+ }
+ } else if (!sinon.deepEqual(exp, act)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ function match(expectation, message) {
+ var m = sinon.create(matcher);
+ var type = sinon.typeOf(expectation);
+ switch (type) {
+ case "object":
+ if (typeof expectation.test === "function") {
+ m.test = function (actual) {
+ return expectation.test(actual) === true;
+ };
+ m.message = "match(" + sinon.functionName(expectation.test) + ")";
+ return m;
+ }
+ var str = [];
+ for (var key in expectation) {
+ if (expectation.hasOwnProperty(key)) {
+ str.push(key + ": " + expectation[key]);
+ }
+ }
+ m.test = function (actual) {
+ return matchObject(expectation, actual);
+ };
+ m.message = "match(" + str.join(", ") + ")";
+ break;
+ case "number":
+ m.test = function (actual) {
+ // we need type coercion here
+ return expectation == actual; // eslint-disable-line eqeqeq
+ };
+ break;
+ case "string":
+ m.test = function (actual) {
+ if (typeof actual !== "string") {
+ return false;
+ }
+ return actual.indexOf(expectation) !== -1;
+ };
+ m.message = "match(\"" + expectation + "\")";
+ break;
+ case "regexp":
+ m.test = function (actual) {
+ if (typeof actual !== "string") {
+ return false;
+ }
+ return expectation.test(actual);
+ };
+ break;
+ case "function":
+ m.test = expectation;
+ if (message) {
+ m.message = message;
+ } else {
+ m.message = "match(" + sinon.functionName(expectation) + ")";
+ }
+ break;
+ default:
+ m.test = function (actual) {
+ return sinon.deepEqual(expectation, actual);
+ };
+ }
+ if (!m.message) {
+ m.message = "match(" + expectation + ")";
+ }
+ return m;
+ }
+
+ matcher.or = function (m2) {
+ if (!arguments.length) {
+ throw new TypeError("Matcher expected");
+ } else if (!isMatcher(m2)) {
+ m2 = match(m2);
+ }
+ var m1 = this;
+ var or = sinon.create(matcher);
+ or.test = function (actual) {
+ return m1.test(actual) || m2.test(actual);
+ };
+ or.message = m1.message + ".or(" + m2.message + ")";
+ return or;
+ };
+
+ matcher.and = function (m2) {
+ if (!arguments.length) {
+ throw new TypeError("Matcher expected");
+ } else if (!isMatcher(m2)) {
+ m2 = match(m2);
+ }
+ var m1 = this;
+ var and = sinon.create(matcher);
+ and.test = function (actual) {
+ return m1.test(actual) && m2.test(actual);
+ };
+ and.message = m1.message + ".and(" + m2.message + ")";
+ return and;
+ };
+
+ match.isMatcher = isMatcher;
+
+ match.any = match(function () {
+ return true;
+ }, "any");
+
+ match.defined = match(function (actual) {
+ return actual !== null && actual !== undefined;
+ }, "defined");
+
+ match.truthy = match(function (actual) {
+ return !!actual;
+ }, "truthy");
+
+ match.falsy = match(function (actual) {
+ return !actual;
+ }, "falsy");
+
+ match.same = function (expectation) {
+ return match(function (actual) {
+ return expectation === actual;
+ }, "same(" + expectation + ")");
+ };
+
+ match.typeOf = function (type) {
+ assertType(type, "string", "type");
+ return match(function (actual) {
+ return sinon.typeOf(actual) === type;
+ }, "typeOf(\"" + type + "\")");
+ };
+
+ match.instanceOf = function (type) {
+ assertType(type, "function", "type");
+ return match(function (actual) {
+ return actual instanceof type;
+ }, "instanceOf(" + sinon.functionName(type) + ")");
+ };
+
+ function createPropertyMatcher(propertyTest, messagePrefix) {
+ return function (property, value) {
+ assertType(property, "string", "property");
+ var onlyProperty = arguments.length === 1;
+ var message = messagePrefix + "(\"" + property + "\"";
+ if (!onlyProperty) {
+ message += ", " + value;
+ }
+ message += ")";
+ return match(function (actual) {
+ if (actual === undefined || actual === null ||
+ !propertyTest(actual, property)) {
+ return false;
+ }
+ return onlyProperty || sinon.deepEqual(value, actual[property]);
+ }, message);
+ };
+ }
+
+ match.has = createPropertyMatcher(function (actual, property) {
+ if (typeof actual === "object") {
+ return property in actual;
+ }
+ return actual[property] !== undefined;
+ }, "has");
+
+ match.hasOwn = createPropertyMatcher(function (actual, property) {
+ return actual.hasOwnProperty(property);
+ }, "hasOwn");
+
+ match.bool = match.typeOf("boolean");
+ match.number = match.typeOf("number");
+ match.string = match.typeOf("string");
+ match.object = match.typeOf("object");
+ match.func = match.typeOf("function");
+ match.array = match.typeOf("array");
+ match.regexp = match.typeOf("regexp");
+ match.date = match.typeOf("date");
+
+ sinon.match = match;
+ return match;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./util/core");
+ require("./typeOf");
+ module.exports = makeApi(sinon);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ */
+/**
+ * Format functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2014 Christian Johansen
+ */
+(function (sinonGlobal, formatio) {
+
+ function makeApi(sinon) {
+ function valueFormatter(value) {
+ return "" + value;
+ }
+
+ function getFormatioFormatter() {
+ var formatter = formatio.configure({
+ quoteStrings: false,
+ limitChildrenCount: 250
+ });
+
+ function format() {
+ return formatter.ascii.apply(formatter, arguments);
+ }
+
+ return format;
+ }
+
+ function getNodeFormatter() {
+ try {
+ var util = require("util");
+ } catch (e) {
+ /* Node, but no util module - would be very old, but better safe than sorry */
+ }
+
+ function format(v) {
+ var isObjectWithNativeToString = typeof v === "object" && v.toString === Object.prototype.toString;
+ return isObjectWithNativeToString ? util.inspect(v) : v;
+ }
+
+ return util ? format : valueFormatter;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var formatter;
+
+ if (isNode) {
+ try {
+ formatio = require("formatio");
+ }
+ catch (e) {} // eslint-disable-line no-empty
+ }
+
+ if (formatio) {
+ formatter = getFormatioFormatter();
+ } else if (isNode) {
+ formatter = getNodeFormatter();
+ } else {
+ formatter = valueFormatter;
+ }
+
+ sinon.format = formatter;
+ return sinon.format;
+ }
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./util/core");
+ module.exports = makeApi(sinon);
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon, // eslint-disable-line no-undef
+ typeof formatio === "object" && formatio // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ * @depend match.js
+ * @depend format.js
+ */
+/**
+ * Spy calls
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @author Maximilian Antoni (mail@maxantoni.de)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ * Copyright (c) 2013 Maximilian Antoni
+ */
+(function (sinonGlobal) {
+
+ var slice = Array.prototype.slice;
+
+ function makeApi(sinon) {
+ function throwYieldError(proxy, text, args) {
+ var msg = sinon.functionName(proxy) + text;
+ if (args.length) {
+ msg += " Received [" + slice.call(args).join(", ") + "]";
+ }
+ throw new Error(msg);
+ }
+
+ var callProto = {
+ calledOn: function calledOn(thisValue) {
+ if (sinon.match && sinon.match.isMatcher(thisValue)) {
+ return thisValue.test(this.thisValue);
+ }
+ return this.thisValue === thisValue;
+ },
+
+ calledWith: function calledWith() {
+ var l = arguments.length;
+ if (l > this.args.length) {
+ return false;
+ }
+ for (var i = 0; i < l; i += 1) {
+ if (!sinon.deepEqual(arguments[i], this.args[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ calledWithMatch: function calledWithMatch() {
+ var l = arguments.length;
+ if (l > this.args.length) {
+ return false;
+ }
+ for (var i = 0; i < l; i += 1) {
+ var actual = this.args[i];
+ var expectation = arguments[i];
+ if (!sinon.match || !sinon.match(expectation).test(actual)) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ calledWithExactly: function calledWithExactly() {
+ return arguments.length === this.args.length &&
+ this.calledWith.apply(this, arguments);
+ },
+
+ notCalledWith: function notCalledWith() {
+ return !this.calledWith.apply(this, arguments);
+ },
+
+ notCalledWithMatch: function notCalledWithMatch() {
+ return !this.calledWithMatch.apply(this, arguments);
+ },
+
+ returned: function returned(value) {
+ return sinon.deepEqual(value, this.returnValue);
+ },
+
+ threw: function threw(error) {
+ if (typeof error === "undefined" || !this.exception) {
+ return !!this.exception;
+ }
+
+ return this.exception === error || this.exception.name === error;
+ },
+
+ calledWithNew: function calledWithNew() {
+ return this.proxy.prototype && this.thisValue instanceof this.proxy;
+ },
+
+ calledBefore: function (other) {
+ return this.callId < other.callId;
+ },
+
+ calledAfter: function (other) {
+ return this.callId > other.callId;
+ },
+
+ callArg: function (pos) {
+ this.args[pos]();
+ },
+
+ callArgOn: function (pos, thisValue) {
+ this.args[pos].apply(thisValue);
+ },
+
+ callArgWith: function (pos) {
+ this.callArgOnWith.apply(this, [pos, null].concat(slice.call(arguments, 1)));
+ },
+
+ callArgOnWith: function (pos, thisValue) {
+ var args = slice.call(arguments, 2);
+ this.args[pos].apply(thisValue, args);
+ },
+
+ "yield": function () {
+ this.yieldOn.apply(this, [null].concat(slice.call(arguments, 0)));
+ },
+
+ yieldOn: function (thisValue) {
+ var args = this.args;
+ for (var i = 0, l = args.length; i < l; ++i) {
+ if (typeof args[i] === "function") {
+ args[i].apply(thisValue, slice.call(arguments, 1));
+ return;
+ }
+ }
+ throwYieldError(this.proxy, " cannot yield since no callback was passed.", args);
+ },
+
+ yieldTo: function (prop) {
+ this.yieldToOn.apply(this, [prop, null].concat(slice.call(arguments, 1)));
+ },
+
+ yieldToOn: function (prop, thisValue) {
+ var args = this.args;
+ for (var i = 0, l = args.length; i < l; ++i) {
+ if (args[i] && typeof args[i][prop] === "function") {
+ args[i][prop].apply(thisValue, slice.call(arguments, 2));
+ return;
+ }
+ }
+ throwYieldError(this.proxy, " cannot yield to '" + prop +
+ "' since no callback was passed.", args);
+ },
+
+ getStackFrames: function () {
+ // Omit the error message and the two top stack frames in sinon itself:
+ return this.stack && this.stack.split("\n").slice(3);
+ },
+
+ toString: function () {
+ var callStr = this.proxy ? this.proxy.toString() + "(" : "";
+ var args = [];
+
+ if (!this.args) {
+ return ":(";
+ }
+
+ for (var i = 0, l = this.args.length; i < l; ++i) {
+ args.push(sinon.format(this.args[i]));
+ }
+
+ callStr = callStr + args.join(", ") + ")";
+
+ if (typeof this.returnValue !== "undefined") {
+ callStr += " => " + sinon.format(this.returnValue);
+ }
+
+ if (this.exception) {
+ callStr += " !" + this.exception.name;
+
+ if (this.exception.message) {
+ callStr += "(" + this.exception.message + ")";
+ }
+ }
+ if (this.stack) {
+ callStr += this.getStackFrames()[0].replace(/^\s*(?:at\s+|@)?/, " at ");
+
+ }
+
+ return callStr;
+ }
+ };
+
+ callProto.invokeCallback = callProto.yield;
+
+ function createSpyCall(spy, thisValue, args, returnValue, exception, id, stack) {
+ if (typeof id !== "number") {
+ throw new TypeError("Call id is not a number");
+ }
+ var proxyCall = sinon.create(callProto);
+ proxyCall.proxy = spy;
+ proxyCall.thisValue = thisValue;
+ proxyCall.args = args;
+ proxyCall.returnValue = returnValue;
+ proxyCall.exception = exception;
+ proxyCall.callId = id;
+ proxyCall.stack = stack;
+
+ return proxyCall;
+ }
+ createSpyCall.toString = callProto.toString; // used by mocks
+
+ sinon.spyCall = createSpyCall;
+ return createSpyCall;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./util/core");
+ require("./match");
+ require("./format");
+ module.exports = makeApi(sinon);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend times_in_words.js
+ * @depend util/core.js
+ * @depend extend.js
+ * @depend call.js
+ * @depend format.js
+ */
+/**
+ * Spy functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+
+ function makeApi(sinon) {
+ var push = Array.prototype.push;
+ var slice = Array.prototype.slice;
+ var callId = 0;
+
+ function spy(object, property, types) {
+ if (!property && typeof object === "function") {
+ return spy.create(object);
+ }
+
+ if (!object && !property) {
+ return spy.create(function () { });
+ }
+
+ if (types) {
+ var methodDesc = sinon.getPropertyDescriptor(object, property);
+ for (var i = 0; i < types.length; i++) {
+ methodDesc[types[i]] = spy.create(methodDesc[types[i]]);
+ }
+ return sinon.wrapMethod(object, property, methodDesc);
+ }
+
+ return sinon.wrapMethod(object, property, spy.create(object[property]));
+ }
+
+ function matchingFake(fakes, args, strict) {
+ if (!fakes) {
+ return undefined;
+ }
+
+ for (var i = 0, l = fakes.length; i < l; i++) {
+ if (fakes[i].matches(args, strict)) {
+ return fakes[i];
+ }
+ }
+ }
+
+ function incrementCallCount() {
+ this.called = true;
+ this.callCount += 1;
+ this.notCalled = false;
+ this.calledOnce = this.callCount === 1;
+ this.calledTwice = this.callCount === 2;
+ this.calledThrice = this.callCount === 3;
+ }
+
+ function createCallProperties() {
+ this.firstCall = this.getCall(0);
+ this.secondCall = this.getCall(1);
+ this.thirdCall = this.getCall(2);
+ this.lastCall = this.getCall(this.callCount - 1);
+ }
+
+ var vars = "a,b,c,d,e,f,g,h,i,j,k,l";
+ function createProxy(func, proxyLength) {
+ // Retain the function length:
+ var p;
+ if (proxyLength) {
+ eval("p = (function proxy(" + vars.substring(0, proxyLength * 2 - 1) + // eslint-disable-line no-eval
+ ") { return p.invoke(func, this, slice.call(arguments)); });");
+ } else {
+ p = function proxy() {
+ return p.invoke(func, this, slice.call(arguments));
+ };
+ }
+ p.isSinonProxy = true;
+ return p;
+ }
+
+ var uuid = 0;
+
+ // Public API
+ var spyApi = {
+ reset: function () {
+ if (this.invoking) {
+ var err = new Error("Cannot reset Sinon function while invoking it. " +
+ "Move the call to .reset outside of the callback.");
+ err.name = "InvalidResetException";
+ throw err;
+ }
+
+ this.called = false;
+ this.notCalled = true;
+ this.calledOnce = false;
+ this.calledTwice = false;
+ this.calledThrice = false;
+ this.callCount = 0;
+ this.firstCall = null;
+ this.secondCall = null;
+ this.thirdCall = null;
+ this.lastCall = null;
+ this.args = [];
+ this.returnValues = [];
+ this.thisValues = [];
+ this.exceptions = [];
+ this.callIds = [];
+ this.stacks = [];
+ if (this.fakes) {
+ for (var i = 0; i < this.fakes.length; i++) {
+ this.fakes[i].reset();
+ }
+ }
+
+ return this;
+ },
+
+ create: function create(func, spyLength) {
+ var name;
+
+ if (typeof func !== "function") {
+ func = function () { };
+ } else {
+ name = sinon.functionName(func);
+ }
+
+ if (!spyLength) {
+ spyLength = func.length;
+ }
+
+ var proxy = createProxy(func, spyLength);
+
+ sinon.extend(proxy, spy);
+ delete proxy.create;
+ sinon.extend(proxy, func);
+
+ proxy.reset();
+ proxy.prototype = func.prototype;
+ proxy.displayName = name || "spy";
+ proxy.toString = sinon.functionToString;
+ proxy.instantiateFake = sinon.spy.create;
+ proxy.id = "spy#" + uuid++;
+
+ return proxy;
+ },
+
+ invoke: function invoke(func, thisValue, args) {
+ var matching = matchingFake(this.fakes, args);
+ var exception, returnValue;
+
+ incrementCallCount.call(this);
+ push.call(this.thisValues, thisValue);
+ push.call(this.args, args);
+ push.call(this.callIds, callId++);
+
+ // Make call properties available from within the spied function:
+ createCallProperties.call(this);
+
+ try {
+ this.invoking = true;
+
+ if (matching) {
+ returnValue = matching.invoke(func, thisValue, args);
+ } else {
+ returnValue = (this.func || func).apply(thisValue, args);
+ }
+
+ var thisCall = this.getCall(this.callCount - 1);
+ if (thisCall.calledWithNew() && typeof returnValue !== "object") {
+ returnValue = thisValue;
+ }
+ } catch (e) {
+ exception = e;
+ } finally {
+ delete this.invoking;
+ }
+
+ push.call(this.exceptions, exception);
+ push.call(this.returnValues, returnValue);
+ push.call(this.stacks, new Error().stack);
+
+ // Make return value and exception available in the calls:
+ createCallProperties.call(this);
+
+ if (exception !== undefined) {
+ throw exception;
+ }
+
+ return returnValue;
+ },
+
+ named: function named(name) {
+ this.displayName = name;
+ return this;
+ },
+
+ getCall: function getCall(i) {
+ if (i < 0 || i >= this.callCount) {
+ return null;
+ }
+
+ return sinon.spyCall(this, this.thisValues[i], this.args[i],
+ this.returnValues[i], this.exceptions[i],
+ this.callIds[i], this.stacks[i]);
+ },
+
+ getCalls: function () {
+ var calls = [];
+ var i;
+
+ for (i = 0; i < this.callCount; i++) {
+ calls.push(this.getCall(i));
+ }
+
+ return calls;
+ },
+
+ calledBefore: function calledBefore(spyFn) {
+ if (!this.called) {
+ return false;
+ }
+
+ if (!spyFn.called) {
+ return true;
+ }
+
+ return this.callIds[0] < spyFn.callIds[spyFn.callIds.length - 1];
+ },
+
+ calledAfter: function calledAfter(spyFn) {
+ if (!this.called || !spyFn.called) {
+ return false;
+ }
+
+ return this.callIds[this.callCount - 1] > spyFn.callIds[spyFn.callCount - 1];
+ },
+
+ withArgs: function () {
+ var args = slice.call(arguments);
+
+ if (this.fakes) {
+ var match = matchingFake(this.fakes, args, true);
+
+ if (match) {
+ return match;
+ }
+ } else {
+ this.fakes = [];
+ }
+
+ var original = this;
+ var fake = this.instantiateFake();
+ fake.matchingAguments = args;
+ fake.parent = this;
+ push.call(this.fakes, fake);
+
+ fake.withArgs = function () {
+ return original.withArgs.apply(original, arguments);
+ };
+
+ for (var i = 0; i < this.args.length; i++) {
+ if (fake.matches(this.args[i])) {
+ incrementCallCount.call(fake);
+ push.call(fake.thisValues, this.thisValues[i]);
+ push.call(fake.args, this.args[i]);
+ push.call(fake.returnValues, this.returnValues[i]);
+ push.call(fake.exceptions, this.exceptions[i]);
+ push.call(fake.callIds, this.callIds[i]);
+ }
+ }
+ createCallProperties.call(fake);
+
+ return fake;
+ },
+
+ matches: function (args, strict) {
+ var margs = this.matchingAguments;
+
+ if (margs.length <= args.length &&
+ sinon.deepEqual(margs, args.slice(0, margs.length))) {
+ return !strict || margs.length === args.length;
+ }
+ },
+
+ printf: function (format) {
+ var spyInstance = this;
+ var args = slice.call(arguments, 1);
+ var formatter;
+
+ return (format || "").replace(/%(.)/g, function (match, specifyer) {
+ formatter = spyApi.formatters[specifyer];
+
+ if (typeof formatter === "function") {
+ return formatter.call(null, spyInstance, args);
+ } else if (!isNaN(parseInt(specifyer, 10))) {
+ return sinon.format(args[specifyer - 1]);
+ }
+
+ return "%" + specifyer;
+ });
+ }
+ };
+
+ function delegateToCalls(method, matchAny, actual, notCalled) {
+ spyApi[method] = function () {
+ if (!this.called) {
+ if (notCalled) {
+ return notCalled.apply(this, arguments);
+ }
+ return false;
+ }
+
+ var currentCall;
+ var matches = 0;
+
+ for (var i = 0, l = this.callCount; i < l; i += 1) {
+ currentCall = this.getCall(i);
+
+ if (currentCall[actual || method].apply(currentCall, arguments)) {
+ matches += 1;
+
+ if (matchAny) {
+ return true;
+ }
+ }
+ }
+
+ return matches === this.callCount;
+ };
+ }
+
+ delegateToCalls("calledOn", true);
+ delegateToCalls("alwaysCalledOn", false, "calledOn");
+ delegateToCalls("calledWith", true);
+ delegateToCalls("calledWithMatch", true);
+ delegateToCalls("alwaysCalledWith", false, "calledWith");
+ delegateToCalls("alwaysCalledWithMatch", false, "calledWithMatch");
+ delegateToCalls("calledWithExactly", true);
+ delegateToCalls("alwaysCalledWithExactly", false, "calledWithExactly");
+ delegateToCalls("neverCalledWith", false, "notCalledWith", function () {
+ return true;
+ });
+ delegateToCalls("neverCalledWithMatch", false, "notCalledWithMatch", function () {
+ return true;
+ });
+ delegateToCalls("threw", true);
+ delegateToCalls("alwaysThrew", false, "threw");
+ delegateToCalls("returned", true);
+ delegateToCalls("alwaysReturned", false, "returned");
+ delegateToCalls("calledWithNew", true);
+ delegateToCalls("alwaysCalledWithNew", false, "calledWithNew");
+ delegateToCalls("callArg", false, "callArgWith", function () {
+ throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
+ });
+ spyApi.callArgWith = spyApi.callArg;
+ delegateToCalls("callArgOn", false, "callArgOnWith", function () {
+ throw new Error(this.toString() + " cannot call arg since it was not yet invoked.");
+ });
+ spyApi.callArgOnWith = spyApi.callArgOn;
+ delegateToCalls("yield", false, "yield", function () {
+ throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
+ });
+ // "invokeCallback" is an alias for "yield" since "yield" is invalid in strict mode.
+ spyApi.invokeCallback = spyApi.yield;
+ delegateToCalls("yieldOn", false, "yieldOn", function () {
+ throw new Error(this.toString() + " cannot yield since it was not yet invoked.");
+ });
+ delegateToCalls("yieldTo", false, "yieldTo", function (property) {
+ throw new Error(this.toString() + " cannot yield to '" + property +
+ "' since it was not yet invoked.");
+ });
+ delegateToCalls("yieldToOn", false, "yieldToOn", function (property) {
+ throw new Error(this.toString() + " cannot yield to '" + property +
+ "' since it was not yet invoked.");
+ });
+
+ spyApi.formatters = {
+ c: function (spyInstance) {
+ return sinon.timesInWords(spyInstance.callCount);
+ },
+
+ n: function (spyInstance) {
+ return spyInstance.toString();
+ },
+
+ C: function (spyInstance) {
+ var calls = [];
+
+ for (var i = 0, l = spyInstance.callCount; i < l; ++i) {
+ var stringifiedCall = " " + spyInstance.getCall(i).toString();
+ if (/\n/.test(calls[i - 1])) {
+ stringifiedCall = "\n" + stringifiedCall;
+ }
+ push.call(calls, stringifiedCall);
+ }
+
+ return calls.length > 0 ? "\n" + calls.join("\n") : "";
+ },
+
+ t: function (spyInstance) {
+ var objects = [];
+
+ for (var i = 0, l = spyInstance.callCount; i < l; ++i) {
+ push.call(objects, sinon.format(spyInstance.thisValues[i]));
+ }
+
+ return objects.join(", ");
+ },
+
+ "*": function (spyInstance, args) {
+ var formatted = [];
+
+ for (var i = 0, l = args.length; i < l; ++i) {
+ push.call(formatted, sinon.format(args[i]));
+ }
+
+ return formatted.join(", ");
+ }
+ };
+
+ sinon.extend(spy, spyApi);
+
+ spy.spyCall = sinon.spyCall;
+ sinon.spy = spy;
+
+ return spy;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var core = require("./util/core");
+ require("./call");
+ require("./extend");
+ require("./times_in_words");
+ require("./format");
+ module.exports = makeApi(core);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ * @depend extend.js
+ */
+/**
+ * Stub behavior
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @author Tim Fischbach (mail@timfischbach.de)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+
+ var slice = Array.prototype.slice;
+ var join = Array.prototype.join;
+ var useLeftMostCallback = -1;
+ var useRightMostCallback = -2;
+
+ var nextTick = (function () {
+ if (typeof process === "object" && typeof process.nextTick === "function") {
+ return process.nextTick;
+ }
+
+ if (typeof setImmediate === "function") {
+ return setImmediate;
+ }
+
+ return function (callback) {
+ setTimeout(callback, 0);
+ };
+ })();
+
+ function throwsException(error, message) {
+ if (typeof error === "string") {
+ this.exception = new Error(message || "");
+ this.exception.name = error;
+ } else if (!error) {
+ this.exception = new Error("Error");
+ } else {
+ this.exception = error;
+ }
+
+ return this;
+ }
+
+ function getCallback(behavior, args) {
+ var callArgAt = behavior.callArgAt;
+
+ if (callArgAt >= 0) {
+ return args[callArgAt];
+ }
+
+ var argumentList;
+
+ if (callArgAt === useLeftMostCallback) {
+ argumentList = args;
+ }
+
+ if (callArgAt === useRightMostCallback) {
+ argumentList = slice.call(args).reverse();
+ }
+
+ var callArgProp = behavior.callArgProp;
+
+ for (var i = 0, l = argumentList.length; i < l; ++i) {
+ if (!callArgProp && typeof argumentList[i] === "function") {
+ return argumentList[i];
+ }
+
+ if (callArgProp && argumentList[i] &&
+ typeof argumentList[i][callArgProp] === "function") {
+ return argumentList[i][callArgProp];
+ }
+ }
+
+ return null;
+ }
+
+ function makeApi(sinon) {
+ function getCallbackError(behavior, func, args) {
+ if (behavior.callArgAt < 0) {
+ var msg;
+
+ if (behavior.callArgProp) {
+ msg = sinon.functionName(behavior.stub) +
+ " expected to yield to '" + behavior.callArgProp +
+ "', but no object with such a property was passed.";
+ } else {
+ msg = sinon.functionName(behavior.stub) +
+ " expected to yield, but no callback was passed.";
+ }
+
+ if (args.length > 0) {
+ msg += " Received [" + join.call(args, ", ") + "]";
+ }
+
+ return msg;
+ }
+
+ return "argument at index " + behavior.callArgAt + " is not a function: " + func;
+ }
+
+ function callCallback(behavior, args) {
+ if (typeof behavior.callArgAt === "number") {
+ var func = getCallback(behavior, args);
+
+ if (typeof func !== "function") {
+ throw new TypeError(getCallbackError(behavior, func, args));
+ }
+
+ if (behavior.callbackAsync) {
+ nextTick(function () {
+ func.apply(behavior.callbackContext, behavior.callbackArguments);
+ });
+ } else {
+ func.apply(behavior.callbackContext, behavior.callbackArguments);
+ }
+ }
+ }
+
+ var proto = {
+ create: function create(stub) {
+ var behavior = sinon.extend({}, sinon.behavior);
+ delete behavior.create;
+ behavior.stub = stub;
+
+ return behavior;
+ },
+
+ isPresent: function isPresent() {
+ return (typeof this.callArgAt === "number" ||
+ this.exception ||
+ typeof this.returnArgAt === "number" ||
+ this.returnThis ||
+ this.returnValueDefined);
+ },
+
+ invoke: function invoke(context, args) {
+ callCallback(this, args);
+
+ if (this.exception) {
+ throw this.exception;
+ } else if (typeof this.returnArgAt === "number") {
+ return args[this.returnArgAt];
+ } else if (this.returnThis) {
+ return context;
+ }
+
+ return this.returnValue;
+ },
+
+ onCall: function onCall(index) {
+ return this.stub.onCall(index);
+ },
+
+ onFirstCall: function onFirstCall() {
+ return this.stub.onFirstCall();
+ },
+
+ onSecondCall: function onSecondCall() {
+ return this.stub.onSecondCall();
+ },
+
+ onThirdCall: function onThirdCall() {
+ return this.stub.onThirdCall();
+ },
+
+ withArgs: function withArgs(/* arguments */) {
+ throw new Error(
+ "Defining a stub by invoking \"stub.onCall(...).withArgs(...)\" " +
+ "is not supported. Use \"stub.withArgs(...).onCall(...)\" " +
+ "to define sequential behavior for calls with certain arguments."
+ );
+ },
+
+ callsArg: function callsArg(pos) {
+ if (typeof pos !== "number") {
+ throw new TypeError("argument index is not number");
+ }
+
+ this.callArgAt = pos;
+ this.callbackArguments = [];
+ this.callbackContext = undefined;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
+
+ return this;
+ },
+
+ callsArgOn: function callsArgOn(pos, context) {
+ if (typeof pos !== "number") {
+ throw new TypeError("argument index is not number");
+ }
+ if (typeof context !== "object") {
+ throw new TypeError("argument context is not an object");
+ }
+
+ this.callArgAt = pos;
+ this.callbackArguments = [];
+ this.callbackContext = context;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
+
+ return this;
+ },
+
+ callsArgWith: function callsArgWith(pos) {
+ if (typeof pos !== "number") {
+ throw new TypeError("argument index is not number");
+ }
+
+ this.callArgAt = pos;
+ this.callbackArguments = slice.call(arguments, 1);
+ this.callbackContext = undefined;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
+
+ return this;
+ },
+
+ callsArgOnWith: function callsArgWith(pos, context) {
+ if (typeof pos !== "number") {
+ throw new TypeError("argument index is not number");
+ }
+ if (typeof context !== "object") {
+ throw new TypeError("argument context is not an object");
+ }
+
+ this.callArgAt = pos;
+ this.callbackArguments = slice.call(arguments, 2);
+ this.callbackContext = context;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
+
+ return this;
+ },
+
+ yields: function () {
+ this.callArgAt = useLeftMostCallback;
+ this.callbackArguments = slice.call(arguments, 0);
+ this.callbackContext = undefined;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
+
+ return this;
+ },
+
+ yieldsRight: function () {
+ this.callArgAt = useRightMostCallback;
+ this.callbackArguments = slice.call(arguments, 0);
+ this.callbackContext = undefined;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
+
+ return this;
+ },
+
+ yieldsOn: function (context) {
+ if (typeof context !== "object") {
+ throw new TypeError("argument context is not an object");
+ }
+
+ this.callArgAt = useLeftMostCallback;
+ this.callbackArguments = slice.call(arguments, 1);
+ this.callbackContext = context;
+ this.callArgProp = undefined;
+ this.callbackAsync = false;
+
+ return this;
+ },
+
+ yieldsTo: function (prop) {
+ this.callArgAt = useLeftMostCallback;
+ this.callbackArguments = slice.call(arguments, 1);
+ this.callbackContext = undefined;
+ this.callArgProp = prop;
+ this.callbackAsync = false;
+
+ return this;
+ },
+
+ yieldsToOn: function (prop, context) {
+ if (typeof context !== "object") {
+ throw new TypeError("argument context is not an object");
+ }
+
+ this.callArgAt = useLeftMostCallback;
+ this.callbackArguments = slice.call(arguments, 2);
+ this.callbackContext = context;
+ this.callArgProp = prop;
+ this.callbackAsync = false;
+
+ return this;
+ },
+
+ throws: throwsException,
+ throwsException: throwsException,
+
+ returns: function returns(value) {
+ this.returnValue = value;
+ this.returnValueDefined = true;
+ this.exception = undefined;
+
+ return this;
+ },
+
+ returnsArg: function returnsArg(pos) {
+ if (typeof pos !== "number") {
+ throw new TypeError("argument index is not number");
+ }
+
+ this.returnArgAt = pos;
+
+ return this;
+ },
+
+ returnsThis: function returnsThis() {
+ this.returnThis = true;
+
+ return this;
+ }
+ };
+
+ function createAsyncVersion(syncFnName) {
+ return function () {
+ var result = this[syncFnName].apply(this, arguments);
+ this.callbackAsync = true;
+ return result;
+ };
+ }
+
+ // create asynchronous versions of callsArg* and yields* methods
+ for (var method in proto) {
+ // need to avoid creating anotherasync versions of the newly added async methods
+ if (proto.hasOwnProperty(method) && method.match(/^(callsArg|yields)/) && !method.match(/Async/)) {
+ proto[method + "Async"] = createAsyncVersion(method);
+ }
+ }
+
+ sinon.behavior = proto;
+ return proto;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./util/core");
+ require("./extend");
+ module.exports = makeApi(sinon);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ */
+(function (sinonGlobal) {
+
+ function makeApi(sinon) {
+ function walkInternal(obj, iterator, context, originalObj, seen) {
+ var proto, prop;
+
+ if (typeof Object.getOwnPropertyNames !== "function") {
+ // We explicitly want to enumerate through all of the prototype's properties
+ // in this case, therefore we deliberately leave out an own property check.
+ /* eslint-disable guard-for-in */
+ for (prop in obj) {
+ iterator.call(context, obj[prop], prop, obj);
+ }
+ /* eslint-enable guard-for-in */
+
+ return;
+ }
+
+ Object.getOwnPropertyNames(obj).forEach(function (k) {
+ if (!seen[k]) {
+ seen[k] = true;
+ var target = typeof Object.getOwnPropertyDescriptor(obj, k).get === "function" ?
+ originalObj : obj;
+ iterator.call(context, target[k], k, target);
+ }
+ });
+
+ proto = Object.getPrototypeOf(obj);
+ if (proto) {
+ walkInternal(proto, iterator, context, originalObj, seen);
+ }
+ }
+
+ /* Public: walks the prototype chain of an object and iterates over every own property
+ * name encountered. The iterator is called in the same fashion that Array.prototype.forEach
+ * works, where it is passed the value, key, and own object as the 1st, 2nd, and 3rd positional
+ * argument, respectively. In cases where Object.getOwnPropertyNames is not available, walk will
+ * default to using a simple for..in loop.
+ *
+ * obj - The object to walk the prototype chain for.
+ * iterator - The function to be called on each pass of the walk.
+ * context - (Optional) When given, the iterator will be called with this object as the receiver.
+ */
+ function walk(obj, iterator, context) {
+ return walkInternal(obj, iterator, context, obj, {});
+ }
+
+ sinon.walk = walk;
+ return sinon.walk;
+ }
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./util/core");
+ module.exports = makeApi(sinon);
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ * @depend extend.js
+ * @depend spy.js
+ * @depend behavior.js
+ * @depend walk.js
+ */
+/**
+ * Stub functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+
+ function makeApi(sinon) {
+ function stub(object, property, func) {
+ if (!!func && typeof func !== "function" && typeof func !== "object") {
+ throw new TypeError("Custom stub should be a function or a property descriptor");
+ }
+
+ var wrapper;
+
+ if (func) {
+ if (typeof func === "function") {
+ wrapper = sinon.spy && sinon.spy.create ? sinon.spy.create(func) : func;
+ } else {
+ wrapper = func;
+ if (sinon.spy && sinon.spy.create) {
+ var types = sinon.objectKeys(wrapper);
+ for (var i = 0; i < types.length; i++) {
+ wrapper[types[i]] = sinon.spy.create(wrapper[types[i]]);
+ }
+ }
+ }
+ } else {
+ var stubLength = 0;
+ if (typeof object === "object" && typeof object[property] === "function") {
+ stubLength = object[property].length;
+ }
+ wrapper = stub.create(stubLength);
+ }
+
+ if (!object && typeof property === "undefined") {
+ return sinon.stub.create();
+ }
+
+ if (typeof property === "undefined" && typeof object === "object") {
+ sinon.walk(object || {}, function (value, prop, propOwner) {
+ // we don't want to stub things like toString(), valueOf(), etc. so we only stub if the object
+ // is not Object.prototype
+ if (
+ propOwner !== Object.prototype &&
+ prop !== "constructor" &&
+ typeof sinon.getPropertyDescriptor(propOwner, prop).value === "function"
+ ) {
+ stub(object, prop);
+ }
+ });
+
+ return object;
+ }
+
+ return sinon.wrapMethod(object, property, wrapper);
+ }
+
+
+ /*eslint-disable no-use-before-define*/
+ function getParentBehaviour(stubInstance) {
+ return (stubInstance.parent && getCurrentBehavior(stubInstance.parent));
+ }
+
+ function getDefaultBehavior(stubInstance) {
+ return stubInstance.defaultBehavior ||
+ getParentBehaviour(stubInstance) ||
+ sinon.behavior.create(stubInstance);
+ }
+
+ function getCurrentBehavior(stubInstance) {
+ var behavior = stubInstance.behaviors[stubInstance.callCount - 1];
+ return behavior && behavior.isPresent() ? behavior : getDefaultBehavior(stubInstance);
+ }
+ /*eslint-enable no-use-before-define*/
+
+ var uuid = 0;
+
+ var proto = {
+ create: function create(stubLength) {
+ var functionStub = function () {
+ return getCurrentBehavior(functionStub).invoke(this, arguments);
+ };
+
+ functionStub.id = "stub#" + uuid++;
+ var orig = functionStub;
+ functionStub = sinon.spy.create(functionStub, stubLength);
+ functionStub.func = orig;
+
+ sinon.extend(functionStub, stub);
+ functionStub.instantiateFake = sinon.stub.create;
+ functionStub.displayName = "stub";
+ functionStub.toString = sinon.functionToString;
+
+ functionStub.defaultBehavior = null;
+ functionStub.behaviors = [];
+
+ return functionStub;
+ },
+
+ resetBehavior: function () {
+ var i;
+
+ this.defaultBehavior = null;
+ this.behaviors = [];
+
+ delete this.returnValue;
+ delete this.returnArgAt;
+ this.returnThis = false;
+
+ if (this.fakes) {
+ for (i = 0; i < this.fakes.length; i++) {
+ this.fakes[i].resetBehavior();
+ }
+ }
+ },
+
+ onCall: function onCall(index) {
+ if (!this.behaviors[index]) {
+ this.behaviors[index] = sinon.behavior.create(this);
+ }
+
+ return this.behaviors[index];
+ },
+
+ onFirstCall: function onFirstCall() {
+ return this.onCall(0);
+ },
+
+ onSecondCall: function onSecondCall() {
+ return this.onCall(1);
+ },
+
+ onThirdCall: function onThirdCall() {
+ return this.onCall(2);
+ }
+ };
+
+ function createBehavior(behaviorMethod) {
+ return function () {
+ this.defaultBehavior = this.defaultBehavior || sinon.behavior.create(this);
+ this.defaultBehavior[behaviorMethod].apply(this.defaultBehavior, arguments);
+ return this;
+ };
+ }
+
+ for (var method in sinon.behavior) {
+ if (sinon.behavior.hasOwnProperty(method) &&
+ !proto.hasOwnProperty(method) &&
+ method !== "create" &&
+ method !== "withArgs" &&
+ method !== "invoke") {
+ proto[method] = createBehavior(method);
+ }
+ }
+
+ sinon.extend(stub, proto);
+ sinon.stub = stub;
+
+ return stub;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var core = require("./util/core");
+ require("./behavior");
+ require("./spy");
+ require("./extend");
+ module.exports = makeApi(core);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend times_in_words.js
+ * @depend util/core.js
+ * @depend call.js
+ * @depend extend.js
+ * @depend match.js
+ * @depend spy.js
+ * @depend stub.js
+ * @depend format.js
+ */
+/**
+ * Mock functions.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+
+ function makeApi(sinon) {
+ var push = [].push;
+ var match = sinon.match;
+
+ function mock(object) {
+ // if (typeof console !== undefined && console.warn) {
+ // console.warn("mock will be removed from Sinon.JS v2.0");
+ // }
+
+ if (!object) {
+ return sinon.expectation.create("Anonymous mock");
+ }
+
+ return mock.create(object);
+ }
+
+ function each(collection, callback) {
+ if (!collection) {
+ return;
+ }
+
+ for (var i = 0, l = collection.length; i < l; i += 1) {
+ callback(collection[i]);
+ }
+ }
+
+ function arrayEquals(arr1, arr2, compareLength) {
+ if (compareLength && (arr1.length !== arr2.length)) {
+ return false;
+ }
+
+ for (var i = 0, l = arr1.length; i < l; i++) {
+ if (!sinon.deepEqual(arr1[i], arr2[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ sinon.extend(mock, {
+ create: function create(object) {
+ if (!object) {
+ throw new TypeError("object is null");
+ }
+
+ var mockObject = sinon.extend({}, mock);
+ mockObject.object = object;
+ delete mockObject.create;
+
+ return mockObject;
+ },
+
+ expects: function expects(method) {
+ if (!method) {
+ throw new TypeError("method is falsy");
+ }
+
+ if (!this.expectations) {
+ this.expectations = {};
+ this.proxies = [];
+ }
+
+ if (!this.expectations[method]) {
+ this.expectations[method] = [];
+ var mockObject = this;
+
+ sinon.wrapMethod(this.object, method, function () {
+ return mockObject.invokeMethod(method, this, arguments);
+ });
+
+ push.call(this.proxies, method);
+ }
+
+ var expectation = sinon.expectation.create(method);
+ push.call(this.expectations[method], expectation);
+
+ return expectation;
+ },
+
+ restore: function restore() {
+ var object = this.object;
+
+ each(this.proxies, function (proxy) {
+ if (typeof object[proxy].restore === "function") {
+ object[proxy].restore();
+ }
+ });
+ },
+
+ verify: function verify() {
+ var expectations = this.expectations || {};
+ var messages = [];
+ var met = [];
+
+ each(this.proxies, function (proxy) {
+ each(expectations[proxy], function (expectation) {
+ if (!expectation.met()) {
+ push.call(messages, expectation.toString());
+ } else {
+ push.call(met, expectation.toString());
+ }
+ });
+ });
+
+ this.restore();
+
+ if (messages.length > 0) {
+ sinon.expectation.fail(messages.concat(met).join("\n"));
+ } else if (met.length > 0) {
+ sinon.expectation.pass(messages.concat(met).join("\n"));
+ }
+
+ return true;
+ },
+
+ invokeMethod: function invokeMethod(method, thisValue, args) {
+ var expectations = this.expectations && this.expectations[method] ? this.expectations[method] : [];
+ var expectationsWithMatchingArgs = [];
+ var currentArgs = args || [];
+ var i, available;
+
+ for (i = 0; i < expectations.length; i += 1) {
+ var expectedArgs = expectations[i].expectedArguments || [];
+ if (arrayEquals(expectedArgs, currentArgs, expectations[i].expectsExactArgCount)) {
+ expectationsWithMatchingArgs.push(expectations[i]);
+ }
+ }
+
+ for (i = 0; i < expectationsWithMatchingArgs.length; i += 1) {
+ if (!expectationsWithMatchingArgs[i].met() &&
+ expectationsWithMatchingArgs[i].allowsCall(thisValue, args)) {
+ return expectationsWithMatchingArgs[i].apply(thisValue, args);
+ }
+ }
+
+ var messages = [];
+ var exhausted = 0;
+
+ for (i = 0; i < expectationsWithMatchingArgs.length; i += 1) {
+ if (expectationsWithMatchingArgs[i].allowsCall(thisValue, args)) {
+ available = available || expectationsWithMatchingArgs[i];
+ } else {
+ exhausted += 1;
+ }
+ }
+
+ if (available && exhausted === 0) {
+ return available.apply(thisValue, args);
+ }
+
+ for (i = 0; i < expectations.length; i += 1) {
+ push.call(messages, " " + expectations[i].toString());
+ }
+
+ messages.unshift("Unexpected call: " + sinon.spyCall.toString.call({
+ proxy: method,
+ args: args
+ }));
+
+ sinon.expectation.fail(messages.join("\n"));
+ }
+ });
+
+ var times = sinon.timesInWords;
+ var slice = Array.prototype.slice;
+
+ function callCountInWords(callCount) {
+ if (callCount === 0) {
+ return "never called";
+ }
+
+ return "called " + times(callCount);
+ }
+
+ function expectedCallCountInWords(expectation) {
+ var min = expectation.minCalls;
+ var max = expectation.maxCalls;
+
+ if (typeof min === "number" && typeof max === "number") {
+ var str = times(min);
+
+ if (min !== max) {
+ str = "at least " + str + " and at most " + times(max);
+ }
+
+ return str;
+ }
+
+ if (typeof min === "number") {
+ return "at least " + times(min);
+ }
+
+ return "at most " + times(max);
+ }
+
+ function receivedMinCalls(expectation) {
+ var hasMinLimit = typeof expectation.minCalls === "number";
+ return !hasMinLimit || expectation.callCount >= expectation.minCalls;
+ }
+
+ function receivedMaxCalls(expectation) {
+ if (typeof expectation.maxCalls !== "number") {
+ return false;
+ }
+
+ return expectation.callCount === expectation.maxCalls;
+ }
+
+ function verifyMatcher(possibleMatcher, arg) {
+ var isMatcher = match && match.isMatcher(possibleMatcher);
+
+ return isMatcher && possibleMatcher.test(arg) || true;
+ }
+
+ sinon.expectation = {
+ minCalls: 1,
+ maxCalls: 1,
+
+ create: function create(methodName) {
+ var expectation = sinon.extend(sinon.stub.create(), sinon.expectation);
+ delete expectation.create;
+ expectation.method = methodName;
+
+ return expectation;
+ },
+
+ invoke: function invoke(func, thisValue, args) {
+ this.verifyCallAllowed(thisValue, args);
+
+ return sinon.spy.invoke.apply(this, arguments);
+ },
+
+ atLeast: function atLeast(num) {
+ if (typeof num !== "number") {
+ throw new TypeError("'" + num + "' is not number");
+ }
+
+ if (!this.limitsSet) {
+ this.maxCalls = null;
+ this.limitsSet = true;
+ }
+
+ this.minCalls = num;
+
+ return this;
+ },
+
+ atMost: function atMost(num) {
+ if (typeof num !== "number") {
+ throw new TypeError("'" + num + "' is not number");
+ }
+
+ if (!this.limitsSet) {
+ this.minCalls = null;
+ this.limitsSet = true;
+ }
+
+ this.maxCalls = num;
+
+ return this;
+ },
+
+ never: function never() {
+ return this.exactly(0);
+ },
+
+ once: function once() {
+ return this.exactly(1);
+ },
+
+ twice: function twice() {
+ return this.exactly(2);
+ },
+
+ thrice: function thrice() {
+ return this.exactly(3);
+ },
+
+ exactly: function exactly(num) {
+ if (typeof num !== "number") {
+ throw new TypeError("'" + num + "' is not a number");
+ }
+
+ this.atLeast(num);
+ return this.atMost(num);
+ },
+
+ met: function met() {
+ return !this.failed && receivedMinCalls(this);
+ },
+
+ verifyCallAllowed: function verifyCallAllowed(thisValue, args) {
+ if (receivedMaxCalls(this)) {
+ this.failed = true;
+ sinon.expectation.fail(this.method + " already called " + times(this.maxCalls));
+ }
+
+ if ("expectedThis" in this && this.expectedThis !== thisValue) {
+ sinon.expectation.fail(this.method + " called with " + thisValue + " as thisValue, expected " +
+ this.expectedThis);
+ }
+
+ if (!("expectedArguments" in this)) {
+ return;
+ }
+
+ if (!args) {
+ sinon.expectation.fail(this.method + " received no arguments, expected " +
+ sinon.format(this.expectedArguments));
+ }
+
+ if (args.length < this.expectedArguments.length) {
+ sinon.expectation.fail(this.method + " received too few arguments (" + sinon.format(args) +
+ "), expected " + sinon.format(this.expectedArguments));
+ }
+
+ if (this.expectsExactArgCount &&
+ args.length !== this.expectedArguments.length) {
+ sinon.expectation.fail(this.method + " received too many arguments (" + sinon.format(args) +
+ "), expected " + sinon.format(this.expectedArguments));
+ }
+
+ for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
+
+ if (!verifyMatcher(this.expectedArguments[i], args[i])) {
+ sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
+ ", didn't match " + this.expectedArguments.toString());
+ }
+
+ if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
+ sinon.expectation.fail(this.method + " received wrong arguments " + sinon.format(args) +
+ ", expected " + sinon.format(this.expectedArguments));
+ }
+ }
+ },
+
+ allowsCall: function allowsCall(thisValue, args) {
+ if (this.met() && receivedMaxCalls(this)) {
+ return false;
+ }
+
+ if ("expectedThis" in this && this.expectedThis !== thisValue) {
+ return false;
+ }
+
+ if (!("expectedArguments" in this)) {
+ return true;
+ }
+
+ args = args || [];
+
+ if (args.length < this.expectedArguments.length) {
+ return false;
+ }
+
+ if (this.expectsExactArgCount &&
+ args.length !== this.expectedArguments.length) {
+ return false;
+ }
+
+ for (var i = 0, l = this.expectedArguments.length; i < l; i += 1) {
+ if (!verifyMatcher(this.expectedArguments[i], args[i])) {
+ return false;
+ }
+
+ if (!sinon.deepEqual(this.expectedArguments[i], args[i])) {
+ return false;
+ }
+ }
+
+ return true;
+ },
+
+ withArgs: function withArgs() {
+ this.expectedArguments = slice.call(arguments);
+ return this;
+ },
+
+ withExactArgs: function withExactArgs() {
+ this.withArgs.apply(this, arguments);
+ this.expectsExactArgCount = true;
+ return this;
+ },
+
+ on: function on(thisValue) {
+ this.expectedThis = thisValue;
+ return this;
+ },
+
+ toString: function () {
+ var args = (this.expectedArguments || []).slice();
+
+ if (!this.expectsExactArgCount) {
+ push.call(args, "[...]");
+ }
+
+ var callStr = sinon.spyCall.toString.call({
+ proxy: this.method || "anonymous mock expectation",
+ args: args
+ });
+
+ var message = callStr.replace(", [...", "[, ...") + " " +
+ expectedCallCountInWords(this);
+
+ if (this.met()) {
+ return "Expectation met: " + message;
+ }
+
+ return "Expected " + message + " (" +
+ callCountInWords(this.callCount) + ")";
+ },
+
+ verify: function verify() {
+ if (!this.met()) {
+ sinon.expectation.fail(this.toString());
+ } else {
+ sinon.expectation.pass(this.toString());
+ }
+
+ return true;
+ },
+
+ pass: function pass(message) {
+ sinon.assert.pass(message);
+ },
+
+ fail: function fail(message) {
+ var exception = new Error(message);
+ exception.name = "ExpectationError";
+
+ throw exception;
+ }
+ };
+
+ sinon.mock = mock;
+ return mock;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./util/core");
+ require("./times_in_words");
+ require("./call");
+ require("./extend");
+ require("./match");
+ require("./spy");
+ require("./stub");
+ require("./format");
+
+ module.exports = makeApi(sinon);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ * @depend spy.js
+ * @depend stub.js
+ * @depend mock.js
+ */
+/**
+ * Collections of stubs, spies and mocks.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+
+ var push = [].push;
+ var hasOwnProperty = Object.prototype.hasOwnProperty;
+
+ function getFakes(fakeCollection) {
+ if (!fakeCollection.fakes) {
+ fakeCollection.fakes = [];
+ }
+
+ return fakeCollection.fakes;
+ }
+
+ function each(fakeCollection, method) {
+ var fakes = getFakes(fakeCollection);
+
+ for (var i = 0, l = fakes.length; i < l; i += 1) {
+ if (typeof fakes[i][method] === "function") {
+ fakes[i][method]();
+ }
+ }
+ }
+
+ function compact(fakeCollection) {
+ var fakes = getFakes(fakeCollection);
+ var i = 0;
+ while (i < fakes.length) {
+ fakes.splice(i, 1);
+ }
+ }
+
+ function makeApi(sinon) {
+ var collection = {
+ verify: function resolve() {
+ each(this, "verify");
+ },
+
+ restore: function restore() {
+ each(this, "restore");
+ compact(this);
+ },
+
+ reset: function restore() {
+ each(this, "reset");
+ },
+
+ verifyAndRestore: function verifyAndRestore() {
+ var exception;
+
+ try {
+ this.verify();
+ } catch (e) {
+ exception = e;
+ }
+
+ this.restore();
+
+ if (exception) {
+ throw exception;
+ }
+ },
+
+ add: function add(fake) {
+ push.call(getFakes(this), fake);
+ return fake;
+ },
+
+ spy: function spy() {
+ return this.add(sinon.spy.apply(sinon, arguments));
+ },
+
+ stub: function stub(object, property, value) {
+ if (property) {
+ var original = object[property];
+
+ if (typeof original !== "function") {
+ if (!hasOwnProperty.call(object, property)) {
+ throw new TypeError("Cannot stub non-existent own property " + property);
+ }
+
+ object[property] = value;
+
+ return this.add({
+ restore: function () {
+ object[property] = original;
+ }
+ });
+ }
+ }
+ if (!property && !!object && typeof object === "object") {
+ var stubbedObj = sinon.stub.apply(sinon, arguments);
+
+ for (var prop in stubbedObj) {
+ if (typeof stubbedObj[prop] === "function") {
+ this.add(stubbedObj[prop]);
+ }
+ }
+
+ return stubbedObj;
+ }
+
+ return this.add(sinon.stub.apply(sinon, arguments));
+ },
+
+ mock: function mock() {
+ return this.add(sinon.mock.apply(sinon, arguments));
+ },
+
+ inject: function inject(obj) {
+ var col = this;
+
+ obj.spy = function () {
+ return col.spy.apply(col, arguments);
+ };
+
+ obj.stub = function () {
+ return col.stub.apply(col, arguments);
+ };
+
+ obj.mock = function () {
+ return col.mock.apply(col, arguments);
+ };
+
+ return obj;
+ }
+ };
+
+ sinon.collection = collection;
+ return collection;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./util/core");
+ require("./mock");
+ require("./spy");
+ require("./stub");
+ module.exports = makeApi(sinon);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * Fake timer API
+ * setTimeout
+ * setInterval
+ * clearTimeout
+ * clearInterval
+ * tick
+ * reset
+ * Date
+ *
+ * Inspired by jsUnitMockTimeOut from JsUnit
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function () {
+
+ function makeApi(s, lol) {
+ /*global lolex */
+ var llx = typeof lolex !== "undefined" ? lolex : lol;
+
+ s.useFakeTimers = function () {
+ var now;
+ var methods = Array.prototype.slice.call(arguments);
+
+ if (typeof methods[0] === "string") {
+ now = 0;
+ } else {
+ now = methods.shift();
+ }
+
+ var clock = llx.install(now || 0, methods);
+ clock.restore = clock.uninstall;
+ return clock;
+ };
+
+ s.clock = {
+ create: function (now) {
+ return llx.createClock(now);
+ }
+ };
+
+ s.timers = {
+ setTimeout: setTimeout,
+ clearTimeout: clearTimeout,
+ setImmediate: (typeof setImmediate !== "undefined" ? setImmediate : undefined),
+ clearImmediate: (typeof clearImmediate !== "undefined" ? clearImmediate : undefined),
+ setInterval: setInterval,
+ clearInterval: clearInterval,
+ Date: Date
+ };
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, epxorts, module, lolex) {
+ var core = require("./core");
+ makeApi(core, lolex);
+ module.exports = core;
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ } else if (isNode) {
+ loadDependencies(require, module.exports, module, require("lolex"));
+ } else {
+ makeApi(sinon); // eslint-disable-line no-undef
+ }
+}());
+
+/**
+ * Minimal Event interface implementation
+ *
+ * Original implementation by Sven Fuchs: https://gist.github.com/995028
+ * Modifications and tests by Christian Johansen.
+ *
+ * @author Sven Fuchs (svenfuchs@artweb-design.de)
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2011 Sven Fuchs, Christian Johansen
+ */
+if (typeof sinon === "undefined") {
+ this.sinon = {};
+}
+
+(function () {
+
+ var push = [].push;
+
+ function makeApi(sinon) {
+ sinon.Event = function Event(type, bubbles, cancelable, target) {
+ this.initEvent(type, bubbles, cancelable, target);
+ };
+
+ sinon.Event.prototype = {
+ initEvent: function (type, bubbles, cancelable, target) {
+ this.type = type;
+ this.bubbles = bubbles;
+ this.cancelable = cancelable;
+ this.target = target;
+ },
+
+ stopPropagation: function () {},
+
+ preventDefault: function () {
+ this.defaultPrevented = true;
+ }
+ };
+
+ sinon.ProgressEvent = function ProgressEvent(type, progressEventRaw, target) {
+ this.initEvent(type, false, false, target);
+ this.loaded = progressEventRaw.loaded || null;
+ this.total = progressEventRaw.total || null;
+ this.lengthComputable = !!progressEventRaw.total;
+ };
+
+ sinon.ProgressEvent.prototype = new sinon.Event();
+
+ sinon.ProgressEvent.prototype.constructor = sinon.ProgressEvent;
+
+ sinon.CustomEvent = function CustomEvent(type, customData, target) {
+ this.initEvent(type, false, false, target);
+ this.detail = customData.detail || null;
+ };
+
+ sinon.CustomEvent.prototype = new sinon.Event();
+
+ sinon.CustomEvent.prototype.constructor = sinon.CustomEvent;
+
+ sinon.EventTarget = {
+ addEventListener: function addEventListener(event, listener) {
+ this.eventListeners = this.eventListeners || {};
+ this.eventListeners[event] = this.eventListeners[event] || [];
+ push.call(this.eventListeners[event], listener);
+ },
+
+ removeEventListener: function removeEventListener(event, listener) {
+ var listeners = this.eventListeners && this.eventListeners[event] || [];
+
+ for (var i = 0, l = listeners.length; i < l; ++i) {
+ if (listeners[i] === listener) {
+ return listeners.splice(i, 1);
+ }
+ }
+ },
+
+ dispatchEvent: function dispatchEvent(event) {
+ var type = event.type;
+ var listeners = this.eventListeners && this.eventListeners[type] || [];
+
+ for (var i = 0; i < listeners.length; i++) {
+ if (typeof listeners[i] === "function") {
+ listeners[i].call(this, event);
+ } else {
+ listeners[i].handleEvent(event);
+ }
+ }
+
+ return !!event.defaultPrevented;
+ }
+ };
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require) {
+ var sinon = require("./core");
+ makeApi(sinon);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ } else if (isNode) {
+ loadDependencies(require);
+ } else {
+ makeApi(sinon); // eslint-disable-line no-undef
+ }
+}());
+
+/**
+ * @depend util/core.js
+ */
+/**
+ * Logs errors
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2014 Christian Johansen
+ */
+(function (sinonGlobal) {
+
+ // cache a reference to setTimeout, so that our reference won't be stubbed out
+ // when using fake timers and errors will still get logged
+ // https://github.com/cjohansen/Sinon.JS/issues/381
+ var realSetTimeout = setTimeout;
+
+ function makeApi(sinon) {
+
+ function log() {}
+
+ function logError(label, err) {
+ var msg = label + " threw exception: ";
+
+ function throwLoggedError() {
+ err.message = msg + err.message;
+ throw err;
+ }
+
+ sinon.log(msg + "[" + err.name + "] " + err.message);
+
+ if (err.stack) {
+ sinon.log(err.stack);
+ }
+
+ if (logError.useImmediateExceptions) {
+ throwLoggedError();
+ } else {
+ logError.setTimeout(throwLoggedError, 0);
+ }
+ }
+
+ // When set to true, any errors logged will be thrown immediately;
+ // If set to false, the errors will be thrown in separate execution frame.
+ logError.useImmediateExceptions = false;
+
+ // wrap realSetTimeout with something we can stub in tests
+ logError.setTimeout = function (func, timeout) {
+ realSetTimeout(func, timeout);
+ };
+
+ var exports = {};
+ exports.log = sinon.log = log;
+ exports.logError = sinon.logError = logError;
+
+ return exports;
+ }
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./util/core");
+ module.exports = makeApi(sinon);
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend core.js
+ * @depend ../extend.js
+ * @depend event.js
+ * @depend ../log_error.js
+ */
+/**
+ * Fake XDomainRequest object
+ */
+
+/**
+ * Returns the global to prevent assigning values to 'this' when this is undefined.
+ * This can occur when files are interpreted by node in strict mode.
+ * @private
+ */
+function getGlobal() {
+
+ return typeof window !== "undefined" ? window : global;
+}
+
+if (typeof sinon === "undefined") {
+ if (typeof this === "undefined") {
+ getGlobal().sinon = {};
+ } else {
+ this.sinon = {};
+ }
+}
+
+// wrapper for global
+(function (global) {
+
+ var xdr = { XDomainRequest: global.XDomainRequest };
+ xdr.GlobalXDomainRequest = global.XDomainRequest;
+ xdr.supportsXDR = typeof xdr.GlobalXDomainRequest !== "undefined";
+ xdr.workingXDR = xdr.supportsXDR ? xdr.GlobalXDomainRequest : false;
+
+ function makeApi(sinon) {
+ sinon.xdr = xdr;
+
+ function FakeXDomainRequest() {
+ this.readyState = FakeXDomainRequest.UNSENT;
+ this.requestBody = null;
+ this.requestHeaders = {};
+ this.status = 0;
+ this.timeout = null;
+
+ if (typeof FakeXDomainRequest.onCreate === "function") {
+ FakeXDomainRequest.onCreate(this);
+ }
+ }
+
+ function verifyState(x) {
+ if (x.readyState !== FakeXDomainRequest.OPENED) {
+ throw new Error("INVALID_STATE_ERR");
+ }
+
+ if (x.sendFlag) {
+ throw new Error("INVALID_STATE_ERR");
+ }
+ }
+
+ function verifyRequestSent(x) {
+ if (x.readyState === FakeXDomainRequest.UNSENT) {
+ throw new Error("Request not sent");
+ }
+ if (x.readyState === FakeXDomainRequest.DONE) {
+ throw new Error("Request done");
+ }
+ }
+
+ function verifyResponseBodyType(body) {
+ if (typeof body !== "string") {
+ var error = new Error("Attempted to respond to fake XDomainRequest with " +
+ body + ", which is not a string.");
+ error.name = "InvalidBodyException";
+ throw error;
+ }
+ }
+
+ sinon.extend(FakeXDomainRequest.prototype, sinon.EventTarget, {
+ open: function open(method, url) {
+ this.method = method;
+ this.url = url;
+
+ this.responseText = null;
+ this.sendFlag = false;
+
+ this.readyStateChange(FakeXDomainRequest.OPENED);
+ },
+
+ readyStateChange: function readyStateChange(state) {
+ this.readyState = state;
+ var eventName = "";
+ switch (this.readyState) {
+ case FakeXDomainRequest.UNSENT:
+ break;
+ case FakeXDomainRequest.OPENED:
+ break;
+ case FakeXDomainRequest.LOADING:
+ if (this.sendFlag) {
+ //raise the progress event
+ eventName = "onprogress";
+ }
+ break;
+ case FakeXDomainRequest.DONE:
+ if (this.isTimeout) {
+ eventName = "ontimeout";
+ } else if (this.errorFlag || (this.status < 200 || this.status > 299)) {
+ eventName = "onerror";
+ } else {
+ eventName = "onload";
+ }
+ break;
+ }
+
+ // raising event (if defined)
+ if (eventName) {
+ if (typeof this[eventName] === "function") {
+ try {
+ this[eventName]();
+ } catch (e) {
+ sinon.logError("Fake XHR " + eventName + " handler", e);
+ }
+ }
+ }
+ },
+
+ send: function send(data) {
+ verifyState(this);
+
+ if (!/^(get|head)$/i.test(this.method)) {
+ this.requestBody = data;
+ }
+ this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
+
+ this.errorFlag = false;
+ this.sendFlag = true;
+ this.readyStateChange(FakeXDomainRequest.OPENED);
+
+ if (typeof this.onSend === "function") {
+ this.onSend(this);
+ }
+ },
+
+ abort: function abort() {
+ this.aborted = true;
+ this.responseText = null;
+ this.errorFlag = true;
+
+ if (this.readyState > sinon.FakeXDomainRequest.UNSENT && this.sendFlag) {
+ this.readyStateChange(sinon.FakeXDomainRequest.DONE);
+ this.sendFlag = false;
+ }
+ },
+
+ setResponseBody: function setResponseBody(body) {
+ verifyRequestSent(this);
+ verifyResponseBodyType(body);
+
+ var chunkSize = this.chunkSize || 10;
+ var index = 0;
+ this.responseText = "";
+
+ do {
+ this.readyStateChange(FakeXDomainRequest.LOADING);
+ this.responseText += body.substring(index, index + chunkSize);
+ index += chunkSize;
+ } while (index < body.length);
+
+ this.readyStateChange(FakeXDomainRequest.DONE);
+ },
+
+ respond: function respond(status, contentType, body) {
+ // content-type ignored, since XDomainRequest does not carry this
+ // we keep the same syntax for respond(...) as for FakeXMLHttpRequest to ease
+ // test integration across browsers
+ this.status = typeof status === "number" ? status : 200;
+ this.setResponseBody(body || "");
+ },
+
+ simulatetimeout: function simulatetimeout() {
+ this.status = 0;
+ this.isTimeout = true;
+ // Access to this should actually throw an error
+ this.responseText = undefined;
+ this.readyStateChange(FakeXDomainRequest.DONE);
+ }
+ });
+
+ sinon.extend(FakeXDomainRequest, {
+ UNSENT: 0,
+ OPENED: 1,
+ LOADING: 3,
+ DONE: 4
+ });
+
+ sinon.useFakeXDomainRequest = function useFakeXDomainRequest() {
+ sinon.FakeXDomainRequest.restore = function restore(keepOnCreate) {
+ if (xdr.supportsXDR) {
+ global.XDomainRequest = xdr.GlobalXDomainRequest;
+ }
+
+ delete sinon.FakeXDomainRequest.restore;
+
+ if (keepOnCreate !== true) {
+ delete sinon.FakeXDomainRequest.onCreate;
+ }
+ };
+ if (xdr.supportsXDR) {
+ global.XDomainRequest = sinon.FakeXDomainRequest;
+ }
+ return sinon.FakeXDomainRequest;
+ };
+
+ sinon.FakeXDomainRequest = FakeXDomainRequest;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./core");
+ require("../extend");
+ require("./event");
+ require("../log_error");
+ makeApi(sinon);
+ module.exports = sinon;
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ } else if (isNode) {
+ loadDependencies(require, module.exports, module);
+ } else {
+ makeApi(sinon); // eslint-disable-line no-undef
+ }
+})(typeof global !== "undefined" ? global : self);
+
+/**
+ * @depend core.js
+ * @depend ../extend.js
+ * @depend event.js
+ * @depend ../log_error.js
+ */
+/**
+ * Fake XMLHttpRequest object
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal, global) {
+
+ function getWorkingXHR(globalScope) {
+ var supportsXHR = typeof globalScope.XMLHttpRequest !== "undefined";
+ if (supportsXHR) {
+ return globalScope.XMLHttpRequest;
+ }
+
+ var supportsActiveX = typeof globalScope.ActiveXObject !== "undefined";
+ if (supportsActiveX) {
+ return function () {
+ return new globalScope.ActiveXObject("MSXML2.XMLHTTP.3.0");
+ };
+ }
+
+ return false;
+ }
+
+ var supportsProgress = typeof ProgressEvent !== "undefined";
+ var supportsCustomEvent = typeof CustomEvent !== "undefined";
+ var supportsFormData = typeof FormData !== "undefined";
+ var supportsArrayBuffer = typeof ArrayBuffer !== "undefined";
+ var supportsBlob = typeof Blob === "function";
+ var sinonXhr = { XMLHttpRequest: global.XMLHttpRequest };
+ sinonXhr.GlobalXMLHttpRequest = global.XMLHttpRequest;
+ sinonXhr.GlobalActiveXObject = global.ActiveXObject;
+ sinonXhr.supportsActiveX = typeof sinonXhr.GlobalActiveXObject !== "undefined";
+ sinonXhr.supportsXHR = typeof sinonXhr.GlobalXMLHttpRequest !== "undefined";
+ sinonXhr.workingXHR = getWorkingXHR(global);
+ sinonXhr.supportsCORS = sinonXhr.supportsXHR && "withCredentials" in (new sinonXhr.GlobalXMLHttpRequest());
+
+ var unsafeHeaders = {
+ "Accept-Charset": true,
+ "Accept-Encoding": true,
+ Connection: true,
+ "Content-Length": true,
+ Cookie: true,
+ Cookie2: true,
+ "Content-Transfer-Encoding": true,
+ Date: true,
+ Expect: true,
+ Host: true,
+ "Keep-Alive": true,
+ Referer: true,
+ TE: true,
+ Trailer: true,
+ "Transfer-Encoding": true,
+ Upgrade: true,
+ "User-Agent": true,
+ Via: true
+ };
+
+ // An upload object is created for each
+ // FakeXMLHttpRequest and allows upload
+ // events to be simulated using uploadProgress
+ // and uploadError.
+ function UploadProgress() {
+ this.eventListeners = {
+ progress: [],
+ load: [],
+ abort: [],
+ error: []
+ };
+ }
+
+ UploadProgress.prototype.addEventListener = function addEventListener(event, listener) {
+ this.eventListeners[event].push(listener);
+ };
+
+ UploadProgress.prototype.removeEventListener = function removeEventListener(event, listener) {
+ var listeners = this.eventListeners[event] || [];
+
+ for (var i = 0, l = listeners.length; i < l; ++i) {
+ if (listeners[i] === listener) {
+ return listeners.splice(i, 1);
+ }
+ }
+ };
+
+ UploadProgress.prototype.dispatchEvent = function dispatchEvent(event) {
+ var listeners = this.eventListeners[event.type] || [];
+
+ for (var i = 0, listener; (listener = listeners[i]) != null; i++) {
+ listener(event);
+ }
+ };
+
+ // Note that for FakeXMLHttpRequest to work pre ES5
+ // we lose some of the alignment with the spec.
+ // To ensure as close a match as possible,
+ // set responseType before calling open, send or respond;
+ function FakeXMLHttpRequest() {
+ this.readyState = FakeXMLHttpRequest.UNSENT;
+ this.requestHeaders = {};
+ this.requestBody = null;
+ this.status = 0;
+ this.statusText = "";
+ this.upload = new UploadProgress();
+ this.responseType = "";
+ this.response = "";
+ if (sinonXhr.supportsCORS) {
+ this.withCredentials = false;
+ }
+
+ var xhr = this;
+ var events = ["loadstart", "load", "abort", "loadend"];
+
+ function addEventListener(eventName) {
+ xhr.addEventListener(eventName, function (event) {
+ var listener = xhr["on" + eventName];
+
+ if (listener && typeof listener === "function") {
+ listener.call(this, event);
+ }
+ });
+ }
+
+ for (var i = events.length - 1; i >= 0; i--) {
+ addEventListener(events[i]);
+ }
+
+ if (typeof FakeXMLHttpRequest.onCreate === "function") {
+ FakeXMLHttpRequest.onCreate(this);
+ }
+ }
+
+ function verifyState(xhr) {
+ if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
+ throw new Error("INVALID_STATE_ERR");
+ }
+
+ if (xhr.sendFlag) {
+ throw new Error("INVALID_STATE_ERR");
+ }
+ }
+
+ function getHeader(headers, header) {
+ header = header.toLowerCase();
+
+ for (var h in headers) {
+ if (h.toLowerCase() === header) {
+ return h;
+ }
+ }
+
+ return null;
+ }
+
+ // filtering to enable a white-list version of Sinon FakeXhr,
+ // where whitelisted requests are passed through to real XHR
+ function each(collection, callback) {
+ if (!collection) {
+ return;
+ }
+
+ for (var i = 0, l = collection.length; i < l; i += 1) {
+ callback(collection[i]);
+ }
+ }
+ function some(collection, callback) {
+ for (var index = 0; index < collection.length; index++) {
+ if (callback(collection[index]) === true) {
+ return true;
+ }
+ }
+ return false;
+ }
+ // largest arity in XHR is 5 - XHR#open
+ var apply = function (obj, method, args) {
+ switch (args.length) {
+ case 0: return obj[method]();
+ case 1: return obj[method](args[0]);
+ case 2: return obj[method](args[0], args[1]);
+ case 3: return obj[method](args[0], args[1], args[2]);
+ case 4: return obj[method](args[0], args[1], args[2], args[3]);
+ case 5: return obj[method](args[0], args[1], args[2], args[3], args[4]);
+ }
+ };
+
+ FakeXMLHttpRequest.filters = [];
+ FakeXMLHttpRequest.addFilter = function addFilter(fn) {
+ this.filters.push(fn);
+ };
+ var IE6Re = /MSIE 6/;
+ FakeXMLHttpRequest.defake = function defake(fakeXhr, xhrArgs) {
+ var xhr = new sinonXhr.workingXHR(); // eslint-disable-line new-cap
+
+ each([
+ "open",
+ "setRequestHeader",
+ "send",
+ "abort",
+ "getResponseHeader",
+ "getAllResponseHeaders",
+ "addEventListener",
+ "overrideMimeType",
+ "removeEventListener"
+ ], function (method) {
+ fakeXhr[method] = function () {
+ return apply(xhr, method, arguments);
+ };
+ });
+
+ var copyAttrs = function (args) {
+ each(args, function (attr) {
+ try {
+ fakeXhr[attr] = xhr[attr];
+ } catch (e) {
+ if (!IE6Re.test(navigator.userAgent)) {
+ throw e;
+ }
+ }
+ });
+ };
+
+ var stateChange = function stateChange() {
+ fakeXhr.readyState = xhr.readyState;
+ if (xhr.readyState >= FakeXMLHttpRequest.HEADERS_RECEIVED) {
+ copyAttrs(["status", "statusText"]);
+ }
+ if (xhr.readyState >= FakeXMLHttpRequest.LOADING) {
+ copyAttrs(["responseText", "response"]);
+ }
+ if (xhr.readyState === FakeXMLHttpRequest.DONE) {
+ copyAttrs(["responseXML"]);
+ }
+ if (fakeXhr.onreadystatechange) {
+ fakeXhr.onreadystatechange.call(fakeXhr, { target: fakeXhr });
+ }
+ };
+
+ if (xhr.addEventListener) {
+ for (var event in fakeXhr.eventListeners) {
+ if (fakeXhr.eventListeners.hasOwnProperty(event)) {
+
+ /*eslint-disable no-loop-func*/
+ each(fakeXhr.eventListeners[event], function (handler) {
+ xhr.addEventListener(event, handler);
+ });
+ /*eslint-enable no-loop-func*/
+ }
+ }
+ xhr.addEventListener("readystatechange", stateChange);
+ } else {
+ xhr.onreadystatechange = stateChange;
+ }
+ apply(xhr, "open", xhrArgs);
+ };
+ FakeXMLHttpRequest.useFilters = false;
+
+ function verifyRequestOpened(xhr) {
+ if (xhr.readyState !== FakeXMLHttpRequest.OPENED) {
+ throw new Error("INVALID_STATE_ERR - " + xhr.readyState);
+ }
+ }
+
+ function verifyRequestSent(xhr) {
+ if (xhr.readyState === FakeXMLHttpRequest.DONE) {
+ throw new Error("Request done");
+ }
+ }
+
+ function verifyHeadersReceived(xhr) {
+ if (xhr.async && xhr.readyState !== FakeXMLHttpRequest.HEADERS_RECEIVED) {
+ throw new Error("No headers received");
+ }
+ }
+
+ function verifyResponseBodyType(body) {
+ if (typeof body !== "string") {
+ var error = new Error("Attempted to respond to fake XMLHttpRequest with " +
+ body + ", which is not a string.");
+ error.name = "InvalidBodyException";
+ throw error;
+ }
+ }
+
+ function convertToArrayBuffer(body) {
+ var buffer = new ArrayBuffer(body.length);
+ var view = new Uint8Array(buffer);
+ for (var i = 0; i < body.length; i++) {
+ var charCode = body.charCodeAt(i);
+ if (charCode >= 256) {
+ throw new TypeError("arraybuffer or blob responseTypes require binary string, " +
+ "invalid character " + body[i] + " found.");
+ }
+ view[i] = charCode;
+ }
+ return buffer;
+ }
+
+ function isXmlContentType(contentType) {
+ return !contentType || /(text\/xml)|(application\/xml)|(\+xml)/.test(contentType);
+ }
+
+ function convertResponseBody(responseType, contentType, body) {
+ if (responseType === "" || responseType === "text") {
+ return body;
+ } else if (supportsArrayBuffer && responseType === "arraybuffer") {
+ return convertToArrayBuffer(body);
+ } else if (responseType === "json") {
+ try {
+ return JSON.parse(body);
+ } catch (e) {
+ // Return parsing failure as null
+ return null;
+ }
+ } else if (supportsBlob && responseType === "blob") {
+ var blobOptions = {};
+ if (contentType) {
+ blobOptions.type = contentType;
+ }
+ return new Blob([convertToArrayBuffer(body)], blobOptions);
+ } else if (responseType === "document") {
+ if (isXmlContentType(contentType)) {
+ return FakeXMLHttpRequest.parseXML(body);
+ }
+ return null;
+ }
+ throw new Error("Invalid responseType " + responseType);
+ }
+
+ function clearResponse(xhr) {
+ if (xhr.responseType === "" || xhr.responseType === "text") {
+ xhr.response = xhr.responseText = "";
+ } else {
+ xhr.response = xhr.responseText = null;
+ }
+ xhr.responseXML = null;
+ }
+
+ FakeXMLHttpRequest.parseXML = function parseXML(text) {
+ // Treat empty string as parsing failure
+ if (text !== "") {
+ try {
+ if (typeof DOMParser !== "undefined") {
+ var parser = new DOMParser();
+ return parser.parseFromString(text, "text/xml");
+ }
+ var xmlDoc = new window.ActiveXObject("Microsoft.XMLDOM");
+ xmlDoc.async = "false";
+ xmlDoc.loadXML(text);
+ return xmlDoc;
+ } catch (e) {
+ // Unable to parse XML - no biggie
+ }
+ }
+
+ return null;
+ };
+
+ FakeXMLHttpRequest.statusCodes = {
+ 100: "Continue",
+ 101: "Switching Protocols",
+ 200: "OK",
+ 201: "Created",
+ 202: "Accepted",
+ 203: "Non-Authoritative Information",
+ 204: "No Content",
+ 205: "Reset Content",
+ 206: "Partial Content",
+ 207: "Multi-Status",
+ 300: "Multiple Choice",
+ 301: "Moved Permanently",
+ 302: "Found",
+ 303: "See Other",
+ 304: "Not Modified",
+ 305: "Use Proxy",
+ 307: "Temporary Redirect",
+ 400: "Bad Request",
+ 401: "Unauthorized",
+ 402: "Payment Required",
+ 403: "Forbidden",
+ 404: "Not Found",
+ 405: "Method Not Allowed",
+ 406: "Not Acceptable",
+ 407: "Proxy Authentication Required",
+ 408: "Request Timeout",
+ 409: "Conflict",
+ 410: "Gone",
+ 411: "Length Required",
+ 412: "Precondition Failed",
+ 413: "Request Entity Too Large",
+ 414: "Request-URI Too Long",
+ 415: "Unsupported Media Type",
+ 416: "Requested Range Not Satisfiable",
+ 417: "Expectation Failed",
+ 422: "Unprocessable Entity",
+ 500: "Internal Server Error",
+ 501: "Not Implemented",
+ 502: "Bad Gateway",
+ 503: "Service Unavailable",
+ 504: "Gateway Timeout",
+ 505: "HTTP Version Not Supported"
+ };
+
+ function makeApi(sinon) {
+ sinon.xhr = sinonXhr;
+
+ sinon.extend(FakeXMLHttpRequest.prototype, sinon.EventTarget, {
+ async: true,
+
+ open: function open(method, url, async, username, password) {
+ this.method = method;
+ this.url = url;
+ this.async = typeof async === "boolean" ? async : true;
+ this.username = username;
+ this.password = password;
+ clearResponse(this);
+ this.requestHeaders = {};
+ this.sendFlag = false;
+
+ if (FakeXMLHttpRequest.useFilters === true) {
+ var xhrArgs = arguments;
+ var defake = some(FakeXMLHttpRequest.filters, function (filter) {
+ return filter.apply(this, xhrArgs);
+ });
+ if (defake) {
+ return FakeXMLHttpRequest.defake(this, arguments);
+ }
+ }
+ this.readyStateChange(FakeXMLHttpRequest.OPENED);
+ },
+
+ readyStateChange: function readyStateChange(state) {
+ this.readyState = state;
+
+ var readyStateChangeEvent = new sinon.Event("readystatechange", false, false, this);
+
+ if (typeof this.onreadystatechange === "function") {
+ try {
+ this.onreadystatechange(readyStateChangeEvent);
+ } catch (e) {
+ sinon.logError("Fake XHR onreadystatechange handler", e);
+ }
+ }
+
+ switch (this.readyState) {
+ case FakeXMLHttpRequest.DONE:
+ if (supportsProgress) {
+ this.upload.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
+ this.dispatchEvent(new sinon.ProgressEvent("progress", {loaded: 100, total: 100}));
+ }
+ this.upload.dispatchEvent(new sinon.Event("load", false, false, this));
+ this.dispatchEvent(new sinon.Event("load", false, false, this));
+ this.dispatchEvent(new sinon.Event("loadend", false, false, this));
+ break;
+ }
+
+ this.dispatchEvent(readyStateChangeEvent);
+ },
+
+ setRequestHeader: function setRequestHeader(header, value) {
+ verifyState(this);
+
+ if (unsafeHeaders[header] || /^(Sec-|Proxy-)/.test(header)) {
+ throw new Error("Refused to set unsafe header \"" + header + "\"");
+ }
+
+ if (this.requestHeaders[header]) {
+ this.requestHeaders[header] += "," + value;
+ } else {
+ this.requestHeaders[header] = value;
+ }
+ },
+
+ // Helps testing
+ setResponseHeaders: function setResponseHeaders(headers) {
+ verifyRequestOpened(this);
+ this.responseHeaders = {};
+
+ for (var header in headers) {
+ if (headers.hasOwnProperty(header)) {
+ this.responseHeaders[header] = headers[header];
+ }
+ }
+
+ if (this.async) {
+ this.readyStateChange(FakeXMLHttpRequest.HEADERS_RECEIVED);
+ } else {
+ this.readyState = FakeXMLHttpRequest.HEADERS_RECEIVED;
+ }
+ },
+
+ // Currently treats ALL data as a DOMString (i.e. no Document)
+ send: function send(data) {
+ verifyState(this);
+
+ if (!/^(get|head)$/i.test(this.method)) {
+ var contentType = getHeader(this.requestHeaders, "Content-Type");
+ if (this.requestHeaders[contentType]) {
+ var value = this.requestHeaders[contentType].split(";");
+ this.requestHeaders[contentType] = value[0] + ";charset=utf-8";
+ } else if (supportsFormData && !(data instanceof FormData)) {
+ this.requestHeaders["Content-Type"] = "text/plain;charset=utf-8";
+ }
+
+ this.requestBody = data;
+ }
+
+ this.errorFlag = false;
+ this.sendFlag = this.async;
+ clearResponse(this);
+ this.readyStateChange(FakeXMLHttpRequest.OPENED);
+
+ if (typeof this.onSend === "function") {
+ this.onSend(this);
+ }
+
+ this.dispatchEvent(new sinon.Event("loadstart", false, false, this));
+ },
+
+ abort: function abort() {
+ this.aborted = true;
+ clearResponse(this);
+ this.errorFlag = true;
+ this.requestHeaders = {};
+ this.responseHeaders = {};
+
+ if (this.readyState > FakeXMLHttpRequest.UNSENT && this.sendFlag) {
+ this.readyStateChange(FakeXMLHttpRequest.DONE);
+ this.sendFlag = false;
+ }
+
+ this.readyState = FakeXMLHttpRequest.UNSENT;
+
+ this.dispatchEvent(new sinon.Event("abort", false, false, this));
+
+ this.upload.dispatchEvent(new sinon.Event("abort", false, false, this));
+
+ if (typeof this.onerror === "function") {
+ this.onerror();
+ }
+ },
+
+ getResponseHeader: function getResponseHeader(header) {
+ if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
+ return null;
+ }
+
+ if (/^Set-Cookie2?$/i.test(header)) {
+ return null;
+ }
+
+ header = getHeader(this.responseHeaders, header);
+
+ return this.responseHeaders[header] || null;
+ },
+
+ getAllResponseHeaders: function getAllResponseHeaders() {
+ if (this.readyState < FakeXMLHttpRequest.HEADERS_RECEIVED) {
+ return "";
+ }
+
+ var headers = "";
+
+ for (var header in this.responseHeaders) {
+ if (this.responseHeaders.hasOwnProperty(header) &&
+ !/^Set-Cookie2?$/i.test(header)) {
+ headers += header + ": " + this.responseHeaders[header] + "\r\n";
+ }
+ }
+
+ return headers;
+ },
+
+ setResponseBody: function setResponseBody(body) {
+ verifyRequestSent(this);
+ verifyHeadersReceived(this);
+ verifyResponseBodyType(body);
+ var contentType = this.getResponseHeader("Content-Type");
+
+ var isTextResponse = this.responseType === "" || this.responseType === "text";
+ clearResponse(this);
+ if (this.async) {
+ var chunkSize = this.chunkSize || 10;
+ var index = 0;
+
+ do {
+ this.readyStateChange(FakeXMLHttpRequest.LOADING);
+
+ if (isTextResponse) {
+ this.responseText = this.response += body.substring(index, index + chunkSize);
+ }
+ index += chunkSize;
+ } while (index < body.length);
+ }
+
+ this.response = convertResponseBody(this.responseType, contentType, body);
+ if (isTextResponse) {
+ this.responseText = this.response;
+ }
+
+ if (this.responseType === "document") {
+ this.responseXML = this.response;
+ } else if (this.responseType === "" && isXmlContentType(contentType)) {
+ this.responseXML = FakeXMLHttpRequest.parseXML(this.responseText);
+ }
+ this.readyStateChange(FakeXMLHttpRequest.DONE);
+ },
+
+ respond: function respond(status, headers, body) {
+ this.status = typeof status === "number" ? status : 200;
+ this.statusText = FakeXMLHttpRequest.statusCodes[this.status];
+ this.setResponseHeaders(headers || {});
+ this.setResponseBody(body || "");
+ },
+
+ uploadProgress: function uploadProgress(progressEventRaw) {
+ if (supportsProgress) {
+ this.upload.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
+ }
+ },
+
+ downloadProgress: function downloadProgress(progressEventRaw) {
+ if (supportsProgress) {
+ this.dispatchEvent(new sinon.ProgressEvent("progress", progressEventRaw));
+ }
+ },
+
+ uploadError: function uploadError(error) {
+ if (supportsCustomEvent) {
+ this.upload.dispatchEvent(new sinon.CustomEvent("error", {detail: error}));
+ }
+ }
+ });
+
+ sinon.extend(FakeXMLHttpRequest, {
+ UNSENT: 0,
+ OPENED: 1,
+ HEADERS_RECEIVED: 2,
+ LOADING: 3,
+ DONE: 4
+ });
+
+ sinon.useFakeXMLHttpRequest = function () {
+ FakeXMLHttpRequest.restore = function restore(keepOnCreate) {
+ if (sinonXhr.supportsXHR) {
+ global.XMLHttpRequest = sinonXhr.GlobalXMLHttpRequest;
+ }
+
+ if (sinonXhr.supportsActiveX) {
+ global.ActiveXObject = sinonXhr.GlobalActiveXObject;
+ }
+
+ delete FakeXMLHttpRequest.restore;
+
+ if (keepOnCreate !== true) {
+ delete FakeXMLHttpRequest.onCreate;
+ }
+ };
+ if (sinonXhr.supportsXHR) {
+ global.XMLHttpRequest = FakeXMLHttpRequest;
+ }
+
+ if (sinonXhr.supportsActiveX) {
+ global.ActiveXObject = function ActiveXObject(objId) {
+ if (objId === "Microsoft.XMLHTTP" || /^Msxml2\.XMLHTTP/i.test(objId)) {
+
+ return new FakeXMLHttpRequest();
+ }
+
+ return new sinonXhr.GlobalActiveXObject(objId);
+ };
+ }
+
+ return FakeXMLHttpRequest;
+ };
+
+ sinon.FakeXMLHttpRequest = FakeXMLHttpRequest;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./core");
+ require("../extend");
+ require("./event");
+ require("../log_error");
+ makeApi(sinon);
+ module.exports = sinon;
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon, // eslint-disable-line no-undef
+ typeof global !== "undefined" ? global : self
+));
+
+/**
+ * @depend fake_xdomain_request.js
+ * @depend fake_xml_http_request.js
+ * @depend ../format.js
+ * @depend ../log_error.js
+ */
+/**
+ * The Sinon "server" mimics a web server that receives requests from
+ * sinon.FakeXMLHttpRequest and provides an API to respond to those requests,
+ * both synchronously and asynchronously. To respond synchronuously, canned
+ * answers have to be provided upfront.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function () {
+
+ var push = [].push;
+
+ function responseArray(handler) {
+ var response = handler;
+
+ if (Object.prototype.toString.call(handler) !== "[object Array]") {
+ response = [200, {}, handler];
+ }
+
+ if (typeof response[2] !== "string") {
+ throw new TypeError("Fake server response body should be string, but was " +
+ typeof response[2]);
+ }
+
+ return response;
+ }
+
+ var wloc = typeof window !== "undefined" ? window.location : {};
+ var rCurrLoc = new RegExp("^" + wloc.protocol + "//" + wloc.host);
+
+ function matchOne(response, reqMethod, reqUrl) {
+ var rmeth = response.method;
+ var matchMethod = !rmeth || rmeth.toLowerCase() === reqMethod.toLowerCase();
+ var url = response.url;
+ var matchUrl = !url || url === reqUrl || (typeof url.test === "function" && url.test(reqUrl));
+
+ return matchMethod && matchUrl;
+ }
+
+ function match(response, request) {
+ var requestUrl = request.url;
+
+ if (!/^https?:\/\//.test(requestUrl) || rCurrLoc.test(requestUrl)) {
+ requestUrl = requestUrl.replace(rCurrLoc, "");
+ }
+
+ if (matchOne(response, this.getHTTPMethod(request), requestUrl)) {
+ if (typeof response.response === "function") {
+ var ru = response.url;
+ var args = [request].concat(ru && typeof ru.exec === "function" ? ru.exec(requestUrl).slice(1) : []);
+ return response.response.apply(response, args);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ function makeApi(sinon) {
+ sinon.fakeServer = {
+ create: function (config) {
+ var server = sinon.create(this);
+ server.configure(config);
+ if (!sinon.xhr.supportsCORS) {
+ this.xhr = sinon.useFakeXDomainRequest();
+ } else {
+ this.xhr = sinon.useFakeXMLHttpRequest();
+ }
+ server.requests = [];
+
+ this.xhr.onCreate = function (xhrObj) {
+ server.addRequest(xhrObj);
+ };
+
+ return server;
+ },
+ configure: function (config) {
+ var whitelist = {
+ "autoRespond": true,
+ "autoRespondAfter": true,
+ "respondImmediately": true,
+ "fakeHTTPMethods": true
+ };
+ var setting;
+
+ config = config || {};
+ for (setting in config) {
+ if (whitelist.hasOwnProperty(setting) && config.hasOwnProperty(setting)) {
+ this[setting] = config[setting];
+ }
+ }
+ },
+ addRequest: function addRequest(xhrObj) {
+ var server = this;
+ push.call(this.requests, xhrObj);
+
+ xhrObj.onSend = function () {
+ server.handleRequest(this);
+
+ if (server.respondImmediately) {
+ server.respond();
+ } else if (server.autoRespond && !server.responding) {
+ setTimeout(function () {
+ server.responding = false;
+ server.respond();
+ }, server.autoRespondAfter || 10);
+
+ server.responding = true;
+ }
+ };
+ },
+
+ getHTTPMethod: function getHTTPMethod(request) {
+ if (this.fakeHTTPMethods && /post/i.test(request.method)) {
+ var matches = (request.requestBody || "").match(/_method=([^\b;]+)/);
+ return matches ? matches[1] : request.method;
+ }
+
+ return request.method;
+ },
+
+ handleRequest: function handleRequest(xhr) {
+ if (xhr.async) {
+ if (!this.queue) {
+ this.queue = [];
+ }
+
+ push.call(this.queue, xhr);
+ } else {
+ this.processRequest(xhr);
+ }
+ },
+
+ log: function log(response, request) {
+ var str;
+
+ str = "Request:\n" + sinon.format(request) + "\n\n";
+ str += "Response:\n" + sinon.format(response) + "\n\n";
+
+ sinon.log(str);
+ },
+
+ respondWith: function respondWith(method, url, body) {
+ if (arguments.length === 1 && typeof method !== "function") {
+ this.response = responseArray(method);
+ return;
+ }
+
+ if (!this.responses) {
+ this.responses = [];
+ }
+
+ if (arguments.length === 1) {
+ body = method;
+ url = method = null;
+ }
+
+ if (arguments.length === 2) {
+ body = url;
+ url = method;
+ method = null;
+ }
+
+ push.call(this.responses, {
+ method: method,
+ url: url,
+ response: typeof body === "function" ? body : responseArray(body)
+ });
+ },
+
+ respond: function respond() {
+ if (arguments.length > 0) {
+ this.respondWith.apply(this, arguments);
+ }
+
+ var queue = this.queue || [];
+ var requests = queue.splice(0, queue.length);
+
+ for (var i = 0; i < requests.length; i++) {
+ this.processRequest(requests[i]);
+ }
+ },
+
+ processRequest: function processRequest(request) {
+ try {
+ if (request.aborted) {
+ return;
+ }
+
+ var response = this.response || [404, {}, ""];
+
+ if (this.responses) {
+ for (var l = this.responses.length, i = l - 1; i >= 0; i--) {
+ if (match.call(this, this.responses[i], request)) {
+ response = this.responses[i].response;
+ break;
+ }
+ }
+ }
+
+ if (request.readyState !== 4) {
+ this.log(response, request);
+
+ request.respond(response[0], response[1], response[2]);
+ }
+ } catch (e) {
+ sinon.logError("Fake server request processing", e);
+ }
+ },
+
+ restore: function restore() {
+ return this.xhr.restore && this.xhr.restore.apply(this.xhr, arguments);
+ }
+ };
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./core");
+ require("./fake_xdomain_request");
+ require("./fake_xml_http_request");
+ require("../format");
+ makeApi(sinon);
+ module.exports = sinon;
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ } else if (isNode) {
+ loadDependencies(require, module.exports, module);
+ } else {
+ makeApi(sinon); // eslint-disable-line no-undef
+ }
+}());
+
+/**
+ * @depend fake_server.js
+ * @depend fake_timers.js
+ */
+/**
+ * Add-on for sinon.fakeServer that automatically handles a fake timer along with
+ * the FakeXMLHttpRequest. The direct inspiration for this add-on is jQuery
+ * 1.3.x, which does not use xhr object's onreadystatehandler at all - instead,
+ * it polls the object for completion with setInterval. Dispite the direct
+ * motivation, there is nothing jQuery-specific in this file, so it can be used
+ * in any environment where the ajax implementation depends on setInterval or
+ * setTimeout.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function () {
+
+ function makeApi(sinon) {
+ function Server() {}
+ Server.prototype = sinon.fakeServer;
+
+ sinon.fakeServerWithClock = new Server();
+
+ sinon.fakeServerWithClock.addRequest = function addRequest(xhr) {
+ if (xhr.async) {
+ if (typeof setTimeout.clock === "object") {
+ this.clock = setTimeout.clock;
+ } else {
+ this.clock = sinon.useFakeTimers();
+ this.resetClock = true;
+ }
+
+ if (!this.longestTimeout) {
+ var clockSetTimeout = this.clock.setTimeout;
+ var clockSetInterval = this.clock.setInterval;
+ var server = this;
+
+ this.clock.setTimeout = function (fn, timeout) {
+ server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
+
+ return clockSetTimeout.apply(this, arguments);
+ };
+
+ this.clock.setInterval = function (fn, timeout) {
+ server.longestTimeout = Math.max(timeout, server.longestTimeout || 0);
+
+ return clockSetInterval.apply(this, arguments);
+ };
+ }
+ }
+
+ return sinon.fakeServer.addRequest.call(this, xhr);
+ };
+
+ sinon.fakeServerWithClock.respond = function respond() {
+ var returnVal = sinon.fakeServer.respond.apply(this, arguments);
+
+ if (this.clock) {
+ this.clock.tick(this.longestTimeout || 0);
+ this.longestTimeout = 0;
+
+ if (this.resetClock) {
+ this.clock.restore();
+ this.resetClock = false;
+ }
+ }
+
+ return returnVal;
+ };
+
+ sinon.fakeServerWithClock.restore = function restore() {
+ if (this.clock) {
+ this.clock.restore();
+ }
+
+ return sinon.fakeServer.restore.apply(this, arguments);
+ };
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require) {
+ var sinon = require("./core");
+ require("./fake_server");
+ require("./fake_timers");
+ makeApi(sinon);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ } else if (isNode) {
+ loadDependencies(require);
+ } else {
+ makeApi(sinon); // eslint-disable-line no-undef
+ }
+}());
+
+/**
+ * @depend util/core.js
+ * @depend extend.js
+ * @depend collection.js
+ * @depend util/fake_timers.js
+ * @depend util/fake_server_with_clock.js
+ */
+/**
+ * Manages fake collections as well as fake utilities such as Sinon's
+ * timers and fake XHR implementation in one convenient object.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+
+ function makeApi(sinon) {
+ var push = [].push;
+
+ function exposeValue(sandbox, config, key, value) {
+ if (!value) {
+ return;
+ }
+
+ if (config.injectInto && !(key in config.injectInto)) {
+ config.injectInto[key] = value;
+ sandbox.injectedKeys.push(key);
+ } else {
+ push.call(sandbox.args, value);
+ }
+ }
+
+ function prepareSandboxFromConfig(config) {
+ var sandbox = sinon.create(sinon.sandbox);
+
+ if (config.useFakeServer) {
+ if (typeof config.useFakeServer === "object") {
+ sandbox.serverPrototype = config.useFakeServer;
+ }
+
+ sandbox.useFakeServer();
+ }
+
+ if (config.useFakeTimers) {
+ if (typeof config.useFakeTimers === "object") {
+ sandbox.useFakeTimers.apply(sandbox, config.useFakeTimers);
+ } else {
+ sandbox.useFakeTimers();
+ }
+ }
+
+ return sandbox;
+ }
+
+ sinon.sandbox = sinon.extend(sinon.create(sinon.collection), {
+ useFakeTimers: function useFakeTimers() {
+ this.clock = sinon.useFakeTimers.apply(sinon, arguments);
+
+ return this.add(this.clock);
+ },
+
+ serverPrototype: sinon.fakeServer,
+
+ useFakeServer: function useFakeServer() {
+ var proto = this.serverPrototype || sinon.fakeServer;
+
+ if (!proto || !proto.create) {
+ return null;
+ }
+
+ this.server = proto.create();
+ return this.add(this.server);
+ },
+
+ inject: function (obj) {
+ sinon.collection.inject.call(this, obj);
+
+ if (this.clock) {
+ obj.clock = this.clock;
+ }
+
+ if (this.server) {
+ obj.server = this.server;
+ obj.requests = this.server.requests;
+ }
+
+ obj.match = sinon.match;
+
+ return obj;
+ },
+
+ restore: function () {
+ sinon.collection.restore.apply(this, arguments);
+ this.restoreContext();
+ },
+
+ restoreContext: function () {
+ if (this.injectedKeys) {
+ for (var i = 0, j = this.injectedKeys.length; i < j; i++) {
+ delete this.injectInto[this.injectedKeys[i]];
+ }
+ this.injectedKeys = [];
+ }
+ },
+
+ create: function (config) {
+ if (!config) {
+ return sinon.create(sinon.sandbox);
+ }
+
+ var sandbox = prepareSandboxFromConfig(config);
+ sandbox.args = sandbox.args || [];
+ sandbox.injectedKeys = [];
+ sandbox.injectInto = config.injectInto;
+ var prop,
+ value;
+ var exposed = sandbox.inject({});
+
+ if (config.properties) {
+ for (var i = 0, l = config.properties.length; i < l; i++) {
+ prop = config.properties[i];
+ value = exposed[prop] || prop === "sandbox" && sandbox;
+ exposeValue(sandbox, config, prop, value);
+ }
+ } else {
+ exposeValue(sandbox, config, "sandbox", value);
+ }
+
+ return sandbox;
+ },
+
+ match: sinon.match
+ });
+
+ sinon.sandbox.useFakeXMLHttpRequest = sinon.sandbox.useFakeServer;
+
+ return sinon.sandbox;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./util/core");
+ require("./extend");
+ require("./util/fake_server_with_clock");
+ require("./util/fake_timers");
+ require("./collection");
+ module.exports = makeApi(sinon);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend util/core.js
+ * @depend sandbox.js
+ */
+/**
+ * Test function, sandboxes fakes
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+
+ function makeApi(sinon) {
+ var slice = Array.prototype.slice;
+
+ function test(callback) {
+ var type = typeof callback;
+
+ if (type !== "function") {
+ throw new TypeError("sinon.test needs to wrap a test function, got " + type);
+ }
+
+ function sinonSandboxedTest() {
+ var config = sinon.getConfig(sinon.config);
+ config.injectInto = config.injectIntoThis && this || config.injectInto;
+ var sandbox = sinon.sandbox.create(config);
+ var args = slice.call(arguments);
+ var oldDone = args.length && args[args.length - 1];
+ var exception, result;
+
+ if (typeof oldDone === "function") {
+ args[args.length - 1] = function sinonDone(res) {
+ if (res) {
+ sandbox.restore();
+ } else {
+ sandbox.verifyAndRestore();
+ }
+ oldDone(res);
+ };
+ }
+
+ try {
+ result = callback.apply(this, args.concat(sandbox.args));
+ } catch (e) {
+ exception = e;
+ }
+
+ if (typeof oldDone !== "function") {
+ if (typeof exception !== "undefined") {
+ sandbox.restore();
+ throw exception;
+ } else {
+ sandbox.verifyAndRestore();
+ }
+ }
+
+ return result;
+ }
+
+ if (callback.length) {
+ return function sinonAsyncSandboxedTest(done) { // eslint-disable-line no-unused-vars
+ return sinonSandboxedTest.apply(this, arguments);
+ };
+ }
+
+ return sinonSandboxedTest;
+ }
+
+ test.config = {
+ injectIntoThis: true,
+ injectInto: null,
+ properties: ["spy", "stub", "mock", "clock", "server", "requests"],
+ useFakeTimers: true,
+ useFakeServer: true
+ };
+
+ sinon.test = test;
+ return test;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var core = require("./util/core");
+ require("./sandbox");
+ module.exports = makeApi(core);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ } else if (isNode) {
+ loadDependencies(require, module.exports, module);
+ } else if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(typeof sinon === "object" && sinon || null)); // eslint-disable-line no-undef
+
+/**
+ * @depend util/core.js
+ * @depend test.js
+ */
+/**
+ * Test case, sandboxes all test functions
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal) {
+
+ function createTest(property, setUp, tearDown) {
+ return function () {
+ if (setUp) {
+ setUp.apply(this, arguments);
+ }
+
+ var exception, result;
+
+ try {
+ result = property.apply(this, arguments);
+ } catch (e) {
+ exception = e;
+ }
+
+ if (tearDown) {
+ tearDown.apply(this, arguments);
+ }
+
+ if (exception) {
+ throw exception;
+ }
+
+ return result;
+ };
+ }
+
+ function makeApi(sinon) {
+ function testCase(tests, prefix) {
+ if (!tests || typeof tests !== "object") {
+ throw new TypeError("sinon.testCase needs an object with test functions");
+ }
+
+ prefix = prefix || "test";
+ var rPrefix = new RegExp("^" + prefix);
+ var methods = {};
+ var setUp = tests.setUp;
+ var tearDown = tests.tearDown;
+ var testName,
+ property,
+ method;
+
+ for (testName in tests) {
+ if (tests.hasOwnProperty(testName) && !/^(setUp|tearDown)$/.test(testName)) {
+ property = tests[testName];
+
+ if (typeof property === "function" && rPrefix.test(testName)) {
+ method = property;
+
+ if (setUp || tearDown) {
+ method = createTest(property, setUp, tearDown);
+ }
+
+ methods[testName] = sinon.test(method);
+ } else {
+ methods[testName] = tests[testName];
+ }
+ }
+ }
+
+ return methods;
+ }
+
+ sinon.testCase = testCase;
+ return testCase;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var core = require("./util/core");
+ require("./test");
+ module.exports = makeApi(core);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon // eslint-disable-line no-undef
+));
+
+/**
+ * @depend times_in_words.js
+ * @depend util/core.js
+ * @depend match.js
+ * @depend format.js
+ */
+/**
+ * Assertions matching the test spy retrieval interface.
+ *
+ * @author Christian Johansen (christian@cjohansen.no)
+ * @license BSD
+ *
+ * Copyright (c) 2010-2013 Christian Johansen
+ */
+(function (sinonGlobal, global) {
+
+ var slice = Array.prototype.slice;
+
+ function makeApi(sinon) {
+ var assert;
+
+ function verifyIsStub() {
+ var method;
+
+ for (var i = 0, l = arguments.length; i < l; ++i) {
+ method = arguments[i];
+
+ if (!method) {
+ assert.fail("fake is not a spy");
+ }
+
+ if (method.proxy && method.proxy.isSinonProxy) {
+ verifyIsStub(method.proxy);
+ } else {
+ if (typeof method !== "function") {
+ assert.fail(method + " is not a function");
+ }
+
+ if (typeof method.getCall !== "function") {
+ assert.fail(method + " is not stubbed");
+ }
+ }
+
+ }
+ }
+
+ function failAssertion(object, msg) {
+ object = object || global;
+ var failMethod = object.fail || assert.fail;
+ failMethod.call(object, msg);
+ }
+
+ function mirrorPropAsAssertion(name, method, message) {
+ if (arguments.length === 2) {
+ message = method;
+ method = name;
+ }
+
+ assert[name] = function (fake) {
+ verifyIsStub(fake);
+
+ var args = slice.call(arguments, 1);
+ var failed = false;
+
+ if (typeof method === "function") {
+ failed = !method(fake);
+ } else {
+ failed = typeof fake[method] === "function" ?
+ !fake[method].apply(fake, args) : !fake[method];
+ }
+
+ if (failed) {
+ failAssertion(this, (fake.printf || fake.proxy.printf).apply(fake, [message].concat(args)));
+ } else {
+ assert.pass(name);
+ }
+ };
+ }
+
+ function exposedName(prefix, prop) {
+ return !prefix || /^fail/.test(prop) ? prop :
+ prefix + prop.slice(0, 1).toUpperCase() + prop.slice(1);
+ }
+
+ assert = {
+ failException: "AssertError",
+
+ fail: function fail(message) {
+ var error = new Error(message);
+ error.name = this.failException || assert.failException;
+
+ throw error;
+ },
+
+ pass: function pass() {},
+
+ callOrder: function assertCallOrder() {
+ verifyIsStub.apply(null, arguments);
+ var expected = "";
+ var actual = "";
+
+ if (!sinon.calledInOrder(arguments)) {
+ try {
+ expected = [].join.call(arguments, ", ");
+ var calls = slice.call(arguments);
+ var i = calls.length;
+ while (i) {
+ if (!calls[--i].called) {
+ calls.splice(i, 1);
+ }
+ }
+ actual = sinon.orderByFirstCall(calls).join(", ");
+ } catch (e) {
+ // If this fails, we'll just fall back to the blank string
+ }
+
+ failAssertion(this, "expected " + expected + " to be " +
+ "called in order but were called as " + actual);
+ } else {
+ assert.pass("callOrder");
+ }
+ },
+
+ callCount: function assertCallCount(method, count) {
+ verifyIsStub(method);
+
+ if (method.callCount !== count) {
+ var msg = "expected %n to be called " + sinon.timesInWords(count) +
+ " but was called %c%C";
+ failAssertion(this, method.printf(msg));
+ } else {
+ assert.pass("callCount");
+ }
+ },
+
+ expose: function expose(target, options) {
+ if (!target) {
+ throw new TypeError("target is null or undefined");
+ }
+
+ var o = options || {};
+ var prefix = typeof o.prefix === "undefined" && "assert" || o.prefix;
+ var includeFail = typeof o.includeFail === "undefined" || !!o.includeFail;
+
+ for (var method in this) {
+ if (method !== "expose" && (includeFail || !/^(fail)/.test(method))) {
+ target[exposedName(prefix, method)] = this[method];
+ }
+ }
+
+ return target;
+ },
+
+ match: function match(actual, expectation) {
+ var matcher = sinon.match(expectation);
+ if (matcher.test(actual)) {
+ assert.pass("match");
+ } else {
+ var formatted = [
+ "expected value to match",
+ " expected = " + sinon.format(expectation),
+ " actual = " + sinon.format(actual)
+ ];
+
+ failAssertion(this, formatted.join("\n"));
+ }
+ }
+ };
+
+ mirrorPropAsAssertion("called", "expected %n to have been called at least once but was never called");
+ mirrorPropAsAssertion("notCalled", function (spy) {
+ return !spy.called;
+ }, "expected %n to not have been called but was called %c%C");
+ mirrorPropAsAssertion("calledOnce", "expected %n to be called once but was called %c%C");
+ mirrorPropAsAssertion("calledTwice", "expected %n to be called twice but was called %c%C");
+ mirrorPropAsAssertion("calledThrice", "expected %n to be called thrice but was called %c%C");
+ mirrorPropAsAssertion("calledOn", "expected %n to be called with %1 as this but was called with %t");
+ mirrorPropAsAssertion(
+ "alwaysCalledOn",
+ "expected %n to always be called with %1 as this but was called with %t"
+ );
+ mirrorPropAsAssertion("calledWithNew", "expected %n to be called with new");
+ mirrorPropAsAssertion("alwaysCalledWithNew", "expected %n to always be called with new");
+ mirrorPropAsAssertion("calledWith", "expected %n to be called with arguments %*%C");
+ mirrorPropAsAssertion("calledWithMatch", "expected %n to be called with match %*%C");
+ mirrorPropAsAssertion("alwaysCalledWith", "expected %n to always be called with arguments %*%C");
+ mirrorPropAsAssertion("alwaysCalledWithMatch", "expected %n to always be called with match %*%C");
+ mirrorPropAsAssertion("calledWithExactly", "expected %n to be called with exact arguments %*%C");
+ mirrorPropAsAssertion("alwaysCalledWithExactly", "expected %n to always be called with exact arguments %*%C");
+ mirrorPropAsAssertion("neverCalledWith", "expected %n to never be called with arguments %*%C");
+ mirrorPropAsAssertion("neverCalledWithMatch", "expected %n to never be called with match %*%C");
+ mirrorPropAsAssertion("threw", "%n did not throw exception%C");
+ mirrorPropAsAssertion("alwaysThrew", "%n did not always throw exception%C");
+
+ sinon.assert = assert;
+ return assert;
+ }
+
+ var isNode = typeof module !== "undefined" && module.exports && typeof require === "function";
+ var isAMD = typeof define === "function" && typeof define.amd === "object" && define.amd;
+
+ function loadDependencies(require, exports, module) {
+ var sinon = require("./util/core");
+ require("./match");
+ require("./format");
+ module.exports = makeApi(sinon);
+ }
+
+ if (isAMD) {
+ define(loadDependencies);
+ return;
+ }
+
+ if (isNode) {
+ loadDependencies(require, module.exports, module);
+ return;
+ }
+
+ if (sinonGlobal) {
+ makeApi(sinonGlobal);
+ }
+}(
+ typeof sinon === "object" && sinon, // eslint-disable-line no-undef
+ typeof global !== "undefined" ? global : self
+));
+
+ return sinon;
+}));
diff --git a/www/wiki/resources/src/dom-level2-skip.js b/www/wiki/resources/src/dom-level2-skip.js
new file mode 100644
index 00000000..484c295e
--- /dev/null
+++ b/www/wiki/resources/src/dom-level2-skip.js
@@ -0,0 +1,6 @@
+/*!
+ * Skip function for dom-level2-shim module.
+ *
+ * Tests for window.Node because that's the only thing that this shim is adding.
+ */
+return !!window.Node;
diff --git a/www/wiki/resources/src/es5-skip.js b/www/wiki/resources/src/es5-skip.js
new file mode 100644
index 00000000..a4039d89
--- /dev/null
+++ b/www/wiki/resources/src/es5-skip.js
@@ -0,0 +1,18 @@
+/*!
+ * Skip function for es5-shim module.
+ *
+ * Test for strict mode as a proxy for full ES5 function support (but not syntax)
+ * Per http://kangax.github.io/compat-table/es5/ this is a reasonable shortcut
+ * that still allows this to be as short as possible (there are no browsers we
+ * support that have strict mode, but lack other features).
+ *
+ * Do explicitly test for Function#bind because of PhantomJS (which implements
+ * strict mode, but lacks Function#bind).
+ *
+ * IE9 supports all features except strict mode, so loading es5-shim should be close to
+ * a no-op but does increase page payload).
+ */
+return ( function () {
+ 'use strict';
+ return !this && !!Function.prototype.bind;
+}() );
diff --git a/www/wiki/resources/src/jquery.tipsy/images/tipsy.png b/www/wiki/resources/src/jquery.tipsy/images/tipsy.png
new file mode 100644
index 00000000..53f7153a
--- /dev/null
+++ b/www/wiki/resources/src/jquery.tipsy/images/tipsy.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery.tipsy/jquery.tipsy.css b/www/wiki/resources/src/jquery.tipsy/jquery.tipsy.css
new file mode 100644
index 00000000..9036dd3c
--- /dev/null
+++ b/www/wiki/resources/src/jquery.tipsy/jquery.tipsy.css
@@ -0,0 +1,73 @@
+.tipsy {
+ padding: 5px;
+ position: absolute;
+ z-index: 100000;
+ cursor: default;
+}
+.tipsy-inner {
+ padding: 5px 8px 4px 8px;
+ /*background-color: #e8f2f8;*/
+ background-color: #fff;
+ border: solid 1px #a7d7f9;
+ color: #000;
+ max-width: 15em;
+ border-radius: 4px;
+ /*
+ -moz-box-shadow: 0px 2px 8px #cccccc;
+ -webkit-box-shadow: 0px 2px 8px #cccccc;
+ box-shadow: 0px 2px 8px #cccccc;
+ -ms-filter: "progid:DXImageTransform.Microsoft.DropShadow(OffX=0, OffY=2, Strength=6, Direction=90, Color='#cccccc')";
+ filter: progid:DXImageTransform.Microsoft.DropShadow(OffX=0, OffY=2, Strength=6, Direction=90, Color='#cccccc');
+ */
+}
+.tipsy-arrow {
+ position: absolute;
+ /* @embed */
+ background: url( images/tipsy.png ) no-repeat top left;
+ width: 11px;
+ height: 6px;
+}
+/* @noflip */ .tipsy-n .tipsy-arrow {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+}
+/* @noflip */ .tipsy-nw .tipsy-arrow {
+ top: 0;
+ left: 10px;
+}
+/* @noflip */ .tipsy-ne .tipsy-arrow {
+ top: 0;
+ right: 10px;
+}
+/* @noflip */ .tipsy-s .tipsy-arrow {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ background-position: bottom left;
+}
+/* @noflip */ .tipsy-sw .tipsy-arrow {
+ bottom: 0;
+ left: 10px;
+ background-position: bottom left;
+}
+/* @noflip */ .tipsy-se .tipsy-arrow {
+ bottom: 0;
+ right: 10px;
+ background-position: bottom left;
+}
+/* @noflip */ .tipsy-e .tipsy-arrow {
+ top: 50%;
+ margin-top: -5px;
+ right: 0;
+ width: 6px;
+ height: 11px;
+ background-position: top right;
+}
+/* @noflip */ .tipsy-w .tipsy-arrow {
+ top: 50%;
+ margin-top: -5px;
+ left: 0;
+ width: 6px;
+ height: 11px;
+}
diff --git a/www/wiki/resources/src/jquery.tipsy/jquery.tipsy.js b/www/wiki/resources/src/jquery.tipsy/jquery.tipsy.js
new file mode 100644
index 00000000..ddda432f
--- /dev/null
+++ b/www/wiki/resources/src/jquery.tipsy/jquery.tipsy.js
@@ -0,0 +1,281 @@
+// tipsy, facebook style tooltips for jquery
+// version 1.0.0a*
+// (c) 2008-2010 jason frame [jason@onehackoranother.com]
+// released under the MIT license
+
+// * This installation of tipsy includes several local modifications to both Javascript and CSS.
+// Please be careful when upgrading.
+
+( function ( mw, $ ) {
+
+ function maybeCall(thing, ctx) {
+ return (typeof thing == 'function') ? (thing.call(ctx)) : thing;
+ }
+
+ function Tipsy(element, options) {
+ this.$element = $(element);
+ this.options = options;
+ this.enabled = true;
+ this.keyHandler = $.proxy( this.closeOnEsc, this );
+ this.fixTitle();
+ }
+
+ Tipsy.prototype = {
+ show: function() {
+ var title = this.getTitle();
+ if (title && this.enabled) {
+ var $tip = this.tip();
+
+ $tip.find('.tipsy-inner')[this.options.html ? 'html' : 'text'](title);
+ $tip[0].className = 'tipsy'; // reset classname in case of dynamic gravity
+ if (this.options.className) {
+ $tip.addClass(maybeCall(this.options.className, this.$element[0]));
+ }
+ $tip.remove()
+ .css({top: 0, left: 0, visibility: 'hidden', display: 'block'})
+ .attr( 'aria-hidden', 'true' )
+ .appendTo(document.body);
+
+ var pos = $.extend({}, this.$element.offset(), {
+ width: this.$element[0].offsetWidth,
+ height: this.$element[0].offsetHeight
+ });
+
+ var gravity = (typeof this.options.gravity == 'function')
+ ? this.options.gravity.call(this.$element[0])
+ : this.options.gravity;
+
+ // Attach css classes before checking height/width so they
+ // can be applied.
+ $tip.addClass('tipsy-' + gravity);
+ if (this.options.className) {
+ $tip.addClass(maybeCall(this.options.className, this.$element[0]));
+ }
+
+ var actualWidth = $tip[0].offsetWidth, actualHeight = $tip[0].offsetHeight;
+ var tp;
+ switch (gravity.charAt(0)) {
+ case 'n':
+ tp = {top: pos.top + pos.height + this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
+ break;
+ case 's':
+ tp = {top: pos.top - actualHeight - this.options.offset, left: pos.left + pos.width / 2 - actualWidth / 2};
+ break;
+ case 'e':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth - this.options.offset};
+ break;
+ case 'w':
+ tp = {top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width + this.options.offset};
+ break;
+ }
+
+ if (gravity.length == 2) {
+ if (gravity.charAt(1) == 'w') {
+ if (this.options.center) {
+ tp.left = pos.left + pos.width / 2 - 15;
+ } else {
+ tp.left = pos.left;
+ }
+ } else {
+ if (this.options.center) {
+ tp.left = pos.left + pos.width / 2 - actualWidth + 15;
+ } else {
+ tp.left = pos.left + pos.width;
+ }
+ }
+ }
+ $tip.css(tp);
+
+ $( document ).on( 'keydown', this.keyHandler );
+ if (this.options.fade) {
+ $tip.stop()
+ .css({opacity: 0, display: 'block', visibility: 'visible'})
+ .attr( 'aria-hidden', 'false' )
+ .animate({opacity: this.options.opacity}, 100);
+ } else {
+ $tip
+ .css({visibility: 'visible', opacity: this.options.opacity})
+ .attr( 'aria-hidden', 'false' );
+ }
+ }
+ },
+
+ hide: function() {
+ $( document ).off( 'keydown', this.keyHandler );
+ if (this.options.fade) {
+ this.tip().stop().fadeOut(100, function() { $(this).remove(); });
+ } else {
+ this.tip().remove();
+ }
+ },
+
+ fixTitle: function() {
+ var $e = this.$element;
+ if ($e.attr('title') || typeof($e.attr('original-title')) != 'string') {
+ $e.attr('original-title', $e.attr('title') || '').removeAttr('title');
+ }
+ },
+
+ getTitle: function() {
+ var title, $e = this.$element, o = this.options;
+ this.fixTitle();
+ if (typeof o.title == 'string') {
+ title = $e.attr(o.title == 'title' ? 'original-title' : o.title);
+ } else if (typeof o.title == 'function') {
+ title = o.title.call($e[0]);
+ }
+ title = ('' + title).replace(/(^\s*|\s*$)/, "");
+ return title || o.fallback;
+ },
+
+ tip: function() {
+ if (!this.$tip) {
+ this.$tip = $('<div class="tipsy" role="tooltip"></div>').html('<div class="tipsy-arrow"></div><div class="tipsy-inner"></div>');
+ }
+ return this.$tip;
+ },
+
+ validate: function() {
+ if (!this.$element[0].parentNode) {
+ this.hide();
+ this.$element = null;
+ this.options = null;
+ }
+ },
+
+ // $.proxy event handler
+ closeOnEsc: function ( e ) {
+ if ( e.keyCode === 27 ) {
+ this.hide();
+ }
+ },
+
+ enable: function() { this.enabled = true; },
+ disable: function() { this.enabled = false; },
+ toggleEnabled: function() { this.enabled = !this.enabled; }
+ };
+
+ $.fn.tipsy = function(options) {
+
+ if (options === true) {
+ return this.data('tipsy');
+ } else if (typeof options == 'string') {
+ var tipsy = this.data('tipsy');
+ if (tipsy) tipsy[options]();
+ return this;
+ }
+
+ options = $.extend({}, $.fn.tipsy.defaults, options);
+
+ function get(ele) {
+ var tipsy = $.data(ele, 'tipsy');
+ if (!tipsy) {
+ tipsy = new Tipsy(ele, $.fn.tipsy.elementOptions(ele, options));
+ $.data(ele, 'tipsy', tipsy);
+ }
+ return tipsy;
+ }
+
+ function enter() {
+ var tipsy = get(this);
+ tipsy.hoverState = 'in';
+ if (options.delayIn == 0) {
+ tipsy.show();
+ } else {
+ tipsy.fixTitle();
+ setTimeout(function() { if (tipsy.hoverState == 'in') tipsy.show(); }, options.delayIn);
+ }
+ };
+
+ function leave() {
+ var tipsy = get(this);
+ tipsy.hoverState = 'out';
+ if (options.delayOut == 0) {
+ tipsy.hide();
+ } else {
+ setTimeout(function() { if (tipsy.hoverState == 'out') tipsy.hide(); }, options.delayOut);
+ }
+ };
+
+ this.each(function() { get(this); });
+
+ if ( options.trigger != 'manual' ) {
+ var eventIn = options.trigger == 'hover' ? 'mouseenter focus' : 'focus',
+ eventOut = options.trigger == 'hover' ? 'mouseleave blur' : 'blur';
+ if ( options.live ) {
+ mw.track( 'mw.deprecate', 'tipsy-live' );
+ mw.log.warn( 'Use of the "live" option of jquery.tipsy is no longer supported.' );
+ }
+ this
+ .on( eventIn, enter )
+ .on( eventOut, leave );
+ }
+
+ return this;
+
+ };
+
+ $.fn.tipsy.defaults = {
+ className: null,
+ delayIn: 0,
+ delayOut: 0,
+ fade: true,
+ fallback: '',
+ gravity: 'n',
+ center: true,
+ html: false,
+ live: false,
+ offset: 0,
+ opacity: 1.0,
+ title: 'title',
+ trigger: 'hover'
+ };
+
+ // Overwrite this method to provide options on a per-element basis.
+ // For example, you could store the gravity in a 'tipsy-gravity' attribute:
+ // return $.extend({}, options, {gravity: $(ele).attr('tipsy-gravity') || 'n' });
+ // (remember - do not modify 'options' in place!)
+ $.fn.tipsy.elementOptions = function(ele, options) {
+ return $.metadata ? $.extend({}, options, $(ele).metadata()) : options;
+ };
+
+ $.fn.tipsy.autoNS = function() {
+ return $(this).offset().top > ($(document).scrollTop() + $(window).height() / 2) ? 's' : 'n';
+ };
+
+ $.fn.tipsy.autoWE = function() {
+ return $(this).offset().left > ($(document).scrollLeft() + $(window).width() / 2) ? 'e' : 'w';
+ };
+
+ /**
+ * yields a closure of the supplied parameters, producing a function that takes
+ * no arguments and is suitable for use as an autogravity function like so:
+ *
+ * @param margin (int) - distance from the viewable region edge that an
+ * element should be before setting its tooltip's gravity to be away
+ * from that edge.
+ * @param prefer (string, e.g. 'n', 'sw', 'w') - the direction to prefer
+ * if there are no viewable region edges effecting the tooltip's
+ * gravity. It will try to vary from this minimally, for example,
+ * if 'sw' is preferred and an element is near the right viewable
+ * region edge, but not the top edge, it will set the gravity for
+ * that element's tooltip to be 'se', preserving the southern
+ * component.
+ */
+ $.fn.tipsy.autoBounds = function(margin, prefer) {
+ return function() {
+ var dir = {ns: prefer[0], ew: (prefer.length > 1 ? prefer[1] : false)},
+ boundTop = $(document).scrollTop() + margin,
+ boundLeft = $(document).scrollLeft() + margin,
+ $this = $(this);
+
+ if ($this.offset().top < boundTop) dir.ns = 'n';
+ if ($this.offset().left < boundLeft) dir.ew = 'w';
+ if ($(window).width() + $(document).scrollLeft() - $this.offset().left < margin) dir.ew = 'e';
+ if ($(window).height() + $(document).scrollTop() - $this.offset().top < margin) dir.ns = 's';
+
+ return dir.ns + (dir.ew ? dir.ew : '');
+ }
+ };
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/jquery/images/jquery.arrowSteps.divider-ltr.png b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.divider-ltr.png
new file mode 100644
index 00000000..84ed2a2d
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.divider-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/jquery.arrowSteps.divider-rtl.png b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.divider-rtl.png
new file mode 100644
index 00000000..c212aeb7
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.divider-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/jquery.arrowSteps.head-ltr.png b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.head-ltr.png
new file mode 100644
index 00000000..e6546bfd
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.head-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/jquery.arrowSteps.head-rtl.png b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.head-rtl.png
new file mode 100644
index 00000000..2af30b96
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.head-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/jquery.arrowSteps.tail-ltr.png b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.tail-ltr.png
new file mode 100644
index 00000000..3ad990b6
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.tail-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/jquery.arrowSteps.tail-rtl.png b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.tail-rtl.png
new file mode 100644
index 00000000..1d3048ef
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/jquery.arrowSteps.tail-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/marker.png b/www/wiki/resources/src/jquery/images/marker.png
new file mode 100644
index 00000000..915b347d
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/marker.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/mask.png b/www/wiki/resources/src/jquery/images/mask.png
new file mode 100644
index 00000000..c9606b09
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/mask.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/sort_both.png b/www/wiki/resources/src/jquery/images/sort_both.png
new file mode 100644
index 00000000..fc630913
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/sort_both.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/sort_both.svg b/www/wiki/resources/src/jquery/images/sort_both.svg
new file mode 100644
index 00000000..f906b932
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/sort_both.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 9" height="9" width="21">
+ <path d="M14.5 5l-4 4-4-4zM14.5 4l-4-4-4 4z"/>
+</svg>
diff --git a/www/wiki/resources/src/jquery/images/sort_down.png b/www/wiki/resources/src/jquery/images/sort_down.png
new file mode 100644
index 00000000..ce04a0fc
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/sort_down.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/sort_down.svg b/www/wiki/resources/src/jquery/images/sort_down.svg
new file mode 100644
index 00000000..105574bc
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/sort_down.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 4" height="4" width="21">
+ <path d="M14.5 0l-4 4-4-4z"/>
+</svg>
diff --git a/www/wiki/resources/src/jquery/images/sort_up.png b/www/wiki/resources/src/jquery/images/sort_up.png
new file mode 100644
index 00000000..2ebe0713
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/sort_up.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/sort_up.svg b/www/wiki/resources/src/jquery/images/sort_up.svg
new file mode 100644
index 00000000..2fa4c731
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/sort_up.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 21 4" height="4" width="21">
+ <path d="M6.5 4l4-4 4 4z"/>
+</svg>
diff --git a/www/wiki/resources/src/jquery/images/spinner-large.gif b/www/wiki/resources/src/jquery/images/spinner-large.gif
new file mode 100644
index 00000000..72203fdd
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/spinner-large.gif
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/spinner.gif b/www/wiki/resources/src/jquery/images/spinner.gif
new file mode 100644
index 00000000..6146be4e
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/spinner.gif
Binary files differ
diff --git a/www/wiki/resources/src/jquery/images/wheel.png b/www/wiki/resources/src/jquery/images/wheel.png
new file mode 100644
index 00000000..d930224c
--- /dev/null
+++ b/www/wiki/resources/src/jquery/images/wheel.png
Binary files differ
diff --git a/www/wiki/resources/src/jquery/jquery.accessKeyLabel.js b/www/wiki/resources/src/jquery/jquery.accessKeyLabel.js
new file mode 100644
index 00000000..4f900a4d
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.accessKeyLabel.js
@@ -0,0 +1,238 @@
+/**
+ * jQuery plugin to update the tooltip to show the correct access key
+ *
+ * @class jQuery.plugin.accessKeyLabel
+ */
+( function ( $, mw ) {
+
+ // Cached access key modifiers for used browser
+ var cachedAccessKeyModifiers,
+
+ // Whether to use 'test-' instead of correct prefix (used for testing)
+ useTestPrefix = false,
+
+ // tag names which can have a label tag
+ // https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Form-associated_content
+ labelable = 'button, input, textarea, keygen, meter, output, progress, select';
+
+ /**
+ * Find the modifier keys that need to be pressed together with the accesskey to trigger the input.
+ *
+ * The result is dependant on the ua paramater or the current platform.
+ * For browsers that support accessKeyLabel, #getAccessKeyLabel never calls here.
+ * Valid key values that are returned can be: ctrl, alt, option, shift, esc
+ *
+ * @private
+ * @param {Object} [ua] An object with a 'userAgent' and 'platform' property.
+ * @return {Array} Array with 1 or more of the string values, in this order: ctrl, option, alt, shift, esc
+ */
+ function getAccessKeyModifiers( ua ) {
+ var profile, accessKeyModifiers;
+
+ // use cached prefix if possible
+ if ( !ua && cachedAccessKeyModifiers ) {
+ return cachedAccessKeyModifiers;
+ }
+
+ profile = $.client.profile( ua );
+
+ switch ( profile.name ) {
+ case 'chrome':
+ case 'opera':
+ if ( profile.name === 'opera' && profile.versionNumber < 15 ) {
+ accessKeyModifiers = [ 'shift', 'esc' ];
+ } else if ( profile.platform === 'mac' ) {
+ accessKeyModifiers = [ 'ctrl', 'option' ];
+ } else {
+ // Chrome/Opera on Windows or Linux
+ // (both alt- and alt-shift work, but alt with E, D, F etc does not
+ // work since they are browser shortcuts)
+ accessKeyModifiers = [ 'alt', 'shift' ];
+ }
+ break;
+ case 'firefox':
+ case 'iceweasel':
+ if ( profile.versionBase < 2 ) {
+ // Before v2, Firefox used alt, though it was rebindable in about:config
+ accessKeyModifiers = [ 'alt' ];
+ } else {
+ if ( profile.platform === 'mac' ) {
+ if ( profile.versionNumber < 14 ) {
+ accessKeyModifiers = [ 'ctrl' ];
+ } else {
+ accessKeyModifiers = [ 'ctrl', 'option' ];
+ }
+ } else {
+ accessKeyModifiers = [ 'alt', 'shift' ];
+ }
+ }
+ break;
+ case 'safari':
+ case 'konqueror':
+ if ( profile.platform === 'win' ) {
+ accessKeyModifiers = [ 'alt' ];
+ } else {
+ if ( profile.layoutVersion > 526 ) {
+ // Non-Windows Safari with webkit_version > 526
+ accessKeyModifiers = [ 'ctrl', profile.platform === 'mac' ? 'option' : 'alt' ];
+ } else {
+ accessKeyModifiers = [ 'ctrl' ];
+ }
+ }
+ break;
+ case 'msie':
+ case 'edge':
+ accessKeyModifiers = [ 'alt' ];
+ break;
+ default:
+ accessKeyModifiers = profile.platform === 'mac' ? [ 'ctrl' ] : [ 'alt' ];
+ break;
+ }
+
+ // cache modifiers
+ if ( !ua ) {
+ cachedAccessKeyModifiers = accessKeyModifiers;
+ }
+ return accessKeyModifiers;
+ }
+
+ /**
+ * Get the access key label for an element.
+ *
+ * Will use native accessKeyLabel if available (currently only in Firefox 8+),
+ * falls back to #getAccessKeyModifiers.
+ *
+ * @private
+ * @param {HTMLElement} element Element to get the label for
+ * @return {string} Access key label
+ */
+ function getAccessKeyLabel( element ) {
+ // abort early if no access key
+ if ( !element.accessKey ) {
+ return '';
+ }
+ // use accessKeyLabel if possible
+ // https://html.spec.whatwg.org/multipage/interaction.html#dom-accesskeylabel
+ if ( !useTestPrefix && element.accessKeyLabel ) {
+ return element.accessKeyLabel;
+ }
+ return ( useTestPrefix ? 'test' : getAccessKeyModifiers().join( '-' ) ) + '-' + element.accessKey;
+ }
+
+ /**
+ * Update the title for an element (on the element with the access key or it's label) to show
+ * the correct access key label.
+ *
+ * @private
+ * @param {HTMLElement} element Element with the accesskey
+ * @param {HTMLElement} titleElement Element with the title to update (may be the same as `element`)
+ */
+ function updateTooltipOnElement( element, titleElement ) {
+ var oldTitle, parts, regexp, newTitle, accessKeyLabel;
+
+ oldTitle = titleElement.title;
+ if ( !oldTitle ) {
+ // don't add a title if the element didn't have one before
+ return;
+ }
+
+ parts = ( mw.msg( 'word-separator' ) + mw.msg( 'brackets' ) ).split( '$1' );
+ regexp = new RegExp( $.map( parts, mw.RegExp.escape ).join( '.*?' ) + '$' );
+ newTitle = oldTitle.replace( regexp, '' );
+ accessKeyLabel = getAccessKeyLabel( element );
+
+ if ( accessKeyLabel ) {
+ // Should be build the same as in Linker::titleAttrib
+ newTitle += mw.msg( 'word-separator' ) + mw.msg( 'brackets', accessKeyLabel );
+ }
+ if ( oldTitle !== newTitle ) {
+ titleElement.title = newTitle;
+ }
+ }
+
+ /**
+ * Update the title for an element to show the correct access key label.
+ *
+ * @private
+ * @param {HTMLElement} element Element with the accesskey
+ */
+ function updateTooltip( element ) {
+ var id, $element, $label, $labelParent;
+ updateTooltipOnElement( element, element );
+
+ // update associated label if there is one
+ $element = $( element );
+ if ( $element.is( labelable ) ) {
+ // Search it using 'for' attribute
+ id = element.id.replace( /"/g, '\\"' );
+ if ( id ) {
+ $label = $( 'label[for="' + id + '"]' );
+ if ( $label.length === 1 ) {
+ updateTooltipOnElement( element, $label[ 0 ] );
+ }
+ }
+
+ // Search it as parent, because the form control can also be inside the label element itself
+ $labelParent = $element.parents( 'label' );
+ if ( $labelParent.length === 1 ) {
+ updateTooltipOnElement( element, $labelParent[ 0 ] );
+ }
+ }
+ }
+
+ /**
+ * Update the titles for all elements in a jQuery selection.
+ *
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.updateTooltipAccessKeys = function () {
+ return this.each( function () {
+ updateTooltip( this );
+ } );
+ };
+
+ /**
+ * getAccessKeyModifiers
+ *
+ * @method updateTooltipAccessKeys_getAccessKeyModifiers
+ * @inheritdoc #getAccessKeyModifiers
+ */
+ $.fn.updateTooltipAccessKeys.getAccessKeyModifiers = getAccessKeyModifiers;
+
+ /**
+ * getAccessKeyLabel
+ *
+ * @method updateTooltipAccessKeys_getAccessKeyLabel
+ * @inheritdoc #getAccessKeyLabel
+ */
+ $.fn.updateTooltipAccessKeys.getAccessKeyLabel = getAccessKeyLabel;
+
+ /**
+ * getAccessKeyPrefix
+ *
+ * @method updateTooltipAccessKeys_getAccessKeyPrefix
+ * @deprecated since 1.27 Use #getAccessKeyModifiers
+ * @param {Object} [ua] An object with a 'userAgent' and 'platform' property.
+ * @return {string}
+ */
+ $.fn.updateTooltipAccessKeys.getAccessKeyPrefix = function ( ua ) {
+ return getAccessKeyModifiers( ua ).join( '-' ) + '-';
+ };
+
+ /**
+ * Switch test mode on and off.
+ *
+ * @method updateTooltipAccessKeys_setTestMode
+ * @param {boolean} mode New mode
+ */
+ $.fn.updateTooltipAccessKeys.setTestMode = function ( mode ) {
+ useTestPrefix = mode;
+ };
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.accessKeyLabel
+ */
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/jquery/jquery.arrowSteps.css b/www/wiki/resources/src/jquery/jquery.arrowSteps.css
new file mode 100644
index 00000000..f8f6e951
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.arrowSteps.css
@@ -0,0 +1,45 @@
+.arrowSteps {
+ list-style-type: none;
+ list-style-image: none;
+ border: 1px solid #666666;
+ position: relative;
+}
+
+.arrowSteps li {
+ float: left;
+ padding: 0px;
+ margin: 0px;
+ border: 0 none;
+}
+
+.arrowSteps li div {
+ padding: 0.5em;
+ text-align: center;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+.arrowSteps li.arrow div {
+ /* @embed */
+ background: url(images/jquery.arrowSteps.divider-ltr.png) no-repeat right center;
+}
+
+/* applied to the element preceding the highlighted step */
+.arrowSteps li.arrow.tail div {
+ /* @embed */
+ background: url(images/jquery.arrowSteps.tail-ltr.png) no-repeat right center;
+}
+
+/* this applies to all highlighted, including the last */
+.arrowSteps li.head div {
+ /* @embed */
+ background: url(images/jquery.arrowSteps.head-ltr.png) no-repeat left center;
+ font-weight: bold;
+}
+
+/* this applies to all highlighted arrows except the last */
+.arrowSteps li.arrow.head div {
+ /* TODO: eliminate duplication of jquery.arrowSteps.head.png embedding */
+ /* @embed */
+ background: url(images/jquery.arrowSteps.head-ltr.png) no-repeat right center;
+}
diff --git a/www/wiki/resources/src/jquery/jquery.arrowSteps.js b/www/wiki/resources/src/jquery/jquery.arrowSteps.js
new file mode 100644
index 00000000..b0c36c65
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.arrowSteps.js
@@ -0,0 +1,98 @@
+/*!
+ * jQuery arrowSteps plugin
+ * Copyright Neil Kandalgaonkar, 2010
+ *
+ * This work is licensed under the terms of the GNU General Public License,
+ * version 2 or later.
+ * (see http://www.fsf.org/licensing/licenses/gpl.html).
+ * Derivative works and later versions of the code must be free software
+ * licensed under the same or a compatible license.
+ */
+
+/**
+ * @class jQuery.plugin.arrowSteps
+ */
+( function ( $ ) {
+ /**
+ * Show users their progress through a series of steps, via a row of items that fit
+ * together like arrows. One item can be highlighted at a time.
+ *
+ * <ul id="robin-hood-daffy">
+ * <li id="guard"><div>Guard!</div></li>
+ * <li id="turn"><div>Turn!</div></li>
+ * <li id="parry"><div>Parry!</div></li>
+ * <li id="dodge"><div>Dodge!</div></li>
+ * <li id="spin"><div>Spin!</div></li>
+ * <li id="ha"><div>Ha!</div></li>
+ * <li id="thrust"><div>Thrust!</div></li>
+ * </ul>
+ *
+ * <script>
+ * $( '#robin-hood-daffy' ).arrowSteps();
+ * </script>
+ *
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.arrowSteps = function () {
+ var $steps, width, arrowWidth, $stepDiv,
+ $el = this,
+ paddingSide = $( 'body' ).hasClass( 'rtl' ) ? 'padding-left' : 'padding-right';
+
+ $el.addClass( 'arrowSteps' );
+ $steps = $el.find( 'li' );
+
+ width = parseInt( 100 / $steps.length, 10 );
+ $steps.css( 'width', width + '%' );
+
+ // Every step except the last one has an arrow pointing forward:
+ // at the right hand side in LTR languages, and at the left hand side in RTL.
+ // Also add in the padding for the calculated arrow width.
+ $stepDiv = $steps.filter( ':not(:last-child)' ).addClass( 'arrow' ).find( 'div' );
+
+ // Execute when complete page is fully loaded, including all frames, objects and images
+ $( window ).on( 'load', function () {
+ arrowWidth = parseInt( $el.outerHeight(), 10 );
+ $stepDiv.css( paddingSide, arrowWidth.toString() + 'px' );
+ } );
+
+ $el.data( 'arrowSteps', $steps );
+
+ return this;
+ };
+
+ /**
+ * Highlights the element selected by the selector.
+ *
+ * $( '#robin-hood-daffy' ).arrowStepsHighlight( '#guard' );
+ * // 'Guard!' is highlighted.
+ *
+ * // ... user completes the 'guard' step ...
+ *
+ * $( '#robin-hood-daffy' ).arrowStepsHighlight( '#turn' );
+ * // 'Turn!' is highlighted.
+ *
+ * @param {string} selector
+ */
+ $.fn.arrowStepsHighlight = function ( selector ) {
+ var $previous,
+ $steps = this.data( 'arrowSteps' );
+ $.each( $steps, function ( i, step ) {
+ var $step = $( step );
+ if ( $step.is( selector ) ) {
+ if ( $previous ) {
+ $previous.addClass( 'tail' );
+ }
+ $step.addClass( 'head' );
+ } else {
+ $step.removeClass( 'head tail lasthead' );
+ }
+ $previous = $step;
+ } );
+ };
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.arrowSteps
+ */
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.autoEllipsis.js b/www/wiki/resources/src/jquery/jquery.autoEllipsis.js
new file mode 100644
index 00000000..8716b694
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.autoEllipsis.js
@@ -0,0 +1,171 @@
+/**
+ * @class jQuery.plugin.autoEllipsis
+ */
+( function ( $ ) {
+
+ var
+ // Cache ellipsed substrings for every string-width-position combination
+ cache = {},
+
+ // Use a separate cache when match highlighting is enabled
+ matchTextCache = {};
+
+ // Due to <https://github.com/jscs-dev/jscs-jsdoc/issues/136>
+ // jscs:disable jsDoc
+ /**
+ * Automatically truncate the plain text contents of an element and add an ellipsis
+ *
+ * @param {Object} options
+ * @param {'left'|'center'|'right'} [options.position='center'] Where to remove text.
+ * @param {boolean} [options.tooltip=false] Whether to show a tooltip with the remainder
+ * of the text.
+ * @param {boolean} [options.restoreText=false] Whether to save the text for restoring
+ * later.
+ * @param {boolean} [options.hasSpan=false] Whether the element is already a container,
+ * or if the library should create a new container for it.
+ * @param {string|null} [options.matchText=null] Text to highlight, e.g. search terms.
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.autoEllipsis = function ( options ) {
+ options = $.extend( {
+ position: 'center',
+ tooltip: false,
+ restoreText: false,
+ hasSpan: false,
+ matchText: null
+ }, options );
+
+ return this.each( function () {
+ var $trimmableText,
+ text, trimmableText, w, pw,
+ l, r, i, side, m,
+ // container element - used for measuring against
+ $container = $( this );
+
+ if ( options.restoreText ) {
+ if ( !$container.data( 'autoEllipsis.originalText' ) ) {
+ $container.data( 'autoEllipsis.originalText', $container.text() );
+ } else {
+ $container.text( $container.data( 'autoEllipsis.originalText' ) );
+ }
+ }
+
+ // trimmable text element - only the text within this element will be trimmed
+ if ( options.hasSpan ) {
+ $trimmableText = $container.children( options.selector );
+ } else {
+ $trimmableText = $( '<span>' )
+ .css( 'whiteSpace', 'nowrap' )
+ .text( $container.text() );
+ $container
+ .empty()
+ .append( $trimmableText );
+ }
+
+ text = $container.text();
+ trimmableText = $trimmableText.text();
+ w = $container.width();
+ pw = 0;
+
+ // Try cache
+ if ( options.matchText ) {
+ if ( !( text in matchTextCache ) ) {
+ matchTextCache[ text ] = {};
+ }
+ if ( !( options.matchText in matchTextCache[ text ] ) ) {
+ matchTextCache[ text ][ options.matchText ] = {};
+ }
+ if ( !( w in matchTextCache[ text ][ options.matchText ] ) ) {
+ matchTextCache[ text ][ options.matchText ][ w ] = {};
+ }
+ if ( options.position in matchTextCache[ text ][ options.matchText ][ w ] ) {
+ $container.html( matchTextCache[ text ][ options.matchText ][ w ][ options.position ] );
+ if ( options.tooltip ) {
+ $container.attr( 'title', text );
+ }
+ return;
+ }
+ } else {
+ if ( !( text in cache ) ) {
+ cache[ text ] = {};
+ }
+ if ( !( w in cache[ text ] ) ) {
+ cache[ text ][ w ] = {};
+ }
+ if ( options.position in cache[ text ][ w ] ) {
+ $container.html( cache[ text ][ w ][ options.position ] );
+ if ( options.tooltip ) {
+ $container.attr( 'title', text );
+ }
+ return;
+ }
+ }
+
+ if ( $trimmableText.width() + pw > w ) {
+ switch ( options.position ) {
+ case 'right':
+ // Use binary search-like technique for efficiency
+ l = 0;
+ r = trimmableText.length;
+ do {
+ m = Math.ceil( ( l + r ) / 2 );
+ $trimmableText.text( trimmableText.slice( 0, m ) + '...' );
+ if ( $trimmableText.width() + pw > w ) {
+ // Text is too long
+ r = m - 1;
+ } else {
+ l = m;
+ }
+ } while ( l < r );
+ $trimmableText.text( trimmableText.slice( 0, l ) + '...' );
+ break;
+ case 'center':
+ // TODO: Use binary search like for 'right'
+ i = [ Math.round( trimmableText.length / 2 ), Math.round( trimmableText.length / 2 ) ];
+ // Begin with making the end shorter
+ side = 1;
+ while ( $trimmableText.outerWidth() + pw > w && i[ 0 ] > 0 ) {
+ $trimmableText.text( trimmableText.slice( 0, i[ 0 ] ) + '...' + trimmableText.slice( i[ 1 ] ) );
+ // Alternate between trimming the end and begining
+ if ( side === 0 ) {
+ // Make the begining shorter
+ i[ 0 ]--;
+ side = 1;
+ } else {
+ // Make the end shorter
+ i[ 1 ]++;
+ side = 0;
+ }
+ }
+ break;
+ case 'left':
+ // TODO: Use binary search like for 'right'
+ r = 0;
+ while ( $trimmableText.outerWidth() + pw > w && r < trimmableText.length ) {
+ $trimmableText.text( '...' + trimmableText.slice( r ) );
+ r++;
+ }
+ break;
+ }
+ }
+ if ( options.tooltip ) {
+ $container.attr( 'title', text );
+ }
+ if ( options.matchText ) {
+ $container.highlightText( options.matchText );
+ matchTextCache[ text ][ options.matchText ][ w ][ options.position ] = $container.html();
+ } else {
+ cache[ text ][ w ][ options.position ] = $container.html();
+ }
+
+ } );
+ };
+ // jscs:enable jsDoc
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.autoEllipsis
+ */
+
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.badge.css b/www/wiki/resources/src/jquery/jquery.badge.css
new file mode 100644
index 00000000..2dbd4a5e
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.badge.css
@@ -0,0 +1,36 @@
+.mw-badge {
+ min-width: 7px;
+ border-radius: 2px;
+ padding: 1px 4px;
+ text-align: center;
+ font-size: 12px;
+ line-height: 12px;
+ background-color: #d2d2d2;
+ cursor: pointer;
+}
+
+.mw-badge-content {
+ font-weight: bold;
+ color: #fff;
+ vertical-align: baseline;
+ text-shadow: 0 1px rgba( 0, 0, 0, 0.4 );
+}
+
+.mw-badge-inline {
+ margin-left: 3px;
+ display: inline-block;
+ /* Hack for IE6 and IE7 (T49926) */
+ zoom: 1;
+ *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */
+
+}
+.mw-badge-overlay {
+ position: absolute;
+ bottom: -1px;
+ right: -3px;
+ z-index: 50;
+}
+
+.mw-badge-important {
+ background-color: #d33;
+}
diff --git a/www/wiki/resources/src/jquery/jquery.badge.js b/www/wiki/resources/src/jquery/jquery.badge.js
new file mode 100644
index 00000000..40b3baf0
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.badge.js
@@ -0,0 +1,88 @@
+/*!
+ * jQuery Badge plugin
+ *
+ * @license MIT
+ *
+ * @author Ryan Kaldari <rkaldari@wikimedia.org>, 2012
+ * @author Andrew Garrett <agarrett@wikimedia.org>, 2012
+ * @author Marius Hoch <hoo@online.de>, 2012
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * This program is distributed WITHOUT ANY WARRANTY.
+ */
+
+/**
+ * @class jQuery.plugin.badge
+ */
+( function ( $, mw ) {
+ /**
+ * Put a badge on an item on the page. The badge container will be appended to the selected element(s).
+ *
+ * $element.badge( text );
+ * $element.badge( 5 );
+ * $element.badge( '100+' );
+ * $element.badge( text, inline );
+ * $element.badge( 'New', true );
+ *
+ * @param {number|string} text The value to display in the badge. If the value is falsey (0,
+ * null, false, '', etc.), any existing badge will be removed.
+ * @param {boolean} [inline=true] True if the badge should be displayed inline, false
+ * if the badge should overlay the parent element.
+ * @param {boolean} [displayZero=false] True if the number zero should be displayed,
+ * false if the number zero should result in the badge being hidden
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.badge = function ( text, inline, displayZero ) {
+ var $badge = this.find( '.mw-badge' ),
+ badgeStyleClass = 'mw-badge-' + ( inline ? 'inline' : 'overlay' ),
+ isImportant = true,
+ displayBadge = true;
+
+ // If we're displaying zero, ensure style to be non-important
+ if ( mw.language.convertNumber( text, true ) === 0 ) {
+ isImportant = false;
+ if ( !displayZero ) {
+ displayBadge = false;
+ }
+ // If text is falsey (besides 0), hide the badge
+ } else if ( !text ) {
+ displayBadge = false;
+ }
+
+ if ( displayBadge ) {
+ // If a badge already exists, reuse it
+ if ( $badge.length ) {
+ $badge
+ .toggleClass( 'mw-badge-important', isImportant )
+ .find( '.mw-badge-content' ).text( text );
+ } else {
+ // Otherwise, create a new badge with the specified text and style
+ $badge = $( '<div class="mw-badge"></div>' )
+ .addClass( badgeStyleClass )
+ .toggleClass( 'mw-badge-important', isImportant )
+ .append(
+ $( '<span class="mw-badge-content"></span>' ).text( text )
+ )
+ .appendTo( this );
+ }
+ } else {
+ $badge.remove();
+ }
+ return this;
+ };
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.badge
+ */
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/jquery/jquery.byteLength.js b/www/wiki/resources/src/jquery/jquery.byteLength.js
new file mode 100644
index 00000000..222f14af
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.byteLength.js
@@ -0,0 +1,40 @@
+/**
+ * @class jQuery.plugin.byteLength
+ * @author Jan Paul Posma, 2011
+ * @author Timo Tijhof, 2012
+ * @author David Chan, 2013
+ */
+
+/**
+ * Calculate the byte length of a string (accounting for UTF-8).
+ *
+ * @static
+ * @inheritable
+ * @param {string} str
+ * @return {number}
+ */
+jQuery.byteLength = function ( str ) {
+ // This basically figures out how many bytes a UTF-16 string (which is what js sees)
+ // will take in UTF-8 by replacing a 2 byte character with 2 *'s, etc, and counting that.
+ // Note, surrogate (\uD800-\uDFFF) characters are counted as 2 bytes, since there's two of them
+ // and the actual character takes 4 bytes in UTF-8 (2*2=4). Might not work perfectly in
+ // edge cases such as illegal sequences, but that should never happen.
+
+ // https://en.wikipedia.org/wiki/UTF-8#Description
+ // The mapping from UTF-16 code units to UTF-8 bytes is as follows:
+ // > Range 0000-007F: codepoints that become 1 byte of UTF-8
+ // > Range 0080-07FF: codepoints that become 2 bytes of UTF-8
+ // > Range 0800-D7FF: codepoints that become 3 bytes of UTF-8
+ // > Range D800-DFFF: Surrogates (each pair becomes 4 bytes of UTF-8)
+ // > Range E000-FFFF: codepoints that become 3 bytes of UTF-8 (continued)
+
+ return str
+ .replace( /[\u0080-\u07FF\uD800-\uDFFF]/g, '**' )
+ .replace( /[\u0800-\uD7FF\uE000-\uFFFF]/g, '***' )
+ .length;
+};
+
+/**
+ * @class jQuery
+ * @mixins jQuery.plugin.byteLength
+ */
diff --git a/www/wiki/resources/src/jquery/jquery.byteLimit.js b/www/wiki/resources/src/jquery/jquery.byteLimit.js
new file mode 100644
index 00000000..c75246c0
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.byteLimit.js
@@ -0,0 +1,238 @@
+/**
+ * @class jQuery.plugin.byteLimit
+ */
+( function ( $ ) {
+
+ var eventKeys = [
+ 'keyup.byteLimit',
+ 'keydown.byteLimit',
+ 'change.byteLimit',
+ 'mouseup.byteLimit',
+ 'cut.byteLimit',
+ 'paste.byteLimit',
+ 'focus.byteLimit',
+ 'blur.byteLimit'
+ ].join( ' ' );
+
+ /**
+ * Utility function to trim down a string, based on byteLimit
+ * and given a safe start position. It supports insertion anywhere
+ * in the string, so "foo" to "fobaro" if limit is 4 will result in
+ * "fobo", not "foba". Basically emulating the native maxlength by
+ * reconstructing where the insertion occurred.
+ *
+ * @static
+ * @param {string} safeVal Known value that was previously returned by this
+ * function, if none, pass empty string.
+ * @param {string} newVal New value that may have to be trimmed down.
+ * @param {number} byteLimit Number of bytes the value may be in size.
+ * @param {Function} [fn] See jQuery#byteLimit.
+ * @return {Object}
+ * @return {string} return.newVal
+ * @return {boolean} return.trimmed
+ */
+ $.trimByteLength = function ( safeVal, newVal, byteLimit, fn ) {
+ var startMatches, endMatches, matchesLen, inpParts,
+ oldVal = safeVal;
+
+ // Run the hook if one was provided, but only on the length
+ // assessment. The value itself is not to be affected by the hook.
+ if ( $.byteLength( fn ? fn( newVal ) : newVal ) <= byteLimit ) {
+ // Limit was not reached, just remember the new value
+ // and let the user continue.
+ return {
+ newVal: newVal,
+ trimmed: false
+ };
+ }
+
+ // Current input is longer than the active limit.
+ // Figure out what was added and limit the addition.
+ startMatches = 0;
+ endMatches = 0;
+
+ // It is important that we keep the search within the range of
+ // the shortest string's length.
+ // Imagine a user adds text that matches the end of the old value
+ // (e.g. "foo" -> "foofoo"). startMatches would be 3, but without
+ // limiting both searches to the shortest length, endMatches would
+ // also be 3.
+ matchesLen = Math.min( newVal.length, oldVal.length );
+
+ // Count same characters from the left, first.
+ // (if "foo" -> "foofoo", assume addition was at the end).
+ while (
+ startMatches < matchesLen &&
+ oldVal.charAt( startMatches ) === newVal.charAt( startMatches )
+ ) {
+ startMatches += 1;
+ }
+
+ while (
+ endMatches < ( matchesLen - startMatches ) &&
+ oldVal.charAt( oldVal.length - 1 - endMatches ) === newVal.charAt( newVal.length - 1 - endMatches )
+ ) {
+ endMatches += 1;
+ }
+
+ inpParts = [
+ // Same start
+ newVal.slice( 0, startMatches ),
+ // Inserted content
+ newVal.slice( startMatches, newVal.length - endMatches ),
+ // Same end
+ newVal.slice( newVal.length - endMatches )
+ ];
+
+ // Chop off characters from the end of the "inserted content" string
+ // until the limit is statisfied.
+ if ( fn ) {
+ // stop, when there is nothing to slice - T43450
+ while ( $.byteLength( fn( inpParts.join( '' ) ) ) > byteLimit && inpParts[ 1 ].length > 0 ) {
+ inpParts[ 1 ] = inpParts[ 1 ].slice( 0, -1 );
+ }
+ } else {
+ while ( $.byteLength( inpParts.join( '' ) ) > byteLimit ) {
+ inpParts[ 1 ] = inpParts[ 1 ].slice( 0, -1 );
+ }
+ }
+
+ return {
+ newVal: inpParts.join( '' ),
+ // For pathological fn() that always returns a value longer than the limit, we might have
+ // ended up not trimming - check for this case to avoid infinite loops
+ trimmed: newVal !== inpParts.join( '' )
+ };
+ };
+
+ /**
+ * Enforces a byte limit on an input field, so that UTF-8 entries are counted as well,
+ * when, for example, a database field has a byte limit rather than a character limit.
+ * Plugin rationale: Browser has native maxlength for number of characters, this plugin
+ * exists to limit number of bytes instead.
+ *
+ * Can be called with a custom limit (to use that limit instead of the maxlength attribute
+ * value), a filter function (in case the limit should apply to something other than the
+ * exact input value), or both. Order of parameters is important!
+ *
+ * @param {number} [limit] Limit to enforce, fallsback to maxLength-attribute,
+ * called with fetched value as argument.
+ * @param {Function} [fn] Function to call on the string before assessing the length.
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.byteLimit = function ( limit, fn ) {
+ // If the first argument is the function,
+ // set fn to the first argument's value and ignore the second argument.
+ if ( $.isFunction( limit ) ) {
+ fn = limit;
+ limit = undefined;
+ // Either way, verify it is a function so we don't have to call
+ // isFunction again after this.
+ } else if ( !fn || !$.isFunction( fn ) ) {
+ fn = undefined;
+ }
+
+ // The following is specific to each element in the collection.
+ return this.each( function ( i, el ) {
+ var $el, elLimit, prevSafeVal;
+
+ $el = $( el );
+
+ // If no limit was passed to byteLimit(), use the maxlength value.
+ // Can't re-use 'limit' variable because it's in the higher scope
+ // that would affect the next each() iteration as well.
+ // Note that we use attribute to read the value instead of property,
+ // because in Chrome the maxLength property by default returns the
+ // highest supported value (no indication that it is being enforced
+ // by choice). We don't want to bind all of this for some ridiculously
+ // high default number, unless it was explicitly set in the HTML.
+ // Also cast to a (primitive) number (most commonly because the maxlength
+ // attribute contains a string, but theoretically the limit parameter
+ // could be something else as well).
+ elLimit = Number( limit === undefined ? $el.attr( 'maxlength' ) : limit );
+
+ // If there is no (valid) limit passed or found in the property,
+ // skip this. The < 0 check is required for Firefox, which returns
+ // -1 (instead of undefined) for maxLength if it is not set.
+ if ( !elLimit || elLimit < 0 ) {
+ return;
+ }
+
+ if ( fn ) {
+ // Save function for reference
+ $el.data( 'byteLimit.callback', fn );
+ }
+
+ // Remove old event handlers (if there are any)
+ $el.off( '.byteLimit' );
+
+ if ( fn ) {
+ // Disable the native maxLength (if there is any), because it interferes
+ // with the (differently calculated) byte limit.
+ // Aside from being differently calculated (average chars with byteLimit
+ // is lower), we also support a callback which can make it to allow longer
+ // values (e.g. count "Foo" from "User:Foo").
+ // maxLength is a strange property. Removing or setting the property to
+ // undefined directly doesn't work. Instead, it can only be unset internally
+ // by the browser when removing the associated attribute (Firefox/Chrome).
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=136004
+ $el.removeAttr( 'maxlength' );
+
+ } else {
+ // If we don't have a callback the bytelimit can only be lower than the charlimit
+ // (that is, there are no characters less than 1 byte in size). So lets (re-)enforce
+ // the native limit for efficiency when possible (it will make the while-loop below
+ // faster by there being less left to interate over).
+ $el.attr( 'maxlength', elLimit );
+ }
+
+ // Safe base value, used to determine the path between the previous state
+ // and the state that triggered the event handler below - and enforce the
+ // limit approppiately (e.g. don't chop from the end if text was inserted
+ // at the beginning of the string).
+ prevSafeVal = '';
+
+ // We need to listen to after the change has already happened because we've
+ // learned that trying to guess the new value and canceling the event
+ // accordingly doesn't work because the new value is not always as simple as:
+ // oldValue + String.fromCharCode( e.which ); because of cut, paste, select-drag
+ // replacements, and custom input methods and what not.
+ // Even though we only trim input after it was changed (never prevent it), we do
+ // listen on events that input text, because there are cases where the text has
+ // changed while text is being entered and keyup/change will not be fired yet
+ // (such as holding down a single key, fires keydown, and after each keydown,
+ // we can trim the previous one).
+ // See https://www.w3.org/TR/DOM-Level-3-Events/#events-keyboard-event-order for
+ // the order and characteristics of the key events.
+ $el.on( eventKeys, function () {
+ var res = $.trimByteLength(
+ prevSafeVal,
+ this.value,
+ elLimit,
+ fn
+ );
+
+ // Only set value property if it was trimmed, because whenever the
+ // value property is set, the browser needs to re-initiate the text context,
+ // which moves the cursor at the end the input, moving it away from wherever it was.
+ // This is a side-effect of limiting after the fact.
+ if ( res.trimmed === true ) {
+ this.value = res.newVal;
+ // Trigger a 'change' event to let other scripts attached to this node know that the value
+ // was changed. This will also call ourselves again, but that's okay, it'll be a no-op.
+ $el.trigger( 'change' );
+ }
+ // Always adjust prevSafeVal to reflect the input value. Not doing this could cause
+ // trimByteLength to compare the new value to an empty string instead of the
+ // old value, resulting in trimming always from the end (T42850).
+ prevSafeVal = res.newVal;
+ } );
+ } );
+ };
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.byteLimit
+ */
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.checkboxShiftClick.js b/www/wiki/resources/src/jquery/jquery.checkboxShiftClick.js
new file mode 100644
index 00000000..d99e9f0a
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.checkboxShiftClick.js
@@ -0,0 +1,43 @@
+/**
+ * @class jQuery.plugin.checkboxShiftClick
+ */
+( function ( $ ) {
+
+ /**
+ * Enable checkboxes to be checked or unchecked in a row by clicking one,
+ * holding shift and clicking another one.
+ *
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.checkboxShiftClick = function () {
+ var prevCheckbox = null,
+ $box = this;
+ // When our boxes are clicked..
+ $box.click( function ( e ) {
+ // And one has been clicked before...
+ if ( prevCheckbox !== null && e.shiftKey ) {
+ // Check or uncheck this one and all in-between checkboxes,
+ // except for disabled ones
+ $box
+ .slice(
+ Math.min( $box.index( prevCheckbox ), $box.index( e.target ) ),
+ Math.max( $box.index( prevCheckbox ), $box.index( e.target ) ) + 1
+ )
+ .filter( function () {
+ return !this.disabled;
+ } )
+ .prop( 'checked', !!e.target.checked );
+ }
+ // Either way, update the prevCheckbox variable to the one clicked now
+ prevCheckbox = e.target;
+ } );
+ return $box;
+ };
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.checkboxShiftClick
+ */
+
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.color.js b/www/wiki/resources/src/jquery/jquery.color.js
new file mode 100644
index 00000000..847afd4e
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.color.js
@@ -0,0 +1,55 @@
+/**
+ * jQuery Color Animations
+ *
+ * @author John Resig, 2007
+ * @author Krinkle, 2011
+ * Released under the MIT and GPL licenses.
+ *
+ * - 2011-01-05: Forked for MediaWiki. See also jQuery.colorUtil plugin
+ */
+( function ( $ ) {
+
+ function getColor( elem, attr ) {
+ var color;
+
+ do {
+ color = $.css( elem, attr );
+
+ // Keep going until we find an element that has color, or we hit the body
+ if ( color !== '' && color !== 'transparent' || elem.nodeName.toLowerCase() === 'body' ) {
+ break;
+ }
+
+ attr = 'backgroundColor';
+ // eslint-disable-next-line no-cond-assign
+ } while ( elem = elem.parentNode );
+
+ return $.colorUtil.getRGB( color );
+ }
+
+ // We override the animation for all of these color styles
+ $.each( [
+ 'backgroundColor',
+ 'borderBottomColor',
+ 'borderLeftColor',
+ 'borderRightColor',
+ 'borderTopColor',
+ 'color',
+ 'outlineColor'
+ ], function ( i, attr ) {
+ $.fx.step[ attr ] = function ( fx ) {
+ if ( !fx.colorInit ) {
+ fx.start = getColor( fx.elem, attr );
+ fx.end = $.colorUtil.getRGB( fx.end );
+ fx.colorInit = true;
+ }
+
+ fx.elem.style[ attr ] = 'rgb(' + [
+ Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 0 ] - fx.start[ 0 ] ) ) + fx.start[ 0 ], 10 ), 255 ), 0 ),
+ Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 1 ] - fx.start[ 1 ] ) ) + fx.start[ 1 ], 10 ), 255 ), 0 ),
+ Math.max( Math.min( parseInt( ( fx.pos * ( fx.end[ 2 ] - fx.start[ 2 ] ) ) + fx.start[ 2 ], 10 ), 255 ), 0 )
+ ].join( ',' ) + ')';
+ };
+ } );
+
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.colorUtil.js b/www/wiki/resources/src/jquery/jquery.colorUtil.js
new file mode 100644
index 00000000..a5b136d9
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.colorUtil.js
@@ -0,0 +1,265 @@
+/*!
+ * jQuery Color Utilities
+ *
+ * Released under the MIT and GPL licenses.
+ *
+ * Mostly based on other plugins and functions (linted and optimized a little).
+ * Sources cited inline.
+ */
+( function ( $ ) {
+ /**
+ * @class jQuery.colorUtil
+ * @singleton
+ */
+ $.colorUtil = {
+
+ /**
+ * Parse CSS color strings looking for color tuples
+ *
+ * Based on highlightFade by Blair Mitchelmore
+ * <http://jquery.offput.ca/highlightFade/>
+ *
+ * @param {Array|string} color
+ * @return {Array}
+ */
+ getRGB: function ( color ) {
+ var result;
+
+ // Check if we're already dealing with an array of colors
+ if ( color && Array.isArray( color ) && color.length === 3 ) {
+ return color;
+ }
+
+ // Look for rgb(num,num,num)
+ // eslint-disable-next-line no-cond-assign
+ if ( result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec( color ) ) {
+ return [
+ parseInt( result[ 1 ], 10 ),
+ parseInt( result[ 2 ], 10 ),
+ parseInt( result[ 3 ], 10 )
+ ];
+ }
+
+ // Look for rgb(num%,num%,num%)
+ // eslint-disable-next-line no-cond-assign
+ if ( result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*,\s*([0-9]+(?:\.[0-9]+)?)%\s*\)/.exec( color ) ) {
+ return [
+ parseFloat( result[ 1 ] ) * 2.55,
+ parseFloat( result[ 2 ] ) * 2.55,
+ parseFloat( result[ 3 ] ) * 2.55
+ ];
+ }
+
+ // Look for #a0b1c2
+ // eslint-disable-next-line no-cond-assign
+ if ( result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec( color ) ) {
+ return [
+ parseInt( result[ 1 ], 16 ),
+ parseInt( result[ 2 ], 16 ),
+ parseInt( result[ 3 ], 16 )
+ ];
+ }
+
+ // Look for #fff
+ // eslint-disable-next-line no-cond-assign
+ if ( result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec( color ) ) {
+ return [
+ parseInt( result[ 1 ] + result[ 1 ], 16 ),
+ parseInt( result[ 2 ] + result[ 2 ], 16 ),
+ parseInt( result[ 3 ] + result[ 3 ], 16 )
+ ];
+ }
+
+ // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
+ // eslint-disable-next-line no-cond-assign
+ if ( result = /rgba\(0, 0, 0, 0\)/.exec( color ) ) {
+ return $.colorUtil.colors.transparent;
+ }
+
+ // Otherwise, we're most likely dealing with a named color
+ return $.colorUtil.colors[ $.trim( color ).toLowerCase() ];
+ },
+
+ /**
+ * Named color map
+ *
+ * Based on Interface by Stefan Petre
+ * <http://interface.eyecon.ro/>
+ *
+ * @property {Object}
+ */
+ colors: {
+ aqua: [ 0, 255, 255 ],
+ azure: [ 240, 255, 255 ],
+ beige: [ 245, 245, 220 ],
+ black: [ 0, 0, 0 ],
+ blue: [ 0, 0, 255 ],
+ brown: [ 165, 42, 42 ],
+ cyan: [ 0, 255, 255 ],
+ darkblue: [ 0, 0, 139 ],
+ darkcyan: [ 0, 139, 139 ],
+ darkgrey: [ 169, 169, 169 ],
+ darkgreen: [ 0, 100, 0 ],
+ darkkhaki: [ 189, 183, 107 ],
+ darkmagenta: [ 139, 0, 139 ],
+ darkolivegreen: [ 85, 107, 47 ],
+ darkorange: [ 255, 140, 0 ],
+ darkorchid: [ 153, 50, 204 ],
+ darkred: [ 139, 0, 0 ],
+ darksalmon: [ 233, 150, 122 ],
+ darkviolet: [ 148, 0, 211 ],
+ fuchsia: [ 255, 0, 255 ],
+ gold: [ 255, 215, 0 ],
+ green: [ 0, 128, 0 ],
+ indigo: [ 75, 0, 130 ],
+ khaki: [ 240, 230, 140 ],
+ lightblue: [ 173, 216, 230 ],
+ lightcyan: [ 224, 255, 255 ],
+ lightgreen: [ 144, 238, 144 ],
+ lightgrey: [ 211, 211, 211 ],
+ lightpink: [ 255, 182, 193 ],
+ lightyellow: [ 255, 255, 224 ],
+ lime: [ 0, 255, 0 ],
+ magenta: [ 255, 0, 255 ],
+ maroon: [ 128, 0, 0 ],
+ navy: [ 0, 0, 128 ],
+ olive: [ 128, 128, 0 ],
+ orange: [ 255, 165, 0 ],
+ pink: [ 255, 192, 203 ],
+ purple: [ 128, 0, 128 ],
+ violet: [ 128, 0, 128 ],
+ red: [ 255, 0, 0 ],
+ silver: [ 192, 192, 192 ],
+ white: [ 255, 255, 255 ],
+ yellow: [ 255, 255, 0 ],
+ transparent: [ 255, 255, 255 ]
+ },
+
+ /**
+ * Convert an RGB color value to HSL.
+ *
+ * Conversion formula based on
+ * <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
+ *
+ * Adapted from <https://en.wikipedia.org/wiki/HSL_color_space>.
+ *
+ * Assumes `r`, `g`, and `b` are contained in the set `[0, 255]` and
+ * returns `h`, `s`, and `l` in the set `[0, 1]`.
+ *
+ * @param {number} r The red color value
+ * @param {number} g The green color value
+ * @param {number} b The blue color value
+ * @return {number[]} The HSL representation
+ */
+ rgbToHsl: function ( r, g, b ) {
+ var d, h, s, l, min, max;
+
+ r = r / 255;
+ g = g / 255;
+ b = b / 255;
+
+ max = Math.max( r, g, b );
+ min = Math.min( r, g, b );
+ l = ( max + min ) / 2;
+
+ if ( max === min ) {
+ // achromatic
+ h = s = 0;
+ } else {
+ d = max - min;
+ s = l > 0.5 ? d / ( 2 - max - min ) : d / ( max + min );
+ switch ( max ) {
+ case r:
+ h = ( g - b ) / d + ( g < b ? 6 : 0 );
+ break;
+ case g:
+ h = ( b - r ) / d + 2;
+ break;
+ case b:
+ h = ( r - g ) / d + 4;
+ break;
+ }
+ h /= 6;
+ }
+
+ return [ h, s, l ];
+ },
+
+ /**
+ * Convert an HSL color value to RGB.
+ *
+ * Conversion formula based on
+ * <http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript>
+ *
+ * Adapted from <https://en.wikipedia.org/wiki/HSL_color_space>.
+ *
+ * Assumes `h`, `s`, and `l` are contained in the set `[0, 1]` and
+ * returns `r`, `g`, and `b` in the set `[0, 255]`.
+ *
+ * @param {number} h The hue
+ * @param {number} s The saturation
+ * @param {number} l The lightness
+ * @return {number[]} The RGB representation
+ */
+ hslToRgb: function ( h, s, l ) {
+ var r, g, b, hue2rgb, q, p;
+
+ if ( s === 0 ) {
+ r = g = b = l; // achromatic
+ } else {
+ hue2rgb = function ( p, q, t ) {
+ if ( t < 0 ) {
+ t += 1;
+ }
+ if ( t > 1 ) {
+ t -= 1;
+ }
+ if ( t < 1 / 6 ) {
+ return p + ( q - p ) * 6 * t;
+ }
+ if ( t < 1 / 2 ) {
+ return q;
+ }
+ if ( t < 2 / 3 ) {
+ return p + ( q - p ) * ( 2 / 3 - t ) * 6;
+ }
+ return p;
+ };
+
+ q = l < 0.5 ? l * ( 1 + s ) : l + s - l * s;
+ p = 2 * l - q;
+ r = hue2rgb( p, q, h + 1 / 3 );
+ g = hue2rgb( p, q, h );
+ b = hue2rgb( p, q, h - 1 / 3 );
+ }
+
+ return [ r * 255, g * 255, b * 255 ];
+ },
+
+ /**
+ * Get a brighter or darker rgb() value string.
+ *
+ * Usage:
+ *
+ * $.colorUtil.getColorBrightness( 'red', +0.1 );
+ * // > "rgb(255,50,50)"
+ * $.colorUtil.getColorBrightness( 'rgb(200,50,50)', -0.2 );
+ * // > "rgb(118,29,29)"
+ *
+ * @param {Mixed} currentColor Current value in css
+ * @param {number} mod Wanted brightness modification between -1 and 1
+ * @return {string} Like `'rgb(r,g,b)'`
+ */
+ getColorBrightness: function ( currentColor, mod ) {
+ var rgbArr = $.colorUtil.getRGB( currentColor ),
+ hslArr = $.colorUtil.rgbToHsl( rgbArr[ 0 ], rgbArr[ 1 ], rgbArr[ 2 ] );
+ rgbArr = $.colorUtil.hslToRgb( hslArr[ 0 ], hslArr[ 1 ], hslArr[ 2 ] + mod );
+
+ return 'rgb(' +
+ [ parseInt( rgbArr[ 0 ], 10 ), parseInt( rgbArr[ 1 ], 10 ), parseInt( rgbArr[ 2 ], 10 ) ].join( ',' ) +
+ ')';
+ }
+
+ };
+
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.confirmable.css b/www/wiki/resources/src/jquery/jquery.confirmable.css
new file mode 100644
index 00000000..78c4c044
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.confirmable.css
@@ -0,0 +1,28 @@
+.jquery-confirmable-button {
+ /* Automatically flipped */
+ margin-left: 1ex;
+}
+
+.jquery-confirmable-wrapper {
+ /* Line breaks within the interface text are unpleasant */
+ white-space: nowrap;
+ /* Hiding the original text when it slides to the left */
+ overflow: hidden;
+}
+
+.jquery-confirmable-wrapper,
+.jquery-confirmable-element,
+.jquery-confirmable-interface {
+ /* We need inline-block to be able to size the elements and calculate their dimensions */
+ display: inline-block;
+ /* inline-block elements in this context align to baseline by default */
+ vertical-align: bottom;
+}
+
+.jquery-confirmable-element {
+ transition: margin 250ms cubic-bezier( 0.2, 0.8, 0.2, 0.8 );
+}
+
+.jquery-confirmable-interface {
+ transition: width 250ms cubic-bezier( 0.2, 0.8, 0.2, 0.8 );
+}
diff --git a/www/wiki/resources/src/jquery/jquery.confirmable.js b/www/wiki/resources/src/jquery/jquery.confirmable.js
new file mode 100644
index 00000000..7931c814
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.confirmable.js
@@ -0,0 +1,183 @@
+/**
+ * jQuery confirmable plugin
+ *
+ * Released under the MIT License.
+ *
+ * @author Bartosz Dziewoński
+ *
+ * @class jQuery.plugin.confirmable
+ */
+( function ( $ ) {
+ var identity = function ( data ) {
+ return data;
+ };
+
+ // eslint-disable-next-line valid-jsdoc
+ /**
+ * Enable inline confirmation for given clickable element (like `<a />` or `<button />`).
+ *
+ * An additional inline confirmation step being shown before the default action is carried out on
+ * click.
+ *
+ * Calling `.confirmable( { handler: function () { … } } )` will fire the handler only after the
+ * confirmation step.
+ *
+ * The element will have the `jquery-confirmable-element` class added to it when it's clicked for
+ * the first time, which has `white-space: nowrap;` and `display: inline-block;` defined in CSS.
+ * If the computed values for the element are different when you make it confirmable, you might
+ * encounter unexpected behavior.
+ *
+ * @param {Object} [options]
+ * @param {string} [options.events='click'] Events to hook to.
+ * @param {Function} [options.wrapperCallback] Callback to fire when preparing confirmable
+ * interface. Receives the interface jQuery object as the only parameter.
+ * @param {Function} [options.buttonCallback] Callback to fire when preparing confirmable buttons.
+ * It is fired separately for the 'Yes' and 'No' button. Receives the button jQuery object as
+ * the first parameter and 'yes' or 'no' as the second.
+ * @param {Function} [options.handler] Callback to fire when the action is confirmed (user clicks
+ * the 'Yes' button).
+ * @param {string} [options.i18n] Text to use for interface elements.
+ * @param {string} [options.i18n.space] Word separator to place between the three text messages.
+ * @param {string} [options.i18n.confirm] Text to use for the confirmation question.
+ * @param {string} [options.i18n.yes] Text to use for the 'Yes' button.
+ * @param {string} [options.i18n.no] Text to use for the 'No' button.
+ * @param {string} [options.i18n.yesTitle] Title text to use for the 'Yes' button.
+ * @param {string} [options.i18n.noTitle] Title text to use for the 'No' button.
+ *
+ * @chainable
+ */
+ $.fn.confirmable = function ( options ) {
+ options = $.extend( true, {}, $.fn.confirmable.defaultOptions, options || {} );
+
+ return this.on( options.events, function ( e ) {
+ var $element, $text, $buttonYes, $buttonNo, $wrapper, $interface, $elementClone,
+ interfaceWidth, elementWidth, rtl, positionOffscreen, positionRestore, sideMargin;
+
+ $element = $( this );
+
+ if ( $element.data( 'jquery-confirmable-button' ) ) {
+ // We're running on a clone of this element that represents the 'Yes' or 'No' button.
+ // (This should never happen for the 'No' case unless calling code does bad things.)
+ return;
+ }
+
+ // Only prevent native event handling. Stopping other JavaScript event handlers
+ // is impossible because they might have already run (we have no control over the order).
+ e.preventDefault();
+
+ rtl = $element.css( 'direction' ) === 'rtl';
+ if ( rtl ) {
+ positionOffscreen = { position: 'absolute', right: '-9999px' };
+ positionRestore = { position: '', right: '' };
+ sideMargin = 'marginRight';
+ } else {
+ positionOffscreen = { position: 'absolute', left: '-9999px' };
+ positionRestore = { position: '', left: '' };
+ sideMargin = 'marginLeft';
+ }
+
+ if ( $element.hasClass( 'jquery-confirmable-element' ) ) {
+ $wrapper = $element.closest( '.jquery-confirmable-wrapper' );
+ $interface = $wrapper.find( '.jquery-confirmable-interface' );
+ $text = $interface.find( '.jquery-confirmable-text' );
+ $buttonYes = $interface.find( '.jquery-confirmable-button-yes' );
+ $buttonNo = $interface.find( '.jquery-confirmable-button-no' );
+
+ interfaceWidth = $interface.data( 'jquery-confirmable-width' );
+ elementWidth = $element.data( 'jquery-confirmable-width' );
+ } else {
+ $elementClone = $element.clone( true );
+ $element.addClass( 'jquery-confirmable-element' );
+
+ elementWidth = $element.width();
+ $element.data( 'jquery-confirmable-width', elementWidth );
+
+ $wrapper = $( '<span>' )
+ .addClass( 'jquery-confirmable-wrapper' );
+ $element.wrap( $wrapper );
+
+ // Build the mini-dialog
+ $text = $( '<span>' )
+ .addClass( 'jquery-confirmable-text' )
+ .text( options.i18n.confirm );
+
+ // Clone original element along with event handlers to easily replicate its behavior.
+ // We could fiddle with .trigger() etc., but that is troublesome especially since
+ // Safari doesn't implement .click() on <a> links and jQuery follows suit.
+ $buttonYes = $elementClone.clone( true )
+ .addClass( 'jquery-confirmable-button jquery-confirmable-button-yes' )
+ .data( 'jquery-confirmable-button', true )
+ .text( options.i18n.yes );
+ if ( options.handler ) {
+ $buttonYes.on( options.events, options.handler );
+ }
+ if ( options.i18n.yesTitle ) {
+ $buttonYes.attr( 'title', options.i18n.yesTitle );
+ }
+ $buttonYes = options.buttonCallback( $buttonYes, 'yes' );
+
+ // Clone it without any events and prevent default action to represent the 'No' button.
+ $buttonNo = $elementClone.clone( false )
+ .addClass( 'jquery-confirmable-button jquery-confirmable-button-no' )
+ .data( 'jquery-confirmable-button', true )
+ .text( options.i18n.no )
+ .on( options.events, function ( e ) {
+ $element.css( sideMargin, 0 );
+ $interface.css( 'width', 0 );
+ e.preventDefault();
+ } );
+ if ( options.i18n.noTitle ) {
+ $buttonNo.attr( 'title', options.i18n.noTitle );
+ } else {
+ $buttonNo.removeAttr( 'title' );
+ }
+ $buttonNo = options.buttonCallback( $buttonNo, 'no' );
+
+ // Prevent memory leaks
+ $elementClone.remove();
+
+ $interface = $( '<span>' )
+ .addClass( 'jquery-confirmable-interface' )
+ .append( $text, options.i18n.space, $buttonYes, options.i18n.space, $buttonNo );
+ $interface = options.wrapperCallback( $interface );
+
+ // Render offscreen to measure real width
+ $interface.css( positionOffscreen );
+ // Insert it in the correct place while we're at it
+ $element.after( $interface );
+ interfaceWidth = $interface.width();
+ $interface.data( 'jquery-confirmable-width', interfaceWidth );
+ $interface.css( positionRestore );
+
+ // Hide to animate the transition later
+ $interface.css( 'width', 0 );
+ }
+
+ // Hide element, show interface. This triggers both transitions.
+ // In a timeout to trigger the 'width' transition.
+ setTimeout( function () {
+ $element.css( sideMargin, -elementWidth );
+ $interface.css( 'width', interfaceWidth );
+ }, 1 );
+ } );
+ };
+
+ /**
+ * Default options. Overridable primarily for internationalisation handling.
+ * @property {Object} defaultOptions
+ */
+ $.fn.confirmable.defaultOptions = {
+ events: 'click',
+ wrapperCallback: identity,
+ buttonCallback: identity,
+ handler: null,
+ i18n: {
+ space: ' ',
+ confirm: 'Are you sure?',
+ yes: 'Yes',
+ no: 'No',
+ yesTitle: undefined,
+ noTitle: undefined
+ }
+ };
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.confirmable.mediawiki.js b/www/wiki/resources/src/jquery/jquery.confirmable.mediawiki.js
new file mode 100644
index 00000000..daf23a99
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.confirmable.mediawiki.js
@@ -0,0 +1,16 @@
+/*!
+ * jQuery confirmable plugin customization for MediaWiki
+ *
+ * This file serves to inject our localised messages into it.
+ */
+
+( function ( mw, $ ) {
+ $.fn.confirmable.defaultOptions.i18n = {
+ space: mw.message( 'word-separator' ).text(),
+ confirm: mw.message( 'confirmable-confirm', mw.user ).text(),
+ yes: mw.message( 'confirmable-yes' ).text(),
+ no: mw.message( 'confirmable-no' ).text(),
+ yesTitle: undefined,
+ noTitle: undefined
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.expandableField.js b/www/wiki/resources/src/jquery/jquery.expandableField.js
new file mode 100644
index 00000000..c3d39daf
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.expandableField.js
@@ -0,0 +1,147 @@
+/**
+ * This plugin provides functionality to expand a text box on focus to double it's current width
+ *
+ * Usage:
+ *
+ * Set options:
+ * $('#textbox').expandableField( { option1: value1, option2: value2 } );
+ * $('#textbox').expandableField( option, value );
+ * Get option:
+ * value = $('#textbox').expandableField( option );
+ * Initialize:
+ * $('#textbox').expandableField();
+ *
+ * Options:
+ */
+( function ( $ ) {
+
+ $.expandableField = {
+ /**
+ * Expand the field, make the callback
+ *
+ * @param {jQuery.Event} e Event
+ * @param {Object} context
+ */
+ expandField: function ( e, context ) {
+ context.config.beforeExpand.call( context.data.$field, context );
+ context.data.$field
+ .animate( { width: context.data.expandedWidth }, 'fast', function () {
+ context.config.afterExpand.call( this, context );
+ } );
+ },
+ /**
+ * Condense the field, make the callback
+ *
+ * @param {jQuery.Event} e Event
+ * @param {Object} context
+ */
+ condenseField: function ( e, context ) {
+ context.config.beforeCondense.call( context.data.$field, context );
+ context.data.$field
+ .animate( { width: context.data.condensedWidth }, 'fast', function () {
+ context.config.afterCondense.call( this, context );
+ } );
+ },
+ /**
+ * Sets the value of a property, and updates the widget accordingly
+ *
+ * @param {Object} context
+ * @param {string} property Name of property
+ * @param {Mixed} value Value to set property with
+ */
+ configure: function ( context, property, value ) {
+ // TODO: Validate creation using fallback values
+ context.config[ property ] = value;
+ }
+
+ };
+
+ $.fn.expandableField = function () {
+
+ // Multi-context fields
+ var returnValue,
+ args = arguments;
+
+ $( this ).each( function () {
+ var key, context, timeout;
+
+ /* Construction / Loading */
+
+ context = $( this ).data( 'expandableField-context' );
+
+ // TODO: Do we need to check both null and undefined?
+ if ( context === undefined || context === null ) {
+ context = {
+ config: {
+ // callback function for before collapse
+ beforeCondense: function () {},
+
+ // callback function for before expand
+ beforeExpand: function () {},
+
+ // callback function for after collapse
+ afterCondense: function () {},
+
+ // callback function for after expand
+ afterExpand: function () {},
+
+ // Whether the field should expand to the left or the right -- defaults to left
+ expandToLeft: true
+ }
+ };
+ }
+
+ /* API */
+ // Handle various calling styles
+ if ( args.length > 0 ) {
+ if ( typeof args[ 0 ] === 'object' ) {
+ // Apply set of properties
+ for ( key in args[ 0 ] ) {
+ $.expandableField.configure( context, key, args[ 0 ][ key ] );
+ }
+ } else if ( typeof args[ 0 ] === 'string' ) {
+ if ( args.length > 1 ) {
+ // Set property values
+ $.expandableField.configure( context, args[ 0 ], args[ 1 ] );
+
+ // TODO: Do we need to check both null and undefined?
+ } else if ( returnValue === null || returnValue === undefined ) {
+ // Get property values, but don't give access to internal data - returns only the first
+ returnValue = ( args[ 0 ] in context.config ? undefined : context.config[ args[ 0 ] ] );
+ }
+ }
+ }
+
+ /* Initialization */
+
+ if ( context.data === undefined ) {
+ context.data = {
+ // The width of the field in it's condensed state
+ condensedWidth: $( this ).width(),
+
+ // The width of the field in it's expanded state
+ expandedWidth: $( this ).width() * 2,
+
+ // Reference to the field
+ $field: $( this )
+ };
+
+ $( this )
+ .addClass( 'expandableField' )
+ .focus( function ( e ) {
+ clearTimeout( timeout );
+ $.expandableField.expandField( e, context );
+ } )
+ .blur( function ( e ) {
+ timeout = setTimeout( function () {
+ $.expandableField.condenseField( e, context );
+ }, 250 );
+ } );
+ }
+ // Store the context for next time
+ $( this ).data( 'expandableField-context', context );
+ } );
+ return returnValue !== undefined ? returnValue : $( this );
+ };
+
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.farbtastic.css b/www/wiki/resources/src/jquery/jquery.farbtastic.css
new file mode 100644
index 00000000..0cba34f4
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.farbtastic.css
@@ -0,0 +1,55 @@
+/**
+ * Farbtastic Color Picker 1.2
+ * © 2008 Steven Wittens
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+.farbtastic {
+ position: relative;
+}
+.farbtastic * {
+ position: absolute;
+ cursor: crosshair;
+}
+.farbtastic,
+.farbtastic .wheel {
+ width: 195px;
+ height: 195px;
+}
+.farbtastic .color,
+.farbtastic .overlay {
+ top: 47px;
+ left: 47px;
+ width: 101px;
+ height: 101px;
+}
+.farbtastic .wheel {
+ /* @embed */
+ background: url( images/wheel.png ) no-repeat;
+ width: 195px;
+ height: 195px;
+}
+.farbtastic .overlay {
+ /* @embed */
+ background: url( images/mask.png ) no-repeat;
+}
+.farbtastic .marker {
+ width: 17px;
+ height: 17px;
+ margin: -8px 0 0 -8px;
+ overflow: hidden;
+ /* @embed */
+ background: url( images/marker.png ) no-repeat;
+}
diff --git a/www/wiki/resources/src/jquery/jquery.farbtastic.js b/www/wiki/resources/src/jquery/jquery.farbtastic.js
new file mode 100644
index 00000000..f70913f9
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.farbtastic.js
@@ -0,0 +1,286 @@
+/**
+ * Farbtastic Color Picker 1.2
+ * © 2008 Steven Wittens
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+//Adapted to uniform style with jQuery UI widgets and slightly change behavior
+//TODO:
+// - remove duplicated code by replacing it with jquery.colorUtils and modern jQuery
+// - uniform code style
+
+jQuery.fn.farbtastic = function (callback) {
+ $.farbtastic(this, callback);
+ return this;
+};
+
+jQuery.farbtastic = function (container, callback) {
+ var container = $(container).get(0);
+ return container.farbtastic || (container.farbtastic = new jQuery._farbtastic(container, callback));
+}
+
+jQuery._farbtastic = function (container, callback) {
+ // Store farbtastic object
+ var fb = this;
+
+ // Insert markup
+ $(container).html('<div class="farbtastic ui-widget-content"><div class="color"></div><div class="wheel"></div><div class="overlay"></div><div class="h-marker marker"></div><div class="sl-marker marker"></div></div>');
+ $(container).addClass('ui-widget');
+ var e = $('.farbtastic', container);
+ fb.wheel = $('.wheel', container).get(0);
+ // Dimensions
+ fb.radius = 84;
+ fb.square = 100;
+ fb.width = 194;
+
+ // Fix background PNGs in IE6
+ if (navigator.appVersion.match(/MSIE [0-6]\./)) {
+ $('*', e).each(function () {
+ if (this.currentStyle.backgroundImage != 'none') {
+ var image = this.currentStyle.backgroundImage;
+ image = this.currentStyle.backgroundImage.slice(5, image.length - 2);
+ $(this).css( {
+ backgroundImage: 'none',
+ filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
+ } );
+ }
+ });
+ }
+
+ /**
+ * Link to the given element(s) or callback.
+ */
+ fb.linkTo = function (callback) {
+ // Unbind previous nodes
+ if (typeof fb.callback == 'object') {
+ $(fb.callback).unbind('keyup', fb.updateValue);
+ }
+
+ // Reset color
+ fb.color = null;
+
+ // Bind callback or elements
+ if (typeof callback == 'function') {
+ fb.callback = callback;
+ }
+ else if (typeof callback == 'object' || typeof callback == 'string') {
+ fb.callback = $(callback);
+ fb.callback.bind('keyup', fb.updateValue);
+ if (fb.callback.get(0).value) {
+ fb.setColor(fb.callback.get(0).value);
+ }
+ }
+ return this;
+ }
+ fb.updateValue = function (event) {
+ if (this.value != fb.color) {
+ fb.setColor(this.value);
+ }
+ }
+
+ /**
+ * Change color with HTML syntax #123456
+ */
+ fb.setColor = function (color) {
+ var rgb = $.colorUtil.getRGB( color );
+ if (fb.color != color && rgb) {
+ rgb = rgb.slice( 0 ); //make a clone
+ //TODO: rewrite code so that this is not needed
+ rgb[0] /= 255;
+ rgb[1] /= 255;
+ rgb[2] /= 255;
+ fb.color = color;
+ fb.rgb = rgb;
+ fb.hsl = fb.RGBToHSL(fb.rgb);
+ fb.updateDisplay();
+ }
+ return this;
+ }
+
+ /**
+ * Change color with HSL triplet [0..1, 0..1, 0..1]
+ */
+ fb.setHSL = function (hsl) {
+ fb.hsl = hsl;
+ fb.rgb = fb.HSLToRGB(hsl);
+ fb.color = fb.pack(fb.rgb);
+ fb.updateDisplay();
+ return this;
+ }
+
+ /////////////////////////////////////////////////////
+
+ /**
+ * Retrieve the coordinates of the given event relative to the center
+ * of the widget.
+ */
+ fb.widgetCoords = function (event) {
+ var ref = $( fb.wheel ).offset();
+ return {
+ x: event.pageX - ref.left - fb.width / 2,
+ y: event.pageY - ref.top - fb.width / 2
+ };
+ }
+
+ /**
+ * Mousedown handler
+ */
+ fb.mousedown = function (event) {
+ // Capture mouse
+ if (!document.dragging) {
+ $(document).bind('mousemove', fb.mousemove).bind('mouseup', fb.mouseup);
+ document.dragging = true;
+ }
+
+ // Check which area is being dragged
+ var pos = fb.widgetCoords(event);
+ fb.circleDrag = Math.max(Math.abs(pos.x), Math.abs(pos.y)) * 2 > fb.square;
+
+ // Process
+ fb.mousemove(event);
+ return false;
+ }
+
+ /**
+ * Mousemove handler
+ */
+ fb.mousemove = function (event) {
+ // Get coordinates relative to color picker center
+ var pos = fb.widgetCoords(event);
+
+ // Set new HSL parameters
+ if (fb.circleDrag) {
+ var hue = Math.atan2(pos.x, -pos.y) / 6.28;
+ if (hue < 0) hue += 1;
+ fb.setHSL([hue, fb.hsl[1], fb.hsl[2]]);
+ }
+ else {
+ var sat = Math.max(0, Math.min(1, -(pos.x / fb.square) + .5));
+ var lum = Math.max(0, Math.min(1, -(pos.y / fb.square) + .5));
+ fb.setHSL([fb.hsl[0], sat, lum]);
+ }
+ return false;
+ }
+
+ /**
+ * Mouseup handler
+ */
+ fb.mouseup = function () {
+ // Uncapture mouse
+ $(document).unbind('mousemove', fb.mousemove);
+ $(document).unbind('mouseup', fb.mouseup);
+ document.dragging = false;
+ }
+
+ /**
+ * Update the markers and styles
+ */
+ fb.updateDisplay = function () {
+ // Markers
+ var angle = fb.hsl[0] * 6.28;
+ $('.h-marker', e).css({
+ left: Math.round(Math.sin(angle) * fb.radius + fb.width / 2) + 'px',
+ top: Math.round(-Math.cos(angle) * fb.radius + fb.width / 2) + 'px'
+ });
+
+ $('.sl-marker', e).css({
+ left: Math.round(fb.square * (.5 - fb.hsl[1]) + fb.width / 2) + 'px',
+ top: Math.round(fb.square * (.5 - fb.hsl[2]) + fb.width / 2) + 'px'
+ });
+
+ // Saturation/Luminance gradient
+ $('.color', e).css('backgroundColor', fb.pack(fb.HSLToRGB([fb.hsl[0], 1, 0.5])));
+
+ // Linked elements or callback
+ if (typeof fb.callback == 'object') {
+ // Set background/foreground color
+ $(fb.callback).css({
+ backgroundColor: fb.color,
+ color: fb.hsl[2] > 0.5 ? '#000' : '#fff'
+ });
+
+ // Change linked value
+ $(fb.callback).each(function() {
+ if ( $( this ).val() != fb.color) {
+ $( this ).val( fb.color ).change();
+ }
+ });
+ }
+ else if (typeof fb.callback == 'function') {
+ fb.callback.call(fb, fb.color);
+ }
+ }
+
+ /* Various color utility functions */
+ fb.pack = function (rgb) {
+ var r = Math.round(rgb[0] * 255);
+ var g = Math.round(rgb[1] * 255);
+ var b = Math.round(rgb[2] * 255);
+ return '#' + (r < 16 ? '0' : '') + r.toString(16) +
+ (g < 16 ? '0' : '') + g.toString(16) +
+ (b < 16 ? '0' : '') + b.toString(16);
+ }
+
+ fb.HSLToRGB = function (hsl) {
+ var m1, m2, r, g, b;
+ var h = hsl[0], s = hsl[1], l = hsl[2];
+ m2 = (l <= 0.5) ? l * (s + 1) : l + s - l*s;
+ m1 = l * 2 - m2;
+ return [this.hueToRGB(m1, m2, h+0.33333),
+ this.hueToRGB(m1, m2, h),
+ this.hueToRGB(m1, m2, h-0.33333)];
+ }
+
+ fb.hueToRGB = function (m1, m2, h) {
+ h = (h < 0) ? h + 1 : ((h > 1) ? h - 1 : h);
+ if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
+ if (h * 2 < 1) return m2;
+ if (h * 3 < 2) return m1 + (m2 - m1) * (0.66666 - h) * 6;
+ return m1;
+ }
+
+ fb.RGBToHSL = function (rgb) {
+ var min, max, delta, h, s, l;
+ var r = rgb[0], g = rgb[1], b = rgb[2];
+ min = Math.min(r, Math.min(g, b));
+ max = Math.max(r, Math.max(g, b));
+ delta = max - min;
+ l = (min + max) / 2;
+ s = 0;
+ if (l > 0 && l < 1) {
+ s = delta / (l < 0.5 ? (2 * l) : (2 - 2 * l));
+ }
+ h = 0;
+ if (delta > 0) {
+ if (max == r && max != g) h += (g - b) / delta;
+ if (max == g && max != b) h += (2 + (b - r) / delta);
+ if (max == b && max != r) h += (4 + (r - g) / delta);
+ h /= 6;
+ }
+ return [h, s, l];
+ }
+
+ // Install mousedown handler (the others are set on the document on-demand)
+ $('*', e).mousedown(fb.mousedown);
+
+ // Init color
+ fb.setColor('#000000');
+
+ // Set linked elements/callback
+ if (callback) {
+ fb.linkTo(callback);
+ }
+}
diff --git a/www/wiki/resources/src/jquery/jquery.footHovzer.css b/www/wiki/resources/src/jquery/jquery.footHovzer.css
new file mode 100644
index 00000000..77d9514c
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.footHovzer.css
@@ -0,0 +1,6 @@
+#jquery-foot-hovzer {
+ position: fixed;
+ bottom: 0;
+ width: 100%;
+ z-index: 1000;
+}
diff --git a/www/wiki/resources/src/jquery/jquery.footHovzer.js b/www/wiki/resources/src/jquery/jquery.footHovzer.js
new file mode 100644
index 00000000..e601ddb1
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.footHovzer.js
@@ -0,0 +1,66 @@
+/**
+ * @class jQuery.plugin.footHovzer
+ */
+( function ( $ ) {
+ var $hovzer, footHovzer, $spacer;
+
+ function getHovzer() {
+ if ( $hovzer === undefined ) {
+ $hovzer = $( '<div id="jquery-foot-hovzer"></div>' ).appendTo( 'body' );
+ }
+ return $hovzer;
+ }
+
+ /**
+ * Utility to stack stuff in an overlay fixed on the bottom of the page.
+ *
+ * Usage:
+ *
+ * var hovzer = $.getFootHovzer();
+ * hovzer.$.append( $myCollection );
+ * hovzer.update();
+ *
+ * @static
+ * @inheritable
+ * @return {jQuery.footHovzer}
+ */
+ $.getFootHovzer = function () {
+ footHovzer.$ = getHovzer();
+ return footHovzer;
+ };
+
+ /**
+ * @private
+ * @class jQuery.footHovzer
+ */
+ footHovzer = {
+
+ /**
+ * @property {jQuery} $ The stack container
+ */
+
+ /**
+ * Update dimensions of stack to account for changes in the subtree.
+ */
+ update: function () {
+ var $body;
+
+ $body = $( 'body' );
+
+ if ( $spacer === undefined ) {
+ $spacer = $( '<div>' ).attr( 'id', 'jquery-foot-hovzer-spacer' );
+ $spacer.appendTo( $body );
+ }
+ // Ensure CSS is applied by browser before using .outerHeight()
+ setTimeout( function () {
+ $spacer.css( 'height', getHovzer().outerHeight( /* includeMargin = */ true ) );
+ }, 0 );
+ }
+ };
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.footHovzer
+ */
+
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.getAttrs.js b/www/wiki/resources/src/jquery/jquery.getAttrs.js
new file mode 100644
index 00000000..e00298f4
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.getAttrs.js
@@ -0,0 +1,37 @@
+/**
+ * @class jQuery.plugin.getAttrs
+ */
+( function ( $ ) {
+ function serializeControls( controls ) {
+ var i,
+ data = {},
+ len = controls.length;
+
+ for ( i = 0; i < len; i++ ) {
+ data[ controls[ i ].name ] = controls[ i ].value;
+ }
+
+ return data;
+ }
+
+ /**
+ * Get the attributes of an element directy as a plain object.
+ *
+ * If there is more than one element in the collection, similar to most other jQuery getter methods,
+ * this will use the first element in the collection.
+ *
+ * @return {Object}
+ */
+ $.fn.getAttrs = function () {
+ return serializeControls( this[ 0 ].attributes );
+ };
+
+ /**
+ * Get form data as a plain object mapping form control names to their values.
+ *
+ * @return {Object}
+ */
+ $.fn.serializeObject = function () {
+ return serializeControls( this.serializeArray() );
+ };
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.hidpi.js b/www/wiki/resources/src/jquery/jquery.hidpi.js
new file mode 100644
index 00000000..7a7109cb
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.hidpi.js
@@ -0,0 +1,177 @@
+/**
+ * Responsive images based on `srcset` and `window.devicePixelRatio` emulation where needed.
+ *
+ * Call `.hidpi()` on a document or part of a document to proces image srcsets within that section.
+ *
+ * `$.devicePixelRatio()` can be used as a substitute for `window.devicePixelRatio`.
+ * It provides a familiar interface to retrieve the pixel ratio for browsers that don't
+ * implement `window.devicePixelRatio` but do have a different way of getting it.
+ *
+ * @class jQuery.plugin.hidpi
+ */
+( function ( $ ) {
+
+ /**
+ * Get reported or approximate device pixel ratio.
+ *
+ * - 1.0 means 1 CSS pixel is 1 hardware pixel
+ * - 2.0 means 1 CSS pixel is 2 hardware pixels
+ * - etc.
+ *
+ * Uses `window.devicePixelRatio` if available, or CSS media queries on IE.
+ *
+ * @static
+ * @inheritable
+ * @return {number} Device pixel ratio
+ */
+ $.devicePixelRatio = function () {
+ if ( window.devicePixelRatio !== undefined ) {
+ // Most web browsers:
+ // * WebKit/Blink (Safari, Chrome, Android browser, etc)
+ // * Opera
+ // * Firefox 18+
+ // * Microsoft Edge (Windows 10)
+ return window.devicePixelRatio;
+ } else if ( window.msMatchMedia !== undefined ) {
+ // Windows 8 desktops / tablets, probably Windows Phone 8
+ //
+ // IE 10/11 doesn't report pixel ratio directly, but we can get the
+ // screen DPI and divide by 96. We'll bracket to [1, 1.5, 2.0] for
+ // simplicity, but you may get different values depending on zoom
+ // factor, size of screen and orientation in Metro IE.
+ if ( window.msMatchMedia( '(min-resolution: 192dpi)' ).matches ) {
+ return 2;
+ } else if ( window.msMatchMedia( '(min-resolution: 144dpi)' ).matches ) {
+ return 1.5;
+ } else {
+ return 1;
+ }
+ } else {
+ // Legacy browsers...
+ // Assume 1 if unknown.
+ return 1;
+ }
+ };
+
+ /**
+ * Bracket a given device pixel ratio to one of [1, 1.5, 2].
+ *
+ * This is useful for grabbing images on the fly with sizes based on the display
+ * density, without causing slowdown and extra thumbnail renderings on devices
+ * that are slightly different from the most common sizes.
+ *
+ * The bracketed ratios match the default 'srcset' output on MediaWiki thumbnails,
+ * so will be consistent with default renderings.
+ *
+ * @static
+ * @inheritable
+ * @param {number} baseRatio Base ratio
+ * @return {number} Device pixel ratio
+ */
+ $.bracketDevicePixelRatio = function ( baseRatio ) {
+ if ( baseRatio > 1.5 ) {
+ return 2;
+ } else if ( baseRatio > 1 ) {
+ return 1.5;
+ } else {
+ return 1;
+ }
+ };
+
+ /**
+ * Get reported or approximate device pixel ratio, bracketed to [1, 1.5, 2].
+ *
+ * This is useful for grabbing images on the fly with sizes based on the display
+ * density, without causing slowdown and extra thumbnail renderings on devices
+ * that are slightly different from the most common sizes.
+ *
+ * The bracketed ratios match the default 'srcset' output on MediaWiki thumbnails,
+ * so will be consistent with default renderings.
+ *
+ * - 1.0 means 1 CSS pixel is 1 hardware pixel
+ * - 1.5 means 1 CSS pixel is 1.5 hardware pixels
+ * - 2.0 means 1 CSS pixel is 2 hardware pixels
+ *
+ * @static
+ * @inheritable
+ * @return {number} Device pixel ratio
+ */
+ $.bracketedDevicePixelRatio = function () {
+ return $.bracketDevicePixelRatio( $.devicePixelRatio() );
+ };
+
+ /**
+ * Implement responsive images based on srcset attributes, if browser has no
+ * native srcset support.
+ *
+ * @return {jQuery} This selection
+ * @chainable
+ */
+ $.fn.hidpi = function () {
+ var $target = this,
+ // TODO add support for dpi media query checks on Firefox, IE
+ devicePixelRatio = $.devicePixelRatio(),
+ testImage = new Image();
+
+ if ( devicePixelRatio > 1 && testImage.srcset === undefined ) {
+ // No native srcset support.
+ $target.find( 'img' ).each( function () {
+ var $img = $( this ),
+ srcset = $img.attr( 'srcset' ),
+ match;
+ if ( typeof srcset === 'string' && srcset !== '' ) {
+ match = $.matchSrcSet( devicePixelRatio, srcset );
+ if ( match !== null ) {
+ $img.attr( 'src', match );
+ }
+ }
+ } );
+ }
+
+ return $target;
+ };
+
+ /**
+ * Match a srcset entry for the given device pixel ratio
+ *
+ * Exposed for testing.
+ *
+ * @private
+ * @static
+ * @param {number} devicePixelRatio
+ * @param {string} srcset
+ * @return {Mixed} null or the matching src string
+ */
+ $.matchSrcSet = function ( devicePixelRatio, srcset ) {
+ var candidates,
+ candidate,
+ bits,
+ src,
+ i,
+ ratioStr,
+ ratio,
+ selectedRatio = 1,
+ selectedSrc = null;
+ candidates = srcset.split( / *, */ );
+ for ( i = 0; i < candidates.length; i++ ) {
+ candidate = candidates[ i ];
+ bits = candidate.split( / +/ );
+ src = bits[ 0 ];
+ if ( bits.length > 1 && bits[ 1 ].charAt( bits[ 1 ].length - 1 ) === 'x' ) {
+ ratioStr = bits[ 1 ].slice( 0, -1 );
+ ratio = parseFloat( ratioStr );
+ if ( ratio <= devicePixelRatio && ratio > selectedRatio ) {
+ selectedRatio = ratio;
+ selectedSrc = src;
+ }
+ }
+ }
+ return selectedSrc;
+ };
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.hidpi
+ */
+
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.highlightText.js b/www/wiki/resources/src/jquery/jquery.highlightText.js
new file mode 100644
index 00000000..a14e3ebd
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.highlightText.js
@@ -0,0 +1,97 @@
+/**
+ * Plugin that highlights matched word partials in a given element.
+ * TODO: Add a function for restoring the previous text.
+ * TODO: Accept mappings for converting shortcuts like WP: to Wikipedia:.
+ */
+( function ( $, mw ) {
+
+ $.highlightText = {
+
+ // Split our pattern string at spaces and run our highlight function on the results
+ splitAndHighlight: function ( node, text ) {
+ var i,
+ words = text.split( ' ' );
+ for ( i = 0; i < words.length; i++ ) {
+ if ( words[ i ].length === 0 ) {
+ continue;
+ }
+ $.highlightText.innerHighlight(
+ node,
+ new RegExp( '(^|\\s)' + mw.RegExp.escape( words[ i ] ), 'i' )
+ );
+ }
+ return node;
+ },
+
+ prefixHighlight: function ( node, prefix ) {
+ $.highlightText.innerHighlight(
+ node,
+ new RegExp( '(^)' + mw.RegExp.escape( prefix ), 'i' )
+ );
+ },
+
+ // scans a node looking for the pattern and wraps a span around each match
+ innerHighlight: function ( node, pat ) {
+ var i, match, pos, spannode, middlebit, middleclone;
+ if ( node.nodeType === Node.TEXT_NODE ) {
+ // TODO - need to be smarter about the character matching here.
+ // non latin characters can make regex think a new word has begun: do not use \b
+ // http://stackoverflow.com/questions/3787072/regex-wordwrap-with-utf8-characters-in-js
+ // look for an occurrence of our pattern and store the starting position
+ match = node.data.match( pat );
+ if ( match ) {
+ pos = match.index + match[ 1 ].length; // include length of any matched spaces
+ // create the span wrapper for the matched text
+ spannode = document.createElement( 'span' );
+ spannode.className = 'highlight';
+ // shave off the characters preceding the matched text
+ middlebit = node.splitText( pos );
+ // shave off any unmatched text off the end
+ middlebit.splitText( match[ 0 ].length - match[ 1 ].length );
+ // clone for appending to our span
+ middleclone = middlebit.cloneNode( true );
+ // append the matched text node to the span
+ spannode.appendChild( middleclone );
+ // replace the matched node, with our span-wrapped clone of the matched node
+ middlebit.parentNode.replaceChild( spannode, middlebit );
+ }
+ } else if (
+ node.nodeType === Node.ELEMENT_NODE &&
+ // element with childnodes, and not a script, style or an element we created
+ node.childNodes &&
+ !/(script|style)/i.test( node.tagName ) &&
+ !(
+ node.tagName.toLowerCase() === 'span' &&
+ node.className.match( /\bhighlight/ )
+ )
+ ) {
+ for ( i = 0; i < node.childNodes.length; ++i ) {
+ // call the highlight function for each child node
+ $.highlightText.innerHighlight( node.childNodes[ i ], pat );
+ }
+ }
+ }
+ };
+
+ /**
+ * Highlight certain text in current nodes (by wrapping it in `<span class="highlight">...</span>`).
+ *
+ * @param {string} matchString String to match
+ * @param {Object} [options]
+ * @param {string} [options.method='splitAndHighlight'] Method of matching to use, one of:
+ * - 'splitAndHighlight': Split `matchString` on spaces, then match each word separately.
+ * - 'prefixHighlight': Match `matchString` at the beginning of text only.
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.highlightText = function ( matchString, options ) {
+ options = options || {};
+ options.method = options.method || 'splitAndHighlight';
+ return this.each( function () {
+ var $el = $( this );
+ $el.data( 'highlightText', { originalText: $el.text() } );
+ $.highlightText[ options.method ]( this, matchString );
+ } );
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/jquery/jquery.localize.js b/www/wiki/resources/src/jquery/jquery.localize.js
new file mode 100644
index 00000000..05b3891d
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.localize.js
@@ -0,0 +1,170 @@
+/**
+ * @class jQuery.plugin.localize
+ */
+( function ( $, mw ) {
+
+ /**
+ * Gets a localized message, using parameters from options if present.
+ *
+ * @ignore
+ * @param {Object} options
+ * @param {string} key
+ * @return {string} Localized message
+ */
+ function msg( options, key ) {
+ var args = options.params[ key ] || [];
+ // Format: mw.msg( key [, p1, p2, ...] )
+ args.unshift( options.prefix + ( options.keys[ key ] || key ) );
+ return mw.msg.apply( mw, args );
+ }
+
+ /**
+ * Localizes a DOM selection by replacing <html:msg /> elements with localized text and adding
+ * localized title and alt attributes to elements with title-msg and alt-msg attributes
+ * respectively.
+ *
+ * Call on a selection of HTML which contains `<html:msg key="message-key" />` elements or elements
+ * with title-msg="message-key", alt-msg="message-key" or placeholder-msg="message-key" attributes.
+ * `<html:msg />` elements will be replaced with localized text, *-msg attributes will be replaced
+ * with attributes that do not have the "-msg" suffix and contain a localized message.
+ *
+ * Example:
+ * // Messages: { 'title': 'Awesome', 'desc': 'Cat doing backflip' 'search' contains 'Search' }
+ * var html = '\
+ * <p>\
+ * <html:msg key="title" />\
+ * <img src="something.jpg" title-msg="title" alt-msg="desc" />\
+ * <input type="text" placeholder-msg="search" />\
+ * </p>';
+ * $( 'body' ).append( $( html ).localize() );
+ *
+ * Appends something like this to the body...
+ * <p>
+ * Awesome
+ * <img src="something.jpg" title="Awesome" alt="Cat doing backflip" />
+ * <input type="text" placeholder="Search" />
+ * </p>
+ *
+ * Arguments can be passed into uses of a message using the params property of the options object
+ * given to .localize(). Multiple messages can be given parameters, because the params property is
+ * an object keyed by the message key to apply the parameters to, each containing an array of
+ * parameters to use. The limitation is that you can not use different parameters to individual uses
+ * of a message in the same selection being localized - they will all recieve the same parameters.
+ *
+ * Example:
+ * // Messages: { 'easy-as': 'Easy as $1 $2 $3.' }
+ * var html = '<p><html:msg key="easy-as" /></p>';
+ * $( 'body' ).append( $( html ).localize( { 'params': { 'easy-as': ['a', 'b', 'c'] } } ) );
+ *
+ * Appends something like this to the body...
+ * <p>Easy as a, b, c</p>
+ *
+ * Raw HTML content can be used, instead of it being escaped as text. To do this, just use the raw
+ * attribute on a msg element.
+ *
+ * Example:
+ * // Messages: { 'hello': '<b><i>Hello</i> $1!</b>' }
+ * var html = '\
+ * <p>\
+ * <!-- escaped: --><html:msg key="hello" />\
+ * <!-- raw: --><html:msg key="hello" raw />\
+ * </p>';
+ * $( 'body' ).append( $( html ).localize( { 'params': { 'hello': ['world'] } } ) );
+ *
+ * Appends something like this to the body...
+ * <p>
+ * <!-- escaped: -->&lt;b&gt;&lt;i&gt;Hello&lt;/i&gt; world!&lt;/b&gt;
+ * <!-- raw: --><b><i>Hello</i> world!</b>
+ * </p>
+ *
+ * Message keys can also be remapped, allowing the same generic template to be used with a variety
+ * of messages. This is important for improving re-usability of templates.
+ *
+ * Example:
+ * // Messages: { 'good-afternoon': 'Good afternoon' }
+ * var html = '<p><html:msg key="greeting" /></p>';
+ * $( 'body' ).append( $( html ).localize( { 'keys': { 'greeting': 'good-afternoon' } } ) );
+ *
+ * Appends something like this to the body...
+ * <p>Good afternoon</p>
+ *
+ * Message keys can also be prefixed globally, which is handy when writing extensions, where by
+ * convention all messages are prefixed with the extension's name.
+ *
+ * Example:
+ * // Messages: { 'teleportation-warning': 'You may not get there all in one piece.' }
+ * var html = '<p><html:msg key="warning" /></p>';
+ * $( 'body' ).append( $( html ).localize( { 'prefix': 'teleportation-' } ) );
+ *
+ * Appends something like this to the body...
+ * <p>You may not get there all in one piece.</p>
+ *
+ * @param {Object} options Map of options to be used while localizing
+ * @param {string} options.prefix String to prepend to all message keys
+ * @param {Object} options.keys Message key aliases, used for remapping keys to a template
+ * @param {Object} options.params Lists of parameters to use with certain message keys
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.localize = function ( options ) {
+ var $target = this,
+ attributes = [ 'title', 'alt', 'placeholder' ];
+
+ // Extend options
+ options = $.extend( {
+ prefix: '',
+ keys: {},
+ params: {}
+ }, options );
+
+ // Elements
+ // Ok, so here's the story on this selector. In IE 6/7, searching for 'msg' turns up the
+ // 'html:msg', but searching for 'html:msg' doesn't. In later IE and other browsers, searching
+ // for 'html:msg' turns up the 'html:msg', but searching for 'msg' doesn't. So searching for
+ // both 'msg' and 'html:msg' seems to get the job done. This feels pretty icky, though.
+ $target.find( 'msg,html\\:msg' ).each( function () {
+ var $el = $( this );
+ // Escape by default
+ if ( $el.attr( 'raw' ) ) {
+ $el.html( msg( options, $el.attr( 'key' ) ) );
+ } else {
+ $el.text( msg( options, $el.attr( 'key' ) ) );
+ }
+ // Remove wrapper
+ $el.replaceWith( $el.html() );
+ } );
+
+ // Attributes
+ // Note: there's no way to prevent escaping of values being injected into attributes, this is
+ // on purpose, not a design flaw.
+ $.each( attributes, function ( i, attr ) {
+ var msgAttr = attr + '-msg';
+ $target.find( '[' + msgAttr + ']' ).each( function () {
+ var $el = $( this );
+ $el.attr( attr, msg( options, $el.attr( msgAttr ) ) ).removeAttr( msgAttr );
+ } );
+ } );
+
+ // HTML, Text for elements which cannot have children e.g. OPTION
+ $target.find( '[data-msg-text]' ).each( function () {
+ var $el = $( this );
+ $el.text( msg( options, $el.attr( 'data-msg-text' ) ) );
+ } );
+
+ $target.find( '[data-msg-html]' ).each( function () {
+ var $el = $( this );
+ $el.html( msg( options, $el.attr( 'data-msg-html' ) ) );
+ } );
+
+ return $target;
+ };
+
+ // Let IE know about the msg tag before it's used...
+ document.createElement( 'msg' );
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.localize
+ */
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/jquery/jquery.makeCollapsible.css b/www/wiki/resources/src/jquery/jquery.makeCollapsible.css
new file mode 100644
index 00000000..2e5efbac
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.makeCollapsible.css
@@ -0,0 +1,47 @@
+/* See also jquery.makeCollapsible.js */
+.mw-collapsible-toggle {
+ float: right;
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+/* Align the toggle based on the direction of the content language */
+/* @noflip */
+.mw-content-ltr .mw-collapsible-toggle,
+.mw-content-rtl .mw-content-ltr .mw-collapsible-toggle {
+ float: right;
+}
+/* @noflip */
+.mw-content-rtl .mw-collapsible-toggle,
+.mw-content-ltr .mw-content-rtl .mw-collapsible-toggle {
+ float: left;
+}
+
+.mw-customtoggle,
+.mw-collapsible-toggle {
+ cursor: pointer;
+}
+
+/* collapse links in captions should be inline */
+caption .mw-collapsible-toggle,
+.mw-content-ltr caption .mw-collapsible-toggle,
+.mw-content-rtl caption .mw-collapsible-toggle,
+.mw-content-rtl .mw-content-ltr caption .mw-collapsible-toggle,
+.mw-content-ltr .mw-content-rtl caption .mw-collapsible-toggle {
+ float: none;
+}
+
+/* list-items go as wide as their parent element, don't float them inside list items */
+li .mw-collapsible-toggle,
+.mw-content-ltr li .mw-collapsible-toggle,
+.mw-content-rtl li .mw-collapsible-toggle,
+.mw-content-rtl .mw-content-ltr li .mw-collapsible-toggle,
+.mw-content-ltr .mw-content-rtl li .mw-collapsible-toggle {
+ float: none;
+}
+
+/* the added list item should have no list-style */
+.mw-collapsible-toggle-li {
+ list-style: none;
+}
diff --git a/www/wiki/resources/src/jquery/jquery.makeCollapsible.js b/www/wiki/resources/src/jquery/jquery.makeCollapsible.js
new file mode 100644
index 00000000..aa76d6df
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.makeCollapsible.js
@@ -0,0 +1,424 @@
+/**
+ * jQuery makeCollapsible
+ *
+ * Dual licensed:
+ * - CC BY 3.0 <http://creativecommons.org/licenses/by/3.0>
+ * - GPL2 <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>
+ *
+ * @class jQuery.plugin.makeCollapsible
+ */
+( function ( $, mw ) {
+
+ /**
+ * Handler for a click on a collapsible toggler.
+ *
+ * @private
+ * @param {jQuery} $collapsible
+ * @param {string} action The action this function will take ('expand' or 'collapse').
+ * @param {jQuery|null} [$defaultToggle]
+ * @param {Object|undefined} [options]
+ */
+ function toggleElement( $collapsible, action, $defaultToggle, options ) {
+ var $collapsibleContent, $containers, hookCallback;
+ options = options || {};
+
+ // Validate parameters
+
+ // $collapsible must be an instance of jQuery
+ if ( !$collapsible.jquery ) {
+ return;
+ }
+ if ( action !== 'expand' && action !== 'collapse' ) {
+ // action must be string with 'expand' or 'collapse'
+ return;
+ }
+ if ( $defaultToggle === undefined ) {
+ $defaultToggle = null;
+ }
+
+ // Trigger a custom event to allow callers to hook to the collapsing/expanding,
+ // allowing the module to be testable, and making it possible to
+ // e.g. implement persistence via cookies
+ $collapsible.trigger( action === 'expand' ? 'beforeExpand.mw-collapsible' : 'beforeCollapse.mw-collapsible' );
+ hookCallback = function () {
+ $collapsible.trigger( action === 'expand' ? 'afterExpand.mw-collapsible' : 'afterCollapse.mw-collapsible' );
+ };
+
+ // Handle different kinds of elements
+
+ if ( !options.plainMode && $collapsible.is( 'table' ) ) {
+ // Tables
+ // If there is a caption, hide all rows; otherwise, only hide body rows
+ if ( $collapsible.find( '> caption' ).length ) {
+ $containers = $collapsible.find( '> * > tr' );
+ } else {
+ $containers = $collapsible.find( '> tbody > tr' );
+ }
+ if ( $defaultToggle ) {
+ // Exclude table row containing togglelink
+ $containers = $containers.not( $defaultToggle.closest( 'tr' ) );
+ }
+
+ if ( action === 'collapse' ) {
+ // Hide all table rows of this table
+ // Slide doesn't work with tables, but fade does as of jQuery 1.1.3
+ // http://stackoverflow.com/questions/467336#920480
+ if ( options.instantHide ) {
+ $containers.hide();
+ hookCallback();
+ } else {
+ $containers.stop( true, true ).fadeOut().promise().done( hookCallback );
+ }
+ } else {
+ $containers.stop( true, true ).fadeIn().promise().done( hookCallback );
+ }
+
+ } else if ( !options.plainMode && ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) ) {
+ // Lists
+ $containers = $collapsible.find( '> li' );
+ if ( $defaultToggle ) {
+ // Exclude list-item containing togglelink
+ $containers = $containers.not( $defaultToggle.parent() );
+ }
+
+ if ( action === 'collapse' ) {
+ if ( options.instantHide ) {
+ $containers.hide();
+ hookCallback();
+ } else {
+ $containers.stop( true, true ).slideUp().promise().done( hookCallback );
+ }
+ } else {
+ $containers.stop( true, true ).slideDown().promise().done( hookCallback );
+ }
+
+ } else {
+ // Everything else: <div>, <p> etc.
+ $collapsibleContent = $collapsible.find( '> .mw-collapsible-content' );
+
+ // If a collapsible-content is defined, act on it
+ if ( !options.plainMode && $collapsibleContent.length ) {
+ if ( action === 'collapse' ) {
+ if ( options.instantHide ) {
+ $collapsibleContent.hide();
+ hookCallback();
+ } else {
+ $collapsibleContent.slideUp().promise().done( hookCallback );
+ }
+ } else {
+ $collapsibleContent.slideDown().promise().done( hookCallback );
+ }
+
+ // Otherwise assume this is a customcollapse with a remote toggle
+ // .. and there is no collapsible-content because the entire element should be toggled
+ } else {
+ if ( action === 'collapse' ) {
+ if ( options.instantHide ) {
+ $collapsible.hide();
+ hookCallback();
+ } else {
+ if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
+ $collapsible.fadeOut().promise().done( hookCallback );
+ } else {
+ $collapsible.slideUp().promise().done( hookCallback );
+ }
+ }
+ } else {
+ if ( $collapsible.is( 'tr' ) || $collapsible.is( 'td' ) || $collapsible.is( 'th' ) ) {
+ $collapsible.fadeIn().promise().done( hookCallback );
+ } else {
+ $collapsible.slideDown().promise().done( hookCallback );
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Handle clicking/keypressing on the collapsible element toggle and other
+ * situations where a collapsible element is toggled (e.g. the initial
+ * toggle for collapsed ones).
+ *
+ * @private
+ * @param {jQuery} $toggle the clickable toggle itself
+ * @param {jQuery} $collapsible the collapsible element
+ * @param {jQuery.Event|null} e either the event or null if unavailable
+ * @param {Object|undefined} options
+ */
+ function togglingHandler( $toggle, $collapsible, e, options ) {
+ var wasCollapsed, $textContainer, collapseText, expandText;
+ options = options || {};
+
+ if ( e ) {
+ if (
+ e.type === 'click' &&
+ e.target.nodeName.toLowerCase() === 'a' &&
+ $( e.target ).attr( 'href' )
+ ) {
+ // Don't fire if a link was clicked (for premade togglers)
+ return;
+ } else if ( e.type === 'keypress' && e.which !== 13 && e.which !== 32 ) {
+ // Only handle keypresses on the "Enter" or "Space" keys
+ return;
+ } else {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }
+
+ // This allows the element to be hidden on initial toggle without fiddling with the class
+ if ( options.wasCollapsed !== undefined ) {
+ wasCollapsed = options.wasCollapsed;
+ } else {
+ wasCollapsed = $collapsible.hasClass( 'mw-collapsed' );
+ }
+
+ // Toggle the state of the collapsible element (that is, expand or collapse)
+ $collapsible.toggleClass( 'mw-collapsed', !wasCollapsed );
+
+ // Toggle the mw-collapsible-toggle classes, if requested (for default and premade togglers by default)
+ if ( options.toggleClasses ) {
+ $toggle
+ .toggleClass( 'mw-collapsible-toggle-collapsed', !wasCollapsed )
+ .toggleClass( 'mw-collapsible-toggle-expanded', wasCollapsed );
+ }
+
+ // Toggle the text ("Show"/"Hide") within elements tagged with mw-collapsible-text
+ if ( options.toggleText ) {
+ collapseText = options.toggleText.collapseText;
+ expandText = options.toggleText.expandText;
+
+ $textContainer = $collapsible.find( '.mw-collapsible-text' );
+ if ( $textContainer.length ) {
+ $textContainer.text( wasCollapsed ? collapseText : expandText );
+ }
+ }
+
+ // And finally toggle the element state itself
+ toggleElement( $collapsible, wasCollapsed ? 'expand' : 'collapse', $toggle, options );
+ }
+
+ /**
+ * Enable collapsible-functionality on all elements in the collection.
+ *
+ * - Will prevent binding twice to the same element.
+ * - Initial state is expanded by default, this can be overridden by adding class
+ * "mw-collapsed" to the "mw-collapsible" element.
+ * - Elements made collapsible have jQuery data "mw-made-collapsible" set to true.
+ * - The inner content is wrapped in a "div.mw-collapsible-content" (except for tables and lists).
+ *
+ * @param {Object} [options]
+ * @param {string} [options.collapseText] Text used for the toggler, when clicking it would
+ * collapse the element. Default: the 'data-collapsetext' attribute of the
+ * collapsible element or the content of 'collapsible-collapse' message.
+ * @param {string} [options.expandText] Text used for the toggler, when clicking it would
+ * expand the element. Default: the 'data-expandtext' attribute of the
+ * collapsible element or the content of 'collapsible-expand' message.
+ * @param {boolean} [options.collapsed] Whether to collapse immediately. By default
+ * collapse only if the elements has the 'mw-collapsible' class.
+ * @param {jQuery} [options.$customTogglers] Elements to be used as togglers
+ * for this collapsible element. By default, if the collapsible element
+ * has an id attribute like 'mw-customcollapsible-XXX', elements with a
+ * *class* of 'mw-customtoggle-XXX' are made togglers for it.
+ * @param {boolean} [options.plainMode=false] Whether to use a "plain mode" when making the
+ * element collapsible - that is, hide entire tables and lists (instead
+ * of hiding only all rows but first of tables, and hiding each list
+ * item separately for lists) and don't wrap other elements in
+ * div.mw-collapsible-content. May only be used with custom togglers.
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.makeCollapsible = function ( options ) {
+ options = options || {};
+
+ this.each( function () {
+ var $collapsible, collapseText, expandText, $caption, $toggle, actionHandler, buildDefaultToggleLink,
+ $toggleLink, $firstItem, collapsibleId, $customTogglers, firstval;
+
+ // Ensure class "mw-collapsible" is present in case .makeCollapsible()
+ // is called on element(s) that don't have it yet.
+ $collapsible = $( this ).addClass( 'mw-collapsible' );
+
+ // Return if it has been enabled already.
+ if ( $collapsible.data( 'mw-made-collapsible' ) ) {
+ return;
+ } else {
+ $collapsible.data( 'mw-made-collapsible', true );
+ }
+
+ // Use custom text or default?
+ collapseText = options.collapseText || $collapsible.attr( 'data-collapsetext' ) || mw.msg( 'collapsible-collapse' );
+ expandText = options.expandText || $collapsible.attr( 'data-expandtext' ) || mw.msg( 'collapsible-expand' );
+
+ // Default click/keypress handler and toggle link to use when none is present
+ actionHandler = function ( e, opts ) {
+ var defaultOpts = {
+ toggleClasses: true,
+ toggleText: { collapseText: collapseText, expandText: expandText }
+ };
+ opts = $.extend( defaultOpts, options, opts );
+ togglingHandler( $( this ), $collapsible, e, opts );
+ };
+
+ // Default toggle link. Only build it when needed to avoid jQuery memory leaks (event data).
+ buildDefaultToggleLink = function () {
+ return $( '<a class="mw-collapsible-text"></a>' )
+ .text( collapseText )
+ .wrap( '<span class="mw-collapsible-toggle"></span>' )
+ .parent()
+ .attr( {
+ role: 'button',
+ tabindex: 0
+ } )
+ .prepend( '<span>[</span>' )
+ .append( '<span>]</span>' )
+ .on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler );
+ };
+
+ // Check if this element has a custom position for the toggle link
+ // (ie. outside the container or deeper inside the tree)
+ if ( options.$customTogglers ) {
+ $customTogglers = $( options.$customTogglers );
+ } else {
+ collapsibleId = $collapsible.attr( 'id' ) || '';
+ if ( collapsibleId.indexOf( 'mw-customcollapsible-' ) === 0 ) {
+ $customTogglers = $( '.' + collapsibleId.replace( 'mw-customcollapsible', 'mw-customtoggle' ) )
+ .addClass( 'mw-customtoggle' );
+ }
+ }
+
+ // Add event handlers to custom togglers or create our own ones
+ if ( $customTogglers && $customTogglers.length ) {
+ actionHandler = function ( e, opts ) {
+ var defaultOpts = {};
+ opts = $.extend( defaultOpts, options, opts );
+ togglingHandler( $( this ), $collapsible, e, opts );
+ };
+
+ $toggleLink = $customTogglers
+ .on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+ .prop( 'tabIndex', 0 );
+
+ } else {
+ // If this is not a custom case, do the default: wrap the
+ // contents and add the toggle link. Different elements are
+ // treated differently.
+
+ if ( $collapsible.is( 'table' ) ) {
+
+ // If the table has a caption, collapse to the caption
+ // as opposed to the first row
+ $caption = $collapsible.find( '> caption' );
+ if ( $caption.length ) {
+ $toggle = $caption.find( '> .mw-collapsible-toggle' );
+
+ // If there is no toggle link, add it to the end of the caption
+ if ( !$toggle.length ) {
+ $toggleLink = buildDefaultToggleLink().appendTo( $caption );
+ } else {
+ $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+ .prop( 'tabIndex', 0 );
+ }
+ } else {
+ // The toggle-link will be in one of the cells (td or th) of the first row
+ $firstItem = $collapsible.find( 'tr:first th, tr:first td' );
+ $toggle = $firstItem.find( '> .mw-collapsible-toggle' );
+
+ // If theres no toggle link, add it to the last cell
+ if ( !$toggle.length ) {
+ $toggleLink = buildDefaultToggleLink().prependTo( $firstItem.eq( -1 ) );
+ } else {
+ $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+ .prop( 'tabIndex', 0 );
+ }
+ }
+
+ } else if ( $collapsible.parent().is( 'li' ) &&
+ $collapsible.parent().children( '.mw-collapsible' ).length === 1 &&
+ $collapsible.find( '> .mw-collapsible-toggle' ).length === 0
+ ) {
+ // special case of one collapsible in <li> tag
+ $toggleLink = buildDefaultToggleLink();
+ $collapsible.before( $toggleLink );
+ } else if ( $collapsible.is( 'ul' ) || $collapsible.is( 'ol' ) ) {
+ // The toggle-link will be in the first list-item
+ $firstItem = $collapsible.find( 'li:first' );
+ $toggle = $firstItem.find( '> .mw-collapsible-toggle' );
+
+ // If theres no toggle link, add it
+ if ( !$toggle.length ) {
+ // Make sure the numeral order doesn't get messed up, force the first (soon to be second) item
+ // to be "1". Except if the value-attribute is already used.
+ // If no value was set WebKit returns "", Mozilla returns '-1', others return 0, null or undefined.
+ firstval = $firstItem.prop( 'value' );
+ if ( firstval === undefined || !firstval || firstval === '-1' || firstval === -1 ) {
+ $firstItem.prop( 'value', '1' );
+ }
+ $toggleLink = buildDefaultToggleLink();
+ $toggleLink.wrap( '<li class="mw-collapsible-toggle-li"></li>' ).parent().prependTo( $collapsible );
+ } else {
+ $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+ .prop( 'tabIndex', 0 );
+ }
+
+ } else { // <div>, <p> etc.
+
+ // The toggle-link will be the first child of the element
+ $toggle = $collapsible.find( '> .mw-collapsible-toggle' );
+
+ // If a direct child .content-wrapper does not exists, create it
+ if ( !$collapsible.find( '> .mw-collapsible-content' ).length ) {
+ $collapsible.wrapInner( '<div class="mw-collapsible-content"></div>' );
+ }
+
+ // If theres no toggle link, add it
+ if ( !$toggle.length ) {
+ $toggleLink = buildDefaultToggleLink().prependTo( $collapsible );
+ } else {
+ $toggleLink = $toggle.on( 'click.mw-collapsible keypress.mw-collapsible', actionHandler )
+ .prop( 'tabIndex', 0 );
+ }
+ }
+ }
+
+ $( this ).data( 'mw-collapsible', {
+ collapse: function () {
+ actionHandler.call( $toggleLink.get( 0 ), null, { instantHide: true, wasCollapsed: false } );
+ },
+ expand: function () {
+ actionHandler.call( $toggleLink.get( 0 ), null, { instantHide: true, wasCollapsed: true } );
+ },
+ toggle: function () {
+ actionHandler.call( $toggleLink.get( 0 ), null, null );
+ }
+ } );
+
+ // Initial state
+ if ( options.collapsed || $collapsible.hasClass( 'mw-collapsed' ) ) {
+ // One toggler can hook to multiple elements, and one element can have
+ // multiple togglers. This is the sanest way to handle that.
+ actionHandler.call( $toggleLink.get( 0 ), null, { instantHide: true, wasCollapsed: false } );
+ }
+
+ } );
+
+ /**
+ * Fired after collapsible content has been initialized
+ *
+ * This gives an option to modify the collapsible behavior.
+ *
+ * @event wikipage_collapsibleContent
+ * @member mw.hook
+ * @param {jQuery} $content All the elements that have been made collapsible
+ */
+ mw.hook( 'wikipage.collapsibleContent' ).fire( this );
+
+ return this;
+ };
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.makeCollapsible
+ */
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/jquery/jquery.mw-jump.js b/www/wiki/resources/src/jquery/jquery.mw-jump.js
new file mode 100644
index 00000000..5eae0bec
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.mw-jump.js
@@ -0,0 +1,15 @@
+/**
+ * JavaScript to show jump links to motor-impaired users when they are focused.
+ */
+jQuery( function ( $ ) {
+
+ $( '.mw-jump' ).on( 'focus blur', 'a', function ( e ) {
+ // Confusingly jQuery leaves e.type as focusout for delegated blur events
+ if ( e.type === 'blur' || e.type === 'focusout' ) {
+ $( this ).closest( '.mw-jump' ).css( { height: 0 } );
+ } else {
+ $( this ).closest( '.mw-jump' ).css( { height: 'auto' } );
+ }
+ } );
+
+} );
diff --git a/www/wiki/resources/src/jquery/jquery.mwExtension.js b/www/wiki/resources/src/jquery/jquery.mwExtension.js
new file mode 100644
index 00000000..27ceb2bc
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.mwExtension.js
@@ -0,0 +1,127 @@
+/*
+ * JavaScript backwards-compatibility alternatives and other convenience functions
+ *
+ * @deprecated since 1.26 Dated collection of miscellaneous utilities. Methods are
+ * either trivially inline, obsolete, or have a better place elsewhere.
+ */
+( function ( $, mw ) {
+ $.each( {
+ trimLeft: function ( str ) {
+ return str === null ? '' : str.toString().replace( /^\s+/, '' );
+ },
+ trimRight: function ( str ) {
+ return str === null ?
+ '' : str.toString().replace( /\s+$/, '' );
+ },
+ ucFirst: function ( str ) {
+ return str.charAt( 0 ).toUpperCase() + str.slice( 1 );
+ },
+ isDomElement: function ( el ) {
+ return !!el && !!el.nodeType;
+ },
+ isEmpty: function ( v ) {
+ var key;
+ if (
+ v === '' || v === 0 || v === '0' || v === null || v === false || v === undefined
+ ) {
+ return true;
+ }
+ // the for-loop could potentially contain prototypes
+ // to avoid that we check its length first
+ if ( v.length === 0 ) {
+ return true;
+ }
+ if ( typeof v === 'object' ) {
+ for ( key in v ) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ },
+ compareArray: function ( arrThis, arrAgainst ) {
+ if ( arrThis.length !== arrAgainst.length ) {
+ return false;
+ }
+ for ( var i = 0; i < arrThis.length; i++ ) {
+ if ( $.isArray( arrThis[ i ] ) ) {
+ if ( !$.compareArray( arrThis[ i ], arrAgainst[ i ] ) ) {
+ return false;
+ }
+ } else if ( arrThis[ i ] !== arrAgainst[ i ] ) {
+ return false;
+ }
+ }
+ return true;
+ },
+ compareObject: function ( objectA, objectB ) {
+ var prop, type;
+
+ // Do a simple check if the types match
+ if ( typeof objectA === typeof objectB ) {
+
+ // Only loop over the contents if it really is an object
+ if ( typeof objectA === 'object' ) {
+ // If they are aliases of the same object (ie. mw and mediaWiki) return now
+ if ( objectA === objectB ) {
+ return true;
+ } else {
+ // Iterate over each property
+ for ( prop in objectA ) {
+ // Check if this property is also present in the other object
+ if ( prop in objectB ) {
+ // Compare the types of the properties
+ type = typeof objectA[ prop ];
+ if ( type === typeof objectB[ prop ] ) {
+ // Recursively check objects inside this one
+ switch ( type ) {
+ case 'object' :
+ if ( !$.compareObject( objectA[ prop ], objectB[ prop ] ) ) {
+ return false;
+ }
+ break;
+ case 'function' :
+ // Functions need to be strings to compare them properly
+ if ( objectA[ prop ].toString() !== objectB[ prop ].toString() ) {
+ return false;
+ }
+ break;
+ default:
+ // Strings, numbers
+ if ( objectA[ prop ] !== objectB[ prop ] ) {
+ return false;
+ }
+ break;
+ }
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+ // Check for properties in B but not in A
+ // This is about 15% faster (tested in Safari 5 and Firefox 3.6)
+ // ...than incrementing a count variable in the above and below loops
+ // See also: https://www.mediawiki.org/wiki/ResourceLoader/Default_modules/compareObject_test#Results
+ for ( prop in objectB ) {
+ if ( !( prop in objectA ) ) {
+ return false;
+ }
+ }
+ }
+ }
+ } else {
+ return false;
+ }
+ return true;
+ }
+ }, function ( key, value ) {
+ mw.log.deprecate( $, key, value );
+ } );
+
+ mw.log.deprecate( $, 'escapeRE', function ( str ) {
+ return str.replace( /([\\{}()|.?*+\-\^$\[\]])/g, '\\$1' );
+ }, 'Use mediawiki.RegExp instead.' );
+
+} )( jQuery, mediaWiki );
diff --git a/www/wiki/resources/src/jquery/jquery.placeholder.js b/www/wiki/resources/src/jquery/jquery.placeholder.js
new file mode 100644
index 00000000..afb8837f
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.placeholder.js
@@ -0,0 +1,18 @@
+/*!
+ * No-op for compatibility with code from before we used
+ * native placeholder in all supported browsers.
+ */
+
+( function ( $ ) {
+ var placeholder;
+
+ placeholder = $.fn.placeholder = function ( text ) {
+ if ( arguments.length ) {
+ this.prop( 'placeholder', text );
+ }
+ return this;
+ };
+
+ placeholder.input = placeholder.textarea = true;
+
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.qunit.completenessTest.js b/www/wiki/resources/src/jquery/jquery.qunit.completenessTest.js
new file mode 100644
index 00000000..8d263fbf
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.qunit.completenessTest.js
@@ -0,0 +1,309 @@
+/**
+ * jQuery QUnit CompletenessTest 0.4
+ *
+ * Tests the completeness of test suites for object oriented javascript
+ * libraries. Written to be used in environments with jQuery and QUnit.
+ * Requires jQuery 1.7.2 or higher.
+ *
+ * Built for and tested with:
+ * - Chrome 19
+ * - Firefox 4
+ * - Safari 5
+ *
+ * @author Timo Tijhof, 2011-2012
+ */
+( function ( mw, $ ) {
+ 'use strict';
+
+ var util,
+ hasOwn = Object.prototype.hasOwnProperty,
+ log = ( window.console && window.console.log )
+ ? function () { return window.console.log.apply( window.console, arguments ); }
+ : function () {};
+
+ // Simplified version of a few jQuery methods, except that they don't
+ // call other jQuery methods. Required to be able to run the CompletenessTest
+ // on jQuery itself as well.
+ util = {
+ keys: Object.keys || function ( object ) {
+ var key, keys = [];
+ for ( key in object ) {
+ if ( hasOwn.call( object, key ) ) {
+ keys.push( key );
+ }
+ }
+ return keys;
+ },
+ each: function ( object, callback ) {
+ var name;
+ for ( name in object ) {
+ if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
+ break;
+ }
+ }
+ },
+ // $.type and $.isEmptyObject are safe as is, they don't call
+ // other $.* methods. Still need to be derefenced into `util`
+ // since the CompletenessTest will overload them with spies.
+ type: $.type,
+ isEmptyObject: $.isEmptyObject
+ };
+
+ /**
+ * CompletenessTest
+ *
+ * @constructor
+ * @example
+ * var myTester = new CompletenessTest( myLib );
+ * @param {Object} masterVariable The root variable that contains all object
+ * members. CompletenessTest will recursively traverse objects and keep track
+ * of all methods.
+ * @param {Function} [ignoreFn] Optionally pass a function to filter out certain
+ * methods. Example: You may want to filter out instances of jQuery or some
+ * other constructor. Otherwise "missingTests" will include all methods that
+ * were not called from that instance.
+ */
+ function CompletenessTest( masterVariable, ignoreFn ) {
+ var warn,
+ that = this;
+
+ // Keep track in these objects. Keyed by strings with the
+ // method names (ie. 'my.foo', 'my.bar', etc.) values are boolean true.
+ this.injectionTracker = {};
+ this.methodCallTracker = {};
+ this.missingTests = {};
+
+ this.ignoreFn = ignoreFn === undefined ? function () { return false; } : ignoreFn;
+
+ // Lazy limit in case something weird happends (like recurse (part of) ourself).
+ this.lazyLimit = 2000;
+ this.lazyCounter = 0;
+
+ // Bind begin and end to QUnit.
+ QUnit.begin( function () {
+ // Suppress warnings (e.g. deprecation notices for accessing the properties)
+ warn = mw.log.warn;
+ mw.log.warn = $.noop;
+
+ that.walkTheObject( masterVariable, null, masterVariable, [] );
+ log( 'CompletenessTest/walkTheObject', that );
+
+ // Restore warnings
+ mw.log.warn = warn;
+ warn = undefined;
+ } );
+
+ QUnit.done( function () {
+ that.populateMissingTests();
+ log( 'CompletenessTest/populateMissingTests', that );
+
+ var toolbar, testResults, cntTotal, cntCalled, cntMissing;
+
+ cntTotal = util.keys( that.injectionTracker ).length;
+ cntCalled = util.keys( that.methodCallTracker ).length;
+ cntMissing = util.keys( that.missingTests ).length;
+
+ function makeTestResults( blob, title, style ) {
+ var elOutputWrapper, elTitle, elContainer, elList, elFoot;
+
+ elTitle = document.createElement( 'strong' );
+ elTitle.textContent = title || 'Values';
+
+ elList = document.createElement( 'ul' );
+ util.each( blob, function ( key ) {
+ var elItem = document.createElement( 'li' );
+ elItem.textContent = key;
+ elList.appendChild( elItem );
+ } );
+
+ elFoot = document.createElement( 'p' );
+ elFoot.innerHTML = '<em>&mdash; CompletenessTest</em>';
+
+ elContainer = document.createElement( 'div' );
+ elContainer.appendChild( elTitle );
+ elContainer.appendChild( elList );
+ elContainer.appendChild( elFoot );
+
+ elOutputWrapper = document.getElementById( 'qunit-completenesstest' );
+ if ( !elOutputWrapper ) {
+ elOutputWrapper = document.createElement( 'div' );
+ elOutputWrapper.id = 'qunit-completenesstest';
+ }
+ elOutputWrapper.appendChild( elContainer );
+
+ util.each( style, function ( key, value ) {
+ elOutputWrapper.style[ key ] = value;
+ } );
+ return elOutputWrapper;
+ }
+
+ if ( cntMissing === 0 ) {
+ // Good
+ testResults = makeTestResults(
+ {},
+ 'Detected calls to ' + cntCalled + '/' + cntTotal + ' methods. No missing tests!',
+ {
+ backgroundColor: '#D2E0E6',
+ color: '#366097',
+ paddingTop: '1em',
+ paddingRight: '1em',
+ paddingBottom: '1em',
+ paddingLeft: '1em'
+ }
+ );
+ } else {
+ // Bad
+ testResults = makeTestResults(
+ that.missingTests,
+ 'Detected calls to ' + cntCalled + '/' + cntTotal + ' methods. ' + cntMissing + ' methods not covered:',
+ {
+ backgroundColor: '#EE5757',
+ color: 'black',
+ paddingTop: '1em',
+ paddingRight: '1em',
+ paddingBottom: '1em',
+ paddingLeft: '1em'
+ }
+ );
+ }
+
+ toolbar = document.getElementById( 'qunit-testrunner-toolbar' );
+ if ( toolbar ) {
+ toolbar.insertBefore( testResults, toolbar.firstChild );
+ }
+ } );
+
+ return this;
+ }
+
+ /* Public methods */
+ CompletenessTest.fn = CompletenessTest.prototype = {
+
+ /**
+ * CompletenessTest.fn.walkTheObject
+ *
+ * This function recursively walks through the given object, calling itself as it goes.
+ * Depending on the action it either injects our listener into the methods, or
+ * reads from our tracker and records which methods have not been called by the test suite.
+ *
+ * @param {Mixed} currObj The variable to check (initially an object,
+ * further down it could be anything).
+ * @param {string|null} currName Name of the given object member (Initially this is null).
+ * @param {Object} masterVariable Throughout our interation, always keep track of the master/root.
+ * Initially this is the same as currVar.
+ * @param {Array} parentPathArray Array of names that indicate our breadcrumb path starting at
+ * masterVariable. Not including currName.
+ */
+ walkTheObject: function ( currObj, currName, masterVariable, parentPathArray ) {
+ var key, currVal, type,
+ ct = this,
+ currPathArray = parentPathArray;
+
+ if ( currName ) {
+ currPathArray.push( currName );
+ currVal = currObj[ currName ];
+ } else {
+ currName = '(root)';
+ currVal = currObj;
+ }
+
+ type = util.type( currVal );
+
+ // Hard ignores
+ if ( this.ignoreFn( currVal, this, currPathArray ) ) {
+ return null;
+ }
+
+ // Handle the lazy limit
+ this.lazyCounter++;
+ if ( this.lazyCounter > this.lazyLimit ) {
+ log( 'CompletenessTest.fn.walkTheObject> Limit reached: ' + this.lazyCounter, currPathArray );
+ return null;
+ }
+
+ // Functions
+ if ( type === 'function' ) {
+ // Don't put a spy in constructor functions as it messes with
+ // instanceof etc.
+ if ( !currVal.prototype || util.isEmptyObject( currVal.prototype ) ) {
+ this.injectionTracker[ currPathArray.join( '.' ) ] = true;
+ this.injectCheck( currObj, currName, function () {
+ ct.methodCallTracker[ currPathArray.join( '.' ) ] = true;
+ } );
+ }
+ }
+
+ // Recursively. After all, this is the *completeness* test
+ // This also traverses static properties and the prototype of a constructor
+ if ( type === 'object' || type === 'function' ) {
+ for ( key in currVal ) {
+ if ( hasOwn.call( currVal, key ) ) {
+ this.walkTheObject( currVal, key, masterVariable, currPathArray.slice() );
+ }
+ }
+ }
+ },
+
+ populateMissingTests: function () {
+ var ct = this;
+ util.each( ct.injectionTracker, function ( key ) {
+ ct.hasTest( key );
+ } );
+ },
+
+ /**
+ * CompletenessTest.fn.hasTest
+ *
+ * Checks if the given method name (ie. 'my.foo.bar')
+ * was called during the test suite (as far as the tracker knows).
+ * If not it adds it to missingTests.
+ *
+ * @param {string} fnName
+ * @return {boolean}
+ */
+ hasTest: function ( fnName ) {
+ if ( !( fnName in this.methodCallTracker ) ) {
+ this.missingTests[ fnName ] = true;
+ return false;
+ }
+ return true;
+ },
+
+ /**
+ * CompletenessTest.fn.injectCheck
+ *
+ * Injects a function (such as a spy that updates methodCallTracker when
+ * it's called) inside another function.
+ *
+ * @param {Object} obj The object into which `injectFn` will be inserted
+ * @param {Array} key The key by which `injectFn` will be known in `obj`; if this already
+ * exists, a wrapper will first call `injectFn` and then the original `obj[key]` function.
+ * @param {Function} injectFn The function to insert
+ */
+ injectCheck: function ( obj, key, injectFn ) {
+ var spy,
+ val = obj[ key ];
+
+ spy = function () {
+ injectFn();
+ return val.apply( this, arguments );
+ };
+
+ // Make the spy inherit from the original so that its static methods are also
+ // visible in the spy (e.g. when we inject a check into mw.log, mw.log.warn
+ // must remain accessible).
+ // XXX: https://github.com/jshint/jshint/issues/2656
+ /*jshint ignore:start */
+ /*jshint proto:true */
+ spy.__proto__ = val;
+ /*jshint ignore:end */
+
+ // Objects are by reference, members (unless objects) are not.
+ obj[ key ] = spy;
+ }
+ };
+
+ /* Expose */
+ window.CompletenessTest = CompletenessTest;
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.spinner.css b/www/wiki/resources/src/jquery/jquery.spinner.css
new file mode 100644
index 00000000..6c7bd0e6
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.spinner.css
@@ -0,0 +1,40 @@
+.mw-spinner {
+ background-color: transparent;
+ background-position: center center;
+ background-repeat: no-repeat;
+}
+
+.mw-spinner-small {
+ /* @embed */
+ background-image: url( images/spinner.gif );
+ height: 20px;
+ width: 20px;
+ /* Avoid issues with .mw-spinner-block when floated without width. */
+ min-width: 20px;
+}
+
+.mw-spinner-large {
+ /* @embed */
+ background-image: url( images/spinner-large.gif );
+ height: 32px;
+ width: 32px;
+ /* Avoid issues with .mw-spinner-block when floated without width. */
+ min-width: 32px;
+}
+
+.mw-spinner-block {
+ display: block;
+ /* This overrides width from .mw-spinner-large / .mw-spinner-small,
+ * This is where the min-width kicks in.
+ */
+ width: 100%;
+}
+
+.mw-spinner-inline {
+ display: inline-block;
+ vertical-align: middle;
+
+ /* IE < 8 */
+ zoom: 1;
+ *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */
+}
diff --git a/www/wiki/resources/src/jquery/jquery.spinner.js b/www/wiki/resources/src/jquery/jquery.spinner.js
new file mode 100644
index 00000000..9079cc09
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.spinner.js
@@ -0,0 +1,114 @@
+/**
+ * jQuery Spinner
+ *
+ * Simple jQuery plugin to create, inject and remove spinners.
+ *
+ * @class jQuery.plugin.spinner
+ */
+( function ( $ ) {
+
+ // Default options for new spinners,
+ // stored outside the function to share between calls.
+ var defaults = {
+ id: undefined,
+ size: 'small',
+ type: 'inline'
+ };
+
+ $.extend( {
+ /**
+ * Create a spinner element
+ *
+ * The argument is an object with options used to construct the spinner (see below).
+ *
+ * It is a good practice to keep a reference to the created spinner to be able to remove it
+ * later. Alternatively, one can use the 'id' option and #removeSpinner (but make sure to choose
+ * an id that's unlikely to cause conflicts, e.g. with extensions, gadgets or user scripts).
+ *
+ * CSS classes used:
+ *
+ * - .mw-spinner for every spinner
+ * - .mw-spinner-small / .mw-spinner-large for size
+ * - .mw-spinner-block / .mw-spinner-inline for display types
+ *
+ * Example:
+ *
+ * // Create a large spinner reserving all available horizontal space.
+ * var $spinner = $.createSpinner( { size: 'large', type: 'block' } );
+ * // Insert above page content.
+ * $( '#mw-content-text' ).prepend( $spinner );
+ *
+ * // Place a small inline spinner next to the "Save" button
+ * var $spinner = $.createSpinner( { size: 'small', type: 'inline' } );
+ * // Alternatively, just `$.createSpinner();` as these are the default options.
+ * $( '#wpSave' ).after( $spinner );
+ *
+ * // The following two are equivalent:
+ * $.createSpinner( 'magic' );
+ * $.createSpinner( { id: 'magic' } );
+ *
+ * @static
+ * @inheritable
+ * @param {Object|string} [opts] Options. If a string is given, it will be treated as the value
+ * of the `id` option. If an object is given, the possible option keys are:
+ * @param {string} [opts.id] If given, spinner will be given an id of "mw-spinner-{id}".
+ * @param {string} [opts.size='small'] 'small' or 'large' for a 20-pixel or 32-pixel spinner.
+ * @param {string} [opts.type='inline'] 'inline' or 'block'. Inline creates an inline-block with
+ * width and height equal to spinner size. Block is a block-level element with width 100%,
+ * height equal to spinner size.
+ * @return {jQuery}
+ */
+ createSpinner: function ( opts ) {
+ var $spinner;
+
+ if ( opts !== undefined && $.type( opts ) !== 'object' ) {
+ opts = {
+ id: opts
+ };
+ }
+
+ opts = $.extend( {}, defaults, opts );
+
+ $spinner = $( '<div>' ).addClass( 'mw-spinner' ).attr( 'title', '...' );
+ if ( opts.id !== undefined ) {
+ $spinner.attr( 'id', 'mw-spinner-' + opts.id );
+ }
+
+ $spinner.addClass( opts.size === 'large' ? 'mw-spinner-large' : 'mw-spinner-small' );
+ $spinner.addClass( opts.type === 'block' ? 'mw-spinner-block' : 'mw-spinner-inline' );
+
+ return $spinner;
+ },
+
+ /**
+ * Remove a spinner element
+ *
+ * @static
+ * @inheritable
+ * @param {string} id Id of the spinner, as passed to #createSpinner
+ * @return {jQuery} The (now detached) spinner element
+ */
+ removeSpinner: function ( id ) {
+ return $( '#mw-spinner-' + id ).remove();
+ }
+ } );
+
+ /**
+ * Inject a spinner after each element in the collection
+ *
+ * Inserts spinner as siblings (not children) of the target elements.
+ * Collection contents remain unchanged.
+ *
+ * @param {Object|string} [opts] See #createSpinner
+ * @return {jQuery}
+ */
+ $.fn.injectSpinner = function ( opts ) {
+ return this.after( $.createSpinner( opts ) );
+ };
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.spinner
+ */
+
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.suggestions.css b/www/wiki/resources/src/jquery/jquery.suggestions.css
new file mode 100644
index 00000000..2cc0cc90
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.suggestions.css
@@ -0,0 +1,75 @@
+/* suggestions plugin */
+
+.suggestions {
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ left: 0;
+ width: 0;
+ border: 0;
+ z-index: 1099;
+ padding: 0;
+ margin: -1px 0 0 0;
+}
+
+.suggestions-special {
+ position: relative;
+ background-color: #fff;
+ cursor: pointer;
+ border: solid 1px #aaa;
+ margin: 0;
+ margin-top: -2px;
+ display: none;
+ padding: 0.25em 0.25em;
+ line-height: 1.25em;
+}
+
+.suggestions-results {
+ background-color: #fff;
+ cursor: pointer;
+ border: solid 1px #aaa;
+ padding: 0;
+ margin: 0;
+}
+
+.suggestions-result {
+ color: #000;
+ margin: 0;
+ line-height: 1.5em;
+ padding: 0.01em 0.25em;
+ text-align: left;
+ /* Apply ellipsis to suggestions */
+ overflow: hidden;
+ -o-text-overflow: ellipsis; /* Opera 9 to 10 */
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.suggestions-result-current {
+ background-color: #4c59a6;
+ color: #fff;
+}
+
+.suggestions-special .special-label {
+ color: #808080;
+ text-align: left;
+}
+
+.suggestions-special .special-query {
+ color: #000;
+ font-style: italic;
+ text-align: left;
+}
+
+.suggestions-special .special-hover {
+ background-color: #c0c0c0;
+}
+
+.suggestions-result-current .special-label,
+.suggestions-result-current .special-query {
+ color: #fff;
+}
+
+.highlight {
+ font-weight: bold;
+}
diff --git a/www/wiki/resources/src/jquery/jquery.suggestions.js b/www/wiki/resources/src/jquery/jquery.suggestions.js
new file mode 100644
index 00000000..4f4edc96
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.suggestions.js
@@ -0,0 +1,787 @@
+/**
+ * This plugin provides a generic way to add suggestions to a text box.
+ *
+ * Set options:
+ *
+ * $( '#textbox' ).suggestions( { option1: value1, option2: value2 } );
+ * $( '#textbox' ).suggestions( option, value );
+ *
+ * Get option:
+ *
+ * value = $( '#textbox' ).suggestions( option );
+ *
+ * Initialize:
+ *
+ * $( '#textbox' ).suggestions();
+ *
+ * Uses jQuery.suggestions singleton internally.
+ *
+ * @class jQuery.plugin.suggestions
+ */
+
+/**
+ * @method suggestions
+ * @chainable
+ * @return {jQuery}
+ *
+ * @param {Object} options
+ *
+ * @param {Function} [options.fetch] Callback that should fetch suggestions and set the suggestions
+ * property. Called in context of the text box.
+ * @param {string} options.fetch.query
+ * @param {Function} options.fetch.response Callback to receive the suggestions with
+ * @param {Array} options.fetch.response.suggestions
+ * @param {number} options.fetch.maxRows
+ *
+ * @param {Function} [options.cancel] Callback function to call when any pending asynchronous
+ * suggestions fetches. Called in context of the text box.
+ *
+ * @param {Object} [options.special] Set of callbacks for rendering and selecting.
+ *
+ * @param {Function} options.special.render Called in context of the suggestions-special element.
+ * @param {string} options.special.render.query
+ * @param {Object} options.special.render.context
+ *
+ * @param {Function} options.special.select Called in context of the suggestions-result-current element.
+ * @param {jQuery} options.special.select.$textbox
+ *
+ * @param {Object} [options.result] Set of callbacks for rendering and selecting
+ *
+ * @param {Function} options.result.render Called in context of the suggestions-result element.
+ * @param {string} options.result.render.suggestion
+ * @param {Object} options.result.render.context
+ *
+ * @param {Function} options.result.select Called in context of the suggestions-result-current element.
+ * @param {jQuery} options.result.select.$textbox
+ *
+ * @param {Object} [options.update] Set of callbacks for listening to a change in the text input.
+ *
+ * @param {Function} options.update.before Called right after the user changes the textbox text.
+ * @param {Function} options.update.after Called after results are updated either from the cache or
+ * the API as a result of the user input.
+ *
+ * @param {jQuery} [options.$region=this] The element to place the suggestions below and match width of.
+ *
+ * @param {string[]} [options.suggestions] Array of suggestions to display.
+ *
+ * @param {number} [options.maxRows=10] Maximum number of suggestions to display at one time.
+ * Must be between 1 and 100.
+ *
+ * @param {number} [options.delay=120] Number of milliseconds to wait for the user to stop typing.
+ * Must be between 0 and 1200.
+ *
+ * @param {boolean} [options.cache=false] Whether to cache results from a fetch.
+ *
+ * @param {number} [options.cacheMaxAge=60000] Number of milliseconds to cache results from a fetch.
+ * Must be higher than 1. Defaults to 1 minute.
+ *
+ * @param {boolean} [options.submitOnClick=false] Whether to submit the form containing the textbox
+ * when a suggestion is clicked.
+ *
+ * @param {number} [options.maxExpandFactor=3] Maximum suggestions box width relative to the textbox
+ * width. If set to e.g. 2, the suggestions box will never be grown beyond 2 times the width of
+ * the textbox. Must be higher than 1.
+ *
+ * @param {string} [options.expandFrom=auto] Which direction to offset the suggestion box from.
+ * Values 'start' and 'end' translate to left and right respectively depending on the directionality
+ * of the current document, according to `$( 'html' ).css( 'direction' )`.
+ * Valid values: "left", "right", "start", "end", and "auto".
+ *
+ * @param {boolean} [options.positionFromLeft] Sets `expandFrom=left`, for backwards
+ * compatibility.
+ *
+ * @param {boolean} [options.highlightInput=false] Whether to highlight matched portions of the
+ * input or not.
+ */
+
+( function ( $, mw ) {
+
+ var hasOwn = Object.hasOwnProperty;
+
+ /**
+ * Used by jQuery.plugin.suggestions.
+ *
+ * @class jQuery.suggestions
+ * @singleton
+ * @private
+ */
+ $.suggestions = {
+ /**
+ * Cancel any delayed maybeFetch() call and callback the context so
+ * they can cancel any async fetching if they use AJAX or something.
+ *
+ * @param {Object} context
+ */
+ cancel: function ( context ) {
+ if ( context.data.timerID !== null ) {
+ clearTimeout( context.data.timerID );
+ }
+ if ( $.isFunction( context.config.cancel ) ) {
+ context.config.cancel.call( context.data.$textbox );
+ }
+ },
+
+ /**
+ * Hide the element with suggestions and clean up some state.
+ *
+ * @param {Object} context
+ */
+ hide: function ( context ) {
+ // Remove any highlights, including on "special" items
+ context.data.$container.find( '.suggestions-result-current' ).removeClass( 'suggestions-result-current' );
+ // Hide the container
+ context.data.$container.hide();
+ },
+
+ /**
+ * Restore the text the user originally typed in the textbox, before it
+ * was overwritten by highlight(). This restores the value the currently
+ * displayed suggestions are based on, rather than the value just before
+ * highlight() overwrote it; the former is arguably slightly more sensible.
+ *
+ * @param {Object} context
+ */
+ restore: function ( context ) {
+ context.data.$textbox.val( context.data.prevText );
+ },
+
+ /**
+ * Ask the user-specified callback for new suggestions. Any previous delayed
+ * call to this function still pending will be canceled. If the value in the
+ * textbox is empty or hasn't changed since the last time suggestions were fetched,
+ * this function does nothing.
+ *
+ * @param {Object} context
+ * @param {boolean} delayed Whether or not to delay this by the currently configured amount of time
+ */
+ update: function ( context, delayed ) {
+ function maybeFetch() {
+ var val = context.data.$textbox.val(),
+ cache = context.data.cache,
+ cacheHit;
+
+ if ( typeof context.config.update.before === 'function' ) {
+ context.config.update.before.call( context.data.$textbox );
+ }
+
+ // Only fetch if the value in the textbox changed and is not empty, or if the results were hidden
+ // if the textbox is empty then clear the result div, but leave other settings intouched
+ if ( val.length === 0 ) {
+ $.suggestions.hide( context );
+ context.data.prevText = '';
+ } else if (
+ val !== context.data.prevText ||
+ !context.data.$container.is( ':visible' )
+ ) {
+ context.data.prevText = val;
+ // Try cache first
+ if ( context.config.cache && hasOwn.call( cache, val ) ) {
+ if ( mw.now() - cache[ val ].timestamp < context.config.cacheMaxAge ) {
+ context.data.$textbox.suggestions( 'suggestions', cache[ val ].suggestions );
+ if ( typeof context.config.update.after === 'function' ) {
+ context.config.update.after.call( context.data.$textbox, cache[ val ].metadata );
+ }
+ cacheHit = true;
+ } else {
+ // Cache expired
+ delete cache[ val ];
+ }
+ }
+ if ( !cacheHit && typeof context.config.fetch === 'function' ) {
+ context.config.fetch.call(
+ context.data.$textbox,
+ val,
+ function ( suggestions, metadata ) {
+ suggestions = suggestions.slice( 0, context.config.maxRows );
+ context.data.$textbox.suggestions( 'suggestions', suggestions );
+ if ( typeof context.config.update.after === 'function' ) {
+ context.config.update.after.call( context.data.$textbox, metadata );
+ }
+ if ( context.config.cache ) {
+ cache[ val ] = {
+ suggestions: suggestions,
+ metadata: metadata,
+ timestamp: mw.now()
+ };
+ }
+ },
+ context.config.maxRows
+ );
+ }
+ }
+
+ // Always update special rendering
+ $.suggestions.special( context );
+ }
+
+ // Cancels any delayed maybeFetch call, and invokes context.config.cancel.
+ $.suggestions.cancel( context );
+
+ if ( delayed ) {
+ // To avoid many started/aborted requests while typing, we're gonna take a short
+ // break before trying to fetch data.
+ context.data.timerID = setTimeout( maybeFetch, context.config.delay );
+ } else {
+ maybeFetch();
+ }
+ },
+
+ /**
+ * @param {Object} context
+ */
+ special: function ( context ) {
+ // Allow custom rendering - but otherwise don't do any rendering
+ if ( typeof context.config.special.render === 'function' ) {
+ // Wait for the browser to update the value
+ setTimeout( function () {
+ // Render special
+ var $special = context.data.$container.find( '.suggestions-special' );
+ context.config.special.render.call( $special, context.data.$textbox.val(), context );
+ }, 1 );
+ }
+ },
+
+ /**
+ * Sets the value of a property, and updates the widget accordingly
+ *
+ * @param {Object} context
+ * @param {string} property Name of property
+ * @param {Mixed} value Value to set property with
+ */
+ configure: function ( context, property, value ) {
+ var newCSS,
+ $result, $results, $spanForWidth, childrenWidth,
+ i, expWidth, maxWidth, text;
+
+ // Validate creation using fallback values
+ switch ( property ) {
+ case 'fetch':
+ case 'cancel':
+ case 'special':
+ case 'result':
+ case 'update':
+ case '$region':
+ case 'expandFrom':
+ context.config[ property ] = value;
+ break;
+ case 'suggestions':
+ context.config[ property ] = value;
+ // Update suggestions
+ if ( context.data !== undefined ) {
+ if ( context.data.$textbox.val().length === 0 ) {
+ // Hide the div when no suggestion exist
+ $.suggestions.hide( context );
+ } else {
+ // Rebuild the suggestions list
+ context.data.$container.show();
+ // Update the size and position of the list
+ newCSS = {
+ top: context.config.$region.offset().top + context.config.$region.outerHeight(),
+ bottom: 'auto',
+ width: context.config.$region.outerWidth(),
+ height: 'auto'
+ };
+
+ // Process expandFrom, after this it is set to left or right.
+ context.config.expandFrom = ( function ( expandFrom ) {
+ var regionWidth, docWidth, regionCenter, docCenter,
+ docDir = $( document.documentElement ).css( 'direction' ),
+ $region = context.config.$region;
+
+ // Backwards compatible
+ if ( context.config.positionFromLeft ) {
+ expandFrom = 'left';
+
+ // Catch invalid values, default to 'auto'
+ } else if ( $.inArray( expandFrom, [ 'left', 'right', 'start', 'end', 'auto' ] ) === -1 ) {
+ expandFrom = 'auto';
+ }
+
+ if ( expandFrom === 'auto' ) {
+ if ( $region.data( 'searchsuggest-expand-dir' ) ) {
+ // If the markup explicitly contains a direction, use it.
+ expandFrom = $region.data( 'searchsuggest-expand-dir' );
+ } else {
+ regionWidth = $region.outerWidth();
+ docWidth = $( document ).width();
+ if ( regionWidth > ( 0.85 * docWidth ) ) {
+ // If the input size takes up more than 85% of the document horizontally
+ // expand the suggestions to the writing direction's native end.
+ expandFrom = 'start';
+ } else {
+ // Calculate the center points of the input and document
+ regionCenter = $region.offset().left + regionWidth / 2;
+ docCenter = docWidth / 2;
+ if ( Math.abs( regionCenter - docCenter ) < ( 0.10 * docCenter ) ) {
+ // If the input's center is within 10% of the document center
+ // use the writing direction's native end.
+ expandFrom = 'start';
+ } else {
+ // Otherwise expand the input from the closest side of the page,
+ // towards the side of the page with the most free open space
+ expandFrom = regionCenter > docCenter ? 'right' : 'left';
+ }
+ }
+ }
+ }
+
+ if ( expandFrom === 'start' ) {
+ expandFrom = docDir === 'rtl' ? 'right' : 'left';
+
+ } else if ( expandFrom === 'end' ) {
+ expandFrom = docDir === 'rtl' ? 'left' : 'right';
+ }
+
+ return expandFrom;
+
+ }( context.config.expandFrom ) );
+
+ if ( context.config.expandFrom === 'left' ) {
+ // Expand from left
+ newCSS.left = context.config.$region.offset().left;
+ newCSS.right = 'auto';
+ } else {
+ // Expand from right
+ newCSS.left = 'auto';
+ newCSS.right = $( 'body' ).width() - ( context.config.$region.offset().left + context.config.$region.outerWidth() );
+ }
+
+ context.data.$container.css( newCSS );
+ $results = context.data.$container.children( '.suggestions-results' );
+ $results.empty();
+ expWidth = -1;
+ for ( i = 0; i < context.config.suggestions.length; i++ ) {
+ text = context.config.suggestions[ i ];
+ $result = $( '<div>' )
+ .addClass( 'suggestions-result' )
+ .attr( 'rel', i )
+ .data( 'text', context.config.suggestions[ i ] )
+ .mousemove( function () {
+ context.data.selectedWithMouse = true;
+ $.suggestions.highlight(
+ context,
+ $( this ).closest( '.suggestions-results .suggestions-result' ),
+ false
+ );
+ } )
+ .appendTo( $results );
+ // Allow custom rendering
+ if ( typeof context.config.result.render === 'function' ) {
+ context.config.result.render.call( $result, context.config.suggestions[ i ], context );
+ } else {
+ $result.text( text );
+ }
+
+ if ( context.config.highlightInput ) {
+ $result.highlightText( context.data.prevText, { method: 'prefixHighlight' } );
+ }
+
+ // Widen results box if needed (new width is only calculated here, applied later).
+
+ // The monstrosity below accomplishes two things:
+ // * Wraps the text contents in a DOM element, so that we can know its width. There is
+ // no way to directly access the width of a text node, and we can't use the parent
+ // node width as it has text-overflow: ellipsis; and overflow: hidden; applied to
+ // it, which trims it to a smaller width.
+ // * Temporarily applies position: absolute; to the wrapper to pull it out of normal
+ // document flow. Otherwise the CSS text-overflow: ellipsis; and overflow: hidden;
+ // rules would cause some browsers (at least all versions of IE from 6 to 11) to
+ // still report the "trimmed" width. This should not be done in regular CSS
+ // stylesheets as we don't want this rule to apply to other <span> elements, like
+ // the ones generated by jquery.highlightText.
+ $spanForWidth = $result.wrapInner( '<span>' ).children();
+ childrenWidth = $spanForWidth.css( 'position', 'absolute' ).outerWidth();
+ $spanForWidth.contents().unwrap();
+
+ if ( childrenWidth > $result.width() && childrenWidth > expWidth ) {
+ // factor in any padding, margin, or border space on the parent
+ expWidth = childrenWidth + ( context.data.$container.width() - $result.width() );
+ }
+ }
+
+ // Apply new width for results box, if any
+ if ( expWidth > context.data.$container.width() ) {
+ maxWidth = context.config.maxExpandFactor * context.data.$textbox.width();
+ context.data.$container.width( Math.min( expWidth, maxWidth ) );
+ }
+ }
+ }
+ break;
+ case 'maxRows':
+ context.config[ property ] = Math.max( 1, Math.min( 100, value ) );
+ break;
+ case 'delay':
+ context.config[ property ] = Math.max( 0, Math.min( 1200, value ) );
+ break;
+ case 'cacheMaxAge':
+ context.config[ property ] = Math.max( 1, value );
+ break;
+ case 'maxExpandFactor':
+ context.config[ property ] = Math.max( 1, value );
+ break;
+ case 'cache':
+ case 'submitOnClick':
+ case 'positionFromLeft':
+ case 'highlightInput':
+ context.config[ property ] = !!value;
+ break;
+ }
+ },
+
+ /**
+ * Highlight a result in the results table
+ *
+ * @param {Object} context
+ * @param {jQuery|string} result `<tr>` to highlight, or 'prev' or 'next'
+ * @param {boolean} updateTextbox If true, put the suggestion in the textbox
+ */
+ highlight: function ( context, result, updateTextbox ) {
+ var selected = context.data.$container.find( '.suggestions-result-current' );
+ if ( !result.get || selected.get( 0 ) !== result.get( 0 ) ) {
+ if ( result === 'prev' ) {
+ if ( selected.hasClass( 'suggestions-special' ) ) {
+ result = context.data.$container.find( '.suggestions-result:last' );
+ } else {
+ result = selected.prev();
+ if ( !( result.length && result.hasClass( 'suggestions-result' ) ) ) {
+ // there is something in the DOM between selected element and the wrapper, bypass it
+ result = selected.parents( '.suggestions-results > *' ).prev().find( '.suggestions-result' ).eq( 0 );
+ }
+
+ if ( selected.length === 0 ) {
+ // we are at the beginning, so lets jump to the last item
+ if ( context.data.$container.find( '.suggestions-special' ).html() !== '' ) {
+ result = context.data.$container.find( '.suggestions-special' );
+ } else {
+ result = context.data.$container.find( '.suggestions-results .suggestions-result:last' );
+ }
+ }
+ }
+ } else if ( result === 'next' ) {
+ if ( selected.length === 0 ) {
+ // No item selected, go to the first one
+ result = context.data.$container.find( '.suggestions-results .suggestions-result:first' );
+ if ( result.length === 0 && context.data.$container.find( '.suggestions-special' ).html() !== '' ) {
+ // No suggestion exists, go to the special one directly
+ result = context.data.$container.find( '.suggestions-special' );
+ }
+ } else {
+ result = selected.next();
+ if ( !( result.length && result.hasClass( 'suggestions-result' ) ) ) {
+ // there is something in the DOM between selected element and the wrapper, bypass it
+ result = selected.parents( '.suggestions-results > *' ).next().find( '.suggestions-result' ).eq( 0 );
+ }
+
+ if ( selected.hasClass( 'suggestions-special' ) ) {
+ result = $( [] );
+ } else if (
+ result.length === 0 &&
+ context.data.$container.find( '.suggestions-special' ).html() !== ''
+ ) {
+ // We were at the last item, jump to the specials!
+ result = context.data.$container.find( '.suggestions-special' );
+ }
+ }
+ }
+ selected.removeClass( 'suggestions-result-current' );
+ result.addClass( 'suggestions-result-current' );
+ }
+ if ( updateTextbox ) {
+ if ( result.length === 0 || result.is( '.suggestions-special' ) ) {
+ $.suggestions.restore( context );
+ } else {
+ context.data.$textbox.val( result.data( 'text' ) );
+ // .val() doesn't call any event handlers, so
+ // let the world know what happened
+ context.data.$textbox.change();
+ }
+ context.data.$textbox.trigger( 'change' );
+ }
+ },
+
+ /**
+ * Respond to keypress event
+ *
+ * @param {jQuery.Event} e
+ * @param {Object} context
+ * @param {number} key Code of key pressed
+ */
+ keypress: function ( e, context, key ) {
+ var selected,
+ wasVisible = context.data.$container.is( ':visible' ),
+ preventDefault = false;
+
+ switch ( key ) {
+ // Arrow down
+ case 40:
+ if ( wasVisible ) {
+ $.suggestions.highlight( context, 'next', true );
+ context.data.selectedWithMouse = false;
+ } else {
+ $.suggestions.update( context, false );
+ }
+ preventDefault = true;
+ break;
+ // Arrow up
+ case 38:
+ if ( wasVisible ) {
+ $.suggestions.highlight( context, 'prev', true );
+ context.data.selectedWithMouse = false;
+ }
+ preventDefault = wasVisible;
+ break;
+ // Escape
+ case 27:
+ $.suggestions.hide( context );
+ $.suggestions.restore( context );
+ $.suggestions.cancel( context );
+ context.data.$textbox.trigger( 'change' );
+ preventDefault = wasVisible;
+ break;
+ // Enter
+ case 13:
+ preventDefault = wasVisible;
+ selected = context.data.$container.find( '.suggestions-result-current' );
+ $.suggestions.hide( context );
+ if ( selected.length === 0 || context.data.selectedWithMouse ) {
+ // If nothing is selected or if something was selected with the mouse
+ // cancel any current requests and allow the form to be submitted
+ // (simply don't prevent default behavior).
+ $.suggestions.cancel( context );
+ preventDefault = false;
+ } else if ( selected.is( '.suggestions-special' ) ) {
+ if ( typeof context.config.special.select === 'function' ) {
+ // Allow the callback to decide whether to prevent default or not
+ if ( context.config.special.select.call( selected, context.data.$textbox, 'keyboard' ) === true ) {
+ preventDefault = false;
+ }
+ }
+ } else {
+ if ( typeof context.config.result.select === 'function' ) {
+ // Allow the callback to decide whether to prevent default or not
+ if ( context.config.result.select.call( selected, context.data.$textbox, 'keyboard' ) === true ) {
+ preventDefault = false;
+ }
+ }
+ }
+ break;
+ default:
+ $.suggestions.update( context, true );
+ break;
+ }
+ if ( preventDefault ) {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }
+ };
+
+ // See file header for method documentation
+ $.fn.suggestions = function () {
+
+ // Multi-context fields
+ var returnValue,
+ args = arguments;
+
+ $( this ).each( function () {
+ var context, key;
+
+ /* Construction and Loading */
+
+ context = $( this ).data( 'suggestions-context' );
+ if ( context === undefined || context === null ) {
+ context = {
+ config: {
+ fetch: function () {},
+ cancel: function () {},
+ special: {},
+ result: {},
+ update: {},
+ $region: $( this ),
+ suggestions: [],
+ maxRows: 10,
+ delay: 120,
+ cache: false,
+ cacheMaxAge: 60000,
+ submitOnClick: false,
+ maxExpandFactor: 3,
+ expandFrom: 'auto',
+ highlightInput: false
+ }
+ };
+ }
+
+ /* API */
+
+ // Handle various calling styles
+ if ( args.length > 0 ) {
+ if ( typeof args[ 0 ] === 'object' ) {
+ // Apply set of properties
+ for ( key in args[ 0 ] ) {
+ $.suggestions.configure( context, key, args[ 0 ][ key ] );
+ }
+ } else if ( typeof args[ 0 ] === 'string' ) {
+ if ( args.length > 1 ) {
+ // Set property values
+ $.suggestions.configure( context, args[ 0 ], args[ 1 ] );
+ } else if ( returnValue === null || returnValue === undefined ) {
+ // Get property values, but don't give access to internal data - returns only the first
+ returnValue = ( args[ 0 ] in context.config ? undefined : context.config[ args[ 0 ] ] );
+ }
+ }
+ }
+
+ /* Initialization */
+
+ if ( context.data === undefined ) {
+ context.data = {
+ // ID of running timer
+ timerID: null,
+
+ // Text in textbox when suggestions were last fetched
+ prevText: null,
+
+ // Cache of fetched suggestions
+ cache: {},
+
+ // Number of results visible without scrolling
+ visibleResults: 0,
+
+ // Suggestion the last mousedown event occurred on
+ mouseDownOn: $( [] ),
+ $textbox: $( this ),
+ selectedWithMouse: false
+ };
+
+ context.data.$container = $( '<div>' )
+ .css( 'display', 'none' )
+ .addClass( 'suggestions' )
+ .append(
+ $( '<div>' ).addClass( 'suggestions-results' )
+ // Can't use click() because the container div is hidden when the
+ // textbox loses focus. Instead, listen for a mousedown followed
+ // by a mouseup on the same div.
+ .mousedown( function ( e ) {
+ context.data.mouseDownOn = $( e.target ).closest( '.suggestions-results .suggestions-result' );
+ } )
+ .mouseup( function ( e ) {
+ var $result = $( e.target ).closest( '.suggestions-results .suggestions-result' ),
+ $other = context.data.mouseDownOn;
+
+ context.data.mouseDownOn = $( [] );
+ if ( $result.get( 0 ) !== $other.get( 0 ) ) {
+ return;
+ }
+ $.suggestions.highlight( context, $result, true );
+ if ( typeof context.config.result.select === 'function' ) {
+ context.config.result.select.call( $result, context.data.$textbox, 'mouse' );
+ }
+ // Don't interfere with special clicks (e.g. to open in new tab)
+ if ( !( e.which !== 1 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey ) ) {
+ // This will hide the link we're just clicking on, which causes problems
+ // when done synchronously in at least Firefox 3.6 (T64858).
+ setTimeout( function () {
+ $.suggestions.hide( context );
+ }, 0 );
+ }
+ // Always bring focus to the textbox, as that's probably where the user expects it
+ // if they were just typing.
+ context.data.$textbox.focus();
+ } )
+ )
+ .append(
+ $( '<div>' ).addClass( 'suggestions-special' )
+ // Can't use click() because the container div is hidden when the
+ // textbox loses focus. Instead, listen for a mousedown followed
+ // by a mouseup on the same div.
+ .mousedown( function ( e ) {
+ context.data.mouseDownOn = $( e.target ).closest( '.suggestions-special' );
+ } )
+ .mouseup( function ( e ) {
+ var $special = $( e.target ).closest( '.suggestions-special' ),
+ $other = context.data.mouseDownOn;
+
+ context.data.mouseDownOn = $( [] );
+ if ( $special.get( 0 ) !== $other.get( 0 ) ) {
+ return;
+ }
+ if ( typeof context.config.special.select === 'function' ) {
+ context.config.special.select.call( $special, context.data.$textbox, 'mouse' );
+ }
+ // Don't interfere with special clicks (e.g. to open in new tab)
+ if ( !( e.which !== 1 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey ) ) {
+ // This will hide the link we're just clicking on, which causes problems
+ // when done synchronously in at least Firefox 3.6 (T64858).
+ setTimeout( function () {
+ $.suggestions.hide( context );
+ }, 0 );
+ }
+ // Always bring focus to the textbox, as that's probably where the user expects it
+ // if they were just typing.
+ context.data.$textbox.focus();
+ } )
+ .mousemove( function ( e ) {
+ context.data.selectedWithMouse = true;
+ $.suggestions.highlight(
+ context, $( e.target ).closest( '.suggestions-special' ), false
+ );
+ } )
+ )
+ .appendTo( $( 'body' ) );
+
+ $( this )
+ // Stop browser autocomplete from interfering
+ .attr( 'autocomplete', 'off' )
+ .keydown( function ( e ) {
+ // Store key pressed to handle later
+ context.data.keypressed = e.which;
+ context.data.keypressedCount = 0;
+ } )
+ .keypress( function ( e ) {
+ context.data.keypressedCount++;
+ $.suggestions.keypress( e, context, context.data.keypressed );
+ } )
+ .keyup( function ( e ) {
+ // The keypress event is fired when a key is pressed down and that key normally
+ // produces a character value. We also want to handle some keys that don't
+ // produce a character value so we also attach to the keydown/keyup events.
+ // List of codes sourced from
+ // https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/keyCode
+ var allowed = [
+ 40, // up arrow
+ 38, // down arrow
+ 27, // escape
+ 13, // enter
+ 46, // delete
+ 8 // backspace
+ ];
+ if ( context.data.keypressedCount === 0 &&
+ e.which === context.data.keypressed &&
+ $.inArray( e.which, allowed ) !== -1
+ ) {
+ $.suggestions.keypress( e, context, context.data.keypressed );
+ }
+ } )
+ .blur( function () {
+ // When losing focus because of a mousedown
+ // on a suggestion, don't hide the suggestions
+ if ( context.data.mouseDownOn.length > 0 ) {
+ return;
+ }
+ $.suggestions.hide( context );
+ $.suggestions.cancel( context );
+ } );
+ }
+
+ // Store the context for next time
+ $( this ).data( 'suggestions-context', context );
+ } );
+ return returnValue !== undefined ? returnValue : $( this );
+ };
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.suggestions
+ */
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/jquery/jquery.tabIndex.js b/www/wiki/resources/src/jquery/jquery.tabIndex.js
new file mode 100644
index 00000000..ed37aa1e
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.tabIndex.js
@@ -0,0 +1,57 @@
+/**
+ * @class jQuery.plugin.tabIndex
+ */
+( function ( $ ) {
+
+ /**
+ * Find the lowest tabindex in use within a selection.
+ *
+ * @return {number} Lowest tabindex on the page
+ */
+ $.fn.firstTabIndex = function () {
+ var minTabIndex = null;
+ $( this ).find( '[tabindex]' ).each( function () {
+ var tabIndex = parseInt( $( this ).prop( 'tabindex' ), 10 );
+ // In IE6/IE7 the above jQuery selector returns all elements,
+ // becuase it has a default value for tabIndex in IE6/IE7 of 0
+ // (rather than null/undefined). Therefore check "> 0" as well.
+ // Under IE7 under Windows NT 5.2 is also capable of returning NaN.
+ if ( tabIndex > 0 && !isNaN( tabIndex ) ) {
+ // Initial value
+ if ( minTabIndex === null ) {
+ minTabIndex = tabIndex;
+ } else if ( tabIndex < minTabIndex ) {
+ minTabIndex = tabIndex;
+ }
+ }
+ } );
+ return minTabIndex;
+ };
+
+ /**
+ * Find the highest tabindex in use within a selection.
+ *
+ * @return {number} Highest tabindex on the page
+ */
+ $.fn.lastTabIndex = function () {
+ var maxTabIndex = null;
+ $( this ).find( '[tabindex]' ).each( function () {
+ var tabIndex = parseInt( $( this ).prop( 'tabindex' ), 10 );
+ if ( tabIndex > 0 && !isNaN( tabIndex ) ) {
+ // Initial value
+ if ( maxTabIndex === null ) {
+ maxTabIndex = tabIndex;
+ } else if ( tabIndex > maxTabIndex ) {
+ maxTabIndex = tabIndex;
+ }
+ }
+ } );
+ return maxTabIndex;
+ };
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.tabIndex
+ */
+
+}( jQuery ) );
diff --git a/www/wiki/resources/src/jquery/jquery.tablesorter.js b/www/wiki/resources/src/jquery/jquery.tablesorter.js
new file mode 100644
index 00000000..ecd376a6
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.tablesorter.js
@@ -0,0 +1,1278 @@
+/*!
+ * TableSorter for MediaWiki
+ *
+ * Written 2011 Leo Koppelkamm
+ * Based on tablesorter.com plugin, written (c) 2007 Christian Bach.
+ *
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ *
+ * Depends on mw.config (wgDigitTransformTable, wgDefaultDateFormat, wgPageContentLanguage)
+ * and mw.language.months.
+ *
+ * Uses 'tableSorterCollation' in mw.config (if available)
+ *
+ * Create a sortable table with multi-column sorting capabilities
+ *
+ * // Create a simple tablesorter interface
+ * $( 'table' ).tablesorter();
+ *
+ * // Create a tablesorter interface, initially sorting on the first and second column
+ * $( 'table' ).tablesorter( { sortList: [ { 0: 'desc' }, { 1: 'asc' } ] } );
+ *
+ * @param {string} [cssHeader="header"] A string of the class name to be appended to sortable
+ * tr elements in the thead of the table.
+ *
+ * @param {string} [cssAsc="headerSortUp"] A string of the class name to be appended to
+ * sortable tr elements in the thead on a ascending sort.
+ *
+ * @param {string} [cssDesc="headerSortDown"] A string of the class name to be appended to
+ * sortable tr elements in the thead on a descending sort.
+ *
+ * @param {string} [sortMultisortKey="shiftKey"] A string of the multi-column sort key.
+ *
+ * @param {boolean} [cancelSelection=true] Boolean flag indicating iftablesorter should cancel
+ * selection of the table headers text.
+ *
+ * @param {Array} [sortList] An array containing objects specifying sorting. By passing more
+ * than one object, multi-sorting will be applied. Object structure:
+ * { <Integer column index>: <String 'asc' or 'desc'> }
+ *
+ * @event sortEnd.tablesorter: Triggered as soon as any sorting has been applied.
+ *
+ * @author Christian Bach/christian.bach@polyester.se
+ */
+( function ( $, mw ) {
+ var ts,
+ parsers = [];
+
+ /* Parser utility functions */
+
+ function getParserById( name ) {
+ var i;
+ for ( i = 0; i < parsers.length; i++ ) {
+ if ( parsers[ i ].id.toLowerCase() === name.toLowerCase() ) {
+ return parsers[ i ];
+ }
+ }
+ return false;
+ }
+
+ function getElementSortKey( node ) {
+ var $node = $( node ),
+ // Use data-sort-value attribute.
+ // Use data() instead of attr() so that live value changes
+ // are processed as well (T40152).
+ data = $node.data( 'sortValue' );
+
+ if ( data !== null && data !== undefined ) {
+ // Cast any numbers or other stuff to a string, methods
+ // like charAt, toLowerCase and split are expected.
+ return String( data );
+ }
+ if ( !node ) {
+ return $node.text();
+ }
+ if ( node.tagName.toLowerCase() === 'img' ) {
+ return $node.attr( 'alt' ) || ''; // handle undefined alt
+ }
+ return $.map( $.makeArray( node.childNodes ), function ( elem ) {
+ if ( elem.nodeType === Node.ELEMENT_NODE ) {
+ return getElementSortKey( elem );
+ }
+ return $.text( elem );
+ } ).join( '' );
+ }
+
+ function detectParserForColumn( table, rows, column ) {
+ var l = parsers.length,
+ config = $( table ).data( 'tablesorter' ).config,
+ cellIndex,
+ nodeValue,
+ nextRow = false,
+ // Start with 1 because 0 is the fallback parser
+ i = 1,
+ lastRowIndex = -1,
+ rowIndex = 0,
+ concurrent = 0,
+ empty = 0,
+ needed = ( rows.length > 4 ) ? 5 : rows.length;
+
+ while ( i < l ) {
+ // if this is a child row, continue to the next row (as buildCache())
+ if ( rows[ rowIndex ] && !$( rows[ rowIndex ] ).hasClass( config.cssChildRow ) ) {
+ if ( rowIndex !== lastRowIndex ) {
+ lastRowIndex = rowIndex;
+ cellIndex = $( rows[ rowIndex ] ).data( 'columnToCell' )[ column ];
+ nodeValue = $.trim( getElementSortKey( rows[ rowIndex ].cells[ cellIndex ] ) );
+ }
+ } else {
+ nodeValue = '';
+ }
+
+ if ( nodeValue !== '' ) {
+ if ( parsers[ i ].is( nodeValue, table ) ) {
+ concurrent++;
+ nextRow = true;
+ if ( concurrent >= needed ) {
+ // Confirmed the parser for multiple cells, let's return it
+ return parsers[ i ];
+ }
+ } else if ( parsers[ i ].id.match( /isoDate/ ) && /^\D*(\d{1,4}) ?(\[.+\])?$/.test( nodeValue ) ) {
+ // For 1-4 digits and maybe reference(s) parser "isoDate" or "number" is possible, check next row
+ empty++;
+ nextRow = true;
+ } else {
+ // Check next parser, reset rows
+ i++;
+ rowIndex = 0;
+ concurrent = 0;
+ empty = 0;
+ nextRow = false;
+ }
+ } else {
+ // Empty cell
+ empty++;
+ nextRow = true;
+ }
+
+ if ( nextRow ) {
+ nextRow = false;
+ rowIndex++;
+ if ( rowIndex >= rows.length ) {
+ if ( concurrent > 0 && concurrent >= rows.length - empty ) {
+ // Confirmed the parser for all filled cells
+ return parsers[ i ];
+ }
+ // Check next parser, reset rows
+ i++;
+ rowIndex = 0;
+ concurrent = 0;
+ empty = 0;
+ }
+ }
+ }
+
+ // 0 is always the generic parser (text)
+ return parsers[ 0 ];
+ }
+
+ function buildParserCache( table, $headers ) {
+ var sortType, len, j, parser,
+ rows = table.tBodies[ 0 ].rows,
+ config = $( table ).data( 'tablesorter' ).config,
+ parsers = [];
+
+ if ( rows[ 0 ] ) {
+ len = config.columns;
+ for ( j = 0; j < len; j++ ) {
+ parser = false;
+ sortType = $headers.eq( config.columnToHeader[ j ] ).data( 'sortType' );
+ if ( sortType !== undefined ) {
+ parser = getParserById( sortType );
+ }
+
+ if ( parser === false ) {
+ parser = detectParserForColumn( table, rows, j );
+ }
+
+ parsers.push( parser );
+ }
+ }
+ return parsers;
+ }
+
+ /* Other utility functions */
+
+ function buildCache( table ) {
+ var i, j, $row, cols,
+ totalRows = ( table.tBodies[ 0 ] && table.tBodies[ 0 ].rows.length ) || 0,
+ config = $( table ).data( 'tablesorter' ).config,
+ parsers = config.parsers,
+ len = parsers.length,
+ cellIndex,
+ cache = {
+ row: [],
+ normalized: []
+ };
+
+ for ( i = 0; i < totalRows; i++ ) {
+
+ // Add the table data to main data array
+ $row = $( table.tBodies[ 0 ].rows[ i ] );
+ cols = [];
+
+ // if this is a child row, add it to the last row's children and
+ // continue to the next row
+ if ( $row.hasClass( config.cssChildRow ) ) {
+ cache.row[ cache.row.length - 1 ] = cache.row[ cache.row.length - 1 ].add( $row );
+ // go to the next for loop
+ continue;
+ }
+
+ cache.row.push( $row );
+
+ for ( j = 0; j < len; j++ ) {
+ cellIndex = $row.data( 'columnToCell' )[ j ];
+ cols.push( parsers[ j ].format( getElementSortKey( $row[ 0 ].cells[ cellIndex ] ) ) );
+ }
+
+ cols.push( cache.normalized.length ); // add position for rowCache
+ cache.normalized.push( cols );
+ cols = null;
+ }
+
+ return cache;
+ }
+
+ function appendToTable( table, cache ) {
+ var i, pos, l, j,
+ row = cache.row,
+ normalized = cache.normalized,
+ totalRows = normalized.length,
+ checkCell = ( normalized[ 0 ].length - 1 ),
+ fragment = document.createDocumentFragment();
+
+ for ( i = 0; i < totalRows; i++ ) {
+ pos = normalized[ i ][ checkCell ];
+
+ l = row[ pos ].length;
+ for ( j = 0; j < l; j++ ) {
+ fragment.appendChild( row[ pos ][ j ] );
+ }
+
+ }
+ table.tBodies[ 0 ].appendChild( fragment );
+
+ $( table ).trigger( 'sortEnd.tablesorter' );
+ }
+
+ /**
+ * Find all header rows in a thead-less table and put them in a <thead> tag.
+ * This only treats a row as a header row if it contains only <th>s (no <td>s)
+ * and if it is preceded entirely by header rows. The algorithm stops when
+ * it encounters the first non-header row.
+ *
+ * After this, it will look at all rows at the bottom for footer rows
+ * And place these in a tfoot using similar rules.
+ *
+ * @param {jQuery} $table object for a <table>
+ */
+ function emulateTHeadAndFoot( $table ) {
+ var $thead, $tfoot, i, len,
+ $rows = $table.find( '> tbody > tr' );
+ if ( !$table.get( 0 ).tHead ) {
+ $thead = $( '<thead>' );
+ $rows.each( function () {
+ if ( $( this ).children( 'td' ).length ) {
+ // This row contains a <td>, so it's not a header row
+ // Stop here
+ return false;
+ }
+ $thead.append( this );
+ } );
+ $table.find( ' > tbody:first' ).before( $thead );
+ }
+ if ( !$table.get( 0 ).tFoot ) {
+ $tfoot = $( '<tfoot>' );
+ len = $rows.length;
+ for ( i = len - 1; i >= 0; i-- ) {
+ if ( $( $rows[ i ] ).children( 'td' ).length ) {
+ break;
+ }
+ $tfoot.prepend( $( $rows[ i ] ) );
+ }
+ $table.append( $tfoot );
+ }
+ }
+
+ function uniqueElements( array ) {
+ var uniques = [];
+ $.each( array, function ( i, elem ) {
+ if ( elem !== undefined && $.inArray( elem, uniques ) === -1 ) {
+ uniques.push( elem );
+ }
+ } );
+ return uniques;
+ }
+
+ function buildHeaders( table, msg ) {
+ var config = $( table ).data( 'tablesorter' ).config,
+ maxSeen = 0,
+ colspanOffset = 0,
+ columns,
+ k,
+ $cell,
+ rowspan,
+ colspan,
+ headerCount,
+ longestTR,
+ headerIndex,
+ exploded,
+ $tableHeaders = $( [] ),
+ $tableRows = $( 'thead:eq(0) > tr', table );
+
+ if ( $tableRows.length <= 1 ) {
+ $tableHeaders = $tableRows.children( 'th' );
+ } else {
+ exploded = [];
+
+ // Loop through all the dom cells of the thead
+ $tableRows.each( function ( rowIndex, row ) {
+ $.each( row.cells, function ( columnIndex, cell ) {
+ var matrixRowIndex,
+ matrixColumnIndex;
+
+ rowspan = Number( cell.rowSpan );
+ colspan = Number( cell.colSpan );
+
+ // Skip the spots in the exploded matrix that are already filled
+ while ( exploded[ rowIndex ] && exploded[ rowIndex ][ columnIndex ] !== undefined ) {
+ ++columnIndex;
+ }
+
+ // Find the actual dimensions of the thead, by placing each cell
+ // in the exploded matrix rowspan times colspan times, with the proper offsets
+ for ( matrixColumnIndex = columnIndex; matrixColumnIndex < columnIndex + colspan; ++matrixColumnIndex ) {
+ for ( matrixRowIndex = rowIndex; matrixRowIndex < rowIndex + rowspan; ++matrixRowIndex ) {
+ if ( !exploded[ matrixRowIndex ] ) {
+ exploded[ matrixRowIndex ] = [];
+ }
+ exploded[ matrixRowIndex ][ matrixColumnIndex ] = cell;
+ }
+ }
+ } );
+ } );
+ // We want to find the row that has the most columns (ignoring colspan)
+ $.each( exploded, function ( index, cellArray ) {
+ headerCount = $( uniqueElements( cellArray ) ).filter( 'th' ).length;
+ if ( headerCount >= maxSeen ) {
+ maxSeen = headerCount;
+ longestTR = index;
+ }
+ } );
+ // We cannot use $.unique() here because it sorts into dom order, which is undesirable
+ $tableHeaders = $( uniqueElements( exploded[ longestTR ] ) ).filter( 'th' );
+ }
+
+ // as each header can span over multiple columns (using colspan=N),
+ // we have to bidirectionally map headers to their columns and columns to their headers
+ config.columnToHeader = [];
+ config.headerToColumns = [];
+ config.headerList = [];
+ headerIndex = 0;
+ $tableHeaders.each( function () {
+ $cell = $( this );
+ columns = [];
+
+ if ( !$cell.hasClass( config.unsortableClass ) ) {
+ $cell
+ .addClass( config.cssHeader )
+ .prop( 'tabIndex', 0 )
+ .attr( {
+ role: 'columnheader button',
+ title: msg[ 1 ]
+ } );
+
+ for ( k = 0; k < this.colSpan; k++ ) {
+ config.columnToHeader[ colspanOffset + k ] = headerIndex;
+ columns.push( colspanOffset + k );
+ }
+
+ config.headerToColumns[ headerIndex ] = columns;
+
+ $cell.data( {
+ headerIndex: headerIndex,
+ order: 0,
+ count: 0
+ } );
+
+ // add only sortable cells to headerList
+ config.headerList[ headerIndex ] = this;
+ headerIndex++;
+ }
+
+ colspanOffset += this.colSpan;
+ } );
+
+ // number of columns with extended colspan, inclusive unsortable
+ // parsers[j], cache[][j], columnToHeader[j], columnToCell[j] have so many elements
+ config.columns = colspanOffset;
+
+ return $tableHeaders.not( '.' + config.unsortableClass );
+ }
+
+ function isValueInArray( v, a ) {
+ var i;
+ for ( i = 0; i < a.length; i++ ) {
+ if ( a[ i ][ 0 ] === v ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Sets the sort count of the columns that are not affected by the sorting to have them sorted
+ * in default (ascending) order when their header cell is clicked the next time.
+ *
+ * @param {jQuery} $headers
+ * @param {Array} sortList 2D number array
+ * @param {Array} headerToColumns 2D number array
+ */
+ function setHeadersOrder( $headers, sortList, headerToColumns ) {
+ // Loop through all headers to retrieve the indices of the columns the header spans across:
+ $.each( headerToColumns, function ( headerIndex, columns ) {
+
+ $.each( columns, function ( i, columnIndex ) {
+ var header = $headers[ headerIndex ],
+ $header = $( header );
+
+ if ( !isValueInArray( columnIndex, sortList ) ) {
+ // Column shall not be sorted: Reset header count and order.
+ $header.data( {
+ order: 0,
+ count: 0
+ } );
+ } else {
+ // Column shall be sorted: Apply designated count and order.
+ $.each( sortList, function ( j, sortColumn ) {
+ if ( sortColumn[ 0 ] === i ) {
+ $header.data( {
+ order: sortColumn[ 1 ],
+ count: sortColumn[ 1 ] + 1
+ } );
+ return false;
+ }
+ } );
+ }
+ } );
+
+ } );
+ }
+
+ function setHeadersCss( table, $headers, list, css, msg, columnToHeader ) {
+ var i, len;
+ // Remove all header information and reset titles to default message
+ $headers.removeClass( css[ 0 ] ).removeClass( css[ 1 ] ).attr( 'title', msg[ 1 ] );
+
+ for ( i = 0, len = list.length; i < len; i++ ) {
+ $headers
+ .eq( columnToHeader[ list[ i ][ 0 ] ] )
+ .addClass( css[ list[ i ][ 1 ] ] )
+ .attr( 'title', msg[ list[ i ][ 1 ] ] );
+ }
+ }
+
+ function sortText( a, b ) {
+ return ( ( a < b ) ? -1 : ( ( a > b ) ? 1 : 0 ) );
+ }
+
+ function sortTextDesc( a, b ) {
+ return ( ( b < a ) ? -1 : ( ( b > a ) ? 1 : 0 ) );
+ }
+
+ function multisort( table, sortList, cache ) {
+ var i,
+ sortFn = [];
+
+ for ( i = 0; i < sortList.length; i++ ) {
+ sortFn[ i ] = ( sortList[ i ][ 1 ] ) ? sortTextDesc : sortText;
+ }
+ cache.normalized.sort( function ( array1, array2 ) {
+ var i, col, ret;
+ for ( i = 0; i < sortList.length; i++ ) {
+ col = sortList[ i ][ 0 ];
+ ret = sortFn[ i ].call( this, array1[ col ], array2[ col ] );
+ if ( ret !== 0 ) {
+ return ret;
+ }
+ }
+ // Fall back to index number column to ensure stable sort
+ return sortText.call( this, array1[ array1.length - 1 ], array2[ array2.length - 1 ] );
+ } );
+ return cache;
+ }
+
+ function buildTransformTable() {
+ var ascii, localised, i, digitClass,
+ digits = '0123456789,.'.split( '' ),
+ separatorTransformTable = mw.config.get( 'wgSeparatorTransformTable' ),
+ digitTransformTable = mw.config.get( 'wgDigitTransformTable' );
+
+ if ( separatorTransformTable === null || ( separatorTransformTable[ 0 ] === '' && digitTransformTable[ 2 ] === '' ) ) {
+ ts.transformTable = false;
+ } else {
+ ts.transformTable = {};
+
+ // Unpack the transform table
+ ascii = separatorTransformTable[ 0 ].split( '\t' ).concat( digitTransformTable[ 0 ].split( '\t' ) );
+ localised = separatorTransformTable[ 1 ].split( '\t' ).concat( digitTransformTable[ 1 ].split( '\t' ) );
+
+ // Construct regexes for number identification
+ for ( i = 0; i < ascii.length; i++ ) {
+ ts.transformTable[ localised[ i ] ] = ascii[ i ];
+ digits.push( mw.RegExp.escape( localised[ i ] ) );
+ }
+ }
+ digitClass = '[' + digits.join( '', digits ) + ']';
+
+ // We allow a trailing percent sign, which we just strip. This works fine
+ // if percents and regular numbers aren't being mixed.
+ ts.numberRegex = new RegExp(
+ '^(' +
+ '[-+\u2212]?[0-9][0-9,]*(\\.[0-9,]*)?(E[-+\u2212]?[0-9][0-9,]*)?' + // Fortran-style scientific
+ '|' +
+ '[-+\u2212]?' + digitClass + '+[\\s\\xa0]*%?' + // Generic localised
+ ')$',
+ 'i'
+ );
+ }
+
+ function buildDateTable() {
+ var i, name,
+ regex = [];
+
+ ts.monthNames = {};
+
+ for ( i = 0; i < 12; i++ ) {
+ name = mw.language.months.names[ i ].toLowerCase();
+ ts.monthNames[ name ] = i + 1;
+ regex.push( mw.RegExp.escape( name ) );
+ name = mw.language.months.genitive[ i ].toLowerCase();
+ ts.monthNames[ name ] = i + 1;
+ regex.push( mw.RegExp.escape( name ) );
+ name = mw.language.months.abbrev[ i ].toLowerCase().replace( '.', '' );
+ ts.monthNames[ name ] = i + 1;
+ regex.push( mw.RegExp.escape( name ) );
+ }
+
+ // Build piped string
+ regex = regex.join( '|' );
+
+ // Build RegEx
+ // Any date formated with . , ' - or /
+ ts.dateRegex[ 0 ] = new RegExp( /^\s*(\d{1,2})[,.\-/'\s]{1,2}(\d{1,2})[,.\-/'\s]{1,2}(\d{2,4})\s*?/i );
+
+ // Written Month name, dmy
+ ts.dateRegex[ 1 ] = new RegExp(
+ '^\\s*(\\d{1,2})[\\,\\.\\-\\/\'\\s]+(' +
+ regex +
+ ')' +
+ '[\\,\\.\\-\\/\'\\s]+(\\d{2,4})\\s*$',
+ 'i'
+ );
+
+ // Written Month name, mdy
+ ts.dateRegex[ 2 ] = new RegExp(
+ '^\\s*(' + regex + ')' +
+ '[\\,\\.\\-\\/\'\\s]+(\\d{1,2})[\\,\\.\\-\\/\'\\s]+(\\d{2,4})\\s*$',
+ 'i'
+ );
+
+ }
+
+ /**
+ * Replace all rowspanned cells in the body with clones in each row, so sorting
+ * need not worry about them.
+ *
+ * @param {jQuery} $table jQuery object for a <table>
+ */
+ function explodeRowspans( $table ) {
+ var spanningRealCellIndex, rowSpan, colSpan,
+ cell, cellData, i, $tds, $clone, $nextRows,
+ rowspanCells = $table.find( '> tbody > tr > [rowspan]' ).get();
+
+ // Short circuit
+ if ( !rowspanCells.length ) {
+ return;
+ }
+
+ // First, we need to make a property like cellIndex but taking into
+ // account colspans. We also cache the rowIndex to avoid having to take
+ // cell.parentNode.rowIndex in the sorting function below.
+ $table.find( '> tbody > tr' ).each( function () {
+ var i,
+ col = 0,
+ len = this.cells.length;
+ for ( i = 0; i < len; i++ ) {
+ $( this.cells[ i ] ).data( 'tablesorter', {
+ realCellIndex: col,
+ realRowIndex: this.rowIndex
+ } );
+ col += this.cells[ i ].colSpan;
+ }
+ } );
+
+ // Split multi row cells into multiple cells with the same content.
+ // Sort by column then row index to avoid problems with odd table structures.
+ // Re-sort whenever a rowspanned cell's realCellIndex is changed, because it
+ // might change the sort order.
+ function resortCells() {
+ var cellAData,
+ cellBData,
+ ret;
+ rowspanCells = rowspanCells.sort( function ( a, b ) {
+ cellAData = $.data( a, 'tablesorter' );
+ cellBData = $.data( b, 'tablesorter' );
+ ret = cellAData.realCellIndex - cellBData.realCellIndex;
+ if ( !ret ) {
+ ret = cellAData.realRowIndex - cellBData.realRowIndex;
+ }
+ return ret;
+ } );
+ $.each( rowspanCells, function () {
+ $.data( this, 'tablesorter' ).needResort = false;
+ } );
+ }
+ resortCells();
+
+ function filterfunc() {
+ return $.data( this, 'tablesorter' ).realCellIndex >= spanningRealCellIndex;
+ }
+
+ function fixTdCellIndex() {
+ $.data( this, 'tablesorter' ).realCellIndex += colSpan;
+ if ( this.rowSpan > 1 ) {
+ $.data( this, 'tablesorter' ).needResort = true;
+ }
+ }
+
+ while ( rowspanCells.length ) {
+ if ( $.data( rowspanCells[ 0 ], 'tablesorter' ).needResort ) {
+ resortCells();
+ }
+
+ cell = rowspanCells.shift();
+ cellData = $.data( cell, 'tablesorter' );
+ rowSpan = cell.rowSpan;
+ colSpan = cell.colSpan;
+ spanningRealCellIndex = cellData.realCellIndex;
+ cell.rowSpan = 1;
+ $nextRows = $( cell ).parent().nextAll();
+ for ( i = 0; i < rowSpan - 1; i++ ) {
+ $tds = $( $nextRows[ i ].cells ).filter( filterfunc );
+ $clone = $( cell ).clone();
+ $clone.data( 'tablesorter', {
+ realCellIndex: spanningRealCellIndex,
+ realRowIndex: cellData.realRowIndex + i,
+ needResort: true
+ } );
+ if ( $tds.length ) {
+ $tds.each( fixTdCellIndex );
+ $tds.first().before( $clone );
+ } else {
+ $nextRows.eq( i ).append( $clone );
+ }
+ }
+ }
+ }
+
+ /**
+ * Build index to handle colspanned cells in the body.
+ * Set the cell index for each column in an array,
+ * so that colspaned cells set multiple in this array.
+ * columnToCell[collumnIndex] point at the real cell in this row.
+ *
+ * @param {jQuery} $table object for a <table>
+ */
+ function manageColspans( $table ) {
+ var i, j, k, $row,
+ $rows = $table.find( '> tbody > tr' ),
+ totalRows = $rows.length || 0,
+ config = $table.data( 'tablesorter' ).config,
+ columns = config.columns,
+ columnToCell, cellsInRow, index;
+
+ for ( i = 0; i < totalRows; i++ ) {
+
+ $row = $rows.eq( i );
+ // if this is a child row, continue to the next row (as buildCache())
+ if ( $row.hasClass( config.cssChildRow ) ) {
+ // go to the next for loop
+ continue;
+ }
+
+ columnToCell = [];
+ cellsInRow = ( $row[ 0 ].cells.length ) || 0; // all cells in this row
+ index = 0; // real cell index in this row
+ for ( j = 0; j < columns; index++ ) {
+ if ( index === cellsInRow ) {
+ // Row with cells less than columns: add empty cell
+ $row.append( '<td>' );
+ cellsInRow++;
+ }
+ for ( k = 0; k < $row[ 0 ].cells[ index ].colSpan; k++ ) {
+ columnToCell[ j++ ] = index;
+ }
+ }
+ // Store it in $row
+ $row.data( 'columnToCell', columnToCell );
+ }
+ }
+
+ function buildCollationTable() {
+ var key, keys = [];
+ ts.collationTable = mw.config.get( 'tableSorterCollation' );
+ ts.collationRegex = null;
+ if ( ts.collationTable ) {
+ // Build array of key names
+ for ( key in ts.collationTable ) {
+ // Check hasOwn to be safe
+ if ( ts.collationTable.hasOwnProperty( key ) ) {
+ keys.push( mw.RegExp.escape( key ) );
+ }
+ }
+ if ( keys.length ) {
+ ts.collationRegex = new RegExp( keys.join( '|' ), 'ig' );
+ }
+ }
+ }
+
+ function cacheRegexs() {
+ if ( ts.rgx ) {
+ return;
+ }
+ ts.rgx = {
+ IPAddress: [
+ new RegExp( /^\d{1,3}[.]\d{1,3}[.]\d{1,3}[.]\d{1,3}$/ )
+ ],
+ currency: [
+ new RegExp( /(^[£$€¥]|[£$€¥]$)/ ),
+ new RegExp( /[£$€¥]/g )
+ ],
+ url: [
+ new RegExp( /^(https?|ftp|file):\/\/$/ ),
+ new RegExp( /(https?|ftp|file):\/\// )
+ ],
+ isoDate: [
+ new RegExp( /^[^-\d]*(-?\d{1,4})-(0\d|1[0-2])(-([0-3]\d))?([T\s]([01]\d|2[0-4]):?(([0-5]\d):?(([0-5]\d|60)([.,]\d{1,3})?)?)?([zZ]|([-+])([01]\d|2[0-3]):?([0-5]\d)?)?)?/ ),
+ new RegExp( /^[^-\d]*(-?\d{1,4})-?(\d\d)?(-?(\d\d))?([T\s](\d\d):?((\d\d)?:?((\d\d)?([.,]\d{1,3})?)?)?([zZ]|([-+])(\d\d):?(\d\d)?)?)?/ )
+ ],
+ usLongDate: [
+ new RegExp( /^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/ )
+ ],
+ time: [
+ new RegExp( /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/ )
+ ]
+ };
+ }
+
+ /**
+ * Converts sort objects [ { Integer: String }, ... ] to the internally used nested array
+ * structure [ [ Integer , Integer ], ... ]
+ *
+ * @param {Array} sortObjects List of sort objects.
+ * @return {Array} List of internal sort definitions.
+ */
+ function convertSortList( sortObjects ) {
+ var sortList = [];
+ $.each( sortObjects, function ( i, sortObject ) {
+ $.each( sortObject, function ( columnIndex, order ) {
+ var orderIndex = ( order === 'desc' ) ? 1 : 0;
+ sortList.push( [ parseInt( columnIndex, 10 ), orderIndex ] );
+ } );
+ } );
+ return sortList;
+ }
+
+ /* Public scope */
+
+ $.tablesorter = {
+ defaultOptions: {
+ cssHeader: 'headerSort',
+ cssAsc: 'headerSortUp',
+ cssDesc: 'headerSortDown',
+ cssChildRow: 'expand-child',
+ sortMultiSortKey: 'shiftKey',
+ unsortableClass: 'unsortable',
+ parsers: [],
+ cancelSelection: true,
+ sortList: [],
+ headerList: [],
+ headerToColumns: [],
+ columnToHeader: [],
+ columns: 0
+ },
+
+ dateRegex: [],
+ monthNames: {},
+
+ /**
+ * @param {jQuery} $tables
+ * @param {Object} [settings]
+ * @return {jQuery}
+ */
+ construct: function ( $tables, settings ) {
+ return $tables.each( function ( i, table ) {
+ // Declare and cache.
+ var $headers, cache, config, sortCSS, sortMsg,
+ $table = $( table ),
+ firstTime = true;
+
+ // Quit if no tbody
+ if ( !table.tBodies ) {
+ return;
+ }
+ if ( !table.tHead ) {
+ // No thead found. Look for rows with <th>s and
+ // move them into a <thead> tag or a <tfoot> tag
+ emulateTHeadAndFoot( $table );
+
+ // Still no thead? Then quit
+ if ( !table.tHead ) {
+ return;
+ }
+ }
+ $table.addClass( 'jquery-tablesorter' );
+
+ // Merge and extend
+ config = $.extend( {}, $.tablesorter.defaultOptions, settings );
+
+ // Save the settings where they read
+ $.data( table, 'tablesorter', { config: config } );
+
+ // Get the CSS class names, could be done elsewhere
+ sortCSS = [ config.cssAsc, config.cssDesc ];
+ // Messages tell the the user what the *next* state will be
+ // so are in reverse order to the CSS classes.
+ sortMsg = [ mw.msg( 'sort-descending' ), mw.msg( 'sort-ascending' ) ];
+
+ // Build headers
+ $headers = buildHeaders( table, sortMsg );
+
+ // Grab and process locale settings.
+ buildTransformTable();
+ buildDateTable();
+
+ // Precaching regexps can bring 10 fold
+ // performance improvements in some browsers.
+ cacheRegexs();
+
+ function setupForFirstSort() {
+ var $tfoot, $sortbottoms;
+
+ firstTime = false;
+
+ // Defer buildCollationTable to first sort. As user and site scripts
+ // may customize tableSorterCollation but load after $.ready(), other
+ // scripts may call .tablesorter() before they have done the
+ // tableSorterCollation customizations.
+ buildCollationTable();
+
+ // Legacy fix of .sortbottoms
+ // Wrap them inside a tfoot (because that's what they actually want to be)
+ // and put the <tfoot> at the end of the <table>
+ $sortbottoms = $table.find( '> tbody > tr.sortbottom' );
+ if ( $sortbottoms.length ) {
+ $tfoot = $table.children( 'tfoot' );
+ if ( $tfoot.length ) {
+ $tfoot.eq( 0 ).prepend( $sortbottoms );
+ } else {
+ $table.append( $( '<tfoot>' ).append( $sortbottoms ) );
+ }
+ }
+
+ explodeRowspans( $table );
+ manageColspans( $table );
+
+ // Try to auto detect column type, and store in tables config
+ config.parsers = buildParserCache( table, $headers );
+ }
+
+ // Apply event handling to headers
+ // this is too big, perhaps break it out?
+ $headers.on( 'keypress click', function ( e ) {
+ var cell, $cell, columns, newSortList, i,
+ totalRows,
+ j, s, o;
+
+ if ( e.type === 'click' && e.target.nodeName.toLowerCase() === 'a' ) {
+ // The user clicked on a link inside a table header.
+ // Do nothing and let the default link click action continue.
+ return true;
+ }
+
+ if ( e.type === 'keypress' && e.which !== 13 ) {
+ // Only handle keypresses on the "Enter" key.
+ return true;
+ }
+
+ if ( firstTime ) {
+ setupForFirstSort();
+ }
+
+ // Build the cache for the tbody cells
+ // to share between calculations for this sort action.
+ // Re-calculated each time a sort action is performed due to possiblity
+ // that sort values change. Shouldn't be too expensive, but if it becomes
+ // too slow an event based system should be implemented somehow where
+ // cells get event .change() and bubbles up to the <table> here
+ cache = buildCache( table );
+
+ totalRows = ( $table[ 0 ].tBodies[ 0 ] && $table[ 0 ].tBodies[ 0 ].rows.length ) || 0;
+ if ( totalRows > 0 ) {
+ cell = this;
+ $cell = $( cell );
+
+ // Get current column sort order
+ $cell.data( {
+ order: $cell.data( 'count' ) % 2,
+ count: $cell.data( 'count' ) + 1
+ } );
+
+ cell = this;
+ // Get current column index
+ columns = config.headerToColumns[ $cell.data( 'headerIndex' ) ];
+ newSortList = $.map( columns, function ( c ) {
+ // jQuery "helpfully" flattens the arrays...
+ return [ [ c, $cell.data( 'order' ) ] ];
+ } );
+ // Index of first column belonging to this header
+ i = columns[ 0 ];
+
+ if ( !e[ config.sortMultiSortKey ] ) {
+ // User only wants to sort on one column set
+ // Flush the sort list and add new columns
+ config.sortList = newSortList;
+ } else {
+ // Multi column sorting
+ // It is not possible for one column to belong to multiple headers,
+ // so this is okay - we don't need to check for every value in the columns array
+ if ( isValueInArray( i, config.sortList ) ) {
+ // The user has clicked on an already sorted column.
+ // Reverse the sorting direction for all tables.
+ for ( j = 0; j < config.sortList.length; j++ ) {
+ s = config.sortList[ j ];
+ o = config.headerList[ config.columnToHeader[ s[ 0 ] ] ];
+ if ( isValueInArray( s[ 0 ], newSortList ) ) {
+ $( o ).data( 'count', s[ 1 ] + 1 );
+ s[ 1 ] = $( o ).data( 'count' ) % 2;
+ }
+ }
+ } else {
+ // Add columns to sort list array
+ config.sortList = config.sortList.concat( newSortList );
+ }
+ }
+
+ // Reset order/counts of cells not affected by sorting
+ setHeadersOrder( $headers, config.sortList, config.headerToColumns );
+
+ // Set CSS for headers
+ setHeadersCss( $table[ 0 ], $headers, config.sortList, sortCSS, sortMsg, config.columnToHeader );
+ appendToTable(
+ $table[ 0 ], multisort( $table[ 0 ], config.sortList, cache )
+ );
+
+ // Stop normal event by returning false
+ return false;
+ }
+
+ // Cancel selection
+ } ).mousedown( function () {
+ if ( config.cancelSelection ) {
+ this.onselectstart = function () {
+ return false;
+ };
+ return false;
+ }
+ } );
+
+ /**
+ * Sorts the table. If no sorting is specified by passing a list of sort
+ * objects, the table is sorted according to the initial sorting order.
+ * Passing an empty array will reset sorting (basically just reset the headers
+ * making the table appear unsorted).
+ *
+ * @param {Array} [sortList] List of sort objects.
+ */
+ $table.data( 'tablesorter' ).sort = function ( sortList ) {
+
+ if ( firstTime ) {
+ setupForFirstSort();
+ }
+
+ if ( sortList === undefined ) {
+ sortList = config.sortList;
+ } else if ( sortList.length > 0 ) {
+ sortList = convertSortList( sortList );
+ }
+
+ // Set each column's sort count to be able to determine the correct sort
+ // order when clicking on a header cell the next time
+ setHeadersOrder( $headers, sortList, config.headerToColumns );
+
+ // re-build the cache for the tbody cells
+ cache = buildCache( table );
+
+ // set css for headers
+ setHeadersCss( table, $headers, sortList, sortCSS, sortMsg, config.columnToHeader );
+
+ // sort the table and append it to the dom
+ appendToTable( table, multisort( table, sortList, cache ) );
+ };
+
+ // sort initially
+ if ( config.sortList.length > 0 ) {
+ config.sortList = convertSortList( config.sortList );
+ $table.data( 'tablesorter' ).sort();
+ }
+
+ } );
+ },
+
+ addParser: function ( parser ) {
+ if ( !getParserById( parser.id ) ) {
+ parsers.push( parser );
+ }
+ },
+
+ formatDigit: function ( s ) {
+ var out, c, p, i;
+ if ( ts.transformTable !== false ) {
+ out = '';
+ for ( p = 0; p < s.length; p++ ) {
+ c = s.charAt( p );
+ if ( c in ts.transformTable ) {
+ out += ts.transformTable[ c ];
+ } else {
+ out += c;
+ }
+ }
+ s = out;
+ }
+ i = parseFloat( s.replace( /[, ]/g, '' ).replace( '\u2212', '-' ) );
+ return isNaN( i ) ? -Infinity : i;
+ },
+
+ formatFloat: function ( s ) {
+ var i = parseFloat( s );
+ return isNaN( i ) ? -Infinity : i;
+ },
+
+ formatInt: function ( s ) {
+ var i = parseInt( s, 10 );
+ return isNaN( i ) ? -Infinity : i;
+ },
+
+ clearTableBody: function ( table ) {
+ $( table.tBodies[ 0 ] ).empty();
+ },
+
+ getParser: function ( id ) {
+ buildTransformTable();
+ buildDateTable();
+ cacheRegexs();
+ buildCollationTable();
+
+ return getParserById( id );
+ },
+
+ getParsers: function () { // for table diagnosis
+ return parsers;
+ }
+ };
+
+ // Shortcut
+ ts = $.tablesorter;
+
+ // Register as jQuery prototype method
+ $.fn.tablesorter = function ( settings ) {
+ return ts.construct( this, settings );
+ };
+
+ // Add default parsers
+ ts.addParser( {
+ id: 'text',
+ is: function () {
+ return true;
+ },
+ format: function ( s ) {
+ var tsc;
+ s = $.trim( s.toLowerCase() );
+ if ( ts.collationRegex ) {
+ tsc = ts.collationTable;
+ s = s.replace( ts.collationRegex, function ( match ) {
+ var r = tsc[ match ] ? tsc[ match ] : tsc[ match.toUpperCase() ];
+ return r.toLowerCase();
+ } );
+ }
+ return s;
+ },
+ type: 'text'
+ } );
+
+ ts.addParser( {
+ id: 'IPAddress',
+ is: function ( s ) {
+ return ts.rgx.IPAddress[ 0 ].test( s );
+ },
+ format: function ( s ) {
+ var i, item,
+ a = s.split( '.' ),
+ r = '';
+ for ( i = 0; i < a.length; i++ ) {
+ item = a[ i ];
+ if ( item.length === 1 ) {
+ r += '00' + item;
+ } else if ( item.length === 2 ) {
+ r += '0' + item;
+ } else {
+ r += item;
+ }
+ }
+ return $.tablesorter.formatFloat( r );
+ },
+ type: 'numeric'
+ } );
+
+ ts.addParser( {
+ id: 'currency',
+ is: function ( s ) {
+ return ts.rgx.currency[ 0 ].test( s );
+ },
+ format: function ( s ) {
+ return $.tablesorter.formatDigit( s.replace( ts.rgx.currency[ 1 ], '' ) );
+ },
+ type: 'numeric'
+ } );
+
+ ts.addParser( {
+ id: 'url',
+ is: function ( s ) {
+ return ts.rgx.url[ 0 ].test( s );
+ },
+ format: function ( s ) {
+ return $.trim( s.replace( ts.rgx.url[ 1 ], '' ) );
+ },
+ type: 'text'
+ } );
+
+ ts.addParser( {
+ id: 'isoDate',
+ is: function ( s ) {
+ return ts.rgx.isoDate[ 0 ].test( s );
+ },
+ format: function ( s ) {
+ var match, i, isodate, ms, hOffset, mOffset;
+ match = s.match( ts.rgx.isoDate[ 0 ] );
+ if ( match === null ) {
+ // Otherwise a signed number with 1-4 digit is parsed as isoDate
+ match = s.match( ts.rgx.isoDate[ 1 ] );
+ }
+ if ( !match ) {
+ return -Infinity;
+ }
+ // Month and day
+ for ( i = 2; i <= 4; i += 2 ) {
+ if ( !match[ i ] || match[ i ].length === 0 ) {
+ match[ i ] = 1;
+ }
+ }
+ // Time
+ for ( i = 6; i <= 15; i++ ) {
+ if ( !match[ i ] || match[ i ].length === 0 ) {
+ match[ i ] = '0';
+ }
+ }
+ ms = parseFloat( match[ 11 ].replace( /,/, '.' ) ) * 1000;
+ hOffset = $.tablesorter.formatInt( match[ 13 ] + match[ 14 ] );
+ mOffset = $.tablesorter.formatInt( match[ 13 ] + match[ 15 ] );
+
+ isodate = new Date( 0 );
+ // Because Date constructor changes year 0-99 to 1900-1999, use setUTCFullYear()
+ isodate.setUTCFullYear( match[ 1 ], match[ 2 ] - 1, match[ 4 ] );
+ isodate.setUTCHours( match[ 6 ] - hOffset, match[ 8 ] - mOffset, match[ 10 ], ms );
+ return isodate.getTime();
+ },
+ type: 'numeric'
+ } );
+
+ ts.addParser( {
+ id: 'usLongDate',
+ is: function ( s ) {
+ return ts.rgx.usLongDate[ 0 ].test( s );
+ },
+ format: function ( s ) {
+ return $.tablesorter.formatFloat( new Date( s ).getTime() );
+ },
+ type: 'numeric'
+ } );
+
+ ts.addParser( {
+ id: 'date',
+ is: function ( s ) {
+ return ( ts.dateRegex[ 0 ].test( s ) || ts.dateRegex[ 1 ].test( s ) || ts.dateRegex[ 2 ].test( s ) );
+ },
+ format: function ( s ) {
+ var match, y;
+ s = $.trim( s.toLowerCase() );
+
+ if ( ( match = s.match( ts.dateRegex[ 0 ] ) ) !== null ) {
+ if ( mw.config.get( 'wgDefaultDateFormat' ) === 'mdy' || mw.config.get( 'wgPageContentLanguage' ) === 'en' ) {
+ s = [ match[ 3 ], match[ 1 ], match[ 2 ] ];
+ } else if ( mw.config.get( 'wgDefaultDateFormat' ) === 'dmy' ) {
+ s = [ match[ 3 ], match[ 2 ], match[ 1 ] ];
+ } else {
+ // If we get here, we don't know which order the dd-dd-dddd
+ // date is in. So return something not entirely invalid.
+ return '99999999';
+ }
+ } else if ( ( match = s.match( ts.dateRegex[ 1 ] ) ) !== null ) {
+ s = [ match[ 3 ], String( ts.monthNames[ match[ 2 ] ] ), match[ 1 ] ];
+ } else if ( ( match = s.match( ts.dateRegex[ 2 ] ) ) !== null ) {
+ s = [ match[ 3 ], String( ts.monthNames[ match[ 1 ] ] ), match[ 2 ] ];
+ } else {
+ // Should never get here
+ return '99999999';
+ }
+
+ // Pad Month and Day
+ if ( s[ 1 ].length === 1 ) {
+ s[ 1 ] = '0' + s[ 1 ];
+ }
+ if ( s[ 2 ].length === 1 ) {
+ s[ 2 ] = '0' + s[ 2 ];
+ }
+
+ if ( ( y = parseInt( s[ 0 ], 10 ) ) < 100 ) {
+ // Guestimate years without centuries
+ if ( y < 30 ) {
+ s[ 0 ] = 2000 + y;
+ } else {
+ s[ 0 ] = 1900 + y;
+ }
+ }
+ while ( s[ 0 ].length < 4 ) {
+ s[ 0 ] = '0' + s[ 0 ];
+ }
+ return parseInt( s.join( '' ), 10 );
+ },
+ type: 'numeric'
+ } );
+
+ ts.addParser( {
+ id: 'time',
+ is: function ( s ) {
+ return ts.rgx.time[ 0 ].test( s );
+ },
+ format: function ( s ) {
+ return $.tablesorter.formatFloat( new Date( '2000/01/01 ' + s ).getTime() );
+ },
+ type: 'numeric'
+ } );
+
+ ts.addParser( {
+ id: 'number',
+ is: function ( s ) {
+ return $.tablesorter.numberRegex.test( $.trim( s ) );
+ },
+ format: function ( s ) {
+ return $.tablesorter.formatDigit( s );
+ },
+ type: 'numeric'
+ } );
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/jquery/jquery.tablesorter.less b/www/wiki/resources/src/jquery/jquery.tablesorter.less
new file mode 100644
index 00000000..11f472ec
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.tablesorter.less
@@ -0,0 +1,19 @@
+@import 'mediawiki.mixins';
+
+/* Table Sorting */
+
+table.jquery-tablesorter th.headerSort {
+ .background-image-svg( 'images/sort_both.svg', 'images/sort_both.png' );
+ cursor: pointer;
+ background-repeat: no-repeat;
+ background-position: center right;
+ padding-right: 21px;
+}
+
+table.jquery-tablesorter th.headerSortUp {
+ .background-image-svg( 'images/sort_up.svg', 'images/sort_up.png' );
+}
+
+table.jquery-tablesorter th.headerSortDown {
+ .background-image-svg( 'images/sort_down.svg', 'images/sort_down.png' );
+}
diff --git a/www/wiki/resources/src/jquery/jquery.textSelection.js b/www/wiki/resources/src/jquery/jquery.textSelection.js
new file mode 100644
index 00000000..c6ad945a
--- /dev/null
+++ b/www/wiki/resources/src/jquery/jquery.textSelection.js
@@ -0,0 +1,610 @@
+/**
+ * These plugins provide extra functionality for interaction with textareas.
+ */
+( function ( $ ) {
+ if ( document.selection && document.selection.createRange ) {
+ // On IE, patch the focus() method to restore the windows' scroll position
+ // (T34241)
+ $.fn.extend( {
+ focus: ( function ( jqFocus ) {
+ return function () {
+ var $w, state, result;
+ if ( arguments.length === 0 ) {
+ $w = $( window );
+ state = { top: $w.scrollTop(), left: $w.scrollLeft() };
+ result = jqFocus.apply( this, arguments );
+ window.scrollTo( state.top, state.left );
+ return result;
+ }
+ return jqFocus.apply( this, arguments );
+ };
+ }( $.fn.focus ) )
+ } );
+ }
+
+ $.fn.textSelection = function ( command, options ) {
+ var fn,
+ alternateFn,
+ context,
+ hasWikiEditor,
+ needSave,
+ retval;
+
+ /**
+ * Helper function to get an IE TextRange object for an element
+ *
+ * @param {HTMLElement} element
+ * @return {TextRange}
+ */
+ function rangeForElementIE( element ) {
+ var sel;
+ if ( element.nodeName.toLowerCase() === 'input' ) {
+ return element.createTextRange();
+ } else {
+ sel = document.body.createTextRange();
+ sel.moveToElementText( element );
+ return sel;
+ }
+ }
+
+ /**
+ * Helper function for IE for activating the textarea. Called only in the
+ * IE-specific code paths below; makes use of IE-specific non-standard
+ * function setActive() if possible to avoid screen flicker.
+ *
+ * @param {HTMLElement} element
+ */
+ function activateElementOnIE( element ) {
+ if ( element.setActive ) {
+ element.setActive(); // T34241: doesn't scroll
+ } else {
+ $( element ).focus(); // may scroll (but we patched it above)
+ }
+ }
+
+ fn = {
+ /**
+ * Get the contents of the textarea
+ *
+ * @return {string}
+ */
+ getContents: function () {
+ return this.val();
+ },
+ /**
+ * Set the contents of the textarea, replacing anything that was there before
+ *
+ * @param {string} content
+ */
+ setContents: function ( content ) {
+ this.val( content );
+ },
+ /**
+ * Get the currently selected text in this textarea. Will focus the textarea
+ * in some browsers (IE/Opera)
+ *
+ * @return {string}
+ */
+ getSelection: function () {
+ var retval, range,
+ el = this.get( 0 );
+
+ if ( !el || $( el ).is( ':hidden' ) ) {
+ retval = '';
+ } else if ( document.selection && document.selection.createRange ) {
+ activateElementOnIE( el );
+ range = document.selection.createRange();
+ retval = range.text;
+ } else if ( el.selectionStart || el.selectionStart === 0 ) {
+ retval = el.value.substring( el.selectionStart, el.selectionEnd );
+ }
+
+ return retval;
+ },
+ /**
+ * Ported from skins/common/edit.js by Trevor Parscal
+ * (c) 2009 Wikimedia Foundation (GPLv2) - http://www.wikimedia.org
+ *
+ * Inserts text at the beginning and end of a text selection, optionally
+ * inserting text at the caret when selection is empty.
+ *
+ * @param {Object} options Options
+ * FIXME document the options parameters
+ * @return {jQuery}
+ */
+ encapsulateSelection: function ( options ) {
+ return this.each( function () {
+ var selText, scrollTop, insertText,
+ isSample, range, range2, range3, startPos, endPos,
+ pre = options.pre,
+ post = options.post;
+
+ /**
+ * Check if the selected text is the same as the insert text
+ */
+ function checkSelectedText() {
+ if ( !selText ) {
+ selText = options.peri;
+ isSample = true;
+ } else if ( options.replace ) {
+ selText = options.peri;
+ } else {
+ while ( selText.charAt( selText.length - 1 ) === ' ' ) {
+ // Exclude ending space char
+ selText = selText.slice( 0, -1 );
+ post += ' ';
+ }
+ while ( selText.charAt( 0 ) === ' ' ) {
+ // Exclude prepending space char
+ selText = selText.slice( 1 );
+ pre = ' ' + pre;
+ }
+ }
+ }
+
+ /**
+ * Do the splitlines stuff.
+ *
+ * Wrap each line of the selected text with pre and post
+ *
+ * @param {string} selText Selected text
+ * @param {string} pre Text before
+ * @param {string} post Text after
+ * @return {string} Wrapped text
+ */
+ function doSplitLines( selText, pre, post ) {
+ var i,
+ insertText = '',
+ selTextArr = selText.split( '\n' );
+ for ( i = 0; i < selTextArr.length; i++ ) {
+ insertText += pre + selTextArr[ i ] + post;
+ if ( i !== selTextArr.length - 1 ) {
+ insertText += '\n';
+ }
+ }
+ return insertText;
+ }
+
+ isSample = false;
+ // Do nothing if display none
+ if ( this.style.display !== 'none' ) {
+ if ( document.selection && document.selection.createRange ) {
+ // IE
+
+ // Note that IE9 will trigger the next section unless we check this first.
+ // See bug T37201.
+
+ activateElementOnIE( this );
+ if ( context ) {
+ context.fn.restoreCursorAndScrollTop();
+ }
+ if ( options.selectionStart !== undefined ) {
+ $( this ).textSelection( 'setSelection', { start: options.selectionStart, end: options.selectionEnd } );
+ }
+
+ selText = $( this ).textSelection( 'getSelection' );
+ scrollTop = this.scrollTop;
+ range = document.selection.createRange();
+
+ checkSelectedText();
+ insertText = pre + selText + post;
+ if ( options.splitlines ) {
+ insertText = doSplitLines( selText, pre, post );
+ }
+ if ( options.ownline && range.moveStart ) {
+ range2 = document.selection.createRange();
+ range2.collapse();
+ range2.moveStart( 'character', -1 );
+ // FIXME: Which check is correct?
+ if ( range2.text !== '\r' && range2.text !== '\n' && range2.text !== '' ) {
+ insertText = '\n' + insertText;
+ pre += '\n';
+ }
+ range3 = document.selection.createRange();
+ range3.collapse( false );
+ range3.moveEnd( 'character', 1 );
+ if ( range3.text !== '\r' && range3.text !== '\n' && range3.text !== '' ) {
+ insertText += '\n';
+ post += '\n';
+ }
+ }
+
+ range.text = insertText;
+ if ( isSample && options.selectPeri && range.moveStart ) {
+ range.moveStart( 'character', -post.length - selText.length );
+ range.moveEnd( 'character', -post.length );
+ }
+ range.select();
+ // Restore the scroll position
+ this.scrollTop = scrollTop;
+ } else if ( this.selectionStart || this.selectionStart === 0 ) {
+ // Mozilla/Opera
+
+ $( this ).focus();
+ if ( options.selectionStart !== undefined ) {
+ $( this ).textSelection( 'setSelection', { start: options.selectionStart, end: options.selectionEnd } );
+ }
+
+ selText = $( this ).textSelection( 'getSelection' );
+ startPos = this.selectionStart;
+ endPos = this.selectionEnd;
+ scrollTop = this.scrollTop;
+ checkSelectedText();
+ if (
+ options.selectionStart !== undefined &&
+ endPos - startPos !== options.selectionEnd - options.selectionStart
+ ) {
+ // This means there is a difference in the selection range returned by browser and what we passed.
+ // This happens for Chrome in the case of composite characters. Ref bug #30130
+ // Set the startPos to the correct position.
+ startPos = options.selectionStart;
+ }
+
+ insertText = pre + selText + post;
+ if ( options.splitlines ) {
+ insertText = doSplitLines( selText, pre, post );
+ }
+ if ( options.ownline ) {
+ if ( startPos !== 0 && this.value.charAt( startPos - 1 ) !== '\n' && this.value.charAt( startPos - 1 ) !== '\r' ) {
+ insertText = '\n' + insertText;
+ pre += '\n';
+ }
+ if ( this.value.charAt( endPos ) !== '\n' && this.value.charAt( endPos ) !== '\r' ) {
+ insertText += '\n';
+ post += '\n';
+ }
+ }
+ this.value = this.value.slice( 0, startPos ) + insertText +
+ this.value.slice( endPos );
+ // Setting this.value scrolls the textarea to the top, restore the scroll position
+ this.scrollTop = scrollTop;
+ if ( window.opera ) {
+ pre = pre.replace( /\r?\n/g, '\r\n' );
+ selText = selText.replace( /\r?\n/g, '\r\n' );
+ post = post.replace( /\r?\n/g, '\r\n' );
+ }
+ if ( isSample && options.selectPeri && ( !options.splitlines || ( options.splitlines && selText.indexOf( '\n' ) === -1 ) ) ) {
+ this.selectionStart = startPos + pre.length;
+ this.selectionEnd = startPos + pre.length + selText.length;
+ } else {
+ this.selectionStart = startPos + insertText.length;
+ this.selectionEnd = this.selectionStart;
+ }
+ }
+ }
+ $( this ).trigger( 'encapsulateSelection', [ options.pre, options.peri, options.post, options.ownline,
+ options.replace, options.spitlines ] );
+ } );
+ },
+ /**
+ * Ported from Wikia's LinkSuggest extension
+ * https://svn.wikia-code.com/wikia/trunk/extensions/wikia/LinkSuggest
+ * Some code copied from
+ * http://www.dedestruct.com/2008/03/22/howto-cross-browser-cursor-position-in-textareas/
+ *
+ * Get the position (in resolution of bytes not necessarily characters)
+ * in a textarea
+ *
+ * Will focus the textarea in some browsers (IE/Opera)
+ *
+ * @param {Object} options Options
+ * FIXME document the options parameters
+ * @return {number} Position
+ */
+ getCaretPosition: function ( options ) {
+ function getCaret( e ) {
+ var caretPos = 0,
+ endPos = 0,
+ preText, rawPreText, periText,
+ rawPeriText, postText,
+ // IE Support
+ preFinished,
+ periFinished,
+ postFinished,
+ // Range containing text in the selection
+ periRange,
+ // Range containing text before the selection
+ preRange,
+ // Range containing text after the selection
+ postRange;
+
+ if ( e && document.selection && document.selection.createRange ) {
+ // IE doesn't properly report non-selected caret position through
+ // the selection ranges when textarea isn't focused. This can
+ // lead to saving a bogus empty selection, which then screws up
+ // whatever we do later (T33847).
+ activateElementOnIE( e );
+
+ preFinished = false;
+ periFinished = false;
+ postFinished = false;
+ periRange = document.selection.createRange().duplicate();
+
+ preRange = rangeForElementIE( e );
+ // Move the end where we need it
+ preRange.setEndPoint( 'EndToStart', periRange );
+
+ postRange = rangeForElementIE( e );
+ // Move the start where we need it
+ postRange.setEndPoint( 'StartToEnd', periRange );
+
+ // Load the text values we need to compare
+ preText = rawPreText = preRange.text;
+ periText = rawPeriText = periRange.text;
+ postText = postRange.text;
+
+ /*
+ * Check each range for trimmed newlines by shrinking the range by 1
+ * character and seeing if the text property has changed. If it has
+ * not changed then we know that IE has trimmed a \r\n from the end.
+ */
+ do {
+ if ( !preFinished ) {
+ if ( preRange.compareEndPoints( 'StartToEnd', preRange ) === 0 ) {
+ preFinished = true;
+ } else {
+ preRange.moveEnd( 'character', -1 );
+ if ( preRange.text === preText ) {
+ rawPreText += '\r\n';
+ } else {
+ preFinished = true;
+ }
+ }
+ }
+ if ( !periFinished ) {
+ if ( periRange.compareEndPoints( 'StartToEnd', periRange ) === 0 ) {
+ periFinished = true;
+ } else {
+ periRange.moveEnd( 'character', -1 );
+ if ( periRange.text === periText ) {
+ rawPeriText += '\r\n';
+ } else {
+ periFinished = true;
+ }
+ }
+ }
+ if ( !postFinished ) {
+ if ( postRange.compareEndPoints( 'StartToEnd', postRange ) === 0 ) {
+ postFinished = true;
+ } else {
+ postRange.moveEnd( 'character', -1 );
+ if ( postRange.text !== postText ) {
+ postFinished = true;
+ }
+ }
+ }
+ } while ( ( !preFinished || !periFinished || !postFinished ) );
+ caretPos = rawPreText.replace( /\r\n/g, '\n' ).length;
+ endPos = caretPos + rawPeriText.replace( /\r\n/g, '\n' ).length;
+ } else if ( e && ( e.selectionStart || e.selectionStart === 0 ) ) {
+ // Firefox support
+ caretPos = e.selectionStart;
+ endPos = e.selectionEnd;
+ }
+ return options.startAndEnd ? [ caretPos, endPos ] : caretPos;
+ }
+ return getCaret( this.get( 0 ) );
+ },
+ /**
+ * @param {Object} options options
+ * FIXME document the options parameters
+ * @return {jQuery}
+ */
+ setSelection: function ( options ) {
+ return this.each( function () {
+ var selection, length, newLines;
+ // Do nothing if hidden
+ if ( !$( this ).is( ':hidden' ) ) {
+ if ( this.selectionStart || this.selectionStart === 0 ) {
+ // Opera 9.0 doesn't allow setting selectionStart past
+ // selectionEnd; any attempts to do that will be ignored
+ // Make sure to set them in the right order
+ if ( options.start > this.selectionEnd ) {
+ this.selectionEnd = options.end;
+ this.selectionStart = options.start;
+ } else {
+ this.selectionStart = options.start;
+ this.selectionEnd = options.end;
+ }
+ } else if ( document.body.createTextRange ) {
+ selection = rangeForElementIE( this );
+ length = this.value.length;
+ // IE doesn't count \n when computing the offset, so we won't either
+ newLines = this.value.match( /\n/g );
+ if ( newLines ) {
+ length = length - newLines.length;
+ }
+ selection.moveStart( 'character', options.start );
+ selection.moveEnd( 'character', -length + options.end );
+
+ // This line can cause an error under certain circumstances (textarea empty, no selection)
+ // Silence that error
+ try {
+ selection.select();
+ } catch ( e ) { }
+ }
+ }
+ } );
+ },
+ /**
+ * Ported from Wikia's LinkSuggest extension
+ * https://svn.wikia-code.com/wikia/trunk/extensions/wikia/LinkSuggest
+ *
+ * Scroll a textarea to the current cursor position. You can set the cursor
+ * position with setSelection()
+ *
+ * @param {Object} options options
+ * @cfg {boolean} [force=false] Whether to force a scroll even if the caret position
+ * is already visible.
+ * FIXME document the options parameters
+ * @return {jQuery}
+ */
+ scrollToCaretPosition: function ( options ) {
+ function getLineLength( e ) {
+ return Math.floor( e.scrollWidth / ( $.client.profile().platform === 'linux' ? 7 : 8 ) );
+ }
+ function getCaretScrollPosition( e ) {
+ // FIXME: This functions sucks and is off by a few lines most
+ // of the time. It should be replaced by something decent.
+ var i, j,
+ nextSpace,
+ text = e.value.replace( /\r/g, '' ),
+ caret = $( e ).textSelection( 'getCaretPosition' ),
+ lineLength = getLineLength( e ),
+ row = 0,
+ charInLine = 0,
+ lastSpaceInLine = 0;
+
+ for ( i = 0; i < caret; i++ ) {
+ charInLine++;
+ if ( text.charAt( i ) === ' ' ) {
+ lastSpaceInLine = charInLine;
+ } else if ( text.charAt( i ) === '\n' ) {
+ lastSpaceInLine = 0;
+ charInLine = 0;
+ row++;
+ }
+ if ( charInLine > lineLength ) {
+ if ( lastSpaceInLine > 0 ) {
+ charInLine = charInLine - lastSpaceInLine;
+ lastSpaceInLine = 0;
+ row++;
+ }
+ }
+ }
+ nextSpace = 0;
+ for ( j = caret; j < caret + lineLength; j++ ) {
+ if (
+ text.charAt( j ) === ' ' ||
+ text.charAt( j ) === '\n' ||
+ caret === text.length
+ ) {
+ nextSpace = j;
+ break;
+ }
+ }
+ if ( nextSpace > lineLength && caret <= lineLength ) {
+ charInLine = caret - lastSpaceInLine;
+ row++;
+ }
+ return ( $.client.profile().platform === 'mac' ? 13 : ( $.client.profile().platform === 'linux' ? 15 : 16 ) ) * row;
+ }
+ return this.each( function () {
+ var scroll, range, savedRange, pos, oldScrollTop;
+ // Do nothing if hidden
+ if ( !$( this ).is( ':hidden' ) ) {
+ if ( this.selectionStart || this.selectionStart === 0 ) {
+ // Mozilla
+ scroll = getCaretScrollPosition( this );
+ if ( options.force || scroll < $( this ).scrollTop() ||
+ scroll > $( this ).scrollTop() + $( this ).height() ) {
+ $( this ).scrollTop( scroll );
+ }
+ } else if ( document.selection && document.selection.createRange ) {
+ // IE / Opera
+ /*
+ * IE automatically scrolls the selected text to the
+ * bottom of the textarea at range.select() time, except
+ * if it was already in view and the cursor position
+ * wasn't changed, in which case it does nothing. To
+ * cover that case, we'll force it to act by moving one
+ * character back and forth.
+ */
+ range = document.body.createTextRange();
+ savedRange = document.selection.createRange();
+ pos = $( this ).textSelection( 'getCaretPosition' );
+ oldScrollTop = this.scrollTop;
+ range.moveToElementText( this );
+ range.collapse();
+ range.move( 'character', pos + 1 );
+ range.select();
+ if ( this.scrollTop !== oldScrollTop ) {
+ this.scrollTop += range.offsetTop;
+ } else if ( options.force ) {
+ range.move( 'character', -1 );
+ range.select();
+ }
+ savedRange.select();
+ }
+ }
+ $( this ).trigger( 'scrollToPosition' );
+ } );
+ }
+ };
+
+ alternateFn = $( this ).data( 'jquery.textSelection' );
+
+ // Apply defaults
+ switch ( command ) {
+ // case 'getContents': // no params
+ // case 'setContents': // no params with defaults
+ // case 'getSelection': // no params
+ case 'encapsulateSelection':
+ options = $.extend( {
+ pre: '', // Text to insert before the cursor/selection
+ peri: '', // Text to insert between pre and post and select afterwards
+ post: '', // Text to insert after the cursor/selection
+ ownline: false, // Put the inserted text on a line of its own
+ replace: false, // If there is a selection, replace it with peri instead of leaving it alone
+ selectPeri: true, // Select the peri text if it was inserted (but not if there was a selection and replace==false, or if splitlines==true)
+ splitlines: false, // If multiple lines are selected, encapsulate each line individually
+ selectionStart: undefined, // Position to start selection at
+ selectionEnd: undefined // Position to end selection at. Defaults to start
+ }, options );
+ break;
+ case 'getCaretPosition':
+ options = $.extend( {
+ // Return [start, end] instead of just start
+ startAndEnd: false
+ }, options );
+ // FIXME: We may not need character position-based functions if we insert markers in the right places
+ break;
+ case 'setSelection':
+ options = $.extend( {
+ // Position to start selection at
+ start: undefined,
+ // Position to end selection at. Defaults to start
+ end: undefined
+ }, options );
+
+ if ( options.end === undefined ) {
+ options.end = options.start;
+ }
+ // FIXME: We may not need character position-based functions if we insert markers in the right places
+ break;
+ case 'scrollToCaretPosition':
+ options = $.extend( {
+ force: false // Force a scroll even if the caret position is already visible
+ }, options );
+ break;
+ case 'register':
+ if ( alternateFn ) {
+ throw new Error( 'Another textSelection API was already registered' );
+ }
+ $( this ).data( 'jquery.textSelection', options );
+ // No need to update alternateFn as this command only stores the options.
+ // A command that uses it will set it again.
+ return;
+ case 'unregister':
+ $( this ).removeData( 'jquery.textSelection' );
+ return;
+ }
+
+ context = $( this ).data( 'wikiEditor-context' );
+ hasWikiEditor = ( context !== undefined && context.$iframe !== undefined );
+
+ // IE selection restore voodoo
+ needSave = false;
+ if ( hasWikiEditor && context.savedSelection !== null ) {
+ context.fn.restoreSelection();
+ needSave = true;
+ }
+ retval = ( alternateFn && alternateFn[ command ] || fn[ command ] ).call( this, options );
+ if ( hasWikiEditor && needSave ) {
+ context.fn.saveSelection();
+ }
+
+ return retval;
+ };
+
+}( jQuery ) );
diff --git a/www/wiki/resources/src/json-skip.js b/www/wiki/resources/src/json-skip.js
new file mode 100644
index 00000000..0a1e1c26
--- /dev/null
+++ b/www/wiki/resources/src/json-skip.js
@@ -0,0 +1,4 @@
+/*!
+ * Skip function for json2.js.
+ */
+return !!( window.JSON && JSON.stringify && JSON.parse );
diff --git a/www/wiki/resources/src/mediawiki.action/images/checker.png b/www/wiki/resources/src/mediawiki.action/images/checker.png
new file mode 100644
index 00000000..3e9e3d09
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/checker.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.action/images/close.png b/www/wiki/resources/src/mediawiki.action/images/close.png
new file mode 100644
index 00000000..80dde951
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/close.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.action/images/close.svg b/www/wiki/resources/src/mediawiki.action/images/close.svg
new file mode 100644
index 00000000..7f755112
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/close.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20">
+ <path d="M3.636 2.222l14.142 14.142-1.414 1.414L2.222 3.636z"/>
+ <path d="M17.778 3.636L3.636 17.778l-1.414-1.414L16.364 2.222z"/>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.action/images/green-checkmark.png b/www/wiki/resources/src/mediawiki.action/images/green-checkmark.png
new file mode 100644
index 00000000..9fc58003
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/green-checkmark.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.action/images/nextredirect-ltr.png b/www/wiki/resources/src/mediawiki.action/images/nextredirect-ltr.png
new file mode 100644
index 00000000..d99ba3ce
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/nextredirect-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.action/images/nextredirect-ltr.svg b/www/wiki/resources/src/mediawiki.action/images/nextredirect-ltr.svg
new file mode 100644
index 00000000..6932e580
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/nextredirect-ltr.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="42" height="20" viewBox="0 0 42 20">
+ <g id="Layer_2">
+ <path fill="#fff" stroke="#000" stroke-width="2" stroke-miterlimit="10" d="M11 10h17.064"/>
+ </g>
+ <g id="Layer_3">
+ <path d="M23 6l8 4-8 4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.action/images/nextredirect-rtl.png b/www/wiki/resources/src/mediawiki.action/images/nextredirect-rtl.png
new file mode 100644
index 00000000..a25d78a1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/nextredirect-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.action/images/nextredirect-rtl.svg b/www/wiki/resources/src/mediawiki.action/images/nextredirect-rtl.svg
new file mode 100644
index 00000000..b309da94
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/nextredirect-rtl.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="42" height="20" viewBox="0 0 42 20">
+ <g id="Layer_2">
+ <path fill="#fff" stroke="#000" stroke-width="2" stroke-miterlimit="10" d="M31 10H13.936"/>
+ </g>
+ <g id="Layer_3">
+ <path d="M19 6l-8 4 8 4z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.action/images/redirect-ltr.png b/www/wiki/resources/src/mediawiki.action/images/redirect-ltr.png
new file mode 100644
index 00000000..ef4a110b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/redirect-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.action/images/redirect-ltr.svg b/www/wiki/resources/src/mediawiki.action/images/redirect-ltr.svg
new file mode 100644
index 00000000..713be6cb
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/redirect-ltr.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="47" height="20" viewBox="0 0 47 20">
+ <g id="Layer_1">
+ <path fill="none" stroke="#000" stroke-width="2" stroke-miterlimit="10" d="M14.98 2.5V11c0 1.04 1.02 1.98 2.02 1.98h6l3 .02"/>
+ </g>
+ <g id="Layer_3">
+ <path d="M23.48 9.5l.02 7L30 13z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.action/images/redirect-rtl.png b/www/wiki/resources/src/mediawiki.action/images/redirect-rtl.png
new file mode 100644
index 00000000..c883795e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/redirect-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.action/images/redirect-rtl.svg b/www/wiki/resources/src/mediawiki.action/images/redirect-rtl.svg
new file mode 100644
index 00000000..ce0c7c92
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/images/redirect-rtl.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="47" height="20" viewBox="0 0 47 20">
+ <g id="Layer_1">
+ <path fill="none" stroke="#000" stroke-width="2" stroke-miterlimit="10" d="M32.002 2.5V11c0 1.04-1.02 1.98-2.02 1.98h-6l-3 .02"/>
+ </g>
+ <g id="Layer_3">
+ <path d="M23.502 9.5l-.02 7-6.5-3.5z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css
new file mode 100644
index 00000000..1af4a7a0
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.css
@@ -0,0 +1,17 @@
+/* Styles for collapsible lists of templates used and hidden categories */
+.mw-editfooter-toggler {
+ cursor: pointer;
+ background-position: left center;
+ padding-left: 16px;
+}
+
+.mw-editfooter-list {
+ margin-bottom: 1em;
+ margin-left: 2.5em;
+}
+
+/* Show/hide animation is incorrect if the table has a margin set. Extra
+ * "table.wikitable" is needed in the selector for CSS specificity. */
+table.wikitable.preview-limit-report {
+ margin: 0;
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js
new file mode 100644
index 00000000..938962f3
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.collapsibleFooter.js
@@ -0,0 +1,66 @@
+( function ( mw ) {
+ var collapsibleLists, handleOne;
+
+ // Collapsible lists of categories and templates
+ // If changing or removing a storeKey, ensure there is a strategy for old keys.
+ // E.g. detect existence via requestIdleCallback and remove. (T121646)
+ collapsibleLists = [
+ {
+ listSel: '.templatesUsed ul',
+ togglerSel: '.mw-templatesUsedExplanation',
+ storeKey: 'mwedit-state-templatesUsed'
+ },
+ {
+ listSel: '.hiddencats ul',
+ togglerSel: '.mw-hiddenCategoriesExplanation',
+ storeKey: 'mwedit-state-hiddenCategories'
+ },
+ {
+ listSel: '.preview-limit-report-wrapper',
+ togglerSel: '.mw-limitReportExplanation',
+ storeKey: 'mwedit-state-limitReport'
+ }
+ ];
+
+ handleOne = function ( $list, $toggler, storeKey ) {
+ var collapsedVal = '0',
+ expandedVal = '1',
+ // Default to collapsed if not set
+ isCollapsed = mw.storage.get( storeKey ) !== expandedVal;
+
+ // Style the toggler with an arrow icon and add a tabIndex and a role for accessibility
+ $toggler.addClass( 'mw-editfooter-toggler' ).prop( 'tabIndex', 0 ).attr( 'role', 'button' );
+ $list.addClass( 'mw-editfooter-list' );
+
+ $list.makeCollapsible( {
+ $customTogglers: $toggler,
+ linksPassthru: true,
+ plainMode: true,
+ collapsed: isCollapsed
+ } );
+
+ $toggler.addClass( isCollapsed ? 'mw-icon-arrow-collapsed' : 'mw-icon-arrow-expanded' );
+
+ $list.on( 'beforeExpand.mw-collapsible', function () {
+ $toggler.removeClass( 'mw-icon-arrow-collapsed' ).addClass( 'mw-icon-arrow-expanded' );
+ mw.storage.set( storeKey, expandedVal );
+ } );
+
+ $list.on( 'beforeCollapse.mw-collapsible', function () {
+ $toggler.removeClass( 'mw-icon-arrow-expanded' ).addClass( 'mw-icon-arrow-collapsed' );
+ mw.storage.set( storeKey, collapsedVal );
+ } );
+ };
+
+ mw.hook( 'wikipage.editform' ).add( function ( $editForm ) {
+ var i;
+ for ( i = 0; i < collapsibleLists.length; i++ ) {
+ // Pass to a function for iteration-local variables
+ handleOne(
+ $editForm.find( collapsibleLists[ i ].listSel ),
+ $editForm.find( collapsibleLists[ i ].togglerSel ),
+ collapsibleLists[ i ].storeKey
+ );
+ }
+ } );
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.css
new file mode 100644
index 00000000..f68dbfaf
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.css
@@ -0,0 +1,15 @@
+/*!
+ * Styles for elements of the editing form, loaded only when JavaScript is enabled.
+ */
+
+.mw-toolbar-editbutton {
+ width: 23px;
+ height: 22px;
+ cursor: pointer;
+ vertical-align: middle;
+ /* Modern browsers */
+ display: inline-block;
+ /* IE7 */
+ zoom: 1;
+ *display: inline; /* stylelint-disable declaration-block-no-duplicate-properties */
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js
new file mode 100644
index 00000000..56dba703
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.editWarning.js
@@ -0,0 +1,42 @@
+/*
+ * Javascript for module editWarning
+ */
+( function ( mw, $ ) {
+ 'use strict';
+
+ $( function () {
+ var allowCloseWindow,
+ $textBox = $( '#wpTextbox1' ),
+ $summary = $( '#wpSummary' ),
+ $both = $textBox.add( $summary );
+
+ // Check if EditWarning is enabled and if we need it
+ if ( !mw.user.options.get( 'useeditwarning' ) ) {
+ return true;
+ }
+
+ // Save the original value of the text fields
+ $both.each( function ( index, element ) {
+ var $element = $( element );
+ $element.data( 'origtext', $element.textSelection( 'getContents' ) );
+ } );
+
+ allowCloseWindow = mw.confirmCloseWindow( {
+ test: function () {
+ // We use .textSelection, because editors might not have updated the form yet.
+ return mw.config.get( 'wgAction' ) === 'submit' ||
+ $textBox.data( 'origtext' ) !== $textBox.textSelection( 'getContents' ) ||
+ $summary.data( 'origtext' ) !== $summary.textSelection( 'getContents' );
+ },
+
+ message: mw.msg( 'editwarning-warning' ),
+ namespace: 'editwarning'
+ } );
+
+ // Add form submission handler
+ $( '#editform' ).submit( function () {
+ allowCloseWindow.release();
+ } );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.js b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.js
new file mode 100644
index 00000000..087c5bce
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.js
@@ -0,0 +1,45 @@
+/*!
+ * Scripts for action=edit at domready
+ */
+( function ( mw, $ ) {
+ 'use strict';
+
+ /**
+ * Fired when the editform is added to the edit page
+ *
+ * Similar to the {@link mw.hook#event-wikipage_content wikipage.content hook}
+ * $editForm can still be detached when this hook is fired.
+ *
+ * @event wikipage_editform
+ * @member mw.hook
+ * @param {jQuery} $editForm The most appropriate element containing the
+ * editform, usually #editform.
+ */
+
+ $( function () {
+ var editBox, scrollTop, $editForm,
+ // TODO T6714: Once this can be adjusted, read this from config.
+ summaryByteLimit = 255,
+ wpSummary = OO.ui.infuse( $( '#wpSummaryWidget' ) );
+
+ // Show a byte-counter to users with how many bytes are left for their edit summary.
+ // TODO: This looks a bit weird, as there is no unit in the UI, just numbers; showing
+ // 'bytes' confused users in testing, and showing 'chars' would be a lie. See T42035.
+ mw.widgets.visibleByteLimit( wpSummary, summaryByteLimit );
+
+ // Restore the edit box scroll state following a preview operation,
+ // and set up a form submission handler to remember this state.
+ editBox = document.getElementById( 'wpTextbox1' );
+ scrollTop = document.getElementById( 'wpScrolltop' );
+ $editForm = $( '#editform' );
+ mw.hook( 'wikipage.editform' ).fire( $editForm );
+ if ( $editForm.length && editBox && scrollTop ) {
+ if ( scrollTop.value ) {
+ editBox.scrollTop = scrollTop.value;
+ }
+ $editForm.submit( function () {
+ scrollTop.value = editBox.scrollTop;
+ } );
+ }
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.preview.js b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.preview.js
new file mode 100644
index 00000000..ab1ce277
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.preview.js
@@ -0,0 +1,334 @@
+/*!
+ * Live edit preview.
+ */
+( function ( mw, $ ) {
+
+ /**
+ * @ignore
+ * @param {jQuery.Event} e
+ */
+ function doLivePreview( e ) {
+ var isDiff, api, parseRequest, diffRequest, postData, copySelectors, section, summary,
+ $wikiPreview, $wikiDiff, $editform, $textbox, $copyElements, $spinner, $errorBox;
+
+ isDiff = ( e.target.name === 'wpDiff' );
+ $wikiPreview = $( '#wikiPreview' );
+ $wikiDiff = $( '#wikiDiff' );
+ $editform = $( '#editform' );
+ $textbox = $editform.find( '#wpTextbox1' );
+
+ summary = OO.ui.infuse( $( '#wpSummaryWidget' ) );
+
+ $spinner = $( '.mw-spinner-preview' );
+ $errorBox = $( '.errorbox' );
+ section = $editform.find( '[name="wpSection"]' ).val();
+
+ if ( $textbox.length === 0 ) {
+ return;
+ }
+ // Show changes for a new section is not yet supported
+ if ( isDiff && section === 'new' ) {
+ return;
+ }
+ e.preventDefault();
+
+ // Remove any previously displayed errors
+ $errorBox.remove();
+ // Show #wikiPreview if it's hidden to be able to scroll to it
+ // (if it is hidden, it's also empty, so nothing changes in the rendering)
+ $wikiPreview.show();
+
+ // Jump to where the preview will appear
+ $wikiPreview[ 0 ].scrollIntoView();
+
+ copySelectors = [
+ // Main
+ '.mw-indicators',
+ '#firstHeading',
+ '#wikiPreview',
+ '#wikiDiff',
+ '#catlinks',
+ '#p-lang',
+ // Editing-related
+ '.templatesUsed',
+ '.limitreport',
+ '.mw-summary-preview'
+ ];
+ $copyElements = $( copySelectors.join( ',' ) );
+
+ // Not shown during normal preview, to be removed if present
+ $( '.mw-newarticletext' ).remove();
+
+ if ( $spinner.length === 0 ) {
+ $spinner = $.createSpinner( {
+ size: 'large',
+ type: 'block'
+ } )
+ .addClass( 'mw-spinner-preview' )
+ .css( 'margin-top', '1em' );
+ $wikiPreview.before( $spinner );
+ } else {
+ $spinner.show();
+ }
+
+ // Can't use fadeTo because it calls show(), and we might want to keep some elements hidden
+ // (e.g. empty #catlinks)
+ $copyElements.animate( { opacity: 0.4 }, 'fast' );
+
+ api = new mw.Api();
+ postData = {
+ formatversion: 2,
+ action: 'parse',
+ title: mw.config.get( 'wgPageName' ),
+ summary: summary.getValue(),
+ prop: ''
+ };
+
+ if ( isDiff ) {
+ $wikiPreview.hide();
+
+ if ( postData.summary ) {
+ parseRequest = api.post( postData );
+ }
+
+ diffRequest = api.post( {
+ formatversion: 2,
+ action: 'query',
+ prop: 'revisions',
+ titles: mw.config.get( 'wgPageName' ),
+ rvdifftotext: $textbox.textSelection( 'getContents' ),
+ rvdifftotextpst: true,
+ rvprop: '',
+ rvsection: section === '' ? undefined : section
+ } );
+
+ // Wait for the summary before showing the diff so the page doesn't jump twice
+ $.when( diffRequest, parseRequest ).done( function ( response ) {
+ var diffHtml;
+ try {
+ diffHtml = response[ 0 ].query.pages[ 0 ]
+ .revisions[ 0 ].diff.body;
+ $wikiDiff.find( 'table.diff tbody' ).html( diffHtml );
+ mw.hook( 'wikipage.diff' ).fire( $wikiDiff.find( 'table.diff' ) );
+ } catch ( err ) {
+ // "result.blah is undefined" error, ignore
+ mw.log.warn( err );
+ }
+ $wikiDiff.show();
+ } );
+ } else {
+ $wikiDiff.hide();
+
+ $.extend( postData, {
+ prop: 'text|indicators|displaytitle|modules|jsconfigvars|categorieshtml|templates|langlinks|limitreporthtml',
+ text: $textbox.textSelection( 'getContents' ),
+ pst: true,
+ preview: true,
+ sectionpreview: section !== '',
+ disableeditsection: true,
+ useskin: mw.config.get( 'skin' ),
+ uselang: mw.config.get( 'wgUserLanguage' )
+ } );
+ if ( section === 'new' ) {
+ postData.section = 'new';
+ postData.sectiontitle = postData.summary;
+ }
+
+ parseRequest = api.post( postData );
+ parseRequest.done( function ( response ) {
+ var li, newList, $displaytitle, $content, $parent, $list;
+ if ( response.parse.jsconfigvars ) {
+ mw.config.set( response.parse.jsconfigvars );
+ }
+ if ( response.parse.modules ) {
+ mw.loader.load( response.parse.modules.concat(
+ response.parse.modulescripts,
+ response.parse.modulestyles
+ ) );
+ }
+
+ newList = [];
+ $.each( response.parse.indicators, function ( name, indicator ) {
+ newList.push(
+ $( '<div>' )
+ .addClass( 'mw-indicator' )
+ .attr( 'id', mw.util.escapeIdForAttribute( 'mw-indicator-' + name ) )
+ .html( indicator )
+ .get( 0 ),
+ // Add a whitespace between the <div>s because
+ // they get displayed with display: inline-block
+ document.createTextNode( '\n' )
+ );
+ } );
+ $( '.mw-indicators' ).empty().append( newList );
+
+ if ( response.parse.displaytitle ) {
+ $displaytitle = $( $.parseHTML( response.parse.displaytitle ) );
+ $( '#firstHeading' ).msg(
+ mw.config.get( 'wgEditMessage', 'editing' ),
+ $displaytitle
+ );
+ document.title = mw.msg(
+ 'pagetitle',
+ mw.msg(
+ mw.config.get( 'wgEditMessage', 'editing' ),
+ $displaytitle.text()
+ )
+ );
+ }
+ if ( response.parse.categorieshtml ) {
+ $content = $( $.parseHTML( response.parse.categorieshtml ) );
+ mw.hook( 'wikipage.categories' ).fire( $content );
+ $( '.catlinks[data-mw="interface"]' ).replaceWith( $content );
+ }
+ if ( response.parse.templates ) {
+ newList = [];
+ $.each( response.parse.templates, function ( i, template ) {
+ li = $( '<li>' )
+ .append( $( '<a>' )
+ .attr( {
+ href: mw.util.getUrl( template.title ),
+ 'class': ( template.exists ? '' : 'new' )
+ } )
+ .text( template.title )
+ );
+ newList.push( li );
+ } );
+
+ $editform.find( '.templatesUsed .mw-editfooter-list' ).detach().empty().append( newList ).appendTo( '.templatesUsed' );
+ }
+ if ( response.parse.limitreporthtml ) {
+ $( '.limitreport' ).html( response.parse.limitreporthtml );
+ }
+ if ( response.parse.langlinks && mw.config.get( 'skin' ) === 'vector' ) {
+ newList = [];
+ $.each( response.parse.langlinks, function ( i, langlink ) {
+ var bcp47 = mw.language.bcp47( langlink.lang );
+ li = $( '<li>' )
+ .addClass( 'interlanguage-link interwiki-' + langlink.lang )
+ .append( $( '<a>' )
+ .attr( {
+ href: langlink.url,
+ title: langlink.title + ' - ' + langlink.langname,
+ lang: bcp47,
+ hreflang: bcp47
+ } )
+ .text( langlink.autonym )
+ );
+ newList.push( li );
+ } );
+ $list = $( '#p-lang ul' );
+ $parent = $list.parent();
+ $list.detach().empty().append( newList ).prependTo( $parent );
+ }
+
+ if ( response.parse.text ) {
+ $content = $wikiPreview.children( '.mw-content-ltr,.mw-content-rtl' );
+ $content
+ .detach()
+ .html( response.parse.text );
+
+ mw.hook( 'wikipage.content' ).fire( $content );
+
+ // Reattach
+ $wikiPreview.append( $content );
+
+ $wikiPreview.show();
+ }
+ } );
+ }
+ $.when( parseRequest, diffRequest ).done( function ( parseResp ) {
+ var parse = parseResp && parseResp[ 0 ].parse,
+ isSubject = ( section === 'new' ),
+ summaryMsg = isSubject ? 'subject-preview' : 'summary-preview',
+ $summaryPreview = $editform.find( '.mw-summary-preview' ).empty();
+ if ( parse && parse.parsedsummary ) {
+ $summaryPreview.append(
+ mw.message( summaryMsg ).parse(),
+ ' ',
+ $( '<span>' ).addClass( 'comment' ).html(
+ // There is no equivalent to rawParams
+ mw.message( 'parentheses' ).escaped()
+ // .replace() use $ as start of a pattern.
+ // $$ is the pattern for '$'.
+ // The inner .replace() duplicates any $ and
+ // the outer .replace() simplifies the $$.
+ .replace( '$1', parse.parsedsummary.replace( /\$/g, '$$$$' ) )
+ )
+ );
+ }
+ mw.hook( 'wikipage.editform' ).fire( $editform );
+ } ).always( function () {
+ $spinner.hide();
+ $copyElements.animate( {
+ opacity: 1
+ }, 'fast' );
+ } ).fail( function ( code, result ) {
+ // This just shows the error for whatever request failed first
+ var errorMsg = 'API error: ' + code;
+ if ( code === 'http' ) {
+ errorMsg = 'HTTP error: ';
+ if ( result.exception ) {
+ errorMsg += result.exception;
+ } else {
+ errorMsg += result.textStatus;
+ }
+ }
+ $errorBox = $( '<div>' )
+ .addClass( 'errorbox' )
+ .html( '<strong>' + mw.message( 'previewerrortext' ).escaped() + '</strong><br>' )
+ .append( document.createTextNode( errorMsg ) );
+ $wikiDiff.hide();
+ $wikiPreview.hide().before( $errorBox );
+ } );
+ }
+
+ $( function () {
+ // Do not enable on user .js/.css pages, as there's no sane way of "previewing"
+ // the scripts or styles without reloading the page.
+ if ( $( '#mw-userjsyoucanpreview' ).length || $( '#mw-usercssyoucanpreview' ).length ) {
+ return;
+ }
+
+ // The following elements can change in a preview but are not output
+ // by the server when they're empty until the preview response.
+ // TODO: Make the server output these always (in a hidden state), so we don't
+ // have to fish and (hopefully) put them in the right place (since skins
+ // can change where they are output).
+
+ if ( !document.getElementById( 'p-lang' ) && document.getElementById( 'p-tb' ) && mw.config.get( 'skin' ) === 'vector' ) {
+ $( '.portal:last' ).after(
+ $( '<div>' ).attr( {
+ 'class': 'portal',
+ id: 'p-lang',
+ role: 'navigation',
+ 'aria-labelledby': 'p-lang-label'
+ } )
+ .append( $( '<h3>' ).attr( 'id', 'p-lang-label' ).text( mw.msg( 'otherlanguages' ) ) )
+ .append( $( '<div>' ).addClass( 'body' ).append( '<ul>' ) )
+ );
+ }
+
+ if ( !$( '.mw-summary-preview' ).length ) {
+ $( '#wpSummaryWidget' ).after(
+ $( '<div>' ).addClass( 'mw-summary-preview' )
+ );
+ }
+
+ if ( !document.getElementById( 'wikiDiff' ) && document.getElementById( 'wikiPreview' ) ) {
+ $( '#wikiPreview' ).after(
+ $( '<div>' )
+ .hide()
+ .attr( 'id', 'wikiDiff' )
+ .html( '<table class="diff"><col class="diff-marker"/><col class="diff-content"/>' +
+ '<col class="diff-marker"/><col class="diff-content"/><tbody/></table>' )
+ );
+ }
+
+ // This should be moved down to '#editform', but is kept on the body for now
+ // because the LiquidThreads extension is re-using this module with only half
+ // the EditPage (doesn't include #editform presumably, T57463).
+ $( document.body ).on( 'click', '#wpPreview, #wpDiff', doLivePreview );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.stash.js b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.stash.js
new file mode 100644
index 00000000..31c22af2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.stash.js
@@ -0,0 +1,164 @@
+/*!
+ * Scripts for pre-emptive edit preparing on action=edit
+ */
+/* eslint-disable no-use-before-define */
+( function ( mw, $ ) {
+ if ( !mw.config.get( 'wgAjaxEditStash' ) ) {
+ return;
+ }
+
+ $( function () {
+ var idleTimeout = 3000,
+ api = new mw.Api(),
+ timer,
+ stashReq,
+ lastText,
+ lastSummary,
+ lastTextHash,
+ $form = $( '#editform' ),
+ $text = $form.find( '#wpTextbox1' ),
+ $summary = $form.find( '#wpSummary' ),
+ section = $form.find( '[name=wpSection]' ).val(),
+ model = $form.find( '[name=model]' ).val(),
+ format = $form.find( '[name=format]' ).val(),
+ revId = $form.find( '[name=parentRevId]' ).val(),
+ lastPriority = 0,
+ PRIORITY_LOW = 1,
+ PRIORITY_HIGH = 2;
+
+ // We don't attempt to stash new section edits because in such cases the parser output
+ // varies on the edit summary (since it determines the new section's name).
+ if ( !$form.length || section === 'new' ) {
+ return;
+ }
+
+ // Send a request to stash the edit to the API.
+ // If a request is in progress, abort it since its payload is stale and the API
+ // may limit concurrent stash parses.
+ function stashEdit() {
+ var req, params,
+ textChanged = isTextChanged(),
+ priority = textChanged ? PRIORITY_HIGH : PRIORITY_LOW;
+
+ if ( stashReq ) {
+ if ( lastPriority > priority ) {
+ // Stash request for summary change should wait on pending text change stash
+ stashReq.then( checkStash );
+ return;
+ }
+ stashReq.abort();
+ }
+
+ // Update the "last" tracking variables
+ lastSummary = $summary.textSelection( 'getContents' );
+ lastPriority = priority;
+ if ( textChanged ) {
+ lastText = $text.textSelection( 'getContents' );
+ // Reset hash
+ lastTextHash = null;
+ }
+
+ params = {
+ formatversion: 2,
+ action: 'stashedit',
+ title: mw.config.get( 'wgPageName' ),
+ section: section,
+ sectiontitle: '',
+ summary: lastSummary,
+ contentmodel: model,
+ contentformat: format,
+ baserevid: revId
+ };
+ if ( lastTextHash ) {
+ params.stashedtexthash = lastTextHash;
+ } else {
+ params.text = lastText;
+ }
+
+ req = api.postWithToken( 'csrf', params );
+ stashReq = req;
+ req.then( function ( data ) {
+ if ( req === stashReq ) {
+ stashReq = null;
+ }
+ if ( data.stashedit && data.stashedit.texthash ) {
+ lastTextHash = data.stashedit.texthash;
+ } else {
+ // Request failed or text hash expired;
+ // include the text in a future stash request.
+ lastTextHash = null;
+ }
+ } );
+ }
+
+ // Whether the body text content changed since the last stashEdit()
+ function isTextChanged() {
+ return lastText !== $text.textSelection( 'getContents' );
+ }
+
+ // Whether the edit summary has changed since the last stashEdit()
+ function isSummaryChanged() {
+ return lastSummary !== $summary.textSelection( 'getContents' );
+ }
+
+ // Check whether text or summary have changed and call stashEdit()
+ function checkStash() {
+ if ( !isTextChanged() && !isSummaryChanged() ) {
+ return;
+ }
+
+ stashEdit();
+ }
+
+ function onKeyUp( e ) {
+ // Ignore keystrokes that don't modify text, like cursor movements.
+ // See <http://www.javascripter.net/faq/keycodes.htm> and
+ // <http://www.quirksmode.org/js/keys.html>. We don't have to be exhaustive,
+ // because the cost of misfiring is low.
+ // * Key code 33-40: Page Up/Down, End, Home, arrow keys.
+ // * Key code 16-18: Shift, Ctrl, Alt.
+ if ( ( e.which >= 33 && e.which <= 40 ) || ( e.which >= 16 && e.which <= 18 ) ) {
+ return;
+ }
+
+ clearTimeout( timer );
+ timer = setTimeout( checkStash, idleTimeout );
+ }
+
+ function onSummaryFocus() {
+ // Summary typing is usually near the end of the workflow and involves less pausing.
+ // Re-stash more frequently in hopes of capturing the final summary before submission.
+ idleTimeout = 1000;
+ // Stash now since the text is likely the final version. The re-stashes based on the
+ // summary are targeted at caching edit checks that need the final summary.
+ checkStash();
+ }
+
+ function onTextFocus() {
+ // User returned to the text field... reset stash rate to default
+ idleTimeout = 3000;
+ }
+
+ $text.on( {
+ keyup: onKeyUp,
+ focus: onTextFocus,
+ change: checkStash
+ } );
+ $summary.on( {
+ keyup: onKeyUp,
+ focus: onSummaryFocus,
+ focusout: checkStash
+ } );
+
+ if (
+ // Reverts may involve use (undo) links; stash as they review the diff.
+ // Since the form has a pre-filled summary, stash the edit immediately.
+ mw.util.getParamValue( 'undo' ) !== null ||
+ // Pressing "show changes" and "preview" also signify that the user will
+ // probably save the page soon
+ $.inArray( $form.find( '#mw-edit-mode' ).val(), [ 'preview', 'diff' ] ) > -1
+ ) {
+ checkStash();
+ }
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.styles.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.styles.css
new file mode 100644
index 00000000..4209aa1f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.styles.css
@@ -0,0 +1,36 @@
+/*!
+ * Styles for elements of the editing form.
+ */
+
+/* General layout */
+#wpTextbox1 {
+ margin: 0;
+ display: block;
+}
+
+/* Adjustments to edit form elements */
+.editCheckboxes {
+ margin-bottom: 1em;
+}
+
+.editCheckboxes input:first-child {
+ margin-left: 0;
+}
+
+.cancelLink {
+ margin-left: 0.5em;
+}
+
+#editpage-copywarn {
+ font-size: 0.9em;
+}
+
+#wpSummary {
+ display: block;
+ margin-top: 0;
+ margin-bottom: 0.5em;
+}
+
+.editButtons input:first-child {
+ margin-left: .1em;
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.styles.less b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.styles.less
new file mode 100644
index 00000000..dc6a366d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.edit.styles.less
@@ -0,0 +1,56 @@
+/*!
+ * Styles for elements of the editing form.
+ */
+
+/*
+ * Add a bit of margin space between the preview and the toolbar.
+ * This replaces the ugly <p><br /></p> we used to insert into the page source
+ */
+#wikiPreview.ontop {
+ margin-bottom: 1em;
+}
+
+.mw-editform {
+ /* General layout */
+ #wpTextbox1 {
+ margin: 0;
+ display: block;
+ /* Ensure the textarea is not higher than browser's viewport on small screens */
+ max-height: 100vh;
+ /* But don't let it collapse into nothingness on really tiny screens */
+ min-height: 5em;
+ }
+
+ /* Adjustments to edit form elements */
+ #editpage-copywarn {
+ font-size: 0.9em;
+ line-height: 1.26;
+ }
+
+ #wpSummaryWidget {
+ display: block;
+ margin-bottom: 1em;
+ max-width: none;
+ }
+
+ #wpSummaryLabel {
+ margin: 0;
+ }
+
+ .editCheckboxes .oo-ui-fieldLayout {
+ margin-right: 1em;
+ }
+
+ .editHelp {
+ margin-left: 0.5em;
+ vertical-align: middle;
+
+ a {
+ font-weight: bold;
+ }
+ }
+
+ .editOptions {
+ border-radius: 0 0 2px 2px;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.css
new file mode 100644
index 00000000..f3ea1639
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.css
@@ -0,0 +1,6 @@
+/* Styles for the JavaScript enhancements of the history page */
+
+#pagehistory li.before input[name='oldid'],
+#pagehistory li.after input[name='diff'] {
+ visibility: hidden;
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.diff.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.diff.css
new file mode 100644
index 00000000..0887476e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.diff.css
@@ -0,0 +1,95 @@
+/*!
+ * Diff rendering
+ */
+table.diff {
+ border: none;
+ border-spacing: 4px;
+ margin: 0;
+ width: 100%;
+ /* Ensure that colums are of equal width */
+ table-layout: fixed;
+}
+
+table.diff td {
+ padding: 0.33em 0.5em;
+}
+
+table.diff td.diff-marker {
+ /* Compensate padding for increased font-size */
+ padding: 0.25em;
+}
+
+table.diff col.diff-marker {
+ width: 2%;
+}
+
+table.diff col.diff-content {
+ width: 48%;
+}
+
+table.diff td div {
+ /* Force-wrap very long lines such as URLs or page-widening char strings */
+ word-wrap: break-word;
+}
+
+td.diff-otitle,
+td.diff-ntitle {
+ text-align: center;
+}
+
+td.diff-lineno {
+ font-weight: bold;
+}
+
+td.diff-marker {
+ text-align: right;
+ font-weight: bold;
+ font-size: 1.25em;
+ line-height: 1.2;
+}
+
+td.diff-addedline,
+td.diff-deletedline,
+td.diff-context {
+ font-size: 88%;
+ line-height: 1.6;
+ vertical-align: top;
+ white-space: -moz-pre-wrap;
+ white-space: pre-wrap;
+ border-style: solid;
+ border-width: 1px 1px 1px 4px;
+ border-radius: 0.33em;
+}
+
+td.diff-addedline {
+ border-color: #a3d3ff;
+}
+
+td.diff-deletedline {
+ border-color: #ffe49c;
+}
+
+td.diff-context {
+ background: #f9f9f9;
+ border-color: #e6e6e6;
+ color: #333333;
+}
+
+.diffchange {
+ font-weight: bold;
+ text-decoration: none;
+}
+
+td.diff-addedline .diffchange,
+td.diff-deletedline .diffchange {
+ border-radius: 0.33em;
+ padding: 0.25em 0;
+}
+
+td.diff-addedline .diffchange {
+ background: #d8ecff;
+}
+
+td.diff-deletedline .diffchange {
+ background: #feeec8;
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.diff.print.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.diff.print.css
new file mode 100644
index 00000000..76b5c9b7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.diff.print.css
@@ -0,0 +1,16 @@
+/*!
+ * Diff rendering
+ */
+td.diff-context,
+td.diff-addedline .diffchange,
+td.diff-deletedline .diffchange {
+ background-color: transparent;
+}
+
+td.diff-addedline .diffchange {
+ text-decoration: underline;
+}
+
+td.diff-deletedline .diffchange {
+ text-decoration: line-through;
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.js b/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.js
new file mode 100644
index 00000000..6f49fa60
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.js
@@ -0,0 +1,111 @@
+/*!
+ * JavaScript for History action
+ */
+jQuery( function ( $ ) {
+ var $historyCompareForm = $( '#mw-history-compare' ),
+ $historySubmitter,
+ $lis = $( '#pagehistory > li' );
+
+ /**
+ * @ignore
+ * @context {Element} input
+ * @param {jQuery.Event} e
+ * @return {boolean} False to cancel the default event
+ */
+ function updateDiffRadios() {
+ var nextState = 'before',
+ $li,
+ $inputs,
+ $oldidRadio,
+ $diffRadio;
+
+ if ( !$lis.length ) {
+ return true;
+ }
+
+ $lis.each( function () {
+ $li = $( this );
+ $inputs = $li.find( 'input[type="radio"]' );
+ $oldidRadio = $inputs.filter( '[name="oldid"]' ).eq( 0 );
+ $diffRadio = $inputs.filter( '[name="diff"]' ).eq( 0 );
+
+ $li.removeClass( 'selected between before after' );
+
+ if ( !$oldidRadio.length || !$diffRadio.length ) {
+ return true;
+ }
+
+ if ( $oldidRadio.prop( 'checked' ) ) {
+ $li.addClass( 'selected after' );
+ nextState = 'after';
+ } else if ( $diffRadio.prop( 'checked' ) ) {
+ $li.addClass( 'selected ' + nextState );
+ nextState = 'between';
+ } else {
+ // This list item has neither checked
+ // apply the appropriate class following the previous item.
+ $li.addClass( nextState );
+ }
+ } );
+
+ return true;
+ }
+
+ $lis.find( 'input[name="diff"], input[name="oldid"]' ).click( updateDiffRadios );
+
+ // Set initial state
+ updateDiffRadios();
+
+ // Prettify url output for HistoryAction submissions,
+ // to cover up action=historysubmit construction.
+
+ // Ideally we'd use e.target instead of $historySubmitter, but e.target points
+ // to the form element for submit actions, so.
+ $historyCompareForm.find( '.historysubmit' ).click( function () {
+ $historySubmitter = $( this );
+ } );
+
+ // On submit we clone the form element, remove unneeded fields in the clone
+ // that pollute the query parameter with stuff from the other "use case",
+ // and then submit the clone.
+ // Without the cloning we'd be changing the real form, which is slower, could make
+ // the page look broken for a second in slow browsers and might show the form broken
+ // again when coming back from a "next" page.
+ $historyCompareForm.submit( function ( e ) {
+ var $copyForm, $copyRadios, $copyAction;
+
+ if ( $historySubmitter ) {
+ $copyForm = $historyCompareForm.clone();
+ $copyRadios = $copyForm.find( '#pagehistory > li' ).find( 'input[name="diff"], input[name="oldid"]' );
+ $copyAction = $copyForm.find( '> [name="action"]' );
+
+ // Remove action=historysubmit and ids[..]=..
+ if ( $historySubmitter.hasClass( 'mw-history-compareselectedversions-button' ) ) {
+ $copyAction.remove();
+ $copyForm.find( 'input[name^="ids["]:checked' ).prop( 'checked', false );
+
+ // Remove diff=&oldid=, change action=historysubmit to revisiondelete, remove revisiondelete
+ } else if ( $historySubmitter.hasClass( 'mw-history-revisiondelete-button' ) ||
+ $historySubmitter.hasClass( 'mw-history-editchangetags-button' ) ) {
+ $copyRadios.remove();
+ $copyAction.val( $historySubmitter.attr( 'name' ) );
+ $copyForm.find( ':submit' ).remove();
+ }
+
+ // IE7 doesn't do submission from an off-DOM clone, so insert hidden into document first
+ // Also remove potentially conflicting id attributes that we don't need anyway
+ $copyForm
+ .css( 'display', 'none' )
+ .find( '[id]' ).removeAttr( 'id' )
+ .end()
+ .insertAfter( $historyCompareForm )
+ .submit();
+
+ e.preventDefault();
+ return false; // Because the submit is special, return false as well.
+ }
+
+ // Continue natural browser handling other wise
+ return true;
+ } );
+} );
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.styles.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.styles.css
new file mode 100644
index 00000000..cad530bf
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.history.styles.css
@@ -0,0 +1,23 @@
+/* Basic styles for the history page */
+
+#pagehistory .history-user {
+ margin-left: 0.4em;
+ margin-right: 0.2em;
+}
+
+#pagehistory li {
+ border: 1px solid #fff;
+}
+
+#pagehistory li.selected {
+ background-color: #f8f9fa;
+ border: 1px dashed #a2a9b1;
+}
+
+.mw-history-revisionactions {
+ float: right;
+}
+
+.updatedmarker {
+ background-color: #b7f430;
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.categoryPage.less b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.categoryPage.less
new file mode 100644
index 00000000..83cc207b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.categoryPage.less
@@ -0,0 +1,15 @@
+@import 'mediawiki.mixins';
+
+.mw-category {
+ .column-count(3);
+ .column-width(24em);
+ .mw-category-group {
+ li {
+ .column-break-inside-avoid;
+ }
+ }
+}
+
+.redirect-in-category {
+ font-style: italic;
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.dblClickEdit.js b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.dblClickEdit.js
new file mode 100644
index 00000000..d89cd4a2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.dblClickEdit.js
@@ -0,0 +1,20 @@
+/*!
+ * Enables double-click-to-edit functionality.
+ */
+( function ( mw, $ ) {
+ $( function () {
+ mw.util.$content.dblclick( function ( e ) {
+ var $a;
+ // Recheck preference so extensions can do a hack to disable this code.
+ if ( parseInt( mw.user.options.get( 'editondblclick' ), 10 ) ) {
+ e.preventDefault();
+ // Trigger native HTMLElement click instead of opening URL (T45052)
+ $a = $( '#ca-edit a' );
+ // Not every page has an edit link (T59713)
+ if ( $a.length ) {
+ $a.get( 0 ).click();
+ }
+ }
+ } );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.filepage.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.filepage.css
new file mode 100644
index 00000000..d4662161
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.filepage.css
@@ -0,0 +1,113 @@
+/*!
+ * File description page
+ */
+
+.mw-filepage-resolutioninfo {
+ font-size: smaller;
+}
+
+/*
+ * File histories
+ */
+#filehistory {
+ clear: both;
+}
+
+.filehistory th,
+.filehistory td {
+ vertical-align: top;
+}
+
+.filehistory th {
+ text-align: left;
+}
+
+.filehistory td.mw-imagepage-filesize,
+.filehistory th.mw-imagepage-filesize {
+ white-space: nowrap;
+}
+
+.filehistory td.filehistory-selected {
+ font-weight: bold;
+}
+
+/*
+ * Add a checkered background image on hover for file
+ * description pages. (T28470)
+ */
+.filehistory a img,
+#file img:hover {
+ /* @embed */
+ background: #fff url( images/checker.png ) repeat;
+}
+
+/*
+ * filetoc
+ */
+#filetoc {
+ text-align: center;
+ border: 1px solid #a2a9b1;
+ background-color: #f8f9fa;
+ padding: 5px;
+ font-size: 95%;
+ margin-bottom: 0.5em;
+ margin-left: 0;
+ margin-right: 0;
+}
+
+#filetoc li {
+ display: inline;
+ list-style-type: none;
+ padding-right: 2em;
+}
+
+/*
+ * Shared images hint
+ */
+#shared-image-dup,
+#shared-image-conflict {
+ font-style: italic;
+}
+
+/*
+ * Classes for Exif data display
+ */
+.mw_metadata {
+ font-size: 0.8em;
+ margin-left: 0.5em;
+ margin-bottom: 0.5em;
+ border: 0;
+ border-collapse: collapse;
+ width: 400px;
+}
+
+.mw_metadata caption {
+ font-weight: bold;
+}
+
+.mw_metadata td,
+.mw_metadata th {
+ border: 1px solid #a2a9b1;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+
+.mw_metadata th {
+ background-color: #f8f9fa;
+ font-weight: normal;
+ text-align: center;
+}
+
+.mw_metadata td {
+ background-color: #fcfcfc;
+ padding-top: 0.1em;
+ padding-bottom: 0.1em;
+}
+
+.mw_metadata ul.metadata-langlist {
+ list-style-type: none;
+ list-style-image: none;
+ padding-right: 5px;
+ padding-left: 5px;
+ margin: 0;
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.filepage.print.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.filepage.print.css
new file mode 100644
index 00000000..15b20f10
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.filepage.print.css
@@ -0,0 +1,8 @@
+/*!
+ * File description page - print style
+ */
+
+span.mw-filepage-other-resolutions,
+#filetoc {
+ display: none;
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.metadata.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.metadata.css
new file mode 100644
index 00000000..b07965ee
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.metadata.css
@@ -0,0 +1,22 @@
+/*!
+ * Hide collapsable rows in a collapsed table.
+ */
+table.collapsed tr.collapsable {
+ display: none;
+}
+
+/*
+ * Exclude user interface elements from selection.
+ */
+.mw-metadata-show-hide-extended {
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+@media print {
+ tr.mw-metadata-show-hide-extended {
+ display: none;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.metadata.js b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.metadata.js
new file mode 100644
index 00000000..0d000c9b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.metadata.js
@@ -0,0 +1,52 @@
+/*!
+ * Exif metadata display for MediaWiki file uploads
+ *
+ * Add an expand/collapse link and collapse by default if set to
+ * (with JS disabled, user will see all items)
+ *
+ * See also ImagePage.php#makeMetadataTable (creates the HTML)
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var $row, $col, $link,
+ showText = mw.msg( 'metadata-expand' ),
+ hideText = mw.msg( 'metadata-collapse' ),
+ $table = $( '#mw_metadata' ),
+ $tbody = $table.find( 'tbody' );
+
+ if ( !$tbody.find( '.collapsable' ).length ) {
+ return;
+ }
+
+ $row = $( '<tr class="mw-metadata-show-hide-extended"></tr>' );
+ $col = $( '<td colspan="2"></td>' );
+
+ $link = $( '<a>' )
+ .text( showText )
+ .attr( {
+ role: 'button',
+ tabindex: 0
+ } )
+ .on( 'click keypress', function ( e ) {
+ if (
+ e.type === 'click' ||
+ e.type === 'keypress' && e.which === 13
+ ) {
+ if ( $table.hasClass( 'collapsed' ) ) {
+ $( this ).text( hideText );
+ } else {
+ $( this ).text( showText );
+ }
+ $table.toggleClass( 'expanded collapsed' );
+ }
+ } );
+
+ $col.append( $link );
+ $row.append( $col );
+ $tbody.append( $row );
+
+ // And collapse!
+ $table.addClass( 'collapsed' );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.css
new file mode 100644
index 00000000..db89990d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.css
@@ -0,0 +1,76 @@
+.postedit-container {
+ margin: 0 auto;
+ position: fixed;
+ top: 0;
+ height: 0;
+ left: 50%;
+ z-index: 1000;
+ font-size: 13px;
+}
+
+.postedit-container:hover {
+ cursor: pointer;
+}
+
+.postedit {
+ position: relative;
+ top: 0.6em;
+ left: -50%;
+ padding: .6em 3.6em .6em 1.1em;
+ line-height: 1.5625em;
+ color: #626465;
+ background-color: #f4f4f4;
+ border: 1px solid #dcd9d9;
+ text-shadow: 0 0.0625em 0 rgba(255, 255, 255, 0.5);
+ border-radius: 5px;
+ box-shadow: 0 2px 5px 0 #ccc;
+ -webkit-transition: all 0.25s ease-in-out;
+ -moz-transition: all 0.25s ease-in-out;
+ -ms-transition: all 0.25s ease-in-out;
+ -o-transition: all 0.25s ease-in-out;
+ transition: all 0.25s ease-in-out;
+}
+
+.skin-monobook .postedit {
+ top: 6em !important;
+}
+
+.postedit-faded {
+ opacity: 0;
+}
+
+.postedit-icon {
+ padding-left: 41px; /* 25 + 8 + 8 */
+ /* like min-height, but old IE compatible and keeps text vertically aligned, too */
+ line-height: 25px;
+ background-repeat: no-repeat;
+ background-position: 8px 50%;
+}
+
+.postedit-icon-checkmark {
+ /* @embed */
+ background-image: url(images/green-checkmark.png);
+ background-position: left;
+}
+
+.postedit-close {
+ position: absolute;
+ padding: 0 .8em;
+ right: 0;
+ top: 0;
+ font-size: 1.25em;
+ font-weight: bold;
+ line-height: 2.3em;
+ color: black;
+ text-shadow: 0 0.0625em 0 white;
+ text-decoration: none;
+ opacity: 0.2;
+ filter: alpha(opacity=20);
+}
+
+.postedit-close:hover {
+ color: black;
+ text-decoration: none;
+ opacity: 0.4;
+ filter: alpha(opacity=40);
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.js b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.js
new file mode 100644
index 00000000..e0ab45a1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.js
@@ -0,0 +1,78 @@
+( function ( mw, $ ) {
+ 'use strict';
+
+ /**
+ * Fired after an edit was successfully saved.
+ *
+ * Does not fire for null edits.
+ *
+ * @event postEdit
+ * @member mw.hook
+ * @param {Object} [data] Optional data
+ * @param {string|jQuery|Array} [data.message] Message that listeners
+ * should use when displaying notifications. String for plain text,
+ * use array or jQuery object to pass actual nodes.
+ * @param {string|mw.user} [data.user=mw.user] User that made the edit.
+ */
+
+ /**
+ * After the listener for #postEdit removes the notification.
+ *
+ * @event postEdit_afterRemoval
+ * @member mw.hook
+ */
+
+ var postEdit = mw.config.get( 'wgPostEdit' );
+
+ function showConfirmation( data ) {
+ var $container, $popup, $content, timeoutId;
+
+ function fadeOutConfirmation() {
+ $popup.addClass( 'postedit-faded' );
+ setTimeout( function () {
+ $container.remove();
+ mw.hook( 'postEdit.afterRemoval' ).fire();
+ }, 250 );
+ }
+
+ data = data || {};
+
+ if ( data.message === undefined ) {
+ data.message = $.parseHTML( mw.message( 'postedit-confirmation-saved', data.user || mw.user ).escaped() );
+ }
+
+ $content = $( '<div>' ).addClass( 'postedit-icon postedit-icon-checkmark postedit-content' );
+ if ( typeof data.message === 'string' ) {
+ $content.text( data.message );
+ } else if ( typeof data.message === 'object' ) {
+ $content.append( data.message );
+ }
+
+ $popup = $( '<div>' ).addClass( 'postedit mw-notification' ).append( $content )
+ .click( function () {
+ clearTimeout( timeoutId );
+ fadeOutConfirmation();
+ } );
+
+ $container = $( '<div>' ).addClass( 'postedit-container' ).append( $popup );
+ timeoutId = setTimeout( fadeOutConfirmation, 3000 );
+
+ $( 'body' ).prepend( $container );
+ }
+
+ mw.hook( 'postEdit' ).add( showConfirmation );
+
+ if ( postEdit ) {
+ mw.hook( 'postEdit' ).fire( {
+ // The following messages can be used here:
+ // postedit-confirmation-saved
+ // postedit-confirmation-created
+ // postedit-confirmation-restored
+ message: mw.msg(
+ 'postedit-confirmation-' + postEdit,
+ mw.user
+ )
+ } );
+ }
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.less b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.less
new file mode 100644
index 00000000..d19f0985
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.less
@@ -0,0 +1,59 @@
+@import 'mediawiki.mixins';
+
+.postedit-container {
+ margin: 0 auto;
+ position: fixed;
+ top: 0;
+ height: 0;
+ left: 50%;
+ z-index: 1000;
+ font-size: 14px;
+ cursor: pointer;
+}
+
+.postedit {
+ position: relative;
+ top: 0.6em;
+ left: -50%;
+ line-height: 1.35;
+ opacity: 1;
+ .transition( opacity 250ms );
+
+ &:after {
+ content: '';
+ background: no-repeat center center;
+ .background-image-svg( 'images/close.svg', 'images/close.png' );
+ background-size: 12px 12px;
+ position: absolute;
+ right: 0.4em;
+ top: 0;
+ bottom: 0;
+ min-width: 32px;
+ min-height: 32px;
+ opacity: 0.87;
+
+ &:hover {
+ opacity: 1;
+ }
+ }
+
+ &.mw-notification {
+ padding-right: 3em;
+ }
+}
+
+.postedit-faded {
+ opacity: 0;
+}
+
+.postedit-icon {
+ padding-left: 25px;
+ /* like min-height, but old IE compatible and keeps text vertically aligned, too */
+ line-height: 25px;
+ background-repeat: no-repeat;
+}
+
+.postedit-icon-checkmark {
+ /* @embed */
+ background-image: url( images/green-checkmark.png );
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.monobook.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.monobook.css
new file mode 100644
index 00000000..50f0c8a6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.postEdit.monobook.css
@@ -0,0 +1,3 @@
+.postedit {
+ top: 6em;
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.redirect.js b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.redirect.js
new file mode 100644
index 00000000..39a122d9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.redirect.js
@@ -0,0 +1,65 @@
+/*!
+ * JavaScript to update page URL when a redirect is viewed, ensuring that the
+ * page is scrolled to the id when it's a redirect with fragment.
+ *
+ * This is loaded in the top queue, so avoid unnecessary dependencies
+ * like mediawiki.Title or mediawiki.Uri.
+ */
+( function ( mw, $ ) {
+ var profile = $.client.profile(),
+ canonical = mw.config.get( 'wgInternalRedirectTargetUrl' ),
+ fragment = null,
+ node, shouldChangeFragment, index;
+
+ index = canonical.indexOf( '#' );
+ if ( index !== -1 ) {
+ fragment = canonical.slice( index );
+ }
+
+ // Never override the fragment if the user intended to look at a different section
+ shouldChangeFragment = fragment && !location.hash;
+
+ // Replace the whole URL if possible, otherwise just change the fragment
+ if ( canonical && history.replaceState ) {
+ if ( !shouldChangeFragment ) {
+ // If the current page view has a fragment already, don't override it
+ canonical = canonical.replace( /#.*$/, '' );
+ canonical += location.hash;
+ }
+
+ // Note that this will update the hash in a modern browser, retaining back behaviour
+ history.replaceState( /* data= */ history.state, /* title= */ document.title, /* url= */ canonical );
+ if ( shouldChangeFragment ) {
+ // Specification for history.replaceState() doesn't require browser to scroll,
+ // so scroll to be sure (see also T110501). Support for IE9 and IE10.
+ node = document.getElementById( fragment.slice( 1 ) );
+ if ( node ) {
+ node.scrollIntoView();
+ }
+ }
+
+ } else if ( shouldChangeFragment ) {
+ if ( profile.layout === 'webkit' && profile.layoutVersion < 420 ) {
+ // Released Safari w/ WebKit 418.9.1 messes up horribly
+ // Nightlies of 420+ are ok
+ return;
+ }
+
+ location.hash = fragment;
+ }
+
+ if ( shouldChangeFragment && profile.layout === 'gecko' ) {
+ // Mozilla needs to wait until after load, otherwise the window doesn't
+ // scroll. See <https://bugzilla.mozilla.org/show_bug.cgi?id=516293>.
+ // There's no obvious way to detect this programmatically, so we use
+ // version-testing. If Firefox fixes the bug, they'll jump twice, but
+ // better twice than not at all, so make the fix hit future versions as
+ // well.
+ $( function () {
+ if ( location.hash === fragment ) {
+ location.hash = fragment;
+ }
+ } );
+ }
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.redirectPage.css b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.redirectPage.css
new file mode 100644
index 00000000..dccbacce
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.redirectPage.css
@@ -0,0 +1,59 @@
+/*!
+ * Display neat icons on redirect pages.
+ */
+
+/* Hide, but keep accessible for screen-readers. */
+.redirectMsg p {
+ overflow: hidden;
+ height: 0;
+ zoom: 1;
+}
+
+.redirectText {
+ list-style: none none;
+ display: inline;
+ /* shared.css has some very weird directionality-specific rules for 'ul' we need to override,
+ * search for "Correct directionality when page dir is different from site/user dir" */
+ /* stylelint-disable declaration-no-important */
+ margin: 0 !important;
+ padding: 0 !important;
+ /* stylelint-enable declaration-no-important */
+}
+
+/* @noflip */
+.mw-content-ltr .redirectText li {
+ display: inline;
+ margin: 0;
+ padding: 0;
+ padding-left: 42px;
+ background: transparent url( images/nextredirect-ltr.png ) bottom left no-repeat;
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/nextredirect-ltr.svg );
+}
+
+/* @noflip */
+.mw-content-ltr .redirectText li:first-child {
+ padding-left: 47px;
+ background: transparent url( images/redirect-ltr.png ) bottom left no-repeat;
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/redirect-ltr.svg );
+}
+
+/* @noflip */
+.mw-content-rtl .redirectText li {
+ display: inline;
+ margin: 0;
+ padding: 0;
+ padding-right: 42px;
+ background: transparent url( images/nextredirect-rtl.png ) bottom right no-repeat;
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/nextredirect-rtl.svg );
+}
+
+/* @noflip */
+.mw-content-rtl .redirectText li:first-child {
+ padding-right: 47px;
+ background: transparent url( images/redirect-rtl.png ) bottom right no-repeat;
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/redirect-rtl.svg );
+}
diff --git a/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.rightClickEdit.js b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.rightClickEdit.js
new file mode 100644
index 00000000..ebd1ebcc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/mediawiki.action.view.rightClickEdit.js
@@ -0,0 +1,26 @@
+/*!
+ * JavaScript to enable right click edit functionality.
+ * When the user right-clicks in a heading, it will open the
+ * edit screen.
+ */
+jQuery( function ( $ ) {
+ // Select all h1-h6 elements that contain editsection links
+ // Don't use the ":has:(.mw-editsection a)" selector because it performs very bad.
+ // http://jsperf.com/jq-1-7-2-vs-jq-1-8-1-performance-of-mw-has/2
+ $( document ).on( 'contextmenu', 'h1, h2, h3, h4, h5, h6', function ( e ) {
+ var $edit = $( this ).find( '.mw-editsection a' );
+ if ( !$edit.length ) {
+ return;
+ }
+
+ // Headings can contain rich text.
+ // Make sure to not block contextmenu events on (other) anchor tags
+ // inside the heading (e.g. to do things like copy URL, open in new tab, ..).
+ // e.target can be the heading, but it can also be anything inside the heading.
+ if ( e.target.nodeName.toLowerCase() !== 'a' ) {
+ // Trigger native HTMLElement click instead of opening URL (T45052)
+ e.preventDefault();
+ $edit.get( 0 ).click();
+ }
+ } );
+} );
diff --git a/www/wiki/resources/src/mediawiki.action/templates/postEdit.html b/www/wiki/resources/src/mediawiki.action/templates/postEdit.html
new file mode 100644
index 00000000..dbb482a6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.action/templates/postEdit.html
@@ -0,0 +1,6 @@
+<div class="postedit-container">
+ <div class="postedit">
+ <div class="postedit-icon postedit-icon-checkmark postedit-content"></div>
+ <a href="#" class="postedit-close">&times;</a>
+ </div>
+</div>
diff --git a/www/wiki/resources/src/mediawiki.hidpi-skip.js b/www/wiki/resources/src/mediawiki.hidpi-skip.js
new file mode 100644
index 00000000..26b63c7b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.hidpi-skip.js
@@ -0,0 +1,4 @@
+/*!
+ * Skip function for mediawiki.hdpi.js.
+ */
+return 'srcset' in new Image();
diff --git a/www/wiki/resources/src/mediawiki.language/languages/bs.js b/www/wiki/resources/src/mediawiki.language/languages/bs.js
new file mode 100644
index 00000000..cb9e19ed
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/bs.js
@@ -0,0 +1,19 @@
+/*!
+ * Bosnian (bosanski) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms = mediaWiki.language.getData( 'bs', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+ switch ( form ) {
+ case 'instrumental': // instrumental
+ word = 's ' + word;
+ break;
+ case 'lokativ': // locative
+ word = 'o ' + word;
+ break;
+ }
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/dsb.js b/www/wiki/resources/src/mediawiki.language/languages/dsb.js
new file mode 100644
index 00000000..dc4447ab
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/dsb.js
@@ -0,0 +1,19 @@
+/*!
+ * Lower Sorbian (Dolnoserbski) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms = mediaWiki.language.getData( 'dsb', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+ switch ( form ) {
+ case 'instrumental': // instrumental
+ word = 'z ' + word;
+ break;
+ case 'lokatiw': // lokatiw
+ word = 'wo ' + word;
+ break;
+ }
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/fi.js b/www/wiki/resources/src/mediawiki.language/languages/fi.js
new file mode 100644
index 00000000..2bbfc6b8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/fi.js
@@ -0,0 +1,47 @@
+/*!
+ * Finnish (Suomi) language functions
+ * @author Santhosh Thottingal
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms, aou, origWord;
+
+ grammarForms = mediaWiki.language.getData( 'fi', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+
+ // vowel harmony flag
+ aou = word.match( /[aou][^äöy]*$/i );
+ origWord = word;
+ if ( word.match( /wiki$/i ) ) {
+ aou = false;
+ }
+ // append i after final consonant
+ if ( word.match( /[bcdfghjklmnpqrstvwxz]$/i ) ) {
+ word += 'i';
+ }
+
+ switch ( form ) {
+ case 'genitive':
+ word += 'n';
+ break;
+ case 'elative':
+ word += ( aou ? 'sta' : 'stä' );
+ break;
+ case 'partitive':
+ word += ( aou ? 'a' : 'ä' );
+ break;
+ case 'illative':
+ // Double the last letter and add 'n'
+ word += word.slice( -1 ) + 'n';
+ break;
+ case 'inessive':
+ word += ( aou ? 'ssa' : 'ssä' );
+ break;
+ default:
+ word = origWord;
+ break;
+ }
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/ga.js b/www/wiki/resources/src/mediawiki.language/languages/ga.js
new file mode 100644
index 00000000..e1362114
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/ga.js
@@ -0,0 +1,37 @@
+/*!
+ * Irish (Gaeilge) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms = mediaWiki.language.getData( 'ga', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+ switch ( form ) {
+ case 'ainmlae':
+ switch ( word ) {
+ case 'an Domhnach':
+ word = 'Dé Domhnaigh';
+ break;
+ case 'an Luan':
+ word = 'Dé Luain';
+ break;
+ case 'an Mháirt':
+ word = 'Dé Mháirt';
+ break;
+ case 'an Chéadaoin':
+ word = 'Dé Chéadaoin';
+ break;
+ case 'an Déardaoin':
+ word = 'Déardaoin';
+ break;
+ case 'an Aoine':
+ word = 'Dé hAoine';
+ break;
+ case 'an Satharn':
+ word = 'Dé Sathairn';
+ break;
+ }
+ }
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/he.js b/www/wiki/resources/src/mediawiki.language/languages/he.js
new file mode 100644
index 00000000..945f02fe
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/he.js
@@ -0,0 +1,29 @@
+/*!
+ * Hebrew (עברית) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms = mediaWiki.language.getData( 'he', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+ switch ( form ) {
+ case 'prefixed':
+ case 'תחילית': // the same word in Hebrew
+ // Duplicate prefixed "Waw", but only if it's not already double
+ if ( word.slice( 0, 1 ) === 'ו' && word.slice( 0, 2 ) !== 'וו' ) {
+ word = 'ו' + word;
+ }
+
+ // Remove the "He" if prefixed
+ if ( word.slice( 0, 1 ) === 'ה' ) {
+ word = word.slice( 1 );
+ }
+
+ // Add a hyphen (maqaf) before numbers and non-Hebrew letters
+ if ( word.slice( 0, 1 ) < 'א' || word.slice( 0, 1 ) > 'ת' ) {
+ word = '־' + word;
+ }
+ }
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/hsb.js b/www/wiki/resources/src/mediawiki.language/languages/hsb.js
new file mode 100644
index 00000000..8e9b1296
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/hsb.js
@@ -0,0 +1,19 @@
+/*!
+ * Upper Sorbian (Hornjoserbsce) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms = mediaWiki.language.getData( 'hsb', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+ switch ( form ) {
+ case 'instrumental': // instrumental
+ word = 'z ' + word;
+ break;
+ case 'lokatiw': // lokatiw
+ word = 'wo ' + word;
+ break;
+ }
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/hu.js b/www/wiki/resources/src/mediawiki.language/languages/hu.js
new file mode 100644
index 00000000..4f8f74df
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/hu.js
@@ -0,0 +1,23 @@
+/*!
+ * Hungarian language functions
+ * @author Santhosh Thottingal
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms = mediaWiki.language.getData( 'hu', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+ switch ( form ) {
+ case 'rol':
+ word += 'ról';
+ break;
+ case 'ba':
+ word += 'ba';
+ break;
+ case 'k':
+ word += 'k';
+ break;
+ }
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/hy.js b/www/wiki/resources/src/mediawiki.language/languages/hy.js
new file mode 100644
index 00000000..bb6f61df
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/hy.js
@@ -0,0 +1,28 @@
+/*!
+ * Armenian (Հայերեն) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms = mediaWiki.language.getData( 'hy', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+
+ // These rules are not perfect, but they are currently only used for site names so it doesn't
+ // matter if they are wrong sometimes. Just add a special case for your site name if necessary.
+
+ switch ( form ) {
+ case 'genitive': // սեռական հոլով
+ if ( word.slice( -1 ) === 'ա' ) {
+ word = word.slice( 0, -1 ) + 'այի';
+ } else if ( word.slice( -1 ) === 'ո' ) {
+ word = word.slice( 0, -1 ) + 'ոյի';
+ } else if ( word.slice( -4 ) === 'գիրք' ) {
+ word = word.slice( 0, -4 ) + 'գրքի';
+ } else {
+ word = word + 'ի';
+ }
+ break;
+ }
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/la.js b/www/wiki/resources/src/mediawiki.language/languages/la.js
new file mode 100644
index 00000000..29e04a67
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/la.js
@@ -0,0 +1,50 @@
+/*!
+ * Latin (lingua Latina) language functions
+ * @author Santhosh Thottingal
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms = mediaWiki.language.getData( 'la', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+ switch ( form ) {
+ case 'genitive':
+ // only a few declensions, and even for those mostly the singular only
+ word = word.replace( /u[ms]$/i, 'i' ); // 2nd declension singular
+ word = word.replace( /ommunia$/i, 'ommunium' ); // 3rd declension neuter plural (partly)
+ word = word.replace( /a$/i, 'ae' ); // 1st declension singular
+ word = word.replace( /libri$/i, 'librorum' ); // 2nd declension plural (partly)
+ word = word.replace( /nuntii$/i, 'nuntiorum' ); // 2nd declension plural (partly)
+ word = word.replace( /tio$/i, 'tionis' ); // 3rd declension singular (partly)
+ word = word.replace( /ns$/i, 'ntis' );
+ word = word.replace( /as$/i, 'atis' );
+ word = word.replace( /es$/i, 'ei' ); // 5th declension singular
+ break;
+ case 'accusative':
+ // only a few declensions, and even for those mostly the singular only
+ word = word.replace( /u[ms]$/i, 'um' ); // 2nd declension singular
+ word = word.replace( /ommunia$/i, 'am' ); // 3rd declension neuter plural (partly)
+ word = word.replace( /a$/i, 'ommunia' ); // 1st declension singular
+ word = word.replace( /libri$/i, 'libros' ); // 2nd declension plural (partly)
+ word = word.replace( /nuntii$/i, 'nuntios' );// 2nd declension plural (partly)
+ word = word.replace( /tio$/i, 'tionem' ); // 3rd declension singular (partly)
+ word = word.replace( /ns$/i, 'ntem' );
+ word = word.replace( /as$/i, 'atem' );
+ word = word.replace( /es$/i, 'em' ); // 5th declension singular
+ break;
+ case 'ablative':
+ // only a few declensions, and even for those mostly the singular only
+ word = word.replace( /u[ms]$/i, 'o' ); // 2nd declension singular
+ word = word.replace( /ommunia$/i, 'ommunibus' ); // 3rd declension neuter plural (partly)
+ word = word.replace( /a$/i, 'a' ); // 1st declension singular
+ word = word.replace( /libri$/i, 'libris' ); // 2nd declension plural (partly)
+ word = word.replace( /nuntii$/i, 'nuntiis' ); // 2nd declension plural (partly)
+ word = word.replace( /tio$/i, 'tione' ); // 3rd declension singular (partly)
+ word = word.replace( /ns$/i, 'nte' );
+ word = word.replace( /as$/i, 'ate' );
+ word = word.replace( /es$/i, 'e' ); // 5th declension singular
+ break;
+ }
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/os.js b/www/wiki/resources/src/mediawiki.language/languages/os.js
new file mode 100644
index 00000000..3e0f279d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/os.js
@@ -0,0 +1,67 @@
+/*!
+ * Ossetian (Ирон) language functions
+ * @author Santhosh Thottingal
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms = mediaWiki.language.getData( 'os', 'grammarForms' ),
+ // Ending for allative case
+ endAllative = 'мæ',
+ // Variable for 'j' beetwen vowels
+ jot = '',
+ // Variable for "-" for not Ossetic words
+ hyphen = '',
+ // Variable for ending
+ ending = '';
+
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+ // Checking if the $word is in plural form
+ if ( word.match( /тæ$/i ) ) {
+ word = word.slice( 0, -1 );
+ endAllative = 'æм';
+ } else if ( word.match( /[аæеёиоыэюя]$/i ) ) {
+ // Works if word is in singular form.
+ // Checking if word ends on one of the vowels: е, ё, и, о, ы, э, ю, я.
+ jot = 'й';
+ } else if ( word.match( /у$/i ) ) {
+ // Checking if word ends on 'у'. 'У' can be either consonant 'W' or vowel 'U' in cyrillic Ossetic.
+ // Examples: {{grammar:genitive|аунеу}} = аунеуы, {{grammar:genitive|лæппу}} = лæппуйы.
+
+ if ( !word.slice( -2, -1 ).match( /[аæеёиоыэюя]$/i ) ) {
+ jot = 'й';
+ }
+ } else if ( !word.match( /[бвгджзйклмнопрстфхцчшщьъ]$/i ) ) {
+ hyphen = '-';
+ }
+
+ switch ( form ) {
+ case 'genitive':
+ ending = hyphen + jot + 'ы';
+ break;
+ case 'dative':
+ ending = hyphen + jot + 'æн';
+ break;
+ case 'allative':
+ ending = hyphen + endAllative;
+ break;
+ case 'ablative':
+ if ( jot === 'й' ) {
+ ending = hyphen + jot + 'æ';
+ } else {
+ ending = hyphen + jot + 'æй';
+ }
+ break;
+ case 'superessive':
+ ending = hyphen + jot + 'ыл';
+ break;
+ case 'equative':
+ ending = hyphen + jot + 'ау';
+ break;
+ case 'comitative':
+ ending = hyphen + 'имæ';
+ break;
+ }
+ return word + ending;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/ru.js b/www/wiki/resources/src/mediawiki.language/languages/ru.js
new file mode 100644
index 00000000..ccc68f1e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/ru.js
@@ -0,0 +1,83 @@
+/*!
+ * Russian (Русский) language functions
+ */
+
+// These tests were originally made for names of Wikimedia
+// websites, so they don't currently cover all the possible
+// cases.
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ /*global $ */
+ 'use strict';
+
+ var grammarForms = mediaWiki.language.getData( 'ru', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+ switch ( form ) {
+ case 'genitive': // родительный падеж
+ if ( word.slice( -1 ) === 'ь' ) {
+ word = word.slice( 0, -1 ) + 'я';
+ } else if ( word.slice( -2 ) === 'ия' ) {
+ word = word.slice( 0, -2 ) + 'ии';
+ } else if ( word.slice( -2 ) === 'ка' ) {
+ word = word.slice( 0, -2 ) + 'ки';
+ } else if ( word.slice( -2 ) === 'ти' ) {
+ word = word.slice( 0, -2 ) + 'тей';
+ } else if ( word.slice( -2 ) === 'ды' ) {
+ word = word.slice( 0, -2 ) + 'дов';
+ } else if ( word.slice( -1 ) === 'д' ) {
+ word = word.slice( 0, -1 ) + 'да';
+ } else if ( word.slice( -3 ) === 'ные' ) {
+ word = word.slice( 0, -3 ) + 'ных';
+ } else if ( word.slice( -3 ) === 'ник' ) {
+ word = word.slice( 0, -3 ) + 'ника';
+ }
+ break;
+ case 'prepositional': // предложный падеж
+ if ( word.slice( -1 ) === 'ь' ) {
+ word = word.slice( 0, -1 ) + 'е';
+ } else if ( word.slice( -2 ) === 'ия' ) {
+ word = word.slice( 0, -2 ) + 'ии';
+ } else if ( word.slice( -2 ) === 'ка' ) {
+ word = word.slice( 0, -2 ) + 'ке';
+ } else if ( word.slice( -2 ) === 'ти' ) {
+ word = word.slice( 0, -2 ) + 'тях';
+ } else if ( word.slice( -2 ) === 'ды' ) {
+ word = word.slice( 0, -2 ) + 'дах';
+ } else if ( word.slice( -1 ) === 'д' ) {
+ word = word.slice( 0, -1 ) + 'де';
+ } else if ( word.slice( -3 ) === 'ные' ) {
+ word = word.slice( 0, -3 ) + 'ных';
+ } else if ( word.slice( -3 ) === 'ник' ) {
+ word = word.slice( 0, -3 ) + 'нике';
+ }
+ break;
+ case 'languagegen': // язык в родительном падеже ("(с) русского")
+ if ( word.slice( -3 ) === 'кий' ) {
+ word = word.slice( 0, -2 ) + 'ого';
+ } else if ( $.inArray( word, [ 'иврит', 'идиш' ] ) > -1 ) {
+ word = word + 'а';
+ }
+ break;
+ case 'languageprep': // язык в предложном падеже ("(на) русском")
+ if ( word.slice( -3 ) === 'кий' ) {
+ word = word.slice( 0, -2 ) + 'ом';
+ } else if ( $.inArray( word, [ 'иврит', 'идиш' ] ) > -1 ) {
+ word = word + 'е';
+ }
+ break;
+ case 'languageadverb': // наречие с названием языка ("по-русски")
+ if ( word.slice( -3 ) === 'кий' ) {
+ word = 'по-' + word.slice( 0, -1 );
+ } else if ( $.inArray( word, [ 'иврит', 'идиш' ] ) > -1 ) {
+ word = 'на ' + word + 'е';
+ } else if ( $.inArray( word, [ 'идо', 'урду', 'хинди', 'эсперанто' ] ) > -1 ) {
+ word = 'на ' + word;
+ } else {
+ word = 'на языке ' + word;
+ }
+ break;
+ }
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/sl.js b/www/wiki/resources/src/mediawiki.language/languages/sl.js
new file mode 100644
index 00000000..3d8bdfde
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/sl.js
@@ -0,0 +1,19 @@
+/*!
+ * Slovenian (Slovenščina) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms = mediaWiki.language.getData( 'sl', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+ switch ( form ) {
+ case 'mestnik': // locative
+ word = 'o ' + word;
+ break;
+ case 'orodnik': // instrumental
+ word = 'z ' + word;
+ break;
+ }
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/languages/uk.js b/www/wiki/resources/src/mediawiki.language/languages/uk.js
new file mode 100644
index 00000000..138045c6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/languages/uk.js
@@ -0,0 +1,32 @@
+/*!
+ * Ukrainian (Українська) language functions
+ */
+
+mediaWiki.language.convertGrammar = function ( word, form ) {
+ var grammarForms = mediaWiki.language.getData( 'uk', 'grammarForms' );
+ if ( grammarForms && grammarForms[ form ] ) {
+ return grammarForms[ form ][ word ];
+ }
+ switch ( form ) {
+ case 'genitive': // родовий відмінок
+ if ( word.slice( -2 ) === 'ія' ) {
+ word = word.slice( 0, -2 ) + 'ії';
+ } else if ( word.slice( -2 ) === 'ти' ) {
+ word = word.slice( 0, -2 ) + 'т';
+ } else if ( word.slice( -2 ) === 'ди' ) {
+ word = word.slice( 0, -2 ) + 'дів';
+ } else if ( word.slice( -3 ) === 'ник' ) {
+ word = word.slice( 0, -3 ) + 'ника';
+ }
+
+ break;
+ case 'accusative': // знахідний відмінок
+ if ( word.slice( -2 ) === 'ія' ) {
+ word = word.slice( 0, -2 ) + 'ію';
+ }
+
+ break;
+ }
+
+ return word;
+};
diff --git a/www/wiki/resources/src/mediawiki.language/mediawiki.cldr.js b/www/wiki/resources/src/mediawiki.language/mediawiki.cldr.js
new file mode 100644
index 00000000..ca4b6fbe
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/mediawiki.cldr.js
@@ -0,0 +1,32 @@
+( function ( mw ) {
+ 'use strict';
+
+ /**
+ * Namespace for CLDR-related utility methods.
+ *
+ * @class
+ * @singleton
+ */
+ mw.cldr = {
+ /**
+ * Get the plural form index for the number.
+ *
+ * In case none of the rules passed, we return `pluralRules.length` -
+ * that means it is the "other" form.
+ *
+ * @param {number} number
+ * @param {Array} pluralRules
+ * @return {number} plural form index
+ */
+ getPluralForm: function ( number, pluralRules ) {
+ var i;
+ for ( i = 0; i < pluralRules.length; i++ ) {
+ if ( mw.libs.pluralRuleParser( pluralRules[ i ], number ) ) {
+ break;
+ }
+ }
+ return i;
+ }
+ };
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.language/mediawiki.language.fallback.js b/www/wiki/resources/src/mediawiki.language/mediawiki.language.fallback.js
new file mode 100644
index 00000000..b1bab02a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/mediawiki.language.fallback.js
@@ -0,0 +1,35 @@
+/*
+ * Language-fallback-chain-related utilities for mediawiki.language.
+ */
+( function ( mw, $ ) {
+ /**
+ * @class mw.language
+ */
+
+ $.extend( mw.language, {
+
+ /**
+ * Get the language fallback chain for current UI language (not including the language itself).
+ *
+ * @return {string[]} List of language keys, e.g. `['de', 'en']`
+ */
+ getFallbackLanguages: function () {
+ return mw.language.getData(
+ mw.config.get( 'wgUserLanguage' ),
+ 'fallbackLanguages'
+ ) || [];
+ },
+
+ /**
+ * Get the language fallback chain for current UI language, including the language itself.
+ *
+ * @return {string[]} List of language keys, e.g. `['pfl', de', 'en']`
+ */
+ getFallbackLanguageChain: function () {
+ return [ mw.config.get( 'wgUserLanguage' ) ]
+ .concat( mw.language.getFallbackLanguages() );
+ }
+
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.language/mediawiki.language.init.js b/www/wiki/resources/src/mediawiki.language/mediawiki.language.init.js
new file mode 100644
index 00000000..808f6e5e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/mediawiki.language.init.js
@@ -0,0 +1,83 @@
+( function ( mw ) {
+ /**
+ * Base language object with methods related to language support, attempting to mirror some of the
+ * functionality of the Language class in MediaWiki:
+ *
+ * - storing and retrieving language data
+ * - transforming message syntax (`{{PLURAL:}}`, `{{GRAMMAR:}}`, `{{GENDER:}}`)
+ * - formatting numbers
+ *
+ * @class
+ * @singleton
+ */
+ mw.language = {
+ /**
+ * Language-related data (keyed by language, contains instances of mw.Map).
+ * Loaded dynamically (see ResourceLoaderLanguageDataModule class in PHP, registered
+ * as mediawiki.language.data on the client).
+ *
+ * To set data:
+ *
+ * // Override, extend or create the language data object of 'nl'
+ * mw.language.setData( 'nl', 'myKey', 'My value' );
+ *
+ * // Set multiple key/values pairs at once
+ * mw.language.setData( 'nl', { foo: 'X', bar: 'Y' } );
+ *
+ * To get GrammarForms data for language 'nl':
+ *
+ * var grammarForms = mw.language.getData( 'nl', 'grammarForms' );
+ *
+ * Possible data keys:
+ *
+ * - `digitTransformTable`
+ * - `separatorTransformTable`
+ * - `grammarForms`
+ * - `pluralRules`
+ * - `digitGroupingPattern`
+ * - `fallbackLanguages`
+ *
+ * @property
+ */
+ data: {},
+
+ /**
+ * Convenience method for retrieving language data.
+ *
+ * Structured by language code and data key, covering for the potential inexistence of a
+ * data object for this language.
+ *
+ * @param {string} langCode
+ * @param {string} dataKey
+ * @return {Mixed} Value stored in the mw.Map (or `undefined` if there is no map for the
+ * specified langCode)
+ */
+ getData: function ( langCode, dataKey ) {
+ var langData = mw.language.data;
+ langCode = langCode.toLowerCase();
+ if ( langData && langData[ langCode ] instanceof mw.Map ) {
+ return langData[ langCode ].get( dataKey );
+ }
+ return undefined;
+ },
+
+ /**
+ * Convenience method for setting language data.
+ *
+ * Creates the data mw.Map if there isn't one for the specified language already.
+ *
+ * @param {string} langCode
+ * @param {string|Object} dataKey Key or object of key/values
+ * @param {Mixed} [value] Value for dataKey, omit if dataKey is an object
+ */
+ setData: function ( langCode, dataKey, value ) {
+ var langData = mw.language.data;
+ langCode = langCode.toLowerCase();
+ if ( !( langData[ langCode ] instanceof mw.Map ) ) {
+ langData[ langCode ] = new mw.Map();
+ }
+ langData[ langCode ].set( dataKey, value );
+ }
+ };
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.language/mediawiki.language.js b/www/wiki/resources/src/mediawiki.language/mediawiki.language.js
new file mode 100644
index 00000000..6a524340
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/mediawiki.language.js
@@ -0,0 +1,233 @@
+/*
+ * Methods for transforming message syntax.
+ */
+( function ( mw, $ ) {
+
+ /**
+ * @class mw.language
+ */
+ $.extend( mw.language, {
+
+ /**
+ * Process the PLURAL template substitution
+ *
+ * @private
+ * @param {Object} template Template object
+ * @param {string} template.title
+ * @param {Array} template.parameters
+ * @return {string}
+ */
+ procPLURAL: function ( template ) {
+ var count;
+ if ( template.title && template.parameters && mw.language.convertPlural ) {
+ // Check if we have forms to replace
+ if ( template.parameters.length === 0 ) {
+ return '';
+ }
+ // Restore the count into a Number ( if it got converted earlier )
+ count = mw.language.convertNumber( template.title, true );
+ // Do convertPlural call
+ return mw.language.convertPlural( parseInt( count, 10 ), template.parameters );
+ }
+ // Could not process plural return first form or nothing
+ if ( template.parameters[ 0 ] ) {
+ return template.parameters[ 0 ];
+ }
+ return '';
+ },
+
+ /**
+ * Plural form transformations, needed for some languages.
+ *
+ * @param {number} count Non-localized quantifier
+ * @param {Array} forms List of plural forms
+ * @param {Object} [explicitPluralForms] List of explicit plural forms
+ * @return {string} Correct form for quantifier in this language
+ */
+ convertPlural: function ( count, forms, explicitPluralForms ) {
+ var pluralRules,
+ pluralFormIndex = 0;
+
+ if ( explicitPluralForms && ( explicitPluralForms[ count ] !== undefined ) ) {
+ return explicitPluralForms[ count ];
+ }
+
+ if ( !forms || forms.length === 0 ) {
+ return '';
+ }
+
+ pluralRules = mw.language.getData( mw.config.get( 'wgUserLanguage' ), 'pluralRules' );
+ if ( !pluralRules ) {
+ // default fallback.
+ return ( count === 1 ) ? forms[ 0 ] : forms[ 1 ];
+ }
+ pluralFormIndex = mw.cldr.getPluralForm( count, pluralRules );
+ pluralFormIndex = Math.min( pluralFormIndex, forms.length - 1 );
+ return forms[ pluralFormIndex ];
+ },
+
+ /**
+ * Pads an array to a specific length by copying the last one element.
+ *
+ * @private
+ * @param {Array} forms Number of forms given to convertPlural
+ * @param {number} count Number of forms required
+ * @return {Array} Padded array of forms
+ */
+ preConvertPlural: function ( forms, count ) {
+ while ( forms.length < count ) {
+ forms.push( forms[ forms.length - 1 ] );
+ }
+ return forms;
+ },
+
+ /**
+ * Provides an alternative text depending on specified gender.
+ *
+ * Usage in message text: `{{gender:[gender|user object]|masculine|feminine|neutral}}`.
+ * If second or third parameter are not specified, masculine is used.
+ *
+ * These details may be overridden per language.
+ *
+ * @param {string} gender 'male', 'female', or anything else for neutral.
+ * @param {Array} forms List of gender forms
+ * @return {string}
+ */
+ gender: function ( gender, forms ) {
+ if ( !forms || forms.length === 0 ) {
+ return '';
+ }
+ forms = mw.language.preConvertPlural( forms, 2 );
+ if ( gender === 'male' ) {
+ return forms[ 0 ];
+ }
+ if ( gender === 'female' ) {
+ return forms[ 1 ];
+ }
+ return ( forms.length === 3 ) ? forms[ 2 ] : forms[ 0 ];
+ },
+
+ /**
+ * Grammatical transformations, needed for inflected languages.
+ * Invoked by putting `{{grammar:case|word}}` in a message.
+ *
+ * The rules can be defined in $wgGrammarForms global or computed
+ * dynamically by overriding this method per language.
+ *
+ * @param {string} word
+ * @param {string} form
+ * @return {string}
+ */
+ convertGrammar: function ( word, form ) {
+ var userLanguage, forms, transformations,
+ patterns, i, rule, sourcePattern, regexp, replacement;
+
+ userLanguage = mw.config.get( 'wgUserLanguage' );
+
+ forms = mw.language.getData( userLanguage, 'grammarForms' );
+ if ( forms && forms[ form ] ) {
+ return forms[ form ][ word ];
+ }
+
+ transformations = mediaWiki.language.getData( userLanguage, 'grammarTransformations' );
+
+ if ( !( transformations && transformations[ form ] ) ) {
+ return word;
+ }
+
+ patterns = transformations[ form ];
+
+ // Some names of grammar rules are aliases for other rules.
+ // In such cases the value is a string rather than object,
+ // so load the actual rules.
+ if ( typeof patterns === 'string' ) {
+ patterns = transformations[ patterns ];
+ }
+
+ for ( i = 0; i < patterns.length; i++ ) {
+ rule = patterns[ i ];
+ sourcePattern = rule[ 0 ];
+
+ if ( sourcePattern === '@metadata' ) {
+ continue;
+ }
+
+ regexp = new RegExp( sourcePattern );
+ replacement = rule[ 1 ];
+
+ if ( word.match( regexp ) ) {
+ return word.replace( regexp, replacement );
+ }
+ }
+
+ return word;
+ },
+
+ /**
+ * Turn a list of string into a simple list using commas and 'and'.
+ *
+ * See Language::listToText in languages/Language.php
+ *
+ * @param {string[]} list
+ * @return {string}
+ */
+ listToText: function ( list ) {
+ var text = '',
+ i = 0;
+
+ for ( ; i < list.length; i++ ) {
+ text += list[ i ];
+ if ( list.length - 2 === i ) {
+ text += mw.msg( 'and' ) + mw.msg( 'word-separator' );
+ } else if ( list.length - 1 !== i ) {
+ text += mw.msg( 'comma-separator' );
+ }
+ }
+ return text;
+ },
+
+ setSpecialCharacters: function ( data ) {
+ this.specialCharacters = data;
+ },
+
+ /**
+ * Formats language tags according the BCP47 standard.
+ * See wfBCP47 for the PHP implementation.
+ *
+ * @param {string} languageTag Well-formed language tag
+ * @return {string}
+ */
+ bcp47: function ( languageTag ) {
+ var formatted,
+ isFirstSegment = true,
+ isPrivate = false,
+ segments = languageTag.split( '-' );
+
+ formatted = segments.map( function ( segment ) {
+ var newSegment;
+
+ // when previous segment is x, it is a private segment and should be lc
+ if ( isPrivate ) {
+ newSegment = segment.toLowerCase();
+ // ISO 3166 country code
+ } else if ( segment.length === 2 && !isFirstSegment ) {
+ newSegment = segment.toUpperCase();
+ // ISO 15924 script code
+ } else if ( segment.length === 4 && !isFirstSegment ) {
+ newSegment = segment.charAt( 0 ).toUpperCase() + segment.substring( 1 ).toLowerCase();
+ // Use lowercase for other cases
+ } else {
+ newSegment = segment.toLowerCase();
+ }
+
+ isPrivate = segment.toLowerCase() === 'x';
+ isFirstSegment = false;
+
+ return newSegment;
+ } );
+
+ return formatted.join( '-' );
+ }
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.language/mediawiki.language.months.js b/www/wiki/resources/src/mediawiki.language/mediawiki.language.months.js
new file mode 100644
index 00000000..5a1a5cb6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/mediawiki.language.months.js
@@ -0,0 +1,56 @@
+/*
+ * Transfer of month names from messages into mw.language.
+ *
+ * Loading this module also ensures the availability of appropriate messages via mw.msg.
+ */
+( function ( mw, $ ) {
+ var
+ monthMessages = [
+ 'january', 'february', 'march', 'april',
+ 'may_long', 'june', 'july', 'august',
+ 'september', 'october', 'november', 'december'
+ ],
+ monthGenMessages = [
+ 'january-gen', 'february-gen', 'march-gen', 'april-gen',
+ 'may-gen', 'june-gen', 'july-gen', 'august-gen',
+ 'september-gen', 'october-gen', 'november-gen', 'december-gen'
+ ],
+ monthAbbrevMessages = [
+ 'jan', 'feb', 'mar', 'apr',
+ 'may', 'jun', 'jul', 'aug',
+ 'sep', 'oct', 'nov', 'dec'
+ ];
+
+ // Function suitable for passing to jQuery.map
+ // Can't use mw.msg directly because jQuery.map passes element index as second argument
+ function mwMsgMapper( key ) {
+ return mw.msg( key );
+ }
+
+ /**
+ * Information about month names in current UI language.
+ *
+ * Object keys:
+ *
+ * - `names`: array of month names (in nominative case in languages which have the distinction),
+ * zero-indexed
+ * - `genitive`: array of month names in genitive case, zero-indexed
+ * - `abbrev`: array of three-letter-long abbreviated month names, zero-indexed
+ * - `keys`: object with three keys like the above, containing zero-indexed arrays of message keys
+ * for appropriate messages which can be passed to mw.msg.
+ *
+ * @property
+ * @member mw.language
+ */
+ mw.language.months = {
+ keys: {
+ names: monthMessages,
+ genitive: monthGenMessages,
+ abbrev: monthAbbrevMessages
+ },
+ names: $.map( monthMessages, mwMsgMapper ),
+ genitive: $.map( monthGenMessages, mwMsgMapper ),
+ abbrev: $.map( monthAbbrevMessages, mwMsgMapper )
+ };
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.language/mediawiki.language.numbers.js b/www/wiki/resources/src/mediawiki.language/mediawiki.language.numbers.js
new file mode 100644
index 00000000..83277cb0
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/mediawiki.language.numbers.js
@@ -0,0 +1,301 @@
+/*
+ * Number-related utilities for mediawiki.language.
+ */
+( function ( mw, $ ) {
+ /**
+ * @class mw.language
+ */
+
+ /**
+ * Replicate a string 'n' times.
+ *
+ * @private
+ * @param {string} str The string to replicate
+ * @param {number} num Number of times to replicate the string
+ * @return {string}
+ */
+ function replicate( str, num ) {
+ var buf = [];
+
+ if ( num <= 0 || !str ) {
+ return '';
+ }
+
+ while ( num-- ) {
+ buf.push( str );
+ }
+ return buf.join( '' );
+ }
+
+ /**
+ * Pad a string to guarantee that it is at least `size` length by
+ * filling with the character `ch` at either the start or end of the
+ * string. Pads at the start, by default.
+ *
+ * Example: Fill the string to length 10 with '+' characters on the right.
+ *
+ * pad( 'blah', 10, '+', true ); // => 'blah++++++'
+ *
+ * @private
+ * @param {string} text The string to pad
+ * @param {number} size The length to pad to
+ * @param {string} [ch='0'] Character to pad with
+ * @param {boolean} [end=false] Adds padding at the end if true, otherwise pads at start
+ * @return {string}
+ */
+ function pad( text, size, ch, end ) {
+ var out, padStr;
+
+ if ( !ch ) {
+ ch = '0';
+ }
+
+ out = String( text );
+ padStr = replicate( ch, Math.ceil( ( size - out.length ) / ch.length ) );
+
+ return end ? out + padStr : padStr + out;
+ }
+
+ /**
+ * Apply numeric pattern to absolute value using options. Gives no
+ * consideration to local customs.
+ *
+ * Adapted from dojo/number library with thanks
+ * <http://dojotoolkit.org/reference-guide/1.8/dojo/number.html>
+ *
+ * @private
+ * @param {number} value the number to be formatted, ignores sign
+ * @param {string} pattern the number portion of a pattern (e.g. `#,##0.00`)
+ * @param {Object} [options] If provided, both option keys must be present:
+ * @param {string} options.decimal The decimal separator. Defaults to: `'.'`.
+ * @param {string} options.group The group separator. Defaults to: `','`.
+ * @return {string}
+ */
+ function commafyNumber( value, pattern, options ) {
+ var padLength,
+ patternDigits,
+ index,
+ whole,
+ off,
+ remainder,
+ patternParts = pattern.split( '.' ),
+ maxPlaces = ( patternParts[ 1 ] || [] ).length,
+ valueParts = String( Math.abs( value ) ).split( '.' ),
+ fractional = valueParts[ 1 ] || '',
+ groupSize = 0,
+ groupSize2 = 0,
+ pieces = [];
+
+ options = options || {
+ group: ',',
+ decimal: '.'
+ };
+
+ if ( isNaN( value ) ) {
+ return value;
+ }
+
+ if ( patternParts[ 1 ] ) {
+ // Pad fractional with trailing zeros
+ padLength = ( patternParts[ 1 ] && patternParts[ 1 ].lastIndexOf( '0' ) + 1 );
+
+ if ( padLength > fractional.length ) {
+ valueParts[ 1 ] = pad( fractional, padLength, '0', true );
+ }
+
+ // Truncate fractional
+ if ( maxPlaces < fractional.length ) {
+ valueParts[ 1 ] = fractional.slice( 0, maxPlaces );
+ }
+ } else {
+ if ( valueParts[ 1 ] ) {
+ valueParts.pop();
+ }
+ }
+
+ // Pad whole with leading zeros
+ patternDigits = patternParts[ 0 ].replace( ',', '' );
+
+ padLength = patternDigits.indexOf( '0' );
+
+ if ( padLength !== -1 ) {
+ padLength = patternDigits.length - padLength;
+
+ if ( padLength > valueParts[ 0 ].length ) {
+ valueParts[ 0 ] = pad( valueParts[ 0 ], padLength );
+ }
+
+ // Truncate whole
+ if ( patternDigits.indexOf( '#' ) === -1 ) {
+ valueParts[ 0 ] = valueParts[ 0 ].slice( valueParts[ 0 ].length - padLength );
+ }
+ }
+
+ // Add group separators
+ index = patternParts[ 0 ].lastIndexOf( ',' );
+
+ if ( index !== -1 ) {
+ groupSize = patternParts[ 0 ].length - index - 1;
+ remainder = patternParts[ 0 ].slice( 0, index );
+ index = remainder.lastIndexOf( ',' );
+ if ( index !== -1 ) {
+ groupSize2 = remainder.length - index - 1;
+ }
+ }
+
+ for ( whole = valueParts[ 0 ]; whole; ) {
+ off = groupSize ? whole.length - groupSize : 0;
+ pieces.push( ( off > 0 ) ? whole.slice( off ) : whole );
+ whole = ( off > 0 ) ? whole.slice( 0, off ) : '';
+
+ if ( groupSize2 ) {
+ groupSize = groupSize2;
+ groupSize2 = null;
+ }
+ }
+ valueParts[ 0 ] = pieces.reverse().join( options.group );
+
+ return valueParts.join( options.decimal );
+ }
+
+ /**
+ * Helper function to flip transformation tables.
+ *
+ * @param {...Object} Transformation tables
+ * @return {Object}
+ */
+ function flipTransform() {
+ var i, key, table, flipped = {};
+
+ // Ensure we strip thousand separators. This might be overwritten.
+ flipped[ ',' ] = '';
+
+ for ( i = 0; i < arguments.length; i++ ) {
+ table = arguments[ i ];
+ for ( key in table ) {
+ if ( table.hasOwnProperty( key ) ) {
+ // The thousand separator should be deleted
+ flipped[ table[ key ] ] = key === ',' ? '' : key;
+ }
+ }
+ }
+
+ return flipped;
+ }
+
+ $.extend( mw.language, {
+
+ /**
+ * Converts a number using #getDigitTransformTable.
+ *
+ * @param {number} num Value to be converted
+ * @param {boolean} [integer=false] Whether to convert the return value to an integer
+ * @return {number|string} Formatted number
+ */
+ convertNumber: function ( num, integer ) {
+ var transformTable, digitTransformTable, separatorTransformTable,
+ i, numberString, convertedNumber, pattern;
+
+ // Quick shortcut for plain numbers
+ if ( integer && parseInt( num, 10 ) === num ) {
+ return num;
+ }
+
+ // Load the transformation tables (can be empty)
+ digitTransformTable = mw.language.getDigitTransformTable();
+ separatorTransformTable = mw.language.getSeparatorTransformTable();
+
+ if ( integer ) {
+ // Reverse the digit transformation tables if we are doing unformatting
+ transformTable = flipTransform( separatorTransformTable, digitTransformTable );
+ numberString = String( num );
+ } else {
+ // This check being here means that digits can still be unformatted
+ // even if we do not produce them. This seems sane behavior.
+ if ( mw.config.get( 'wgTranslateNumerals' ) ) {
+ transformTable = digitTransformTable;
+ }
+
+ // Commaying is more complex, so we handle it here separately.
+ // When unformatting, we just use separatorTransformTable.
+ pattern = mw.language.getData( mw.config.get( 'wgUserLanguage' ),
+ 'digitGroupingPattern' ) || '#,##0.###';
+ numberString = mw.language.commafy( num, pattern );
+ }
+
+ if ( transformTable ) {
+ convertedNumber = '';
+ for ( i = 0; i < numberString.length; i++ ) {
+ if ( transformTable.hasOwnProperty( numberString[ i ] ) ) {
+ convertedNumber += transformTable[ numberString[ i ] ];
+ } else {
+ convertedNumber += numberString[ i ];
+ }
+ }
+ } else {
+ convertedNumber = numberString;
+ }
+
+ if ( integer ) {
+ // Parse string to integer. This loses decimals!
+ convertedNumber = parseInt( convertedNumber, 10 );
+ }
+
+ return convertedNumber;
+ },
+
+ /**
+ * Get the digit transform table for current UI language.
+ *
+ * @return {Object|Array}
+ */
+ getDigitTransformTable: function () {
+ return mw.language.getData( mw.config.get( 'wgUserLanguage' ),
+ 'digitTransformTable' ) || [];
+ },
+
+ /**
+ * Get the separator transform table for current UI language.
+ *
+ * @return {Object|Array}
+ */
+ getSeparatorTransformTable: function () {
+ return mw.language.getData( mw.config.get( 'wgUserLanguage' ),
+ 'separatorTransformTable' ) || [];
+ },
+
+ /**
+ * Apply pattern to format value as a string.
+ *
+ * Using patterns from [Unicode TR35](http://www.unicode.org/reports/tr35/#Number_Format_Patterns).
+ *
+ * @param {number} value
+ * @param {string} pattern Pattern string as described by Unicode TR35
+ * @throws {Error} If unable to find a number expression in `pattern`.
+ * @return {string}
+ */
+ commafy: function ( value, pattern ) {
+ var numberPattern,
+ transformTable = mw.language.getSeparatorTransformTable(),
+ group = transformTable[ ',' ] || ',',
+ numberPatternRE = /[#0,]*[#0](?:\.0*#*)?/, // not precise, but good enough
+ decimal = transformTable[ '.' ] || '.',
+ patternList = pattern.split( ';' ),
+ positivePattern = patternList[ 0 ];
+
+ pattern = patternList[ ( value < 0 ) ? 1 : 0 ] || ( '-' + positivePattern );
+ numberPattern = positivePattern.match( numberPatternRE );
+
+ if ( !numberPattern ) {
+ throw new Error( 'unable to find a number expression in pattern: ' + pattern );
+ }
+
+ return pattern.replace( numberPatternRE, commafyNumber( value, numberPattern[ 0 ], {
+ decimal: decimal,
+ group: group
+ } ) );
+ }
+
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.language/specialcharacters.json b/www/wiki/resources/src/mediawiki.language/specialcharacters.json
new file mode 100644
index 00000000..f0a86ffc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.language/specialcharacters.json
@@ -0,0 +1,510 @@
+{
+ "latin": [
+ "Á", "á", "À", "à", "Â", "â", "Ä", "ä", "Ã", "ã", "Ǎ", "ǎ", "Ā", "ā", "Ă", "ă", "Ą", "ą", "Å", "å", "Ć", "ć", "Ĉ", "ĉ", "Ç", "ç", "Č", "č", "Ċ", "ċ", "Đ", "đ", "Ď", "ď", "É", "é", "È", "è", "Ê", "ê", "Ë", "ë", "Ě", "ě", "Ē", "ē", "Ĕ", "ĕ", "Ė", "ė", "Ę", "ę", "Ĝ", "ĝ", "Ģ", "ģ", "Ğ", "ğ", "Ġ", "ġ", "Ĥ", "ĥ", "Ħ", "ħ", "Í", "í", "Ì", "ì", "Î", "î", "Ï", "ï", "Ĩ", "ĩ", "Ǐ", "ǐ", "Ī", "ī", "Ĭ", "ĭ", "İ", "ı", "Į", "į", "Ĵ", "ĵ", "Ķ", "ķ", "Ĺ", "ĺ", "Ļ", "ļ", "Ľ", "ľ", "Ł", "ł", "Ń", "ń", "Ñ", "ñ", "Ņ", "ņ", "Ň", "ň", "Ó", "ó", "Ò", "ò", "Ô", "ô", "Ö", "ö", "Õ", "õ", "Ǒ", "ǒ", "Ō", "ō", "Ŏ", "ŏ", "Ǫ", "ǫ", "Ő", "ő", "Ŕ", "ŕ", "Ŗ", "ŗ", "Ř", "ř", "Ś", "ś", "Ŝ", "ŝ", "Ş", "ş", "Š", "š", "Ș", "ș", "Ț", "ț", "Ť", "ť", "Ú", "ú", "Ù", "ù", "Û", "û", "Ü", "ü", "Ũ", "ũ", "Ů", "ů", "Ǔ", "ǔ", "Ū", "ū", "ǖ", "ǘ", "ǚ", "ǜ", "Ŭ", "ŭ", "Ų", "ų", "Ű", "ű", "Ŵ", "ŵ", "Ý", "ý", "Ŷ", "ŷ", "Ÿ", "ÿ", "Ȳ", "ȳ", "Ź", "ź", "Ž", "ž", "Ż", "ż", "Æ", "æ", "Ǣ", "ǣ", "Ø", "ø", "Œ", "œ", "ß", "Ð", "ð", "Þ", "þ", "Ə", "ə"
+ ],
+ "latinextended": [
+ "Ḁ", "ḁ", "ẚ", "Ạ", "ạ", "Ả", "ả", "Ấ", "ấ", "Ầ", "ầ", "Ẩ", "ẩ", "Ẫ", "ẫ", "Ậ", "ậ", "Ắ", "ắ", "Ằ", "ằ", "Ẳ", "ẳ", "Ẵ", "ẵ", "Ặ", "ặ", "Ḃ", "ḃ", "Ḅ", "ḅ", "Ḇ", "ḇ", "Ḉ", "ḉ", "Ḋ", "ḋ", "Ḍ", "ḍ", "Ḏ", "ḏ", "Ḑ", "ḑ", "Ḓ", "ḓ", "Ḕ", "ḕ", "Ḗ", "ḗ", "Ḙ", "ḙ", "Ḛ", "ḛ", "Ḝ", "ḝ", "Ẹ", "ẹ", "Ẻ", "ẻ", "Ẽ", "ẽ", "Ế", "ế", "Ề", "ề", "Ể", "ể", "Ễ", "ễ", "Ệ", "ệ", "Ḟ", "ḟ", "Ḡ", "ḡ", "Ḣ", "ḣ", "Ḥ", "ḥ", "Ḧ", "ḧ", "Ḩ", "ḩ", "Ḫ", "ḫ", "ẖ", "Ḭ", "ḭ", "Ḯ", "ḯ", "Ỉ", "ỉ", "Ị", "ị", "Ḱ", "ḱ", "Ḳ", "ḳ", "Ḵ", "ḵ", "Ḷ", "ḷ", "Ḹ", "ḹ", "Ḻ", "ḻ", "Ḽ", "ḽ", "Ỻ", "ỻ", "Ḿ", "ḿ", "Ṁ", "ṁ", "Ṃ", "ṃ", "Ṅ", "ṅ", "Ṇ", "ṇ", "Ṉ", "ṉ", "Ṋ", "ṋ", "Ṍ", "ṍ", "Ṏ", "ṏ", "Ṑ", "ṑ", "Ṓ", "ṓ", "Ọ", "ọ", "Ỏ", "ỏ", "Ố", "ố", "Ồ", "ồ", "Ổ", "ổ", "Ỗ", "ỗ", "Ộ", "ộ", "Ớ", "ớ", "Ờ", "ờ", "Ở", "ở", "Ỡ", "ỡ", "Ợ", "ợ", "Ǿ", "ǿ", "Ơ", "ơ", "Ṕ", "ṕ", "Ṗ", "ṗ", "Ṙ", "ṙ", "Ṛ", "ṛ", "Ṝ", "ṝ", "Ṟ", "ṟ", "Ṡ", "ṡ", "ẛ", "Ṣ", "ṣ", "Ṥ", "ṥ", "Ṧ", "ṧ", "Ṩ", "ṩ", "ẜ", "ẝ", "Ṫ", "ṫ", "Ṭ", "ṭ", "Ṯ", "ṯ", "Ṱ", "ṱ", "ẗ", "Ṳ", "ṳ", "Ṵ", "ṵ", "Ṷ", "ṷ", "Ṹ", "ṹ", "Ṻ", "ṻ", "Ụ", "ụ", "Ủ", "ủ", "Ứ", "ứ", "Ừ", "ừ", "Ử", "ử", "Ữ", "ữ", "Ự", "ự", "Ư", "ư", "Ǖ", "Ǘ", "Ǚ", "Ǜ", "Ṽ", "ṽ", "Ṿ", "ṿ", "Ỽ", "ỽ", "Ẁ", "ẁ", "Ẃ", "ẃ", "Ẅ", "ẅ", "Ẇ", "ẇ", "Ẉ", "ẉ", "ẘ", "Ẋ", "ẋ", "Ẍ", "ẍ", "Ẏ", "ẏ", "ẙ", "Ỳ", "ỳ", "Ỵ", "ỵ", "Ỷ", "ỷ", "Ỹ", "ỹ", "Ỿ", "ỿ", "Ẑ", "ẑ", "Ẓ", "ẓ", "Ẕ", "ẕ", "Ǽ", "ǽ", "ẞ", "ẟ"
+ ],
+ "ipa": [
+ "p", "t̪", "t", "ʈ", "c", "k", "q", "ʡ", "ʔ", "b", "d̪", "d", "ɖ", "ɟ", "ɡ", "ɢ", "ɓ", "ɗ", "ʄ", "ɠ", "ʛ", "t͡s", "t͡ʃ", "t͡ɕ", "d͡z", "d͡ʒ", "d͡ʑ", "ɸ", "f", "θ", "s", "ʃ", "ʅ", "ʆ", "ʂ", "ɕ", "ç", "ɧ", "x", "χ", "ħ", "ʜ", "h", "β", "v", "ʍ", "ð", "z", "ʒ", "ʓ", "ʐ", "ʑ", "ʝ", "ɣ", "ʁ", "ʕ", "ʖ", "ʢ", "ɦ", "ɬ", "ɮ", "m", "m̩", "ɱ", "ɱ̩", "ɱ̍", "n̪", "n̪̍", "n", "n̩", "ɳ", "ɳ̩", "ɲ", "ɲ̩", "ŋ", "ŋ̍", "ŋ̩", "ɴ", "ɴ̩", "ʙ", "ʙ̩", "r", "r̩", "ʀ", "ʀ̩", "ɾ", "ɽ", "ɿ", "ɺ", "l̪", "l̪̩", "l", "l̩", "ɫ", "ɫ̩", "ɭ", "ɭ̩", "ʎ", "ʎ̩", "ʟ", "ʟ̩", "w", "ɥ", "ʋ", "ɹ", "ɻ", "j", "ɰ", "ʘ", "ǂ", "ǀ", "!", "ǁ", "ʰ", "ʱ", "ʷ", "ʸ", "ʲ", "ʳ", "ⁿ", "ˡ", "ʴ", "ʵ", "ˢ", "ˣ", "ˠ", "ʶ", "ˤ", "ˁ", "ˀ", "ʼ", "i", "i̯", "ĩ", "y", "y̯", "ỹ", "ɪ", "ɪ̯", "ɪ̃", "ʏ", "ʏ̯", "ʏ̃", "ɨ", "ɨ̯", "ɨ̃", "ʉ", "ʉ̯", "ʉ̃", "ɯ", "ɯ̯", "ɯ̃", "u", "u̯", "ũ", "ʊ", "ʊ̯", "ʊ̃", "e", "e̯", "ẽ", "ø", "ø̯", "ø̃", "ɘ", "ɘ̯", "ɘ̃", "ɵ", "ɵ̯", "ɵ̃", "ɤ", "ɤ̯", "ɤ̃", "o", "o̯", "õ", "ɛ", "ɛ̯", "ɛ̃", "œ", "œ̯", "œ̃", "ɜ", "ɜ̯", "ɜ̃", "ə", "ə̯", "ə̃", "ɞ", "ɞ̯", "ɞ̃", "ʌ", "ʌ̯", "ʌ̃", "ɔ", "ɔ̯", "ɔ̃", "æ", "æ̯", "æ̃", "ɶ", "ɶ̯", "ɶ̃", "a", "a̯", "ã", "ɐ", "ɐ̯", "ɐ̃", "ɑ", "ɑ̯", "ɑ̃", "ɒ", "ɒ̯", "ɒ̃", "ˈ", "ˌ", "ː", "ˑ", "˘", ".", "‿", "|", "‖", "ɚ", "ɝ"
+ ],
+ "symbols": [
+ "~", "|", "¡", "¿", "†", "‡", "↔", "↑", "↓", "•", "¶", "#", "½", "⅓", "⅔", "¼", "¾", "⅛", "⅜", "⅝", "⅞", "∞", "‘", "’",
+ {
+ "label": "“”",
+ "action": {
+ "type": "encapsulate",
+ "options": {
+ "pre": "“",
+ "post": "”"
+ }
+ }
+ },
+ {
+ "label": "„“",
+ "action": {
+ "type": "encapsulate",
+ "options": {
+ "pre": "„",
+ "post": "“"
+ }
+ }
+ },
+ {
+ "label": "„”",
+ "action": {
+ "type": "encapsulate",
+ "options": {
+ "pre": "„",
+ "post": "”"
+ }
+ }
+ },
+ {
+ "label": "«»",
+ "action": {
+ "type": "encapsulate",
+ "options": {
+ "pre": "«",
+ "post": "»"
+ }
+ }
+ },
+ {
+ "label": "‹›",
+ "action": {
+ "type": "encapsulate",
+ "options": {
+ "pre": "‹",
+ "post": "›"
+ }
+ }
+ },
+ {
+ "label": "⟨⟩",
+ "action": {
+ "type": "encapsulate",
+ "options": {
+ "pre": "⟨",
+ "post": "⟩"
+ }
+ }
+ },
+ "¤", "₳", "฿", "₵", "¢", "₡", "₢", "$", "₫", "₯", "€", "₠", "₣", "ƒ", "₴", "₭", "₤", "ℳ", "₥", "₦", "№", "₧", "₰", "£", "៛", "₨", "₪", "৳", "₮", "₩", "¥", "♠", "♣", "♥", "♦", "m²", "m³",
+ {
+ "label": "–",
+ "titleMsg": "special-characters-title-endash",
+ "action": {
+ "type": "replace",
+ "options": {
+ "peri": "–",
+ "selectPeri": false
+ }
+ }
+ },
+ {
+ "label": "—",
+ "titleMsg": "special-characters-title-emdash",
+ "action": {
+ "type": "replace",
+ "options": {
+ "peri": "—",
+ "selectPeri": false
+ }
+ }
+ },
+ "…", "‘", "’", "“", "”", "°", "%", "‰", "′", "″", "≈", "≠", "≤", "≥", "±",
+ {
+ "label": "−",
+ "titleMsg": "special-characters-title-minus",
+ "action": {
+ "type": "replace",
+ "options": {
+ "peri": "−",
+ "selectPeri": false
+ }
+ }
+ },
+ "×", "÷", "←", "→", "·", "§", "‽"
+ ],
+ "greek": [
+ "Α", "Ά", "α", "ά", "Β", "β", "Γ", "γ", "Δ", "δ", "Ε", "Έ", "ε", "έ", "Ζ", "ζ", "Η", "Ή", "η", "ή", "Θ", "θ", "Ι", "Ί", "ι", "ί", "Κ", "κ", "Λ", "λ", "Μ", "μ", "Ν", "ν", "Ξ", "ξ", "Ο", "Ό", "ο", "ό", "Π", "π", "Ρ", "ρ", "Σ", "σ", "ς", "Τ", "τ", "Υ", "Ύ", "υ", "ύ", "Φ", "φ", "Χ", "χ", "Ψ", "ψ", "Ω", "Ώ", "ω", "ώ"
+ ],
+ "greekextended": [
+ "ἀ", "ἁ", "ἂ", "ἃ", "ἄ", "ἅ", "ἆ", "ἇ", "Ἀ", "Ἁ", "Ἂ", "Ἃ", "Ἄ", "Ἅ", "Ἆ", "Ἇ", "ἐ", "ἑ", "ἒ", "ἓ", "ἔ", "ἕ", "Ἐ", "Ἑ", "Ἒ", "Ἓ", "Ἔ", "Ἕ", "ἠ", "ἡ", "ἢ", "ἣ", "ἤ", "ἥ", "ἦ", "ἧ", "Ἠ", "Ἡ", "Ἢ", "Ἣ", "Ἤ", "Ἥ", "Ἦ", "Ἧ", "ἰ", "ἱ", "ἲ", "ἳ", "ἴ", "ἵ", "ἶ", "ἷ", "Ἰ", "Ἱ", "Ἲ", "Ἳ", "Ἴ", "Ἵ", "Ἶ", "Ἷ", "ὀ", "ὁ", "ὂ", "ὃ", "ὄ", "ὅ", "Ὀ", "Ὁ", "Ὂ", "Ὃ", "Ὄ", "Ὅ", "ὐ", "ὑ", "ὒ", "ὓ", "ὔ", "ὕ", "ὖ", "ὗ", "Ὑ", "Ὓ", "Ὕ", "Ὗ", "ὠ", "ὡ", "ὢ", "ὣ", "ὤ", "ὥ", "ὦ", "ὧ", "Ὠ", "Ὡ", "Ὢ", "Ὣ", "Ὤ", "Ὥ", "Ὦ", "Ὧ", "ὰ", "ά", "ὲ", "έ", "ὴ", "ή", "ὶ", "ί", "ὸ", "ό", "ὺ", "ύ", "ὼ", "ώ", "ᾀ", "ᾁ", "ᾂ", "ᾃ", "ᾄ", "ᾅ", "ᾆ", "ᾇ", "ᾈ", "ᾉ", "ᾊ", "ᾋ", "ᾌ", "ᾍ", "ᾎ", "ᾏ", "ᾐ", "ᾑ", "ᾒ", "ᾓ", "ᾔ", "ᾕ", "ᾖ", "ᾗ", "ᾘ", "ᾙ", "ᾚ", "ᾛ", "ᾜ", "ᾝ", "ᾞ", "ᾟ", "ᾠ", "ᾡ", "ᾢ", "ᾣ", "ᾤ", "ᾥ", "ᾦ", "ᾧ", "ᾨ", "ᾩ", "ᾪ", "ᾫ", "ᾬ", "ᾭ", "ᾮ", "ᾯ", "ᾰ", "ᾱ", "ᾲ", "ᾳ", "ᾴ", "ᾶ", "ᾷ", "Ᾰ", "Ᾱ", "Ὰ", "Ά", "ᾼ", "᾽", "ι", "᾿", "῀", "῁", "ῂ", "ῃ", "ῄ", "ῆ", "ῇ", "Ὲ", "Έ", "Ὴ", "Ή", "ῌ", "῍", "῎", "῏", "ῐ", "ῑ", "ῒ", "ΐ", "ῖ", "ῗ", "Ῐ", "Ῑ", "Ὶ", "Ί", "῝", "῞", "῟", "ῠ", "ῡ", "ῢ", "ΰ", "ῤ", "ῥ", "ῦ", "ῧ", "Ῠ", "Ῡ", "Ὺ", "Ύ", "Ῥ", "῭", "΅", "`", "ῲ", "ῳ", "ῴ", "ῶ", "ῷ", "Ὸ", "Ό", "Ὼ", "Ώ", "ῼ", "´", "῾"
+ ],
+ "cyrillic": [
+ "А", "а", "Ӑ", "ӑ", "Ӓ", "ӓ", "Ә", "ә", "Ӛ", "ӛ", "Б", "б", "В", "в", "Г", "г", "Ґ", "ґ", "Ӷ", "ӷ", "Ѓ", "ѓ", "Ӻ", "ӻ", "Ғ", "ғ", "Ҕ", "ҕ", "Д", "д", "Ԁ", "ԁ", "Ԃ", "ԃ", "Ђ", "ђ", "Е", "е", "Ѐ", "ѐ", "Є", "є", "Ё", "ё", "Ӗ", "ӗ", "Ҽ", "ҽ", "Ҿ", "ҿ", "Ж", "ж", "Җ", "җ", "Ӂ", "ӂ", "Ӝ", "ӝ", "З", "з", "Ҙ", "ҙ", "Ӟ", "ӟ", "Ԑ", "ԑ", "Ӡ", "ӡ", "Ѕ", "ѕ", "Ԅ", "ԅ", "Ԇ", "ԇ", "И", "и", "І", "і", "Ї", "ї",
+ [
+ "◌Ӏ",
+ "Ӏ"
+ ],
+ [
+ "◌ӏ",
+ "ӏ"
+ ],
+ "Й", "й", "Ӣ", "ӣ", "Ѝ", "ѝ", "Ҋ", "ҋ", "Ӥ", "ӥ", "Ј", "ј", "К", "к", "Ќ", "ќ", "Қ", "қ", "Ҝ", "ҝ", "Ҟ", "ҟ", "Ҡ", "ҡ", "Ӄ", "ӄ", "Ԛ", "ԛ", "Л", "л", "Љ", "љ", "Ԉ", "ԉ", "Ԓ", "ԓ", "Ӆ", "ӆ", "М", "м", "Ӎ", "ӎ", "Н", "н", "Њ", "њ", "Ң", "ң", "Ҥ", "ҥ", "Ӈ", "ӈ", "Ԋ", "ԋ", "Ӊ", "ӊ", "О", "о", "Ҩ", "ҩ", "Ӧ", "ӧ", "Ө", "ө", "Ӫ", "ӫ", "П", "п", "Ԥ", "ԥ", "Ҧ", "ҧ", "Р", "р", "Ҏ", "ҏ", "С", "с", "Ҫ", "ҫ", "Т", "т", "Ћ", "ћ", "Ԍ", "ԍ", "Ҭ", "ҭ", "Ԏ", "ԏ", "У", "у", "Ў", "ў", "Ӯ", "ӯ", "Ӱ", "ӱ", "Ӳ", "ӳ", "Ү", "ү", "Ұ", "ұ", "Ф", "ф", "Х", "х", "Ҳ", "ҳ", "Ӽ", "ӽ", "Ӿ", "ӿ", "Һ", "һ", "Ц", "ц", "Ч", "ч", "Ҵ", "ҵ", "Ҷ", "ҷ", "Ҹ", "ҹ", "Ӌ", "ӌ", "Ӵ", "ӵ", "Џ", "џ", "Ш", "ш", "Щ", "щ", "Ъ", "ъ", "Ы", "ы", "Ӹ", "ӹ", "Ь", "ь", "Ҍ", "ҍ", "Э", "э", "Ӭ", "ӭ", "Ю", "ю", "Я", "я", "Ԝ", "ԝ", "Ѡ", "ѡ", "Ѣ", "ѣ", "Ѥ", "ѥ", "Ѧ", "ѧ", "Ѩ", "ѩ", "Ѫ", "ѫ", "Ѭ", "ѭ", "Ѯ", "ѯ", "Ѱ", "ѱ", "Ѳ", "ѳ", "Ѵ", "ѵ", "Ѷ", "ѷ", "Ѹ", "ѹ", "Ѻ", "ѻ", "Ѽ", "ѽ", "Ѿ", "ѿ", "Ҁ", "ҁ"
+ ],
+ "arabic": [
+ "ا", "ب", "ت", "ث", "ج", "ح", "خ", "د", "ذ", "ر", "ز", "س", "ش", "ص", "ض", "ط", "ظ", "ع", "غ", "ف", "ق", "ك", "ل", "م", "ن", "ه", "و", "ي", "ء", "آ", "أ", "إ", "ٱ", "ؤ", "ئ", "ى", "ة", "َ", "ُ", "ِ", "ً", "ٌ", "ٍ", "ّ", "ْ", "ٰ", "،", "؛", "؟", "ـ", "٠", "١", "٢", "٣", "٤", "٥", "٦", "٧", "٨", "٩", "٪", "٫", "٬", "٭",
+ [
+ "zwnj",
+ "‌"
+ ],
+ [
+ "zwj",
+ "‍"
+ ]
+ ],
+ "arabicextended": [
+ "ٲ", "ٳ", "ٴ", "ٵ", "ݳ", "ݴ", "ٮ", "ٻ", "پ", "ڀ", "ݐ", "ݑ", "ݒ", "ݓ", "ݔ", "ݕ", "ݖ", "ٹ", "ٺ", "ټ", "ٽ", "ٿ", "ځ", "ڂ", "ڃ", "ڄ", "څ", "چ", "ڇ", "ڿ", "ݗ", "ݘ", "ݮ", "ݯ", "ݲ", "ݼ", "ڈ", "ډ", "ڊ", "ڋ", "ڌ", "ڍ", "ڎ", "ڏ", "ڐ", "ۮ", "ݙ", "ݚ", "ڑ", "ڒ", "ړ", "ڔ", "ڕ", "ږ", "ڗ", "ژ", "ڙ", "ۯ", "ݛ", "ݫ", "ݬ", "ݱ", "ښ", "ڛ", "ڜ", "ݽ", "ۺ", "ݜ", "ݭ", "ݰ", "ݾ", "ڝ", "ڞ", "ۻ", "ڟ", "ڠ", "ݝ", "ݞ", "ݟ", "ۼ", "ڡ", "ڢ", "ڣ", "ڤ", "ڥ", "ڦ", "ݠ", "ݡ", "ٯ", "ڧ", "ڨ", "ػ", "ؼ", "ک", "ڪ", "ګ", "ڬ", "ڭ", "ڮ", "گ", "ڰ", "ڱ", "ڲ", "ڳ", "ڴ", "ݢ", "ݣ", "ݤ", "ݿ", "ڵ", "ڶ", "ڷ", "ڸ", "ݪ", "ݥ", "ݦ", "ڹ", "ں", "ڻ", "ڼ", "ڽ", "ݧ", "ݨ", "ݩ", "ھ", "ۀ", "ہ", "ۂ", "ۃ", "ە", "ۿ", "ٶ", "ٷ", "ۄ", "ۅ", "ۆ", "ۇ", "ۈ", "ۉ", "ۊ", "ۋ", "ۏ", "ݸ", "ݹ", "ؠ", "ؽ", "ؾ", "ؿ", "ٸ", "ی", "ۍ", "ێ", "ې", "ۑ", "ے", "ۓ", "ݵ", "ݶ", "ݷ", "ݺ", "ݻ", "ٖ", "ٗ", "٘", "ٙ", "ٚ", "ٛ", "ٜ", "ٝ", "ٞ", "ٟ", "۔", "۽", "۾", "۰", "۱", "۲", "۳", "۴", "۵", "۶", "۷", "۸", "۹"
+ ],
+ "hebrew": [
+ "א", "ב", "ג", "ד", "ה", "ו", "ז", "ח", "ט", "י", "כ", "ך", "ל", "מ", "ם", "נ", "ן", "ס", "ע", "פ", "ף", "צ", "ץ", "ק", "ר", "ש", "ת", "װ", "ױ", "ײ", "׳", "״", "־", "–",
+ {
+ "label": "„”",
+ "action": {
+ "type": "encapsulate",
+ "options": {
+ "pre": "„",
+ "post": "”"
+ }
+ }
+ },
+ {
+ "label": "‚’",
+ "action": {
+ "type": "encapsulate",
+ "options": {
+ "pre": "‚",
+ "post": "’"
+ }
+ }
+ },
+ [
+ "◌ְ",
+ "ְ"
+ ],
+ [
+ "◌ֱ",
+ "ֱ"
+ ],
+ [
+ "◌ֲ",
+ "ֲ"
+ ],
+ [
+ "◌ֳ",
+ "ֳ"
+ ],
+ [
+ "◌ִ",
+ "ִ"
+ ],
+ [
+ "◌ֵ",
+ "ֵ"
+ ],
+ [
+ "◌ֶ",
+ "ֶ"
+ ],
+ [
+ "◌ַ",
+ "ַ"
+ ],
+ [
+ "◌ָ",
+ "ָ"
+ ],
+ [
+ "◌ֹ",
+ "ֹ"
+ ],
+ [
+ "◌ֻ",
+ "ֻ"
+ ],
+ [
+ "◌ּ",
+ "ּ"
+ ],
+ [
+ "◌ׁ",
+ "ׁ"
+ ],
+ [
+ "◌ׂ",
+ "ׂ"
+ ],
+ [
+ "◌ׇ",
+ "ׇ"
+ ],
+ [
+ "◌֑",
+ "֑"
+ ],
+ [
+ "◌֒",
+ "֒"
+ ],
+ [
+ "◌֓",
+ "֓"
+ ],
+ [
+ "◌֔",
+ "֔"
+ ],
+ [
+ "◌֕",
+ "֕"
+ ],
+ [
+ "◌֖",
+ "֖"
+ ],
+ [
+ "◌֗",
+ "֗"
+ ],
+ [
+ "◌֘",
+ "֘"
+ ],
+ [
+ "◌֙",
+ "֙"
+ ],
+ [
+ "◌֚",
+ "֚"
+ ],
+ [
+ "◌֛",
+ "֛"
+ ],
+ [
+ "◌֜",
+ "֜"
+ ],
+ [
+ "◌֝",
+ "֝"
+ ],
+ [
+ "◌֞",
+ "֞"
+ ],
+ [
+ "◌֟",
+ "֟"
+ ],
+ [
+ "◌֠",
+ "֠"
+ ],
+ [
+ "◌֡",
+ "֡"
+ ],
+ [
+ "◌֢",
+ "֢"
+ ],
+ [
+ "◌֣",
+ "֣"
+ ],
+ [
+ "◌֤",
+ "֤"
+ ],
+ [
+ "◌֥",
+ "֥"
+ ],
+ [
+ "◌֦",
+ "֦"
+ ],
+ [
+ "◌֧",
+ "֧"
+ ],
+ [
+ "◌֨",
+ "֨"
+ ],
+ [
+ "◌֩",
+ "֩"
+ ],
+ [
+ "◌֪",
+ "֪"
+ ],
+ [
+ "◌֫",
+ "֫"
+ ],
+ [
+ "◌֬",
+ "֬"
+ ],
+ [
+ "◌֭",
+ "֭"
+ ],
+ [
+ "◌֮",
+ "֮"
+ ],
+ [
+ "◌֯",
+ "֯"
+ ],
+ [
+ "◌ֿ",
+ "ֿ"
+ ],
+ [
+ "◌׀",
+ "׀"
+ ],
+ [
+ "◌׃",
+ "׃"
+ ]
+ ],
+ "bangla": [
+ "ঀ", "অ", "আ", "ই", "ঈ", "উ", "ঊ", "ঋ", "ঌ", "এ", "ঐ", "ও", "ঔ", "া", "ি", "ী", "ু", "ূ", "ৃ", "ে", "ৈ", "ো", "ৌ", "্য", "্র", "ক", "খ", "গ", "ঘ", "ঙ", "চ", "ছ", "জ", "ঝ", "ঞ", "ট", "ঠ", "ড", "ঢ", "ণ", "ত", "থ", "দ", "ধ", "ন", "প", "ফ", "ব", "ভ", "ম", "য", "র", "ল", "শ", "ষ", "স", "হ", "ড়", "ঢ়", "য়", "ৎ", "ং", "ঃ", "ঁ", "্", "৷", "॥", "১", "২", "৩", "৪", "৫", "৬", "৭", "৮", "৯", "০", "ঽ", "ৗ", "়", "ৰ", "ৱ", "৲", "৻", "৳", "৴", "৵", "৶", "৷", "৸", "৹", "৺", "ৠ", "ৡ", "ৄ", "ৢ", "ৣ", "‘", "’", "“", "”",
+ [
+ "zws",
+ "​"
+ ],
+ [
+ "zwnj",
+ "‌"
+ ],
+ [
+ "zwj",
+ "‍"
+ ]
+ ],
+ "tamil": [
+ "௦", "௧", "௨", "௩", "௪", "௫", "௬", "௭", "௮", "௯", "௰", "௱", "௲", "௳", "௴", "௵", "௶", "௷", "௸", "௹", "௺", "ௐ"
+ ],
+ "telugu": [
+ "ఁ", "ం", "ః", "అ", "ఆ", "ఇ", "ఈ", "ఉ", "ఊ", "ఋ", "ౠ", "ఌ", "ౡ", "ఎ", "ఏ", "ఐ", "ఒ", "ఓ", "ఔ", "క", "ఖ", "గ", "ఘ", "ఙ", "చ", "ఛ", "జ", "ఝ", "ఞ", "ట", "ఠ", "డ", "ఢ", "ణ", "త", "థ", "ద", "ధ", "న", "ప", "ఫ", "బ", "భ", "మ", "య", "ర", "ఱ", "ల", "ళ", "వ", "శ", "ష", "స", "హ", "ా", "ి", "ీ", "ు", "ూ", "ృ", "ౄ", "ె", "ే", "ై", "ొ", "ో", "ౌ", "్", "ౢ", "ౣ", "ౘ", "ౙ", "౦", "౧", "౨", "౩", "౪", "౫", "౬", "౭", "౮", "౯", "ఽ", "౸", "౹", "౺", "౻", "౼", "౽", "౾", "౿"
+ ],
+ "sinhala": [
+ "අ", "ආ", "ඇ", "ඈ", "ඉ", "ඊ", "උ", "ඌ", "ඍ", "ඎ", "ඏ", "ඐ", "එ", "ඒ", "ඓ", "ඔ", "ඕ", "ඖ", "ක", "ඛ", "ග", "ඝ", "ඞ", "ඟ", "ච", "ඡ", "ජ", "ඣ", "ඤ", "ඥ", "ඦ", "ට", "ඨ", "ඩ", "ඪ", "ණ", "ඬ", "ත", "ථ", "ද", "ධ", "න", "ඳ", "ප", "ඵ", "බ", "භ", "ම", "ඹ", "ය", "ර", "ල", "ව", "ශ", "ෂ", "ස", "හ", "ළ", "ෆ",
+ [
+ "◌ා",
+ "ා"
+ ],
+ [
+ "◌ැ",
+ "ැ"
+ ],
+ [
+ "◌ෑ",
+ "ෑ"
+ ],
+ [
+ "◌ි",
+ "ි"
+ ],
+ [
+ "◌ී",
+ "ී"
+ ],
+ [
+ "◌ු",
+ "ු"
+ ],
+ [
+ "◌ූ",
+ "ූ"
+ ],
+ [
+ "◌ෘ",
+ "ෘ"
+ ],
+ [
+ "◌ෲ",
+ "ෲ"
+ ],
+ [
+ "◌ෟ",
+ "ෟ"
+ ],
+ [
+ "◌ෳ",
+ "ෳ"
+ ],
+ [
+ "◌ෙ",
+ "ෙ"
+ ],
+ [
+ "◌ේ",
+ "ේ"
+ ],
+ [
+ "◌ො",
+ "ො"
+ ],
+ [
+ "◌ෝ",
+ "ෝ"
+ ],
+ [
+ "◌ෞ",
+ "ෞ"
+ ],
+ [
+ "◌්",
+ "්"
+ ]
+ ],
+ "devanagari": [
+ "ऀ", "ँ", "ं", "ः", "ऄ", "अ", "आ", "इ", "ई", "उ", "ऊ", "ऋ", "ऌ", "ऍ", "ऎ", "ए", "ऐ", "ऑ", "ऒ", "ओ", "औ", "क", "ख", "ग", "घ", "ङ", "च", "छ", "ज", "झ", "ञ", "ट", "ठ", "ड", "ढ", "ण", "त", "थ", "द", "ध", "न", "ऩ", "प", "फ", "ब", "भ", "म", "य", "र", "ऱ", "ल", "ळ", "ऴ", "व", "श", "ष", "स", "ह", "ऺ", "ऻ", "़", "ऽ", "ा", "ि", "ी", "ु", "ू", "ृ", "ॄ", "ॅ", "ॆ", "े", "ै", "ॉ", "ॊ", "ो", "ौ", "्", "ॎ", "ॏ", "ॐ", "॑", "॒", "॓", "॔", "ॕ", "ॖ", "ॗ", "क़", "ख़", "ग़", "ज़", "ड़", "ढ़", "फ़", "य़", "ॠ", "ॡ", "ॢ", "ॣ", "।", "॥", "०", "१", "२", "३", "४", "५", "६", "७", "८", "९", "॰", "ॱ", "ॲ", "ॳ", "ॴ", "ॵ", "ॶ", "ॷ", "ॹ", "ॺ", "ॻ", "ॼ", "ॽ", "ॾ", "ॿ"
+ ],
+ "gujarati": [
+ "ૐ", "ઁ", "ં", "ઃ", "અ", "આ", "ઇ", "ઈ", "ઉ", "ઊ", "એ", "ઐ", "ઓ", "ઔ", "અં", "ઋ", "ઍ", "ઑ", "ઌ", "ૠ", "ૡ", "ક", "ખ", "ગ", "ઘ", "ઙ", "ચ", "છ", "જ", "ઝ", "ઞ", "ટ", "ઠ", "ડ", "ઢ", "ણ", "ત", "થ", "દ", "ધ", "ન", "પ", "ફ", "બ", "ભ", "મ", "ય", "ર", "લ", "ળ", "વ", "શ", "ષ", "સ", "હ", "ક્ષ", "જ્ઞ", "ઽ", "ા", "િ", "ી", "ી", "ુ", "ૂ", "ૃ", "ૄ", "ૅ", "ે", "ૈ", "ૉ", "ો", "ૌ", "ૢ", "ૣ", "્", "૦", "૧", "૨", "૩", "૪", "૫", "૬", "૭", "૮", "૯", "૱"
+ ],
+ "thai": [
+ "ก", "ข", "ฃ", "ค", "ฅ", "ฆ", "ง", "จ", "ฉ", "ช", "ซ", "ฌ", "ญ", "ฎ", "ฏ", "ฐ", "ฑ", "ฒ", "ณ", "ด", "ต", "ถ", "ท", "ธ", "น", "บ", "ป", "ผ", "ฝ", "พ", "ฟ", "ภ", "ม", "ย", "ร", "ฤ", "ล", "ฦ", "ว", "ศ", "ษ", "ส", "ห", "ฬ", "อ", "ฮ", "ะ", "ั", "า", "ๅ", "ำ", "ิ", "ี", "ึ", "ื", "ุ", "ู", "เ", "แ", "โ", "ใ", "ไ", "็", "่", "้", "๊", "๋", "์", "ํ", "ฺ", "๎", "๐", "๑", "๒", "๓", "๔", "๕", "๖", "๗", "๘", "๙", "฿", "ๆ", "ฯ", "๚", "๏", "๛"
+ ],
+ "lao": [
+ "ກ", "ຂ", "ຄ", "ງ", "ຈ", "ສ", "ຊ", "ຍ", "ດ", "ຕ", "ຖ", "ທ", "ນ", "ບ", "ປ", "ຜ", "ຝ", "ພ", "ຟ", "ມ", "ຢ", "ລ", "ວ", "ຫ", "ອ", "ຮ", "ຣ", "ໜ", "ໝ", "ຼ", "ຽ", "ະ", "ັ", "າ", "ຳ", "ິ", "ີ", "ຶ", "ື", "ຸ", "ູ", "ົ", "ເ", "ແ", "ໂ", "ໃ", "ໄ", "່", "້", "໊", "໋", "໌", "ໍ", "໐", "໑", "໒", "໓", "໔", "໕", "໖", "໗", "໘", "໙", "₭", "ໆ", "ຯ"
+ ],
+ "khmer": [
+ "ក", "ខ", "គ", "ឃ", "ង", "ច", "ឆ", "ជ", "ឈ", "ញ", "ដ", "ឋ", "ឌ", "ឍ", "ណ", "ត", "ថ", "ទ", "ធ", "ន", "ប", "ផ", "ព", "ភ", "ម", "យ", "រ", "ល", "វ", "ស", "ហ", "ឡ", "អ", "ឣ", "ឤ", "ឥ", "ឦ", "ឧ", "ឨ", "ឩ", "ឪ", "ឫ", "ឬ", "ឭ", "ឮ", "ឯ", "ឰ", "ឱ", "ឲ", "ឳ", "្", "឴", "឵", "ា", "ិ", "ី", "ឹ", "ឺ", "ុ", "ូ", "ួ", "ើ", "ឿ", "ៀ", "េ", "ែ", "ៃ", "ោ", "ៅ", "ំ", "ះ", "ៈ", "៉", "៊", "់", "៌", "៍", "៎", "៏", "័", "៑", "៓", "៝", "ៜ", "០", "១", "២", "៣", "៤", "៥", "៦", "៧", "៨", "៩", "៛", "។", "៕", "៖", "ៗ", "៘", "៙", "៚", "៰", "៱", "៲", "៳", "៴", "៵", "៶", "៷", "៸", "៹", "᧠", "᧡", "᧢", "᧣", "᧤", "᧥", "᧦", "᧧", "᧨", "᧩", "᧪", "᧫", "᧬", "᧭", "᧮", "᧯", "᧰", "᧱", "᧲", "᧳", "᧴", "᧵", "᧶", "᧷", "᧸", "᧹", "᧺", "᧻", "᧼", "᧽", "᧾", "᧿"
+ ],
+ "canadianaboriginal": [
+ "ᐁ", "ᐂ", "ᐃ", "ᐄ", "ᐅ", "ᐆ", "ᐇ", "ᐈ", "ᐉ", "ᐊ", "ᐋ", "ᐌ", "ᐍ", "ᐎ", "ᐏ", "ᐐ",
+ "ᐑ", "ᐒ", "ᐓ", "ᐔ", "ᐕ", "ᐖ", "ᐗ", "ᐘ", "ᐙ", "ᐚ", "ᐛ", "ᐜ", "ᐝ", "ᐞ", "ᐟ", "ᐠ",
+ "ᐡ", "ᐢ", "ᐣ", "ᐤ", "ᐥ", "ᐦ", "ᐧ", "ᐨ", "ᐩ", "ᐪ", "ᐫ", "ᐬ", "ᐭ", "ᐮ", "ᐯ", "ᐰ",
+ "ᐱ", "ᐲ", "ᐳ", "ᐴ", "ᐵ", "ᐶ", "ᐷ", "ᐸ", "ᐹ", "ᐺ", "ᐻ", "ᐼ", "ᐽ", "ᐾ", "ᐿ", "ᑀ",
+ "ᑁ", "ᑂ", "ᑃ", "ᑄ", "ᑅ", "ᑆ", "ᑇ", "ᑈ", "ᑉ", "ᑊ", "ᑋ", "ᑌ", "ᑍ", "ᑎ", "ᑏ", "ᑐ",
+ "ᑑ", "ᑒ", "ᑓ", "ᑔ", "ᑕ", "ᑖ", "ᑗ", "ᑘ", "ᑙ", "ᑚ", "ᑛ", "ᑜ", "ᑝ", "ᑞ", "ᑟ", "ᑠ",
+ "ᑡ", "ᑢ", "ᑣ", "ᑤ", "ᑥ", "ᑦ", "ᑧ", "ᑨ", "ᑩ", "ᑪ", "ᑫ", "ᑬ", "ᑭ", "ᑮ", "ᑯ", "ᑰ",
+ "ᑱ", "ᑲ", "ᑳ", "ᑴ", "ᑵ", "ᑶ", "ᑷ", "ᑸ", "ᑹ", "ᑺ", "ᑻ", "ᑼ", "ᑽ", "ᑾ", "ᑿ", "ᒀ",
+ "ᒁ", "ᒂ", "ᒃ", "ᒄ", "ᒅ", "ᒆ", "ᒇ", "ᒈ", "ᒉ", "ᒊ", "ᒋ", "ᒌ", "ᒍ", "ᒎ", "ᒏ", "ᒐ",
+ "ᒑ", "ᒒ", "ᒓ", "ᒔ", "ᒕ", "ᒖ", "ᒗ", "ᒘ", "ᒙ", "ᒚ", "ᒛ", "ᒜ", "ᒝ", "ᒞ", "ᒟ", "ᒠ",
+ "ᒡ", "ᒢ", "ᒣ", "ᒤ", "ᒥ", "ᒦ", "ᒧ", "ᒨ", "ᒩ", "ᒪ", "ᒫ", "ᒬ", "ᒭ", "ᒮ", "ᒯ", "ᒰ",
+ "ᒱ", "ᒲ", "ᒳ", "ᒴ", "ᒵ", "ᒶ", "ᒷ", "ᒸ", "ᒹ", "ᒺ", "ᒻ", "ᒼ", "ᒽ", "ᒾ", "ᒿ", "ᓀ",
+ "ᓁ", "ᓂ", "ᓃ", "ᓄ", "ᓅ", "ᓆ", "ᓇ", "ᓈ", "ᓉ", "ᓊ", "ᓋ", "ᓌ", "ᓍ", "ᓎ", "ᓏ", "ᓐ",
+ "ᓑ", "ᓒ", "ᓓ", "ᓔ", "ᓕ", "ᓖ", "ᓗ", "ᓘ", "ᓙ", "ᓚ", "ᓛ", "ᓜ", "ᓝ", "ᓞ", "ᓟ", "ᓠ",
+ "ᓡ", "ᓢ", "ᓣ", "ᓤ", "ᓥ", "ᓦ", "ᓧ", "ᓨ", "ᓩ", "ᓪ", "ᓫ", "ᓬ", "ᓭ", "ᓮ", "ᓯ", "ᓰ",
+ "ᓱ", "ᓲ", "ᓳ", "ᓴ", "ᓵ", "ᓶ", "ᓷ", "ᓸ", "ᓹ", "ᓺ", "ᓻ", "ᓼ", "ᓽ", "ᓾ", "ᓿ", "ᔀ",
+ "ᔁ", "ᔂ", "ᔃ", "ᔄ", "ᔅ", "ᔆ", "ᔇ", "ᔈ", "ᔉ", "ᔊ", "ᔋ", "ᔌ", "ᔍ", "ᔎ", "ᔏ", "ᔐ",
+ "ᔑ", "ᔒ", "ᔓ", "ᔔ", "ᔕ", "ᔖ", "ᔗ", "ᔘ", "ᔙ", "ᔚ", "ᔛ", "ᔜ", "ᔝ", "ᔞ", "ᔟ", "ᔠ",
+ "ᔡ", "ᔢ", "ᔣ", "ᔤ", "ᔥ", "ᔦ", "ᔧ", "ᔨ", "ᔩ", "ᔪ", "ᔫ", "ᔬ", "ᔭ", "ᔮ", "ᔯ", "ᔰ",
+ "ᔱ", "ᔲ", "ᔳ", "ᔴ", "ᔵ", "ᔶ", "ᔷ", "ᔸ", "ᔹ", "ᔺ", "ᔻ", "ᔼ", "ᔽ", "ᔾ", "ᔿ", "ᕀ",
+ "ᕁ", "ᕂ", "ᕃ", "ᕄ", "ᕅ", "ᕆ", "ᕇ", "ᕈ", "ᕉ", "ᕊ", "ᕋ", "ᕌ", "ᕍ", "ᕎ", "ᕏ", "ᕐ",
+ "ᕑ", "ᕒ", "ᕓ", "ᕔ", "ᕕ", "ᕖ", "ᕗ", "ᕘ", "ᕙ", "ᕚ", "ᕛ", "ᕜ", "ᕝ", "ᕞ", "ᕟ", "ᕠ",
+ "ᕡ", "ᕢ", "ᕣ", "ᕤ", "ᕥ", "ᕦ", "ᕧ", "ᕨ", "ᕩ", "ᕪ", "ᕫ", "ᕬ", "ᕭ", "ᕮ", "ᕯ", "ᕰ",
+ "ᕱ", "ᕲ", "ᕳ", "ᕴ", "ᕵ", "ᕶ", "ᕷ", "ᕸ", "ᕹ", "ᕺ", "ᕻ", "ᕼ", "ᕽ", "ᕾ", "ᕿ", "ᖀ",
+ "ᖁ", "ᖂ", "ᖃ", "ᖄ", "ᖅ", "ᖆ", "ᖇ", "ᖈ", "ᖉ", "ᖊ", "ᖋ", "ᖌ", "ᖍ", "ᖎ", "ᖏ", "ᖐ",
+ "ᖑ", "ᖒ", "ᖓ", "ᖔ", "ᖕ", "ᖖ", "ᖗ", "ᖘ", "ᖙ", "ᖚ", "ᖛ", "ᖜ", "ᖝ", "ᖞ", "ᖟ", "ᖠ",
+ "ᖡ", "ᖢ", "ᖣ", "ᖤ", "ᖥ", "ᖦ", "ᖧ", "ᖨ", "ᖩ", "ᖪ", "ᖫ", "ᖬ", "ᖭ", "ᖮ", "ᖯ", "ᖰ",
+ "ᖱ", "ᖲ", "ᖳ", "ᖴ", "ᖵ", "ᖶ", "ᖷ", "ᖸ", "ᖹ", "ᖺ", "ᖻ", "ᖼ", "ᖽ", "ᖾ", "ᖿ", "ᗀ",
+ "ᗁ", "ᗂ", "ᗃ", "ᗄ", "ᗅ", "ᗆ", "ᗇ", "ᗈ", "ᗉ", "ᗊ", "ᗋ", "ᗌ", "ᗍ", "ᗎ", "ᗏ", "ᗐ",
+ "ᗑ", "ᗒ", "ᗓ", "ᗔ", "ᗕ", "ᗖ", "ᗗ", "ᗘ", "ᗙ", "ᗚ", "ᗛ", "ᗜ", "ᗝ", "ᗞ", "ᗟ", "ᗠ",
+ "ᗡ", "ᗢ", "ᗣ", "ᗤ", "ᗥ", "ᗦ", "ᗧ", "ᗨ", "ᗩ", "ᗪ", "ᗫ", "ᗬ", "ᗭ", "ᗮ", "ᗯ", "ᗰ",
+ "ᗱ", "ᗲ", "ᗳ", "ᗴ", "ᗵ", "ᗶ", "ᗷ", "ᗸ", "ᗹ", "ᗺ", "ᗻ", "ᗼ", "ᗽ", "ᗾ", "ᗿ", "ᘀ",
+ "ᘁ", "ᘂ", "ᘃ", "ᘄ", "ᘅ", "ᘆ", "ᘇ", "ᘈ", "ᘉ", "ᘊ", "ᘋ", "ᘌ", "ᘍ", "ᘎ", "ᘏ", "ᘐ",
+ "ᘑ", "ᘒ", "ᘓ", "ᘔ", "ᘕ", "ᘖ", "ᘗ", "ᘘ", "ᘙ", "ᘚ", "ᘛ", "ᘜ", "ᘝ", "ᘞ", "ᘟ", "ᘠ",
+ "ᘡ", "ᘢ", "ᘣ", "ᘤ", "ᘥ", "ᘦ", "ᘧ", "ᘨ", "ᘩ", "ᘪ", "ᘫ", "ᘬ", "ᘭ", "ᘮ", "ᘯ", "ᘰ",
+ "ᘱ", "ᘲ", "ᘳ", "ᘴ", "ᘵ", "ᘶ", "ᘷ", "ᘸ", "ᘹ", "ᘺ", "ᘻ", "ᘼ", "ᘽ", "ᘾ", "ᘿ", "ᙀ",
+ "ᙁ", "ᙂ", "ᙃ", "ᙄ", "ᙅ", "ᙆ", "ᙇ", "ᙈ", "ᙉ", "ᙊ", "ᙋ", "ᙌ", "ᙍ", "ᙎ", "ᙏ", "ᙐ",
+ "ᙑ", "ᙒ", "ᙓ", "ᙔ", "ᙕ", "ᙖ", "ᙗ", "ᙘ", "ᙙ", "ᙚ", "ᙛ", "ᙜ", "ᙝ", "ᙞ", "ᙟ", "ᙠ",
+ "ᙡ", "ᙢ", "ᙣ", "ᙤ", "ᙥ", "ᙦ", "ᙧ", "ᙨ", "ᙩ", "ᙪ", "ᙫ", "ᙬ", "᙭", "᙮", "ᙯ", "ᙰ",
+ "ᙱ", "ᙲ", "ᙳ", "ᙴ", "ᙵ", "ᙶ"
+ ]
+}
diff --git a/www/wiki/resources/src/mediawiki.legacy/commonPrint.css b/www/wiki/resources/src/mediawiki.legacy/commonPrint.css
new file mode 100644
index 00000000..8ff06342
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/commonPrint.css
@@ -0,0 +1,373 @@
+/**
+ * MediaWiki print style sheet
+ * Largely based on work by Gabriel Wicke
+ *
+ * Originally derived from Plone (https://plone.org/) styles
+ * Copyright Alexander Limi
+ */
+
+/**
+ * Hide all the elements irrelevant for printing
+ * Skins however can and should override.
+ */
+/* General hide-in-print class, please only use sparely */
+.noprint,
+/* Various content classes, in alphabetical order */
+.catlinks,
+.magnify,
+.mw-cite-backlink,
+.mw-jump,
+.mw-editsection,
+.mw-editsection-like,
+.mw-hidden-catlinks,
+.mw-indicators,
+.mw-redirectedfrom,
+.patrollink,
+.usermessage,
+/* Various content ids, in alphabetical order */
+#column-one,
+#footer-places,
+#jump-to-nav,
+#mw-navigation,
+#siteNotice,
+/* Deprecated, changed in core */
+#f-poweredbyico,
+#f-copyrightico,
+li#about,
+li#disclaimer,
+li#mobileview,
+li#privacy {
+ display: none;
+}
+
+/**
+ * Generic HTML elements
+ */
+body {
+ background: #fff;
+ color: #000;
+ margin: 0;
+ padding: 0;
+}
+
+/* Links */
+a {
+ background: none !important; /* stylelint-disable-line declaration-no-important */
+ padding: 0 !important; /* stylelint-disable-line declaration-no-important */
+}
+
+a,
+a.external,
+a.new,
+a.stub {
+ /* IE 6 & 7 don't understand `inherit` */
+ color: #000 !important; /* stylelint-disable-line declaration-no-important */
+ text-decoration: none !important; /* stylelint-disable-line declaration-no-important */
+ /* Modern browser will apply this, IE 6 & 7 ignore the unknown */
+ color: inherit !important; /* stylelint-disable-line declaration-block-no-duplicate-properties, declaration-no-important */
+ text-decoration: inherit !important; /* stylelint-disable-line declaration-block-no-duplicate-properties, declaration-no-important */
+}
+
+/* Expand URLs for printing */
+.mw-body-content a.external.text:after,
+.mw-body-content a.external.autonumber:after {
+ content: ' (' attr( href ) ')';
+ word-break: break-all;
+ word-wrap: break-word;
+}
+
+/* Expand protocol-relative URLs for printing */
+.mw-body-content a.external.text[href^='//']:after,
+.mw-body-content a.external.autonumber[href^='//']:after {
+ content: ' (https:' attr( href ) ')';
+}
+
+dt {
+ font-weight: bold;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-weight: bold;
+ /* Pagination */
+ page-break-after: avoid;
+ page-break-before: avoid;
+}
+
+p {
+ margin: 1em 0;
+ line-height: 1.2;
+ /* Pagination */
+ orphans: 3;
+ widows: 3;
+}
+
+img,
+figure,
+.wikitable,
+.thumb {
+ /* Pagination */
+ page-break-inside: avoid;
+}
+
+img {
+ border: 0;
+ vertical-align: middle;
+}
+
+pre,
+.mw-code {
+ background: #fff;
+ color: #000;
+ border: 1pt dashed #000;
+ padding: 1em 0;
+ font-size: 8pt;
+ white-space: pre;
+ word-wrap: break-word;
+ overflow: auto;
+}
+
+/* Prevent citations and subscripts from interfering with the line-height */
+sup,
+sub {
+ line-height: 1;
+}
+
+ul {
+ list-style-type: square;
+}
+
+/**
+ * MediaWiki-specific elements
+ */
+#globalWrapper {
+ width: 100% !important; /* stylelint-disable-line declaration-no-important */
+ min-width: 0 !important; /* stylelint-disable-line declaration-no-important */
+}
+
+.mw-body {
+ background: #fff;
+ color: #000;
+ border: 0 !important; /* stylelint-disable-line declaration-no-important */
+ padding: 0 !important; /* stylelint-disable-line declaration-no-important */
+ margin: 0 !important; /* stylelint-disable-line declaration-no-important */
+ direction: ltr;
+}
+
+#column-content {
+ margin: 0 !important; /* stylelint-disable-line declaration-no-important */
+}
+
+#column-content .mw-body {
+ padding: 1em;
+ margin: 0 !important; /* stylelint-disable-line declaration-no-important */
+}
+
+#toc,
+.toc {
+ background-color: #f9f9f9;
+ border: 1pt solid #aaa;
+ padding: 5px;
+ display: table;
+}
+
+/* Separate columns for `.tocnumber` and `.toctext` */
+.tocnumber,
+.toctext {
+ display: table-cell;
+}
+
+/* Space between those columns */
+.tocnumber {
+ padding-left: 0;
+ padding-right: 0.5em;
+}
+
+/* @noflip */
+.mw-content-ltr .tocnumber {
+ padding-left: 0;
+ padding-right: 0.5em;
+}
+
+/* @noflip */
+.mw-content-rtl .tocnumber {
+ padding-left: 0.5em;
+ padding-right: 0;
+}
+
+/**
+ * Floating divs (and thumbnails)
+ */
+/* @noflip */
+table.floatright,
+div.floatright,
+div.tright {
+ float: right;
+ clear: right;
+ position: relative;
+}
+
+/* @noflip */
+table.floatleft,
+div.floatleft,
+div.tleft {
+ float: left;
+ clear: left;
+ position: relative;
+}
+
+/* @noflip */
+div.tleft {
+ margin: 0.5em 1.4em 1.3em 0;
+}
+
+/* @noflip */
+div.tright {
+ margin: 0.5em 0 1.3em 1.4em;
+}
+
+/* @noflip */
+table.floatright,
+div.floatright {
+ margin: 0 0 0.5em 0.5em;
+ border: 0;
+}
+
+/* @noflip */
+table.floatleft,
+div.floatleft {
+ margin: 0 0.5em 0.5em 0;
+ border: 0;
+}
+
+div.floatleft p,
+div.floatright p {
+ font-style: italic;
+}
+
+.center {
+ text-align: center;
+}
+
+/**
+ * Thumbnails
+ */
+div.thumb {
+ background-color: transparent;
+ width: auto;
+}
+
+div.thumb a {
+ border-bottom: 0;
+}
+
+div.thumbinner {
+ background-color: #fff;
+ border: 0;
+ border-radius: 2px;
+ padding: 5px;
+ font-size: 10pt;
+ color: #666;
+ text-align: center;
+ /* new block formatting context,
+ * to clear background from floating content */
+ overflow: hidden;
+ min-width: 100px;
+}
+
+html .thumbcaption {
+ text-align: left;
+ line-height: 1.4;
+ padding: 3px;
+}
+
+img.thumbborder {
+ border: 1pt solid #ddd;
+}
+
+/**
+ * Table rendering
+ */
+/* Compare `table.wikitable` in shared.css */
+table.wikitable,
+.mw_metadata {
+ background: #fff;
+ margin: 1em 0;
+ border: 1pt solid #aaa;
+ border-collapse: collapse;
+ font-size: 10pt;
+}
+
+table.wikitable > caption,
+.mw_metadata caption {
+ padding: 5px;
+ font-size: 10pt;
+}
+
+table.wikitable > tr > th,
+table.wikitable > tr > td,
+table.wikitable > * > tr > th,
+table.wikitable > * > tr > td,
+.mw_metadata th,
+.mw_metadata td {
+ /* Important is required to override any inline styles provided by editors */
+ background: #fff !important; /* stylelint-disable-line declaration-no-important */
+ /* We need to also set color in case editors applied a light text color */
+ color: #000 !important; /* stylelint-disable-line declaration-no-important */
+ border: 1pt solid #aaa;
+ padding: 0.4em 0.6em;
+}
+
+table.wikitable > tr > th,
+table.wikitable > * > tr > th,
+.mw_metadata th {
+ text-align: center;
+}
+
+table.listing,
+table.listing td {
+ border: 1pt solid #000;
+ border-collapse: collapse;
+}
+
+/**
+ * Categories
+ */
+.catlinks ul {
+ display: inline;
+ padding: 0;
+ list-style: none none;
+}
+
+.catlinks li {
+ display: inline-block;
+ line-height: 1.15;
+ margin: 0.1em 0;
+ border-left: 1pt solid #aaa;
+ padding: 0 0.4em;
+}
+
+.catlinks li:first-child {
+ border-left: 0;
+ padding-left: 0.2em;
+}
+
+/**
+ * Footer
+ */
+.printfooter {
+ padding: 1em 0;
+}
+
+#footer {
+ background: #fff;
+ color: #000;
+ margin-top: 1em;
+ border-top: 1pt solid #aaa;
+ padding-top: 5px;
+ direction: ltr;
+}
diff --git a/www/wiki/resources/src/mediawiki.legacy/images/ajax-loader.gif b/www/wiki/resources/src/mediawiki.legacy/images/ajax-loader.gif
new file mode 100644
index 00000000..72203fdd
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/images/ajax-loader.gif
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.legacy/images/help-question-hover.gif b/www/wiki/resources/src/mediawiki.legacy/images/help-question-hover.gif
new file mode 100644
index 00000000..515138db
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/images/help-question-hover.gif
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.legacy/images/help-question.gif b/www/wiki/resources/src/mediawiki.legacy/images/help-question.gif
new file mode 100644
index 00000000..b4fc9c5b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/images/help-question.gif
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-ltr.png b/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-ltr.png
new file mode 100644
index 00000000..afad5c65
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-ltr.svg b/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-ltr.svg
new file mode 100644
index 00000000..4d3dcb65
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11 15" width="15" height="11">
+ <g id="magnify-clip" fill="#fff" stroke="#000">
+ <path id="bigbox" d="M1.509 1.865h10.99v7.919h-10.99z"/>
+ <path id="smallbox" d="M-1.499 6.868h5.943v4.904h-5.943z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-rtl.png b/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-rtl.png
new file mode 100644
index 00000000..4ccc9436
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-rtl.svg b/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-rtl.svg
new file mode 100644
index 00000000..582e4ae7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/images/magnify-clip-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11 15" width="15" height="11">
+ <g id="magnify-clip" fill="#fff" stroke="#000">
+ <path id="bigbox" d="M9.491 1.865h-10.99v7.919h10.99z"/>
+ <path id="smallbox" d="M12.499 6.868h-5.943v4.904h5.943z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.legacy/images/spinner.gif b/www/wiki/resources/src/mediawiki.legacy/images/spinner.gif
new file mode 100644
index 00000000..6146be4e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/images/spinner.gif
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.legacy/oldshared.css b/www/wiki/resources/src/mediawiki.legacy/oldshared.css
new file mode 100644
index 00000000..7b2d7110
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/oldshared.css
@@ -0,0 +1,462 @@
+/**
+ * oldshared.css
+ * This file contains CSS settings common to Wikistandard, Nostalgia and
+ * CologneBlue, the old pre-Monobook skins
+ */
+
+/* For clarity, explicitly state some recommendations from
+ * https://www.w3.org/TR/CSS21/sample.html to make sure the editsection links scale right
+ */
+
+h1 {
+ font-size: 2em;
+}
+
+h2 {
+ font-size: 1.5em;
+}
+
+h3 {
+ font-size: 1.17em;
+}
+
+h4 {
+ font-size: 1.11em;
+}
+
+h5 {
+ font-size: 1.05em;
+}
+
+h6 {
+ font-size: 1em;
+}
+
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ font-weight: bolder;
+}
+
+/* Now the custom parts */
+
+#footer {
+ clear: both;
+}
+
+/* images */
+/* @noflip */
+div.floatright {
+ float: right;
+ clear: right;
+ margin: 0 0 1em 1em;
+}
+
+/* @noflip */
+div.floatright p {
+ font-style: italic;
+}
+
+/* @noflip */
+div.floatleft {
+ float: left;
+ clear: left;
+ margin: 0.3em 0.5em 0.5em 0;
+}
+
+/* @noflip */
+div.floatleft p {
+ font-style: italic;
+}
+
+/* table standards */
+table.rimage {
+ float: right;
+ margin-left: 1em;
+ margin-bottom: 1em;
+ text-align: center;
+ font-size: smaller;
+}
+
+/* thumbnails */
+div.thumb {
+ margin-bottom: 0.5em;
+ border-style: solid;
+ border-color: #fff;
+ width: auto;
+}
+
+div.thumbinner {
+ border: 1px solid #ccc;
+ padding: 3px;
+ background-color: #f9f9f9;
+ font-size: 94%;
+ text-align: center;
+ /* new block formatting context,
+ * to clear background from floating content */
+ overflow: hidden;
+}
+
+html .thumbimage {
+ border: 1px solid #ccc;
+}
+
+html .thumbcaption {
+ border: 0;
+ line-height: 1.4em;
+ padding: 3px;
+ font-size: 94%;
+ text-align: left;
+}
+
+div.magnify {
+ float: right;
+ margin-left: 3px;
+}
+
+div.magnify a {
+ display: block;
+ /* Hide the text… */
+ text-indent: 15px;
+ white-space: nowrap;
+ overflow: hidden;
+ /* …and replace it with the image */
+ width: 15px;
+ height: 11px;
+ /* Use same SVG support hack as mediawiki.legacy's shared.css */
+ background: url( images/magnify-clip-ltr.png ) center center no-repeat;
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/magnify-clip-ltr.svg );
+ /* Don't annoy people who copy-paste everything too much */
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+/* @noflip */
+div.tright {
+ clear: right;
+ float: right;
+ border-width: 0.5em 0 0.8em 1.4em;
+}
+
+/* @noflip */
+div.tleft {
+ float: left;
+ clear: left;
+ margin-right: 0.5em;
+ border-width: 0.5em 1.4em 0.8em 0;
+}
+
+img.thumbborder {
+ border: 1px solid #ddd;
+}
+
+/* Page history styling */
+/* the auto-generated edit comments */
+.autocomment {
+ color: #4b4b4b;
+}
+
+img {
+ border: 0;
+}
+
+#toc,
+.toc {
+ border: 1px solid #bba;
+ background-color: #f7f8ff;
+ padding: 7px;
+ font-size: 95%;
+ text-align: center;
+ display: inline-block;
+ display: table;
+
+ /* IE7 and earlier */
+ zoom: 1;
+ *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */
+}
+
+/* CSS for backwards-compatibility with cached page renders and creative uses in wikitext */
+table#toc,
+table.toc {
+ border-collapse: collapse;
+}
+
+/* Remove additional paddings inside table-cells that are not present in <div>s */
+table#toc td,
+table.toc td {
+ padding: 0;
+}
+
+#toc h2,
+.toc h2 {
+ display: inline;
+ border: 0;
+ padding: 0;
+ font-size: 100%;
+ font-weight: bold;
+}
+
+#toc ul,
+.toc ul {
+ list-style-type: none;
+ list-style-image: none;
+ padding: 0;
+ text-align: left;
+}
+
+#toc ul ul,
+.toc ul ul {
+ margin: 0 0 0 2em;
+}
+
+.error {
+ color: #f00;
+ font-size: larger;
+}
+
+/* preference page with js-genrated toc */
+#preftoc {
+ float: left;
+ margin: 1em 1em 1em 1em;
+ width: 13em;
+}
+
+#preftoc li {
+ border: 1px solid #fff;
+}
+
+#preftoc li.selected {
+ background-color: #f9f9f9;
+ border: 1px dashed #aaa;
+}
+
+#preftoc a,
+#preftoc a:active {
+ display: block;
+ color: #005189;
+}
+
+.mw-prefs-buttons {
+ clear: left;
+ float: left;
+ margin-top: 1em;
+}
+
+div.htmlform-tip {
+ font-size: 94%;
+ margin-top: 0.4em;
+ color: #666;
+}
+
+/* emulate center */
+.center {
+ width: 100%;
+ text-align: center;
+}
+
+*.center * {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+/* small for tables and similar */
+.small {
+ font-size: 94%;
+}
+
+table.small {
+ font-size: 100%;
+}
+
+/* use this instead of #toc for page content */
+.toccolours {
+ border: 1px solid #aaa;
+ background-color: #f9f9f9;
+ padding: 5px;
+ font-size: 95%;
+}
+
+#siteNotice {
+ border: 1px solid #aaa;
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+}
+
+.sharedUploadNotice {
+ font-style: italic;
+}
+
+span.unpatrolled {
+ font-weight: bold;
+ color: #f00;
+}
+
+div.gallerybox {
+ width: 150px;
+}
+
+span.comment {
+ font-style: italic;
+}
+
+.previewnote {
+ text-align: center;
+ color: #c00;
+}
+
+.editExternally {
+ border: 1px solid #808080;
+ background: #fff;
+ padding: 3px;
+ margin-top: 0.5em;
+ float: left;
+ font-size: small;
+ text-align: center;
+}
+
+.editExternallyHelp {
+ font-style: italic;
+ color: #808080;
+}
+
+li span.deleted {
+ text-decoration: line-through;
+ color: #888;
+ font-style: italic;
+}
+
+/* Classes for Exif data display */
+table.mw_metadata {
+ margin-left: 0.5em;
+ border: 0;
+ border-collapse: collapse;
+}
+
+table.mw_metadata caption {
+ font-weight: bold;
+}
+
+table.mw_metadata td,
+table.mw_metadata th {
+ border: 1px solid #aaa;
+ padding-left: 4px;
+ padding-right: 4px;
+}
+
+table.mw_metadata th {
+ background-color: #f9f9f9;
+ font-weight: normal;
+}
+
+table.mw_metadata td {
+ background-color: #fcfcfc;
+ padding-top: 0.1em;
+ padding-bottom: 0.1em;
+}
+
+table.mw_metadata td.spacer {
+ background: inherit;
+ border-width: 0 1px;
+}
+
+.visualClear {
+ clear: both;
+}
+
+/* Allmessages table */
+#allmessagestable th {
+ background-color: #b2b2ff;
+}
+
+#allmessagestable tr.orig {
+ background-color: #ffe2e2;
+}
+
+#allmessagestable tr.new {
+ background-color: #e2ffe2;
+}
+
+#allmessagestable tr.def {
+ background-color: #f0f0ff;
+}
+
+#jump-to-nav {
+ display: none;
+}
+
+div.multipageimagenavbox {
+ border: 1px solid #c0c0c0;
+ padding: 4px;
+ margin: 1em;
+ background: #f0f0f0;
+}
+
+div.multipageimagenavbox div.thumb {
+ border: 0;
+ margin-left: 2em;
+ margin-right: 2em;
+}
+
+div.multipageimagenavbox hr {
+ margin: 6px;
+}
+
+table.multipageimage td {
+ text-align: center;
+}
+
+.templatesUsed {
+ margin-top: 1em;
+}
+
+.MediaTransformError {
+ border: thin solid #777;
+ background-color: #ccc;
+ padding: 0.1em;
+}
+
+.MediaTransformError td {
+ text-align: center;
+ vertical-align: middle;
+ font-size: 90%;
+}
+
+form#specialpages {
+ display: inline;
+}
+
+body {
+ direction: ltr;
+ unicode-bidi: embed;
+ background-color: #ffffec;
+}
+
+body.ns-0 {
+ background-color: #fff;
+}
+
+/** RTL specific CSS starts here **/
+
+/**
+ * Lists:
+ * The following lines don't have a visible effect on non-Gecko browsers
+ * They fix a problem with Gecko browsers rendering lists to the right of
+ * left-floated objects in an RTL layout.
+ */
+/* @noflip */
+html > body.rtl div#article ul {
+ display: table;
+}
+
+/* @noflip */
+html > body.rtl .mw-body ul#filetoc {
+ display: block;
+}
+
+/** RTL specific CSS ends here **/
diff --git a/www/wiki/resources/src/mediawiki.legacy/protect.js b/www/wiki/resources/src/mediawiki.legacy/protect.js
new file mode 100644
index 00000000..aa49ae13
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/protect.js
@@ -0,0 +1,245 @@
+( function ( mw, $ ) {
+
+ var ProtectionForm = window.ProtectionForm = {
+ /**
+ * Set up the protection chaining interface (i.e. "unlock move permissions" checkbox)
+ * on the protection form
+ *
+ * @return {boolean}
+ */
+ init: function () {
+ var $cell = $( '<td>' ),
+ $row = $( '<tr>' ).append( $cell );
+
+ if ( !$( '#mwProtectSet' ).length ) {
+ return false;
+ }
+
+ if ( mw.config.get( 'wgCascadeableLevels' ) !== undefined ) {
+ $( 'form#mw-Protect-Form' ).submit( this.toggleUnchainedInputs.bind( ProtectionForm, true ) );
+ }
+ this.getExpirySelectors().each( function () {
+ $( this ).change( ProtectionForm.updateExpiryList.bind( ProtectionForm, this ) );
+ } );
+ this.getExpiryInputs().each( function () {
+ $( this ).on( 'keyup change', ProtectionForm.updateExpiry.bind( ProtectionForm, this ) );
+ } );
+ this.getLevelSelectors().each( function () {
+ $( this ).change( ProtectionForm.updateLevels.bind( ProtectionForm, this ) );
+ } );
+
+ $( '#mwProtectSet > tbody > tr:first' ).after( $row );
+
+ // If there is only one protection type, there is nothing to chain
+ if ( $( '[id ^= mw-protect-table-]' ).length > 1 ) {
+ $cell.append(
+ $( '<input>' )
+ .attr( { id: 'mwProtectUnchained', type: 'checkbox' } )
+ .click( this.onChainClick.bind( this ) )
+ .prop( 'checked', !this.areAllTypesMatching() ),
+ document.createTextNode( ' ' ),
+ $( '<label>' )
+ .attr( 'for', 'mwProtectUnchained' )
+ .text( mw.msg( 'protect-unchain-permissions' ) )
+ );
+
+ this.toggleUnchainedInputs( !this.areAllTypesMatching() );
+ }
+
+ $( '#mwProtect-reason' ).byteLimit( 180 );
+
+ this.updateCascadeCheckbox();
+ return true;
+ },
+
+ /**
+ * Sets the disabled attribute on the cascade checkbox depending on the current selected levels
+ */
+ updateCascadeCheckbox: function () {
+ this.getLevelSelectors().each( function () {
+ if ( !ProtectionForm.isCascadeableLevel( $( this ).val() ) ) {
+ $( '#mwProtect-cascade' ).prop( { checked: false, disabled: true } );
+ return false;
+ } else {
+ $( '#mwProtect-cascade' ).prop( 'disabled', false );
+ }
+ } );
+ },
+
+ /**
+ * Checks if a certain protection level is cascadeable.
+ *
+ * @param {string} level
+ * @return {boolean}
+ */
+ isCascadeableLevel: function ( level ) {
+ return $.inArray( level, mw.config.get( 'wgCascadeableLevels' ) ) !== -1;
+ },
+
+ /**
+ * When protection levels are locked together, update the rest
+ * when one action's level changes
+ *
+ * @param {Element} source Level selector that changed
+ */
+ updateLevels: function ( source ) {
+ if ( !this.isUnchained() ) {
+ this.setAllSelectors( source.selectedIndex );
+ }
+ this.updateCascadeCheckbox();
+ },
+
+ /**
+ * When protection levels are locked together, update the
+ * expiries when one changes
+ *
+ * @param {Element} source expiry input that changed
+ */
+
+ updateExpiry: function ( source ) {
+ if ( !this.isUnchained() ) {
+ this.getExpiryInputs().each( function () {
+ this.value = source.value;
+ } );
+ }
+ if ( this.isUnchained() ) {
+ $( '#' + source.id.replace( /^mwProtect-(\w+)-expires$/, 'mwProtectExpirySelection-$1' ) ).val( 'othertime' );
+ } else {
+ this.getExpirySelectors().each( function () {
+ this.value = 'othertime';
+ } );
+ }
+ },
+
+ /**
+ * When protection levels are locked together, update the
+ * expiry lists when one changes and clear the custom inputs
+ *
+ * @param {Element} source Expiry selector that changed
+ */
+ updateExpiryList: function ( source ) {
+ if ( !this.isUnchained() ) {
+ this.getExpirySelectors().each( function () {
+ this.value = source.value;
+ } );
+ this.getExpiryInputs().each( function () {
+ this.value = '';
+ } );
+ }
+ },
+
+ /**
+ * Update chain status and enable/disable various bits of the UI
+ * when the user changes the "unlock move permissions" checkbox
+ */
+ onChainClick: function () {
+ this.toggleUnchainedInputs( this.isUnchained() );
+ if ( !this.isUnchained() ) {
+ this.setAllSelectors( this.getMaxLevel() );
+ }
+ this.updateCascadeCheckbox();
+ },
+
+ /**
+ * Returns true if the named attribute in all objects in the given array are matching
+ *
+ * @param {Object[]} objects
+ * @param {string} attrName
+ * @return {boolean}
+ */
+ matchAttribute: function ( objects, attrName ) {
+ return $.map( objects, function ( object ) {
+ return object[ attrName ];
+ } ).filter( function ( item, index, a ) {
+ return index === a.indexOf( item );
+ } ).length === 1;
+ },
+
+ /**
+ * Are all actions protected at the same level, with the same expiry time?
+ *
+ * @return {boolean}
+ */
+ areAllTypesMatching: function () {
+ return this.matchAttribute( this.getLevelSelectors(), 'selectedIndex' ) &&
+ this.matchAttribute( this.getExpirySelectors(), 'selectedIndex' ) &&
+ this.matchAttribute( this.getExpiryInputs(), 'value' );
+ },
+
+ /**
+ * Is protection chaining off?
+ *
+ * @return {boolean}
+ */
+ isUnchained: function () {
+ var element = document.getElementById( 'mwProtectUnchained' );
+ return element ?
+ element.checked :
+ true; // No control, so we need to let the user set both levels
+ },
+
+ /**
+ * Find the highest protection level in any selector
+ *
+ * @return {number}
+ */
+ getMaxLevel: function () {
+ return Math.max.apply( Math, this.getLevelSelectors().map( function () {
+ return this.selectedIndex;
+ } ) );
+ },
+
+ /**
+ * Protect all actions at the specified level
+ *
+ * @param {number} index Protection level
+ */
+ setAllSelectors: function ( index ) {
+ this.getLevelSelectors().each( function () {
+ this.selectedIndex = index;
+ } );
+ },
+
+ /**
+ * Get a list of all protection selectors on the page
+ *
+ * @return {jQuery}
+ */
+ getLevelSelectors: function () {
+ return $( 'select[id ^= mwProtect-level-]' );
+ },
+
+ /**
+ * Get a list of all expiry inputs on the page
+ *
+ * @return {jQuery}
+ */
+ getExpiryInputs: function () {
+ return $( 'input[id ^= mwProtect-][id $= -expires]' );
+ },
+
+ /**
+ * Get a list of all expiry selector lists on the page
+ *
+ * @return {jQuery}
+ */
+ getExpirySelectors: function () {
+ return $( 'select[id ^= mwProtectExpirySelection-]' );
+ },
+
+ /**
+ * Enable/disable protection selectors and expiry inputs
+ *
+ * @param {boolean} val Enable?
+ */
+ toggleUnchainedInputs: function ( val ) {
+ var setDisabled = function () { this.disabled = !val; };
+ this.getLevelSelectors().slice( 1 ).each( setDisabled );
+ this.getExpiryInputs().slice( 1 ).each( setDisabled );
+ this.getExpirySelectors().slice( 1 ).each( setDisabled );
+ }
+ };
+
+ $( ProtectionForm.init.bind( ProtectionForm ) );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.legacy/shared.css b/www/wiki/resources/src/mediawiki.legacy/shared.css
new file mode 100644
index 00000000..9930525f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/shared.css
@@ -0,0 +1,806 @@
+/**
+ * CSS in this file is used by *all* skins (that have any CSS at all). Be
+ * careful what you put in here, since what looks good in one skin may not in
+ * another, but don't ignore the poor pre-Monobook users either.
+ *
+ * NOTE: The images which are referenced in this file are no longer in use in
+ * essential interface components. They should NOT be embedded, because that
+ * optimizes for the uncommon case at the cost of bloating the size of render-
+ * blocking CSS common to all pages.
+ */
+
+/* GENERAL CLASSES FOR DIRECTIONALITY SUPPORT */
+
+/**
+ * These classes should be used for text depending on the content direction.
+ * Content stuff like editsection, ul/ol and TOC depend on this.
+ */
+.mw-content-ltr {
+ /* @noflip */
+ direction: ltr;
+}
+
+.mw-content-rtl {
+ /* @noflip */
+ direction: rtl;
+}
+
+/* Most input fields should be in site direction */
+.sitedir-ltr textarea,
+.sitedir-ltr input {
+ /* @noflip */
+ direction: ltr;
+}
+
+.sitedir-rtl textarea,
+.sitedir-rtl input {
+ /* @noflip */
+ direction: rtl;
+}
+
+.mw-userlink {
+ unicode-bidi: embed;
+}
+
+/* User-Agent styles for new HTML5 elements */
+mark {
+ background-color: #ff0;
+ color: #000;
+}
+
+/* Helper for wbr element on IE 8+; in HTML5, but not supported by default as of IE 11. */
+/* Note canonical HTML5 styles recommend "content: \u200B", but this doesn't work as of IE 11. */
+wbr {
+ display: inline-block;
+}
+
+/* Input types that should follow user direction, like buttons */
+/* TODO: What about buttons in wikipage content ? */
+input[type='submit'],
+input[type='button'],
+input[type='reset'],
+input[type='file'] {
+ direction: ltr;
+}
+
+/* Override default values */
+textarea[dir='ltr'],
+input[dir='ltr'] {
+ /* @noflip */
+ direction: ltr;
+}
+
+textarea[dir='rtl'],
+input[dir='rtl'] {
+ /* @noflip */
+ direction: rtl;
+}
+
+/* Default style for semantic tags */
+abbr[title],
+.explain[title] {
+ border-bottom: 1px dotted;
+ cursor: help;
+}
+
+@supports ( text-decoration: underline dotted ) {
+ abbr[title],
+ .explain[title] {
+ border-bottom: 0;
+ text-decoration: underline dotted;
+ }
+}
+
+/* Comment portions of RC entries */
+span.comment {
+ font-style: italic;
+ unicode-bidi: -moz-isolate;
+ unicode-bidi: isolate;
+}
+
+/* Stop floats from intruding into edit area in previews */
+#editform,
+#toolbar,
+#wpTextbox1 {
+ clear: both;
+}
+
+/* Prevent editing textarea from jumping when toolbar is loaded */
+#toolbar {
+ height: 22px;
+}
+
+/* Edit font preference */
+/* TODO: for 'default' on non-textareas we could compute the default font of textarea in the client */
+.mw-editfont-default:not( textarea ) {
+ font-family: monospace;
+}
+
+/* Keep this rule separate from the :not rule above so it still works in older browsers */
+.mw-editfont-monospace {
+ font-family: monospace;
+}
+
+.mw-editfont-sans-serif {
+ font-family: sans-serif;
+}
+
+.mw-editfont-serif {
+ font-family: serif;
+}
+
+/* Underline preference */
+
+.mw-underline-always a {
+ text-decoration: underline;
+}
+
+.mw-underline-never a {
+ text-decoration: none;
+}
+
+/**
+ * rev_deleted stuff
+ */
+li span.deleted,
+span.history-deleted {
+ text-decoration: line-through;
+ color: #72777d;
+ font-style: italic;
+}
+
+/**
+ * Patrol stuff
+ */
+.not-patrolled {
+ background-color: #ffa;
+}
+
+.unpatrolled {
+ font-weight: bold;
+ color: #d33;
+}
+
+div.patrollink {
+ font-size: 75%;
+ text-align: right;
+}
+
+/**
+ * Forms
+ */
+td.mw-label {
+ text-align: right;
+ vertical-align: middle;
+}
+
+td.mw-input {
+ text-align: left;
+}
+
+td.mw-submit {
+ text-align: left;
+ white-space: nowrap;
+}
+
+.mw-input-with-label {
+ white-space: nowrap;
+ display: inline-block;
+}
+
+/**
+ * Image captions.
+ *
+ * This is only meant to provide the most basic of styles, visual settings shouldn't be added here.
+ */
+
+/* @noflip */
+.mw-content-ltr .thumbcaption {
+ text-align: left;
+}
+
+/* @noflip */
+.mw-content-ltr .magnify {
+ float: right;
+}
+
+/* @noflip */
+.mw-content-rtl .thumbcaption {
+ text-align: right;
+}
+
+/* @noflip */
+.mw-content-rtl .magnify {
+ float: left;
+}
+
+/**
+ * Categories
+ */
+#catlinks {
+ /**
+ * Overrides text justification (user preference)
+ * See T33990
+ */
+ text-align: left;
+}
+
+.catlinks ul {
+ display: inline;
+ margin: 0;
+ padding: 0;
+ list-style: none;
+ list-style-type: none;
+ list-style-image: none;
+ vertical-align: middle !ie;
+}
+
+.catlinks li {
+ display: inline-block;
+ line-height: 1.25em;
+ border-left: 1px solid #a2a9b1;
+ margin: 0.125em 0;
+ padding: 0 0.5em;
+ zoom: 1;
+ display: inline !ie; /* stylelint-disable-line declaration-block-no-duplicate-properties */
+}
+
+.catlinks li:first-child {
+ padding-left: 0.25em;
+ border-left: 0;
+}
+
+/* (T7346) make category redirects italic */
+.catlinks li a.mw-redirect {
+ font-style: italic;
+}
+
+/**
+ * Hidden categories
+ */
+.mw-hidden-cats-hidden {
+ display: none;
+}
+
+.catlinks-allhidden {
+ display: none;
+}
+
+/**
+ * Convenience links to edit delete and protect reasons
+ */
+p.mw-protect-editreasons,
+p.mw-filedelete-editreasons,
+p.mw-delete-editreasons {
+ font-size: 90%;
+ text-align: right;
+}
+
+/* The auto-generated edit comments */
+.autocomment {
+ color: #72777d;
+}
+
+/** Generic minor/bot/newpage styling (recent changes) */
+.newpage,
+.minoredit,
+.botedit {
+ font-weight: bold;
+}
+
+/**
+ * Recreating deleted page warning
+ * Reupload file warning
+ * Page protection warning
+ * incl. log entries for these warnings
+ */
+div.mw-warning-with-logexcerpt {
+ padding: 3px;
+ margin-bottom: 3px;
+ border: 2px solid #2a4b8d;
+ clear: both;
+}
+
+div.mw-warning-with-logexcerpt ul li {
+ font-size: 90%;
+}
+
+/* (show/hide) revision deletion links */
+span.mw-revdelundel-link,
+strong.mw-revdelundel-link {
+ font-size: 90%;
+}
+
+span.mw-revdelundel-hidden,
+input.mw-revdelundel-hidden {
+ visibility: hidden;
+}
+
+td.mw-revdel-checkbox,
+th.mw-revdel-checkbox {
+ padding-right: 10px;
+ text-align: center;
+}
+
+/* red links; see T38276 */
+a.new {
+ color: #ba0000;
+}
+
+/* self links */
+a.mw-selflink {
+ color: inherit;
+ font-weight: bold;
+ text-decoration: inherit;
+}
+a.mw-selflink:hover {
+ cursor: inherit;
+ text-decoration: inherit;
+}
+a.mw-selflink:active,
+a.mw-selflink:visited {
+ color: inherit;
+}
+
+/* Plainlinks - this can be used to switch
+ * off special external link styling */
+.plainlinks a.external {
+ background: none !important; /* stylelint-disable-line declaration-no-important */
+ padding: 0 !important; /* stylelint-disable-line declaration-no-important */
+}
+
+/* External URLs should always be treated as LTR (T6330) */
+/* @noflip */ .rtl a.external.free,
+.rtl a.external.autonumber {
+ direction: ltr;
+ unicode-bidi: embed;
+}
+
+/**
+ * wikitable class for skinning normal tables
+ * keep in sync with commonPrint.css
+ */
+table.wikitable {
+ background-color: #f8f9fa;
+ color: #222;
+ margin: 1em 0;
+ border: 1px solid #a2a9b1;
+ border-collapse: collapse;
+}
+
+table.wikitable > tr > th,
+table.wikitable > tr > td,
+table.wikitable > * > tr > th,
+table.wikitable > * > tr > td {
+ border: 1px solid #a2a9b1;
+ padding: 0.2em 0.4em;
+}
+
+table.wikitable > tr > th,
+table.wikitable > * > tr > th {
+ background-color: #eaecf0;
+ text-align: center;
+}
+
+table.wikitable > caption {
+ font-weight: bold;
+}
+
+/* success and error messages */
+.error,
+.warning,
+.success {
+ font-size: larger;
+}
+
+.error {
+ color: #d33;
+}
+
+.warning {
+ color: #705000;
+}
+
+.success {
+ color: #009000;
+}
+
+.errorbox,
+.warningbox,
+.successbox {
+ border: 1px solid;
+ padding: 0.5em 1em;
+ margin-bottom: 1em;
+ display: inline-block;
+ zoom: 1;
+ *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */
+}
+
+.errorbox h2,
+.warningbox h2,
+.successbox h2 {
+ font-size: 1em;
+ color: inherit;
+ font-weight: bold;
+ display: inline;
+ margin: 0 0.5em 0 0;
+ border: 0;
+}
+
+.errorbox {
+ color: #d33;
+ border-color: #fac5c5;
+ background-color: #fae3e3;
+}
+
+.warningbox {
+ color: #705000;
+ border-color: #fde29b;
+ background-color: #fdf1d1;
+}
+
+.successbox {
+ color: #008000;
+ border-color: #b7fdb5;
+ background-color: #e1fddf;
+}
+
+/* general info/warning box for SP */
+.mw-infobox {
+ border: 2px solid #ff7f00;
+ margin: 0.5em;
+ clear: left;
+ overflow: hidden;
+}
+
+.mw-infobox-left {
+ margin: 7px;
+ float: left;
+ width: 35px;
+}
+
+.mw-infobox-right {
+ margin: 0.5em 0.5em 0.5em 49px;
+}
+
+/* Note on preview page */
+.previewnote {
+ color: #d33;
+ margin-bottom: 1em;
+}
+
+.previewnote p {
+ text-indent: 3em;
+ margin: 0.8em 0;
+}
+
+.visualClear {
+ clear: both;
+}
+
+/**
+ * Data table style
+ *
+ * Transparent table with suddle borders
+ * and blue row-highlighting.
+ */
+.mw-datatable {
+ border-collapse: collapse;
+}
+
+.mw-datatable,
+.mw-datatable td,
+.mw-datatable th {
+ border: 1px solid #a2a9b1;
+ padding: 0 0.15em 0 0.15em;
+}
+
+.mw-datatable th {
+ background-color: #ddf;
+}
+
+.mw-datatable td {
+ background-color: #fff;
+}
+
+.mw-datatable tr:hover td {
+ background-color: #eaf3ff;
+}
+
+/* Correct directionality when page dir is different from site/user dir */
+.mw-content-ltr ul,
+.mw-content-rtl .mw-content-ltr ul {
+ /* @noflip */
+ margin: 0.3em 0 0 1.6em;
+ padding: 0;
+}
+
+.mw-content-rtl ul,
+.mw-content-ltr .mw-content-rtl ul {
+ /* @noflip */
+ margin: 0.3em 1.6em 0 0;
+ padding: 0;
+}
+
+.mw-content-ltr ol,
+.mw-content-rtl .mw-content-ltr ol {
+ /* @noflip */
+ margin: 0.3em 0 0 3.2em;
+ padding: 0;
+}
+
+.mw-content-rtl ol,
+.mw-content-ltr .mw-content-rtl ol {
+ /* @noflip */
+ margin: 0.3em 3.2em 0 0;
+ padding: 0;
+}
+
+/* @noflip */
+.mw-content-ltr dd,
+.mw-content-rtl .mw-content-ltr dd {
+ margin-left: 1.6em;
+ margin-right: 0;
+}
+
+/* @noflip */
+.mw-content-rtl dd,
+.mw-content-ltr .mw-content-rtl dd {
+ margin-right: 1.6em;
+ margin-left: 0;
+}
+
+.mw-ajax-loader {
+ background-image: url( images/ajax-loader.gif );
+ background-position: center center;
+ background-repeat: no-repeat;
+ padding: 16px;
+ position: relative;
+ top: -16px;
+}
+
+.mw-small-spinner {
+ padding: 10px !important; /* stylelint-disable-line declaration-no-important */
+ margin-right: 0.6em;
+ background-image: url( images/spinner.gif );
+ background-position: center center;
+ background-repeat: no-repeat;
+}
+
+/* Language specific height correction for titles. Ref T31405 and T32809 */
+/* Languages like hi or ml require slightly more vertical space to show diacritics properly */
+h1:lang( anp ),
+h1:lang( as ),
+h1:lang( bh ), /* Macrolanguage, used on bh.wikipedia.org, should be removed one day */
+h1:lang( bho ),
+h1:lang( bn ),
+h1:lang( gu ),
+h1:lang( hi ),
+h1:lang( kn ),
+h1:lang( ks ),
+h1:lang( ml ),
+h1:lang( mr ),
+h1:lang( my ),
+h1:lang( mai ),
+h1:lang( ne ),
+h1:lang( new ),
+h1:lang( or ),
+h1:lang( pa ),
+h1:lang( pi ),
+h1:lang( sa ),
+h1:lang( ta ),
+h1:lang( te ) {
+ line-height: 1.6em !important; /* stylelint-disable-line declaration-no-important */
+}
+
+/* stylelint-disable selector-list-comma-newline-after */
+h2:lang( anp ), h3:lang( anp ), h4:lang( anp ), h5:lang( anp ), h6:lang( anp ),
+h2:lang( as ), h3:lang( as ), h4:lang( as ), h5:lang( as ), h6:lang( as ),
+h2:lang( bho ), h3:lang( bho ), h4:lang( bho ), h5:lang( bho ), h6:lang( bho ),
+h2:lang( bh ), h3:lang( bh ), h4:lang( bh ), h5:lang( bh ), h6:lang( bh ),
+h2:lang( bn ), h3:lang( bn ), h4:lang( bn ), h5:lang( bn ), h6:lang( bn ),
+h2:lang( gu ), h3:lang( gu ), h4:lang( gu ), h5:lang( gu ), h6:lang( gu ),
+h2:lang( hi ), h3:lang( hi ), h4:lang( hi ), h5:lang( hi ), h6:lang( hi ),
+h2:lang( kn ), h3:lang( kn ), h4:lang( kn ), h5:lang( kn ), h6:lang( kn ),
+h2:lang( ks ), h3:lang( ks ), h4:lang( ks ), h5:lang( ks ), h6:lang( ks ),
+h2:lang( ml ), h3:lang( ml ), h4:lang( ml ), h5:lang( ml ), h6:lang( ml ),
+h2:lang( mr ), h3:lang( mr ), h4:lang( mr ), h5:lang( mr ), h6:lang( mr ),
+h2:lang( my ), h3:lang( my ), h4:lang( my ), h5:lang( my ), h6:lang( my ),
+h2:lang( mai ), h3:lang( mai ), h4:lang( mai ), h5:lang( mai ), h6:lang( mai ),
+h2:lang( ne ), h3:lang( ne ), h4:lang( ne ), h5:lang( ne ), h6:lang( ne ),
+h2:lang( new ), h3:lang( new ), h4:lang( new ), h5:lang( new ), h6:lang( new ),
+h2:lang( or ), h3:lang( or ), h4:lang( or ), h5:lang( or ), h6:lang( or ),
+h2:lang( pa ), h3:lang( pa ), h4:lang( pa ), h5:lang( pa ), h6:lang( pa ),
+h2:lang( pi ), h3:lang( pi ), h4:lang( pi ), h5:lang( pi ), h6:lang( pi ),
+h2:lang( sa ), h3:lang( sa ), h4:lang( sa ), h5:lang( sa ), h6:lang( sa ),
+h2:lang( ta ), h3:lang( ta ), h4:lang( ta ), h5:lang( ta ), h6:lang( ta ),
+h2:lang( te ), h3:lang( te ), h4:lang( te ), h5:lang( te ), h6:lang( te ) {
+ line-height: 1.2em;
+}
+/* stylelint-enable selector-list-comma-newline-after */
+
+/* Localised ordered list numbering for some languages */
+ol:lang( azb ) li,
+ol:lang( bcc ) li,
+ol:lang( bgn ) li,
+ol:lang( bqi ) li,
+ol:lang( fa ) li,
+ol:lang( glk ) li,
+ol:lang( kk-arab ) li,
+ol:lang( lrc ) li,
+ol:lang( luz ) li,
+ol:lang( mzn ) li {
+ list-style-type: -moz-persian;
+ list-style-type: persian;
+}
+
+ol:lang( ckb ) li,
+ol:lang( sdh ) li {
+ list-style-type: -moz-arabic-indic;
+ list-style-type: arabic-indic;
+}
+
+ol:lang( hi ) li,
+ol:lang( mai ) li,
+ol:lang( mr ) li,
+ol:lang( ne ) li {
+ list-style-type: -moz-devanagari;
+ list-style-type: devanagari;
+}
+
+ol:lang( as ) li,
+ol:lang( bn ) li {
+ list-style-type: -moz-bengali;
+ list-style-type: bengali;
+}
+
+ol:lang( or ) li {
+ list-style-type: -moz-oriya;
+ list-style-type: oriya;
+}
+
+#toc ul,
+.toc ul {
+ margin: 0.3em 0;
+}
+
+/* Correct directionality when page dir is different from site/user dir */
+/* @noflip */ .mw-content-ltr .toc ul,
+.mw-content-ltr #toc ul,
+.mw-content-rtl .mw-content-ltr .toc ul,
+.mw-content-rtl .mw-content-ltr #toc ul {
+ text-align: left;
+}
+
+/* @noflip */ .mw-content-rtl .toc ul,
+.mw-content-rtl #toc ul,
+.mw-content-ltr .mw-content-rtl .toc ul,
+.mw-content-ltr .mw-content-rtl #toc ul {
+ text-align: right;
+}
+
+/* @noflip */ .mw-content-ltr .toc ul ul,
+.mw-content-ltr #toc ul ul,
+.mw-content-rtl .mw-content-ltr .toc ul ul,
+.mw-content-rtl .mw-content-ltr #toc ul ul {
+ margin: 0 0 0 2em;
+}
+
+/* @noflip */ .mw-content-rtl .toc ul ul,
+.mw-content-rtl #toc ul ul,
+.mw-content-ltr .mw-content-rtl .toc ul ul,
+.mw-content-ltr .mw-content-rtl #toc ul ul {
+ margin: 0 2em 0 0;
+}
+
+#toc #toctitle,
+.toc #toctitle,
+#toc .toctitle,
+.toc .toctitle {
+ direction: ltr;
+}
+
+#mw-clearyourcache,
+#mw-sitecsspreview,
+#mw-sitejspreview,
+#mw-usercsspreview,
+#mw-userjspreview {
+ direction: ltr;
+ unicode-bidi: embed;
+}
+
+#mw-revision-info,
+#mw-revision-info-current,
+#mw-revision-nav {
+ direction: ltr;
+}
+
+/* Images */
+
+/* @noflip */ div.tright,
+div.floatright,
+table.floatright {
+ clear: right;
+ float: right;
+}
+
+/* @noflip */ div.tleft,
+div.floatleft,
+table.floatleft {
+ float: left;
+ clear: left;
+}
+
+div.floatright,
+table.floatright,
+div.floatleft,
+table.floatleft {
+ position: relative;
+}
+
+/* T14205 */
+#mw-credits a {
+ unicode-bidi: embed;
+}
+
+/* Accessibility */
+.mw-jump,
+#jump-to-nav {
+ overflow: hidden;
+ height: 0;
+ zoom: 1; /* http://webaim.org/techniques/skipnav/#iequirk */
+}
+
+/* Print footer should be hidden by default in screen. */
+.printfooter {
+ display: none;
+}
+
+/* For developers */
+.xdebug-error {
+ position: absolute;
+ z-index: 99;
+}
+
+.mw-editsection,
+#jump-to-nav {
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+/* Display editsection links smaller and next to headings */
+.mw-editsection,
+.mw-editsection-like {
+ font-size: small;
+ font-weight: normal;
+ margin-left: 1em;
+ vertical-align: baseline;
+ /* Reset line-height; headings tend to have it set to larger values */
+ line-height: 1em;
+ /* As .mw-editsection is a <span> (inline element), it is treated as part */
+ /* of the heading content when selecting text by multiple clicks and thus */
+ /* selected together with heading content, despite the user-select: none; */
+ /* rule set above. This enforces non-selection without changing the look. */
+ display: inline-block;
+}
+
+/* Correct directionality when page dir is different from site/user dir */
+/* @noflip */
+.mw-content-ltr .mw-editsection,
+.mw-content-rtl .mw-content-ltr .mw-editsection {
+ margin-left: 1em;
+}
+
+/* @noflip */
+.mw-content-rtl .mw-editsection,
+.mw-content-ltr .mw-content-rtl .mw-editsection {
+ margin-right: 1em;
+}
+
+/* Prevent citations and subscripts from interfering with the line-height */
+sup,
+sub {
+ line-height: 1;
+}
diff --git a/www/wiki/resources/src/mediawiki.legacy/wikibits.js b/www/wiki/resources/src/mediawiki.legacy/wikibits.js
new file mode 100644
index 00000000..bd1b9188
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.legacy/wikibits.js
@@ -0,0 +1,105 @@
+/**
+ * MediaWiki legacy wikibits
+ */
+( function ( mw, $ ) {
+ var msg,
+ loadedScripts = {};
+
+ function wikiUrlencode( page ) {
+ return encodeURIComponent( String( page ) )
+ .replace( /'/g, '%27' )
+ .replace( /%20/g, '_' )
+ // wfUrlencode replacements
+ .replace( /%3B/g, ';' )
+ .replace( /%40/g, '@' )
+ .replace( /%24/g, '$' )
+ .replace( /%21/g, '!' )
+ .replace( /%2A/g, '*' )
+ .replace( /%28/g, '(' )
+ .replace( /%29/g, ')' )
+ .replace( /%2C/g, ',' )
+ .replace( /%2F/g, '/' )
+ .replace( /%7E/g, '~' )
+ .replace( /%3A/g, ':' );
+ }
+
+ /**
+ * @deprecated since 1.17 Use jQuery instead
+ */
+ mw.log.deprecate( window, 'addOnloadHook', function ( fn ) {
+ $( function () { fn(); } );
+ }, 'Use jQuery instead.' );
+
+ /**
+ * Wikipage import methods
+ *
+ * See https://www.mediawiki.org/wiki/ResourceLoader/Legacy_JavaScript#wikibits.js
+ */
+
+ /**
+ * @deprecated since 1.17 Use mw.loader instead. Warnings added in 1.25.
+ * @param {string} url
+ * @return {HTMLElement} Script tag
+ */
+ function importScriptURI( url ) {
+ var s;
+ if ( loadedScripts[ url ] ) {
+ return null;
+ }
+ loadedScripts[ url ] = true;
+ s = document.createElement( 'script' );
+ s.setAttribute( 'src', url );
+ document.getElementsByTagName( 'head' )[ 0 ].appendChild( s );
+ return s;
+ }
+
+ function importScript( page ) {
+ var uri = mw.config.get( 'wgScript' ) + '?title=' + wikiUrlencode( page ) +
+ '&action=raw&ctype=text/javascript';
+ return importScriptURI( uri );
+ }
+
+ /**
+ * @deprecated since 1.17 Use mw.loader instead. Warnings added in 1.25.
+ * @param {string} url
+ * @param {string} media
+ * @return {HTMLElement} Link tag
+ */
+ function importStylesheetURI( url, media ) {
+ var l = document.createElement( 'link' );
+ l.rel = 'stylesheet';
+ l.href = url;
+ if ( media ) {
+ l.media = media;
+ }
+ document.getElementsByTagName( 'head' )[ 0 ].appendChild( l );
+ return l;
+ }
+
+ function importStylesheet( page ) {
+ var uri = mw.config.get( 'wgScript' ) + '?title=' + wikiUrlencode( page ) +
+ '&action=raw&ctype=text/css';
+ return importStylesheetURI( uri );
+ }
+
+ msg = 'Use mw.loader instead.';
+ mw.log.deprecate( window, 'loadedScripts', loadedScripts, msg );
+ mw.log.deprecate( window, 'importScriptURI', importScriptURI, msg );
+ mw.log.deprecate( window, 'importStylesheetURI', importStylesheetURI, msg );
+ // Not quite deprecated yet.
+ window.importScript = importScript;
+ window.importStylesheet = importStylesheet;
+
+ /**
+ * Replace document.write/writeln with basic html parsing that appends
+ * to the <body> to avoid blanking pages. Added JavaScript will not run.
+ *
+ * @deprecated since 1.26
+ */
+ $.each( [ 'write', 'writeln' ], function ( idx, method ) {
+ mw.log.deprecate( document, method, function () {
+ $( 'body' ).append( $.parseHTML( Array.prototype.join.call( arguments, '' ) ) );
+ }, 'Use jQuery or mw.loader.load instead.', 'document.' + method );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.less/mediawiki.mixins.animation.less b/www/wiki/resources/src/mediawiki.less/mediawiki.mixins.animation.less
new file mode 100644
index 00000000..266834ce
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.less/mediawiki.mixins.animation.less
@@ -0,0 +1,11 @@
+.animation( ... ) {
+ -webkit-animation: @arguments; // Chrome 4-42, Safari 4-8, Opera 15-29, Android 2.1-4.4.4
+ -moz-animation: @arguments; // Firefox 5-15
+ animation: @arguments; // Chrome 43+, Firefox 16+, IE 10+, Edge 12+, Safari 9+, Opera 12.10 & 30+, iOS 9+, Android 47+
+}
+
+.transform-rotate( @deg ) {
+ -webkit-transform: rotate( @deg );
+ -moz-transform: rotate( @deg );
+ transform: rotate( @deg );
+}
diff --git a/www/wiki/resources/src/mediawiki.less/mediawiki.mixins.less b/www/wiki/resources/src/mediawiki.less/mediawiki.mixins.less
new file mode 100644
index 00000000..fb3b00ed
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.less/mediawiki.mixins.less
@@ -0,0 +1,192 @@
+// Common Less mixin library for MediaWiki
+//
+// By default the folder containing this file is included in $wgResourceLoaderLESSImportPaths,
+// which makes this file importable by all less files via `@import 'mediawiki.mixins';`.
+//
+// The mixins included below are considered a public interface for MediaWiki extensions.
+// The signatures of parametrized mixins should be kept as stable as possible.
+//
+// See <http://lesscss.org/#-mixins> for more information about how to write mixins.
+
+.background-image( @url ) {
+ background-image: e( '/* @embed */' ) url( @url );
+}
+
+// Deprecated in MW 1.27
+.background-size( @width, @height ) {
+ // Vendor prefix is added to support Android 2
+ -webkit-background-size: @width @height;
+ background-size: @width @height;
+}
+
+.vertical-gradient( @startColor: gray, @endColor: white, @startPos: 0, @endPos: 100% ) {
+ background-color: @endColor;
+ background-image: -webkit-gradient( linear, left top, left bottom, color-stop( @startPos, @startColor ), color-stop( @endPos, @endColor ) ); // Safari 4+, Chrome 2+
+ background-image: -webkit-linear-gradient( top, @startColor @startPos, @endColor @endPos ); // Safari 5.1+, Chrome 10+
+ background-image: -moz-linear-gradient( top, @startColor @startPos, @endColor @endPos ); // Firefox 3.6+
+ background-image: linear-gradient( @startColor @startPos, @endColor @endPos ); // Standard
+}
+
+// SVG support using a transparent gradient to guarantee cross-browser
+// compatibility (browsers able to understand gradient syntax support also SVG).
+// http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique
+//
+// We use gzip compression, which means that it is okay to embed twice.
+//
+// We do not embed the fallback image on the assumption that the gain for old browsers
+// is not worth the harm done to modern ones.
+.background-image-svg( @svg, @fallback ) {
+ background-image: url( @fallback );
+ background-image: linear-gradient( transparent, transparent ), e( '/* @embed */' ) url( @svg );
+ // Do not serve SVG to Opera 12, bad rendering with border-radius or background-size (T87504)
+ background-image: -o-linear-gradient( transparent, transparent ), url( @fallback );
+}
+
+// Shorthand for background-image-svg. Use if your PNG and SVG have the same name
+// and only if you cannot use ResourceLoaderImage module for some particular reason.
+.background-image-svg-quick( @url ) {
+ .background-image-svg( ~'@{url}.svg', ~'@{url}.png' );
+}
+
+.list-style-image( @url ) {
+ list-style-image: e( '/* @embed */' ) url( @url );
+}
+
+.list-style-image-svg( @svg, @fallback ) {
+ list-style-image: e( '/* @embed */' ) url( @svg );
+ /* Fallback to PNG bullet for IE 8 and below using CSS hack */
+ list-style-image: e( '/* @embed */' ) url( @fallback ) e( '\9' );
+}
+
+.transform( @value ) {
+ -webkit-transform: @value; // Safari 3.1-8.0, iOS 3.2-8.4, Android 2.1-4.4.4
+ -moz-transform: @value; // Firefox 3.5-15
+ transform: @value; // Chrome 36+, Firefox 16+, IE 10+, Safari 9+, Opera 23+, iOS 9.2+, Android 5+
+}
+
+.transition( @value ) {
+ -webkit-transition: @value; // Safari 3.1-6.0, iOS 3.2-6.1, Android 2.1-4.3
+ -moz-transition: @value; // Firefox 4-15
+ transition: @value; // Chrome 26+, Firefox 16+, IE 10+, Safari 6.1+, Opera 12.1+, iOS 7+, Android 4.4+
+}
+
+// Provide a hardware accelerated transform transition
+// We can't use `.transition()` because WebKit requires `-webkit-` prefix before `transform`
+// Example usage: `.transition-transform( 1s, opacity 2s );`
+// First parameter is additional options for `transform` transition commencing with
+// duration property @see https://www.w3.org/TR/css3-transitions/#transition-duration-property
+// and remaining parameters are additional transitions."
+.transition-transform( ... ) {
+ -webkit-backface-visibility: hidden; // Older Webkit browsers: Promote element to a composite layer & involve the GPU
+
+ -webkit-transition: -webkit-transform @arguments; // Safari 3.1-8, iOS 3.2-8.4, Android 2.1-4.4.4
+ -moz-transition: -moz-transform @arguments; // Firefox 4-15 for `-moz-transition`
+ transition: transform @arguments; // Chrome 36+, Firefox 16+, IE 10+, Safari 9+, Opera 12.1+, iOS 9.2+, Android 36+
+}
+
+.box-sizing( @value ) {
+ -webkit-box-sizing: @value; // Safari 3.1-5.0, iOS 3.2-4.3, Android 2.1-3.0
+ -moz-box-sizing: @value; // Firefox 4-28,
+ box-sizing: @value; // Chrome 10+, Firefox 29+, IE 8+, Safari 5.1+, Opera 10+, iOS 5+, Android 4+
+}
+
+.box-shadow( @value ) {
+ -webkit-box-shadow: @value; // Safari 3.1-5.0, iOS 3.2-4.3, Android 2.1-3.0
+ box-shadow: @value; // Chrome 10+, Firefox 4+, IE 9+, Safari 5.1+, Opera 11+, iOS 5+, Android 4+
+}
+
+.column-count( @value ) {
+ -webkit-column-count: @value;
+ -moz-column-count: @value;
+ column-count: @value;
+}
+
+.column-width( @value ) {
+ -webkit-column-width: @value; // Chrome Any, Safari 3+, Opera 15+
+ -moz-column-width: @value; // Firefox 1.5+
+ column-width: @value; // IE 10+, Opera 11.1-12.1
+}
+
+.column-break-inside-avoid() {
+ -webkit-column-break-inside: avoid; // Chrome Any, Safari 3+, Opera 15+
+ page-break-inside: avoid; // Firefox 1.5+
+ break-inside: avoid-column; // IE 10+, Opera 11.1-12.1
+}
+
+.flex-display( @display: flex ) {
+ display: ~'-webkit-@{display}'; // iOS 6-, Safari 3.1-6
+ display: ~'-moz-@{display}'; // Firefox 21-
+ display: ~'-ms-@{display}box'; // IE 10
+ display: @display;
+}
+
+.flex-wrap( @wrap: wrap ) {
+ -webkit-flex-wrap: @wrap; // iOS 6-, Safari 3.1-6
+ -moz-flex-wrap: @wrap; // Firefox 21-
+ -ms-flex-wrap: @wrap; // IE 10
+ flex-wrap: @wrap;
+}
+
+.flex( @grow: 1, @shrink: 1, @width: auto, @order: 1 ) {
+ // For 2009/2012 spec alignment consistency with current default
+ -webkit-box-pack: justify; // iOS 6-, Safari 3.1-6
+ -moz-box-pack: justify; // Firefox 21-
+ -ms-flex-pack: justify; // IE 10 (2012 spec)
+ justify-content: space-between; // Current default
+
+ // 2009 spec only supports 'flexible' as opposed to grow (flexPositive)
+ // and shrink (flexNegative); default to grow value
+ -webkit-box-flex: @grow; // iOS 6-, Safari 3.1-6
+ -moz-box-flex: @grow; // Firefox 21-
+ width: @width; // Fallback for flex-basis
+
+ -ms-flex: @grow @shrink @width; // IE 10
+ flex: @grow @shrink @width;
+
+ -webkit-box-ordinal-group: @order; // iOS 6-, Safari 3.1-6
+ -moz-box-ordinal-group: @order; // Firefox 21-
+ -ms-flex-order: @order; // IE 10
+ order: @order;
+}
+
+/* stylelint-disable selector-no-vendor-prefix, at-rule-no-unknown */
+.mixin-placeholder( @rules ) {
+ // WebKit, Blink, Edge
+ &::-webkit-input-placeholder {
+ @rules();
+ }
+ // Internet Explorer 10-11
+ &:-ms-input-placeholder {
+ @rules();
+ }
+ // Firefox 19-
+ &::-moz-placeholder {
+ @rules();
+ }
+ // Firefox 4-18
+ &:-moz-placeholder {
+ @rules();
+ }
+ // W3C Standard Selectors Level 4
+ &::placeholder {
+ @rules();
+ }
+ // For inputs that use jquery.placeholder.js e.g. IE9
+ &.placeholder {
+ @rules();
+ }
+}
+/* stylelint-enable selector-no-vendor-prefix, at-rule-no-unknown */
+
+// Screen Reader Helper Mixin
+.mixin-screen-reader-text() {
+ display: block;
+ position: absolute !important; /* stylelint-disable-line declaration-no-important */
+ clip: rect( 1px, 1px, 1px, 1px );
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ border: 0;
+ padding: 0;
+ overflow: hidden;
+}
diff --git a/www/wiki/resources/src/mediawiki.less/mediawiki.mixins.rotation.less b/www/wiki/resources/src/mediawiki.less/mediawiki.mixins.rotation.less
new file mode 100644
index 00000000..64d6b3d6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.less/mediawiki.mixins.rotation.less
@@ -0,0 +1,29 @@
+// This is a separate file because importing the mixin causes
+// the keyframes blocks to be included in the output, regardless
+// of whether .rotation is used.
+@import 'mediawiki.mixins.animation';
+
+.rotate-frames() {
+ from {
+ .transform-rotate( 0deg );
+ }
+ to {
+ .transform-rotate( 360deg );
+ }
+}
+
+@-webkit-keyframes rotate {
+ .rotate-frames;
+}
+
+@-moz-keyframes rotate {
+ .rotate-frames;
+}
+
+@keyframes rotate {
+ .rotate-frames;
+}
+
+.rotation( @time ) {
+ .animation( rotate, @time, infinite, linear );
+}
diff --git a/www/wiki/resources/src/mediawiki.less/mediawiki.ui/mixins.less b/www/wiki/resources/src/mediawiki.less/mediawiki.ui/mixins.less
new file mode 100644
index 00000000..a0ff7679
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.less/mediawiki.ui/mixins.less
@@ -0,0 +1,149 @@
+// ----------------------------------------------------------------------------
+// Form styling mixins
+// ----------------------------------------------------------------------------
+.agora-label-styling() {
+ font-size: 0.9em;
+ color: @colorText;
+
+ * {
+ font-weight: normal;
+ }
+}
+
+.agora-inline-label-styling() {
+ margin-bottom: 0.5em;
+ cursor: pointer;
+ vertical-align: bottom;
+ line-height: normal;
+ font-weight: normal;
+
+ & > input[type='checkbox'],
+ & > input[type='radio'] {
+ width: auto;
+ height: auto;
+ margin: 0 0.1em 0 0;
+ padding: 0;
+ border: 1px solid @colorGray7;
+ cursor: pointer;
+ }
+}
+
+// ----------------------------------------------------------------------------
+// Button styling
+// ----------------------------------------------------------------------------
+
+.button-colors( @bgColor, @highlightColor, @activeColor ) {
+ background-color: @bgColor;
+ color: @colorButtonText;
+ border: 1px solid @colorFieldBorder;
+
+ // Make sure that `color` isn't inheriting from user-agent styles
+ &:visited {
+ color: @colorButtonText;
+ }
+
+ &:hover {
+ background-color: @highlightColor;
+ color: @colorGray4;
+ border-color: @colorGray10;
+ }
+
+ &:focus {
+ background-color: @highlightColor;
+ // Make sure that `color` isn't inheriting from user-agent styles
+ color: @colorButtonText;
+ border-color: @colorProgressive;
+ box-shadow: inset 0 0 0 1px @colorProgressive, inset 0 0 0 2px #fff;
+ }
+
+ &:active,
+ &.is-on,
+ &.mw-ui-checked {
+ background-color: @activeColor;
+ color: @colorGray1;
+ border-color: @colorGray7;
+ box-shadow: none;
+ }
+
+ &:disabled {
+ background-color: @colorGray12;
+ color: #fff;
+ border-color: @colorGray12;
+
+ // Make sure disabled buttons don't have hover and active states
+ &:hover,
+ &:active {
+ background-color: @colorGray12;
+ color: #fff;
+ box-shadow: none;
+ border-color: @colorGray12;
+ }
+ }
+}
+
+.button-colors-primary( @bgColor, @highlightColor, @activeColor ) {
+ background-color: @bgColor;
+ color: #fff;
+ // border of the same color as background so that light background and
+ // dark background buttons are the same height and width
+ border: 1px solid @bgColor;
+ text-shadow: 0 1px rgba( 0, 0, 0, 0.1 );
+
+ &:hover {
+ background-color: @highlightColor;
+ border-color: @highlightColor;
+ }
+
+ &:focus {
+ box-shadow: inset 0 0 0 1px @bgColor, inset 0 0 0 2px #fff;
+ }
+
+ &:active,
+ &.is-on,
+ &.mw-ui-checked {
+ background-color: @activeColor;
+ border-color: @activeColor;
+ box-shadow: none;
+ }
+
+ &:disabled {
+ background-color: @colorGray12;
+ color: #fff;
+ border-color: @colorGray12;
+
+ // Make sure disabled buttons don't have hover and active states
+ &:hover,
+ &:active,
+ &.mw-ui-checked {
+ background-color: @colorGray12;
+ color: #fff;
+ border-color: @colorGray12;
+ box-shadow: none;
+ }
+ }
+}
+
+.button-colors-quiet( @textColor, @highlightColor, @activeColor ) {
+ // Quiet buttons all start gray, and reveal
+ // progressive/destructive color on hover and active.
+ color: @colorButtonText;
+
+ &:hover {
+ background-color: transparent;
+ color: @highlightColor;
+ }
+
+ &:active,
+ &.mw-ui-checked {
+ color: @activeColor;
+ }
+
+ &:focus {
+ background-color: transparent;
+ color: @textColor;
+ }
+
+ &:disabled {
+ color: @colorDisabledText;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.less/mediawiki.ui/variables.less b/www/wiki/resources/src/mediawiki.less/mediawiki.ui/variables.less
new file mode 100644
index 00000000..0c897dc9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.less/mediawiki.ui/variables.less
@@ -0,0 +1,85 @@
+// Colors for use in mediawiki.ui and elsewhere
+
+// Although this defines many shades, be parsimonious in your own use of grays.
+// Prefer semantic color names such as `@colorText` below.
+@colorGray1: #000; // darkest
+@colorGray2: #222;
+@colorGray4: #444;
+@colorGray5: #54595d;
+@colorGray7: #72777d;
+@colorGray10: #a2a9b1;
+@colorGray12: #c8ccd1;
+@colorGray14: #eaecf0;
+@colorGray15: #f8f9fa; // lightest
+@colorBaseInverted: #fff;
+
+// Semantic colors
+// Blue; for contextual use of a continuing action
+@colorProgressive: #36c;
+@colorProgressiveHighlight: #447ff5;
+@colorProgressiveActive: #2a4b8d;
+// Orange; for contextual use of returning to a past action
+@colorRegressive: #ff5d00;
+// Red; for contextual use of a negative action of high severity
+@colorDestructive: #d33;
+@colorDestructiveHighlight: #ff4242;
+@colorDestructiveActive: #b32424;
+// Orange; for contextual use of a potentially negative action of medium severity
+@colorMediumSevere: #ff5d00;
+// Yellow; for contextual use of a potentially negative action of low severity
+@colorLowSevere: #fc3;
+
+// Used in mixins to darken contextual colors by the same amount (eg. focus)
+@colorDarkenPercentage: 13.5%;
+// Used in mixins to lighten contextual colors by the same amount (eg. hover)
+@colorLightenPercentage: 13.5%;
+
+// Text colors
+@colorText: @colorGray2;
+@colorTextLight: @colorGray5;
+@colorButtonText: @colorGray2;
+@colorButtonTextHighlight: @colorGray4;
+@colorButtonTextActive: @colorGray1;
+@colorDisabledText: @colorGray12;
+@colorErrorText: #d33;
+@colorWarningText: #705000;
+
+// UI colors
+@backgroundColorInputBinaryChecked: @colorProgressive;
+@backgroundColorInputBinaryActive: @colorProgressiveActive;
+@colorFieldBorder: #a2a9b1;
+@colorShadow: @colorGray14;
+@colorPlaceholder: @colorGray10;
+@colorNeutral: @colorGray7;
+
+// Border colors
+@borderColorInputBinaryChecked: @colorProgressive;
+@borderColorInputBinaryActive: @colorProgressiveActive;
+
+// Checked radio input border-width, equal to OOUI at 14px base font-size
+@borderWidthRadioChecked: 0.4285em;
+
+// Global border radius to be used to buttons and inputs
+@borderRadius: 2px;
+
+// Box shadows
+@boxShadowWidget: inset 0 0 0 1px transparent;
+@boxShadowWidgetFocus: inset 0 0 0 1px @colorProgressive;
+@boxShadowProgressiveFocus: inset 0 0 0 1px @colorProgressive, inset 0 0 0 2px @colorBaseInverted;
+@boxShadowInputBinaryActive: inset 0 0 0 1px @colorProgressiveActive;
+
+// Icon related variables
+@iconSize: 1.5em;
+@iconGutterWidth: 1em;
+
+// Form input sizes, equal to OOUI at 14px base font-size
+@sizeInputBinary: 1.5625em;
+
+// Deprecated color variables from when WikimediaUI color palette wasn't around
+// See https://wikimedia.github.io/WikimediaUI-Style-Guide/visual-style_colors.html
+@colorGray3: #333;
+@colorGray6: #666;
+@colorGray8: #888;
+@colorGray9: #999;
+@colorGray11: #bbb;
+@colorGray13: #ddd;
diff --git a/www/wiki/resources/src/mediawiki.libs/CLDRPluralRuleParser.js b/www/wiki/resources/src/mediawiki.libs/CLDRPluralRuleParser.js
new file mode 100644
index 00000000..549a9ab3
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.libs/CLDRPluralRuleParser.js
@@ -0,0 +1,596 @@
+/* This is CLDRPluralRuleParser v1.1.3, ported to MediaWiki ResourceLoader */
+
+/**
+* CLDRPluralRuleParser.js
+* A parser engine for CLDR plural rules.
+*
+* Copyright 2012-2014 Santhosh Thottingal and other contributors
+* Released under the MIT license
+* http://opensource.org/licenses/MIT
+*
+* @source https://github.com/santhoshtr/CLDRPluralRuleParser
+* @author Santhosh Thottingal <santhosh.thottingal@gmail.com>
+* @author Timo Tijhof
+* @author Amir Aharoni
+*/
+
+( function ( mw ) {
+/**
+ * Evaluates a plural rule in CLDR syntax for a number
+ * @param {string} rule
+ * @param {integer} number
+ * @return {boolean} true if evaluation passed, false if evaluation failed.
+ */
+
+function pluralRuleParser(rule, number) {
+ 'use strict';
+
+ /*
+ Syntax: see http://unicode.org/reports/tr35/#Language_Plural_Rules
+ -----------------------------------------------------------------
+ condition = and_condition ('or' and_condition)*
+ ('@integer' samples)?
+ ('@decimal' samples)?
+ and_condition = relation ('and' relation)*
+ relation = is_relation | in_relation | within_relation
+ is_relation = expr 'is' ('not')? value
+ in_relation = expr (('not')? 'in' | '=' | '!=') range_list
+ within_relation = expr ('not')? 'within' range_list
+ expr = operand (('mod' | '%') value)?
+ operand = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
+ range_list = (range | value) (',' range_list)*
+ value = digit+
+ digit = 0|1|2|3|4|5|6|7|8|9
+ range = value'..'value
+ samples = sampleRange (',' sampleRange)* (',' ('…'|'...'))?
+ sampleRange = decimalValue '~' decimalValue
+ decimalValue = value ('.' value)?
+ */
+
+ // We don't evaluate the samples section of the rule. Ignore it.
+ rule = rule.split('@')[0].replace(/^\s*/, '').replace(/\s*$/, '');
+
+ if (!rule.length) {
+ // Empty rule or 'other' rule.
+ return true;
+ }
+
+ // Indicates the current position in the rule as we parse through it.
+ // Shared among all parsing functions below.
+ var pos = 0,
+ operand,
+ expression,
+ relation,
+ result,
+ whitespace = makeRegexParser(/^\s+/),
+ value = makeRegexParser(/^\d+/),
+ _n_ = makeStringParser('n'),
+ _i_ = makeStringParser('i'),
+ _f_ = makeStringParser('f'),
+ _t_ = makeStringParser('t'),
+ _v_ = makeStringParser('v'),
+ _w_ = makeStringParser('w'),
+ _is_ = makeStringParser('is'),
+ _isnot_ = makeStringParser('is not'),
+ _isnot_sign_ = makeStringParser('!='),
+ _equal_ = makeStringParser('='),
+ _mod_ = makeStringParser('mod'),
+ _percent_ = makeStringParser('%'),
+ _not_ = makeStringParser('not'),
+ _in_ = makeStringParser('in'),
+ _within_ = makeStringParser('within'),
+ _range_ = makeStringParser('..'),
+ _comma_ = makeStringParser(','),
+ _or_ = makeStringParser('or'),
+ _and_ = makeStringParser('and');
+
+ function debug() {
+ // console.log.apply(console, arguments);
+ }
+
+ debug('pluralRuleParser', rule, number);
+
+ // Try parsers until one works, if none work return null
+ function choice(parserSyntax) {
+ return function() {
+ var i, result;
+
+ for (i = 0; i < parserSyntax.length; i++) {
+ result = parserSyntax[i]();
+
+ if (result !== null) {
+ return result;
+ }
+ }
+
+ return null;
+ };
+ }
+
+ // Try several parserSyntax-es in a row.
+ // All must succeed; otherwise, return null.
+ // This is the only eager one.
+ function sequence(parserSyntax) {
+ var i, parserRes,
+ originalPos = pos,
+ result = [];
+
+ for (i = 0; i < parserSyntax.length; i++) {
+ parserRes = parserSyntax[i]();
+
+ if (parserRes === null) {
+ pos = originalPos;
+
+ return null;
+ }
+
+ result.push(parserRes);
+ }
+
+ return result;
+ }
+
+ // Run the same parser over and over until it fails.
+ // Must succeed a minimum of n times; otherwise, return null.
+ function nOrMore(n, p) {
+ return function() {
+ var originalPos = pos,
+ result = [],
+ parsed = p();
+
+ while (parsed !== null) {
+ result.push(parsed);
+ parsed = p();
+ }
+
+ if (result.length < n) {
+ pos = originalPos;
+
+ return null;
+ }
+
+ return result;
+ };
+ }
+
+ // Helpers - just make parserSyntax out of simpler JS builtin types
+ function makeStringParser(s) {
+ var len = s.length;
+
+ return function() {
+ var result = null;
+
+ if (rule.substr(pos, len) === s) {
+ result = s;
+ pos += len;
+ }
+
+ return result;
+ };
+ }
+
+ function makeRegexParser(regex) {
+ return function() {
+ var matches = rule.substr(pos).match(regex);
+
+ if (matches === null) {
+ return null;
+ }
+
+ pos += matches[0].length;
+
+ return matches[0];
+ };
+ }
+
+ /**
+ * Integer digits of n.
+ */
+ function i() {
+ var result = _i_();
+
+ if (result === null) {
+ debug(' -- failed i', parseInt(number, 10));
+
+ return result;
+ }
+
+ result = parseInt(number, 10);
+ debug(' -- passed i ', result);
+
+ return result;
+ }
+
+ /**
+ * Absolute value of the source number (integer and decimals).
+ */
+ function n() {
+ var result = _n_();
+
+ if (result === null) {
+ debug(' -- failed n ', number);
+
+ return result;
+ }
+
+ result = parseFloat(number, 10);
+ debug(' -- passed n ', result);
+
+ return result;
+ }
+
+ /**
+ * Visible fractional digits in n, with trailing zeros.
+ */
+ function f() {
+ var result = _f_();
+
+ if (result === null) {
+ debug(' -- failed f ', number);
+
+ return result;
+ }
+
+ result = (number + '.').split('.')[1] || 0;
+ debug(' -- passed f ', result);
+
+ return result;
+ }
+
+ /**
+ * Visible fractional digits in n, without trailing zeros.
+ */
+ function t() {
+ var result = _t_();
+
+ if (result === null) {
+ debug(' -- failed t ', number);
+
+ return result;
+ }
+
+ result = (number + '.').split('.')[1].replace(/0$/, '') || 0;
+ debug(' -- passed t ', result);
+
+ return result;
+ }
+
+ /**
+ * Number of visible fraction digits in n, with trailing zeros.
+ */
+ function v() {
+ var result = _v_();
+
+ if (result === null) {
+ debug(' -- failed v ', number);
+
+ return result;
+ }
+
+ result = (number + '.').split('.')[1].length || 0;
+ debug(' -- passed v ', result);
+
+ return result;
+ }
+
+ /**
+ * Number of visible fraction digits in n, without trailing zeros.
+ */
+ function w() {
+ var result = _w_();
+
+ if (result === null) {
+ debug(' -- failed w ', number);
+
+ return result;
+ }
+
+ result = (number + '.').split('.')[1].replace(/0$/, '').length || 0;
+ debug(' -- passed w ', result);
+
+ return result;
+ }
+
+ // operand = 'n' | 'i' | 'f' | 't' | 'v' | 'w'
+ operand = choice([n, i, f, t, v, w]);
+
+ // expr = operand (('mod' | '%') value)?
+ expression = choice([mod, operand]);
+
+ function mod() {
+ var result = sequence(
+ [operand, whitespace, choice([_mod_, _percent_]), whitespace, value]
+ );
+
+ if (result === null) {
+ debug(' -- failed mod');
+
+ return null;
+ }
+
+ debug(' -- passed ' + parseInt(result[0], 10) + ' ' + result[2] + ' ' + parseInt(result[4], 10));
+
+ return parseInt(result[0], 10) % parseInt(result[4], 10);
+ }
+
+ function not() {
+ var result = sequence([whitespace, _not_]);
+
+ if (result === null) {
+ debug(' -- failed not');
+
+ return null;
+ }
+
+ return result[1];
+ }
+
+ // is_relation = expr 'is' ('not')? value
+ function is() {
+ var result = sequence([expression, whitespace, choice([_is_]), whitespace, value]);
+
+ if (result !== null) {
+ debug(' -- passed is : ' + result[0] + ' == ' + parseInt(result[4], 10));
+
+ return result[0] === parseInt(result[4], 10);
+ }
+
+ debug(' -- failed is');
+
+ return null;
+ }
+
+ // is_relation = expr 'is' ('not')? value
+ function isnot() {
+ var result = sequence(
+ [expression, whitespace, choice([_isnot_, _isnot_sign_]), whitespace, value]
+ );
+
+ if (result !== null) {
+ debug(' -- passed isnot: ' + result[0] + ' != ' + parseInt(result[4], 10));
+
+ return result[0] !== parseInt(result[4], 10);
+ }
+
+ debug(' -- failed isnot');
+
+ return null;
+ }
+
+ function not_in() {
+ var i, range_list,
+ result = sequence([expression, whitespace, _isnot_sign_, whitespace, rangeList]);
+
+ if (result !== null) {
+ debug(' -- passed not_in: ' + result[0] + ' != ' + result[4]);
+ range_list = result[4];
+
+ for (i = 0; i < range_list.length; i++) {
+ if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ debug(' -- failed not_in');
+
+ return null;
+ }
+
+ // range_list = (range | value) (',' range_list)*
+ function rangeList() {
+ var result = sequence([choice([range, value]), nOrMore(0, rangeTail)]),
+ resultList = [];
+
+ if (result !== null) {
+ resultList = resultList.concat(result[0]);
+
+ if (result[1][0]) {
+ resultList = resultList.concat(result[1][0]);
+ }
+
+ return resultList;
+ }
+
+ debug(' -- failed rangeList');
+
+ return null;
+ }
+
+ function rangeTail() {
+ // ',' range_list
+ var result = sequence([_comma_, rangeList]);
+
+ if (result !== null) {
+ return result[1];
+ }
+
+ debug(' -- failed rangeTail');
+
+ return null;
+ }
+
+ // range = value'..'value
+ function range() {
+ var i, array, left, right,
+ result = sequence([value, _range_, value]);
+
+ if (result !== null) {
+ debug(' -- passed range');
+
+ array = [];
+ left = parseInt(result[0], 10);
+ right = parseInt(result[2], 10);
+
+ for (i = left; i <= right; i++) {
+ array.push(i);
+ }
+
+ return array;
+ }
+
+ debug(' -- failed range');
+
+ return null;
+ }
+
+ function _in() {
+ var result, range_list, i;
+
+ // in_relation = expr ('not')? 'in' range_list
+ result = sequence(
+ [expression, nOrMore(0, not), whitespace, choice([_in_, _equal_]), whitespace, rangeList]
+ );
+
+ if (result !== null) {
+ debug(' -- passed _in:' + result);
+
+ range_list = result[5];
+
+ for (i = 0; i < range_list.length; i++) {
+ if (parseInt(range_list[i], 10) === parseInt(result[0], 10)) {
+ return (result[1][0] !== 'not');
+ }
+ }
+
+ return (result[1][0] === 'not');
+ }
+
+ debug(' -- failed _in ');
+
+ return null;
+ }
+
+ /**
+ * The difference between "in" and "within" is that
+ * "in" only includes integers in the specified range,
+ * while "within" includes all values.
+ */
+ function within() {
+ var range_list, result;
+
+ // within_relation = expr ('not')? 'within' range_list
+ result = sequence(
+ [expression, nOrMore(0, not), whitespace, _within_, whitespace, rangeList]
+ );
+
+ if (result !== null) {
+ debug(' -- passed within');
+
+ range_list = result[5];
+
+ if ((result[0] >= parseInt(range_list[0], 10)) &&
+ (result[0] < parseInt(range_list[range_list.length - 1], 10))) {
+
+ return (result[1][0] !== 'not');
+ }
+
+ return (result[1][0] === 'not');
+ }
+
+ debug(' -- failed within ');
+
+ return null;
+ }
+
+ // relation = is_relation | in_relation | within_relation
+ relation = choice([is, not_in, isnot, _in, within]);
+
+ // and_condition = relation ('and' relation)*
+ function and() {
+ var i,
+ result = sequence([relation, nOrMore(0, andTail)]);
+
+ if (result) {
+ if (!result[0]) {
+ return false;
+ }
+
+ for (i = 0; i < result[1].length; i++) {
+ if (!result[1][i]) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ debug(' -- failed and');
+
+ return null;
+ }
+
+ // ('and' relation)*
+ function andTail() {
+ var result = sequence([whitespace, _and_, whitespace, relation]);
+
+ if (result !== null) {
+ debug(' -- passed andTail' + result);
+
+ return result[3];
+ }
+
+ debug(' -- failed andTail');
+
+ return null;
+
+ }
+ // ('or' and_condition)*
+ function orTail() {
+ var result = sequence([whitespace, _or_, whitespace, and]);
+
+ if (result !== null) {
+ debug(' -- passed orTail: ' + result[3]);
+
+ return result[3];
+ }
+
+ debug(' -- failed orTail');
+
+ return null;
+ }
+
+ // condition = and_condition ('or' and_condition)*
+ function condition() {
+ var i,
+ result = sequence([and, nOrMore(0, orTail)]);
+
+ if (result) {
+ for (i = 0; i < result[1].length; i++) {
+ if (result[1][i]) {
+ return true;
+ }
+ }
+
+ return result[0];
+ }
+
+ return false;
+ }
+
+ result = condition();
+
+ /**
+ * For success, the pos must have gotten to the end of the rule
+ * and returned a non-null.
+ * n.b. This is part of language infrastructure,
+ * so we do not throw an internationalizable message.
+ */
+ if (result === null) {
+ throw new Error('Parse error at position ' + pos.toString() + ' for rule: ' + rule);
+ }
+
+ if (pos !== rule.length) {
+ debug('Warning: Rule not parsed completely. Parser stopped at ' + rule.substr(0, pos) + ' for rule: ' + rule);
+ }
+
+ return result;
+}
+
+/* pluralRuleParser ends here */
+mw.libs.pluralRuleParser = pluralRuleParser;
+module.exports = pluralRuleParser;
+
+} )( mediaWiki );
diff --git a/www/wiki/resources/src/mediawiki.libs/mediawiki.libs.jpegmeta.js b/www/wiki/resources/src/mediawiki.libs/mediawiki.libs.jpegmeta.js
new file mode 100644
index 00000000..67460ad7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.libs/mediawiki.libs.jpegmeta.js
@@ -0,0 +1,737 @@
+/**
+ * This is JsJpegMeta v1.0
+ * From: https://code.google.com/p/jsjpegmeta/downloads/list
+ * From: https://github.com/bennoleslie/jsjpegmeta/blob/v1.0.0/jpegmeta.js
+ *
+ * Ported to MediaWiki ResourceLoader by Bryan Tong Minh
+ * Changes:
+ * - Add closure.
+ * - Add this.JpegMeta assignment to expose it as global.
+ * - Add mw.libs.jpegmeta wrapper.
+ */
+
+( function ( mw ) {
+ /*
+ Copyright (c) 2009 Ben Leslie
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+ /*
+ This JavaScript library is used to parse meta-data from files
+ with mime-type image/jpeg.
+
+ Include it with something like:
+
+ <script type="text/javascript" src="jpegmeta.js"></script>
+
+ This adds a single 'module' object called 'JpegMeta' to the global
+ namespace.
+
+ Public Functions
+ ----------------
+ JpegMeta.parseNum - parse unsigned integers from binary data
+ JpegMeta.parseSnum - parse signed integers from binary data
+
+ Public Classes
+ --------------
+ JpegMeta.Rational - A rational number class
+ JpegMeta.JfifSegment
+ JpegMeta.ExifSegment
+ JpegMeta.JpegFile - Primary class for Javascript parsing
+ */
+
+ var JpegMeta = {};
+ // MediaWiki: Expose as global
+ this.JpegMeta = JpegMeta;
+
+ /*
+ parse an unsigned number of size bytes at offset in some binary string data.
+ If endian
+ is "<" parse the data as little endian, if endian
+ is ">" parse as big-endian.
+ */
+ JpegMeta.parseNum = function parseNum(endian, data, offset, size) {
+ var i;
+ var ret;
+ var big_endian = (endian === ">");
+ if (offset === undefined) offset = 0;
+ if (size === undefined) size = data.length - offset;
+ for (big_endian ? i = offset : i = offset + size - 1;
+ big_endian ? i < offset + size : i >= offset;
+ big_endian ? i++ : i--) {
+ ret <<= 8;
+ ret += data.charCodeAt(i);
+ }
+ return ret;
+ };
+
+ /*
+ parse an signed number of size bytes at offset in some binary string data.
+ If endian
+ is "<" parse the data as little endian, if endian
+ is ">" parse as big-endian.
+ */
+ JpegMeta.parseSnum = function parseSnum(endian, data, offset, size) {
+ var i;
+ var ret;
+ var neg;
+ var big_endian = (endian === ">");
+ if (offset === undefined) offset = 0;
+ if (size === undefined) size = data.length - offset;
+ for (big_endian ? i = offset : i = offset + size - 1;
+ big_endian ? i < offset + size : i >= offset;
+ big_endian ? i++ : i--) {
+ if (neg === undefined) {
+ /* Negative if top bit is set */
+ neg = (data.charCodeAt(i) & 0x80) === 0x80;
+ }
+ ret <<= 8;
+ /* If it is negative we invert the bits */
+ ret += neg ? ~data.charCodeAt(i) & 0xff: data.charCodeAt(i);
+ }
+ if (neg) {
+ /* If it is negative we do two's complement */
+ ret += 1;
+ ret *= -1;
+ }
+ return ret;
+ };
+
+ /* Rational number class */
+ JpegMeta.Rational = function Rational(num, den)
+ {
+ this.num = num;
+ this.den = den || 1;
+ return this;
+ };
+
+ /* Rational number methods */
+ JpegMeta.Rational.prototype.toString = function toString() {
+ if (this.num === 0) {
+ return "" + this.num;
+ }
+ if (this.den === 1) {
+ return "" + this.num;
+ }
+ if (this.num === 1) {
+ return this.num + " / " + this.den;
+ }
+ return this.num / this.den; // + "/" + this.den;
+ };
+
+ JpegMeta.Rational.prototype.asFloat = function asFloat() {
+ return this.num / this.den;
+ };
+
+ /* MetaGroup class */
+ JpegMeta.MetaGroup = function MetaGroup(fieldName, description) {
+ this.fieldName = fieldName;
+ this.description = description;
+ this.metaProps = {};
+ return this;
+ };
+
+ JpegMeta.MetaGroup.prototype._addProperty = function _addProperty(fieldName, description, value) {
+ var property = new JpegMeta.MetaProp(fieldName, description, value);
+ this[property.fieldName] = property;
+ this.metaProps[property.fieldName] = property;
+ };
+
+ JpegMeta.MetaGroup.prototype.toString = function toString() {
+ return "[MetaGroup " + this.description + "]";
+ };
+
+ /* MetaProp class */
+ JpegMeta.MetaProp = function MetaProp(fieldName, description, value) {
+ this.fieldName = fieldName;
+ this.description = description;
+ this.value = value;
+ return this;
+ };
+
+ JpegMeta.MetaProp.prototype.toString = function toString() {
+ return "" + this.value;
+ };
+
+ /* JpegFile class */
+ JpegMeta.JpegFile = function JpegFile(binary_data, filename) {
+ /* Change this to EOI if we want to parse. */
+ var break_segment = this._SOS;
+
+ this.metaGroups = {};
+ this._binary_data = binary_data;
+ this.filename = filename;
+
+ /* Go through and parse. */
+ var pos = 0;
+ var pos_start_of_segment = 0;
+ var delim;
+ var mark;
+ var _mark;
+ var segsize;
+ var headersize;
+ var mark_code;
+ var mark_fn;
+
+ /* Check to see if this looks like a JPEG file */
+ if (this._binary_data.slice(0, 2) !== this._SOI_MARKER) {
+ throw new Error("Doesn't look like a JPEG file. First two bytes are " +
+ this._binary_data.charCodeAt(0) + "," +
+ this._binary_data.charCodeAt(1) + ".");
+ }
+
+ pos += 2;
+
+ while (pos < this._binary_data.length) {
+ delim = this._binary_data.charCodeAt(pos++);
+ mark = this._binary_data.charCodeAt(pos++);
+
+ pos_start_of_segment = pos;
+
+ if (delim != this._DELIM) {
+ break;
+ }
+
+ if (mark === break_segment) {
+ break;
+ }
+
+ headersize = JpegMeta.parseNum(">", this._binary_data, pos, 2);
+
+ /* Find the end */
+ pos += headersize;
+ while (pos < this._binary_data.length) {
+ delim = this._binary_data.charCodeAt(pos++);
+ if (delim == this._DELIM) {
+ _mark = this._binary_data.charCodeAt(pos++);
+ if (_mark != 0x0) {
+ pos -= 2;
+ break;
+ }
+ }
+ }
+
+ segsize = pos - pos_start_of_segment;
+
+ if (this._markers[mark]) {
+ mark_code = this._markers[mark][0];
+ mark_fn = this._markers[mark][1];
+ } else {
+ mark_code = "UNKN";
+ mark_fn = undefined;
+ }
+
+ if (mark_fn) {
+ this[mark_fn](mark, pos_start_of_segment + 2);
+ }
+
+ }
+
+ if (this.general === undefined) {
+ throw Error("Invalid JPEG file.");
+ }
+
+ return this;
+ };
+
+ this.JpegMeta.JpegFile.prototype.toString = function () {
+ return "[JpegFile " + this.filename + " " +
+ this.general.type + " " +
+ this.general.pixelWidth + "x" +
+ this.general.pixelHeight +
+ " Depth: " + this.general.depth + "]";
+ };
+
+ /* Some useful constants */
+ this.JpegMeta.JpegFile.prototype._SOI_MARKER = '\xff\xd8';
+ this.JpegMeta.JpegFile.prototype._DELIM = 0xff;
+ this.JpegMeta.JpegFile.prototype._EOI = 0xd9;
+ this.JpegMeta.JpegFile.prototype._SOS = 0xda;
+
+ this.JpegMeta.JpegFile.prototype._sofHandler = function _sofHandler (mark, pos) {
+ if (this.general !== undefined) {
+ throw Error("Unexpected multiple-frame image");
+ }
+
+ this._addMetaGroup("general", "General");
+ this.general._addProperty("depth", "Depth", JpegMeta.parseNum(">", this._binary_data, pos, 1));
+ this.general._addProperty("pixelHeight", "Pixel Height", JpegMeta.parseNum(">", this._binary_data, pos + 1, 2));
+ this.general._addProperty("pixelWidth", "Pixel Width",JpegMeta.parseNum(">", this._binary_data, pos + 3, 2));
+ this.general._addProperty("type", "Type", this._markers[mark][2]);
+ };
+
+ /* JFIF idents */
+ this.JpegMeta.JpegFile.prototype._JFIF_IDENT = "JFIF\x00";
+ this.JpegMeta.JpegFile.prototype._JFXX_IDENT = "JFXX\x00";
+
+ /* Exif idents */
+ this.JpegMeta.JpegFile.prototype._EXIF_IDENT = "Exif\x00";
+
+ /* TIFF types */
+ this.JpegMeta.JpegFile.prototype._types = {
+ /* The format is identifier : ["type name", type_size_in_bytes ] */
+ 1 : ["BYTE", 1],
+ 2 : ["ASCII", 1],
+ 3 : ["SHORT", 2],
+ 4 : ["LONG", 4],
+ 5 : ["RATIONAL", 8],
+ 6 : ["SBYTE", 1],
+ 7 : ["UNDEFINED", 1],
+ 8 : ["SSHORT", 2],
+ 9 : ["SLONG", 4],
+ 10 : ["SRATIONAL", 8],
+ 11 : ["FLOAT", 4],
+ 12 : ["DOUBLE", 8]
+ };
+
+ this.JpegMeta.JpegFile.prototype._tifftags = {
+ /* A. Tags relating to image data structure */
+ 256 : ["Image width", "ImageWidth"],
+ 257 : ["Image height", "ImageLength"],
+ 258 : ["Number of bits per component", "BitsPerSample"],
+ 259 : ["Compression scheme", "Compression",
+ {1 : "uncompressed", 6 : "JPEG compression" }],
+ 262 : ["Pixel composition", "PhotmetricInerpretation",
+ {2 : "RGB", 6 : "YCbCr"}],
+ 274 : ["Orientation of image", "Orientation",
+ /* FIXME: Check the mirror-image / reverse encoding and rotation */
+ {1 : "Normal", 2 : "Reverse?",
+ 3 : "Upside-down", 4 : "Upside-down Reverse",
+ 5 : "90 degree CW", 6 : "90 degree CW reverse",
+ 7 : "90 degree CCW", 8 : "90 degree CCW reverse"}],
+ 277 : ["Number of components", "SamplesPerPixel"],
+ 284 : ["Image data arrangement", "PlanarConfiguration",
+ {1 : "chunky format", 2 : "planar format"}],
+ 530 : ["Subsampling ratio of Y to C", "YCbCrSubSampling"],
+ 531 : ["Y and C positioning", "YCbCrPositioning",
+ {1 : "centered", 2 : "co-sited"}],
+ 282 : ["X Resolution", "XResolution"],
+ 283 : ["Y Resolution", "YResolution"],
+ 296 : ["Resolution Unit", "ResolutionUnit",
+ {2 : "inches", 3 : "centimeters"}],
+ /* B. Tags realting to recording offset */
+ 273 : ["Image data location", "StripOffsets"],
+ 278 : ["Number of rows per strip", "RowsPerStrip"],
+ 279 : ["Bytes per compressed strip", "StripByteCounts"],
+ 513 : ["Offset to JPEG SOI", "JPEGInterchangeFormat"],
+ 514 : ["Bytes of JPEG Data", "JPEGInterchangeFormatLength"],
+ /* C. Tags relating to image data characteristics */
+ 301 : ["Transfer function", "TransferFunction"],
+ 318 : ["White point chromaticity", "WhitePoint"],
+ 319 : ["Chromaticities of primaries", "PrimaryChromaticities"],
+ 529 : ["Color space transformation matrix coefficients", "YCbCrCoefficients"],
+ 532 : ["Pair of black and white reference values", "ReferenceBlackWhite"],
+ /* D. Other tags */
+ 306 : ["Date and time", "DateTime"],
+ 270 : ["Image title", "ImageDescription"],
+ 271 : ["Make", "Make"],
+ 272 : ["Model", "Model"],
+ 305 : ["Software", "Software"],
+ 315 : ["Person who created the image", "Artist"],
+ 316 : ["Host Computer", "HostComputer"],
+ 33432 : ["Copyright holder", "Copyright"],
+
+ 34665 : ["Exif tag", "ExifIfdPointer"],
+ 34853 : ["GPS tag", "GPSInfoIfdPointer"]
+ };
+
+ this.JpegMeta.JpegFile.prototype._exiftags = {
+ /* Tag Support Levels (2) - 0th IFX Exif Private Tags */
+ /* A. Tags Relating to Version */
+ 36864 : ["Exif Version", "ExifVersion"],
+ 40960 : ["FlashPix Version", "FlashpixVersion"],
+
+ /* B. Tag Relating to Image Data Characteristics */
+ 40961 : ["Color Space", "ColorSpace"],
+
+ /* C. Tags Relating to Image Configuration */
+ 37121 : ["Meaning of each component", "ComponentsConfiguration"],
+ 37122 : ["Compressed Bits Per Pixel", "CompressedBitsPerPixel"],
+ 40962 : ["Pixel X Dimension", "PixelXDimension"],
+ 40963 : ["Pixel Y Dimension", "PixelYDimension"],
+
+ /* D. Tags Relating to User Information */
+ 37500 : ["Manufacturer notes", "MakerNote"],
+ 37510 : ["User comments", "UserComment"],
+
+ /* E. Tag Relating to Related File Information */
+ 40964 : ["Related audio file", "RelatedSoundFile"],
+
+ /* F. Tags Relating to Date and Time */
+ 36867 : ["Date Time Original", "DateTimeOriginal"],
+ 36868 : ["Date Time Digitized", "DateTimeDigitized"],
+ 37520 : ["DateTime subseconds", "SubSecTime"],
+ 37521 : ["DateTimeOriginal subseconds", "SubSecTimeOriginal"],
+ 37522 : ["DateTimeDigitized subseconds", "SubSecTimeDigitized"],
+
+ /* G. Tags Relating to Picture-Taking Conditions */
+ 33434 : ["Exposure time", "ExposureTime"],
+ 33437 : ["FNumber", "FNumber"],
+ 34850 : ["Exposure program", "ExposureProgram"],
+ 34852 : ["Spectral sensitivity", "SpectralSensitivity"],
+ 34855 : ["ISO Speed Ratings", "ISOSpeedRatings"],
+ 34856 : ["Optoelectric coefficient", "OECF"],
+ 37377 : ["Shutter Speed", "ShutterSpeedValue"],
+ 37378 : ["Aperture Value", "ApertureValue"],
+ 37379 : ["Brightness", "BrightnessValue"],
+ 37380 : ["Exposure Bias Value", "ExposureBiasValue"],
+ 37381 : ["Max Aperture Value", "MaxApertureValue"],
+ 37382 : ["Subject Distance", "SubjectDistance"],
+ 37383 : ["Metering Mode", "MeteringMode"],
+ 37384 : ["Light Source", "LightSource"],
+ 37385 : ["Flash", "Flash"],
+ 37386 : ["Focal Length", "FocalLength"],
+ 37396 : ["Subject Area", "SubjectArea"],
+ 41483 : ["Flash Energy", "FlashEnergy"],
+ 41484 : ["Spatial Frequency Response", "SpatialFrequencyResponse"],
+ 41486 : ["Focal Plane X Resolution", "FocalPlaneXResolution"],
+ 41487 : ["Focal Plane Y Resolution", "FocalPlaneYResolution"],
+ 41488 : ["Focal Plane Resolution Unit", "FocalPlaneResolutionUnit"],
+ 41492 : ["Subject Location", "SubjectLocation"],
+ 41493 : ["Exposure Index", "ExposureIndex"],
+ 41495 : ["Sensing Method", "SensingMethod"],
+ 41728 : ["File Source", "FileSource"],
+ 41729 : ["Scene Type", "SceneType"],
+ 41730 : ["CFA Pattern", "CFAPattern"],
+ 41985 : ["Custom Rendered", "CustomRendered"],
+ 41986 : ["Exposure Mode", "Exposure Mode"],
+ 41987 : ["White Balance", "WhiteBalance"],
+ 41988 : ["Digital Zoom Ratio", "DigitalZoomRatio"],
+ 41990 : ["Scene Capture Type", "SceneCaptureType"],
+ 41991 : ["Gain Control", "GainControl"],
+ 41992 : ["Contrast", "Contrast"],
+ 41993 : ["Saturation", "Saturation"],
+ 41994 : ["Sharpness", "Sharpness"],
+ 41995 : ["Device settings description", "DeviceSettingDescription"],
+ 41996 : ["Subject distance range", "SubjectDistanceRange"],
+
+ /* H. Other Tags */
+ 42016 : ["Unique image ID", "ImageUniqueID"],
+
+ 40965 : ["Interoperability tag", "InteroperabilityIFDPointer"]
+ };
+
+ this.JpegMeta.JpegFile.prototype._gpstags = {
+ /* A. Tags Relating to GPS */
+ 0 : ["GPS tag version", "GPSVersionID"],
+ 1 : ["North or South Latitude", "GPSLatitudeRef"],
+ 2 : ["Latitude", "GPSLatitude"],
+ 3 : ["East or West Longitude", "GPSLongitudeRef"],
+ 4 : ["Longitude", "GPSLongitude"],
+ 5 : ["Altitude reference", "GPSAltitudeRef"],
+ 6 : ["Altitude", "GPSAltitude"],
+ 7 : ["GPS time (atomic clock)", "GPSTimeStamp"],
+ 8 : ["GPS satellites usedd for measurement", "GPSSatellites"],
+ 9 : ["GPS receiver status", "GPSStatus"],
+ 10 : ["GPS mesaurement mode", "GPSMeasureMode"],
+ 11 : ["Measurement precision", "GPSDOP"],
+ 12 : ["Speed unit", "GPSSpeedRef"],
+ 13 : ["Speed of GPS receiver", "GPSSpeed"],
+ 14 : ["Reference for direction of movement", "GPSTrackRef"],
+ 15 : ["Direction of movement", "GPSTrack"],
+ 16 : ["Reference for direction of image", "GPSImgDirectionRef"],
+ 17 : ["Direction of image", "GPSImgDirection"],
+ 18 : ["Geodetic survey data used", "GPSMapDatum"],
+ 19 : ["Reference for latitude of destination", "GPSDestLatitudeRef"],
+ 20 : ["Latitude of destination", "GPSDestLatitude"],
+ 21 : ["Reference for longitude of destination", "GPSDestLongitudeRef"],
+ 22 : ["Longitude of destination", "GPSDestLongitude"],
+ 23 : ["Reference for bearing of destination", "GPSDestBearingRef"],
+ 24 : ["Bearing of destination", "GPSDestBearing"],
+ 25 : ["Reference for distance to destination", "GPSDestDistanceRef"],
+ 26 : ["Distance to destination", "GPSDestDistance"],
+ 27 : ["Name of GPS processing method", "GPSProcessingMethod"],
+ 28 : ["Name of GPS area", "GPSAreaInformation"],
+ 29 : ["GPS Date", "GPSDateStamp"],
+ 30 : ["GPS differential correction", "GPSDifferential"]
+ };
+
+ this.JpegMeta.JpegFile.prototype._markers = {
+ /* Start Of Frame markers, non-differential, Huffman coding */
+ 0xc0: ["SOF0", "_sofHandler", "Baseline DCT"],
+ 0xc1: ["SOF1", "_sofHandler", "Extended sequential DCT"],
+ 0xc2: ["SOF2", "_sofHandler", "Progressive DCT"],
+ 0xc3: ["SOF3", "_sofHandler", "Lossless (sequential)"],
+
+ /* Start Of Frame markers, differential, Huffman coding */
+ 0xc5: ["SOF5", "_sofHandler", "Differential sequential DCT"],
+ 0xc6: ["SOF6", "_sofHandler", "Differential progressive DCT"],
+ 0xc7: ["SOF7", "_sofHandler", "Differential lossless (sequential)"],
+
+ /* Start Of Frame markers, non-differential, arithmetic coding */
+ 0xc8: ["JPG", null, "Reserved for JPEG extensions"],
+ 0xc9: ["SOF9", "_sofHandler", "Extended sequential DCT"],
+ 0xca: ["SOF10", "_sofHandler", "Progressive DCT"],
+ 0xcb: ["SOF11", "_sofHandler", "Lossless (sequential)"],
+
+ /* Start Of Frame markers, differential, arithmetic coding */
+ 0xcd: ["SOF13", "_sofHandler", "Differential sequential DCT"],
+ 0xce: ["SOF14", "_sofHandler", "Differential progressive DCT"],
+ 0xcf: ["SOF15", "_sofHandler", "Differential lossless (sequential)"],
+
+ /* Huffman table specification */
+ 0xc4: ["DHT", null, "Define Huffman table(s)"],
+ 0xcc: ["DAC", null, "Define arithmetic coding conditioning(s)"],
+
+ /* Restart interval termination" */
+ 0xd0: ["RST0", null, "Restart with modulo 8 count “0”"],
+ 0xd1: ["RST1", null, "Restart with modulo 8 count “1”"],
+ 0xd2: ["RST2", null, "Restart with modulo 8 count “2”"],
+ 0xd3: ["RST3", null, "Restart with modulo 8 count “3”"],
+ 0xd4: ["RST4", null, "Restart with modulo 8 count “4”"],
+ 0xd5: ["RST5", null, "Restart with modulo 8 count “5”"],
+ 0xd6: ["RST6", null, "Restart with modulo 8 count “6”"],
+ 0xd7: ["RST7", null, "Restart with modulo 8 count “7”"],
+
+ /* Other markers */
+ 0xd8: ["SOI", null, "Start of image"],
+ 0xd9: ["EOI", null, "End of image"],
+ 0xda: ["SOS", null, "Start of scan"],
+ 0xdb: ["DQT", null, "Define quantization table(s)"],
+ 0xdc: ["DNL", null, "Define number of lines"],
+ 0xdd: ["DRI", null, "Define restart interval"],
+ 0xde: ["DHP", null, "Define hierarchical progression"],
+ 0xdf: ["EXP", null, "Expand reference component(s)"],
+ 0xe0: ["APP0", "_app0Handler", "Reserved for application segments"],
+ 0xe1: ["APP1", "_app1Handler"],
+ 0xe2: ["APP2", null],
+ 0xe3: ["APP3", null],
+ 0xe4: ["APP4", null],
+ 0xe5: ["APP5", null],
+ 0xe6: ["APP6", null],
+ 0xe7: ["APP7", null],
+ 0xe8: ["APP8", null],
+ 0xe9: ["APP9", null],
+ 0xea: ["APP10", null],
+ 0xeb: ["APP11", null],
+ 0xec: ["APP12", null],
+ 0xed: ["APP13", null],
+ 0xee: ["APP14", null],
+ 0xef: ["APP15", null],
+ 0xf0: ["JPG0", null], /* Reserved for JPEG extensions */
+ 0xf1: ["JPG1", null],
+ 0xf2: ["JPG2", null],
+ 0xf3: ["JPG3", null],
+ 0xf4: ["JPG4", null],
+ 0xf5: ["JPG5", null],
+ 0xf6: ["JPG6", null],
+ 0xf7: ["JPG7", null],
+ 0xf8: ["JPG8", null],
+ 0xf9: ["JPG9", null],
+ 0xfa: ["JPG10", null],
+ 0xfb: ["JPG11", null],
+ 0xfc: ["JPG12", null],
+ 0xfd: ["JPG13", null],
+ 0xfe: ["COM", null], /* Comment */
+
+ /* Reserved markers */
+ 0x01: ["JPG13", null] /* For temporary private use in arithmetic coding */
+ /* 02 -> bf are reserverd */
+ };
+
+ /* Private methods */
+ this.JpegMeta.JpegFile.prototype._addMetaGroup = function _addMetaGroup(name, description) {
+ var group = new JpegMeta.MetaGroup(name, description);
+ this[group.fieldName] = group;
+ this.metaGroups[group.fieldName] = group;
+ return group;
+ };
+
+ this.JpegMeta.JpegFile.prototype._parseIfd = function _parseIfd(endian, _binary_data, base, ifd_offset, tags, name, description) {
+ var num_fields = JpegMeta.parseNum(endian, _binary_data, base + ifd_offset, 2);
+ /* Per tag variables */
+ var i, j;
+ var tag_base;
+ var tag_field;
+ var type, type_field, type_size;
+ var num_values;
+ var value_offset;
+ var value;
+ var _val;
+ var num;
+ var den;
+
+ var group;
+
+ group = this._addMetaGroup(name, description);
+
+ for (var i = 0; i < num_fields; i++) {
+ /* parse the field */
+ tag_base = base + ifd_offset + 2 + (i * 12);
+ tag_field = JpegMeta.parseNum(endian, _binary_data, tag_base, 2);
+ type_field = JpegMeta.parseNum(endian, _binary_data, tag_base + 2, 2);
+ num_values = JpegMeta.parseNum(endian, _binary_data, tag_base + 4, 4);
+ value_offset = JpegMeta.parseNum(endian, _binary_data, tag_base + 8, 4);
+ if (this._types[type_field] === undefined) {
+ continue;
+ }
+ type = this._types[type_field][0];
+ type_size = this._types[type_field][1];
+
+ if (type_size * num_values <= 4) {
+ /* Data is in-line */
+ value_offset = tag_base + 8;
+ } else {
+ value_offset = base + value_offset;
+ }
+
+ /* Read the value */
+ if (type == "UNDEFINED") {
+ value = _binary_data.slice(value_offset, value_offset + num_values);
+ } else if (type == "ASCII") {
+ value = _binary_data.slice(value_offset, value_offset + num_values);
+ value = value.split('\x00')[0];
+ /* strip trail nul */
+ } else {
+ value = new Array();
+ for (j = 0; j < num_values; j++, value_offset += type_size) {
+ if (type == "BYTE" || type == "SHORT" || type == "LONG") {
+ value.push(JpegMeta.parseNum(endian, _binary_data, value_offset, type_size));
+ }
+ if (type == "SBYTE" || type == "SSHORT" || type == "SLONG") {
+ value.push(JpegMeta.parseSnum(endian, _binary_data, value_offset, type_size));
+ }
+ if (type == "RATIONAL") {
+ num = JpegMeta.parseNum(endian, _binary_data, value_offset, 4);
+ den = JpegMeta.parseNum(endian, _binary_data, value_offset + 4, 4);
+ value.push(new JpegMeta.Rational(num, den));
+ }
+ if (type == "SRATIONAL") {
+ num = JpegMeta.parseSnum(endian, _binary_data, value_offset, 4);
+ den = JpegMeta.parseSnum(endian, _binary_data, value_offset + 4, 4);
+ value.push(new JpegMeta.Rational(num, den));
+ }
+ value.push();
+ }
+ if (num_values === 1) {
+ value = value[0];
+ }
+ }
+ if (tags[tag_field] !== undefined) {
+ group._addProperty(tags[tag_field][1], tags[tag_field][0], value);
+ }
+ }
+ };
+
+ this.JpegMeta.JpegFile.prototype._jfifHandler = function _jfifHandler(mark, pos) {
+ if (this.jfif !== undefined) {
+ throw Error("Multiple JFIF segments found");
+ }
+ this._addMetaGroup("jfif", "JFIF");
+ this.jfif._addProperty("version_major", "Version Major", this._binary_data.charCodeAt(pos + 5));
+ this.jfif._addProperty("version_minor", "Version Minor", this._binary_data.charCodeAt(pos + 6));
+ this.jfif._addProperty("version", "JFIF Version", this.jfif.version_major.value + "." + this.jfif.version_minor.value);
+ this.jfif._addProperty("units", "Density Unit", this._binary_data.charCodeAt(pos + 7));
+ this.jfif._addProperty("Xdensity", "X density", JpegMeta.parseNum(">", this._binary_data, pos + 8, 2));
+ this.jfif._addProperty("Ydensity", "Y Density", JpegMeta.parseNum(">", this._binary_data, pos + 10, 2));
+ this.jfif._addProperty("Xthumbnail", "X Thumbnail", JpegMeta.parseNum(">", this._binary_data, pos + 12, 1));
+ this.jfif._addProperty("Ythumbnail", "Y Thumbnail", JpegMeta.parseNum(">", this._binary_data, pos + 13, 1));
+ };
+
+ /* Handle app0 segments */
+ this.JpegMeta.JpegFile.prototype._app0Handler = function app0Handler(mark, pos) {
+ var ident = this._binary_data.slice(pos, pos + 5);
+ if (ident == this._JFIF_IDENT) {
+ this._jfifHandler(mark, pos);
+ } else if (ident == this._JFXX_IDENT) {
+ /* Don't handle JFXX Ident yet */
+ } else {
+ /* Don't know about other idents */
+ }
+ };
+
+ /* Handle app1 segments */
+ this.JpegMeta.JpegFile.prototype._app1Handler = function _app1Handler(mark, pos) {
+ var ident = this._binary_data.slice(pos, pos + 5);
+ if (ident == this._EXIF_IDENT) {
+ this._exifHandler(mark, pos + 6);
+ } else {
+ /* Don't know about other idents */
+ }
+ };
+
+ /* Handle exif segments */
+ JpegMeta.JpegFile.prototype._exifHandler = function _exifHandler(mark, pos) {
+ if (this.exif !== undefined) {
+ throw new Error("Multiple JFIF segments found");
+ }
+
+ /* Parse this TIFF header */
+ var endian;
+ var magic_field;
+ var ifd_offset;
+ var primary_ifd, exif_ifd, gps_ifd;
+ var endian_field = this._binary_data.slice(pos, pos + 2);
+
+ /* Trivia: This 'I' is for Intel, the 'M' is for Motorola */
+ if (endian_field === "II") {
+ endian = "<";
+ } else if (endian_field === "MM") {
+ endian = ">";
+ } else {
+ throw new Error("Malformed TIFF meta-data. Unknown endianess: " + endian_field);
+ }
+
+ magic_field = JpegMeta.parseNum(endian, this._binary_data, pos + 2, 2);
+
+ if (magic_field !== 42) {
+ throw new Error("Malformed TIFF meta-data. Bad magic: " + magic_field);
+ }
+
+ ifd_offset = JpegMeta.parseNum(endian, this._binary_data, pos + 4, 4);
+
+ /* Parse 0th IFD */
+ this._parseIfd(endian, this._binary_data, pos, ifd_offset, this._tifftags, "tiff", "TIFF");
+
+ if (this.tiff.ExifIfdPointer) {
+ this._parseIfd(endian, this._binary_data, pos, this.tiff.ExifIfdPointer.value, this._exiftags, "exif", "Exif");
+ }
+
+ if (this.tiff.GPSInfoIfdPointer) {
+ this._parseIfd(endian, this._binary_data, pos, this.tiff.GPSInfoIfdPointer.value, this._gpstags, "gps", "GPS");
+ if (this.gps.GPSLatitude) {
+ var latitude;
+ latitude = this.gps.GPSLatitude.value[0].asFloat() +
+ (1 / 60) * this.gps.GPSLatitude.value[1].asFloat() +
+ (1 / 3600) * this.gps.GPSLatitude.value[2].asFloat();
+ if (this.gps.GPSLatitudeRef.value === "S") {
+ latitude = -latitude;
+ }
+ this.gps._addProperty("latitude", "Dec. Latitude", latitude);
+ }
+ if (this.gps.GPSLongitude) {
+ var longitude;
+ longitude = this.gps.GPSLongitude.value[0].asFloat() +
+ (1 / 60) * this.gps.GPSLongitude.value[1].asFloat() +
+ (1 / 3600) * this.gps.GPSLongitude.value[2].asFloat();
+ if (this.gps.GPSLongitudeRef.value === "W") {
+ longitude = -longitude;
+ }
+ this.gps._addProperty("longitude", "Dec. Longitude", longitude);
+ }
+ }
+ };
+
+ // MediaWiki: Add mw.libs wrapper
+ mw.libs.jpegmeta = function( fileReaderResult, fileName ) {
+ return new JpegMeta.JpegFile( fileReaderResult, fileName );
+ };
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.MessagePoster.js b/www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.MessagePoster.js
new file mode 100644
index 00000000..64642b26
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.MessagePoster.js
@@ -0,0 +1,40 @@
+( function ( mw ) {
+ /**
+ * This is the abstract base class for MessagePoster implementations.
+ *
+ * @abstract
+ * @class
+ *
+ * @constructor
+ * @param {mw.Title} title Title to post to
+ */
+ mw.messagePoster.MessagePoster = function MwMessagePoster() {};
+
+ OO.initClass( mw.messagePoster.MessagePoster );
+
+ /**
+ * Post a message (with subject and body) to a talk page.
+ *
+ * @abstract
+ * @param {string} subject Subject/topic title. The amount of wikitext supported is
+ * implementation-specific. It is recommended to only use basic wikilink syntax for
+ * maximum compatibility.
+ * @param {string} body Body, as wikitext. Signature code will automatically be added
+ * by MessagePosters that require one, unless the message already contains the string
+ * ~~~.
+ * @return {jQuery.Promise} Promise completing when the post succeeds or fails.
+ * For failure, will be rejected with three arguments:
+ *
+ * - primaryError - Primary error code. For a mw.Api failure,
+ * this should be 'api-fail'.
+ * - secondaryError - Secondary error code. For a mw.Api failure,
+ * this, should be mw.Api's code, e.g. 'http', 'ok-but-empty', or the error passed through
+ * from the server.
+ * - details - Further details about the error
+ *
+ * @localdoc
+ * The base class currently does nothing, but could be used for shared analytics or
+ * something.
+ */
+ mw.messagePoster.MessagePoster.prototype.post = function () {};
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.WikitextMessagePoster.js b/www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.WikitextMessagePoster.js
new file mode 100644
index 00000000..a2dbcd49
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.WikitextMessagePoster.js
@@ -0,0 +1,53 @@
+( function ( mw, $ ) {
+ /**
+ * This is an implementation of MessagePoster for wikitext talk pages.
+ *
+ * @class mw.messagePoster.WikitextMessagePoster
+ * @extends mw.messagePoster.MessagePoster
+ *
+ * @constructor
+ * @param {mw.Title} title Wikitext page in a talk namespace, to post to
+ * @param {mw.Api} api mw.Api object to use
+ */
+ function WikitextMessagePoster( title, api ) {
+ this.api = api;
+ this.title = title;
+ }
+
+ OO.inheritClass(
+ WikitextMessagePoster,
+ mw.messagePoster.MessagePoster
+ );
+
+ /**
+ * @inheritdoc
+ */
+ WikitextMessagePoster.prototype.post = function ( subject, body ) {
+ mw.messagePoster.WikitextMessagePoster.parent.prototype.post.call( this, subject, body );
+
+ // Add signature if needed
+ if ( body.indexOf( '~~~' ) === -1 ) {
+ body += '\n\n~~~~';
+ }
+
+ return this.api.newSection(
+ this.title,
+ subject,
+ body,
+ { redirect: true }
+ ).then( function ( resp, jqXHR ) {
+ if ( resp.edit.result === 'Success' ) {
+ return $.Deferred().resolve( resp, jqXHR );
+ } else {
+ // mw.Api checks for response error. Are there actually cases where the
+ // request fails, but it's not caught there?
+ return $.Deferred().reject( 'api-unexpected' );
+ }
+ }, function ( code, details ) {
+ return $.Deferred().reject( 'api-fail', code, details );
+ } ).promise();
+ };
+
+ mw.messagePoster.factory.register( 'wikitext', WikitextMessagePoster );
+ mw.messagePoster.WikitextMessagePoster = WikitextMessagePoster;
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.factory.js b/www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.factory.js
new file mode 100644
index 00000000..e20b422f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.messagePoster/mediawiki.messagePoster.factory.js
@@ -0,0 +1,107 @@
+( function ( mw, $ ) {
+ /**
+ * Factory for MessagePoster objects. This provides a pluggable to way to script the action
+ * of adding a message to someone's talk page.
+ *
+ * @class mw.messagePoster.factory
+ * @singleton
+ */
+ function MessagePosterFactory() {
+ this.contentModelToClass = {};
+ }
+
+ OO.initClass( MessagePosterFactory );
+
+ // Note: This registration scheme is currently not compatible with LQT, since that doesn't
+ // have its own content model, just islqttalkpage. LQT pages will be passed to the wikitext
+ // MessagePoster.
+ /**
+ * Register a MessagePoster subclass for a given content model.
+ *
+ * @param {string} contentModel Content model of pages this MessagePoster can post to
+ * @param {Function} constructor Constructor of a MessagePoster subclass
+ */
+ MessagePosterFactory.prototype.register = function ( contentModel, constructor ) {
+ if ( this.contentModelToClass[ contentModel ] !== undefined ) {
+ throw new Error( 'Content model "' + contentModel + '" is already registered' );
+ }
+
+ this.contentModelToClass[ contentModel ] = constructor;
+ };
+
+ /**
+ * Unregister a given content model.
+ * This is exposed for testing and should not normally be used.
+ *
+ * @param {string} contentModel Content model to unregister
+ */
+ MessagePosterFactory.prototype.unregister = function ( contentModel ) {
+ delete this.contentModelToClass[ contentModel ];
+ };
+
+ /**
+ * Create a MessagePoster for given a title.
+ *
+ * A promise for this is returned. It works by determining the content model, then loading
+ * the corresponding module (which registers the MessagePoster class), and finally constructing
+ * an object for the given title.
+ *
+ * This does not require the message and should be called as soon as possible, so that the
+ * API and ResourceLoader requests run in the background.
+ *
+ * @param {mw.Title} title Title that will be posted to
+ * @param {string} [apiUrl] api.php URL if the title is on another wiki
+ * @return {jQuery.Promise} Promise resolving to a mw.messagePoster.MessagePoster.
+ * For failure, rejected with up to three arguments:
+ *
+ * - errorCode Error code string
+ * - error Error explanation
+ * - details Further error details
+ */
+ MessagePosterFactory.prototype.create = function ( title, apiUrl ) {
+ var factory = this,
+ api = apiUrl ? new mw.ForeignApi( apiUrl ) : new mw.Api();
+
+ return api.get( {
+ formatversion: 2,
+ action: 'query',
+ prop: 'info',
+ titles: title.getPrefixedDb()
+ } ).then( function ( data ) {
+ var contentModel, moduleName, page = data.query.pages[ 0 ];
+ if ( !page ) {
+ return $.Deferred().reject( 'unexpected-response', 'Unexpected API response' );
+ }
+ contentModel = page.contentmodel;
+ moduleName = 'mediawiki.messagePoster.' + contentModel;
+ return mw.loader.using( moduleName ).then( function () {
+ return factory.createForContentModel(
+ contentModel,
+ title,
+ api
+ );
+ }, function () {
+ return $.Deferred().reject( 'failed-to-load-module', 'Failed to load "' + moduleName + '"' );
+ } );
+ }, function ( error, details ) {
+ return $.Deferred().reject( 'content-model-query-failed', error, details );
+ } );
+ };
+
+ /**
+ * Creates a MessagePoster instance, given a title and content model
+ *
+ * @private
+ * @param {string} contentModel Content model of title
+ * @param {mw.Title} title Title being posted to
+ * @param {mw.Api} api mw.Api instance that the instance should use
+ * @return {mw.messagePoster.MessagePoster}
+ */
+ MessagePosterFactory.prototype.createForContentModel = function ( contentModel, title, api ) {
+ return new this.contentModelToClass[ contentModel ]( title, api );
+ };
+
+ mw.messagePoster = {
+ factory: new MessagePosterFactory()
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js
new file mode 100644
index 00000000..0155a587
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ChangesListViewModel.js
@@ -0,0 +1,160 @@
+( function ( mw ) {
+ /**
+ * View model for the changes list
+ *
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ */
+ mw.rcfilters.dm.ChangesListViewModel = function MwRcfiltersDmChangesListViewModel() {
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ this.valid = true;
+ this.newChangesExist = false;
+ this.nextFrom = null;
+ this.liveUpdate = false;
+ this.unseenWatchedChanges = false;
+ };
+
+ /* Initialization */
+ OO.initClass( mw.rcfilters.dm.ChangesListViewModel );
+ OO.mixinClass( mw.rcfilters.dm.ChangesListViewModel, OO.EventEmitter );
+
+ /* Events */
+
+ /**
+ * @event invalidate
+ *
+ * The list of changes is now invalid (out of date)
+ */
+
+ /**
+ * @event update
+ * @param {jQuery|string} $changesListContent List of changes
+ * @param {jQuery} $fieldset Server-generated form
+ * @param {boolean} isInitialDOM Whether the previous dom variables are from the initial page load
+ * @param {boolean} fromLiveUpdate These are new changes fetched via Live Update
+ *
+ * The list of changes has been updated
+ */
+
+ /**
+ * @event newChangesExist
+ * @param {boolean} newChangesExist
+ *
+ * The existence of changes newer than those currently displayed has changed.
+ */
+
+ /**
+ * @event liveUpdateChange
+ * @param {boolean} enable
+ *
+ * The state of the 'live update' feature has changed.
+ */
+
+ /* Methods */
+
+ /**
+ * Invalidate the list of changes
+ *
+ * @fires invalidate
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.invalidate = function () {
+ if ( this.valid ) {
+ this.valid = false;
+ this.emit( 'invalidate' );
+ }
+ };
+
+ /**
+ * Update the model with an updated list of changes
+ *
+ * @param {jQuery|string} changesListContent
+ * @param {jQuery} $fieldset
+ * @param {boolean} [isInitialDOM] Using the initial (already attached) DOM elements
+ * @param {boolean} [separateOldAndNew] Whether a logical separation between old and new changes is needed
+ * @fires update
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.update = function ( changesListContent, $fieldset, isInitialDOM, separateOldAndNew ) {
+ var from = this.nextFrom;
+ this.valid = true;
+ this.extractNextFrom( $fieldset );
+ this.checkForUnseenWatchedChanges( changesListContent );
+ this.emit( 'update', changesListContent, $fieldset, isInitialDOM, separateOldAndNew ? from : null );
+ };
+
+ /**
+ * Specify whether new changes exist
+ *
+ * @param {boolean} newChangesExist
+ * @fires newChangesExist
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.setNewChangesExist = function ( newChangesExist ) {
+ if ( newChangesExist !== this.newChangesExist ) {
+ this.newChangesExist = newChangesExist;
+ this.emit( 'newChangesExist', newChangesExist );
+ }
+ };
+
+ /**
+ * @return {boolean} Whether new changes exist
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.getNewChangesExist = function () {
+ return this.newChangesExist;
+ };
+
+ /**
+ * Extract the value of the 'from' parameter from a link in the field set
+ *
+ * @param {jQuery} $fieldset
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.extractNextFrom = function ( $fieldset ) {
+ var data = $fieldset.find( '.rclistfrom > a' ).data( 'params' );
+ this.nextFrom = data ? data.from : null;
+ };
+
+ /**
+ * @return {string} The 'from' parameter that can be used to query new changes
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.getNextFrom = function () {
+ return this.nextFrom;
+ };
+
+ /**
+ * Toggle the 'live update' feature on/off
+ *
+ * @param {boolean} enable
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.toggleLiveUpdate = function ( enable ) {
+ enable = enable === undefined ? !this.liveUpdate : enable;
+ if ( enable !== this.liveUpdate ) {
+ this.liveUpdate = enable;
+ this.emit( 'liveUpdateChange', this.liveUpdate );
+ }
+ };
+
+ /**
+ * @return {boolean} The 'live update' feature is enabled
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.getLiveUpdate = function () {
+ return this.liveUpdate;
+ };
+
+ /**
+ * Check if some of the given changes watched and unseen
+ *
+ * @param {jQuery|string} changeslistContent
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.checkForUnseenWatchedChanges = function ( changeslistContent ) {
+ this.unseenWatchedChanges = changeslistContent !== 'NO_RESULTS' &&
+ changeslistContent.find( '.mw-changeslist-line-watched' ).length > 0;
+ };
+
+ /**
+ * @return {boolean} Whether some of the current changes are watched and unseen
+ */
+ mw.rcfilters.dm.ChangesListViewModel.prototype.hasUnseenWatchedChanges = function () {
+ return this.unseenWatchedChanges;
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js
new file mode 100644
index 00000000..4dc86f6f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js
@@ -0,0 +1,892 @@
+( function ( mw ) {
+ /**
+ * View model for a filter group
+ *
+ * @mixins OO.EventEmitter
+ * @mixins OO.EmitterList
+ *
+ * @constructor
+ * @param {string} name Group name
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [type='send_unselected_if_any'] Group type
+ * @cfg {string} [view='default'] Name of the display group this group
+ * is a part of.
+ * @cfg {boolean} [isSticky] This group is using a 'sticky' default; meaning
+ * that every time a value is changed, it becomes the new default
+ * @cfg {boolean} [excludedFromSavedQueries] A specific requirement to exclude
+ * this filter from saved queries. This is always true if the filter is 'sticky'
+ * but can be used for non-sticky filters as an additional requirement. Similarly
+ * to 'sticky' it works for the entire group as a whole.
+ * @cfg {string} [title] Group title
+ * @cfg {boolean} [hidden] This group is hidden from the regular menu views
+ * @cfg {boolean} [allowArbitrary] Allows for an arbitrary value to be added to the
+ * group from the URL, even if it wasn't initially set up.
+ * @cfg {number} [range] An object defining minimum and maximum values for numeric
+ * groups. { min: x, max: y }
+ * @cfg {number} [minValue] Minimum value for numeric groups
+ * @cfg {string} [separator='|'] Value separator for 'string_options' groups
+ * @cfg {boolean} [active] Group is active
+ * @cfg {boolean} [fullCoverage] This filters in this group collectively cover all results
+ * @cfg {Object} [conflicts] Defines the conflicts for this filter group
+ * @cfg {string|Object} [labelPrefixKey] An i18n key defining the prefix label for this
+ * group. If the prefix has 'invert' state, the parameter is expected to be an object
+ * with 'default' and 'inverted' as keys.
+ * @cfg {Object} [whatsThis] Defines the messages that should appear for the 'what's this' popup
+ * @cfg {string} [whatsThis.header] The header of the whatsThis popup message
+ * @cfg {string} [whatsThis.body] The body of the whatsThis popup message
+ * @cfg {string} [whatsThis.url] The url for the link in the whatsThis popup message
+ * @cfg {string} [whatsThis.linkMessage] The text for the link in the whatsThis popup message
+ */
+ mw.rcfilters.dm.FilterGroup = function MwRcfiltersDmFilterGroup( name, config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+ OO.EmitterList.call( this );
+
+ this.name = name;
+ this.type = config.type || 'send_unselected_if_any';
+ this.view = config.view || 'default';
+ this.sticky = !!config.isSticky;
+ this.excludedFromSavedQueries = this.sticky || !!config.excludedFromSavedQueries;
+ this.title = config.title || name;
+ this.hidden = !!config.hidden;
+ this.allowArbitrary = !!config.allowArbitrary;
+ this.numericRange = config.range;
+ this.separator = config.separator || '|';
+ this.labelPrefixKey = config.labelPrefixKey;
+
+ this.currSelected = null;
+ this.active = !!config.active;
+ this.fullCoverage = !!config.fullCoverage;
+
+ this.whatsThis = config.whatsThis || {};
+
+ this.conflicts = config.conflicts || {};
+ this.defaultParams = {};
+ this.defaultFilters = {};
+
+ this.aggregate( { update: 'filterItemUpdate' } );
+ this.connect( this, { filterItemUpdate: 'onFilterItemUpdate' } );
+ };
+
+ /* Initialization */
+ OO.initClass( mw.rcfilters.dm.FilterGroup );
+ OO.mixinClass( mw.rcfilters.dm.FilterGroup, OO.EventEmitter );
+ OO.mixinClass( mw.rcfilters.dm.FilterGroup, OO.EmitterList );
+
+ /* Events */
+
+ /**
+ * @event update
+ *
+ * Group state has been updated
+ */
+
+ /* Methods */
+
+ /**
+ * Initialize the group and create its filter items
+ *
+ * @param {Object} filterDefinition Filter definition for this group
+ * @param {string|Object} [groupDefault] Definition of the group default
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.initializeFilters = function ( filterDefinition, groupDefault ) {
+ var defaultParam,
+ supersetMap = {},
+ model = this,
+ items = [];
+
+ filterDefinition.forEach( function ( filter ) {
+ // Instantiate an item
+ var subsetNames = [],
+ filterItem = new mw.rcfilters.dm.FilterItem( filter.name, model, {
+ group: model.getName(),
+ label: filter.label || filter.name,
+ description: filter.description || '',
+ labelPrefixKey: model.labelPrefixKey,
+ cssClass: filter.cssClass,
+ identifiers: filter.identifiers
+ } );
+
+ if ( filter.subset ) {
+ filter.subset = filter.subset.map( function ( el ) {
+ return el.filter;
+ } );
+
+ subsetNames = [];
+
+ filter.subset.forEach( function ( subsetFilterName ) { // eslint-disable-line no-loop-func
+ // Subsets (unlike conflicts) are always inside the same group
+ // We can re-map the names of the filters we are getting from
+ // the subsets with the group prefix
+ var subsetName = model.getPrefixedName( subsetFilterName );
+ // For convenience, we should store each filter's "supersets" -- these are
+ // the filters that have that item in their subset list. This will just
+ // make it easier to go through whether the item has any other items
+ // that affect it (and are selected) at any given time
+ supersetMap[ subsetName ] = supersetMap[ subsetName ] || [];
+ mw.rcfilters.utils.addArrayElementsUnique(
+ supersetMap[ subsetName ],
+ filterItem.getName()
+ );
+
+ // Translate subset param name to add the group name, so we
+ // get consistent naming. We know that subsets are only within
+ // the same group
+ subsetNames.push( subsetName );
+ } );
+
+ // Set translated subset
+ filterItem.setSubset( subsetNames );
+ }
+
+ items.push( filterItem );
+
+ // Store default parameter state; in this case, default is defined per filter
+ if (
+ model.getType() === 'send_unselected_if_any' ||
+ model.getType() === 'boolean'
+ ) {
+ // Store the default parameter state
+ // For this group type, parameter values are direct
+ // We need to convert from a boolean to a string ('1' and '0')
+ model.defaultParams[ filter.name ] = String( Number( filter.default || 0 ) );
+ }
+ } );
+
+ // Add items
+ this.addItems( items );
+
+ // Now that we have all items, we can apply the superset map
+ this.getItems().forEach( function ( filterItem ) {
+ filterItem.setSuperset( supersetMap[ filterItem.getName() ] );
+ } );
+
+ // Store default parameter state; in this case, default is defined per the
+ // entire group, given by groupDefault method parameter
+ if ( this.getType() === 'string_options' ) {
+ // Store the default parameter group state
+ // For this group, the parameter is group name and value is the names
+ // of selected items
+ this.defaultParams[ this.getName() ] = mw.rcfilters.utils.normalizeParamOptions(
+ // Current values
+ groupDefault ?
+ groupDefault.split( this.getSeparator() ) :
+ [],
+ // Legal values
+ this.getItems().map( function ( item ) {
+ return item.getParamName();
+ } )
+ ).join( this.getSeparator() );
+ } else if ( this.getType() === 'single_option' ) {
+ defaultParam = groupDefault !== undefined ?
+ groupDefault : this.getItems()[ 0 ].getParamName();
+
+ // For this group, the parameter is the group name,
+ // and a single item can be selected: default or first item
+ this.defaultParams[ this.getName() ] = defaultParam;
+ }
+
+ // Store default filter state based on default params
+ this.defaultFilters = this.getFilterRepresentation( this.getDefaultParams() );
+
+ // Check for filters that should be initially selected by their default value
+ if ( this.isSticky() ) {
+ $.each( this.defaultFilters, function ( filterName, filterValue ) {
+ model.getItemByName( filterName ).toggleSelected( filterValue );
+ } );
+ }
+
+ // Verify that single_option group has at least one item selected
+ if (
+ this.getType() === 'single_option' &&
+ this.getSelectedItems().length === 0
+ ) {
+ defaultParam = groupDefault !== undefined ?
+ groupDefault : this.getItems()[ 0 ].getParamName();
+
+ // Single option means there must be a single option
+ // selected, so we have to either select the default
+ // or select the first option
+ this.selectItemByParamName( defaultParam );
+ }
+ };
+
+ /**
+ * Respond to filterItem update event
+ *
+ * @param {mw.rcfilters.dm.FilterItem} item Updated filter item
+ * @fires update
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.onFilterItemUpdate = function ( item ) {
+ // Update state
+ var changed = false,
+ active = this.areAnySelected(),
+ model = this;
+
+ if ( this.getType() === 'single_option' ) {
+ // This group must have one item selected always
+ // and must never have more than one item selected at a time
+ if ( this.getSelectedItems().length === 0 ) {
+ // Nothing is selected anymore
+ // Select the default or the first item
+ this.currSelected = this.getItemByParamName( this.defaultParams[ this.getName() ] ) ||
+ this.getItems()[ 0 ];
+ this.currSelected.toggleSelected( true );
+ changed = true;
+ } else if ( this.getSelectedItems().length > 1 ) {
+ // There is more than one item selected
+ // This should only happen if the item given
+ // is the one that is selected, so unselect
+ // all items that is not it
+ this.getSelectedItems().forEach( function ( itemModel ) {
+ // Note that in case the given item is actually
+ // not selected, this loop will end up unselecting
+ // all items, which would trigger the case above
+ // when the last item is unselected anyways
+ var selected = itemModel.getName() === item.getName() &&
+ item.isSelected();
+
+ itemModel.toggleSelected( selected );
+ if ( selected ) {
+ model.currSelected = itemModel;
+ }
+ } );
+ changed = true;
+ }
+ }
+
+ if (
+ changed ||
+ this.active !== active ||
+ this.currSelected !== item
+ ) {
+ if ( this.isSticky() ) {
+ // If this group is sticky, then change the default according to the
+ // current selection.
+ this.defaultParams = this.getParamRepresentation( this.getSelectedState() );
+ }
+
+ this.active = active;
+ this.currSelected = item;
+
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Get group active state
+ *
+ * @return {boolean} Active state
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.isActive = function () {
+ return this.active;
+ };
+
+ /**
+ * Get group hidden state
+ *
+ * @return {boolean} Hidden state
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.isHidden = function () {
+ return this.hidden;
+ };
+
+ /**
+ * Get group allow arbitrary state
+ *
+ * @return {boolean} Group allows an arbitrary value from the URL
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.isAllowArbitrary = function () {
+ return this.allowArbitrary;
+ };
+
+ /**
+ * Get group maximum value for numeric groups
+ *
+ * @return {number|null} Group max value
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getMaxValue = function () {
+ return this.numericRange && this.numericRange.max !== undefined ?
+ this.numericRange.max : null;
+ };
+
+ /**
+ * Get group minimum value for numeric groups
+ *
+ * @return {number|null} Group max value
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getMinValue = function () {
+ return this.numericRange && this.numericRange.min !== undefined ?
+ this.numericRange.min : null;
+ };
+
+ /**
+ * Get group name
+ *
+ * @return {string} Group name
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getName = function () {
+ return this.name;
+ };
+
+ /**
+ * Get the default param state of this group
+ *
+ * @return {Object} Default param state
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getDefaultParams = function () {
+ return this.defaultParams;
+ };
+
+ /**
+ * Get the default filter state of this group
+ *
+ * @return {Object} Default filter state
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getDefaultFilters = function () {
+ return this.defaultFilters;
+ };
+
+ /**
+ * This is for a single_option and string_options group types
+ * it returns the value of the default
+ *
+ * @return {string} Value of the default
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getDefaulParamValue = function () {
+ return this.defaultParams[ this.getName() ];
+ };
+ /**
+ * Get the messags defining the 'whats this' popup for this group
+ *
+ * @return {Object} What's this messages
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getWhatsThis = function () {
+ return this.whatsThis;
+ };
+
+ /**
+ * Check whether this group has a 'what's this' message
+ *
+ * @return {boolean} This group has a what's this message
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.hasWhatsThis = function () {
+ return !!this.whatsThis.body;
+ };
+
+ /**
+ * Get the conflicts associated with the entire group.
+ * Conflict object is set up by filter name keys and conflict
+ * definition. For example:
+ * [
+ * {
+ * filterName: {
+ * filter: filterName,
+ * group: group1
+ * }
+ * },
+ * {
+ * filterName2: {
+ * filter: filterName2,
+ * group: group2
+ * }
+ * }
+ * ]
+ * @return {Object} Conflict definition
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getConflicts = function () {
+ return this.conflicts;
+ };
+
+ /**
+ * Set conflicts for this group. See #getConflicts for the expected
+ * structure of the definition.
+ *
+ * @param {Object} conflicts Conflicts for this group
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.setConflicts = function ( conflicts ) {
+ this.conflicts = conflicts;
+ };
+
+ /**
+ * Set conflicts for each filter item in the group based on the
+ * given conflict map
+ *
+ * @param {Object} conflicts Object representing the conflict map,
+ * keyed by the item name, where its value is an object for all its conflicts
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.setFilterConflicts = function ( conflicts ) {
+ this.getItems().forEach( function ( filterItem ) {
+ if ( conflicts[ filterItem.getName() ] ) {
+ filterItem.setConflicts( conflicts[ filterItem.getName() ] );
+ }
+ } );
+ };
+
+ /**
+ * Check whether this item has a potential conflict with the given item
+ *
+ * This checks whether the given item is in the list of conflicts of
+ * the current item, but makes no judgment about whether the conflict
+ * is currently at play (either one of the items may not be selected)
+ *
+ * @param {mw.rcfilters.dm.FilterItem} filterItem Filter item
+ * @return {boolean} This item has a conflict with the given item
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.existsInConflicts = function ( filterItem ) {
+ return Object.prototype.hasOwnProperty.call( this.getConflicts(), filterItem.getName() );
+ };
+
+ /**
+ * Check whether there are any items selected
+ *
+ * @return {boolean} Any items in the group are selected
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.areAnySelected = function () {
+ return this.getItems().some( function ( filterItem ) {
+ return filterItem.isSelected();
+ } );
+ };
+
+ /**
+ * Check whether all items selected
+ *
+ * @return {boolean} All items are selected
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.areAllSelected = function () {
+ var selected = [],
+ unselected = [];
+
+ this.getItems().forEach( function ( filterItem ) {
+ if ( filterItem.isSelected() ) {
+ selected.push( filterItem );
+ } else {
+ unselected.push( filterItem );
+ }
+ } );
+
+ if ( unselected.length === 0 ) {
+ return true;
+ }
+
+ // check if every unselected is a subset of a selected
+ return unselected.every( function ( unselectedFilterItem ) {
+ return selected.some( function ( selectedFilterItem ) {
+ return selectedFilterItem.existsInSubset( unselectedFilterItem.getName() );
+ } );
+ } );
+ };
+
+ /**
+ * Get all selected items in this group
+ *
+ * @param {mw.rcfilters.dm.FilterItem} [excludeItem] Item to exclude from the list
+ * @return {mw.rcfilters.dm.FilterItem[]} Selected items
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getSelectedItems = function ( excludeItem ) {
+ var excludeName = ( excludeItem && excludeItem.getName() ) || '';
+
+ return this.getItems().filter( function ( item ) {
+ return item.getName() !== excludeName && item.isSelected();
+ } );
+ };
+
+ /**
+ * Check whether all selected items are in conflict with the given item
+ *
+ * @param {mw.rcfilters.dm.FilterItem} filterItem Filter item to test
+ * @return {boolean} All selected items are in conflict with this item
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.areAllSelectedInConflictWith = function ( filterItem ) {
+ var selectedItems = this.getSelectedItems( filterItem );
+
+ return selectedItems.length > 0 &&
+ (
+ // The group as a whole is in conflict with this item
+ this.existsInConflicts( filterItem ) ||
+ // All selected items are in conflict individually
+ selectedItems.every( function ( selectedFilter ) {
+ return selectedFilter.existsInConflicts( filterItem );
+ } )
+ );
+ };
+
+ /**
+ * Check whether any of the selected items are in conflict with the given item
+ *
+ * @param {mw.rcfilters.dm.FilterItem} filterItem Filter item to test
+ * @return {boolean} Any of the selected items are in conflict with this item
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.areAnySelectedInConflictWith = function ( filterItem ) {
+ var selectedItems = this.getSelectedItems( filterItem );
+
+ return selectedItems.length > 0 && (
+ // The group as a whole is in conflict with this item
+ this.existsInConflicts( filterItem ) ||
+ // Any selected items are in conflict individually
+ selectedItems.some( function ( selectedFilter ) {
+ return selectedFilter.existsInConflicts( filterItem );
+ } )
+ );
+ };
+
+ /**
+ * Get the parameter representation from this group
+ *
+ * @param {Object} [filterRepresentation] An object defining the state
+ * of the filters in this group, keyed by their name and current selected
+ * state value.
+ * @return {Object} Parameter representation
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getParamRepresentation = function ( filterRepresentation ) {
+ var values,
+ areAnySelected = false,
+ buildFromCurrentState = !filterRepresentation,
+ defaultFilters = this.getDefaultFilters(),
+ result = {},
+ model = this,
+ filterParamNames = {},
+ getSelectedParameter = function ( filters ) {
+ var item,
+ selected = [];
+
+ // Find if any are selected
+ $.each( filters, function ( name, value ) {
+ if ( value ) {
+ selected.push( name );
+ }
+ } );
+
+ item = model.getItemByName( selected[ 0 ] );
+ return ( item && item.getParamName() ) || '';
+ };
+
+ filterRepresentation = filterRepresentation || {};
+
+ // Create or complete the filterRepresentation definition
+ this.getItems().forEach( function ( item ) {
+ // Map filter names to their parameter names
+ filterParamNames[ item.getName() ] = item.getParamName();
+
+ if ( buildFromCurrentState ) {
+ // This means we have not been given a filter representation
+ // so we are building one based on current state
+ filterRepresentation[ item.getName() ] = item.isSelected();
+ } else if ( filterRepresentation[ item.getName() ] === undefined ) {
+ // We are given a filter representation, but we have to make
+ // sure that we fill in the missing filters if there are any
+ // we will assume they are all falsey
+ if ( model.isSticky() ) {
+ filterRepresentation[ item.getName() ] = !!defaultFilters[ item.getName() ];
+ } else {
+ filterRepresentation[ item.getName() ] = false;
+ }
+ }
+
+ if ( filterRepresentation[ item.getName() ] ) {
+ areAnySelected = true;
+ }
+ } );
+
+ // Build result
+ if (
+ this.getType() === 'send_unselected_if_any' ||
+ this.getType() === 'boolean'
+ ) {
+ // First, check if any of the items are selected at all.
+ // If none is selected, we're treating it as if they are
+ // all false
+
+ // Go over the items and define the correct values
+ $.each( filterRepresentation, function ( name, value ) {
+ // We must store all parameter values as strings '0' or '1'
+ if ( model.getType() === 'send_unselected_if_any' ) {
+ result[ filterParamNames[ name ] ] = areAnySelected ?
+ String( Number( !value ) ) :
+ '0';
+ } else if ( model.getType() === 'boolean' ) {
+ // Representation is straight-forward and direct from
+ // the parameter value to the filter state
+ result[ filterParamNames[ name ] ] = String( Number( !!value ) );
+ }
+ } );
+ } else if ( this.getType() === 'string_options' ) {
+ values = [];
+
+ $.each( filterRepresentation, function ( name, value ) {
+ // Collect values
+ if ( value ) {
+ values.push( filterParamNames[ name ] );
+ }
+ } );
+
+ result[ this.getName() ] = ( values.length === Object.keys( filterRepresentation ).length ) ?
+ 'all' : values.join( this.getSeparator() );
+ } else if ( this.getType() === 'single_option' ) {
+ result[ this.getName() ] = getSelectedParameter( filterRepresentation );
+ }
+
+ return result;
+ };
+
+ /**
+ * Get the filter representation this group would provide
+ * based on given parameter states.
+ *
+ * @param {Object} [paramRepresentation] An object defining a parameter
+ * state to translate the filter state from. If not given, an object
+ * representing all filters as falsey is returned; same as if the parameter
+ * given were an empty object, or had some of the filters missing.
+ * @return {Object} Filter representation
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getFilterRepresentation = function ( paramRepresentation ) {
+ var areAnySelected, paramValues, item, currentValue,
+ oneWasSelected = false,
+ defaultParams = this.getDefaultParams(),
+ expandedParams = $.extend( true, {}, paramRepresentation ),
+ model = this,
+ paramToFilterMap = {},
+ result = {};
+
+ if ( this.isSticky() ) {
+ // If the group is sticky, check if all parameters are represented
+ // and for those that aren't represented, add them with their default
+ // values
+ paramRepresentation = $.extend( true, {}, this.getDefaultParams(), paramRepresentation );
+ }
+
+ paramRepresentation = paramRepresentation || {};
+ if (
+ this.getType() === 'send_unselected_if_any' ||
+ this.getType() === 'boolean'
+ ) {
+ // Go over param representation; map and check for selections
+ this.getItems().forEach( function ( filterItem ) {
+ var paramName = filterItem.getParamName();
+
+ expandedParams[ paramName ] = paramRepresentation[ paramName ] || '0';
+ paramToFilterMap[ paramName ] = filterItem;
+
+ if ( Number( paramRepresentation[ filterItem.getParamName() ] ) ) {
+ areAnySelected = true;
+ }
+ } );
+
+ $.each( expandedParams, function ( paramName, paramValue ) {
+ var filterItem = paramToFilterMap[ paramName ];
+
+ if ( model.getType() === 'send_unselected_if_any' ) {
+ // Flip the definition between the parameter
+ // state and the filter state
+ // This is what the 'toggleSelected' value of the filter is
+ result[ filterItem.getName() ] = areAnySelected ?
+ !Number( paramValue ) :
+ // Otherwise, there are no selected items in the
+ // group, which means the state is false
+ false;
+ } else if ( model.getType() === 'boolean' ) {
+ // Straight-forward definition of state
+ result[ filterItem.getName() ] = !!Number( paramRepresentation[ filterItem.getParamName() ] );
+ }
+ } );
+ } else if ( this.getType() === 'string_options' ) {
+ currentValue = paramRepresentation[ this.getName() ] || '';
+
+ // Normalize the given parameter values
+ paramValues = mw.rcfilters.utils.normalizeParamOptions(
+ // Given
+ currentValue.split(
+ this.getSeparator()
+ ),
+ // Allowed values
+ this.getItems().map( function ( filterItem ) {
+ return filterItem.getParamName();
+ } )
+ );
+ // Translate the parameter values into a filter selection state
+ this.getItems().forEach( function ( filterItem ) {
+ // All true (either because all values are written or the term 'all' is written)
+ // is the same as all filters set to true
+ result[ filterItem.getName() ] = (
+ // If it is the word 'all'
+ paramValues.length === 1 && paramValues[ 0 ] === 'all' ||
+ // All values are written
+ paramValues.length === model.getItemCount()
+ ) ?
+ true :
+ // Otherwise, the filter is selected only if it appears in the parameter values
+ paramValues.indexOf( filterItem.getParamName() ) > -1;
+ } );
+ } else if ( this.getType() === 'single_option' ) {
+ // There is parameter that fits a single filter and if not, get the default
+ this.getItems().forEach( function ( filterItem ) {
+ var selected = filterItem.getParamName() === paramRepresentation[ model.getName() ];
+
+ result[ filterItem.getName() ] = selected;
+ oneWasSelected = oneWasSelected || selected;
+ } );
+ }
+
+ // Go over result and make sure all filters are represented.
+ // If any filters are missing, they will get a falsey value
+ this.getItems().forEach( function ( filterItem ) {
+ if ( result[ filterItem.getName() ] === undefined ) {
+ result[ filterItem.getName() ] = false;
+ }
+ } );
+
+ // Make sure that at least one option is selected in
+ // single_option groups, no matter what path was taken
+ // If none was selected by the given definition, then
+ // we need to select the one in the base state -- either
+ // the default given, or the first item
+ if (
+ this.getType() === 'single_option' &&
+ !oneWasSelected
+ ) {
+ item = this.getItems()[ 0 ];
+ if ( defaultParams[ this.getName() ] ) {
+ item = this.getItemByParamName( defaultParams[ this.getName() ] );
+ }
+
+ result[ item.getName() ] = true;
+ }
+
+ return result;
+ };
+
+ /**
+ * Get current selected state of all filter items in this group
+ *
+ * @return {Object} Selected state
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getSelectedState = function () {
+ var state = {};
+
+ this.getItems().forEach( function ( filterItem ) {
+ state[ filterItem.getName() ] = filterItem.isSelected();
+ } );
+
+ return state;
+ };
+
+ /**
+ * Get item by its filter name
+ *
+ * @param {string} filterName Filter name
+ * @return {mw.rcfilters.dm.FilterItem} Filter item
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getItemByName = function ( filterName ) {
+ return this.getItems().filter( function ( item ) {
+ return item.getName() === filterName;
+ } )[ 0 ];
+ };
+
+ /**
+ * Select an item by its parameter name
+ *
+ * @param {string} paramName Filter parameter name
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.selectItemByParamName = function ( paramName ) {
+ this.getItems().forEach( function ( item ) {
+ item.toggleSelected( item.getParamName() === String( paramName ) );
+ } );
+ };
+
+ /**
+ * Get item by its parameter name
+ *
+ * @param {string} paramName Parameter name
+ * @return {mw.rcfilters.dm.FilterItem} Filter item
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getItemByParamName = function ( paramName ) {
+ return this.getItems().filter( function ( item ) {
+ return item.getParamName() === String( paramName );
+ } )[ 0 ];
+ };
+
+ /**
+ * Get group type
+ *
+ * @return {string} Group type
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getType = function () {
+ return this.type;
+ };
+
+ /**
+ * Get display group
+ *
+ * @return {string} Display group
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getView = function () {
+ return this.view;
+ };
+
+ /**
+ * Get the prefix used for the filter names inside this group.
+ *
+ * @param {string} [name] Filter name to prefix
+ * @return {string} Group prefix
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getNamePrefix = function () {
+ return this.getName() + '__';
+ };
+
+ /**
+ * Get a filter name with the prefix used for the filter names inside this group.
+ *
+ * @param {string} name Filter name to prefix
+ * @return {string} Group prefix
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getPrefixedName = function ( name ) {
+ return this.getNamePrefix() + name;
+ };
+
+ /**
+ * Get group's title
+ *
+ * @return {string} Title
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getTitle = function () {
+ return this.title;
+ };
+
+ /**
+ * Get group's values separator
+ *
+ * @return {string} Values separator
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.getSeparator = function () {
+ return this.separator;
+ };
+
+ /**
+ * Check whether the group is defined as full coverage
+ *
+ * @return {boolean} Group is full coverage
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.isFullCoverage = function () {
+ return this.fullCoverage;
+ };
+
+ /**
+ * Check whether the group is defined as sticky default
+ *
+ * @return {boolean} Group is sticky default
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.isSticky = function () {
+ return this.sticky;
+ };
+
+ /**
+ * Check whether the group value is excluded from saved queries
+ *
+ * @return {boolean} Group value is excluded from saved queries
+ */
+ mw.rcfilters.dm.FilterGroup.prototype.isExcludedFromSavedQueries = function () {
+ return this.excludedFromSavedQueries;
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js
new file mode 100644
index 00000000..4e2079dc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js
@@ -0,0 +1,372 @@
+( function ( mw ) {
+ /**
+ * Filter item model
+ *
+ * @extends mw.rcfilters.dm.ItemModel
+ *
+ * @constructor
+ * @param {string} param Filter param name
+ * @param {mw.rcfilters.dm.FilterGroup} groupModel Filter group model
+ * @param {Object} config Configuration object
+ * @cfg {string[]} [excludes=[]] A list of filter names this filter, if
+ * selected, makes inactive.
+ * @cfg {string[]} [subset] Defining the names of filters that are a subset of this filter
+ * @cfg {Object} [conflicts] Defines the conflicts for this filter
+ */
+ mw.rcfilters.dm.FilterItem = function MwRcfiltersDmFilterItem( param, groupModel, config ) {
+ config = config || {};
+
+ this.groupModel = groupModel;
+
+ // Parent
+ mw.rcfilters.dm.FilterItem.parent.call( this, param, $.extend( {
+ namePrefix: this.groupModel.getNamePrefix()
+ }, config ) );
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ // Interaction definitions
+ this.subset = config.subset || [];
+ this.conflicts = config.conflicts || {};
+ this.superset = [];
+
+ // Interaction states
+ this.included = false;
+ this.conflicted = false;
+ this.fullyCovered = false;
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.dm.FilterItem, mw.rcfilters.dm.ItemModel );
+
+ /* Methods */
+
+ /**
+ * Return the representation of the state of this item.
+ *
+ * @return {Object} State of the object
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getState = function () {
+ return {
+ selected: this.isSelected(),
+ included: this.isIncluded(),
+ conflicted: this.isConflicted(),
+ fullyCovered: this.isFullyCovered()
+ };
+ };
+
+ /**
+ * Get the message for the display area for the currently active conflict
+ *
+ * @private
+ * @return {string} Conflict result message key
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getCurrentConflictResultMessage = function () {
+ var details = {};
+
+ // First look in filter's own conflicts
+ details = this.getConflictDetails( this.getOwnConflicts(), 'globalDescription' );
+ if ( !details.message ) {
+ // Fall back onto conflicts in the group
+ details = this.getConflictDetails( this.getGroupModel().getConflicts(), 'globalDescription' );
+ }
+
+ return details.message;
+ };
+
+ /**
+ * Get the details of the active conflict on this filter
+ *
+ * @private
+ * @param {Object} conflicts Conflicts to examine
+ * @param {string} [key='contextDescription'] Message key
+ * @return {Object} Object with conflict message and conflict items
+ * @return {string} return.message Conflict message
+ * @return {string[]} return.names Conflicting item labels
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getConflictDetails = function ( conflicts, key ) {
+ var group,
+ conflictMessage = '',
+ itemLabels = [];
+
+ key = key || 'contextDescription';
+
+ $.each( conflicts, function ( filterName, conflict ) {
+ if ( !conflict.item.isSelected() ) {
+ return;
+ }
+
+ if ( !conflictMessage ) {
+ conflictMessage = conflict[ key ];
+ group = conflict.group;
+ }
+
+ if ( group === conflict.group ) {
+ itemLabels.push( mw.msg( 'quotation-marks', conflict.item.getLabel() ) );
+ }
+ } );
+
+ return {
+ message: conflictMessage,
+ names: itemLabels
+ };
+
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getStateMessage = function () {
+ var messageKey, details, superset,
+ affectingItems = [];
+
+ if ( this.isSelected() ) {
+ if ( this.isConflicted() ) {
+ // First look in filter's own conflicts
+ details = this.getConflictDetails( this.getOwnConflicts() );
+ if ( !details.message ) {
+ // Fall back onto conflicts in the group
+ details = this.getConflictDetails( this.getGroupModel().getConflicts() );
+ }
+
+ messageKey = details.message;
+ affectingItems = details.names;
+ } else if ( this.isIncluded() && !this.isHighlighted() ) {
+ // We only show the 'no effect' full-coverage message
+ // if the item is also not highlighted. See T161273
+ superset = this.getSuperset();
+ // For this message we need to collect the affecting superset
+ affectingItems = this.getGroupModel().getSelectedItems( this )
+ .filter( function ( item ) {
+ return superset.indexOf( item.getName() ) !== -1;
+ } )
+ .map( function ( item ) {
+ return mw.msg( 'quotation-marks', item.getLabel() );
+ } );
+
+ messageKey = 'rcfilters-state-message-subset';
+ } else if ( this.isFullyCovered() && !this.isHighlighted() ) {
+ affectingItems = this.getGroupModel().getSelectedItems( this )
+ .map( function ( item ) {
+ return mw.msg( 'quotation-marks', item.getLabel() );
+ } );
+
+ messageKey = 'rcfilters-state-message-fullcoverage';
+ }
+ }
+
+ if ( messageKey ) {
+ // Build message
+ return mw.msg(
+ messageKey,
+ mw.language.listToText( affectingItems ),
+ affectingItems.length
+ );
+ }
+
+ // Display description
+ return this.getDescription();
+ };
+
+ /**
+ * Get the model of the group this filter belongs to
+ *
+ * @return {mw.rcfilters.dm.FilterGroup} Filter group model
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getGroupModel = function () {
+ return this.groupModel;
+ };
+
+ /**
+ * Get the group name this filter belongs to
+ *
+ * @return {string} Filter group name
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getGroupName = function () {
+ return this.groupModel.getName();
+ };
+
+ /**
+ * Get filter subset
+ * This is a list of filter names that are defined to be included
+ * when this filter is selected.
+ *
+ * @return {string[]} Filter subset
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getSubset = function () {
+ return this.subset;
+ };
+
+ /**
+ * Get filter superset
+ * This is a generated list of filters that define this filter
+ * to be included when either of them is selected.
+ *
+ * @return {string[]} Filter superset
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getSuperset = function () {
+ return this.superset;
+ };
+
+ /**
+ * Check whether the filter is currently in a conflict state
+ *
+ * @return {boolean} Filter is in conflict state
+ */
+ mw.rcfilters.dm.FilterItem.prototype.isConflicted = function () {
+ return this.conflicted;
+ };
+
+ /**
+ * Check whether the filter is currently in an already included subset
+ *
+ * @return {boolean} Filter is in an already-included subset
+ */
+ mw.rcfilters.dm.FilterItem.prototype.isIncluded = function () {
+ return this.included;
+ };
+
+ /**
+ * Check whether the filter is currently fully covered
+ *
+ * @return {boolean} Filter is in fully-covered state
+ */
+ mw.rcfilters.dm.FilterItem.prototype.isFullyCovered = function () {
+ return this.fullyCovered;
+ };
+
+ /**
+ * Get all conflicts associated with this filter or its group
+ *
+ * Conflict object is set up by filter name keys and conflict
+ * definition. For example:
+ * {
+ * filterName: {
+ * filter: filterName,
+ * group: group1,
+ * label: itemLabel,
+ * item: itemModel
+ * }
+ * filterName2: {
+ * filter: filterName2,
+ * group: group2
+ * label: itemLabel2,
+ * item: itemModel2
+ * }
+ * }
+ *
+ * @return {Object} Filter conflicts
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getConflicts = function () {
+ return $.extend( {}, this.conflicts, this.getGroupModel().getConflicts() );
+ };
+
+ /**
+ * Get the conflicts associated with this filter
+ *
+ * @return {Object} Filter conflicts
+ */
+ mw.rcfilters.dm.FilterItem.prototype.getOwnConflicts = function () {
+ return this.conflicts;
+ };
+
+ /**
+ * Set conflicts for this filter. See #getConflicts for the expected
+ * structure of the definition.
+ *
+ * @param {Object} conflicts Conflicts for this filter
+ */
+ mw.rcfilters.dm.FilterItem.prototype.setConflicts = function ( conflicts ) {
+ this.conflicts = conflicts || {};
+ };
+
+ /**
+ * Set filter superset
+ *
+ * @param {string[]} superset Filter superset
+ */
+ mw.rcfilters.dm.FilterItem.prototype.setSuperset = function ( superset ) {
+ this.superset = superset || [];
+ };
+
+ /**
+ * Set filter subset
+ *
+ * @param {string[]} subset Filter subset
+ */
+ mw.rcfilters.dm.FilterItem.prototype.setSubset = function ( subset ) {
+ this.subset = subset || [];
+ };
+
+ /**
+ * Check whether a filter exists in the subset list for this filter
+ *
+ * @param {string} filterName Filter name
+ * @return {boolean} Filter name is in the subset list
+ */
+ mw.rcfilters.dm.FilterItem.prototype.existsInSubset = function ( filterName ) {
+ return this.subset.indexOf( filterName ) > -1;
+ };
+
+ /**
+ * Check whether this item has a potential conflict with the given item
+ *
+ * This checks whether the given item is in the list of conflicts of
+ * the current item, but makes no judgment about whether the conflict
+ * is currently at play (either one of the items may not be selected)
+ *
+ * @param {mw.rcfilters.dm.FilterItem} filterItem Filter item
+ * @return {boolean} This item has a conflict with the given item
+ */
+ mw.rcfilters.dm.FilterItem.prototype.existsInConflicts = function ( filterItem ) {
+ return Object.prototype.hasOwnProperty.call( this.getConflicts(), filterItem.getName() );
+ };
+
+ /**
+ * Set the state of this filter as being conflicted
+ * (This means any filters in its conflicts are selected)
+ *
+ * @param {boolean} [conflicted] Filter is in conflict state
+ * @fires update
+ */
+ mw.rcfilters.dm.FilterItem.prototype.toggleConflicted = function ( conflicted ) {
+ conflicted = conflicted === undefined ? !this.conflicted : conflicted;
+
+ if ( this.conflicted !== conflicted ) {
+ this.conflicted = conflicted;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Set the state of this filter as being already included
+ * (This means any filters in its superset are selected)
+ *
+ * @param {boolean} [included] Filter is included as part of a subset
+ * @fires update
+ */
+ mw.rcfilters.dm.FilterItem.prototype.toggleIncluded = function ( included ) {
+ included = included === undefined ? !this.included : included;
+
+ if ( this.included !== included ) {
+ this.included = included;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Toggle the fully covered state of the item
+ *
+ * @param {boolean} [isFullyCovered] Filter is fully covered
+ * @fires update
+ */
+ mw.rcfilters.dm.FilterItem.prototype.toggleFullyCovered = function ( isFullyCovered ) {
+ isFullyCovered = isFullyCovered === undefined ? !this.fullycovered : isFullyCovered;
+
+ if ( this.fullyCovered !== isFullyCovered ) {
+ this.fullyCovered = isFullyCovered;
+ this.emit( 'update' );
+ }
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js
new file mode 100644
index 00000000..3b882a6b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js
@@ -0,0 +1,1118 @@
+( function ( mw, $ ) {
+ /**
+ * View model for the filters selection and display
+ *
+ * @mixins OO.EventEmitter
+ * @mixins OO.EmitterList
+ *
+ * @constructor
+ */
+ mw.rcfilters.dm.FiltersViewModel = function MwRcfiltersDmFiltersViewModel() {
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+ OO.EmitterList.call( this );
+
+ this.groups = {};
+ this.defaultParams = {};
+ this.defaultFiltersEmpty = null;
+ this.highlightEnabled = false;
+ this.invertedNamespaces = false;
+ this.parameterMap = {};
+
+ this.views = {};
+ this.currentView = 'default';
+
+ // Events
+ this.aggregate( { update: 'filterItemUpdate' } );
+ this.connect( this, { filterItemUpdate: [ 'emit', 'itemUpdate' ] } );
+ };
+
+ /* Initialization */
+ OO.initClass( mw.rcfilters.dm.FiltersViewModel );
+ OO.mixinClass( mw.rcfilters.dm.FiltersViewModel, OO.EventEmitter );
+ OO.mixinClass( mw.rcfilters.dm.FiltersViewModel, OO.EmitterList );
+
+ /* Events */
+
+ /**
+ * @event initialize
+ *
+ * Filter list is initialized
+ */
+
+ /**
+ * @event update
+ *
+ * Model has been updated
+ */
+
+ /**
+ * @event itemUpdate
+ * @param {mw.rcfilters.dm.FilterItem} item Filter item updated
+ *
+ * Filter item has changed
+ */
+
+ /**
+ * @event highlightChange
+ * @param {boolean} Highlight feature is enabled
+ *
+ * Highlight feature has been toggled enabled or disabled
+ */
+
+ /**
+ * @event invertChange
+ * @param {boolean} isInverted Namespace selected is inverted
+ *
+ * Namespace selection is inverted or straight forward
+ */
+
+ /* Methods */
+
+ /**
+ * Re-assess the states of filter items based on the interactions between them
+ *
+ * @param {mw.rcfilters.dm.FilterItem} [item] Changed item. If not given, the
+ * method will go over the state of all items
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.reassessFilterInteractions = function ( item ) {
+ var allSelected,
+ model = this,
+ iterationItems = item !== undefined ? [ item ] : this.getItems();
+
+ iterationItems.forEach( function ( checkedItem ) {
+ var allCheckedItems = checkedItem.getSubset().concat( [ checkedItem.getName() ] ),
+ groupModel = checkedItem.getGroupModel();
+
+ // Check for subsets (included filters) plus the item itself:
+ allCheckedItems.forEach( function ( filterItemName ) {
+ var itemInSubset = model.getItemByName( filterItemName );
+
+ itemInSubset.toggleIncluded(
+ // If any of itemInSubset's supersets are selected, this item
+ // is included
+ itemInSubset.getSuperset().some( function ( supersetName ) {
+ return ( model.getItemByName( supersetName ).isSelected() );
+ } )
+ );
+ } );
+
+ // Update coverage for the changed group
+ if ( groupModel.isFullCoverage() ) {
+ allSelected = groupModel.areAllSelected();
+ groupModel.getItems().forEach( function ( filterItem ) {
+ filterItem.toggleFullyCovered( allSelected );
+ } );
+ }
+ } );
+
+ // Check for conflicts
+ // In this case, we must go over all items, since
+ // conflicts are bidirectional and depend not only on
+ // individual items, but also on the selected states of
+ // the groups they're in.
+ this.getItems().forEach( function ( filterItem ) {
+ var inConflict = false,
+ filterItemGroup = filterItem.getGroupModel();
+
+ // For each item, see if that item is still conflicting
+ $.each( model.groups, function ( groupName, groupModel ) {
+ if ( filterItem.getGroupName() === groupName ) {
+ // Check inside the group
+ inConflict = groupModel.areAnySelectedInConflictWith( filterItem );
+ } else {
+ // According to the spec, if two items conflict from two different
+ // groups, the conflict only lasts if the groups **only have selected
+ // items that are conflicting**. If a group has selected items that
+ // are conflicting and non-conflicting, the scope of the result has
+ // expanded enough to completely remove the conflict.
+
+ // For example, see two groups with conflicts:
+ // userExpLevel: [
+ // {
+ // name: 'experienced',
+ // conflicts: [ 'unregistered' ]
+ // }
+ // ],
+ // registration: [
+ // {
+ // name: 'registered',
+ // },
+ // {
+ // name: 'unregistered',
+ // }
+ // ]
+ // If we select 'experienced', then 'unregistered' is in conflict (and vice versa),
+ // because, inherently, 'experienced' filter only includes registered users, and so
+ // both filters are in conflict with one another.
+ // However, the minute we select 'registered', the scope of our results
+ // has expanded to no longer have a conflict with 'experienced' filter, and
+ // so the conflict is removed.
+
+ // In our case, we need to check if the entire group conflicts with
+ // the entire item's group, so we follow the above spec
+ inConflict = (
+ // The foreign group is in conflict with this item
+ groupModel.areAllSelectedInConflictWith( filterItem ) &&
+ // Every selected member of the item's own group is also
+ // in conflict with the other group
+ filterItemGroup.getSelectedItems().every( function ( otherGroupItem ) {
+ return groupModel.areAllSelectedInConflictWith( otherGroupItem );
+ } )
+ );
+ }
+
+ // If we're in conflict, this will return 'false' which
+ // will break the loop. Otherwise, we're not in conflict
+ // and the loop continues
+ return !inConflict;
+ } );
+
+ // Toggle the item state
+ filterItem.toggleConflicted( inConflict );
+ } );
+ };
+
+ /**
+ * Get whether the model has any conflict in its items
+ *
+ * @return {boolean} There is a conflict
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.hasConflict = function () {
+ return this.getItems().some( function ( filterItem ) {
+ return filterItem.isSelected() && filterItem.isConflicted();
+ } );
+ };
+
+ /**
+ * Get the first item with a current conflict
+ *
+ * @return {mw.rcfilters.dm.FilterItem} Conflicted item
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getFirstConflictedItem = function () {
+ var conflictedItem;
+
+ $.each( this.getItems(), function ( index, filterItem ) {
+ if ( filterItem.isSelected() && filterItem.isConflicted() ) {
+ conflictedItem = filterItem;
+ return false;
+ }
+ } );
+
+ return conflictedItem;
+ };
+
+ /**
+ * Set filters and preserve a group relationship based on
+ * the definition given by an object
+ *
+ * @param {Array} filterGroups Filters definition
+ * @param {Object} [views] Extra views definition
+ * Expected in the following format:
+ * {
+ * namespaces: {
+ * label: 'namespaces', // Message key
+ * trigger: ':',
+ * groups: [
+ * {
+ * // Group info
+ * name: 'namespaces' // Parameter name
+ * title: 'namespaces' // Message key
+ * type: 'string_options',
+ * separator: ';',
+ * labelPrefixKey: { 'default': 'rcfilters-tag-prefix-namespace', inverted: 'rcfilters-tag-prefix-namespace-inverted' },
+ * fullCoverage: true
+ * items: []
+ * }
+ * ]
+ * }
+ * }
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.initializeFilters = function ( filterGroups, views ) {
+ var filterConflictResult, groupConflictResult,
+ allViews = {},
+ model = this,
+ items = [],
+ groupConflictMap = {},
+ filterConflictMap = {},
+ /*!
+ * Expand a conflict definition from group name to
+ * the list of all included filters in that group.
+ * We do this so that the direct relationship in the
+ * models are consistently item->items rather than
+ * mixing item->group with item->item.
+ *
+ * @param {Object} obj Conflict definition
+ * @return {Object} Expanded conflict definition
+ */
+ expandConflictDefinitions = function ( obj ) {
+ var result = {};
+
+ $.each( obj, function ( key, conflicts ) {
+ var filterName,
+ adjustedConflicts = {};
+
+ conflicts.forEach( function ( conflict ) {
+ var filter;
+
+ if ( conflict.filter ) {
+ filterName = model.groups[ conflict.group ].getPrefixedName( conflict.filter );
+ filter = model.getItemByName( filterName );
+
+ // Rename
+ adjustedConflicts[ filterName ] = $.extend(
+ {},
+ conflict,
+ {
+ filter: filterName,
+ item: filter
+ }
+ );
+ } else {
+ // This conflict is for an entire group. Split it up to
+ // represent each filter
+
+ // Get the relevant group items
+ model.groups[ conflict.group ].getItems().forEach( function ( groupItem ) {
+ // Rebuild the conflict
+ adjustedConflicts[ groupItem.getName() ] = $.extend(
+ {},
+ conflict,
+ {
+ filter: groupItem.getName(),
+ item: groupItem
+ }
+ );
+ } );
+ }
+ } );
+
+ result[ key ] = adjustedConflicts;
+ } );
+
+ return result;
+ };
+
+ // Reset
+ this.clearItems();
+ this.groups = {};
+ this.views = {};
+
+ // Clone
+ filterGroups = OO.copy( filterGroups );
+
+ // Normalize definition from the server
+ filterGroups.forEach( function ( data ) {
+ var i;
+ // What's this information needs to be normalized
+ data.whatsThis = {
+ body: data.whatsThisBody,
+ header: data.whatsThisHeader,
+ linkText: data.whatsThisLinkText,
+ url: data.whatsThisUrl
+ };
+
+ // Title is a msg-key
+ data.title = data.title ? mw.msg( data.title ) : data.name;
+
+ // Filters are given to us with msg-keys, we need
+ // to translate those before we hand them off
+ for ( i = 0; i < data.filters.length; i++ ) {
+ data.filters[ i ].label = data.filters[ i ].label ? mw.msg( data.filters[ i ].label ) : data.filters[ i ].name;
+ data.filters[ i ].description = data.filters[ i ].description ? mw.msg( data.filters[ i ].description ) : '';
+ }
+ } );
+
+ // Collect views
+ allViews = $.extend( true, {
+ 'default': {
+ title: mw.msg( 'rcfilters-filterlist-title' ),
+ groups: filterGroups
+ }
+ }, views );
+
+ // Go over all views
+ $.each( allViews, function ( viewName, viewData ) {
+ // Define the view
+ model.views[ viewName ] = {
+ name: viewData.name,
+ title: viewData.title,
+ trigger: viewData.trigger
+ };
+
+ // Go over groups
+ viewData.groups.forEach( function ( groupData ) {
+ var group = groupData.name;
+
+ if ( !model.groups[ group ] ) {
+ model.groups[ group ] = new mw.rcfilters.dm.FilterGroup(
+ group,
+ $.extend( true, {}, groupData, { view: viewName } )
+ );
+ }
+
+ model.groups[ group ].initializeFilters( groupData.filters, groupData.default );
+ items = items.concat( model.groups[ group ].getItems() );
+
+ // Prepare conflicts
+ if ( groupData.conflicts ) {
+ // Group conflicts
+ groupConflictMap[ group ] = groupData.conflicts;
+ }
+
+ groupData.filters.forEach( function ( itemData ) {
+ var filterItem = model.groups[ group ].getItemByParamName( itemData.name );
+ // Filter conflicts
+ if ( itemData.conflicts ) {
+ filterConflictMap[ filterItem.getName() ] = itemData.conflicts;
+ }
+ } );
+ } );
+ } );
+
+ // Add item references to the model, for lookup
+ this.addItems( items );
+
+ // Expand conflicts
+ groupConflictResult = expandConflictDefinitions( groupConflictMap );
+ filterConflictResult = expandConflictDefinitions( filterConflictMap );
+
+ // Set conflicts for groups
+ $.each( groupConflictResult, function ( group, conflicts ) {
+ model.groups[ group ].setConflicts( conflicts );
+ } );
+
+ // Set conflicts for items
+ $.each( filterConflictResult, function ( filterName, conflicts ) {
+ var filterItem = model.getItemByName( filterName );
+ // set conflicts for items in the group
+ filterItem.setConflicts( conflicts );
+ } );
+
+ // Create a map between known parameters and their models
+ $.each( this.groups, function ( group, groupModel ) {
+ if (
+ groupModel.getType() === 'send_unselected_if_any' ||
+ groupModel.getType() === 'boolean'
+ ) {
+ // Individual filters
+ groupModel.getItems().forEach( function ( filterItem ) {
+ model.parameterMap[ filterItem.getParamName() ] = filterItem;
+ } );
+ } else if (
+ groupModel.getType() === 'string_options' ||
+ groupModel.getType() === 'single_option'
+ ) {
+ // Group
+ model.parameterMap[ groupModel.getName() ] = groupModel;
+ }
+ } );
+
+ this.currentView = 'default';
+
+ // Finish initialization
+ this.emit( 'initialize' );
+ };
+
+ /**
+ * Get the names of all available filters
+ *
+ * @return {string[]} An array of filter names
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getFilterNames = function () {
+ return this.getItems().map( function ( item ) { return item.getName(); } );
+ };
+
+ /**
+ * Get the object that defines groups by their name.
+ *
+ * @return {Object} Filter groups
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getFilterGroups = function () {
+ return this.groups;
+ };
+
+ /**
+ * Get the object that defines groups that match a certain view by their name.
+ *
+ * @param {string} [view] Requested view. If not given, uses current view
+ * @return {Object} Filter groups matching a display group
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getFilterGroupsByView = function ( view ) {
+ var result = {};
+
+ view = view || this.getCurrentView();
+
+ $.each( this.groups, function ( groupName, groupModel ) {
+ if ( groupModel.getView() === view ) {
+ result[ groupName ] = groupModel;
+ }
+ } );
+
+ return result;
+ };
+
+ /**
+ * Get an array of filters matching the given display group.
+ *
+ * @param {string} [view] Requested view. If not given, uses current view
+ * @return {mw.rcfilters.dm.FilterItem} Filter items matching the group
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getFiltersByView = function ( view ) {
+ var groups,
+ result = [];
+
+ view = view || this.getCurrentView();
+
+ groups = this.getFilterGroupsByView( view );
+
+ $.each( groups, function ( groupName, groupModel ) {
+ result = result.concat( groupModel.getItems() );
+ } );
+
+ return result;
+ };
+
+ /**
+ * Get the trigger for the requested view.
+ *
+ * @param {string} view View name
+ * @return {string} View trigger, if exists
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getViewTrigger = function ( view ) {
+ return ( this.views[ view ] && this.views[ view ].trigger ) || '';
+ };
+ /**
+ * Get the value of a specific parameter
+ *
+ * @param {string} name Parameter name
+ * @return {number|string} Parameter value
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getParamValue = function ( name ) {
+ return this.parameters[ name ];
+ };
+
+ /**
+ * Get the current selected state of the filters
+ *
+ * @return {Object} Filters selected state
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getSelectedState = function () {
+ var i,
+ items = this.getItems(),
+ result = {};
+
+ for ( i = 0; i < items.length; i++ ) {
+ result[ items[ i ].getName() ] = items[ i ].isSelected();
+ }
+
+ return result;
+ };
+
+ /**
+ * Get the current full state of the filters
+ *
+ * @return {Object} Filters full state
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getFullState = function () {
+ var i,
+ items = this.getItems(),
+ result = {};
+
+ for ( i = 0; i < items.length; i++ ) {
+ result[ items[ i ].getName() ] = {
+ selected: items[ i ].isSelected(),
+ conflicted: items[ i ].isConflicted(),
+ included: items[ i ].isIncluded()
+ };
+ }
+
+ return result;
+ };
+
+ /**
+ * Get an object representing default parameters state
+ *
+ * @return {Object} Default parameter values
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getDefaultParams = function () {
+ var result = {};
+
+ // Get default filter state
+ $.each( this.groups, function ( name, model ) {
+ $.extend( true, result, model.getDefaultParams() );
+ } );
+
+ return result;
+ };
+
+ /**
+ * Get a parameter representation of all sticky parameters
+ *
+ * @return {Object} Sticky parameter values
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getStickyParams = function () {
+ var result = {};
+
+ $.each( this.groups, function ( name, model ) {
+ if ( model.isSticky() ) {
+ $.extend( true, result, model.getDefaultParams() );
+ }
+ } );
+
+ return result;
+ };
+
+ /**
+ * Get a filter representation of all sticky parameters
+ *
+ * @return {Object} Sticky filters values
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getStickyFiltersState = function () {
+ var result = {};
+
+ $.each( this.groups, function ( name, model ) {
+ if ( model.isSticky() ) {
+ $.extend( true, result, model.getSelectedState() );
+ }
+ } );
+
+ return result;
+ };
+
+ /**
+ * Get a filter representation of all parameters that are marked
+ * as being excluded from saved query.
+ *
+ * @return {Object} Excluded filters values
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getExcludedFiltersState = function () {
+ var result = {};
+
+ $.each( this.groups, function ( name, model ) {
+ if ( model.isExcludedFromSavedQueries() ) {
+ $.extend( true, result, model.getSelectedState() );
+ }
+ } );
+
+ return result;
+ };
+
+ /**
+ * Analyze the groups and their filters and output an object representing
+ * the state of the parameters they represent.
+ *
+ * @param {Object} [filterDefinition] An object defining the filter values,
+ * keyed by filter names.
+ * @return {Object} Parameter state object
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getParametersFromFilters = function ( filterDefinition ) {
+ var groupItemDefinition,
+ result = {},
+ groupItems = this.getFilterGroups();
+
+ if ( filterDefinition ) {
+ groupItemDefinition = {};
+ // Filter definition is "flat", but in effect
+ // each group needs to tell us its result based
+ // on the values in it. We need to split this list
+ // back into groupings so we can "feed" it to the
+ // loop below, and we need to expand it so it includes
+ // all filters (set to false)
+ this.getItems().forEach( function ( filterItem ) {
+ groupItemDefinition[ filterItem.getGroupName() ] = groupItemDefinition[ filterItem.getGroupName() ] || {};
+ groupItemDefinition[ filterItem.getGroupName() ][ filterItem.getName() ] = !!filterDefinition[ filterItem.getName() ];
+ } );
+ }
+
+ $.each( groupItems, function ( group, model ) {
+ $.extend(
+ result,
+ model.getParamRepresentation(
+ groupItemDefinition ?
+ groupItemDefinition[ group ] : null
+ )
+ );
+ } );
+
+ return result;
+ };
+
+ /**
+ * This is the opposite of the #getParametersFromFilters method; this goes over
+ * the given parameters and translates into a selected/unselected value in the filters.
+ *
+ * @param {Object} params Parameters query object
+ * @return {Object} Filter state object
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getFiltersFromParameters = function ( params ) {
+ var groupMap = {},
+ model = this,
+ result = {};
+
+ // Go over the given parameters, break apart to groupings
+ // The resulting object represents the group with its parameter
+ // values. For example:
+ // {
+ // group1: {
+ // param1: "1",
+ // param2: "0",
+ // param3: "1"
+ // },
+ // group2: "param4|param5"
+ // }
+ $.each( params, function ( paramName, paramValue ) {
+ var groupName,
+ itemOrGroup = model.parameterMap[ paramName ];
+
+ if ( itemOrGroup ) {
+ groupName = itemOrGroup instanceof mw.rcfilters.dm.FilterItem ?
+ itemOrGroup.getGroupName() : itemOrGroup.getName();
+
+ groupMap[ groupName ] = groupMap[ groupName ] || {};
+ groupMap[ groupName ][ paramName ] = paramValue;
+ }
+ } );
+
+ // Go over all groups, so we make sure we get the complete output
+ // even if the parameters don't include a certain group
+ $.each( this.groups, function ( groupName, groupModel ) {
+ result = $.extend( true, {}, result, groupModel.getFilterRepresentation( groupMap[ groupName ] ) );
+ } );
+
+ return result;
+ };
+
+ /**
+ * Get the highlight parameters based on current filter configuration
+ *
+ * @return {Object} Object where keys are `<filter name>_color` and values
+ * are the selected highlight colors.
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getHighlightParameters = function () {
+ var result = {};
+
+ this.getItems().forEach( function ( filterItem ) {
+ result[ filterItem.getName() + '_color' ] = filterItem.getHighlightColor() || null;
+ } );
+ result.highlight = String( Number( this.isHighlightEnabled() ) );
+
+ return result;
+ };
+
+ /**
+ * Extract the highlight values from given object. Since highlights are
+ * the same for filter and parameters, it doesn't matter which one is
+ * given; values will be returned with a full list of the highlights
+ * with colors or null values.
+ *
+ * @param {Object} representation Object containing representation of
+ * some or all highlight values
+ * @return {Object} Object where keys are `<filter name>_color` and values
+ * are the selected highlight colors. The returned object
+ * contains all available filters either with a color value
+ * or with null.
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.extractHighlightValues = function ( representation ) {
+ var result = {};
+
+ this.getItems().forEach( function ( filterItem ) {
+ var highlightName = filterItem.getName() + '_color';
+ result[ highlightName ] = representation[ highlightName ] || null;
+ } );
+
+ return result;
+ };
+
+ /**
+ * Get an array of currently applied highlight colors
+ *
+ * @return {string[]} Currently applied highlight colors
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getCurrentlyUsedHighlightColors = function () {
+ var result = [];
+
+ this.getHighlightedItems().forEach( function ( filterItem ) {
+ var color = filterItem.getHighlightColor();
+
+ if ( result.indexOf( color ) === -1 ) {
+ result.push( color );
+ }
+ } );
+
+ return result;
+ };
+
+ /**
+ * Sanitize value group of a string_option groups type
+ * Remove duplicates and make sure to only use valid
+ * values.
+ *
+ * @private
+ * @param {string} groupName Group name
+ * @param {string[]} valueArray Array of values
+ * @return {string[]} Array of valid values
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.sanitizeStringOptionGroup = function ( groupName, valueArray ) {
+ var validNames = this.getGroupFilters( groupName ).map( function ( filterItem ) {
+ return filterItem.getParamName();
+ } );
+
+ return mw.rcfilters.utils.normalizeParamOptions( valueArray, validNames );
+ };
+
+ /**
+ * Check whether the current filter state is set to all false.
+ *
+ * @return {boolean} Current filters are all empty
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.areCurrentFiltersEmpty = function () {
+ // Check if there are either any selected items or any items
+ // that have highlight enabled
+ return !this.getItems().some( function ( filterItem ) {
+ return !filterItem.getGroupModel().isHidden() && ( filterItem.isSelected() || filterItem.isHighlighted() );
+ } );
+ };
+
+ /**
+ * Get the item that matches the given name
+ *
+ * @param {string} name Filter name
+ * @return {mw.rcfilters.dm.FilterItem} Filter item
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getItemByName = function ( name ) {
+ return this.getItems().filter( function ( item ) {
+ return name === item.getName();
+ } )[ 0 ];
+ };
+
+ /**
+ * Set all filters to false or empty/all
+ * This is equivalent to display all.
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.emptyAllFilters = function () {
+ this.getItems().forEach( function ( filterItem ) {
+ if ( !filterItem.getGroupModel().isSticky() ) {
+ this.toggleFilterSelected( filterItem.getName(), false );
+ }
+ }.bind( this ) );
+ };
+
+ /**
+ * Toggle selected state of one item
+ *
+ * @param {string} name Name of the filter item
+ * @param {boolean} [isSelected] Filter selected state
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.toggleFilterSelected = function ( name, isSelected ) {
+ var item = this.getItemByName( name );
+
+ if ( item ) {
+ item.toggleSelected( isSelected );
+ }
+ };
+
+ /**
+ * Toggle selected state of items by their names
+ *
+ * @param {Object} filterDef Filter definitions
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.toggleFiltersSelected = function ( filterDef ) {
+ Object.keys( filterDef ).forEach( function ( name ) {
+ this.toggleFilterSelected( name, filterDef[ name ] );
+ }.bind( this ) );
+ };
+
+ /**
+ * Get a group model from its name
+ *
+ * @param {string} groupName Group name
+ * @return {mw.rcfilters.dm.FilterGroup} Group model
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getGroup = function ( groupName ) {
+ return this.groups[ groupName ];
+ };
+
+ /**
+ * Get all filters within a specified group by its name
+ *
+ * @param {string} groupName Group name
+ * @return {mw.rcfilters.dm.FilterItem[]} Filters belonging to this group
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getGroupFilters = function ( groupName ) {
+ return ( this.getGroup( groupName ) && this.getGroup( groupName ).getItems() ) || [];
+ };
+
+ /**
+ * Find items whose labels match the given string
+ *
+ * @param {string} query Search string
+ * @param {boolean} [returnFlat] Return a flat array. If false, the result
+ * is an object whose keys are the group names and values are an array of
+ * filters per group. If set to true, returns an array of filters regardless
+ * of their groups.
+ * @return {Object} An object of items to show
+ * arranged by their group names
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.findMatches = function ( query, returnFlat ) {
+ var i, searchIsEmpty,
+ groupTitle,
+ result = {},
+ flatResult = [],
+ view = this.getViewByTrigger( query.substr( 0, 1 ) ),
+ items = this.getFiltersByView( view );
+
+ // Normalize so we can search strings regardless of case and view
+ query = query.trim().toLowerCase();
+ if ( view !== 'default' ) {
+ query = query.substr( 1 );
+ }
+ // Trim again to also intercept cases where the spaces were after the trigger
+ // eg: '# str'
+ query = query.trim();
+
+ // Check if the search if actually empty; this can be a problem when
+ // we use prefixes to denote different views
+ searchIsEmpty = query.length === 0;
+
+ // item label starting with the query string
+ for ( i = 0; i < items.length; i++ ) {
+ if (
+ searchIsEmpty ||
+ items[ i ].getLabel().toLowerCase().indexOf( query ) === 0 ||
+ (
+ // For tags, we want the parameter name to be included in the search
+ view === 'tags' &&
+ items[ i ].getParamName().toLowerCase().indexOf( query ) > -1
+ )
+ ) {
+ result[ items[ i ].getGroupName() ] = result[ items[ i ].getGroupName() ] || [];
+ result[ items[ i ].getGroupName() ].push( items[ i ] );
+ flatResult.push( items[ i ] );
+ }
+ }
+
+ if ( $.isEmptyObject( result ) ) {
+ // item containing the query string in their label, description, or group title
+ for ( i = 0; i < items.length; i++ ) {
+ groupTitle = items[ i ].getGroupModel().getTitle();
+ if (
+ searchIsEmpty ||
+ items[ i ].getLabel().toLowerCase().indexOf( query ) > -1 ||
+ items[ i ].getDescription().toLowerCase().indexOf( query ) > -1 ||
+ groupTitle.toLowerCase().indexOf( query ) > -1 ||
+ (
+ // For tags, we want the parameter name to be included in the search
+ view === 'tags' &&
+ items[ i ].getParamName().toLowerCase().indexOf( query ) > -1
+ )
+ ) {
+ result[ items[ i ].getGroupName() ] = result[ items[ i ].getGroupName() ] || [];
+ result[ items[ i ].getGroupName() ].push( items[ i ] );
+ flatResult.push( items[ i ] );
+ }
+ }
+ }
+
+ return returnFlat ? flatResult : result;
+ };
+
+ /**
+ * Get items that are highlighted
+ *
+ * @return {mw.rcfilters.dm.FilterItem[]} Highlighted items
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getHighlightedItems = function () {
+ return this.getItems().filter( function ( filterItem ) {
+ return filterItem.isHighlightSupported() &&
+ filterItem.getHighlightColor();
+ } );
+ };
+
+ /**
+ * Get items that allow highlights even if they're not currently highlighted
+ *
+ * @return {mw.rcfilters.dm.FilterItem[]} Items supporting highlights
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getItemsSupportingHighlights = function () {
+ return this.getItems().filter( function ( filterItem ) {
+ return filterItem.isHighlightSupported();
+ } );
+ };
+
+ /**
+ * Get all selected items
+ *
+ * @return {mw.rcfilters.dm.FilterItem[]} Selected items
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getSelectedItems = function () {
+ var allSelected = [];
+
+ $.each( this.getFilterGroups(), function ( groupName, groupModel ) {
+ allSelected = allSelected.concat( groupModel.getSelectedItems() );
+ } );
+
+ return allSelected;
+ };
+ /**
+ * Switch the current view
+ *
+ * @param {string} view View name
+ * @fires update
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.switchView = function ( view ) {
+ if ( this.views[ view ] && this.currentView !== view ) {
+ this.currentView = view;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Get the current view
+ *
+ * @return {string} Current view
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getCurrentView = function () {
+ return this.currentView;
+ };
+
+ /**
+ * Get the label for the current view
+ *
+ * @param {string} viewName View name
+ * @return {string} Label for the current view
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getViewTitle = function ( viewName ) {
+ viewName = viewName || this.getCurrentView();
+
+ return this.views[ viewName ] && this.views[ viewName ].title;
+ };
+
+ /**
+ * Get an array of all available view names
+ *
+ * @return {string} Available view names
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getAvailableViews = function () {
+ return Object.keys( this.views );
+ };
+
+ /**
+ * Get the view that fits the given trigger
+ *
+ * @param {string} trigger Trigger
+ * @return {string} Name of view
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.getViewByTrigger = function ( trigger ) {
+ var result = 'default';
+
+ $.each( this.views, function ( name, data ) {
+ if ( data.trigger === trigger ) {
+ result = name;
+ }
+ } );
+
+ return result;
+ };
+
+ /**
+ * Toggle the highlight feature on and off.
+ * Propagate the change to filter items.
+ *
+ * @param {boolean} enable Highlight should be enabled
+ * @fires highlightChange
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.toggleHighlight = function ( enable ) {
+ enable = enable === undefined ? !this.highlightEnabled : enable;
+
+ if ( this.highlightEnabled !== enable ) {
+ this.highlightEnabled = enable;
+
+ this.getItems().forEach( function ( filterItem ) {
+ filterItem.toggleHighlight( this.highlightEnabled );
+ }.bind( this ) );
+
+ this.emit( 'highlightChange', this.highlightEnabled );
+ }
+ };
+
+ /**
+ * Check if the highlight feature is enabled
+ * @return {boolean}
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.isHighlightEnabled = function () {
+ return !!this.highlightEnabled;
+ };
+
+ /**
+ * Toggle the inverted namespaces property on and off.
+ * Propagate the change to namespace filter items.
+ *
+ * @param {boolean} enable Inverted property is enabled
+ * @fires invertChange
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.toggleInvertedNamespaces = function ( enable ) {
+ enable = enable === undefined ? !this.invertedNamespaces : enable;
+
+ if ( this.invertedNamespaces !== enable ) {
+ this.invertedNamespaces = enable;
+
+ this.getFiltersByView( 'namespaces' ).forEach( function ( filterItem ) {
+ filterItem.toggleInverted( this.invertedNamespaces );
+ }.bind( this ) );
+
+ this.emit( 'invertChange', this.invertedNamespaces );
+ }
+ };
+
+ /**
+ * Check if the namespaces selection is set to be inverted
+ * @return {boolean}
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.areNamespacesInverted = function () {
+ return !!this.invertedNamespaces;
+ };
+
+ /**
+ * Set highlight color for a specific filter item
+ *
+ * @param {string} filterName Name of the filter item
+ * @param {string} color Selected color
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.setHighlightColor = function ( filterName, color ) {
+ this.getItemByName( filterName ).setHighlightColor( color );
+ };
+
+ /**
+ * Clear highlight for a specific filter item
+ *
+ * @param {string} filterName Name of the filter item
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.clearHighlightColor = function ( filterName ) {
+ this.getItemByName( filterName ).clearHighlightColor();
+ };
+
+ /**
+ * Clear highlight for all filter items
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.clearAllHighlightColors = function () {
+ this.getItems().forEach( function ( filterItem ) {
+ filterItem.clearHighlightColor();
+ } );
+ };
+
+ /**
+ * Return a version of the given string that is without any
+ * view triggers.
+ *
+ * @param {string} str Given string
+ * @return {string} Result
+ */
+ mw.rcfilters.dm.FiltersViewModel.prototype.removeViewTriggers = function ( str ) {
+ if ( this.getViewByTrigger( str.substr( 0, 1 ) ) !== 'default' ) {
+ str = str.substr( 1 );
+ }
+
+ return str;
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ItemModel.js b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ItemModel.js
new file mode 100644
index 00000000..aa82e218
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.ItemModel.js
@@ -0,0 +1,298 @@
+( function ( mw ) {
+ /**
+ * RCFilter base item model
+ *
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {string} param Filter param name
+ * @param {Object} config Configuration object
+ * @cfg {string} [label] The label for the filter
+ * @cfg {string} [description] The description of the filter
+ * @cfg {string|Object} [labelPrefixKey] An i18n key defining the prefix label for this
+ * group. If the prefix has 'invert' state, the parameter is expected to be an object
+ * with 'default' and 'inverted' as keys.
+ * @cfg {boolean} [active=true] The filter is active and affecting the result
+ * @cfg {boolean} [selected] The item is selected
+ * @cfg {boolean} [inverted] The item is inverted, meaning the search is excluding
+ * this parameter.
+ * @cfg {string} [namePrefix='item_'] A prefix to add to the param name to act as a unique
+ * identifier
+ * @cfg {string} [cssClass] The class identifying the results that match this filter
+ * @cfg {string[]} [identifiers] An array of identifiers for this item. They will be
+ * added and considered in the view.
+ */
+ mw.rcfilters.dm.ItemModel = function MwRcfiltersDmItemModel( param, config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ this.param = param;
+ this.namePrefix = config.namePrefix || 'item_';
+ this.name = this.namePrefix + param;
+
+ this.label = config.label || this.name;
+ this.labelPrefixKey = config.labelPrefixKey;
+ this.description = config.description || '';
+ this.selected = !!config.selected;
+
+ this.inverted = !!config.inverted;
+ this.identifiers = config.identifiers || [];
+
+ // Highlight
+ this.cssClass = config.cssClass;
+ this.highlightColor = null;
+ this.highlightEnabled = false;
+ };
+
+ /* Initialization */
+
+ OO.initClass( mw.rcfilters.dm.ItemModel );
+ OO.mixinClass( mw.rcfilters.dm.ItemModel, OO.EventEmitter );
+
+ /* Events */
+
+ /**
+ * @event update
+ *
+ * The state of this filter has changed
+ */
+
+ /* Methods */
+
+ /**
+ * Return the representation of the state of this item.
+ *
+ * @return {Object} State of the object
+ */
+ mw.rcfilters.dm.ItemModel.prototype.getState = function () {
+ return {
+ selected: this.isSelected(),
+ inverted: this.isInverted()
+ };
+ };
+
+ /**
+ * Get the name of this filter
+ *
+ * @return {string} Filter name
+ */
+ mw.rcfilters.dm.ItemModel.prototype.getName = function () {
+ return this.name;
+ };
+
+ /**
+ * Get a prefixed label
+ *
+ * @return {string} Prefixed label
+ */
+ mw.rcfilters.dm.ItemModel.prototype.getPrefixedLabel = function () {
+ if ( this.labelPrefixKey ) {
+ if ( typeof this.labelPrefixKey === 'string' ) {
+ return mw.message( this.labelPrefixKey, this.getLabel() ).parse();
+ } else {
+ return mw.message(
+ this.labelPrefixKey[
+ // Only use inverted-prefix if the item is selected
+ // Highlight-only an inverted item makes no sense
+ this.isInverted() && this.isSelected() ?
+ 'inverted' : 'default'
+ ],
+ this.getLabel()
+ ).parse();
+ }
+ } else {
+ return this.getLabel();
+ }
+ };
+
+ /**
+ * Get the param name or value of this filter
+ *
+ * @return {string} Filter param name
+ */
+ mw.rcfilters.dm.ItemModel.prototype.getParamName = function () {
+ return this.param;
+ };
+
+ /**
+ * Get the message representing the state of this model.
+ *
+ * @return {string} State message
+ */
+ mw.rcfilters.dm.ItemModel.prototype.getStateMessage = function () {
+ // Display description
+ return this.getDescription();
+ };
+
+ /**
+ * Get the label of this filter
+ *
+ * @return {string} Filter label
+ */
+ mw.rcfilters.dm.ItemModel.prototype.getLabel = function () {
+ return this.label;
+ };
+
+ /**
+ * Get the description of this filter
+ *
+ * @return {string} Filter description
+ */
+ mw.rcfilters.dm.ItemModel.prototype.getDescription = function () {
+ return this.description;
+ };
+
+ /**
+ * Get the default value of this filter
+ *
+ * @return {boolean} Filter default
+ */
+ mw.rcfilters.dm.ItemModel.prototype.getDefault = function () {
+ return this.default;
+ };
+
+ /**
+ * Get the selected state of this filter
+ *
+ * @return {boolean} Filter is selected
+ */
+ mw.rcfilters.dm.ItemModel.prototype.isSelected = function () {
+ return this.selected;
+ };
+
+ /**
+ * Toggle the selected state of the item
+ *
+ * @param {boolean} [isSelected] Filter is selected
+ * @fires update
+ */
+ mw.rcfilters.dm.ItemModel.prototype.toggleSelected = function ( isSelected ) {
+ isSelected = isSelected === undefined ? !this.selected : isSelected;
+
+ if ( this.selected !== isSelected ) {
+ this.selected = isSelected;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Get the inverted state of this item
+ *
+ * @return {boolean} Item is inverted
+ */
+ mw.rcfilters.dm.ItemModel.prototype.isInverted = function () {
+ return this.inverted;
+ };
+
+ /**
+ * Toggle the inverted state of the item
+ *
+ * @param {boolean} [isInverted] Item is inverted
+ * @fires update
+ */
+ mw.rcfilters.dm.ItemModel.prototype.toggleInverted = function ( isInverted ) {
+ isInverted = isInverted === undefined ? !this.inverted : isInverted;
+
+ if ( this.inverted !== isInverted ) {
+ this.inverted = isInverted;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Set the highlight color
+ *
+ * @param {string|null} highlightColor
+ */
+ mw.rcfilters.dm.ItemModel.prototype.setHighlightColor = function ( highlightColor ) {
+ if ( this.highlightColor !== highlightColor ) {
+ this.highlightColor = highlightColor;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Clear the highlight color
+ */
+ mw.rcfilters.dm.ItemModel.prototype.clearHighlightColor = function () {
+ this.setHighlightColor( null );
+ };
+
+ /**
+ * Get the highlight color, or null if none is configured
+ *
+ * @return {string|null}
+ */
+ mw.rcfilters.dm.ItemModel.prototype.getHighlightColor = function () {
+ return this.highlightColor;
+ };
+
+ /**
+ * Get the CSS class that matches changes that fit this filter
+ * or null if none is configured
+ *
+ * @return {string|null}
+ */
+ mw.rcfilters.dm.ItemModel.prototype.getCssClass = function () {
+ return this.cssClass;
+ };
+
+ /**
+ * Get the item's identifiers
+ *
+ * @return {string[]}
+ */
+ mw.rcfilters.dm.ItemModel.prototype.getIdentifiers = function () {
+ return this.identifiers;
+ };
+
+ /**
+ * Toggle the highlight feature on and off for this filter.
+ * It only works if highlight is supported for this filter.
+ *
+ * @param {boolean} enable Highlight should be enabled
+ */
+ mw.rcfilters.dm.ItemModel.prototype.toggleHighlight = function ( enable ) {
+ enable = enable === undefined ? !this.highlightEnabled : enable;
+
+ if ( !this.isHighlightSupported() ) {
+ return;
+ }
+
+ if ( enable === this.highlightEnabled ) {
+ return;
+ }
+
+ this.highlightEnabled = enable;
+ this.emit( 'update' );
+ };
+
+ /**
+ * Check if the highlight feature is currently enabled for this filter
+ *
+ * @return {boolean}
+ */
+ mw.rcfilters.dm.ItemModel.prototype.isHighlightEnabled = function () {
+ return !!this.highlightEnabled;
+ };
+
+ /**
+ * Check if the highlight feature is supported for this filter
+ *
+ * @return {boolean}
+ */
+ mw.rcfilters.dm.ItemModel.prototype.isHighlightSupported = function () {
+ return !!this.getCssClass();
+ };
+
+ /**
+ * Check if the filter is currently highlighted
+ *
+ * @return {boolean}
+ */
+ mw.rcfilters.dm.ItemModel.prototype.isHighlighted = function () {
+ return this.isHighlightEnabled() && !!this.getHighlightColor();
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueriesModel.js b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueriesModel.js
new file mode 100644
index 00000000..f8789415
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueriesModel.js
@@ -0,0 +1,282 @@
+( function ( mw, $ ) {
+ /**
+ * View model for saved queries
+ *
+ * @class
+ * @mixins OO.EventEmitter
+ * @mixins OO.EmitterList
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [default] Default query ID
+ */
+ mw.rcfilters.dm.SavedQueriesModel = function MwRcfiltersDmSavedQueriesModel( config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+ OO.EmitterList.call( this );
+
+ this.default = config.default;
+ this.baseState = {};
+
+ // Events
+ this.aggregate( { update: 'itemUpdate' } );
+ };
+
+ /* Initialization */
+
+ OO.initClass( mw.rcfilters.dm.SavedQueriesModel );
+ OO.mixinClass( mw.rcfilters.dm.SavedQueriesModel, OO.EventEmitter );
+ OO.mixinClass( mw.rcfilters.dm.SavedQueriesModel, OO.EmitterList );
+
+ /* Events */
+
+ /**
+ * @event initialize
+ *
+ * Model is initialized
+ */
+
+ /**
+ * @event itemUpdate
+ * @param {mw.rcfilters.dm.SavedQueryItemModel} Changed item
+ *
+ * An item has changed
+ */
+
+ /**
+ * @event default
+ * @param {string} New default ID
+ *
+ * The default has changed
+ */
+
+ /* Methods */
+
+ /**
+ * Initialize the saved queries model by reading it from the user's settings.
+ * The structure of the saved queries is:
+ * {
+ * default: (string) Query ID
+ * queries:{
+ * query_id_1: {
+ * data:{
+ * filters: (Object) Minimal definition of the filters
+ * highlights: (Object) Definition of the highlights
+ * },
+ * label: (optional) Name of this query
+ * }
+ * }
+ * }
+ *
+ * @param {Object} [savedQueries] An object with the saved queries with
+ * the above structure.
+ * @param {Object} [baseState] An object representing the base state
+ * so we can normalize the data
+ * @param {string[]} [ignoreFilters] Filters to ignore and remove from
+ * the data
+ * @fires initialize
+ */
+ mw.rcfilters.dm.SavedQueriesModel.prototype.initialize = function ( savedQueries, baseState, ignoreFilters ) {
+ var items = [],
+ defaultItem = null;
+
+ savedQueries = savedQueries || {};
+ ignoreFilters = ignoreFilters || {};
+
+ this.baseState = baseState;
+
+ this.clearItems();
+ $.each( savedQueries.queries || {}, function ( id, obj ) {
+ var item,
+ normalizedData = $.extend( true, {}, baseState, obj.data ),
+ isDefault = String( savedQueries.default ) === String( id );
+
+ // Backwards-compat fix: We stored the 'highlight' state with
+ // "1" and "0" instead of true/false; for already-stored states,
+ // we need to fix that.
+ // NOTE: Since this feature is only available in beta, we should
+ // not need this line when we release this to the general wikis.
+ // This method will automatically fix all saved queries anyways
+ // for existing users, who are only betalabs users at the moment.
+ normalizedData.highlights.highlight = !!Number( normalizedData.highlights.highlight );
+
+ // Backwards-compat fix: Remove sticky parameters from the 'ignoreFilters' list
+ ignoreFilters.forEach( function ( name ) {
+ delete normalizedData.filters[ name ];
+ } );
+
+ item = new mw.rcfilters.dm.SavedQueryItemModel(
+ id,
+ obj.label,
+ normalizedData,
+ { 'default': isDefault }
+ );
+
+ if ( isDefault ) {
+ defaultItem = item;
+ }
+
+ items.push( item );
+ } );
+
+ if ( defaultItem ) {
+ this.default = defaultItem.getID();
+ }
+
+ this.addItems( items );
+
+ this.emit( 'initialize' );
+ };
+
+ /**
+ * Add a query item
+ *
+ * @param {string} label Label for the new query
+ * @param {Object} data Data for the new query
+ * @return {string} ID of the newly added query
+ */
+ mw.rcfilters.dm.SavedQueriesModel.prototype.addNewQuery = function ( label, data ) {
+ var randomID = ( new Date() ).getTime(),
+ normalizedData = $.extend( true, {}, this.baseState, data );
+
+ // Add item
+ this.addItems( [
+ new mw.rcfilters.dm.SavedQueryItemModel(
+ randomID,
+ label,
+ normalizedData
+ )
+ ] );
+
+ return randomID;
+ };
+
+ /**
+ * Remove query from model
+ *
+ * @param {string} queryID Query ID
+ */
+ mw.rcfilters.dm.SavedQueriesModel.prototype.removeQuery = function ( queryID ) {
+ var query = this.getItemByID( queryID );
+
+ if ( query ) {
+ // Check if this item was the default
+ if ( String( this.getDefault() ) === String( queryID ) ) {
+ // Nulify the default
+ this.setDefault( null );
+ }
+
+ this.removeItems( [ query ] );
+ }
+ };
+
+ /**
+ * Get an item that matches the requested query
+ *
+ * @param {Object} fullQueryComparison Object representing all filters and highlights to compare
+ * @return {mw.rcfilters.dm.SavedQueryItemModel} Matching item model
+ */
+ mw.rcfilters.dm.SavedQueriesModel.prototype.findMatchingQuery = function ( fullQueryComparison ) {
+ var model = this;
+
+ fullQueryComparison = this.getDifferenceFromBase( fullQueryComparison );
+
+ return this.getItems().filter( function ( item ) {
+ var comparedData = model.getDifferenceFromBase( item.getData() );
+ return OO.compare(
+ comparedData,
+ fullQueryComparison
+ );
+ } )[ 0 ];
+ };
+
+ /**
+ * Get a minimal representation of the state for comparison
+ *
+ * @param {Object} state Given state
+ * @return {Object} Minimal state
+ */
+ mw.rcfilters.dm.SavedQueriesModel.prototype.getDifferenceFromBase = function ( state ) {
+ var result = { filters: {}, highlights: {}, invert: state.invert },
+ baseState = this.baseState;
+
+ // XOR results
+ $.each( state.filters, function ( name, value ) {
+ if ( baseState.filters !== undefined && baseState.filters[ name ] !== value ) {
+ result.filters[ name ] = value;
+ }
+ } );
+
+ $.each( state.highlights, function ( name, value ) {
+ if ( baseState.highlights !== undefined && baseState.highlights[ name ] !== value && name !== 'highlight' ) {
+ result.highlights[ name ] = value;
+ }
+ } );
+
+ return result;
+ };
+ /**
+ * Get query by its identifier
+ *
+ * @param {string} queryID Query identifier
+ * @return {mw.rcfilters.dm.SavedQueryItemModel|undefined} Item matching
+ * the search. Undefined if not found.
+ */
+ mw.rcfilters.dm.SavedQueriesModel.prototype.getItemByID = function ( queryID ) {
+ return this.getItems().filter( function ( item ) {
+ return item.getID() === queryID;
+ } )[ 0 ];
+ };
+
+ /**
+ * Get the object representing the state of the entire model and items
+ *
+ * @return {Object} Object representing the state of the model and items
+ */
+ mw.rcfilters.dm.SavedQueriesModel.prototype.getState = function () {
+ var obj = { queries: {} };
+
+ // Translate the items to the saved object
+ this.getItems().forEach( function ( item ) {
+ var itemState = item.getState();
+
+ obj.queries[ item.getID() ] = itemState;
+ } );
+
+ if ( this.getDefault() ) {
+ obj.default = this.getDefault();
+ }
+
+ return obj;
+ };
+
+ /**
+ * Set a default query. Null to unset default.
+ *
+ * @param {string} itemID Query identifier
+ * @fires default
+ */
+ mw.rcfilters.dm.SavedQueriesModel.prototype.setDefault = function ( itemID ) {
+ if ( this.default !== itemID ) {
+ this.default = itemID;
+
+ // Set for individual itens
+ this.getItems().forEach( function ( item ) {
+ item.toggleDefault( item.getID() === itemID );
+ } );
+
+ this.emit( 'default', itemID );
+ }
+ };
+
+ /**
+ * Get the default query ID
+ *
+ * @return {string} Default query identifier
+ */
+ mw.rcfilters.dm.SavedQueriesModel.prototype.getDefault = function () {
+ return this.default;
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueryItemModel.js b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueryItemModel.js
new file mode 100644
index 00000000..81c8306c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueryItemModel.js
@@ -0,0 +1,116 @@
+( function ( mw ) {
+ /**
+ * View model for a single saved query
+ *
+ * @class
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {string} id Unique identifier
+ * @param {string} label Saved query label
+ * @param {Object} data Saved query data
+ * @param {Object} [config] Configuration options
+ * @param {boolean} [default] This item is the default
+ */
+ mw.rcfilters.dm.SavedQueryItemModel = function MwRcfiltersDmSavedQueriesModel( id, label, data, config ) {
+ config = config || {};
+
+ // Mixin constructor
+ OO.EventEmitter.call( this );
+
+ this.id = id;
+ this.label = label;
+ this.data = data;
+ this.default = !!config.default;
+ };
+
+ /* Initialization */
+
+ OO.initClass( mw.rcfilters.dm.SavedQueryItemModel );
+ OO.mixinClass( mw.rcfilters.dm.SavedQueryItemModel, OO.EventEmitter );
+
+ /* Events */
+
+ /**
+ * @event update
+ *
+ * Model has been updated
+ */
+
+ /* Methods */
+
+ /**
+ * Get an object representing the state of this item
+ *
+ * @return {Object} Object representing the current data state
+ * of the object
+ */
+ mw.rcfilters.dm.SavedQueryItemModel.prototype.getState = function () {
+ return {
+ data: this.getData(),
+ label: this.getLabel()
+ };
+ };
+
+ /**
+ * Get the query's identifier
+ *
+ * @return {string} Query identifier
+ */
+ mw.rcfilters.dm.SavedQueryItemModel.prototype.getID = function () {
+ return this.id;
+ };
+
+ /**
+ * Get query label
+ *
+ * @return {string} Query label
+ */
+ mw.rcfilters.dm.SavedQueryItemModel.prototype.getLabel = function () {
+ return this.label;
+ };
+
+ /**
+ * Update the query label
+ *
+ * @param {string} newLabel New label
+ */
+ mw.rcfilters.dm.SavedQueryItemModel.prototype.updateLabel = function ( newLabel ) {
+ if ( newLabel && this.label !== newLabel ) {
+ this.label = newLabel;
+ this.emit( 'update' );
+ }
+ };
+
+ /**
+ * Get query data
+ *
+ * @return {Object} Object representing parameter and highlight data
+ */
+ mw.rcfilters.dm.SavedQueryItemModel.prototype.getData = function () {
+ return this.data;
+ };
+
+ /**
+ * Check whether this item is the default
+ *
+ * @return {boolean} Query is set to be default
+ */
+ mw.rcfilters.dm.SavedQueryItemModel.prototype.isDefault = function () {
+ return this.default;
+ };
+
+ /**
+ * Toggle the default state of this query item
+ *
+ * @param {boolean} isDefault Query is default
+ */
+ mw.rcfilters.dm.SavedQueryItemModel.prototype.toggleDefault = function ( isDefault ) {
+ isDefault = isDefault === undefined ? !this.default : isDefault;
+
+ if ( this.default !== isDefault ) {
+ this.default = isDefault;
+ this.emit( 'update' );
+ }
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/images/clip.svg b/www/wiki/resources/src/mediawiki.rcfilters/images/clip.svg
new file mode 100644
index 00000000..86d1dbfb
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/images/clip.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.5 4.5v13.2L12 13.5l-5.5 4.2V4.5zM5 21l7-6 7 6V3H5z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/images/pending.gif b/www/wiki/resources/src/mediawiki.rcfilters/images/pending.gif
new file mode 100644
index 00000000..1194eed2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/images/pending.gif
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/images/pushPin.svg b/www/wiki/resources/src/mediawiki.rcfilters/images/pushPin.svg
new file mode 100644
index 00000000..b852cd06
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/images/pushPin.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M17.445 12.225c-.813-.935-1.775-.739-2.883-1.768-.55-.511-.498-2.36-.498-2.36s-.041-1.836.524-2.401c.39-.39 1.076-.49 1.475-.883a.973.973 0 0 0 .217-.317c.007-.013.014-.023.018-.035.035-.092.054-.2.064-.316.003-.03.017-.055.017-.085 0-.005-.003-.01-.004-.015.001-.008.004-.014.004-.022 0-.02-.015-.03-.017-.048a1.052 1.052 0 0 0-1.043-.974H8.681c-.555 0-.997.43-1.043.974-.002.018-.017.028-.017.048 0 .008.003.014.003.022 0 .006-.003.01-.003.015 0 .03.014.055.017.085.01.116.029.224.064.316.004.012.012.022.018.035a.965.965 0 0 0 .217.317c.399.393 1.084.493 1.475.883.565.565.523 2.401.523 2.401s.053 1.849-.497 2.36c-1.108 1.03-2.07.833-2.883 1.768C5.979 12.887 6 14 6 14h5.333v4.578L12 21l.668-2.422V14H18s.02-1.113-.555-1.775z"/>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/images/unClip.svg b/www/wiki/resources/src/mediawiki.rcfilters/images/unClip.svg
new file mode 100644
index 00000000..68459db6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/images/unClip.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24">
+ <path d="M5 21l7-6 7 6V3H5z" fill-rule="evenodd"/>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js b/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
new file mode 100644
index 00000000..507c9793
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js
@@ -0,0 +1,1300 @@
+( function ( mw, $ ) {
+ /* eslint no-underscore-dangle: "off" */
+ /**
+ * Controller for the filters in Recent Changes
+ * @class
+ *
+ * @constructor
+ * @param {mw.rcfilters.dm.FiltersViewModel} filtersModel Filters view model
+ * @param {mw.rcfilters.dm.ChangesListViewModel} changesListModel Changes list view model
+ * @param {mw.rcfilters.dm.SavedQueriesModel} savedQueriesModel Saved queries model
+ * @param {Object} config Additional configuration
+ * @cfg {string} savedQueriesPreferenceName Where to save the saved queries
+ */
+ mw.rcfilters.Controller = function MwRcfiltersController( filtersModel, changesListModel, savedQueriesModel, config ) {
+ this.filtersModel = filtersModel;
+ this.changesListModel = changesListModel;
+ this.savedQueriesModel = savedQueriesModel;
+ this.savedQueriesPreferenceName = config.savedQueriesPreferenceName;
+
+ this.requestCounter = {};
+ this.baseFilterState = {};
+ this.uriProcessor = null;
+ this.initializing = false;
+
+ this.prevLoggedItems = [];
+
+ this.FILTER_CHANGE = 'filterChange';
+ this.SHOW_NEW_CHANGES = 'showNewChanges';
+ this.LIVE_UPDATE = 'liveUpdate';
+ };
+
+ /* Initialization */
+ OO.initClass( mw.rcfilters.Controller );
+
+ /**
+ * Initialize the filter and parameter states
+ *
+ * @param {Array} filterStructure Filter definition and structure for the model
+ * @param {Object} [namespaceStructure] Namespace definition
+ * @param {Object} [tagList] Tag definition
+ */
+ mw.rcfilters.Controller.prototype.initialize = function ( filterStructure, namespaceStructure, tagList ) {
+ var parsedSavedQueries,
+ displayConfig = mw.config.get( 'StructuredChangeFiltersDisplayConfig' ),
+ controller = this,
+ views = {},
+ items = [],
+ uri = new mw.Uri(),
+ $changesList = $( '.mw-changeslist' ).first().contents();
+
+ // Prepare views
+ if ( namespaceStructure ) {
+ items = [];
+ $.each( namespaceStructure, function ( namespaceID, label ) {
+ // Build and clean up the individual namespace items definition
+ items.push( {
+ name: namespaceID,
+ label: label || mw.msg( 'blanknamespace' ),
+ description: '',
+ identifiers: [
+ ( namespaceID < 0 || namespaceID % 2 === 0 ) ?
+ 'subject' : 'talk'
+ ],
+ cssClass: 'mw-changeslist-ns-' + namespaceID
+ } );
+ } );
+
+ views.namespaces = {
+ title: mw.msg( 'namespaces' ),
+ trigger: ':',
+ groups: [ {
+ // Group definition (single group)
+ name: 'namespace', // parameter name is singular
+ type: 'string_options',
+ title: mw.msg( 'namespaces' ),
+ labelPrefixKey: { 'default': 'rcfilters-tag-prefix-namespace', inverted: 'rcfilters-tag-prefix-namespace-inverted' },
+ separator: ';',
+ fullCoverage: true,
+ filters: items
+ } ]
+ };
+ }
+ if ( tagList ) {
+ views.tags = {
+ title: mw.msg( 'rcfilters-view-tags' ),
+ trigger: '#',
+ groups: [ {
+ // Group definition (single group)
+ name: 'tagfilter', // Parameter name
+ type: 'string_options',
+ title: 'rcfilters-view-tags', // Message key
+ labelPrefixKey: 'rcfilters-tag-prefix-tags',
+ separator: '|',
+ fullCoverage: false,
+ filters: tagList
+ } ]
+ };
+ }
+
+ // Add parameter range operations
+ views.range = {
+ groups: [
+ {
+ name: 'limit',
+ type: 'single_option',
+ title: '', // Because it's a hidden group, this title actually appears nowhere
+ hidden: true,
+ allowArbitrary: true,
+ validate: $.isNumeric,
+ range: {
+ min: 0, // The server normalizes negative numbers to 0 results
+ max: 1000
+ },
+ sortFunc: function ( a, b ) { return Number( a.name ) - Number( b.name ); },
+ 'default': displayConfig.limitDefault,
+ // Temporarily making this not sticky until we resolve the problem
+ // with the misleading preference. Note that if this is to be permanent
+ // we should remove all sticky behavior methods completely
+ // See T172156
+ // isSticky: true,
+ excludedFromSavedQueries: true,
+ filters: displayConfig.limitArray.map( function ( num ) {
+ return controller._createFilterDataFromNumber( num, num );
+ } )
+ },
+ {
+ name: 'days',
+ type: 'single_option',
+ title: '', // Because it's a hidden group, this title actually appears nowhere
+ hidden: true,
+ allowArbitrary: true,
+ validate: $.isNumeric,
+ range: {
+ min: 0,
+ max: displayConfig.maxDays
+ },
+ sortFunc: function ( a, b ) { return Number( a.name ) - Number( b.name ); },
+ numToLabelFunc: function ( i ) {
+ return Number( i ) < 1 ?
+ ( Number( i ) * 24 ).toFixed( 2 ) :
+ Number( i );
+ },
+ 'default': displayConfig.daysDefault,
+ // Temporarily making this not sticky while limit is not sticky, see above
+ // isSticky: true,
+ excludedFromSavedQueries: true,
+ filters: [
+ // Hours (1, 2, 6, 12)
+ 0.04166, 0.0833, 0.25, 0.5
+ // Days
+ ].concat( displayConfig.daysArray )
+ .map( function ( num ) {
+ return controller._createFilterDataFromNumber(
+ num,
+ // Convert fractions of days to number of hours for the labels
+ num < 1 ? Math.round( num * 24 ) : num
+ );
+ } )
+ }
+ ]
+ };
+
+ views.display = {
+ groups: [
+ {
+ name: 'display',
+ type: 'boolean',
+ title: '', // Because it's a hidden group, this title actually appears nowhere
+ hidden: true,
+ isSticky: true,
+ filters: [
+ {
+ name: 'enhanced',
+ 'default': String( mw.user.options.get( 'usenewrc', 0 ) )
+ }
+ ]
+ }
+ ]
+ };
+
+ // Before we do anything, we need to see if we require additional items in the
+ // groups that have 'AllowArbitrary'. For the moment, those are only single_option
+ // groups; if we ever expand it, this might need further generalization:
+ $.each( views, function ( viewName, viewData ) {
+ viewData.groups.forEach( function ( groupData ) {
+ var extraValues = [];
+ if ( groupData.allowArbitrary ) {
+ // If the value in the URI isn't in the group, add it
+ if ( uri.query[ groupData.name ] !== undefined ) {
+ extraValues.push( uri.query[ groupData.name ] );
+ }
+ // If the default value isn't in the group, add it
+ if ( groupData.default !== undefined ) {
+ extraValues.push( String( groupData.default ) );
+ }
+ controller.addNumberValuesToGroup( groupData, extraValues );
+ }
+ } );
+ } );
+
+ // Initialize the model
+ this.filtersModel.initializeFilters( filterStructure, views );
+
+ this._buildBaseFilterState();
+
+ this.uriProcessor = new mw.rcfilters.UriProcessor(
+ this.filtersModel
+ );
+
+ if ( !mw.user.isAnon() ) {
+ try {
+ parsedSavedQueries = JSON.parse( mw.user.options.get( this.savedQueriesPreferenceName ) || '{}' );
+ } catch ( err ) {
+ parsedSavedQueries = {};
+ }
+
+ // The queries are saved in a minimized state, so we need
+ // to send over the base state so the saved queries model
+ // can normalize them per each query item
+ this.savedQueriesModel.initialize(
+ parsedSavedQueries,
+ this._getBaseFilterState(),
+ // This is for backwards compatibility - delete all excluded filter states
+ Object.keys( this.filtersModel.getExcludedFiltersState() )
+ );
+ }
+
+ // Check whether we need to load defaults.
+ // We do this by checking whether the current URI query
+ // contains any parameters recognized by the system.
+ // If it does, we load the given state.
+ // If it doesn't, we have no values at all, and we assume
+ // the user loads the base-page and we load defaults.
+ // Defaults should only be applied on load (if necessary)
+ // or on request
+ this.initializing = true;
+ if (
+ !mw.user.isAnon() && this.savedQueriesModel.getDefault() &&
+ !this.uriProcessor.doesQueryContainRecognizedParams( uri.query )
+ ) {
+ // We have defaults from a saved query.
+ // We will load them straight-forward (as if
+ // they were clicked in the menu) so we trigger
+ // a full ajax request and change of URL
+ this.applySavedQuery( this.savedQueriesModel.getDefault() );
+ } else {
+ // There are either recognized parameters in the URL
+ // or there are none, but there is also no default
+ // saved query (so defaults are from the backend)
+ // We want to update the state but not fetch results
+ // again
+ this.updateStateFromUrl( false );
+
+ // Update the changes list with the existing data
+ // so it gets processed
+ this.changesListModel.update(
+ $changesList.length ? $changesList : 'NO_RESULTS',
+ $( 'fieldset.cloptions' ).first(),
+ true // We're using existing DOM elements
+ );
+ }
+
+ this.initializing = false;
+ this.switchView( 'default' );
+
+ this._scheduleLiveUpdate();
+ };
+
+ /**
+ * Create filter data from a number, for the filters that are numerical value
+ *
+ * @param {Number} num Number
+ * @param {Number} numForDisplay Number for the label
+ * @return {Object} Filter data
+ */
+ mw.rcfilters.Controller.prototype._createFilterDataFromNumber = function ( num, numForDisplay ) {
+ return {
+ name: String( num ),
+ label: mw.language.convertNumber( numForDisplay )
+ };
+ };
+
+ /**
+ * Add an arbitrary values to groups that allow arbitrary values
+ *
+ * @param {Object} groupData Group data
+ * @param {string|string[]} arbitraryValues An array of arbitrary values to add to the group
+ */
+ mw.rcfilters.Controller.prototype.addNumberValuesToGroup = function ( groupData, arbitraryValues ) {
+ var controller = this,
+ normalizeWithinRange = function ( range, val ) {
+ if ( val < range.min ) {
+ return range.min; // Min
+ } else if ( val >= range.max ) {
+ return range.max; // Max
+ }
+ return val;
+ };
+
+ arbitraryValues = Array.isArray( arbitraryValues ) ? arbitraryValues : [ arbitraryValues ];
+
+ // Normalize the arbitrary values and the default value for a range
+ if ( groupData.range ) {
+ arbitraryValues = arbitraryValues.map( function ( val ) {
+ return normalizeWithinRange( groupData.range, val );
+ } );
+
+ // Normalize the default, since that's user defined
+ if ( groupData.default !== undefined ) {
+ groupData.default = String( normalizeWithinRange( groupData.range, groupData.default ) );
+ }
+ }
+
+ // This is only true for single_option group
+ // We assume these are the only groups that will allow for
+ // arbitrary, since it doesn't make any sense for the other
+ // groups.
+ arbitraryValues.forEach( function ( val ) {
+ if (
+ // If the group allows for arbitrary data
+ groupData.allowArbitrary &&
+ // and it is single_option (or string_options, but we
+ // don't have cases of those yet, nor do we plan to)
+ groupData.type === 'single_option' &&
+ // and, if there is a validate method and it passes on
+ // the data
+ ( !groupData.validate || groupData.validate( val ) ) &&
+ // but if that value isn't already in the definition
+ groupData.filters
+ .map( function ( filterData ) {
+ return String( filterData.name );
+ } )
+ .indexOf( String( val ) ) === -1
+ ) {
+ // Add the filter information
+ groupData.filters.push( controller._createFilterDataFromNumber(
+ val,
+ groupData.numToLabelFunc ?
+ groupData.numToLabelFunc( val ) :
+ val
+ ) );
+
+ // If there's a sort function set up, re-sort the values
+ if ( groupData.sortFunc ) {
+ groupData.filters.sort( groupData.sortFunc );
+ }
+ }
+ } );
+ };
+
+ /**
+ * Switch the view of the filters model
+ *
+ * @param {string} view Requested view
+ */
+ mw.rcfilters.Controller.prototype.switchView = function ( view ) {
+ this.filtersModel.switchView( view );
+ };
+
+ /**
+ * Reset to default filters
+ */
+ mw.rcfilters.Controller.prototype.resetToDefaults = function () {
+ this.uriProcessor.updateModelBasedOnQuery( this._getDefaultParams() );
+
+ this.updateChangesList();
+ };
+
+ /**
+ * Check whether the default values of the filters are all false.
+ *
+ * @return {boolean} Defaults are all false
+ */
+ mw.rcfilters.Controller.prototype.areDefaultsEmpty = function () {
+ var defaultFilters = this.filtersModel.getFiltersFromParameters( this._getDefaultParams() );
+
+ this._deleteExcludedValuesFromFilterState( defaultFilters );
+
+ // Defaults can change in a session, so we need to do this every time
+ return Object.keys( defaultFilters ).every( function ( filterName ) {
+ return !defaultFilters[ filterName ];
+ } );
+ };
+
+ /**
+ * Empty all selected filters
+ */
+ mw.rcfilters.Controller.prototype.emptyFilters = function () {
+ var highlightedFilterNames = this.filtersModel
+ .getHighlightedItems()
+ .map( function ( filterItem ) { return { name: filterItem.getName() }; } );
+
+ this.filtersModel.emptyAllFilters();
+ this.filtersModel.clearAllHighlightColors();
+ // Check all filter interactions
+ this.filtersModel.reassessFilterInteractions();
+
+ this.updateChangesList();
+
+ if ( highlightedFilterNames ) {
+ this._trackHighlight( 'clearAll', highlightedFilterNames );
+ }
+ };
+
+ /**
+ * Update the selected state of a filter
+ *
+ * @param {string} filterName Filter name
+ * @param {boolean} [isSelected] Filter selected state
+ */
+ mw.rcfilters.Controller.prototype.toggleFilterSelect = function ( filterName, isSelected ) {
+ var filterItem = this.filtersModel.getItemByName( filterName );
+
+ if ( !filterItem ) {
+ // If no filter was found, break
+ return;
+ }
+
+ isSelected = isSelected === undefined ? !filterItem.isSelected() : isSelected;
+
+ if ( filterItem.isSelected() !== isSelected ) {
+ this.filtersModel.toggleFilterSelected( filterName, isSelected );
+
+ this.updateChangesList();
+
+ // Check filter interactions
+ this.filtersModel.reassessFilterInteractions( filterItem );
+ }
+ };
+
+ /**
+ * Clear both highlight and selection of a filter
+ *
+ * @param {string} filterName Name of the filter item
+ */
+ mw.rcfilters.Controller.prototype.clearFilter = function ( filterName ) {
+ var filterItem = this.filtersModel.getItemByName( filterName ),
+ isHighlighted = filterItem.isHighlighted();
+
+ if ( filterItem.isSelected() || isHighlighted ) {
+ this.filtersModel.clearHighlightColor( filterName );
+ this.filtersModel.toggleFilterSelected( filterName, false );
+ this.updateChangesList();
+ this.filtersModel.reassessFilterInteractions( filterItem );
+
+ // Log filter grouping
+ this.trackFilterGroupings( 'removefilter' );
+ }
+
+ if ( isHighlighted ) {
+ this._trackHighlight( 'clear', filterName );
+ }
+ };
+
+ /**
+ * Toggle the highlight feature on and off
+ */
+ mw.rcfilters.Controller.prototype.toggleHighlight = function () {
+ this.filtersModel.toggleHighlight();
+ this._updateURL();
+
+ if ( this.filtersModel.isHighlightEnabled() ) {
+ mw.hook( 'RcFilters.highlight.enable' ).fire();
+ }
+ };
+
+ /**
+ * Toggle the namespaces inverted feature on and off
+ */
+ mw.rcfilters.Controller.prototype.toggleInvertedNamespaces = function () {
+ this.filtersModel.toggleInvertedNamespaces();
+
+ if (
+ this.filtersModel.getFiltersByView( 'namespaces' ).filter(
+ function ( filterItem ) { return filterItem.isSelected(); }
+ ).length
+ ) {
+ // Only re-fetch results if there are namespace items that are actually selected
+ this.updateChangesList();
+ }
+ };
+
+ /**
+ * Set the highlight color for a filter item
+ *
+ * @param {string} filterName Name of the filter item
+ * @param {string} color Selected color
+ */
+ mw.rcfilters.Controller.prototype.setHighlightColor = function ( filterName, color ) {
+ this.filtersModel.setHighlightColor( filterName, color );
+ this._updateURL();
+ this._trackHighlight( 'set', { name: filterName, color: color } );
+ };
+
+ /**
+ * Clear highlight for a filter item
+ *
+ * @param {string} filterName Name of the filter item
+ */
+ mw.rcfilters.Controller.prototype.clearHighlightColor = function ( filterName ) {
+ this.filtersModel.clearHighlightColor( filterName );
+ this._updateURL();
+ this._trackHighlight( 'clear', filterName );
+ };
+
+ /**
+ * Enable or disable live updates.
+ * @param {boolean} enable True to enable, false to disable
+ */
+ mw.rcfilters.Controller.prototype.toggleLiveUpdate = function ( enable ) {
+ this.changesListModel.toggleLiveUpdate( enable );
+ if ( this.changesListModel.getLiveUpdate() && this.changesListModel.getNewChangesExist() ) {
+ this.updateChangesList( null, this.LIVE_UPDATE );
+ }
+ };
+
+ /**
+ * Set a timeout for the next live update.
+ * @private
+ */
+ mw.rcfilters.Controller.prototype._scheduleLiveUpdate = function () {
+ setTimeout( this._doLiveUpdate.bind( this ), 3000 );
+ };
+
+ /**
+ * Perform a live update.
+ * @private
+ */
+ mw.rcfilters.Controller.prototype._doLiveUpdate = function () {
+ if ( !this._shouldCheckForNewChanges() ) {
+ // skip this turn and check back later
+ this._scheduleLiveUpdate();
+ return;
+ }
+
+ this._checkForNewChanges()
+ .then( function ( newChanges ) {
+ if ( !this._shouldCheckForNewChanges() ) {
+ // by the time the response is received,
+ // it may not be appropriate anymore
+ return;
+ }
+
+ if ( newChanges ) {
+ if ( this.changesListModel.getLiveUpdate() ) {
+ return this.updateChangesList( null, this.LIVE_UPDATE );
+ } else {
+ this.changesListModel.setNewChangesExist( true );
+ }
+ }
+ }.bind( this ) )
+ .always( this._scheduleLiveUpdate.bind( this ) );
+ };
+
+ /**
+ * @return {boolean} It's appropriate to check for new changes now
+ * @private
+ */
+ mw.rcfilters.Controller.prototype._shouldCheckForNewChanges = function () {
+ return !document.hidden &&
+ !this.filtersModel.hasConflict() &&
+ !this.changesListModel.getNewChangesExist() &&
+ !this.updatingChangesList &&
+ this.changesListModel.getNextFrom();
+ };
+
+ /**
+ * Check if new changes, newer than those currently shown, are available
+ *
+ * @return {jQuery.Promise} Promise object that resolves with a bool
+ * specifying if there are new changes or not
+ *
+ * @private
+ */
+ mw.rcfilters.Controller.prototype._checkForNewChanges = function () {
+ var params = {
+ limit: 1,
+ peek: 1, // bypasses ChangesList specific UI
+ from: this.changesListModel.getNextFrom()
+ };
+ return this._queryChangesList( 'liveUpdate', params ).then(
+ function ( data ) {
+ // no result is 204 with the 'peek' param
+ return data.status === 200;
+ }
+ );
+ };
+
+ /**
+ * Show the new changes
+ *
+ * @return {jQuery.Promise} Promise object that resolves after
+ * fetching and showing the new changes
+ */
+ mw.rcfilters.Controller.prototype.showNewChanges = function () {
+ return this.updateChangesList( null, this.SHOW_NEW_CHANGES );
+ };
+
+ /**
+ * Save the current model state as a saved query
+ *
+ * @param {string} [label] Label of the saved query
+ * @param {boolean} [setAsDefault=false] This query should be set as the default
+ */
+ mw.rcfilters.Controller.prototype.saveCurrentQuery = function ( label, setAsDefault ) {
+ var queryID,
+ highlightedItems = {},
+ highlightEnabled = this.filtersModel.isHighlightEnabled(),
+ selectedState = this.filtersModel.getSelectedState();
+
+ // Prepare highlights
+ this.filtersModel.getHighlightedItems().forEach( function ( item ) {
+ highlightedItems[ item.getName() ] = highlightEnabled ?
+ item.getHighlightColor() : null;
+ } );
+ // These are filter states; highlight is stored as boolean
+ highlightedItems.highlight = this.filtersModel.isHighlightEnabled();
+
+ // Delete all excluded filters
+ this._deleteExcludedValuesFromFilterState( selectedState );
+
+ // Add item
+ queryID = this.savedQueriesModel.addNewQuery(
+ label || mw.msg( 'rcfilters-savedqueries-defaultlabel' ),
+ {
+ filters: selectedState,
+ highlights: highlightedItems,
+ invert: this.filtersModel.areNamespacesInverted()
+ }
+ );
+
+ if ( setAsDefault ) {
+ this.savedQueriesModel.setDefault( queryID );
+ }
+
+ // Save item
+ this._saveSavedQueries();
+ };
+
+ /**
+ * Remove a saved query
+ *
+ * @param {string} queryID Query id
+ */
+ mw.rcfilters.Controller.prototype.removeSavedQuery = function ( queryID ) {
+ this.savedQueriesModel.removeQuery( queryID );
+
+ this._saveSavedQueries();
+ };
+
+ /**
+ * Rename a saved query
+ *
+ * @param {string} queryID Query id
+ * @param {string} newLabel New label for the query
+ */
+ mw.rcfilters.Controller.prototype.renameSavedQuery = function ( queryID, newLabel ) {
+ var queryItem = this.savedQueriesModel.getItemByID( queryID );
+
+ if ( queryItem ) {
+ queryItem.updateLabel( newLabel );
+ }
+ this._saveSavedQueries();
+ };
+
+ /**
+ * Set a saved query as default
+ *
+ * @param {string} queryID Query Id. If null is given, default
+ * query is reset.
+ */
+ mw.rcfilters.Controller.prototype.setDefaultSavedQuery = function ( queryID ) {
+ this.savedQueriesModel.setDefault( queryID );
+ this._saveSavedQueries();
+ };
+
+ /**
+ * Load a saved query
+ *
+ * @param {string} queryID Query id
+ */
+ mw.rcfilters.Controller.prototype.applySavedQuery = function ( queryID ) {
+ var data, highlights,
+ queryItem = this.savedQueriesModel.getItemByID( queryID ),
+ currentMatchingQuery = this.findQueryMatchingCurrentState();
+
+ if (
+ queryItem &&
+ (
+ // If there's already a query, don't reload it
+ // if it's the same as the one that already exists
+ !currentMatchingQuery ||
+ currentMatchingQuery.getID() !== queryItem.getID()
+ )
+ ) {
+ data = queryItem.getData();
+ highlights = data.highlights;
+
+ // Backwards compatibility; initial version mispelled 'highlight' with 'highlights'
+ highlights.highlight = highlights.highlights || highlights.highlight;
+
+ // Update model state from filters
+ this.filtersModel.toggleFiltersSelected(
+ // Merge filters with excluded values
+ $.extend( true, {}, data.filters, this.filtersModel.getExcludedFiltersState() )
+ );
+
+ // Update namespace inverted property
+ this.filtersModel.toggleInvertedNamespaces( !!Number( data.invert ) );
+
+ // Update highlight state
+ this.filtersModel.toggleHighlight( !!Number( highlights.highlight ) );
+ this.filtersModel.getItems().forEach( function ( filterItem ) {
+ var color = highlights[ filterItem.getName() ];
+ if ( color ) {
+ filterItem.setHighlightColor( color );
+ } else {
+ filterItem.clearHighlightColor();
+ }
+ } );
+
+ // Check all filter interactions
+ this.filtersModel.reassessFilterInteractions();
+
+ this.updateChangesList();
+
+ // Log filter grouping
+ this.trackFilterGroupings( 'savedfilters' );
+ }
+ };
+
+ /**
+ * Check whether the current filter and highlight state exists
+ * in the saved queries model.
+ *
+ * @return {boolean} Query exists
+ */
+ mw.rcfilters.Controller.prototype.findQueryMatchingCurrentState = function () {
+ var highlightedItems = {},
+ selectedState = this.filtersModel.getSelectedState();
+
+ // Prepare highlights of the current query
+ this.filtersModel.getItemsSupportingHighlights().forEach( function ( item ) {
+ highlightedItems[ item.getName() ] = item.getHighlightColor();
+ } );
+ highlightedItems.highlight = this.filtersModel.isHighlightEnabled();
+
+ // Remove anything that should be excluded from the saved query
+ // this includes sticky filters and filters marked with 'excludedFromSavedQueries'
+ this._deleteExcludedValuesFromFilterState( selectedState );
+
+ return this.savedQueriesModel.findMatchingQuery(
+ {
+ filters: selectedState,
+ highlights: highlightedItems,
+ invert: this.filtersModel.areNamespacesInverted()
+ }
+ );
+ };
+
+ /**
+ * Delete sticky filters from given object
+ *
+ * @param {Object} filterState Filter state
+ */
+ mw.rcfilters.Controller.prototype._deleteExcludedValuesFromFilterState = function ( filterState ) {
+ // Remove excluded filters
+ $.each( this.filtersModel.getExcludedFiltersState(), function ( filterName ) {
+ delete filterState[ filterName ];
+ } );
+ };
+
+ /**
+ * Get an object representing the base state of parameters
+ * and highlights.
+ *
+ * This is meant to make sure that the saved queries that are
+ * in memory are always the same structure as what we would get
+ * by calling the current model's "getSelectedState" and by checking
+ * highlight items.
+ *
+ * In cases where a user saved a query when the system had a certain
+ * set of filters, and then a filter was added to the system, we want
+ * to make sure that the stored queries can still be comparable to
+ * the current state, which means that we need the base state for
+ * two operations:
+ *
+ * - Saved queries are stored in "minimal" view (only changed filters
+ * are stored); When we initialize the system, we merge each minimal
+ * query with the base state (using 'getNormalizedFilters') so all
+ * saved queries have the exact same structure as what we would get
+ * by checking the getSelectedState of the filter.
+ * - When we save the queries, we minimize the object to only represent
+ * whatever has actually changed, rather than store the entire
+ * object. To check what actually is different so we can store it,
+ * we need to obtain a base state to compare against, this is
+ * what #_getMinimalFilterList does
+ */
+ mw.rcfilters.Controller.prototype._buildBaseFilterState = function () {
+ var defaultParams = this.filtersModel.getDefaultParams(),
+ highlightedItems = {};
+
+ // Prepare highlights
+ this.filtersModel.getItemsSupportingHighlights().forEach( function ( item ) {
+ highlightedItems[ item.getName() ] = null;
+ } );
+ highlightedItems.highlight = false;
+
+ this.baseFilterState = {
+ filters: this.filtersModel.getFiltersFromParameters( defaultParams ),
+ highlights: highlightedItems,
+ invert: false
+ };
+ };
+
+ /**
+ * Get an object representing the base filter state of both
+ * filters and highlights. The structure is similar to what we use
+ * to store each query in the saved queries object:
+ * {
+ * filters: {
+ * filterName: (bool)
+ * },
+ * highlights: {
+ * filterName: (string|null)
+ * }
+ * }
+ *
+ * @return {Object} Object representing the base state of
+ * parameters and highlights
+ */
+ mw.rcfilters.Controller.prototype._getBaseFilterState = function () {
+ return this.baseFilterState;
+ };
+
+ /**
+ * Get an object that holds only the parameters and highlights that have
+ * values different than the base default value.
+ *
+ * This is the reverse of the normalization we do initially on loading and
+ * initializing the saved queries model.
+ *
+ * @param {Object} valuesObject Object representing the state of both
+ * filters and highlights in its normalized version, to be minimized.
+ * @return {Object} Minimal filters and highlights list
+ */
+ mw.rcfilters.Controller.prototype._getMinimalFilterList = function ( valuesObject ) {
+ var result = { filters: {}, highlights: {}, invert: valuesObject.invert },
+ baseState = this._getBaseFilterState();
+
+ // XOR results
+ $.each( valuesObject.filters, function ( name, value ) {
+ if ( baseState.filters !== undefined && baseState.filters[ name ] !== value ) {
+ result.filters[ name ] = value;
+ }
+ } );
+
+ $.each( valuesObject.highlights, function ( name, value ) {
+ if ( baseState.highlights !== undefined && baseState.highlights[ name ] !== value ) {
+ result.highlights[ name ] = value;
+ }
+ } );
+
+ return result;
+ };
+
+ /**
+ * Save the current state of the saved queries model with all
+ * query item representation in the user settings.
+ */
+ mw.rcfilters.Controller.prototype._saveSavedQueries = function () {
+ var stringified,
+ state = this.savedQueriesModel.getState(),
+ controller = this;
+
+ // Minimize before save
+ $.each( state.queries, function ( queryID, info ) {
+ state.queries[ queryID ].data = controller._getMinimalFilterList( info.data );
+ } );
+
+ // Stringify state
+ stringified = JSON.stringify( state );
+
+ if ( $.byteLength( stringified ) > 65535 ) {
+ // Sanity check, since the preference can only hold that.
+ return;
+ }
+
+ // Save the preference
+ new mw.Api().saveOption( this.savedQueriesPreferenceName, stringified );
+ // Update the preference for this session
+ mw.user.options.set( this.savedQueriesPreferenceName, stringified );
+ };
+
+ /**
+ * Update sticky preferences with current model state
+ */
+ mw.rcfilters.Controller.prototype.updateStickyPreferences = function () {
+ // Update default sticky values with selected, whether they came from
+ // the initial defaults or from the URL value that is being normalized
+ this.updateDaysDefault( this.filtersModel.getGroup( 'days' ).getSelectedItems()[ 0 ].getParamName() );
+ this.updateLimitDefault( this.filtersModel.getGroup( 'limit' ).getSelectedItems()[ 0 ].getParamName() );
+
+ // TODO: Make these automatic by having the model go over sticky
+ // items and update their default values automatically
+ };
+
+ /**
+ * Update the limit default value
+ *
+ * param {number} newValue New value
+ */
+ mw.rcfilters.Controller.prototype.updateLimitDefault = function ( /* newValue */ ) {
+ // HACK: Temporarily remove this from being sticky
+ // See T172156
+
+ /*
+ if ( !$.isNumeric( newValue ) ) {
+ return;
+ }
+
+ newValue = Number( newValue );
+
+ if ( mw.user.options.get( 'rcfilters-rclimit' ) !== newValue ) {
+ // Save the preference
+ new mw.Api().saveOption( 'rcfilters-rclimit', newValue );
+ // Update the preference for this session
+ mw.user.options.set( 'rcfilters-rclimit', newValue );
+ }
+ */
+ return;
+ };
+
+ /**
+ * Update the days default value
+ *
+ * param {number} newValue New value
+ */
+ mw.rcfilters.Controller.prototype.updateDaysDefault = function ( /* newValue */ ) {
+ // HACK: Temporarily remove this from being sticky
+ // See T172156
+
+ /*
+ if ( !$.isNumeric( newValue ) ) {
+ return;
+ }
+
+ newValue = Number( newValue );
+
+ if ( mw.user.options.get( 'rcdays' ) !== newValue ) {
+ // Save the preference
+ new mw.Api().saveOption( 'rcdays', newValue );
+ // Update the preference for this session
+ mw.user.options.set( 'rcdays', newValue );
+ }
+ */
+ return;
+ };
+
+ /**
+ * Update the group by page default value
+ *
+ * @param {number} newValue New value
+ */
+ mw.rcfilters.Controller.prototype.updateGroupByPageDefault = function ( newValue ) {
+ if ( !$.isNumeric( newValue ) ) {
+ return;
+ }
+
+ newValue = Number( newValue );
+
+ if ( mw.user.options.get( 'usenewrc' ) !== newValue ) {
+ // Save the preference
+ new mw.Api().saveOption( 'usenewrc', newValue );
+ // Update the preference for this session
+ mw.user.options.set( 'usenewrc', newValue );
+ }
+ };
+
+ /**
+ * Synchronize the URL with the current state of the filters
+ * without adding an history entry.
+ */
+ mw.rcfilters.Controller.prototype.replaceUrl = function () {
+ mw.rcfilters.UriProcessor.static.replaceState( this._getUpdatedUri() );
+ };
+
+ /**
+ * Update filter state (selection and highlighting) based
+ * on current URL values.
+ *
+ * @param {boolean} [fetchChangesList=true] Fetch new results into the changes
+ * list based on the updated model.
+ */
+ mw.rcfilters.Controller.prototype.updateStateFromUrl = function ( fetchChangesList ) {
+ fetchChangesList = fetchChangesList === undefined ? true : !!fetchChangesList;
+
+ this.uriProcessor.updateModelBasedOnQuery( new mw.Uri().query );
+
+ // Update the sticky preferences, in case we received a value
+ // from the URL
+ this.updateStickyPreferences();
+
+ // Only update and fetch new results if it is requested
+ if ( fetchChangesList ) {
+ this.updateChangesList();
+ }
+ };
+
+ /**
+ * Update the list of changes and notify the model
+ *
+ * @param {Object} [params] Extra parameters to add to the API call
+ * @param {string} [updateMode='filterChange'] One of 'filterChange', 'liveUpdate', 'showNewChanges', 'markSeen'
+ * @return {jQuery.Promise} Promise that is resolved when the update is complete
+ */
+ mw.rcfilters.Controller.prototype.updateChangesList = function ( params, updateMode ) {
+ updateMode = updateMode === undefined ? this.FILTER_CHANGE : updateMode;
+
+ if ( updateMode === this.FILTER_CHANGE ) {
+ this._updateURL( params );
+ }
+ if ( updateMode === this.FILTER_CHANGE || updateMode === this.SHOW_NEW_CHANGES ) {
+ this.changesListModel.invalidate();
+ }
+ this.changesListModel.setNewChangesExist( false );
+ this.updatingChangesList = true;
+ return this._fetchChangesList()
+ .then(
+ // Success
+ function ( pieces ) {
+ var $changesListContent = pieces.changes,
+ $fieldset = pieces.fieldset;
+ this.changesListModel.update(
+ $changesListContent,
+ $fieldset,
+ false,
+ // separator between old and new changes
+ updateMode === this.SHOW_NEW_CHANGES || updateMode === this.LIVE_UPDATE
+ );
+ }.bind( this )
+ // Do nothing for failure
+ )
+ .always( function () {
+ this.updatingChangesList = false;
+ }.bind( this ) );
+ };
+
+ /**
+ * Get an object representing the default parameter state, whether
+ * it is from the model defaults or from the saved queries.
+ *
+ * @return {Object} Default parameters
+ */
+ mw.rcfilters.Controller.prototype._getDefaultParams = function () {
+ var data, queryHighlights,
+ savedParams = {},
+ savedHighlights = {},
+ defaultSavedQueryItem = !mw.user.isAnon() && this.savedQueriesModel.getItemByID( this.savedQueriesModel.getDefault() );
+
+ if ( defaultSavedQueryItem ) {
+ data = defaultSavedQueryItem.getData();
+
+ queryHighlights = data.highlights || {};
+ savedParams = this.filtersModel.getParametersFromFilters(
+ $.extend( true, {}, data.filters, this.filtersModel.getStickyFiltersState() )
+ );
+
+ // Translate highlights to parameters
+ savedHighlights.highlight = String( Number( queryHighlights.highlight ) );
+ $.each( queryHighlights, function ( filterName, color ) {
+ if ( filterName !== 'highlights' ) {
+ savedHighlights[ filterName + '_color' ] = color;
+ }
+ } );
+
+ return $.extend( true, {}, savedParams, savedHighlights, { invert: String( Number( data.invert || 0 ) ) } );
+ }
+
+ return this.filtersModel.getDefaultParams();
+ };
+
+ /**
+ * Update the URL of the page to reflect current filters
+ *
+ * This should not be called directly from outside the controller.
+ * If an action requires changing the URL, it should either use the
+ * highlighting actions below, or call #updateChangesList which does
+ * the uri corrections already.
+ *
+ * @param {Object} [params] Extra parameters to add to the API call
+ */
+ mw.rcfilters.Controller.prototype._updateURL = function ( params ) {
+ var currentUri = new mw.Uri(),
+ updatedUri = this._getUpdatedUri();
+
+ updatedUri.extend( params || {} );
+
+ if (
+ this.uriProcessor.getVersion( currentUri.query ) !== 2 ||
+ this.uriProcessor.isNewState( currentUri.query, updatedUri.query )
+ ) {
+ mw.rcfilters.UriProcessor.static.replaceState( updatedUri );
+ }
+ };
+
+ /**
+ * Get an updated mw.Uri object based on the model state
+ *
+ * @return {mw.Uri} Updated Uri
+ */
+ mw.rcfilters.Controller.prototype._getUpdatedUri = function () {
+ var uri = new mw.Uri();
+
+ // Minimize url
+ uri.query = this.uriProcessor.minimizeQuery(
+ $.extend(
+ true,
+ {},
+ // We want to retain unrecognized params
+ // The uri params from model will override
+ // any recognized value in the current uri
+ // query, retain unrecognized params, and
+ // the result will then be minimized
+ uri.query,
+ this.uriProcessor.getUriParametersFromModel(),
+ { urlversion: '2' }
+ )
+ );
+
+ return uri;
+ };
+
+ /**
+ * Query the list of changes from the server for the current filters
+ *
+ * @param {string} counterId Id for this request. To allow concurrent requests
+ * not to invalidate each other.
+ * @param {Object} [params={}] Parameters to add to the query
+ *
+ * @return {jQuery.Promise} Promise object resolved with { content, status }
+ */
+ mw.rcfilters.Controller.prototype._queryChangesList = function ( counterId, params ) {
+ var uri = this._getUpdatedUri(),
+ stickyParams = this.filtersModel.getStickyParams(),
+ requestId,
+ latestRequest;
+
+ params = params || {};
+ params.action = 'render'; // bypasses MW chrome
+
+ uri.extend( params );
+
+ this.requestCounter[ counterId ] = this.requestCounter[ counterId ] || 0;
+ requestId = ++this.requestCounter[ counterId ];
+ latestRequest = function () {
+ return requestId === this.requestCounter[ counterId ];
+ }.bind( this );
+
+ // Sticky parameters override the URL params
+ // this is to make sure that whether we represent
+ // the sticky params in the URL or not (they may
+ // be normalized out) the sticky parameters are
+ // always being sent to the server with their
+ // current/default values
+ uri.extend( stickyParams );
+
+ return $.ajax( uri.toString(), { contentType: 'html' } )
+ .then(
+ function ( content, message, jqXHR ) {
+ if ( !latestRequest() ) {
+ return $.Deferred().reject();
+ }
+ return {
+ content: content,
+ status: jqXHR.status
+ };
+ },
+ // RC returns 404 when there is no results
+ function ( jqXHR ) {
+ if ( latestRequest() ) {
+ return $.Deferred().resolve(
+ {
+ content: jqXHR.responseText,
+ status: jqXHR.status
+ }
+ ).promise();
+ }
+ }
+ );
+ };
+
+ /**
+ * Fetch the list of changes from the server for the current filters
+ *
+ * @return {jQuery.Promise} Promise object that will resolve with the changes list
+ * and the fieldset.
+ */
+ mw.rcfilters.Controller.prototype._fetchChangesList = function () {
+ return this._queryChangesList( 'updateChangesList' )
+ .then(
+ function ( data ) {
+ var $parsed = $( '<div>' ).append( $( $.parseHTML( data.content ) ) ),
+ pieces = {
+ // Changes list
+ changes: $parsed.find( '.mw-changeslist' ).first().contents(),
+ // Fieldset
+ fieldset: $parsed.find( 'fieldset.cloptions' ).first()
+ };
+
+ if ( pieces.changes.length === 0 ) {
+ pieces.changes = 'NO_RESULTS';
+ }
+
+ return pieces;
+ }
+ );
+ };
+
+ /**
+ * Track usage of highlight feature
+ *
+ * @param {string} action
+ * @param {Array|Object|string} filters
+ */
+ mw.rcfilters.Controller.prototype._trackHighlight = function ( action, filters ) {
+ filters = typeof filters === 'string' ? { name: filters } : filters;
+ filters = !Array.isArray( filters ) ? [ filters ] : filters;
+ mw.track(
+ 'event.ChangesListHighlights',
+ {
+ action: action,
+ filters: filters,
+ userId: mw.user.getId()
+ }
+ );
+ };
+
+ /**
+ * Track filter grouping usage
+ *
+ * @param {string} action Action taken
+ */
+ mw.rcfilters.Controller.prototype.trackFilterGroupings = function ( action ) {
+ var controller = this,
+ rightNow = new Date().getTime(),
+ randomIdentifier = String( mw.user.sessionId() ) + String( rightNow ) + String( Math.random() ),
+ // Get all current filters
+ filters = this.filtersModel.getSelectedItems().map( function ( item ) {
+ return item.getName();
+ } );
+
+ action = action || 'filtermenu';
+
+ // Check if these filters were the ones we just logged previously
+ // (Don't log the same grouping twice, in case the user opens/closes)
+ // the menu without action, or with the same result
+ if (
+ // Only log if the two arrays are different in size
+ filters.length !== this.prevLoggedItems.length ||
+ // Or if any filters are not the same as the cached filters
+ filters.some( function ( filterName ) {
+ return controller.prevLoggedItems.indexOf( filterName ) === -1;
+ } ) ||
+ // Or if any cached filters are not the same as given filters
+ this.prevLoggedItems.some( function ( filterName ) {
+ return filters.indexOf( filterName ) === -1;
+ } )
+ ) {
+ filters.forEach( function ( filterName ) {
+ mw.track(
+ 'event.ChangesListFilterGrouping',
+ {
+ action: action,
+ groupIdentifier: randomIdentifier,
+ filter: filterName,
+ userId: mw.user.getId()
+ }
+ );
+ } );
+
+ // Cache the filter names
+ this.prevLoggedItems = filters;
+ }
+ };
+
+ /**
+ * Mark all changes as seen on Watchlist
+ */
+ mw.rcfilters.Controller.prototype.markAllChangesAsSeen = function () {
+ var api = new mw.Api();
+ api.postWithToken( 'csrf', {
+ formatversion: 2,
+ action: 'setnotificationtimestamp',
+ entirewatchlist: true
+ } ).then( function () {
+ this.updateChangesList( null, 'markSeen' );
+ }.bind( this ) );
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.HighlightColors.js b/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.HighlightColors.js
new file mode 100644
index 00000000..0bef9028
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.HighlightColors.js
@@ -0,0 +1,10 @@
+( function ( mw ) {
+ /**
+ * Supported highlight colors.
+ * Warning: These are also hardcoded in "styles/mw.rcfilters.variables.less"
+ *
+ * @member mw.rcfilters
+ * @property {string[]}
+ */
+ mw.rcfilters.HighlightColors = [ 'c1', 'c2', 'c3', 'c4', 'c5' ];
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.UriProcessor.js b/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.UriProcessor.js
new file mode 100644
index 00000000..1894b619
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.UriProcessor.js
@@ -0,0 +1,313 @@
+( function ( mw, $ ) {
+ /* eslint no-underscore-dangle: "off" */
+ /**
+ * URI Processor for RCFilters
+ *
+ * @param {mw.rcfilters.dm.FiltersViewModel} filtersModel Filters view model
+ */
+ mw.rcfilters.UriProcessor = function MwRcfiltersController( filtersModel ) {
+ this.emptyParameterState = {};
+ this.filtersModel = filtersModel;
+
+ // Initialize
+ this._buildEmptyParameterState();
+ };
+
+ /* Initialization */
+ OO.initClass( mw.rcfilters.UriProcessor );
+
+ /* Static methods */
+
+ /**
+ * Replace the url history through replaceState
+ *
+ * @param {mw.Uri} newUri New URI to replace
+ */
+ mw.rcfilters.UriProcessor.static.replaceState = function ( newUri ) {
+ window.history.replaceState(
+ { tag: 'rcfilters' },
+ document.title,
+ newUri.toString()
+ );
+ };
+
+ /**
+ * Push the url to history through pushState
+ *
+ * @param {mw.Uri} newUri New URI to push
+ */
+ mw.rcfilters.UriProcessor.static.pushState = function ( newUri ) {
+ window.history.pushState(
+ { tag: 'rcfilters' },
+ document.title,
+ newUri.toString()
+ );
+ };
+
+ /* Methods */
+
+ /**
+ * Get the version that this URL query is tagged with.
+ *
+ * @param {Object} [uriQuery] URI query
+ * @return {number} URL version
+ */
+ mw.rcfilters.UriProcessor.prototype.getVersion = function ( uriQuery ) {
+ uriQuery = uriQuery || new mw.Uri().query;
+
+ return Number( uriQuery.urlversion || 1 );
+ };
+
+ /**
+ * Update the filters model based on the URI query
+ * This happens on initialization, and from this moment on,
+ * we consider the system synchronized, and the model serves
+ * as the source of truth for the URL.
+ *
+ * This methods should only be called once on initialiation.
+ * After initialization, the model updates the URL, not the
+ * other way around.
+ *
+ * @param {Object} [uriQuery] URI query
+ */
+ mw.rcfilters.UriProcessor.prototype.updateModelBasedOnQuery = function ( uriQuery ) {
+ var parameters;
+
+ uriQuery = uriQuery || new mw.Uri().query;
+
+ // For arbitrary numeric single_option values, check the uri and see if it's beyond the limit
+ $.each( this.filtersModel.getFilterGroups(), function ( groupName, groupModel ) {
+ if (
+ groupModel.getType() === 'single_option' &&
+ groupModel.isAllowArbitrary()
+ ) {
+ if (
+ groupModel.getMaxValue() !== null &&
+ uriQuery[ groupName ] > groupModel.getMaxValue()
+ ) {
+ // Change the value to the actual max value
+ uriQuery[ groupName ] = String( groupModel.getMaxValue() );
+ } else if (
+ groupModel.getMinValue() !== null &&
+ uriQuery[ groupName ] < groupModel.getMinValue()
+ ) {
+ // Change the value to the actual min value
+ uriQuery[ groupName ] = String( groupModel.getMinValue() );
+ }
+ }
+ } );
+
+ // Normalize
+ parameters = this._getNormalizedQueryParams( uriQuery );
+
+ // Update filter states
+ this.filtersModel.toggleFiltersSelected(
+ this.filtersModel.getFiltersFromParameters(
+ parameters
+ )
+ );
+
+ this.filtersModel.toggleInvertedNamespaces( !!Number( parameters.invert ) );
+
+ // Update highlight state
+ this.filtersModel.getItems().forEach( function ( filterItem ) {
+ var color = parameters[ filterItem.getName() + '_color' ];
+ if ( color ) {
+ filterItem.setHighlightColor( color );
+ } else {
+ filterItem.clearHighlightColor();
+ }
+ } );
+ this.filtersModel.toggleHighlight( !!Number( parameters.highlight ) );
+
+ // Check all filter interactions
+ this.filtersModel.reassessFilterInteractions();
+ };
+
+ /**
+ * Get parameters representing the current state of the model
+ *
+ * @return {Object} Uri query parameters
+ */
+ mw.rcfilters.UriProcessor.prototype.getUriParametersFromModel = function () {
+ return $.extend(
+ true,
+ {},
+ this.filtersModel.getParametersFromFilters(),
+ this.filtersModel.getHighlightParameters(),
+ {
+ highlight: String( Number( this.filtersModel.isHighlightEnabled() ) ),
+ invert: String( Number( this.filtersModel.areNamespacesInverted() ) )
+ }
+ );
+ };
+
+ /**
+ * Build the full parameter representation based on given query parameters
+ *
+ * @private
+ * @param {Object} uriQuery Given URI query
+ * @return {Object} Full parameter state representing the URI query
+ */
+ mw.rcfilters.UriProcessor.prototype._expandModelParameters = function ( uriQuery ) {
+ var filterRepresentation = this.filtersModel.getFiltersFromParameters( uriQuery );
+
+ return $.extend( true,
+ {},
+ uriQuery,
+ this.filtersModel.getParametersFromFilters( filterRepresentation ),
+ this.filtersModel.extractHighlightValues( uriQuery ),
+ {
+ highlight: String( Number( uriQuery.highlight ) ),
+ invert: String( Number( uriQuery.invert ) )
+ }
+ );
+ };
+
+ /**
+ * Compare two URI queries to decide whether they are different
+ * enough to represent a new state.
+ *
+ * @param {Object} currentUriQuery Current Uri query
+ * @param {Object} updatedUriQuery Updated Uri query
+ * @return {boolean} This is a new state
+ */
+ mw.rcfilters.UriProcessor.prototype.isNewState = function ( currentUriQuery, updatedUriQuery ) {
+ var currentParamState, updatedParamState,
+ notEquivalent = function ( obj1, obj2 ) {
+ var keys = Object.keys( obj1 ).concat( Object.keys( obj2 ) );
+ return keys.some( function ( key ) {
+ return obj1[ key ] != obj2[ key ]; // eslint-disable-line eqeqeq
+ } );
+ };
+
+ // Compare states instead of parameters
+ // This will allow us to always have a proper check of whether
+ // the requested new url is one to change or not, regardless of
+ // actual parameter visibility/representation in the URL
+ currentParamState = this._expandModelParameters( currentUriQuery );
+ updatedParamState = this._expandModelParameters( updatedUriQuery );
+
+ return notEquivalent( currentParamState, updatedParamState );
+ };
+
+ /**
+ * Check whether the given query has parameters that are
+ * recognized as parameters we should load the system with
+ *
+ * @param {mw.Uri} [uriQuery] Given URI query
+ * @return {boolean} Query contains valid recognized parameters
+ */
+ mw.rcfilters.UriProcessor.prototype.doesQueryContainRecognizedParams = function ( uriQuery ) {
+ var anyValidInUrl,
+ validParameterNames = Object.keys( this._getEmptyParameterState() )
+ .filter( function ( param ) {
+ // Remove 'highlight' parameter from this check;
+ // if it's the only parameter in the URL we still
+ // want to consider the URL 'empty' for defaults to load
+ return param !== 'highlight';
+ } );
+
+ uriQuery = uriQuery || new mw.Uri().query;
+
+ anyValidInUrl = Object.keys( uriQuery ).some( function ( parameter ) {
+ return validParameterNames.indexOf( parameter ) > -1;
+ } );
+
+ // URL version 2 is allowed to be empty or within nonrecognized params
+ return anyValidInUrl || this.getVersion( uriQuery ) === 2;
+ };
+
+ /**
+ * Remove all parameters that have the same value as the base state
+ * This method expects uri queries of the urlversion=2 format
+ *
+ * @private
+ * @param {Object} uriQuery Current uri query
+ * @return {Object} Minimized query
+ */
+ mw.rcfilters.UriProcessor.prototype.minimizeQuery = function ( uriQuery ) {
+ var baseParams = this._getEmptyParameterState(),
+ uriResult = $.extend( true, {}, uriQuery );
+
+ $.each( uriResult, function ( paramName, paramValue ) {
+ if (
+ baseParams[ paramName ] !== undefined &&
+ baseParams[ paramName ] === paramValue
+ ) {
+ // Remove parameter from query
+ delete uriResult[ paramName ];
+ }
+ } );
+
+ return uriResult;
+ };
+
+ /**
+ * Get the adjusted URI params based on the url version
+ * If the urlversion is not 2, the parameters are merged with
+ * the model's defaults.
+ *
+ * @private
+ * @param {Object} uriQuery Current URI query
+ * @return {Object} Normalized parameters
+ */
+ mw.rcfilters.UriProcessor.prototype._getNormalizedQueryParams = function ( uriQuery ) {
+ // Check whether we are dealing with urlversion=2
+ // If we are, we do not merge the initial request with
+ // defaults. Not having urlversion=2 means we need to
+ // reproduce the server-side request and merge the
+ // requested parameters (or starting state) with the
+ // wiki default.
+ // Any subsequent change of the URL through the RCFilters
+ // system will receive 'urlversion=2'
+ var hiddenParamDefaults = {},
+ base = this.getVersion( uriQuery ) === 2 ?
+ {} :
+ this.filtersModel.getDefaultParams();
+
+ // Go over the model and get all hidden parameters' defaults
+ // These defaults should be applied regardless of the urlversion
+ // but be overridden by the URL params if they exist
+ $.each( this.filtersModel.getFilterGroups(), function ( groupName, groupModel ) {
+ if ( groupModel.isHidden() ) {
+ $.extend( true, hiddenParamDefaults, groupModel.getDefaultParams() );
+ }
+ } );
+
+ return this.minimizeQuery(
+ $.extend( true, {}, hiddenParamDefaults, base, uriQuery, { urlversion: '2' } )
+ );
+ };
+
+ /**
+ * Get the representation of an empty parameter state
+ *
+ * @private
+ * @return {Object} Empty parameter state
+ */
+ mw.rcfilters.UriProcessor.prototype._getEmptyParameterState = function () {
+ // Override empty parameter state with the sticky parameter values
+ return $.extend( true, {}, this.emptyParameterState, this.filtersModel.getStickyParams() );
+ };
+
+ /**
+ * Build an empty representation of the parameters, where all parameters
+ * are either set to '0' or '' depending on their type.
+ * This must run during initialization, before highlights are set.
+ *
+ * @private
+ */
+ mw.rcfilters.UriProcessor.prototype._buildEmptyParameterState = function () {
+ var emptyParams = this.filtersModel.getParametersFromFilters( {} ),
+ emptyHighlights = this.filtersModel.getHighlightParameters();
+
+ this.emptyParameterState = $.extend(
+ true,
+ {},
+ emptyParams,
+ emptyHighlights,
+ { highlight: '0', invert: '0' }
+ );
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js b/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js
new file mode 100644
index 00000000..20c14634
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.init.js
@@ -0,0 +1,103 @@
+/*!
+ * JavaScript for Special:RecentChanges
+ */
+( function ( mw, $ ) {
+ var rcfilters = {
+ /**
+ * @member mw.rcfilters
+ * @private
+ */
+ init: function () {
+ var $topLinks,
+ rcTopSection,
+ $watchlistDetails,
+ wlTopSection,
+ savedQueriesPreferenceName = mw.config.get( 'wgStructuredChangeFiltersSavedQueriesPreferenceName' ),
+ filtersModel = new mw.rcfilters.dm.FiltersViewModel(),
+ changesListModel = new mw.rcfilters.dm.ChangesListViewModel(),
+ savedQueriesModel = new mw.rcfilters.dm.SavedQueriesModel(),
+ controller = new mw.rcfilters.Controller(
+ filtersModel, changesListModel, savedQueriesModel,
+ {
+ savedQueriesPreferenceName: savedQueriesPreferenceName
+ }
+ ),
+ $overlay = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-overlay' ),
+ filtersWidget = new mw.rcfilters.ui.FilterWrapperWidget(
+ controller, filtersModel, savedQueriesModel, changesListModel, { $overlay: $overlay } ),
+ savedLinksListWidget = new mw.rcfilters.ui.SavedLinksListWidget(
+ controller, savedQueriesModel, { $overlay: $overlay }
+ ),
+ currentPage = mw.config.get( 'wgCanonicalNamespace' ) +
+ ':' +
+ mw.config.get( 'wgCanonicalSpecialPageName' );
+
+ // TODO: The changesListWrapperWidget should be able to initialize
+ // after the model is ready.
+ // eslint-disable-next-line no-new
+ new mw.rcfilters.ui.ChangesListWrapperWidget(
+ filtersModel, changesListModel, controller, $( '.mw-changeslist, .mw-changeslist-empty' ) );
+
+ // Remove the -loading class that may have been added on the server side.
+ // If we are in fact going to load a default saved query, this .initialize()
+ // call will do that and add the -loading class right back.
+ $( 'body' ).removeClass( 'mw-rcfilters-ui-loading' );
+
+ controller.initialize(
+ mw.config.get( 'wgStructuredChangeFilters' ),
+ mw.config.get( 'wgFormattedNamespaces' ),
+ mw.config.get( 'wgRCFiltersChangeTags' )
+ );
+
+ // eslint-disable-next-line no-new
+ new mw.rcfilters.ui.FormWrapperWidget(
+ filtersModel, changesListModel, controller, $( 'fieldset.cloptions' ) );
+
+ $( '.rcfilters-container' ).append( filtersWidget.$element );
+ $( 'body' )
+ .append( $overlay )
+ .addClass( 'mw-rcfilters-ui-initialized' );
+
+ $( 'a.mw-helplink' ).attr(
+ 'href',
+ 'https://www.mediawiki.org/wiki/Special:MyLanguage/Help:New_filters_for_edit_review'
+ );
+
+ controller.replaceUrl();
+
+ if ( currentPage === 'Special:Recentchanges' ||
+ currentPage === 'Special:Recentchangeslinked' ) {
+ $topLinks = $( '.mw-recentchanges-toplinks' ).detach();
+
+ rcTopSection = new mw.rcfilters.ui.RcTopSectionWidget(
+ savedLinksListWidget, $topLinks
+ );
+ filtersWidget.setTopSection( rcTopSection.$element );
+ } // end Special:RC
+
+ if ( currentPage === 'Special:Watchlist' ) {
+ $( '#contentSub, form#mw-watchlist-resetbutton' ).detach();
+ $watchlistDetails = $( '.watchlistDetails' ).detach().contents();
+
+ wlTopSection = new mw.rcfilters.ui.WatchlistTopSectionWidget(
+ controller, changesListModel, savedLinksListWidget, $watchlistDetails
+ );
+ filtersWidget.setTopSection( wlTopSection.$element );
+ } // end Special:WL
+
+ /**
+ * Fired when initialization of the filtering interface for changes list is complete.
+ *
+ * @event structuredChangeFilters_ui_initialized
+ * @member mw.hook
+ */
+ mw.hook( 'structuredChangeFilters.ui.initialized' ).fire();
+ }
+ };
+
+ $( rcfilters.init );
+
+ module.exports = rcfilters;
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.js b/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.js
new file mode 100644
index 00000000..d2033289
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/mw.rcfilters.js
@@ -0,0 +1,53 @@
+( function ( mw ) {
+ /**
+ * @class
+ * @singleton
+ */
+ mw.rcfilters = {
+ dm: {},
+ ui: {},
+ utils: {
+ addArrayElementsUnique: function ( arr, elements ) {
+ elements = Array.isArray( elements ) ? elements : [ elements ];
+
+ elements.forEach( function ( element ) {
+ if ( arr.indexOf( element ) === -1 ) {
+ arr.push( element );
+ }
+ } );
+
+ return arr;
+ },
+ normalizeParamOptions: function ( givenOptions, legalOptions ) {
+ var result = [];
+
+ if ( givenOptions.indexOf( 'all' ) > -1 ) {
+ // If anywhere in the values there's 'all', we
+ // treat it as if only 'all' was selected.
+ // Example: param=valid1,valid2,all
+ // Result: param=all
+ return [ 'all' ];
+ }
+
+ // Get rid of any dupe and invalid parameter, only output
+ // valid ones
+ // Example: param=valid1,valid2,invalid1,valid1
+ // Result: param=valid1,valid2
+ givenOptions.forEach( function ( value ) {
+ if (
+ legalOptions.indexOf( value ) > -1 &&
+ result.indexOf( value ) === -1
+ ) {
+ result.push( value );
+ }
+ } );
+
+ return result;
+ }
+ },
+ featureFlags: {
+ liveUpdate: mw.config.get( 'wgStructuredChangeFiltersLiveUpdateSupported' ) &&
+ ( mw.user.options.get( 'rcenhancedfilters' ) || new mw.Uri().query.liveupdate )
+ }
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
new file mode 100644
index 00000000..a0bc3a2e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.less
@@ -0,0 +1,134 @@
+@import 'mediawiki.mixins.animation';
+@import 'mw.rcfilters.mixins';
+
+@rcfilters-spinner-width: 70px;
+@rcfilters-head-min-height: 200px;
+
+// Corrections for the standard special page
+.client-js {
+ .cloptions {
+ border: 0;
+ }
+
+ .rcfilters-head {
+ min-height: @rcfilters-head-min-height;
+ }
+ body:not( .mw-rcfilters-ui-initialized ) .rcfilters-head {
+ opacity: 0.5;
+ pointer-events: none;
+
+ .cloptions {
+ display: none;
+ }
+ }
+
+ .rcfilters-container {
+ min-height: 100px;
+ margin: 0;
+ }
+
+ .mw-changeslist {
+ &-empty {
+ // Hide the 'empty' message when we load rcfilters
+ // since we replace it anyways with a specific
+ // message of our own
+ display: none;
+ }
+ }
+
+ body.mw-rcfilters-ui-loading .mw-changeslist {
+ opacity: 0.5;
+ }
+
+ .rcfilters-spinner {
+ display: none;
+ position: absolute;
+ left: 50%;
+ width: @rcfilters-spinner-width;
+ // Make sure the middle of the spinner is centered, rather than its left edge
+ margin-left: -@rcfilters-spinner-width/2;
+
+ opacity: 0.8;
+ white-space: nowrap;
+
+ & .rcfilters-spinner-bounce,
+ &:before,
+ &:after {
+ content: '';
+ display: inline-block;
+ width: 12px;
+ height: 12px;
+ background-color: #c8ccd1;
+ border-radius: 100%;
+ .animation( rcfiltersBouncedelay 1.5s ease-in-out -0.16s infinite both );
+ }
+
+ &:before {
+ .animation-delay( -0.33s );
+ }
+
+ &:after {
+ .animation-delay( 0s );
+ }
+ }
+ body:not( .mw-rcfilters-ui-initialized ) .rcfilters-spinner {
+ display: block;
+ // When initializing, display the spinner on top of the area where the UI will appear
+ margin-top: -@rcfilters-head-min-height/2;
+ }
+ body.mw-rcfilters-ui-loading .rcfilters-spinner {
+ display: block;
+ // When loading new results, display the spinner on top of the results area
+ margin-top: 4em;
+ }
+
+ #contentSub,
+ .watchlistDetails,
+ form#mw-watchlist-resetbutton {
+ display: none;
+ }
+}
+
+.mw-rcfilters-staticfilters-selected {
+ font-weight: bold;
+}
+
+@-webkit-keyframes rcfiltersBouncedelay {
+ 0%,
+ 80%,
+ 100% {
+ -webkit-transform: scale( 0.7 );
+ transform: scale( 0.7 );
+ }
+ 40% {
+ background-color: #a2a9b1;
+ -webkit-transform: scale( 1 );
+ transform: scale( 1 );
+ }
+}
+
+@-moz-keyframes rcfiltersBouncedelay {
+ 0%,
+ 80%,
+ 100% {
+ -moz-transform: scale( 0.7 );
+ transform: scale( 0.7 );
+ }
+ 40% {
+ background-color: #a2a9b1;
+ -moz-transform: scale( 0.7 );
+ transform: scale( 1 );
+ }
+}
+
+@keyframes rcfiltersBouncedelay {
+ 0%,
+ 80%,
+ 100% {
+ transform: scale( 0.7 );
+ }
+ 40% {
+ background-color: #a2a9b1;
+ transform: scale( 1 );
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less
new file mode 100644
index 00000000..b4e3b0e4
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.mixins.less
@@ -0,0 +1,87 @@
+@import 'mediawiki.mixins';
+@import 'mw.rcfilters.variables';
+
+.animation-delay( ... ) {
+ -webkit-animation-delay: @arguments; // Chrome 4-42, Safari 4-8, Opera 15-29, Android 2.1-4.4.4
+ -moz-animation-delay: @arguments; // Firefox 5-15
+ animation-delay: @arguments; // Chrome 43+, Firefox 16+, IE 10+, Edge 12+, Safari 9+, Opera 12.10 & 30+, iOS 9+, Android 47+
+}
+
+// This is a general mixin for a color circle
+.mw-rcfilters-mixin-circle( @color: #fff, @diameter: 2em, @padding: 0.5em, @border: false, @borderColor: #54595d, @emptyBackground: false ) {
+ .box-sizing( border-box );
+ min-width: @diameter;
+ width: @diameter;
+ min-height: @diameter;
+ height: @diameter;
+ margin: @padding;
+ border-radius: 50%;
+
+ & when ( @emptyBackground = false ) {
+ background-color: @color;
+ }
+ & when ( @emptyBackground = true ) {
+ background-color: @highlight-none;
+ }
+
+ & when ( @border = true ) {
+ border: 1px solid @borderColor;
+ }
+}
+
+// This is the circle that appears next to the results
+// Its visibility is directly dependent on whether there is
+// a color class on its parent element
+.result-circle( @colorName: 'none' ) {
+ &-@{colorName} {
+ .mw-rcfilters-mixin-circle( ~'@{highlight-@{colorName}}', @result-circle-diameter, 0 );
+ display: none;
+
+ .mw-rcfilters-highlight-color-@{colorName} & {
+ display: inline-block;
+ }
+ }
+}
+
+// A mixin just for changesListWrapperWidget page, to output the scope of the widget
+// so it is before the rest of the rule; we need the li& to be in
+// between the wrapper scope and the color-cX class, which doesn't
+// work if the rules are inside the above widget LESS scope
+.highlight-changesListWrapperWidget( @bgcolor ) {
+ .mw-rcfilters-ui-changesListWrapperWidget li&,
+ .mw-rcfilters-ui-changesListWrapperWidget & tr:first-child,
+ .mw-rcfilters-ui-changesListWrapperWidget tr&.mw-rcfilters-ui-changesListWrapperWidget-enhanced-toplevel:not(.mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey) td:not( :nth-child( -n+2 ) ),
+ .mw-rcfilters-ui-changesListWrapperWidget tr&.mw-rcfilters-ui-changesListWrapperWidget-enhanced-nested:not(.mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey) td:not( :nth-child( -n+3 ) ) {
+ background-color: @bgcolor;
+ }
+}
+
+// This mixin produces color mixes for two, three and four colors
+.highlight-color-mix( @color1, @color2, @color3: false, @color4: false ) {
+ @highlight-color-class-var: ~'.mw-rcfilters-highlight-color-@{color1}.mw-rcfilters-highlight-color-@{color2}';
+
+ // The nature of these variables and them being inside
+ // a 'tint' and 'average' LESS functions is such where
+ // the parsing is failing if it is done inside those functions.
+ // Instead, we first construct their LESS variable names,
+ // and then we call them inside those functions by calling @@var
+ @c1var: ~'highlight-@{color1}';
+ @c2var: ~'highlight-@{color2}';
+
+ // Two colors
+ @{highlight-color-class-var} when ( @color3 = false ) and ( @color4 = false ) and not ( @color1 = false ), ( @color2 = false ) {
+ .highlight-changesListWrapperWidget( tint( average( @@c1var, @@c2var ), 50% ) );
+ }
+ // Three colors
+ @{highlight-color-class-var}.mw-rcfilters-highlight-color-@{color3} when ( @color4 = false ) and not ( @color3 = false ) {
+ @c3var: ~'highlight-@{color3}';
+ .highlight-changesListWrapperWidget( tint( mix( @@c1var, average( @@c2var, @@c3var ), 33% ), 30% ) );
+ }
+
+ // Four colors
+ @{highlight-color-class-var}.mw-rcfilters-highlight-color-@{color3}.mw-rcfilters-highlight-color-@{color4} when not ( @color4 = false ) {
+ @c3var: ~'highlight-@{color3}';
+ @c4var: ~'highlight-@{color4}';
+ .highlight-changesListWrapperWidget( tint( mix( @@c1var, mix( @@c2var, average( @@c3var, @@c4var ), 25% ), 25% ), 25% ) );
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.CapsuleItemWidget.monobook.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.CapsuleItemWidget.monobook.less
new file mode 100644
index 00000000..04e5efe0
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.CapsuleItemWidget.monobook.less
@@ -0,0 +1,9 @@
+.mw-rcfilters-ui-capsuleItemWidget {
+ .oo-ui-buttonElement {
+ // Override the vertical align for the close button
+ // for some unknown reason, this rule, in combination
+ // with the negative margin-top rule, pushes all the
+ // close buttons up above the capsule item.
+ vertical-align: baseline;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesLimitPopupWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesLimitPopupWidget.less
new file mode 100644
index 00000000..b79e54b0
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesLimitPopupWidget.less
@@ -0,0 +1,9 @@
+.mw-rcfilters-ui-changesLimitPopupWidget {
+ .oo-ui-fieldsetLayout {
+ margin-top: 1em;
+
+ .oo-ui-fieldsetLayout-header .oo-ui-labelElement-label {
+ font-size: 1em;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.highlightCircles.seenunseen.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.highlightCircles.seenunseen.less
new file mode 100644
index 00000000..deaee284
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.highlightCircles.seenunseen.less
@@ -0,0 +1,66 @@
+@import 'mw.rcfilters.mixins';
+
+.mw-rcfilters-ui-changesListWrapperWidget {
+ ul {
+ list-style: none;
+
+ li {
+ list-style: none;
+ }
+ }
+
+ // Make more specific for the overrides
+ div&-highlights {
+ display: inline-block;
+
+ &-color {
+ &-none {
+ display: inline-block;
+ .mw-changeslist-watchedseen & {
+ .mw-rcfilters-ui-changesListWrapperWidget.mw-rcfilters-ui-changesListWrapperWidget-highlighted & {
+ .mw-rcfilters-mixin-circle( @highlight-none, @result-circle-diameter, 0, true, @highlight-grey, true );
+ }
+
+ .mw-rcfilters-ui-changesListWrapperWidget:not(.mw-rcfilters-ui-changesListWrapperWidget-highlighted) & {
+ .mw-rcfilters-mixin-circle( @highlight-none, @result-circle-diameter, 0, true, @highlight-bluedot, true );
+ }
+ }
+
+ .mw-changeslist-watchedunseen & {
+ .mw-rcfilters-ui-changesListWrapperWidget.mw-rcfilters-ui-changesListWrapperWidget-highlighted & {
+ .mw-rcfilters-mixin-circle( @highlight-grey, @result-circle-diameter, 0, true, @highlight-grey );
+ }
+
+ .mw-rcfilters-ui-changesListWrapperWidget:not(.mw-rcfilters-ui-changesListWrapperWidget-highlighted) & {
+ .mw-rcfilters-mixin-circle( @highlight-bluedot, @result-circle-diameter, 0, true, @highlight-bluedot );
+ }
+ }
+
+ }
+
+ // Watchlist unseen highlighted fixes
+ // Seen (empty circle)
+ // There's no need to correct 'unseen' because that would be
+ // a filled colorful circle, which is the regular rendering
+ .mw-changeslist-watchedseen &-c1 {
+ .mw-rcfilters-mixin-circle( @highlight-c1, @result-circle-diameter, 0, true, @highlight-c1, true );
+ }
+
+ .mw-changeslist-watchedseen &-c2 {
+ .mw-rcfilters-mixin-circle( @highlight-c2, @result-circle-diameter, 0, true, @highlight-c2, true );
+ }
+
+ .mw-changeslist-watchedseen &-c3 {
+ .mw-rcfilters-mixin-circle( @highlight-c3, @result-circle-diameter, 0, true, @highlight-c3, true );
+ }
+
+ .mw-changeslist-watchedseen &-c4 {
+ .mw-rcfilters-mixin-circle( @highlight-c4, @result-circle-diameter, 0, true, @highlight-c4, true );
+ }
+
+ .mw-changeslist-watchedseen &-c5 {
+ .mw-rcfilters-mixin-circle( @highlight-c5, @result-circle-diameter, 0, true, @highlight-c5, true );
+ }
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less
new file mode 100644
index 00000000..5ef60e09
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ChangesListWrapperWidget.less
@@ -0,0 +1,189 @@
+@import 'mw.rcfilters.mixins';
+
+@keyframes fadeBlue {
+ 60% {
+ border-top-color: #36c;
+ }
+ 100% {
+ border-top-color: #c8ccd1;
+ }
+}
+
+.mw-rcfilters-ui-changesListWrapperWidget {
+
+ &-newChanges {
+ min-height: 34px;
+ margin: 8px 0 0 0;
+ text-align: center;
+ }
+
+ &-previousChangesIndicator {
+ margin: 10px 0;
+ border-top: 2px solid #c8ccd1;
+ animation: 1s ease fadeBlue;
+ }
+
+ &-results {
+ width: 35em;
+ margin: 5em auto;
+
+ &-noresult,
+ &-conflict {
+ font-weight: bold;
+ margin-bottom: 0.5em;
+ }
+ }
+
+ // Rule needs to be specific
+ // We want the expand button to appear outside the color
+ // to match the way the general highlight background appears
+ &-enhanced-grey td:not( :nth-child( -n+2 ) ) {
+ background-color: #dee0e3;
+ }
+
+ h4:first-of-type {
+ margin-top: 0;
+ padding-top: 0;
+ }
+
+ ul {
+ // Each li's margin-left should be the width of the highlights
+ // element + the margin
+ margin-left: ~'calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * 5 + @{result-circle-general-margin} )';
+ }
+
+ &-highlighted {
+ ul {
+ list-style: none;
+
+ li {
+ list-style: none;
+ }
+ }
+ }
+
+ .mw-changeslist-legend {
+ background-color: #fff;
+ }
+
+ // Correction for Enhanced RC
+ // This is outside the scope of the 'highlights' wrapper
+ table.mw-enhanced-rc {
+ margin-left: ~'calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * 5 + @{result-circle-general-margin} )';
+
+ td:last-child {
+ width: 100%;
+ }
+ }
+
+ &-highlights {
+ display: none;
+ padding: 0 @result-circle-general-margin 0 0;
+ text-align: right;
+ // The width is 5 circles times their diameter + individual margin
+ // and then plus the general margin
+ width: ~'calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * 5 )';
+ // And we want to shift the entire block to the left of the li
+ position: relative;
+ // Negative left margin of width + padding
+ margin-left: ~'calc( ( @{result-circle-diameter} + @{result-circle-margin} ) * -5 - @{result-circle-general-margin} )';
+
+ .mw-rcfilters-ui-changesListWrapperWidget-highlighted & {
+ display: inline-block;
+ }
+
+ // This needs to be very specific, since these are
+ // position rules that should apply to all overrides
+ .mw-rcfilters-ui-changesListWrapperWidget .mw-rcfilters-ui-changesListWrapperWidget-highlights > div&-circle {
+ .box-sizing( border-box );
+ margin-right: @result-circle-margin;
+ vertical-align: middle;
+ // This is to make the dots appear at the center of the
+ // text itself; it's a horrendous hack and blame JamesF for it.
+ margin-top: -2px;
+ }
+
+ &-color {
+
+ &-none {
+ .mw-rcfilters-mixin-circle( @highlight-none, @result-circle-diameter, 0, true );
+ display: inline-block;
+
+ .mw-rcfilters-highlight-color-c1 &,
+ .mw-rcfilters-highlight-color-c2 &,
+ .mw-rcfilters-highlight-color-c3 &,
+ .mw-rcfilters-highlight-color-c4 &,
+ .mw-rcfilters-highlight-color-c5 & {
+ display: none;
+ }
+ }
+ .result-circle( c1 );
+ .result-circle( c2 );
+ .result-circle( c3 );
+ .result-circle( c4 );
+ .result-circle( c5 );
+ }
+ }
+}
+
+// One color
+.mw-rcfilters-highlight-color-c1 {
+ .highlight-changesListWrapperWidget( tint( @highlight-c1, 70% ); );
+}
+
+.mw-rcfilters-highlight-color-c2 {
+ .highlight-changesListWrapperWidget( tint( @highlight-c2, 70% ); );
+}
+
+.mw-rcfilters-highlight-color-c3 {
+ .highlight-changesListWrapperWidget( tint( @highlight-c3, 70% ); );
+}
+
+.mw-rcfilters-highlight-color-c4 {
+ .highlight-changesListWrapperWidget( tint( @highlight-c4, 70% ); );
+}
+
+.mw-rcfilters-highlight-color-c5 {
+ .highlight-changesListWrapperWidget( tint( @highlight-c5, 70% ); );
+}
+
+// Two colors
+.highlight-color-mix( c1, c2 );
+// Overriding .highlight-color-mix( c1, c3 ); to produce
+// a custom color rather than the computed tint
+// see https://phabricator.wikimedia.org/T161267
+.mw-rcfilters-highlight-color-c1.mw-rcfilters-highlight-color-c3 {
+ .highlight-changesListWrapperWidget( #ccdecc );
+}
+.highlight-color-mix( c1, c4 );
+.highlight-color-mix( c1, c5 );
+.highlight-color-mix( c2, c3 );
+.highlight-color-mix( c2, c4 );
+.highlight-color-mix( c2, c5 );
+.highlight-color-mix( c3, c4 );
+.highlight-color-mix( c3, c5 );
+.highlight-color-mix( c4, c5 );
+
+// Three colors
+.highlight-color-mix( c1, c2, c3 );
+.highlight-color-mix( c1, c2, c5 );
+.highlight-color-mix( c1, c2, c4 );
+.highlight-color-mix( c1, c3, c4 );
+.highlight-color-mix( c1, c3, c5 );
+.highlight-color-mix( c1, c4, c5 );
+.highlight-color-mix( c2, c3, c4 );
+.highlight-color-mix( c2, c3, c5 );
+.highlight-color-mix( c2, c4, c5 );
+.highlight-color-mix( c3, c4, c5 );
+
+// Four colors
+.highlight-color-mix( c1, c2, c3, c4 );
+.highlight-color-mix( c1, c2, c3, c5 );
+.highlight-color-mix( c1, c2, c4, c5 );
+.highlight-color-mix( c1, c3, c4, c5 );
+.highlight-color-mix( c2, c3, c4, c5 );
+
+// Five colors:
+.mw-rcfilters-highlight-color-c1.mw-rcfilters-highlight-color-c2.mw-rcfilters-highlight-color-c3.mw-rcfilters-highlight-color-c4.mw-rcfilters-highlight-color-c5 {
+ .highlight-changesListWrapperWidget( tint( mix( @highlight-c1, mix( @highlight-c2, mix( @highlight-c3, average( @highlight-c4, @highlight-c5 ), 20% ), 20% ), 20% ), 15% ) );
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.DatePopupWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.DatePopupWidget.less
new file mode 100644
index 00000000..41557792
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.DatePopupWidget.less
@@ -0,0 +1,5 @@
+.mw-rcfilters-ui-datePopupWidget {
+ &-days {
+ margin-top: 1em;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemHighlightButton.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemHighlightButton.less
new file mode 100644
index 00000000..198f5997
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterItemHighlightButton.less
@@ -0,0 +1,30 @@
+@import 'mw.rcfilters.mixins';
+
+.mw-rcfilters-ui-filterItemHighlightButton {
+ .oo-ui-buttonWidget.oo-ui-popupButtonWidget .oo-ui-buttonElement-button > &-circle {
+ display: inline-block;
+ vertical-align: middle;
+ background-image: none;
+ margin-right: 0.2em;
+
+ &-color {
+ &-c1 {
+ // These values duplicate the sizing of the icon
+ // width/height 1.875em
+ .mw-rcfilters-mixin-circle( @highlight-c1, 1.875em, 0.2em 0 );
+ }
+ &-c2 {
+ .mw-rcfilters-mixin-circle( @highlight-c2, 1.875em, 0.2em 0 );
+ }
+ &-c3 {
+ .mw-rcfilters-mixin-circle( @highlight-c3, 1.875em, 0.2em 0 );
+ }
+ &-c4 {
+ .mw-rcfilters-mixin-circle( @highlight-c4, 1.875em, 0.2em 0 );
+ }
+ &-c5 {
+ .mw-rcfilters-mixin-circle( @highlight-c5, 1.875em, 0.2em 0 );
+ }
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuHeaderWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuHeaderWidget.less
new file mode 100644
index 00000000..d9c42bae
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuHeaderWidget.less
@@ -0,0 +1,36 @@
+@import 'mediawiki.mixins';
+
+.mw-rcfilters-ui-filterMenuHeaderWidget {
+ &-title {
+ font-size: 1.2em;
+ padding: 0.75em 0.5em;
+ // TODO: Unify colors with official design palette
+ color: #54595d;
+ }
+
+ &-header {
+ border-bottom: 1px solid #c8ccd1;
+ background: #f8f9fa;
+
+ &-invert,
+ &-highlight {
+ width: 1em;
+ vertical-align: middle;
+ // Using the same padding that the filter item
+ // uses, so the button is aligned with the highlight
+ // buttons for the filters
+ padding-right: 0.5em;
+ }
+
+ &-back {
+ width: 1em;
+ vertical-align: middle;
+ padding-left: 0.5em;
+ }
+
+ &-title {
+ width: 100%;
+ vertical-align: middle;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuOptionWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuOptionWidget.less
new file mode 100644
index 00000000..ea93247a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuOptionWidget.less
@@ -0,0 +1,26 @@
+@import 'mediawiki.mixins';
+
+.mw-rcfilters-ui-filterMenuOptionWidget {
+ &.oo-ui-flaggedElement-muted {
+ &:not( .oo-ui-optionWidget-selected ) {
+ // Namespaces are muted 'the other way around' when they
+ // are also inverted, so if they are also selected, we
+ // should make sure the selected background is shown rather
+ // than the muted one
+ background-color: #f8f9fa; // Base90 AAA
+ }
+
+ .mw-rcfilters-ui-itemMenuOptionWidget-label-title,
+ .mw-rcfilters-ui-itemMenuOptionWidget-label-desc {
+ color: #54595d; // Base20 AAA
+ }
+
+ &.oo-ui-optionWidget-highlighted {
+ // Copying over styles from OOUI, since it must
+ // override our 'muted' state
+ background-color: #eaecf0;
+ color: #000;
+ }
+ }
+
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuOptionWidget.monobook.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuOptionWidget.monobook.less
new file mode 100644
index 00000000..01b87c08
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuOptionWidget.monobook.less
@@ -0,0 +1,5 @@
+.mw-rcfilters-ui-filterMenuOptionWidget {
+ &.oo-ui-menuOptionWidget.oo-ui-optionWidget-selected > .oo-ui-iconElement-icon {
+ background-image: none;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuSectionOptionWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuSectionOptionWidget.less
new file mode 100644
index 00000000..b6fb0bbc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterMenuSectionOptionWidget.less
@@ -0,0 +1,54 @@
+@import 'mediawiki.mixins';
+
+.mw-rcfilters-ui-filterMenuSectionOptionWidget {
+ background: #eaecf0;
+ padding-bottom: 0.7em;
+
+ &-header {
+ padding: 0 0.75em;
+ // Use a high specificity to override OOUI
+ .oo-ui-optionWidget.oo-ui-labelElement &-title.oo-ui-labelElement-label {
+ color: #54595d;
+ .box-sizing( border-box );
+ display: inline-block;
+ }
+ }
+
+ &-whatsThisButton {
+ margin-left: 1.5em;
+
+ &.oo-ui-buttonElement > .oo-ui-buttonElement-button {
+ font-weight: normal;
+ border: 0; // Override OOUI `border` needed for frameless keyboard focus
+ padding: 0;
+
+ &:focus {
+ box-shadow: none;
+ outline: 0;
+ }
+ }
+
+ &-popup-content {
+ padding: 1em;
+
+ &-header {
+ font-weight: bold;
+ margin-bottom: 1em;
+ }
+
+ &-link {
+ margin: 1em 0;
+ }
+
+ .oo-ui-buttonElement-frameless.oo-ui-labelElement > .oo-ui-buttonElement-button > .oo-ui-labelElement-label {
+ margin-left: 0;
+ }
+ }
+ }
+
+ &-active {
+ .mw-rcfilters-ui-filterMenuSectionOptionWidget-header-title {
+ font-weight: bold;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterTagMultiselectWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterTagMultiselectWidget.less
new file mode 100644
index 00000000..e7233a82
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterTagMultiselectWidget.less
@@ -0,0 +1,103 @@
+@import 'mediawiki.mixins';
+
+.mw-rcfilters-ui-filterTagMultiselectWidget {
+ max-width: none;
+
+ .oo-ui-tagMultiselectWidget-input input {
+ // Make sure this uses the interface direction, not the content direction
+ direction: ltr;
+ border-bottom-right-radius: 0;
+ height: 2.5em;
+ }
+
+ &.oo-ui-widget-enabled .oo-ui-tagMultiselectWidget-handle {
+ border: 1px solid #a2a9b1;
+ border-bottom: 0;
+ background-color: #f8f9fa;
+ border-radius: 2px 2px 0 0;
+ padding: 0.6em;
+ margin-top: 1em;
+ line-height: normal;
+ }
+
+ .oo-ui-tagMultiselectWidget.oo-ui-widget-enabled &-animate.oo-ui-tagMultiselectWidget-handle {
+ .transition( background-color 500ms ease-out );
+ }
+
+ .oo-ui-tagMultiselectWidget.oo-ui-widget-enabled &-emphasize.oo-ui-tagMultiselectWidget-handle {
+ background-color: #eaf3ff; // Accent90
+ }
+
+ &-wrapper {
+ .mw-rcfilters-ui-table {
+ margin-top: 0.3em;
+ }
+
+ &-content {
+ &-title {
+ font-weight: bold;
+ color: #54595d;
+ }
+
+ &-savedQueryTitle {
+ color: #222; // Base10
+ font-weight: bold;
+ vertical-align: top;
+ margin-left: 1em;
+ width: ~'calc( 100% - 10em )';
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ }
+ }
+
+ &-views {
+ &-input {
+ width: 100%;
+ }
+
+ &-select {
+ width: 1em;
+
+ &-widget.oo-ui-widget {
+ border: 1px solid #a2a9b1;
+ border-left-width: 0;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+ border-bottom-left-radius: 0;
+
+ display: block;
+ text-align: right;
+ height: 2.5em;
+ box-sizing: border-box;
+
+ .oo-ui-buttonElement-frameless.oo-ui-iconElement:first-child {
+ margin-left: 0;
+ }
+
+ .oo-ui-labelElement.oo-ui-optionWidget.oo-ui-buttonElement:first-child {
+ margin-left: 0;
+ }
+ }
+ }
+ }
+
+ &-emptyFilters {
+ color: #72777d;
+ }
+
+ &-cell-filters {
+ width: 100%;
+
+ div.oo-ui-tagMultiselectWidget-group {
+ margin-top: 0.2em;
+ display: block;
+ }
+ }
+
+ &-cell-reset {
+ text-align: right;
+ padding-left: 0.5em;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less
new file mode 100644
index 00000000..bbd2c740
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.FilterWrapperWidget.less
@@ -0,0 +1,22 @@
+.mw-rcfilters-ui-filterWrapperWidget {
+ width: 100%;
+ // Make sure this uses the interface direction, not the content direction
+ direction: ltr;
+
+ &-viewToggleButtons {
+ margin-top: 1em;
+ }
+
+ &-bottom {
+ margin-top: 1em;
+
+ .mw-rcfilters-ui-changesLimitButtonWidget,
+ .mw-rcfilters-ui-dateButtonWidget {
+ display: inline-block;
+
+ &:not( :first-child ) {
+ margin-left: 0.5em;
+ }
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.HighlightColorPickerWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.HighlightColorPickerWidget.less
new file mode 100644
index 00000000..0adec465
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.HighlightColorPickerWidget.less
@@ -0,0 +1,96 @@
+@import 'mw.rcfilters.mixins';
+
+.mw-rcfilters-ui-highlightColorPickerWidget {
+ &-label {
+ display: block;
+ font-weight: bold;
+ font-size: 1.2em;
+ }
+
+ &-buttonSelect {
+ &-color {
+ // Override OOUI definition from padded popup; the definition
+ // forces the first-child to be margin-top:0; which overrides
+ // our definitions below where margin is 0.5em.
+ // We set up the margin-top as 0.5em for all circles so we get
+ // a consistent result
+ &.oo-ui-widget-enabled.oo-ui-optionWidget.oo-ui-buttonElement.oo-ui-buttonElement-frameless.oo-ui-buttonOptionWidget {
+ margin-top: 0.5em;
+ }
+
+ // Make the rule much more specific to override OOUI
+ .oo-ui-iconElement-icon.oo-ui-icon-check {
+ // Override OOUI icon dimensions
+ // The parent is 2em with 0.5em margin
+ // (see mw-rcfilters-mixin-circle below)
+ // so here we want 2em - 0.5em = 1.5em
+ width: 1.5em;
+ height: 1.5em;
+ // By eye, this is centered horizontally for the color circle
+ margin-left: -0.1em;
+ }
+
+ &-none {
+ .oo-ui-iconElement-icon.oo-ui-icon-check {
+ // By eye, this is centered horizontally for the white circle
+ margin-left: -0.2em;
+ }
+
+ .mw-rcfilters-mixin-circle( @highlight-none, 2em, 0.5em, true );
+ // Override border to dashed
+ border: 1px dashed #54595d;
+
+ &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+ background-color: @highlight-none;
+ }
+ }
+ &-c1 {
+ .mw-rcfilters-mixin-circle( @highlight-c1 );
+
+ &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+ background-color: @highlight-c1;
+ }
+ }
+ &-c2 {
+ .mw-rcfilters-mixin-circle( @highlight-c2 );
+
+ &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+ background-color: @highlight-c2;
+ }
+ }
+ &-c3 {
+ .mw-rcfilters-mixin-circle( @highlight-c3 );
+
+ &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+ background-color: @highlight-c3;
+ }
+ }
+ &-c4 {
+ .mw-rcfilters-mixin-circle( @highlight-c4 );
+
+ &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+ background-color: @highlight-c4;
+ }
+ }
+ &-c5 {
+ .mw-rcfilters-mixin-circle( @highlight-c5 );
+
+ &.oo-ui-buttonOptionWidget.oo-ui-buttonElement-active,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-pressed,
+ &.oo-ui-buttonOptionWidget.oo-ui-optionWidget-selected {
+ background-color: @highlight-c5;
+ }
+ }
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ItemMenuOptionWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ItemMenuOptionWidget.less
new file mode 100644
index 00000000..75ea061a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ItemMenuOptionWidget.less
@@ -0,0 +1,71 @@
+@import 'mediawiki.mixins';
+
+.mw-rcfilters-ui-itemMenuOptionWidget {
+ min-height: 3.5em;
+ padding: 0 0.5em;
+ .box-sizing( border-box );
+
+ &:not( :last-child ) {
+ border-bottom: 1px solid #eaecf0; // Base80 AAA
+ }
+
+ &-view-namespaces {
+ border-top: 5px solid #c8ccd1;
+
+ &:first-child,
+ &.mw-rcfilters-ui-itemMenuOptionWidget-identifier-subject + &.mw-rcfilters-ui-itemMenuOptionWidget-identifier-talk {
+ border-top: 0;
+ }
+ }
+
+ &:hover {
+ background-color: #f8f9fa;
+ }
+
+ .mw-rcfilters-ui-table {
+ padding-top: 0.5em;
+ }
+
+ &.oo-ui-optionWidget-selected {
+ background-color: #eaf3ff; // Accent90 AAA
+ }
+
+ &-label {
+ &-title {
+ font-weight: bold;
+ font-size: 1.15em;
+ color: #222;
+ }
+ &-desc {
+ color: #54595d;
+ white-space: normal;
+ }
+ }
+
+ &-itemCheckbox {
+ .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline {
+ // Override margin-top and -bottom rules from FieldLayout
+ margin: 0 !important; /* stylelint-disable-line declaration-no-important */
+ }
+
+ .oo-ui-checkboxInputWidget {
+ // Workaround for IE11 rendering issues. T162098
+ display: block;
+ }
+ }
+
+ .mw-rcfilters-ui-cell {
+ vertical-align: middle;
+ }
+
+ &-excludeLabel {
+ width: 5em;
+ padding-left: 1em;
+ color: #54595d; // Base20 AAA
+ }
+
+ &-highlightButton {
+ width: 4em;
+ padding-left: 1em;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.LiveUpdateButtonWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.LiveUpdateButtonWidget.less
new file mode 100644
index 00000000..04f4174d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.LiveUpdateButtonWidget.less
@@ -0,0 +1,40 @@
+.mw-rcfilters-ui-liveUpdateButtonWidget {
+ margin-left: 1em;
+
+ &.oo-ui-toggleWidget-on {
+ position: relative;
+ overflow: hidden;
+ &:after {
+ content: '';
+ mix-blend-mode: screen;
+ pointer-events: none;
+ position: absolute;
+ width: 1.875em;
+ height: 1.875em;
+ top: 1.875em / 4;
+ left: 0.46875em;
+ background: rgba( 51, 102, 204, 0.5 );
+ border-radius: 100%;
+ transform-origin: 50% 50%;
+ opacity: 0;
+ animation: ripple 1.2s ease-out infinite;
+ animation-delay: 1s;
+ }
+ }
+}
+
+@keyframes ripple {
+ 0%,
+ 35% {
+ transform: scale( 0 );
+ opacity: 1;
+ }
+ 50% {
+ transform: scale( 1.5 );
+ opacity: 0.8;
+ }
+ 100% {
+ opacity: 0;
+ transform: scale( 4 );
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less
new file mode 100644
index 00000000..24e062e6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.MenuSelectWidget.less
@@ -0,0 +1,38 @@
+@import 'mediawiki.mixins';
+
+.mw-rcfilters-ui-menuSelectWidget {
+ z-index: auto;
+ max-width: 650px;
+
+ &.oo-ui-menuSelectWidget-invisible {
+ display: block;
+ }
+
+ &-noresults {
+ display: none;
+ padding: 0.5em;
+ color: #54595d;
+
+ .oo-ui-menuSelectWidget-invisible & {
+ display: inline-block;
+ }
+ }
+
+ &-body {
+ max-height: 70vh;
+ }
+
+ &-footer {
+ padding: 0.5em;
+ background-color: #f8f9fa;
+ border-top: 1px solid #c8ccd1;
+
+ & + & {
+ border-top: 0;
+ }
+
+ &-feedback {
+ text-align: right;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.Overlay.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.Overlay.less
new file mode 100644
index 00000000..06840da7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.Overlay.less
@@ -0,0 +1,8 @@
+.mw-rcfilters-ui-overlay {
+ font-size: 0.875em;
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ z-index: 1;
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.Overlay.monobook.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.Overlay.monobook.less
new file mode 100644
index 00000000..fae2b321
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.Overlay.monobook.less
@@ -0,0 +1,3 @@
+.mw-rcfilters-ui-overlay {
+ font-size: 1.28em; /* 0.8em / x-small */
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.RcTopSectionWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.RcTopSectionWidget.less
new file mode 100644
index 00000000..aca3ea68
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.RcTopSectionWidget.less
@@ -0,0 +1,44 @@
+.mw-rcfilters-ui-rcTopSectionWidget {
+ &-topLinks {
+ &-table {
+ width: 100%;
+ }
+
+ &-top {
+ display: block;
+ width: 100%;
+
+ .mw-recentchanges-toplinks {
+ margin-bottom: 0.5em;
+ }
+ }
+ }
+
+ &-savedLinks {
+ vertical-align: bottom;
+ padding-left: 1em;
+ }
+
+ .mw-recentchanges-toplinks {
+ padding: 0 0.5em;
+
+ .oo-ui-widget-enabled.oo-ui-buttonElement.oo-ui-buttonElement-frameless .oo-ui-buttonElement-button {
+ padding: 0 2.5em 0 0.5em;
+ }
+
+ &-title,
+ .mw-collapsible-text {
+ // Same as the legend
+ font-size: 0.85em;
+ }
+
+ &:not( .mw-collapsed ) {
+ // Same as the legend
+ border: 1px solid #ddd;
+ }
+
+ body:not( .mw-rcfilters-ui-initialized ) & {
+ display: none;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SaveFiltersPopupButtonWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SaveFiltersPopupButtonWidget.less
new file mode 100644
index 00000000..4e8ad567
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SaveFiltersPopupButtonWidget.less
@@ -0,0 +1,39 @@
+@import 'mediawiki.mixins';
+
+.mw-rcfilters-ui-saveFiltersPopupButtonWidget {
+ &-popup {
+ &-layout,
+ &-options {
+ padding-bottom: 1.5em;
+ }
+
+ > .oo-ui-popupWidget-popup > .oo-ui-popupWidget-head {
+ position: relative;
+ height: auto;
+ padding: 1em;
+ // Icon width + icon left position (rounded to 0.5 to give a little extra margin)
+ padding-right: 1.875em + 0.5em;
+
+ > .oo-ui-buttonWidget {
+ top: 50%;
+ .transform( translateY( -50% ) );
+ }
+
+ > .oo-ui-iconWidget {
+ float: none;
+ display: inline-block;
+ margin: 0;
+ }
+
+ > .oo-ui-labelElement-label {
+ float: none;
+ display: inline-block;
+ font-size: 1.2em;
+ margin: 0;
+ font-weight: bold;
+ vertical-align: middle;
+ }
+ }
+ }
+
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SavedLinksListItemWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SavedLinksListItemWidget.less
new file mode 100644
index 00000000..9dccc245
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SavedLinksListItemWidget.less
@@ -0,0 +1,58 @@
+.mw-rcfilters-ui-savedLinksListItemWidget {
+ padding: 0 0.5em;
+ line-height: normal;
+
+ &:hover {
+ // Mimicking optionWidget styles
+ background-color: #eaecf0;
+ color: #000;
+ }
+
+ .mw-rcfilters-ui-cell {
+ vertical-align: middle;
+ }
+
+ .mw-rcfilters-ui-savedLinksListItemWidget-icon .oo-ui-iconElement-icon {
+ // Since we made the rows narrower (height smaller than usual)
+ // then the icon needs to be slightly smaller as well, so that
+ // when we toggle 'default' the icon doesn't bounce the option
+ // height up a little
+ width: 1.2em;
+ height: 1.2em;
+ min-width: 16px;
+ min-height: 16px;
+ opacity: 0.5;
+ }
+
+ &-icon span {
+ display: inline-block;
+ }
+
+ &-input {
+ display: inline-block;
+ margin-right: 0;
+ width: 15em;
+ }
+
+ &-label {
+ max-width: 15em;
+ display: inline-block;
+ vertical-align: middle;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ cursor: pointer;
+ margin-left: 0.5px;
+ color: #36c; // Accent50;
+ }
+
+ &-icon,
+ &-button {
+ width: 2em;
+ }
+
+ &-content {
+ width: 100%;
+ line-height: normal;
+ }
+
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SavedLinksListWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SavedLinksListWidget.less
new file mode 100644
index 00000000..2b713e1a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.SavedLinksListWidget.less
@@ -0,0 +1,28 @@
+.mw-rcfilters-ui-savedLinksListWidget {
+ &-menu {
+ width: 100%;
+ }
+
+ &-placeholder {
+ &-title {
+ font-weight: bold;
+ margin-bottom: 1em;
+ }
+
+ // Extra specificity needed to override OOUI rule that sets white-space: nowrap;
+ // on labels inside options
+ &.oo-ui-optionWidget .oo-ui-labelElement-label {
+ color: #72777d;
+ white-space: normal;
+ }
+
+ .oo-ui-iconElement-icon {
+ opacity: 0.5;
+ // Override OOUI option widget rules for icons
+ // we want the icon to appear at the top near the
+ // title, not in the middle of the multiline option
+ top: 0.7em !important; /* stylelint-disable-line declaration-no-important */
+ height: inherit !important; /* stylelint-disable-line declaration-no-important */
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.TagItemWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.TagItemWidget.less
new file mode 100644
index 00000000..26ea64cf
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.TagItemWidget.less
@@ -0,0 +1,79 @@
+@import 'mw.rcfilters.mixins';
+
+.mw-rcfilters-ui-tagItemWidget {
+ // Background and color of the capsule widget need a bit
+ // more specificity to override OOUI internals
+ &.oo-ui-flaggedElement-muted.oo-ui-tagItemWidget.oo-ui-widget-enabled {
+ // Muted state
+ background-color: #eaecf0;
+ border-color: #c8ccd1;
+
+ .oo-ui-labelElement-label {
+ color: #72777d;
+ }
+ .oo-ui-buttonWidget {
+ opacity: @muted-opacity;
+ }
+ }
+
+ &.oo-ui-flaggedElement-invalid.oo-ui-tagItemWidget.oo-ui-widget-enabled {
+ .oo-ui-labelElement-label {
+ color: #b32424;
+ }
+ }
+
+ // OOUI classes require super-specificity in order to override
+ // the white background
+ // The specificity is fixed in the patch: https://gerrit.wikimedia.org/r/#/c/349525/
+ // and will be available in the next OOUI release.
+ .oo-ui-tagMultiselectWidget.oo-ui-widget-enabled.oo-ui-tagMultiselectWidget-outlined &-selected.oo-ui-tagItemWidget.oo-ui-widget-enabled {
+ background-color: #eaf3ff;
+ border-color: #36c;
+ }
+
+ &-popup-content {
+ padding: 0.5em;
+ color: #54595d;
+ }
+
+ &.oo-ui-labelElement .oo-ui-labelElement-label {
+ cursor: pointer;
+ }
+
+ &-highlight {
+ display: none;
+ margin-right: 0.5em;
+ width: 10px;
+
+ &-highlighted {
+ display: inline-block;
+ }
+
+ &:before {
+ content: '';
+ position: absolute;
+ display: block;
+ top: 50%;
+ }
+
+ &[data-color='c1']:before {
+ .mw-rcfilters-mixin-circle( @highlight-c1, 10px, ~'-5px 0.5em 0 0' );
+ }
+
+ &[data-color='c2']:before {
+ .mw-rcfilters-mixin-circle( @highlight-c2, 10px, ~'-5px 0.5em 0 0' );
+ }
+
+ &[data-color='c3']:before {
+ .mw-rcfilters-mixin-circle( @highlight-c3, 10px, ~'-5px 0.5em 0 0' );
+ }
+
+ &[data-color='c4']:before {
+ .mw-rcfilters-mixin-circle( @highlight-c4, 10px, ~'-5px 0.5em 0 0' );
+ }
+
+ &[data-color='c5']:before {
+ .mw-rcfilters-mixin-circle( @highlight-c5, 10px, ~'-5px 0.5em 0 0' );
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ValuePickerWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ValuePickerWidget.less
new file mode 100644
index 00000000..38ad1ee6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ValuePickerWidget.less
@@ -0,0 +1,7 @@
+.mw-rcfilters-ui-valuePickerWidget {
+ &-title {
+ display: block;
+ font-weight: bold;
+ margin-bottom: 0.5em;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ViewSwitchWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ViewSwitchWidget.less
new file mode 100644
index 00000000..a6ce4cd8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.ViewSwitchWidget.less
@@ -0,0 +1,14 @@
+.mw-rcfilters-ui-viewSwitchWidget {
+ label.oo-ui-labelWidget {
+ color: #54595d;
+ font-weight: bold;
+ }
+
+ &-buttons {
+ margin-top: 0.5em;
+
+ .oo-ui-buttonWidget:not( :first-child ) {
+ margin-left: 0.5em;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.WatchlistTopSectionWidget.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.WatchlistTopSectionWidget.less
new file mode 100644
index 00000000..5e1e1184
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.WatchlistTopSectionWidget.less
@@ -0,0 +1,27 @@
+.mw-rcfilters-ui-watchlistTopSectionWidget {
+ &-watchlistDetails {
+ width: 100%;
+ }
+
+ &-editWatchlistButton {
+ vertical-align: bottom;
+
+ // actual button
+ .oo-ui-buttonWidget {
+ margin-left: 3em;
+ }
+ }
+
+ &-savedLinks {
+ float: right;
+ }
+
+ .mw-rcfilters-ui-table {
+ margin-top: 1em;
+ }
+
+ &-separator {
+ margin-top: 1em;
+ border-top: 2px solid #eaecf0; // Base80 AAA
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.less
new file mode 100644
index 00000000..f7081af4
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.ui.less
@@ -0,0 +1,19 @@
+.mw-rcfilters-ui {
+ &-table {
+ display: table;
+ width: 100%;
+
+ &-placeholder {
+ width: 100%;
+ }
+ }
+
+ &-row {
+ display: table-row;
+ }
+
+ &-cell {
+ display: table-cell;
+ vertical-align: top;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.variables.less b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.variables.less
new file mode 100644
index 00000000..fc8c9efe
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/styles/mw.rcfilters.variables.less
@@ -0,0 +1,21 @@
+// Highlight color definitions
+@highlight-none: #fff;
+@highlight-c1: #36c;
+@highlight-c2: #00af89;
+@highlight-c3: #fc3;
+@highlight-c4: #ff6d22;
+@highlight-c5: #d33;
+@highlight-bluedot: #1d4aad; // Simulates the 'known' browser <li> blue dot
+@highlight-grey: #54595d; // The color of full dots on Watchlist when highlight is enabled
+
+// Muted state
+@muted-opacity: 0.5;
+
+// Result list circle indicators
+// Defined and used in mw.rcfilters.ui.ChangesListWrapperWidget.less
+@result-circle-margin: 3px;
+@result-circle-general-margin: 0.5em;
+// In these small sizes, 'em' appears
+// squished and inconsistent.
+// Pixels are better for this use case:
+@result-circle-diameter: 6px;
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesLimitButtonWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesLimitButtonWidget.js
new file mode 100644
index 00000000..c2f20b71
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesLimitButtonWidget.js
@@ -0,0 +1,129 @@
+( function ( mw ) {
+ /**
+ * Widget defining the button controlling the popup for the number of results
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller Controller
+ * @param {mw.rcfilters.dm.FiltersViewModel} model View model
+ * @param {Object} [config] Configuration object
+ * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
+ */
+ mw.rcfilters.ui.ChangesLimitButtonWidget = function MwRcfiltersUiChangesLimitWidget( controller, model, config ) {
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.ChangesLimitButtonWidget.parent.call( this, config );
+
+ this.controller = controller;
+ this.model = model;
+
+ this.$overlay = config.$overlay || this.$element;
+
+ this.button = null;
+ this.limitGroupModel = null;
+
+ this.model.connect( this, {
+ initialize: 'onModelInitialize'
+ } );
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-changesLimitButtonWidget' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.ChangesLimitButtonWidget, OO.ui.Widget );
+
+ /**
+ * Respond to model initialize event
+ */
+ mw.rcfilters.ui.ChangesLimitButtonWidget.prototype.onModelInitialize = function () {
+ var changesLimitPopupWidget, selectedItem, currentValue,
+ displayGroupModel = this.model.getGroup( 'display' );
+
+ this.limitGroupModel = this.model.getGroup( 'limit' );
+ this.groupByPageItemModel = displayGroupModel.getItemByParamName( 'enhanced' );
+
+ // HACK: We need the model to be ready before we populate the button
+ // and the widget, because we require the filter items for the
+ // limit and their events. This addition is only done after the
+ // model is initialized.
+ // Note: This will be fixed soon!
+ if ( this.limitGroupModel ) {
+ changesLimitPopupWidget = new mw.rcfilters.ui.ChangesLimitPopupWidget(
+ this.limitGroupModel,
+ this.groupByPageItemModel
+ );
+
+ selectedItem = this.limitGroupModel.getSelectedItems()[ 0 ];
+ currentValue = ( selectedItem && selectedItem.getLabel() ) ||
+ mw.language.convertNumber( this.limitGroupModel.getDefaultParamValue() );
+
+ this.button = new OO.ui.PopupButtonWidget( {
+ indicator: 'down',
+ label: mw.msg( 'rcfilters-limit-shownum', currentValue ),
+ $overlay: this.$overlay,
+ popup: {
+ width: 300,
+ padded: true,
+ anchor: false,
+ align: 'forwards',
+ $autoCloseIgnore: this.$overlay,
+ $content: changesLimitPopupWidget.$element
+ }
+ } );
+
+ // Events
+ this.limitGroupModel.connect( this, { update: 'onLimitGroupModelUpdate' } );
+ changesLimitPopupWidget.connect( this, {
+ limit: 'onPopupLimit',
+ groupByPage: 'onPopupGroupByPage'
+ } );
+
+ this.$element.append( this.button.$element );
+ }
+ };
+
+ /**
+ * Respond to popup limit change event
+ *
+ * @param {string} filterName Chosen filter name
+ */
+ mw.rcfilters.ui.ChangesLimitButtonWidget.prototype.onPopupLimit = function ( filterName ) {
+ var item = this.limitGroupModel.getItemByName( filterName );
+
+ this.controller.toggleFilterSelect( filterName, true );
+ this.controller.updateLimitDefault( item.getParamName() );
+ this.button.popup.toggle( false );
+ };
+
+ /**
+ * Respond to popup limit change event
+ *
+ * @param {boolean} isGrouped The result set is grouped by page
+ */
+ mw.rcfilters.ui.ChangesLimitButtonWidget.prototype.onPopupGroupByPage = function ( isGrouped ) {
+ this.controller.toggleFilterSelect( this.groupByPageItemModel.getName(), isGrouped );
+ this.controller.updateGroupByPageDefault( Number( isGrouped ) );
+ this.button.popup.toggle( false );
+ };
+
+ /**
+ * Respond to limit choose event
+ *
+ * @param {string} filterName Filter name
+ */
+ mw.rcfilters.ui.ChangesLimitButtonWidget.prototype.onLimitGroupModelUpdate = function () {
+ var item = this.limitGroupModel.getSelectedItems()[ 0 ],
+ label = item && item.getLabel();
+
+ // Update the label
+ if ( label ) {
+ this.button.setLabel( mw.msg( 'rcfilters-limit-shownum', label ) );
+ }
+ };
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesLimitPopupWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesLimitPopupWidget.js
new file mode 100644
index 00000000..7248bd77
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesLimitPopupWidget.js
@@ -0,0 +1,83 @@
+( function ( mw ) {
+ /**
+ * Widget defining the popup to choose number of results
+ *
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.rcfilters.dm.FilterGroup} limitModel Group model for 'limit'
+ * @param {mw.rcfilters.dm.FilterItem} groupByPageItemModel Group model for 'limit'
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.ChangesLimitPopupWidget = function MwRcfiltersUiChangesLimitPopupWidget( limitModel, groupByPageItemModel, config ) {
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.ChangesLimitPopupWidget.parent.call( this, config );
+
+ this.limitModel = limitModel;
+ this.groupByPageItemModel = groupByPageItemModel;
+
+ this.valuePicker = new mw.rcfilters.ui.ValuePickerWidget(
+ this.limitModel,
+ {
+ label: mw.msg( 'rcfilters-limit-title' )
+ }
+ );
+
+ this.groupByPageCheckbox = new OO.ui.CheckboxInputWidget( {
+ selected: this.groupByPageItemModel.isSelected()
+ } );
+
+ // Events
+ this.valuePicker.connect( this, { choose: [ 'emit', 'limit' ] } );
+ this.groupByPageCheckbox.connect( this, { change: [ 'emit', 'groupByPage' ] } );
+ this.groupByPageItemModel.connect( this, { update: 'onGroupByPageModelUpdate' } );
+
+ // Initialize
+ this.$element
+ .addClass( 'mw-rcfilters-ui-changesLimitPopupWidget' )
+ .append(
+ this.valuePicker.$element,
+ new OO.ui.FieldsetLayout( {
+ label: mw.msg( 'rcfilters-grouping-title' ),
+ items: [
+ new OO.ui.FieldLayout(
+ this.groupByPageCheckbox,
+ {
+ align: 'inline',
+ label: mw.msg( 'rcfilters-group-results-by-page' )
+ }
+ )
+ ]
+ } ).$element
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.ChangesLimitPopupWidget, OO.ui.Widget );
+
+ /* Events */
+
+ /**
+ * @event limit
+ * @param {string} name Item name
+ *
+ * A limit item was chosen
+ */
+
+ /**
+ * @event groupByPage
+ * @param {boolean} isGrouped The results are grouped by page
+ *
+ * Results are grouped by page
+ */
+
+ /**
+ * Respond to group by page model update
+ */
+ mw.rcfilters.ui.ChangesLimitPopupWidget.prototype.onGroupByPageModelUpdate = function () {
+ this.groupByPageCheckbox.setSelected( this.groupByPageItemModel.isSelected() );
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js
new file mode 100644
index 00000000..429def4e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ChangesListWrapperWidget.js
@@ -0,0 +1,478 @@
+( function ( mw ) {
+ /**
+ * List of changes
+ *
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.rcfilters.dm.FiltersViewModel} filtersViewModel View model
+ * @param {mw.rcfilters.dm.ChangesListViewModel} changesListViewModel View model
+ * @param {mw.rcfilters.Controller} controller
+ * @param {jQuery} $changesListRoot Root element of the changes list to attach to
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget = function MwRcfiltersUiChangesListWrapperWidget(
+ filtersViewModel,
+ changesListViewModel,
+ controller,
+ $changesListRoot,
+ config
+ ) {
+ config = $.extend( {}, config, {
+ $element: $changesListRoot
+ } );
+
+ // Parent
+ mw.rcfilters.ui.ChangesListWrapperWidget.parent.call( this, config );
+
+ this.filtersViewModel = filtersViewModel;
+ this.changesListViewModel = changesListViewModel;
+ this.controller = controller;
+ this.highlightClasses = null;
+ this.filtersModelInitialized = false;
+
+ // Events
+ this.filtersViewModel.connect( this, {
+ itemUpdate: 'onItemUpdate',
+ highlightChange: 'onHighlightChange',
+ initialize: 'onFiltersModelInitialize'
+ } );
+ this.changesListViewModel.connect( this, {
+ invalidate: 'onModelInvalidate',
+ update: 'onModelUpdate',
+ newChangesExist: 'onNewChangesExist'
+ } );
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget' )
+ // We handle our own display/hide of the empty results message
+ .removeClass( 'mw-changeslist-empty' );
+
+ this.setupNewChangesButtonContainer( this.$element );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.ChangesListWrapperWidget, OO.ui.Widget );
+
+ /**
+ * Respond to filters model initialize event
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onFiltersModelInitialize = function () {
+ this.filtersModelInitialized = true;
+ // Set up highlight containers. We need to wait for the filters model
+ // to be initialized, so we can make sure we have all the css class definitions
+ // we get from the server with our filters
+ this.setupHighlightContainers( this.$element );
+ };
+
+ /**
+ * Get all available highlight classes
+ *
+ * @return {string[]} An array of available highlight class names
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.getHighlightClasses = function () {
+ if ( !this.highlightClasses || !this.highlightClasses.length ) {
+ this.highlightClasses = this.filtersViewModel.getItemsSupportingHighlights()
+ .map( function ( filterItem ) {
+ return filterItem.getCssClass();
+ } );
+ }
+
+ return this.highlightClasses;
+ };
+
+ /**
+ * Respond to the highlight feature being toggled on and off
+ *
+ * @param {boolean} highlightEnabled
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onHighlightChange = function ( highlightEnabled ) {
+ if ( highlightEnabled ) {
+ this.applyHighlight();
+ } else {
+ this.clearHighlight();
+ }
+ };
+
+ /**
+ * Respond to a filter item model update
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onItemUpdate = function () {
+ if ( this.filtersModelInitialized && this.filtersViewModel.isHighlightEnabled() ) {
+ this.clearHighlight();
+ this.applyHighlight();
+ }
+ };
+
+ /**
+ * Respond to changes list model invalidate
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelInvalidate = function () {
+ $( 'body' ).addClass( 'mw-rcfilters-ui-loading' );
+ };
+
+ /**
+ * Respond to changes list model update
+ *
+ * @param {jQuery|string} $changesListContent The content of the updated changes list
+ * @param {jQuery} $fieldset The content of the updated fieldset
+ * @param {boolean} isInitialDOM Whether $changesListContent is the existing (already attached) DOM
+ * @param {boolean} from Timestamp of the new changes
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onModelUpdate = function (
+ $changesListContent, $fieldset, isInitialDOM, from
+ ) {
+ var conflictItem,
+ $message = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-results' ),
+ isEmpty = $changesListContent === 'NO_RESULTS',
+ // For enhanced mode, we have to load these modules, which are
+ // not loaded for the 'regular' mode in the backend
+ loaderPromise = mw.user.options.get( 'usenewrc' ) ?
+ mw.loader.using( [ 'mediawiki.special.changeslist.enhanced', 'mediawiki.icon' ] ) :
+ $.Deferred().resolve(),
+ widget = this;
+
+ this.$element.toggleClass( 'mw-changeslist', !isEmpty );
+ if ( isEmpty ) {
+ this.$element.empty();
+
+ if ( this.filtersViewModel.hasConflict() ) {
+ conflictItem = this.filtersViewModel.getFirstConflictedItem();
+
+ $message
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-results-conflict' )
+ .text( mw.message( 'rcfilters-noresults-conflict' ).text() ),
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-results-message' )
+ .text( mw.message( conflictItem.getCurrentConflictResultMessage() ).text() )
+ );
+ } else {
+ $message
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-results-noresult' )
+ .text( mw.message( 'recentchanges-noresult' ).text() )
+ );
+ }
+
+ this.$element.append( $message );
+ } else {
+ if ( !isInitialDOM ) {
+ this.$element.empty().append( $changesListContent );
+
+ if ( from ) {
+ this.emphasizeNewChanges( from );
+ }
+ }
+
+ // Set up highlight containers
+ this.setupHighlightContainers( this.$element );
+
+ // Apply highlight
+ this.applyHighlight();
+
+ }
+
+ loaderPromise.done( function () {
+ if ( !isInitialDOM && !isEmpty ) {
+ // Make sure enhanced RC re-initializes correctly
+ mw.hook( 'wikipage.content' ).fire( widget.$element );
+ }
+
+ $( 'body' ).removeClass( 'mw-rcfilters-ui-loading' );
+ } );
+ };
+
+ /**
+ * Emphasize the elements (or groups) newer than the 'from' parameter
+ * @param {string} from Anything newer than this is considered 'new'
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.emphasizeNewChanges = function ( from ) {
+ var $firstNew,
+ $indicator,
+ $newChanges = $( [] ),
+ selector = this.inEnhancedMode() ?
+ 'table.mw-enhanced-rc[data-mw-ts]' :
+ 'li[data-mw-ts]',
+ set = this.$element.find( selector ),
+ length = set.length;
+
+ set.each( function ( index ) {
+ var $this = $( this ),
+ ts = $this.data( 'mw-ts' );
+
+ if ( ts >= from ) {
+ $newChanges = $newChanges.add( $this );
+ $firstNew = $this;
+
+ // guards against putting the marker after the last element
+ if ( index === ( length - 1 ) ) {
+ $firstNew = null;
+ }
+ }
+ } );
+
+ if ( $firstNew ) {
+ $indicator = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-previousChangesIndicator' );
+
+ $firstNew.after( $indicator );
+ }
+
+ $newChanges
+ .hide()
+ .fadeIn( 1000 );
+ };
+
+ /**
+ * Respond to changes list model newChangesExist
+ *
+ * @param {boolean} newChangesExist Whether new changes exist
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onNewChangesExist = function ( newChangesExist ) {
+ this.showNewChangesLink.toggle( newChangesExist );
+ };
+
+ /**
+ * Respond to the user clicking the 'show new changes' button
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.onShowNewChangesClick = function () {
+ this.controller.showNewChanges();
+ };
+
+ /**
+ * Setup the container for the 'new changes' button.
+ *
+ * @param {jQuery} $content
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupNewChangesButtonContainer = function ( $content ) {
+ this.showNewChangesLink = new OO.ui.ButtonWidget( {
+ framed: false,
+ label: mw.message( 'rcfilters-show-new-changes' ).text(),
+ flags: [ 'progressive' ]
+ } );
+ this.showNewChangesLink.connect( this, { click: 'onShowNewChangesClick' } );
+ this.showNewChangesLink.toggle( false );
+
+ $content.before(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-newChanges' )
+ .append( this.showNewChangesLink.$element )
+ );
+ };
+
+ /**
+ * Set up the highlight containers with all color circle indicators.
+ *
+ * @param {jQuery|string} $content The content of the updated changes list
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.setupHighlightContainers = function ( $content ) {
+ var $enhancedTopPageCell, $enhancedNestedPagesCell,
+ widget = this,
+ highlightClass = 'mw-rcfilters-ui-changesListWrapperWidget-highlights',
+ $highlights = $( '<div>' )
+ .addClass( highlightClass )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights-circle' )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights-color-none' )
+ .prop( 'data-color', 'none' )
+ );
+
+ if ( $( '.mw-rcfilters-ui-changesListWrapperWidget-highlights' ).length ) {
+ // Already set up
+ return;
+ }
+
+ mw.rcfilters.HighlightColors.forEach( function ( color ) {
+ $highlights.append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights-color-' + color )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlights-circle' )
+ .prop( 'data-color', color )
+ );
+ } );
+
+ if ( this.inEnhancedMode() ) {
+ $enhancedTopPageCell = $content.find( 'table.mw-enhanced-rc.mw-collapsible' );
+ $enhancedNestedPagesCell = $content.find( 'td.mw-enhanced-rc-nested' );
+
+ // Enhanced RC highlight containers
+ $content.find( 'table.mw-enhanced-rc tr:first-child' )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhanced-toplevel' )
+ .prepend(
+ $( '<td>' )
+ .append( $highlights.clone() )
+ );
+
+ // We are adding and changing cells in a table that, despite having nested rows,
+ // is actually all one big table. To do that right, we want to remove the 'placeholder'
+ // cell from the top row, because we're actually adding that placeholder in the children
+ // with the highlights.
+ $content.find( 'table.mw-enhanced-rc tr:first-child td.mw-changeslist-line-prefix' )
+ .detach();
+ $content.find( 'table.mw-enhanced-rc tr:first-child td.mw-enhanced-rc' )
+ .prop( 'colspan', '2' );
+
+ $enhancedNestedPagesCell
+ .before(
+ $( '<td>' )
+ .append( $highlights.clone().addClass( 'mw-enhanced-rc-nested' ) )
+ );
+
+ // We need to target the nested rows differently than the top rows so that the
+ // LESS rules applies correctly. In top rows, the rule should highlight all but
+ // the first 2 cells td:not( :nth-child( -n+2 ) and the nested rows, the rule
+ // should highlight all but the first 3 cells td:not( :nth-child( -n+3 )
+ $enhancedNestedPagesCell
+ .closest( 'tr' )
+ .addClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhanced-nested' );
+
+ // Go over pages that have sub results
+ // HACK: We really only can collect those by targetting the collapsible class
+ $enhancedTopPageCell.each( function () {
+ var collectedClasses,
+ $table = $( this );
+
+ // Go over <tr>s and pick up all recognized classes
+ collectedClasses = widget.getHighlightClasses().filter( function ( className ) {
+ return $table.find( 'tr' ).hasClass( className );
+ } );
+
+ $table.find( 'tr:first-child' )
+ .addClass( collectedClasses.join( ' ' ) );
+ } );
+
+ $content.addClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhancedView' );
+ } else {
+ // Regular RC
+ $content.find( 'ul.special li' )
+ .prepend( $highlights.clone() );
+ }
+ };
+
+ /**
+ * In enhanced mode, we need to check whether the grouped results all have the
+ * same active highlights in order to see whether the "parent" of the group should
+ * be grey or highlighted normally.
+ *
+ * This is called every time highlights are applied.
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.updateEnhancedParentHighlight = function () {
+ var activeHighlightClasses,
+ $enhancedTopPageCell = this.$element.find( 'table.mw-enhanced-rc.mw-collapsible' );
+
+ activeHighlightClasses = this.filtersViewModel.getCurrentlyUsedHighlightColors().map( function ( color ) {
+ return 'mw-rcfilters-highlight-color-' + color;
+ } );
+
+ // Go over top pages and their children, and figure out if all sub-pages have the
+ // same highlights between themselves. If they do, the parent should be highlighted
+ // with all colors. If classes are different, the parent should receive a grey
+ // background
+ $enhancedTopPageCell.each( function () {
+ var firstChildClasses, $rowsWithDifferentHighlights,
+ $table = $( this );
+
+ // Collect the relevant classes from the first nested child
+ firstChildClasses = activeHighlightClasses.filter( function ( className ) {
+ return $table.find( 'tr:nth-child(2)' ).hasClass( className );
+ } );
+ // Filter the non-head rows and see if they all have the same classes
+ // to the first row
+ $rowsWithDifferentHighlights = $table.find( 'tr:not(:first-child)' ).filter( function () {
+ var classesInThisRow,
+ $this = $( this );
+
+ classesInThisRow = activeHighlightClasses.filter( function ( className ) {
+ return $this.hasClass( className );
+ } );
+
+ return !OO.compare( firstChildClasses, classesInThisRow );
+ } );
+
+ // If classes are different, tag the row for using grey color
+ $table.find( 'tr:first-child' )
+ .toggleClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey', $rowsWithDifferentHighlights.length > 0 );
+ } );
+ };
+
+ /**
+ * @return {boolean} Whether the changes are grouped by page
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.inEnhancedMode = function () {
+ var uri = new mw.Uri();
+ return ( uri.query.enhanced !== undefined && Number( uri.query.enhanced ) ) ||
+ ( uri.query.enhanced === undefined && Number( mw.user.options.get( 'usenewrc' ) ) );
+ };
+
+ /**
+ * Apply color classes based on filters highlight configuration
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.applyHighlight = function () {
+ if ( !this.filtersViewModel.isHighlightEnabled() ) {
+ return;
+ }
+
+ this.filtersViewModel.getHighlightedItems().forEach( function ( filterItem ) {
+ var $elements = this.$element.find( '.' + filterItem.getCssClass() );
+
+ // Add highlight class to all highlighted list items
+ $elements
+ .addClass( 'mw-rcfilters-highlight-color-' + filterItem.getHighlightColor() );
+
+ $elements.each( function () {
+ var filterString = $( this ).attr( 'data-highlightedFilters' ) || '',
+ filters = filterString ? filterString.split( '|' ) : [];
+
+ if ( filters.indexOf( filterItem.getLabel() ) === -1 ) {
+ filters.push( filterItem.getLabel() );
+ }
+
+ $( this )
+ .attr( 'data-highlightedFilters', filters.join( '|' ) );
+ } );
+ }.bind( this ) );
+ // Apply a title for relevant filters
+ this.$element.find( '[data-highlightedFilters]' ).each( function () {
+ var filterString = $( this ).attr( 'data-highlightedFilters' ) || '',
+ filters = filterString ? filterString.split( '|' ) : [];
+
+ if ( filterString ) {
+ $( this ).attr( 'title', mw.msg( 'rcfilters-highlighted-filters-list', filters.join( ', ' ) ) );
+ }
+ } );
+
+ if ( this.inEnhancedMode() ) {
+ this.updateEnhancedParentHighlight();
+ }
+
+ // Turn on highlights
+ this.$element.addClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlighted' );
+ };
+
+ /**
+ * Remove all color classes
+ */
+ mw.rcfilters.ui.ChangesListWrapperWidget.prototype.clearHighlight = function () {
+ // Remove highlight classes
+ mw.rcfilters.HighlightColors.forEach( function ( color ) {
+ this.$element.find( '.mw-rcfilters-highlight-color-' + color ).removeClass( 'mw-rcfilters-highlight-color-' + color );
+ }.bind( this ) );
+
+ this.$element.find( '[data-highlightedFilters]' )
+ .removeAttr( 'title' )
+ .removeAttr( 'data-highlightedFilters' );
+
+ // Remove grey from enhanced rows
+ this.$element.find( '.mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey' )
+ .removeClass( 'mw-rcfilters-ui-changesListWrapperWidget-enhanced-grey' );
+
+ // Turn off highlights
+ this.$element.removeClass( 'mw-rcfilters-ui-changesListWrapperWidget-highlighted' );
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CheckboxInputWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CheckboxInputWidget.js
new file mode 100644
index 00000000..9fd45939
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.CheckboxInputWidget.js
@@ -0,0 +1,63 @@
+( function ( mw ) {
+ /**
+ * A widget representing a single toggle filter
+ *
+ * @extends OO.ui.CheckboxInputWidget
+ *
+ * @constructor
+ * @param {Object} config Configuration object
+ */
+ mw.rcfilters.ui.CheckboxInputWidget = function MwRcfiltersUiCheckboxInputWidget( config ) {
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.CheckboxInputWidget.parent.call( this, config );
+
+ // Event
+ this.$input
+ // HACK: This widget just pretends to be a checkbox for visual purposes.
+ // In reality, all actions - setting to true or false, etc - are
+ // decided by the model, and executed by the controller. This means
+ // that we want to let the controller and model make the decision
+ // of whether to check/uncheck this checkboxInputWidget, and for that,
+ // we have to bypass the browser action that checks/unchecks it during
+ // click.
+ .on( 'click', false )
+ .on( 'change', this.onUserChange.bind( this ) );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.CheckboxInputWidget, OO.ui.CheckboxInputWidget );
+
+ /* Events */
+
+ /**
+ * @event userChange
+ * @param {boolean} Current state of the checkbox
+ *
+ * The user has checked or unchecked this checkbox
+ */
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.CheckboxInputWidget.prototype.onEdit = function () {
+ // Similarly to preventing defaults in 'click' event, we want
+ // to prevent this widget from deciding anything about its own
+ // state; it emits a change event and the model and controller
+ // make a decision about what its select state is.
+ // onEdit has a widget.$input.prop( 'checked' ) inside a setTimeout()
+ // so we really want to prevent that from messing with what
+ // the model decides the state of the widget is.
+ };
+
+ /**
+ * Respond to checkbox change by a user and emit 'userChange'.
+ */
+ mw.rcfilters.ui.CheckboxInputWidget.prototype.onUserChange = function () {
+ this.emit( 'userChange', this.$input.prop( 'checked' ) );
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DateButtonWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DateButtonWidget.js
new file mode 100644
index 00000000..82607f1b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DateButtonWidget.js
@@ -0,0 +1,120 @@
+( function ( mw ) {
+ /**
+ * Widget defining the button controlling the popup for the date range for the results
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller Controller
+ * @param {mw.rcfilters.dm.FiltersViewModel} model View model
+ * @param {Object} [config] Configuration object
+ * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
+ */
+ mw.rcfilters.ui.DateButtonWidget = function MwRcfiltersUiDateButtonWidget( controller, model, config ) {
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.ChangesLimitButtonWidget.parent.call( this, config );
+
+ this.controller = controller;
+ this.model = model;
+
+ this.$overlay = config.$overlay || this.$element;
+
+ this.button = null;
+ this.daysGroupModel = null;
+
+ this.model.connect( this, {
+ initialize: 'onModelInitialize'
+ } );
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-dateButtonWidget' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.DateButtonWidget, OO.ui.Widget );
+
+ /**
+ * Respond to model initialize event
+ */
+ mw.rcfilters.ui.DateButtonWidget.prototype.onModelInitialize = function () {
+ var datePopupWidget;
+
+ this.daysGroupModel = this.model.getGroup( 'days' );
+
+ // HACK: We need the model to be ready before we populate the button
+ // and the widget, because we require the filter items for the
+ // limit and their events. This addition is only done after the
+ // model is initialized.
+ // Note: This will be fixed soon!
+ if ( this.daysGroupModel ) {
+ datePopupWidget = new mw.rcfilters.ui.DatePopupWidget(
+ this.daysGroupModel
+ );
+
+ this.button = new OO.ui.PopupButtonWidget( {
+ indicator: 'down',
+ icon: 'calendar',
+ $overlay: this.$overlay,
+ popup: {
+ width: 300,
+ padded: true,
+ anchor: false,
+ align: 'forwards',
+ $autoCloseIgnore: this.$overlay,
+ $content: datePopupWidget.$element
+ }
+ } );
+ this.updateButtonLabel();
+
+ // Events
+ this.daysGroupModel.connect( this, { update: 'onDaysGroupModelUpdate' } );
+ datePopupWidget.connect( this, { days: 'onPopupDays' } );
+
+ this.$element.append( this.button.$element );
+ }
+ };
+
+ /**
+ * Respond to popup limit change event
+ *
+ * @param {string} filterName Chosen filter name
+ */
+ mw.rcfilters.ui.DateButtonWidget.prototype.onPopupDays = function ( filterName ) {
+ var item = this.daysGroupModel.getItemByName( filterName );
+
+ this.controller.toggleFilterSelect( filterName, true );
+ this.controller.updateDaysDefault( item.getParamName() );
+ this.button.popup.toggle( false );
+ };
+
+ /**
+ * Respond to limit choose event
+ *
+ * @param {string} filterName Filter name
+ */
+ mw.rcfilters.ui.DateButtonWidget.prototype.onDaysGroupModelUpdate = function () {
+ this.updateButtonLabel();
+ };
+
+ /**
+ * Update the button label
+ */
+ mw.rcfilters.ui.DateButtonWidget.prototype.updateButtonLabel = function () {
+ var item = this.daysGroupModel.getSelectedItems()[ 0 ];
+
+ // Update the label
+ if ( item ) {
+ this.button.setLabel(
+ mw.msg(
+ Number( item.getParamName() ) < 1 ?
+ 'rcfilters-days-show-hours' : 'rcfilters-days-show-days',
+ item.getLabel()
+ )
+ );
+ }
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DatePopupWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DatePopupWidget.js
new file mode 100644
index 00000000..6971df52
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.DatePopupWidget.js
@@ -0,0 +1,61 @@
+( function ( mw ) {
+ /**
+ * Widget defining the popup to choose date for the results
+ *
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.rcfilters.dm.FilterGroup} model Group model for 'days'
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.DatePopupWidget = function MwRcfiltersUiDatePopupWidget( model, config ) {
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.ChangesLimitPopupWidget.parent.call( this, config );
+
+ this.model = model;
+
+ this.hoursValuePicker = new mw.rcfilters.ui.ValuePickerWidget(
+ this.model,
+ {
+ classes: [ 'mw-rcfilters-ui-datePopupWidget-hours' ],
+ label: mw.msg( 'rcfilters-hours-title' ),
+ itemFilter: function ( itemModel ) { return Number( itemModel.getParamName() ) < 1; }
+ }
+ );
+ this.daysValuePicker = new mw.rcfilters.ui.ValuePickerWidget(
+ this.model,
+ {
+ classes: [ 'mw-rcfilters-ui-datePopupWidget-days' ],
+ label: mw.msg( 'rcfilters-days-title' ),
+ itemFilter: function ( itemModel ) { return Number( itemModel.getParamName() ) >= 1; }
+ }
+ );
+
+ // Events
+ this.hoursValuePicker.connect( this, { choose: [ 'emit', 'days' ] } );
+ this.daysValuePicker.connect( this, { choose: [ 'emit', 'days' ] } );
+
+ // Initialize
+ this.$element
+ .addClass( 'mw-rcfilters-ui-datePopupWidget' )
+ .append(
+ this.hoursValuePicker.$element,
+ this.daysValuePicker.$element
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.DatePopupWidget, OO.ui.Widget );
+
+ /* Events */
+
+ /**
+ * @event days
+ * @param {string} name Item name
+ *
+ * A days item was chosen
+ */
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemHighlightButton.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemHighlightButton.js
new file mode 100644
index 00000000..74261236
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterItemHighlightButton.js
@@ -0,0 +1,84 @@
+( function ( mw, $ ) {
+ /**
+ * A button to configure highlight for a filter item
+ *
+ * @extends OO.ui.PopupButtonWidget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller RCFilters controller
+ * @param {mw.rcfilters.dm.FilterItem} model Filter item model
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.FilterItemHighlightButton = function MwRcfiltersUiFilterItemHighlightButton( controller, model, config ) {
+ config = config || {};
+
+ this.colorPickerWidget = new mw.rcfilters.ui.HighlightColorPickerWidget( controller, model );
+
+ // Parent
+ mw.rcfilters.ui.FilterItemHighlightButton.parent.call( this, $.extend( true, {}, config, {
+ icon: 'highlight',
+ indicator: 'down',
+ popup: {
+ anchor: false,
+ padded: true,
+ align: 'backwards',
+ horizontalPosition: 'end',
+ $floatableContainer: this.$element,
+ width: 290,
+ $content: this.colorPickerWidget.$element
+ }
+ } ) );
+
+ this.controller = controller;
+ this.model = model;
+
+ // Event
+ this.model.connect( this, { update: 'onModelUpdate' } );
+ this.colorPickerWidget.connect( this, { chooseColor: 'onChooseColor' } );
+ // This lives inside a MenuOptionWidget, which intercepts mousedown
+ // to select the item. We want to prevent that when we click the highlight
+ // button
+ this.$element.on( 'mousedown', function ( e ) { e.stopPropagation(); } );
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-filterItemHighlightButton' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.FilterItemHighlightButton, OO.ui.PopupButtonWidget );
+
+ /* Static Properties */
+
+ /**
+ * @static
+ */
+ mw.rcfilters.ui.FilterItemHighlightButton.static.cancelButtonMouseDownEvents = true;
+
+ /* Methods */
+
+ /**
+ * Respond to item model update event
+ */
+ mw.rcfilters.ui.FilterItemHighlightButton.prototype.onModelUpdate = function () {
+ var currentColor = this.model.getHighlightColor(),
+ widget = this;
+
+ this.$icon.toggleClass(
+ 'mw-rcfilters-ui-filterItemHighlightButton-circle',
+ currentColor !== null
+ );
+
+ mw.rcfilters.HighlightColors.forEach( function ( c ) {
+ widget.$icon
+ .toggleClass(
+ 'mw-rcfilters-ui-filterItemHighlightButton-circle-color-' + c,
+ c === currentColor
+ );
+ } );
+ };
+
+ mw.rcfilters.ui.FilterItemHighlightButton.prototype.onChooseColor = function () {
+ this.popup.toggle( false );
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuHeaderWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuHeaderWidget.js
new file mode 100644
index 00000000..eeb5ddc2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuHeaderWidget.js
@@ -0,0 +1,165 @@
+( function ( mw, $ ) {
+ /**
+ * Menu header for the RCFilters filters menu
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller Controller
+ * @param {mw.rcfilters.dm.FiltersViewModel} model View model
+ * @param {Object} config Configuration object
+ * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
+ */
+ mw.rcfilters.ui.FilterMenuHeaderWidget = function MwRcfiltersUiFilterMenuHeaderWidget( controller, model, config ) {
+ config = config || {};
+
+ this.controller = controller;
+ this.model = model;
+ this.$overlay = config.$overlay || this.$element;
+
+ // Parent
+ mw.rcfilters.ui.FilterMenuHeaderWidget.parent.call( this, config );
+ OO.ui.mixin.LabelElement.call( this, $.extend( {
+ label: mw.msg( 'rcfilters-filterlist-title' ),
+ $label: $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-filterMenuHeaderWidget-title' )
+ }, config ) );
+
+ // "Back" to default view button
+ this.backButton = new OO.ui.ButtonWidget( {
+ icon: 'previous',
+ framed: false,
+ title: mw.msg( 'rcfilters-view-return-to-default-tooltip' ),
+ classes: [ 'mw-rcfilters-ui-filterMenuHeaderWidget-backButton' ]
+ } );
+ this.backButton.toggle( this.model.getCurrentView() !== 'default' );
+
+ // Highlight button
+ this.highlightButton = new OO.ui.ToggleButtonWidget( {
+ icon: 'highlight',
+ label: mw.message( 'rcfilters-highlightbutton-title' ).text(),
+ classes: [ 'mw-rcfilters-ui-filterMenuHeaderWidget-hightlightButton' ]
+ } );
+
+ // Invert namespaces button
+ this.invertNamespacesButton = new OO.ui.ToggleButtonWidget( {
+ icon: '',
+ classes: [ 'mw-rcfilters-ui-filterMenuHeaderWidget-invertNamespacesButton' ]
+ } );
+ this.invertNamespacesButton.toggle( this.model.getCurrentView() === 'namespaces' );
+ this.updateInvertButton( this.model.areNamespacesInverted() );
+
+ // Events
+ this.backButton.connect( this, { click: 'onBackButtonClick' } );
+ this.highlightButton
+ .connect( this, { click: 'onHighlightButtonClick' } );
+ this.invertNamespacesButton
+ .connect( this, { click: 'onInvertNamespacesButtonClick' } );
+ this.model.connect( this, {
+ highlightChange: 'onModelHighlightChange',
+ invertChange: 'onModelInvertChange',
+ update: 'onModelUpdate'
+ } );
+
+ // Initialize
+ this.$element
+ .addClass( 'mw-rcfilters-ui-filterMenuHeaderWidget' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-table' )
+ .addClass( 'mw-rcfilters-ui-filterMenuHeaderWidget-header' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-row' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-filterMenuHeaderWidget-header-back' )
+ .append( this.backButton.$element ),
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-filterMenuHeaderWidget-header-title' )
+ .append( this.$label ),
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-filterMenuHeaderWidget-header-invert' )
+ .append( this.invertNamespacesButton.$element ),
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-filterMenuHeaderWidget-header-highlight' )
+ .append( this.highlightButton.$element )
+ )
+ )
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.FilterMenuHeaderWidget, OO.ui.Widget );
+ OO.mixinClass( mw.rcfilters.ui.FilterMenuHeaderWidget, OO.ui.mixin.LabelElement );
+
+ /* Methods */
+
+ /**
+ * Respond to model update event
+ */
+ mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onModelUpdate = function () {
+ var currentView = this.model.getCurrentView();
+
+ this.setLabel( this.model.getViewTitle( currentView ) );
+
+ this.invertNamespacesButton.toggle( currentView === 'namespaces' );
+ this.backButton.toggle( currentView !== 'default' );
+ };
+
+ /**
+ * Respond to model highlight change event
+ *
+ * @param {boolean} highlightEnabled Highlight is enabled
+ */
+ mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onModelHighlightChange = function ( highlightEnabled ) {
+ this.highlightButton.setActive( highlightEnabled );
+ };
+
+ /**
+ * Respond to model invert change event
+ *
+ * @param {boolean} isInverted Namespaces selection is inverted
+ */
+ mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onModelInvertChange = function ( isInverted ) {
+ this.updateInvertButton( isInverted );
+ };
+
+ /**
+ * Update the state of the invert button
+ *
+ * @param {boolean} isInverted Namespaces selection is inverted
+ */
+ mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.updateInvertButton = function ( isInverted ) {
+ this.invertNamespacesButton.setActive( isInverted );
+ this.invertNamespacesButton.setLabel(
+ isInverted ?
+ mw.msg( 'rcfilters-exclude-button-on' ) :
+ mw.msg( 'rcfilters-exclude-button-off' )
+ );
+ };
+
+ mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onBackButtonClick = function () {
+ this.controller.switchView( 'default' );
+ };
+
+ /**
+ * Respond to highlight button click
+ */
+ mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onHighlightButtonClick = function () {
+ this.controller.toggleHighlight();
+ };
+
+ /**
+ * Respond to highlight button click
+ */
+ mw.rcfilters.ui.FilterMenuHeaderWidget.prototype.onInvertNamespacesButtonClick = function () {
+ this.controller.toggleInvertedNamespaces();
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuOptionWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuOptionWidget.js
new file mode 100644
index 00000000..5198c699
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuOptionWidget.js
@@ -0,0 +1,84 @@
+( function ( mw ) {
+ /**
+ * A widget representing a single toggle filter
+ *
+ * @extends mw.rcfilters.ui.ItemMenuOptionWidget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller RCFilters controller
+ * @param {mw.rcfilters.dm.FilterItem} model Filter item model
+ * @param {Object} config Configuration object
+ */
+ mw.rcfilters.ui.FilterMenuOptionWidget = function MwRcfiltersUiFilterMenuOptionWidget( controller, model, config ) {
+ config = config || {};
+
+ this.controller = controller;
+ this.model = model;
+
+ // Parent
+ mw.rcfilters.ui.FilterMenuOptionWidget.parent.call( this, controller, model, config );
+
+ // Event
+ this.model.getGroupModel().connect( this, { update: 'onGroupModelUpdate' } );
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-filterMenuOptionWidget' );
+ };
+
+ /* Initialization */
+ OO.inheritClass( mw.rcfilters.ui.FilterMenuOptionWidget, mw.rcfilters.ui.ItemMenuOptionWidget );
+
+ /* Static properties */
+
+ // We do our own scrolling to top
+ mw.rcfilters.ui.FilterMenuOptionWidget.static.scrollIntoViewOnSelect = false;
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.FilterMenuOptionWidget.prototype.onModelUpdate = function () {
+ // Parent
+ mw.rcfilters.ui.FilterMenuOptionWidget.parent.prototype.onModelUpdate.call( this );
+
+ this.setCurrentMuteState();
+ };
+
+ /**
+ * Respond to item group model update event
+ */
+ mw.rcfilters.ui.FilterMenuOptionWidget.prototype.onGroupModelUpdate = function () {
+ this.setCurrentMuteState();
+ };
+
+ /**
+ * Set the current muted view of the widget based on its state
+ */
+ mw.rcfilters.ui.FilterMenuOptionWidget.prototype.setCurrentMuteState = function () {
+ if (
+ this.model.getGroupModel().getView() === 'namespaces' &&
+ this.model.isInverted()
+ ) {
+ // This is an inverted behavior than the other rules, specifically
+ // for inverted namespaces
+ this.setFlags( {
+ muted: this.model.isSelected()
+ } );
+ } else {
+ this.setFlags( {
+ muted: (
+ this.model.isConflicted() ||
+ (
+ // Item is also muted when any of the items in its group is active
+ this.model.getGroupModel().isActive() &&
+ // But it isn't selected
+ !this.model.isSelected() &&
+ // And also not included
+ !this.model.isIncluded()
+ )
+ )
+ } );
+ }
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuSectionOptionWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuSectionOptionWidget.js
new file mode 100644
index 00000000..e053914e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterMenuSectionOptionWidget.js
@@ -0,0 +1,123 @@
+( function ( mw ) {
+ /**
+ * A widget representing a menu section for filter groups
+ *
+ * @class
+ * @extends OO.ui.MenuSectionOptionWidget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller RCFilters controller
+ * @param {mw.rcfilters.dm.FilterGroup} model Filter group model
+ * @param {Object} config Configuration object
+ * @cfg {jQuery} [$overlay] Overlay
+ */
+ mw.rcfilters.ui.FilterMenuSectionOptionWidget = function MwRcfiltersUiFilterMenuSectionOptionWidget( controller, model, config ) {
+ var whatsThisMessages,
+ $header = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-filterMenuSectionOptionWidget-header' ),
+ $popupContent = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-filterMenuSectionOptionWidget-whatsThisButton-popup-content' );
+
+ config = config || {};
+
+ this.controller = controller;
+ this.model = model;
+ this.$overlay = config.$overlay || this.$element;
+
+ // Parent
+ mw.rcfilters.ui.FilterMenuSectionOptionWidget.parent.call( this, $.extend( {
+ label: this.model.getTitle(),
+ $label: $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-filterMenuSectionOptionWidget-header-title' )
+ }, config ) );
+
+ $header.append( this.$label );
+
+ if ( this.model.hasWhatsThis() ) {
+ whatsThisMessages = this.model.getWhatsThis();
+
+ // Create popup
+ if ( whatsThisMessages.header ) {
+ $popupContent.append(
+ ( new OO.ui.LabelWidget( {
+ label: mw.msg( whatsThisMessages.header ),
+ classes: [ 'mw-rcfilters-ui-filterMenuSectionOptionWidget-whatsThisButton-popup-content-header' ]
+ } ) ).$element
+ );
+ }
+ if ( whatsThisMessages.body ) {
+ $popupContent.append(
+ ( new OO.ui.LabelWidget( {
+ label: mw.msg( whatsThisMessages.body ),
+ classes: [ 'mw-rcfilters-ui-filterMenuSectionOptionWidget-whatsThisButton-popup-content-body' ]
+ } ) ).$element
+ );
+ }
+ if ( whatsThisMessages.linkText && whatsThisMessages.url ) {
+ $popupContent.append(
+ ( new OO.ui.ButtonWidget( {
+ framed: false,
+ flags: [ 'progressive' ],
+ href: whatsThisMessages.url,
+ label: mw.msg( whatsThisMessages.linkText ),
+ classes: [ 'mw-rcfilters-ui-filterMenuSectionOptionWidget-whatsThisButton-popup-content-link' ]
+ } ) ).$element
+ );
+ }
+
+ // Add button
+ this.whatsThisButton = new OO.ui.PopupButtonWidget( {
+ framed: false,
+ label: mw.msg( 'rcfilters-filterlist-whatsthis' ),
+ $overlay: this.$overlay,
+ classes: [ 'mw-rcfilters-ui-filterMenuSectionOptionWidget-whatsThisButton' ],
+ flags: [ 'progressive' ],
+ popup: {
+ padded: false,
+ align: 'center',
+ position: 'above',
+ $content: $popupContent,
+ classes: [ 'mw-rcfilters-ui-filterMenuSectionOptionWidget-whatsThisButton-popup' ]
+ }
+ } );
+
+ $header
+ .append( this.whatsThisButton.$element );
+ }
+
+ // Events
+ this.model.connect( this, { update: 'onModelUpdate' } );
+
+ // Initialize
+ this.$element
+ .addClass( 'mw-rcfilters-ui-filterMenuSectionOptionWidget' )
+ .addClass( 'mw-rcfilters-ui-filterMenuSectionOptionWidget-name-' + this.model.getName() )
+ .append( $header );
+ };
+
+ /* Initialize */
+
+ OO.inheritClass( mw.rcfilters.ui.FilterMenuSectionOptionWidget, OO.ui.MenuSectionOptionWidget );
+
+ /* Methods */
+
+ /**
+ * Respond to model update event
+ */
+ mw.rcfilters.ui.FilterMenuSectionOptionWidget.prototype.onModelUpdate = function () {
+ this.$element.toggleClass(
+ 'mw-rcfilters-ui-filterMenuSectionOptionWidget-active',
+ this.model.isActive()
+ );
+ };
+
+ /**
+ * Get the group name
+ *
+ * @return {string} Group name
+ */
+ mw.rcfilters.ui.FilterMenuSectionOptionWidget.prototype.getName = function () {
+ return this.model.getName();
+ };
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagItemWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagItemWidget.js
new file mode 100644
index 00000000..8a36eb41
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagItemWidget.js
@@ -0,0 +1,41 @@
+( function ( mw ) {
+ /**
+ * Extend OOUI's FilterTagItemWidget to also display a popup on hover.
+ *
+ * @class
+ * @extends mw.rcfilters.ui.TagItemWidget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller
+ * @param {mw.rcfilters.dm.FilterItem} model Item model
+ * @param {Object} config Configuration object
+ */
+ mw.rcfilters.ui.FilterTagItemWidget = function MwRcfiltersUiFilterTagItemWidget( controller, model, config ) {
+ config = config || {};
+
+ mw.rcfilters.ui.FilterTagItemWidget.parent.call( this, controller, model, config );
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-filterTagItemWidget' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.FilterTagItemWidget, mw.rcfilters.ui.TagItemWidget );
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.FilterTagItemWidget.prototype.setCurrentMuteState = function () {
+ this.setFlags( {
+ muted: (
+ !this.model.isSelected() ||
+ this.model.isIncluded() ||
+ this.model.isFullyCovered()
+ ),
+ invalid: this.model.isSelected() && this.model.isConflicted()
+ } );
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js
new file mode 100644
index 00000000..757a0003
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterTagMultiselectWidget.js
@@ -0,0 +1,685 @@
+( function ( mw ) {
+ /**
+ * List displaying all filter groups
+ *
+ * @class
+ * @extends OO.ui.MenuTagMultiselectWidget
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller Controller
+ * @param {mw.rcfilters.dm.FiltersViewModel} model View model
+ * @param {mw.rcfilters.dm.SavedQueriesModel} savedQueriesModel Saved queries model
+ * @param {Object} config Configuration object
+ * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget = function MwRcfiltersUiFilterTagMultiselectWidget( controller, model, savedQueriesModel, config ) {
+ var rcFiltersRow,
+ title = new OO.ui.LabelWidget( {
+ label: mw.msg( 'rcfilters-activefilters' ),
+ classes: [ 'mw-rcfilters-ui-filterTagMultiselectWidget-wrapper-content-title' ]
+ } ),
+ $contentWrapper = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-wrapper' );
+
+ config = config || {};
+
+ this.controller = controller;
+ this.model = model;
+ this.queriesModel = savedQueriesModel;
+ this.$overlay = config.$overlay || this.$element;
+ this.matchingQuery = null;
+ this.currentView = this.model.getCurrentView();
+
+ // Parent
+ mw.rcfilters.ui.FilterTagMultiselectWidget.parent.call( this, $.extend( true, {
+ label: mw.msg( 'rcfilters-filterlist-title' ),
+ placeholder: mw.msg( 'rcfilters-empty-filter' ),
+ inputPosition: 'outline',
+ allowArbitrary: false,
+ allowDisplayInvalidTags: false,
+ allowReordering: false,
+ $overlay: this.$overlay,
+ menu: {
+ hideWhenOutOfView: false,
+ hideOnChoose: false,
+ width: 650,
+ footers: [
+ {
+ name: 'viewSelect',
+ sticky: false,
+ // View select menu, appears on default view only
+ $element: $( '<div>' )
+ .append( new mw.rcfilters.ui.ViewSwitchWidget( this.controller, this.model ).$element ),
+ views: [ 'default' ]
+ },
+ {
+ name: 'feedback',
+ // Feedback footer, appears on all views
+ $element: $( '<div>' )
+ .append(
+ new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'feedback',
+ flags: [ 'progressive' ],
+ label: mw.msg( 'rcfilters-filterlist-feedbacklink' ),
+ href: 'https://www.mediawiki.org/wiki/Help_talk:New_filters_for_edit_review'
+ } ).$element
+ )
+ }
+ ]
+ },
+ input: {
+ icon: 'menu',
+ placeholder: mw.msg( 'rcfilters-search-placeholder' )
+ }
+ }, config ) );
+
+ this.savedQueryTitle = new OO.ui.LabelWidget( {
+ label: '',
+ classes: [ 'mw-rcfilters-ui-filterTagMultiselectWidget-wrapper-content-savedQueryTitle' ]
+ } );
+
+ this.resetButton = new OO.ui.ButtonWidget( {
+ framed: false,
+ classes: [ 'mw-rcfilters-ui-filterTagMultiselectWidget-resetButton' ]
+ } );
+
+ if ( !mw.user.isAnon() ) {
+ this.saveQueryButton = new mw.rcfilters.ui.SaveFiltersPopupButtonWidget(
+ this.controller,
+ this.queriesModel
+ );
+
+ this.saveQueryButton.$element.on( 'mousedown', function ( e ) { e.stopPropagation(); } );
+
+ this.saveQueryButton.connect( this, {
+ click: 'onSaveQueryButtonClick',
+ saveCurrent: 'setSavedQueryVisibility'
+ } );
+ this.queriesModel.connect( this, {
+ itemUpdate: 'onSavedQueriesItemUpdate',
+ initialize: 'onSavedQueriesInitialize',
+ 'default': 'reevaluateResetRestoreState'
+ } );
+ }
+
+ this.emptyFilterMessage = new OO.ui.LabelWidget( {
+ label: mw.msg( 'rcfilters-empty-filter' ),
+ classes: [ 'mw-rcfilters-ui-filterTagMultiselectWidget-emptyFilters' ]
+ } );
+ this.$content.append( this.emptyFilterMessage.$element );
+
+ // Events
+ this.resetButton.connect( this, { click: 'onResetButtonClick' } );
+ // Stop propagation for mousedown, so that the widget doesn't
+ // trigger the focus on the input and scrolls up when we click the reset button
+ this.resetButton.$element.on( 'mousedown', function ( e ) { e.stopPropagation(); } );
+ this.model.connect( this, {
+ initialize: 'onModelInitialize',
+ update: 'onModelUpdate',
+ itemUpdate: 'onModelItemUpdate',
+ highlightChange: 'onModelHighlightChange'
+ } );
+ this.input.connect( this, { change: 'onInputChange' } );
+
+ // The filter list and button should appear side by side regardless of how
+ // wide the button is; the button also changes its width depending
+ // on language and its state, so the safest way to present both side
+ // by side is with a table layout
+ rcFiltersRow = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-row' )
+ .append(
+ this.$content
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-cell-filters' )
+ );
+
+ if ( !mw.user.isAnon() ) {
+ rcFiltersRow.append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-cell-save' )
+ .append( this.saveQueryButton.$element )
+ );
+ }
+
+ // Add a selector at the right of the input
+ this.viewsSelectWidget = new OO.ui.ButtonSelectWidget( {
+ classes: [ 'mw-rcfilters-ui-filterTagMultiselectWidget-views-select-widget' ],
+ items: [
+ new OO.ui.ButtonOptionWidget( {
+ framed: false,
+ data: '',
+ disabled: true,
+ classes: [ 'mw-rcfilters-ui-filterTagMultiselectWidget-views-select-widget-label' ],
+ label: mw.msg( 'rcfilters-view-advanced-filters-label' )
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ framed: false,
+ data: 'namespaces',
+ icon: 'article',
+ title: mw.msg( 'rcfilters-view-namespaces-tooltip' )
+ } ),
+ new OO.ui.ButtonOptionWidget( {
+ framed: false,
+ data: 'tags',
+ icon: 'tag',
+ title: mw.msg( 'rcfilters-view-tags-tooltip' )
+ } )
+ ]
+ } );
+
+ // Rearrange the UI so the select widget is at the right of the input
+ this.$element.append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-table' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-row' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-views-input' )
+ .append( this.input.$element ),
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-views-select' )
+ .append( this.viewsSelectWidget.$element )
+ )
+ )
+ );
+
+ // Event
+ this.viewsSelectWidget.connect( this, { choose: 'onViewsSelectWidgetChoose' } );
+
+ rcFiltersRow.append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-cell-reset' )
+ .append( this.resetButton.$element )
+ );
+
+ // Build the content
+ $contentWrapper.append(
+ title.$element,
+ this.savedQueryTitle.$element,
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-table' )
+ .append(
+ rcFiltersRow
+ )
+ );
+
+ // Initialize
+ this.$handle.append( $contentWrapper );
+ this.emptyFilterMessage.toggle( this.isEmpty() );
+ this.savedQueryTitle.toggle( false );
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget' );
+
+ this.reevaluateResetRestoreState();
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.FilterTagMultiselectWidget, OO.ui.MenuTagMultiselectWidget );
+
+ /* Methods */
+
+ /**
+ * Respond to view select widget choose event
+ *
+ * @param {OO.ui.ButtonOptionWidget} buttonOptionWidget Chosen widget
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onViewsSelectWidgetChoose = function ( buttonOptionWidget ) {
+ this.controller.switchView( buttonOptionWidget.getData() );
+ this.viewsSelectWidget.selectItem( null );
+ this.focus();
+ };
+
+ /**
+ * Respond to input change event
+ *
+ * @param {string} value Value of the input
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onInputChange = function ( value ) {
+ var view;
+
+ value = value.trim();
+
+ view = this.model.getViewByTrigger( value.substr( 0, 1 ) );
+
+ this.controller.switchView( view );
+ };
+ /**
+ * Respond to query button click
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onSaveQueryButtonClick = function () {
+ this.getMenu().toggle( false );
+ };
+
+ /**
+ * Respond to save query model initialization
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onSavedQueriesInitialize = function () {
+ this.setSavedQueryVisibility();
+ };
+
+ /**
+ * Respond to save query item change. Mainly this is done to update the label in case
+ * a query item has been edited
+ *
+ * @param {mw.rcfilters.dm.SavedQueryItemModel} item Saved query item
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onSavedQueriesItemUpdate = function ( item ) {
+ if ( this.matchingQuery === item ) {
+ // This means we just edited the item that is currently matched
+ this.savedQueryTitle.setLabel( item.getLabel() );
+ }
+ };
+
+ /**
+ * Respond to menu toggle
+ *
+ * @param {boolean} isVisible Menu is visible
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onMenuToggle = function ( isVisible ) {
+ // Parent
+ mw.rcfilters.ui.FilterTagMultiselectWidget.parent.prototype.onMenuToggle.call( this );
+
+ if ( isVisible ) {
+ mw.hook( 'RcFilters.popup.open' ).fire();
+
+ if ( !this.getMenu().getSelectedItem() ) {
+ // If there are no selected items, scroll menu to top
+ // This has to be in a setTimeout so the menu has time
+ // to be positioned and fixed
+ setTimeout( function () { this.getMenu().scrollToTop(); }.bind( this ), 0 );
+ }
+ } else {
+ // Clear selection
+ this.selectTag( null );
+
+ // Clear input if the only thing in the input is the prefix
+ if (
+ this.input.getValue().trim() === this.model.getViewTrigger( this.model.getCurrentView() )
+ ) {
+ // Clear the input
+ this.input.setValue( '' );
+ }
+
+ // Log filter grouping
+ this.controller.trackFilterGroupings( 'filtermenu' );
+ }
+
+ this.input.setIcon( isVisible ? 'search' : 'menu' );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onInputFocus = function () {
+ // Parent
+ mw.rcfilters.ui.FilterTagMultiselectWidget.parent.prototype.onInputFocus.call( this );
+
+ // Only scroll to top of the viewport if:
+ // - The widget is more than 20px from the top
+ // - The widget is not above the top of the viewport (do not scroll downwards)
+ // (This isn't represented because >20 is, anyways and always, bigger than 0)
+ this.scrollToTop( this.$element, 0, { min: 20, max: Infinity } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.doInputEscape = function () {
+ // Parent
+ mw.rcfilters.ui.FilterTagMultiselectWidget.parent.prototype.doInputEscape.call( this );
+
+ // Blur the input
+ this.input.$input.blur();
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onChangeTags = function () {
+ // Parent method
+ mw.rcfilters.ui.FilterTagMultiselectWidget.parent.prototype.onChangeTags.call( this );
+
+ this.emptyFilterMessage.toggle( this.isEmpty() );
+ };
+
+ /**
+ * Respond to model initialize event
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onModelInitialize = function () {
+ this.setSavedQueryVisibility();
+ };
+
+ /**
+ * Respond to model update event
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onModelUpdate = function () {
+ this.updateElementsForView();
+ };
+
+ /**
+ * Update the elements in the widget to the current view
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.updateElementsForView = function () {
+ var view = this.model.getCurrentView(),
+ inputValue = this.input.getValue().trim(),
+ inputView = this.model.getViewByTrigger( inputValue.substr( 0, 1 ) );
+
+ if ( inputView !== 'default' ) {
+ // We have a prefix already, remove it
+ inputValue = inputValue.substr( 1 );
+ }
+
+ if ( inputView !== view ) {
+ // Add the correct prefix
+ inputValue = this.model.getViewTrigger( view ) + inputValue;
+ }
+
+ // Update input
+ this.input.setValue( inputValue );
+
+ if ( this.currentView !== view ) {
+ this.scrollToTop( this.$element );
+ this.currentView = view;
+ }
+ };
+
+ /**
+ * Set the visibility of the saved query button
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.setSavedQueryVisibility = function () {
+ if ( mw.user.isAnon() ) {
+ return;
+ }
+
+ this.matchingQuery = this.controller.findQueryMatchingCurrentState();
+
+ this.savedQueryTitle.setLabel(
+ this.matchingQuery ? this.matchingQuery.getLabel() : ''
+ );
+ this.savedQueryTitle.toggle( !!this.matchingQuery );
+ this.saveQueryButton.toggle( !this.matchingQuery );
+
+ if ( this.matchingQuery ) {
+ this.emphasize();
+ }
+ };
+
+ /**
+ * Respond to model itemUpdate event
+ *
+ * @param {mw.rcfilters.dm.FilterItem} item Filter item model
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onModelItemUpdate = function ( item ) {
+ if ( item.getGroupModel().isHidden() ) {
+ return;
+ }
+
+ if (
+ item.isSelected() ||
+ (
+ this.model.isHighlightEnabled() &&
+ item.isHighlightSupported() &&
+ item.getHighlightColor()
+ )
+ ) {
+ this.addTag( item.getName(), item.getLabel() );
+ } else {
+ this.removeTagByData( item.getName() );
+ }
+
+ this.setSavedQueryVisibility();
+
+ // Re-evaluate reset state
+ this.reevaluateResetRestoreState();
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.isAllowedData = function ( data ) {
+ return (
+ this.model.getItemByName( data ) &&
+ !this.isDuplicateData( data )
+ );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onMenuChoose = function ( item ) {
+ this.controller.toggleFilterSelect( item.model.getName() );
+
+ // Select the tag if it exists, or reset selection otherwise
+ this.selectTag( this.getItemFromData( item.model.getName() ) );
+
+ this.focus();
+ };
+
+ /**
+ * Respond to highlightChange event
+ *
+ * @param {boolean} isHighlightEnabled Highlight is enabled
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onModelHighlightChange = function ( isHighlightEnabled ) {
+ var highlightedItems = this.model.getHighlightedItems();
+
+ if ( isHighlightEnabled ) {
+ // Add capsule widgets
+ highlightedItems.forEach( function ( filterItem ) {
+ this.addTag( filterItem.getName(), filterItem.getLabel() );
+ }.bind( this ) );
+ } else {
+ // Remove capsule widgets if they're not selected
+ highlightedItems.forEach( function ( filterItem ) {
+ if ( !filterItem.isSelected() ) {
+ this.removeTagByData( filterItem.getName() );
+ }
+ }.bind( this ) );
+ }
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onTagSelect = function ( tagItem ) {
+ var widget = this,
+ menuOption = this.menu.getItemFromModel( tagItem.getModel() ),
+ oldInputValue = this.input.getValue().trim();
+
+ this.menu.setUserSelecting( true );
+
+ // Reset input
+ this.input.setValue( '' );
+
+ // Switch view
+ this.controller.switchView( tagItem.getView() );
+
+ // Parent method
+ mw.rcfilters.ui.FilterTagMultiselectWidget.parent.prototype.onTagSelect.call( this, tagItem );
+
+ this.menu.selectItem( menuOption );
+ this.selectTag( tagItem );
+
+ // Scroll to the item
+ if ( this.model.removeViewTriggers( oldInputValue ) ) {
+ // We're binding a 'once' to the itemVisibilityChange event
+ // so this happens when the menu is ready after the items
+ // are visible again, in case this is done right after the
+ // user filtered the results
+ this.getMenu().once(
+ 'itemVisibilityChange',
+ function () {
+ widget.scrollToTop( menuOption.$element );
+ widget.menu.setUserSelecting( false );
+ }
+ );
+ } else {
+ this.scrollToTop( menuOption.$element );
+ this.menu.setUserSelecting( false );
+ }
+
+ };
+
+ /**
+ * Select a tag by reference. This is what OO.ui.SelectWidget is doing.
+ * If no items are given, reset selection from all.
+ *
+ * @param {mw.rcfilters.ui.FilterTagItemWidget} [item] Tag to select,
+ * omit to deselect all
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.selectTag = function ( item ) {
+ var i, len, selected;
+
+ for ( i = 0, len = this.items.length; i < len; i++ ) {
+ selected = this.items[ i ] === item;
+ if ( this.items[ i ].isSelected() !== selected ) {
+ this.items[ i ].toggleSelected( selected );
+ }
+ }
+ };
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onTagRemove = function ( tagItem ) {
+ // Parent method
+ mw.rcfilters.ui.FilterTagMultiselectWidget.parent.prototype.onTagRemove.call( this, tagItem );
+
+ this.controller.clearFilter( tagItem.getName() );
+
+ tagItem.destroy();
+ };
+
+ /**
+ * Respond to click event on the reset button
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.onResetButtonClick = function () {
+ if ( this.model.areCurrentFiltersEmpty() ) {
+ // Reset to default filters
+ this.controller.resetToDefaults();
+ } else {
+ // Reset to have no filters
+ this.controller.emptyFilters();
+ }
+ };
+
+ /**
+ * Reevaluate the restore state for the widget between setting to defaults and clearing all filters
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.reevaluateResetRestoreState = function () {
+ var defaultsAreEmpty = this.controller.areDefaultsEmpty(),
+ currFiltersAreEmpty = this.model.areCurrentFiltersEmpty(),
+ hideResetButton = currFiltersAreEmpty && defaultsAreEmpty;
+
+ this.resetButton.setIcon(
+ currFiltersAreEmpty ? 'history' : 'trash'
+ );
+
+ this.resetButton.setLabel(
+ currFiltersAreEmpty ? mw.msg( 'rcfilters-restore-default-filters' ) : ''
+ );
+ this.resetButton.setTitle(
+ currFiltersAreEmpty ? null : mw.msg( 'rcfilters-clear-all-filters' )
+ );
+
+ this.resetButton.toggle( !hideResetButton );
+ this.emptyFilterMessage.toggle( currFiltersAreEmpty );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.createMenuWidget = function ( menuConfig ) {
+ return new mw.rcfilters.ui.MenuSelectWidget(
+ this.controller,
+ this.model,
+ $.extend( {
+ filterFromInput: true
+ }, menuConfig )
+ );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.createTagItemWidget = function ( data ) {
+ var filterItem = this.model.getItemByName( data );
+
+ if ( filterItem ) {
+ return new mw.rcfilters.ui.FilterTagItemWidget(
+ this.controller,
+ filterItem,
+ {
+ $overlay: this.$overlay
+ }
+ );
+ }
+ };
+
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.emphasize = function () {
+ if (
+ !this.$handle.hasClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-animate' )
+ ) {
+ this.$handle
+ .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-emphasize' )
+ .addClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-animate' );
+
+ setTimeout( function () {
+ this.$handle
+ .removeClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-emphasize' );
+
+ setTimeout( function () {
+ this.$handle
+ .removeClass( 'mw-rcfilters-ui-filterTagMultiselectWidget-animate' );
+ }.bind( this ), 1000 );
+ }.bind( this ), 500 );
+
+ }
+ };
+ /**
+ * Scroll the element to top within its container
+ *
+ * @private
+ * @param {jQuery} $element Element to position
+ * @param {number} [marginFromTop=0] When scrolling the entire widget to the top, leave this
+ * much space (in pixels) above the widget.
+ * @param {Object} [threshold] Minimum distance from the top of the element to scroll at all
+ * @param {number} [threshold.min] Minimum distance above the element
+ * @param {number} [threshold.max] Minimum distance below the element
+ */
+ mw.rcfilters.ui.FilterTagMultiselectWidget.prototype.scrollToTop = function ( $element, marginFromTop, threshold ) {
+ var container = OO.ui.Element.static.getClosestScrollableContainer( $element[ 0 ], 'y' ),
+ pos = OO.ui.Element.static.getRelativePosition( $element, $( container ) ),
+ containerScrollTop = $( container ).scrollTop(),
+ effectiveScrollTop = $( container ).is( 'body, html' ) ? 0 : containerScrollTop,
+ newScrollTop = effectiveScrollTop + pos.top - ( marginFromTop || 0 );
+
+ // Scroll to item
+ if (
+ threshold === undefined ||
+ (
+ (
+ threshold.min === undefined ||
+ newScrollTop - containerScrollTop >= threshold.min
+ ) &&
+ (
+ threshold.max === undefined ||
+ newScrollTop - containerScrollTop <= threshold.max
+ )
+ )
+ ) {
+ $( container ).animate( {
+ scrollTop: newScrollTop
+ } );
+ }
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js
new file mode 100644
index 00000000..db7acaa0
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FilterWrapperWidget.js
@@ -0,0 +1,100 @@
+( function ( mw ) {
+ /**
+ * List displaying all filter groups
+ *
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller Controller
+ * @param {mw.rcfilters.dm.FiltersViewModel} model View model
+ * @param {mw.rcfilters.dm.SavedQueriesModel} savedQueriesModel Saved queries model
+ * @param {mw.rcfilters.dm.ChangesListViewModel} changesListModel
+ * @param {Object} [config] Configuration object
+ * @cfg {Object} [filters] A definition of the filter groups in this list
+ * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
+ */
+ mw.rcfilters.ui.FilterWrapperWidget = function MwRcfiltersUiFilterWrapperWidget(
+ controller, model, savedQueriesModel, changesListModel, config
+ ) {
+ var $bottom;
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.FilterWrapperWidget.parent.call( this, config );
+ // Mixin constructors
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ this.controller = controller;
+ this.model = model;
+ this.queriesModel = savedQueriesModel;
+ this.$overlay = config.$overlay || this.$element;
+
+ this.filterTagWidget = new mw.rcfilters.ui.FilterTagMultiselectWidget(
+ this.controller,
+ this.model,
+ this.queriesModel,
+ { $overlay: this.$overlay }
+ );
+
+ this.liveUpdateButton = new mw.rcfilters.ui.LiveUpdateButtonWidget(
+ this.controller,
+ changesListModel
+ );
+
+ this.numChangesWidget = new mw.rcfilters.ui.ChangesLimitButtonWidget(
+ this.controller,
+ this.model,
+ {
+ $overlay: this.$overlay
+ }
+ );
+
+ this.dateWidget = new mw.rcfilters.ui.DateButtonWidget(
+ this.controller,
+ this.model,
+ {
+ $overlay: this.$overlay
+ }
+ );
+
+ // Initialize
+ this.$top = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-filterWrapperWidget-top' );
+
+ $bottom = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-filterWrapperWidget-bottom' )
+ .append(
+ this.numChangesWidget.$element,
+ this.dateWidget.$element
+ );
+
+ if ( mw.rcfilters.featureFlags.liveUpdate ) {
+ $bottom.append( this.liveUpdateButton.$element );
+ }
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-filterWrapperWidget' )
+ .append(
+ this.$top,
+ this.filterTagWidget.$element,
+ $bottom
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.FilterWrapperWidget, OO.ui.Widget );
+ OO.mixinClass( mw.rcfilters.ui.FilterWrapperWidget, OO.ui.mixin.PendingElement );
+
+ /* Methods */
+
+ /**
+ * Set the content of the top section
+ *
+ * @param {jQuery} $topSectionElement
+ */
+ mw.rcfilters.ui.FilterWrapperWidget.prototype.setTopSection = function ( $topSectionElement ) {
+ this.$top.append( $topSectionElement );
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js
new file mode 100644
index 00000000..83905d5b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.FormWrapperWidget.js
@@ -0,0 +1,169 @@
+( function ( mw ) {
+ /**
+ * Wrapper for the RC form with hide/show links
+ * Must be constructed after the model is initialized.
+ *
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.rcfilters.dm.FiltersViewModel} filtersModel Changes list view model
+ * @param {mw.rcfilters.dm.ChangesListViewModel} changeListModel Changes list view model
+ * @param {mw.rcfilters.Controller} controller RCfilters controller
+ * @param {jQuery} $formRoot Root element of the form to attach to
+ * @param {Object} config Configuration object
+ */
+ mw.rcfilters.ui.FormWrapperWidget = function MwRcfiltersUiFormWrapperWidget( filtersModel, changeListModel, controller, $formRoot, config ) {
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.FormWrapperWidget.parent.call( this, $.extend( {}, config, {
+ $element: $formRoot
+ } ) );
+
+ this.changeListModel = changeListModel;
+ this.filtersModel = filtersModel;
+ this.controller = controller;
+ this.$submitButton = this.$element.find( 'form input[type=submit]' );
+
+ this.$element
+ .on( 'click', 'a[data-params]', this.onLinkClick.bind( this ) );
+
+ this.$element
+ .on( 'submit', 'form', this.onFormSubmit.bind( this ) );
+
+ // Events
+ this.changeListModel.connect( this, {
+ invalidate: 'onChangesModelInvalidate',
+ update: 'onChangesModelUpdate'
+ } );
+
+ // Initialize
+ this.cleanUpFieldset();
+ this.$element
+ .addClass( 'mw-rcfilters-ui-FormWrapperWidget' );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.FormWrapperWidget, OO.ui.Widget );
+
+ /**
+ * Respond to link click
+ *
+ * @param {jQuery.Event} e Event
+ * @return {boolean} false
+ */
+ mw.rcfilters.ui.FormWrapperWidget.prototype.onLinkClick = function ( e ) {
+ this.controller.updateChangesList( $( e.target ).data( 'params' ) );
+ return false;
+ };
+
+ /**
+ * Respond to form submit event
+ *
+ * @param {jQuery.Event} e Event
+ * @return {boolean} false
+ */
+ mw.rcfilters.ui.FormWrapperWidget.prototype.onFormSubmit = function ( e ) {
+ var data = {};
+
+ // Collect all data from form
+ $( e.target ).find( 'input:not([type="hidden"],[type="submit"]), select' ).each( function () {
+ var value = '';
+
+ if ( !$( this ).is( ':checkbox' ) || $( this ).is( ':checked' ) ) {
+ value = $( this ).val();
+ }
+
+ data[ $( this ).prop( 'name' ) ] = value;
+ } );
+
+ this.controller.updateChangesList( data );
+ return false;
+ };
+
+ /**
+ * Respond to model invalidate
+ */
+ mw.rcfilters.ui.FormWrapperWidget.prototype.onChangesModelInvalidate = function () {
+ this.$submitButton.prop( 'disabled', true );
+ };
+
+ /**
+ * Respond to model update, replace the show/hide links with the ones from the
+ * server so they feature the correct state.
+ *
+ * @param {jQuery|string} $changesList Updated changes list
+ * @param {jQuery} $fieldset Updated fieldset
+ * @param {boolean} isInitialDOM Whether $changesListContent is the existing (already attached) DOM
+ */
+ mw.rcfilters.ui.FormWrapperWidget.prototype.onChangesModelUpdate = function ( $changesList, $fieldset, isInitialDOM ) {
+ this.$submitButton.prop( 'disabled', false );
+
+ // Replace the entire fieldset
+ this.$element.empty().append( $fieldset.contents() );
+
+ if ( !isInitialDOM ) {
+ // Make sure enhanced RC re-initializes correctly
+ mw.hook( 'wikipage.content' ).fire( this.$element );
+ }
+
+ this.cleanUpFieldset();
+ };
+
+ /**
+ * Clean up the old-style show/hide that we have implemented in the filter list
+ */
+ mw.rcfilters.ui.FormWrapperWidget.prototype.cleanUpFieldset = function () {
+ this.$element.find( '.clshowhideoption[data-feature-in-structured-ui=1]' ).each( function () {
+ // HACK: Remove the text node after the span.
+ // If there isn't one, we're at the end, so remove the text node before the span.
+ // This would be unnecessary if we added separators with CSS.
+ if ( this.nextSibling && this.nextSibling.nodeType === Node.TEXT_NODE ) {
+ this.parentNode.removeChild( this.nextSibling );
+ } else if ( this.previousSibling && this.previousSibling.nodeType === Node.TEXT_NODE ) {
+ this.parentNode.removeChild( this.previousSibling );
+ }
+ // Remove the span itself
+ this.parentNode.removeChild( this );
+ } );
+
+ // Hide namespaces and tags
+ this.$element.find( '.namespaceForm' ).detach();
+ this.$element.find( '.mw-tagfilter-label' ).closest( 'tr' ).detach();
+
+ // misc: limit, days, watchlist info msg
+ this.$element.find( '.rclinks, .cldays, .wlinfo' ).detach();
+
+ if ( !this.$element.find( '.mw-recentchanges-table tr' ).length ) {
+ this.$element.find( '.mw-recentchanges-table' ).detach();
+ this.$element.find( 'hr' ).detach();
+ }
+
+ // Get rid of all <br>s, which are inside rcshowhide
+ // If we still have content in rcshowhide, the <br>s are
+ // gone. Instead, the CSS now has a rule to mark all <span>s
+ // inside .rcshowhide with display:block; to simulate newlines
+ // where they're actually needed.
+ this.$element.find( 'br' ).detach();
+ if ( !this.$element.find( '.rcshowhide' ).contents().length ) {
+ this.$element.find( '.rcshowhide' ).detach();
+ }
+
+ if ( this.$element.find( '.cloption' ).text().trim() === '' ) {
+ this.$element.find( '.cloption-submit' ).detach();
+ }
+
+ this.$element.find(
+ '.rclistfrom, .rcnotefrom, .rcoptions-listfromreset'
+ ).detach();
+
+ // Get rid of the legend
+ this.$element.find( 'legend' ).detach();
+
+ // Check if the element is essentially empty, and detach it if it is
+ if ( !this.$element.text().trim().length ) {
+ this.$element.detach();
+ }
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.HighlightColorPickerWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.HighlightColorPickerWidget.js
new file mode 100644
index 00000000..570647e6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.HighlightColorPickerWidget.js
@@ -0,0 +1,112 @@
+( function ( mw, $ ) {
+ /**
+ * A widget representing a filter item highlight color picker
+ *
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.LabelElement
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller RCFilters controller
+ * @param {mw.rcfilters.dm.FilterItem} model Filter item model
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.HighlightColorPickerWidget = function MwRcfiltersUiHighlightColorPickerWidget( controller, model, config ) {
+ var colors = [ 'none' ].concat( mw.rcfilters.HighlightColors );
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.HighlightColorPickerWidget.parent.call( this, config );
+ // Mixin constructors
+ OO.ui.mixin.LabelElement.call( this, $.extend( {}, config, {
+ label: mw.message( 'rcfilters-highlightmenu-title' ).text()
+ } ) );
+
+ this.controller = controller;
+ this.model = model;
+
+ this.currentSelection = '';
+ this.buttonSelect = new OO.ui.ButtonSelectWidget( {
+ items: colors.map( function ( color ) {
+ return new OO.ui.ButtonOptionWidget( {
+ icon: color === 'none' ? 'check' : null,
+ data: color,
+ classes: [
+ 'mw-rcfilters-ui-highlightColorPickerWidget-buttonSelect-color',
+ 'mw-rcfilters-ui-highlightColorPickerWidget-buttonSelect-color-' + color
+ ],
+ framed: false
+ } );
+ } ),
+ classes: 'mw-rcfilters-ui-highlightColorPickerWidget-buttonSelect'
+ } );
+ this.selectColor( 'none' );
+
+ // Event
+ this.model.connect( this, { update: 'onModelUpdate' } );
+ this.buttonSelect.connect( this, { choose: 'onChooseColor' } );
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-highlightColorPickerWidget' )
+ .append(
+ this.$label
+ .addClass( 'mw-rcfilters-ui-highlightColorPickerWidget-label' ),
+ this.buttonSelect.$element
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.HighlightColorPickerWidget, OO.ui.Widget );
+ OO.mixinClass( mw.rcfilters.ui.HighlightColorPickerWidget, OO.ui.mixin.LabelElement );
+
+ /* Events */
+
+ /**
+ * @event chooseColor
+ * @param {string} The chosen color
+ *
+ * A color has been chosen
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to item model update event
+ */
+ mw.rcfilters.ui.HighlightColorPickerWidget.prototype.onModelUpdate = function () {
+ this.selectColor( this.model.getHighlightColor() || 'none' );
+ };
+
+ /**
+ * Select the color for this widget
+ *
+ * @param {string} color Selected color
+ */
+ mw.rcfilters.ui.HighlightColorPickerWidget.prototype.selectColor = function ( color ) {
+ var previousItem = this.buttonSelect.getItemFromData( this.currentSelection ),
+ selectedItem = this.buttonSelect.getItemFromData( color );
+
+ if ( this.currentSelection !== color ) {
+ this.currentSelection = color;
+
+ this.buttonSelect.selectItem( selectedItem );
+ if ( previousItem ) {
+ previousItem.setIcon( null );
+ }
+
+ if ( selectedItem ) {
+ selectedItem.setIcon( 'check' );
+ }
+ }
+ };
+
+ mw.rcfilters.ui.HighlightColorPickerWidget.prototype.onChooseColor = function ( button ) {
+ var color = button.data;
+ if ( color === 'none' ) {
+ this.controller.clearHighlightColor( this.model.getName() );
+ } else {
+ this.controller.setHighlightColor( this.model.getName(), color );
+ }
+ this.emit( 'chooseColor', color );
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ItemMenuOptionWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ItemMenuOptionWidget.js
new file mode 100644
index 00000000..f2e9b1db
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ItemMenuOptionWidget.js
@@ -0,0 +1,144 @@
+( function ( mw ) {
+ /**
+ * A widget representing a base toggle item
+ *
+ * @extends OO.ui.MenuOptionWidget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller RCFilters controller
+ * @param {mw.rcfilters.dm.ItemModel} model Item model
+ * @param {Object} config Configuration object
+ */
+ mw.rcfilters.ui.ItemMenuOptionWidget = function MwRcfiltersUiItemMenuOptionWidget( controller, model, config ) {
+ var layout,
+ classes = [],
+ $label = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-itemMenuOptionWidget-label' );
+
+ config = config || {};
+
+ this.controller = controller;
+ this.model = model;
+
+ // Parent
+ mw.rcfilters.ui.ItemMenuOptionWidget.parent.call( this, $.extend( {
+ // Override the 'check' icon that OOUI defines
+ icon: '',
+ data: this.model.getName(),
+ label: this.model.getLabel()
+ }, config ) );
+
+ this.checkboxWidget = new mw.rcfilters.ui.CheckboxInputWidget( {
+ value: this.model.getName(),
+ selected: this.model.isSelected()
+ } );
+
+ $label.append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-itemMenuOptionWidget-label-title' )
+ .append( this.$label )
+ );
+ if ( this.model.getDescription() ) {
+ $label.append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-itemMenuOptionWidget-label-desc' )
+ .text( this.model.getDescription() )
+ );
+ }
+
+ this.highlightButton = new mw.rcfilters.ui.FilterItemHighlightButton(
+ this.controller,
+ this.model,
+ {
+ $overlay: config.$overlay || this.$element,
+ title: mw.msg( 'rcfilters-highlightmenu-help' )
+ }
+ );
+ this.highlightButton.toggle( this.model.isHighlightEnabled() );
+
+ this.excludeLabel = new OO.ui.LabelWidget( {
+ label: mw.msg( 'rcfilters-filter-excluded' )
+ } );
+ this.excludeLabel.toggle( this.model.isSelected() && this.model.isInverted() );
+
+ layout = new OO.ui.FieldLayout( this.checkboxWidget, {
+ label: $label,
+ align: 'inline'
+ } );
+
+ // Events
+ this.model.connect( this, { update: 'onModelUpdate' } );
+ // HACK: Prevent defaults on 'click' for the label so it
+ // doesn't steal the focus away from the input. This means
+ // we can continue arrow-movement after we click the label
+ // and is consistent with the checkbox *itself* also preventing
+ // defaults on 'click' as well.
+ layout.$label.on( 'click', false );
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-itemMenuOptionWidget' )
+ .addClass( 'mw-rcfilters-ui-itemMenuOptionWidget-view-' + this.model.getGroupModel().getView() )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-table' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-row' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell mw-rcfilters-ui-itemMenuOptionWidget-itemCheckbox' )
+ .append( layout.$element ),
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell mw-rcfilters-ui-itemMenuOptionWidget-excludeLabel' )
+ .append( this.excludeLabel.$element ),
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell mw-rcfilters-ui-itemMenuOptionWidget-highlightButton' )
+ .append( this.highlightButton.$element )
+ )
+ )
+ );
+
+ if ( this.model.getIdentifiers() ) {
+ this.model.getIdentifiers().forEach( function ( ident ) {
+ classes.push( 'mw-rcfilters-ui-itemMenuOptionWidget-identifier-' + ident );
+ } );
+
+ this.$element.addClass( classes.join( ' ' ) );
+ }
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.ItemMenuOptionWidget, OO.ui.MenuOptionWidget );
+
+ /* Static properties */
+
+ // We do our own scrolling to top
+ mw.rcfilters.ui.ItemMenuOptionWidget.static.scrollIntoViewOnSelect = false;
+
+ /* Methods */
+
+ /**
+ * Respond to item model update event
+ */
+ mw.rcfilters.ui.ItemMenuOptionWidget.prototype.onModelUpdate = function () {
+ this.checkboxWidget.setSelected( this.model.isSelected() );
+
+ this.highlightButton.toggle( this.model.isHighlightEnabled() );
+ this.excludeLabel.toggle( this.model.isSelected() && this.model.isInverted() );
+ };
+
+ /**
+ * Get the name of this filter
+ *
+ * @return {string} Filter name
+ */
+ mw.rcfilters.ui.ItemMenuOptionWidget.prototype.getName = function () {
+ return this.model.getName();
+ };
+
+ mw.rcfilters.ui.ItemMenuOptionWidget.prototype.getModel = function () {
+ return this.model;
+ };
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.LiveUpdateButtonWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.LiveUpdateButtonWidget.js
new file mode 100644
index 00000000..0fb3cb77
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.LiveUpdateButtonWidget.js
@@ -0,0 +1,69 @@
+( function ( mw ) {
+ /**
+ * Widget for toggling live updates
+ *
+ * @extends OO.ui.ToggleButtonWidget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller
+ * @param {mw.rcfilters.dm.ChangesListViewModel} changesListModel
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.LiveUpdateButtonWidget = function MwRcfiltersUiLiveUpdateButtonWidget( controller, changesListModel, config ) {
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.LiveUpdateButtonWidget.parent.call( this, $.extend( {
+ label: mw.message( 'rcfilters-liveupdates-button' ).text()
+ }, config ) );
+
+ this.controller = controller;
+ this.model = changesListModel;
+
+ // Events
+ this.connect( this, { click: 'onClick' } );
+ this.model.connect( this, { liveUpdateChange: 'onLiveUpdateChange' } );
+
+ this.$element.addClass( 'mw-rcfilters-ui-liveUpdateButtonWidget' );
+
+ this.setState( false );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.LiveUpdateButtonWidget, OO.ui.ToggleButtonWidget );
+
+ /* Methods */
+
+ /**
+ * Respond to the button being clicked
+ */
+ mw.rcfilters.ui.LiveUpdateButtonWidget.prototype.onClick = function () {
+ this.controller.toggleLiveUpdate();
+ };
+
+ /**
+ * Set the button's state and change its appearance
+ *
+ * @param {boolean} enable Whether the 'live update' feature is now on/off
+ */
+ mw.rcfilters.ui.LiveUpdateButtonWidget.prototype.setState = function ( enable ) {
+ this.setValue( enable );
+ this.setIcon( enable ? 'stop' : 'play' );
+ this.setTitle( mw.message(
+ enable ?
+ 'rcfilters-liveupdates-button-title-on' :
+ 'rcfilters-liveupdates-button-title-off'
+ ).text() );
+ };
+
+ /**
+ * Respond to the 'live update' feature being turned on/off
+ *
+ * @param {boolean} enable Whether the 'live update' feature is now on/off
+ */
+ mw.rcfilters.ui.LiveUpdateButtonWidget.prototype.onLiveUpdateChange = function ( enable ) {
+ this.setState( enable );
+ };
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MarkSeenButtonWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MarkSeenButtonWidget.js
new file mode 100644
index 00000000..56fe5b93
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MarkSeenButtonWidget.js
@@ -0,0 +1,55 @@
+( function ( mw ) {
+ /**
+ * Button for marking all changes as seen on the Watchlist
+ *
+ * @extends OO.ui.ButtonWidget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller
+ * @param {mw.rcfilters.dm.ChangesListViewModel} model Changes list view model
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.MarkSeenButtonWidget = function MwRcfiltersUiMarkSeenButtonWidget( controller, model, config ) {
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.MarkSeenButtonWidget.parent.call( this, $.extend( {
+ label: mw.message( 'rcfilters-watchlist-markseen-button' ).text(),
+ icon: 'doubleCheck'
+ }, config ) );
+
+ this.controller = controller;
+ this.model = model;
+
+ // Events
+ this.connect( this, { click: 'onClick' } );
+ this.model.connect( this, { update: 'onModelUpdate' } );
+
+ this.$element.addClass( 'mw-rcfilters-ui-markSeenButtonWidget' );
+
+ this.onModelUpdate();
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.MarkSeenButtonWidget, OO.ui.ButtonWidget );
+
+ /* Methods */
+
+ /**
+ * Respond to the button being clicked
+ */
+ mw.rcfilters.ui.MarkSeenButtonWidget.prototype.onClick = function () {
+ this.controller.markAllChangesAsSeen();
+ // assume there's no more unseen changes until the next model update
+ this.setDisabled( true );
+ };
+
+ /**
+ * Respond to the model being updated with new changes
+ */
+ mw.rcfilters.ui.MarkSeenButtonWidget.prototype.onModelUpdate = function () {
+ this.setDisabled( !this.model.hasUnseenWatchedChanges() );
+ };
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js
new file mode 100644
index 00000000..07d4506b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js
@@ -0,0 +1,359 @@
+( function ( mw ) {
+ /**
+ * A floating menu widget for the filter list
+ *
+ * @extends OO.ui.MenuSelectWidget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller Controller
+ * @param {mw.rcfilters.dm.FiltersViewModel} model View model
+ * @param {Object} [config] Configuration object
+ * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
+ * @cfg {Object[]} [footers] An array of objects defining the footers for
+ * this menu, with a definition whether they appear per specific views.
+ * The expected structure is:
+ * [
+ * {
+ * name: {string} A unique name for the footer object
+ * $element: {jQuery} A jQuery object for the content of the footer
+ * views: {string[]} Optional. An array stating which views this footer is
+ * active on. Use null or omit to display this on all views.
+ * }
+ * ]
+ */
+ mw.rcfilters.ui.MenuSelectWidget = function MwRcfiltersUiMenuSelectWidget( controller, model, config ) {
+ var header;
+
+ config = config || {};
+
+ this.controller = controller;
+ this.model = model;
+ this.currentView = '';
+ this.views = {};
+ this.userSelecting = false;
+
+ this.inputValue = '';
+ this.$overlay = config.$overlay || this.$element;
+ this.$body = $( '<div>' ).addClass( 'mw-rcfilters-ui-menuSelectWidget-body' );
+ this.footers = [];
+
+ // Parent
+ mw.rcfilters.ui.MenuSelectWidget.parent.call( this, $.extend( {
+ $autoCloseIgnore: this.$overlay,
+ width: 650
+ }, config ) );
+ this.setGroupElement(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-menuSelectWidget-group' )
+ );
+ this.setClippableElement( this.$body );
+ this.setClippableContainer( this.$element );
+
+ header = new mw.rcfilters.ui.FilterMenuHeaderWidget(
+ this.controller,
+ this.model,
+ {
+ $overlay: this.$overlay
+ }
+ );
+
+ this.noResults = new OO.ui.LabelWidget( {
+ label: mw.msg( 'rcfilters-filterlist-noresults' ),
+ classes: [ 'mw-rcfilters-ui-menuSelectWidget-noresults' ]
+ } );
+
+ // Events
+ this.model.connect( this, {
+ update: 'onModelUpdate',
+ initialize: 'onModelInitialize'
+ } );
+
+ // Initialization
+ this.$element
+ .addClass( 'mw-rcfilters-ui-menuSelectWidget' )
+ .append( header.$element )
+ .append(
+ this.$body
+ .append( this.$group, this.noResults.$element )
+ );
+
+ // Append all footers; we will control their visibility
+ // based on view
+ config.footers = config.footers || [];
+ config.footers.forEach( function ( footerData ) {
+ var isSticky = footerData.sticky === undefined ? true : !!footerData.sticky,
+ adjustedData = {
+ // Wrap the element with our own footer wrapper
+ $element: $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-menuSelectWidget-footer' )
+ .addClass( 'mw-rcfilters-ui-menuSelectWidget-footer-' + footerData.name )
+ .append( footerData.$element ),
+ views: footerData.views
+ };
+
+ if ( !footerData.disabled ) {
+ this.footers.push( adjustedData );
+
+ if ( isSticky ) {
+ this.$element.append( adjustedData.$element );
+ } else {
+ this.$body.append( adjustedData.$element );
+ }
+ }
+ }.bind( this ) );
+
+ // Switch to the correct view
+ this.switchView( this.model.getCurrentView() );
+ };
+
+ /* Initialize */
+
+ OO.inheritClass( mw.rcfilters.ui.MenuSelectWidget, OO.ui.MenuSelectWidget );
+
+ /* Events */
+
+ /**
+ * @event itemVisibilityChange
+ *
+ * Item visibility has changed
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to model update event
+ */
+ mw.rcfilters.ui.MenuSelectWidget.prototype.onModelUpdate = function () {
+ // Change view
+ this.switchView( this.model.getCurrentView() );
+ };
+
+ /**
+ * Respond to model initialize event. Populate the menu from the model
+ */
+ mw.rcfilters.ui.MenuSelectWidget.prototype.onModelInitialize = function () {
+ var widget = this,
+ viewGroupCount = {},
+ groups = this.model.getFilterGroups();
+
+ // Reset
+ this.clearItems();
+
+ // Count groups per view
+ $.each( groups, function ( groupName, groupModel ) {
+ if ( !groupModel.isHidden() ) {
+ viewGroupCount[ groupModel.getView() ] = viewGroupCount[ groupModel.getView() ] || 0;
+ viewGroupCount[ groupModel.getView() ]++;
+ }
+ } );
+
+ $.each( groups, function ( groupName, groupModel ) {
+ var currentItems = [],
+ view = groupModel.getView();
+
+ if ( !groupModel.isHidden() ) {
+ if ( viewGroupCount[ view ] > 1 ) {
+ // Only add a section header if there is more than
+ // one group
+ currentItems.push(
+ // Group section
+ new mw.rcfilters.ui.FilterMenuSectionOptionWidget(
+ widget.controller,
+ groupModel,
+ {
+ $overlay: widget.$overlay
+ }
+ )
+ );
+ }
+
+ // Add items
+ widget.model.getGroupFilters( groupName ).forEach( function ( filterItem ) {
+ currentItems.push(
+ new mw.rcfilters.ui.FilterMenuOptionWidget(
+ widget.controller,
+ filterItem,
+ {
+ $overlay: widget.$overlay
+ }
+ )
+ );
+ } );
+
+ // Cache the items per view, so we can switch between them
+ // without rebuilding the widgets each time
+ widget.views[ view ] = widget.views[ view ] || [];
+ widget.views[ view ] = widget.views[ view ].concat( currentItems );
+ }
+ } );
+
+ this.switchView( this.model.getCurrentView() );
+ };
+
+ /**
+ * Switch view
+ *
+ * @param {string} [viewName] View name. If not given, default is used.
+ */
+ mw.rcfilters.ui.MenuSelectWidget.prototype.switchView = function ( viewName ) {
+ viewName = viewName || 'default';
+
+ if ( this.views[ viewName ] && this.currentView !== viewName ) {
+ this.clearItems();
+ this.addItems( this.views[ viewName ] );
+ this.updateFooterVisibility( viewName );
+
+ this.$element
+ .data( 'view', viewName )
+ .removeClass( 'mw-rcfilters-ui-menuSelectWidget-view-' + this.currentView )
+ .addClass( 'mw-rcfilters-ui-menuSelectWidget-view-' + viewName );
+
+ this.currentView = viewName;
+ this.scrollToTop();
+ this.clip();
+ }
+ };
+
+ /**
+ * Go over the available footers and decide which should be visible
+ * for this view
+ *
+ * @param {string} [currentView] Current view
+ */
+ mw.rcfilters.ui.MenuSelectWidget.prototype.updateFooterVisibility = function ( currentView ) {
+ currentView = currentView || this.model.getCurrentView();
+
+ this.footers.forEach( function ( data ) {
+ data.$element.toggle(
+ // This footer should only be shown if it is configured
+ // for all views or for this specific view
+ !data.views || data.views.length === 0 || data.views.indexOf( currentView ) > -1
+ );
+ } );
+ };
+
+ /**
+ * @fires itemVisibilityChange
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.MenuSelectWidget.prototype.updateItemVisibility = function () {
+ var i,
+ itemWasSelected = false,
+ inputVal = this.$input.val(),
+ items = this.getItems();
+
+ // Since the method hides/shows items, we don't want to
+ // call it unless the input actually changed
+ if (
+ !this.userSelecting &&
+ this.inputValue !== inputVal
+ ) {
+ // Parent method
+ mw.rcfilters.ui.MenuSelectWidget.parent.prototype.updateItemVisibility.call( this );
+
+ // Select the first item in the list
+ for ( i = 0; i < items.length; i++ ) {
+ if (
+ !( items[ i ] instanceof OO.ui.MenuSectionOptionWidget ) &&
+ items[ i ].isVisible()
+ ) {
+ itemWasSelected = true;
+ this.selectItem( items[ i ] );
+ break;
+ }
+ }
+
+ if ( !itemWasSelected ) {
+ this.selectItem( null );
+ }
+
+ // Cache value
+ this.inputValue = inputVal;
+
+ this.emit( 'itemVisibilityChange' );
+ }
+
+ this.noResults.toggle( !this.getItems().some( function ( item ) {
+ return item.isVisible();
+ } ) );
+ };
+
+ /**
+ * Get the option widget that matches the model given
+ *
+ * @param {mw.rcfilters.dm.ItemModel} model Item model
+ * @return {mw.rcfilters.ui.ItemMenuOptionWidget} Option widget
+ */
+ mw.rcfilters.ui.MenuSelectWidget.prototype.getItemFromModel = function ( model ) {
+ return this.views[ model.getGroupModel().getView() ].filter( function ( item ) {
+ return item.getName() === model.getName();
+ } )[ 0 ];
+ };
+
+ /**
+ * Override the item matcher to use the model's match process
+ *
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.MenuSelectWidget.prototype.getItemMatcher = function ( s ) {
+ var results = this.model.findMatches( s, true );
+
+ return function ( item ) {
+ return results.indexOf( item.getModel() ) > -1;
+ };
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.rcfilters.ui.MenuSelectWidget.prototype.onKeyDown = function ( e ) {
+ var nextItem,
+ currentItem = this.getHighlightedItem() || this.getSelectedItem();
+
+ // Call parent
+ mw.rcfilters.ui.MenuSelectWidget.parent.prototype.onKeyDown.call( this, e );
+
+ // We want to select the item on arrow movement
+ // rather than just highlight it, like the menu
+ // does by default
+ if ( !this.isDisabled() && this.isVisible() ) {
+ switch ( e.keyCode ) {
+ case OO.ui.Keys.UP:
+ case OO.ui.Keys.LEFT:
+ // Get the next item
+ nextItem = this.getRelativeSelectableItem( currentItem, -1 );
+ break;
+ case OO.ui.Keys.DOWN:
+ case OO.ui.Keys.RIGHT:
+ // Get the next item
+ nextItem = this.getRelativeSelectableItem( currentItem, 1 );
+ break;
+ }
+
+ nextItem = nextItem && nextItem.constructor.static.selectable ?
+ nextItem : null;
+
+ // Select the next item
+ this.selectItem( nextItem );
+ }
+ };
+
+ /**
+ * Scroll to the top of the menu
+ */
+ mw.rcfilters.ui.MenuSelectWidget.prototype.scrollToTop = function () {
+ this.$body.scrollTop( 0 );
+ };
+
+ /**
+ * Set whether the user is currently selecting an item.
+ * This is important when the user selects an item that is in between
+ * different views, and makes sure we do not re-select a different
+ * item (like the item on top) when this is happening.
+ *
+ * @param {boolean} isSelecting User is selecting
+ */
+ mw.rcfilters.ui.MenuSelectWidget.prototype.setUserSelecting = function ( isSelecting ) {
+ this.userSelecting = !!isSelecting;
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.RcTopSectionWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.RcTopSectionWidget.js
new file mode 100644
index 00000000..95a4e592
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.RcTopSectionWidget.js
@@ -0,0 +1,109 @@
+( function ( mw ) {
+ /**
+ * Top section (between page title and filters) on Special:Recentchanges
+ *
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.rcfilters.ui.SavedLinksListWidget} savedLinksListWidget
+ * @param {jQuery} $topLinks Content of the community-defined links
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.RcTopSectionWidget = function MwRcfiltersUiRcTopSectionWidget(
+ savedLinksListWidget, $topLinks, config
+ ) {
+ var toplinksTitle,
+ topLinksCookieName = 'rcfilters-toplinks-collapsed-state',
+ topLinksCookie = mw.cookie.get( topLinksCookieName ),
+ topLinksCookieValue = topLinksCookie || 'collapsed',
+ widget = this;
+
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.RcTopSectionWidget.parent.call( this, config );
+
+ this.$topLinks = $topLinks;
+
+ toplinksTitle = new OO.ui.ButtonWidget( {
+ framed: false,
+ indicator: topLinksCookieValue === 'collapsed' ? 'down' : 'up',
+ flags: [ 'progressive' ],
+ label: $( '<span>' ).append( mw.message( 'rcfilters-other-review-tools' ).parse() ).contents()
+ } );
+
+ this.$topLinks
+ .makeCollapsible( {
+ collapsed: topLinksCookieValue === 'collapsed',
+ $customTogglers: toplinksTitle.$element
+ } )
+ .on( 'beforeExpand.mw-collapsible', function () {
+ mw.cookie.set( topLinksCookieName, 'expanded' );
+ toplinksTitle.setIndicator( 'up' );
+ widget.switchTopLinks( 'expanded' );
+ } )
+ .on( 'beforeCollapse.mw-collapsible', function () {
+ mw.cookie.set( topLinksCookieName, 'collapsed' );
+ toplinksTitle.setIndicator( 'down' );
+ widget.switchTopLinks( 'collapsed' );
+ } );
+
+ this.$topLinks.find( '.mw-recentchanges-toplinks-title' ).replaceWith( toplinksTitle.$element );
+
+ // Create two positions for the toplinks to toggle between
+ // in the table (first cell) or up above it
+ this.$top = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-rcTopSectionWidget-topLinks-top' );
+ this.$tableTopLinks = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-rcTopSectionWidget-topLinks-table' );
+
+ // Initialize
+ this.$element
+ .addClass( 'mw-rcfilters-ui-rcTopSectionWidget' )
+ .append(
+ this.$top,
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-table' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-row' )
+ .append(
+ this.$tableTopLinks,
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-table-placeholder' )
+ .addClass( 'mw-rcfilters-ui-cell' ),
+ !mw.user.isAnon() ?
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-rcTopSectionWidget-savedLinks' )
+ .append( savedLinksListWidget.$element ) :
+ null
+ )
+ )
+ );
+
+ // Initialize top links position
+ widget.switchTopLinks( topLinksCookieValue );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.RcTopSectionWidget, OO.ui.Widget );
+
+ /**
+ * Switch the top links widget from inside the table (when collapsed)
+ * to the 'top' (when open)
+ *
+ * @param {string} [state] The state of the top links widget: 'expanded' or 'collapsed'
+ */
+ mw.rcfilters.ui.RcTopSectionWidget.prototype.switchTopLinks = function ( state ) {
+ state = state || 'expanded';
+
+ if ( state === 'expanded' ) {
+ this.$top.append( this.$topLinks );
+ } else {
+ this.$tableTopLinks.append( this.$topLinks );
+ }
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SaveFiltersPopupButtonWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SaveFiltersPopupButtonWidget.js
new file mode 100644
index 00000000..bb837e00
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SaveFiltersPopupButtonWidget.js
@@ -0,0 +1,189 @@
+( function ( mw ) {
+ /**
+ * Save filters widget. This widget is displayed in the tag area
+ * and allows the user to save the current state of the system
+ * as a new saved filter query they can later load or set as
+ * default.
+ *
+ * @extends OO.ui.PopupButtonWidget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller Controller
+ * @param {mw.rcfilters.dm.SavedQueriesModel} model View model
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.SaveFiltersPopupButtonWidget = function MwRcfiltersUiSaveFiltersPopupButtonWidget( controller, model, config ) {
+ var layout,
+ checkBoxLayout,
+ $popupContent = $( '<div>' );
+
+ config = config || {};
+
+ this.controller = controller;
+ this.model = model;
+
+ // Parent
+ mw.rcfilters.ui.SaveFiltersPopupButtonWidget.parent.call( this, $.extend( {
+ framed: false,
+ icon: 'unClip',
+ $overlay: this.$overlay,
+ title: mw.msg( 'rcfilters-savedqueries-add-new-title' ),
+ popup: {
+ classes: [ 'mw-rcfilters-ui-saveFiltersPopupButtonWidget-popup' ],
+ padded: true,
+ head: true,
+ label: mw.msg( 'rcfilters-savedqueries-add-new-title' ),
+ $content: $popupContent
+ }
+ }, config ) );
+ // // HACK: Add an icon to the popup head label
+ this.popup.$head.prepend( ( new OO.ui.IconWidget( { icon: 'unClip' } ) ).$element );
+
+ this.input = new OO.ui.TextInputWidget( {
+ placeholder: mw.msg( 'rcfilters-savedqueries-new-name-placeholder' )
+ } );
+ layout = new OO.ui.FieldLayout( this.input, {
+ label: mw.msg( 'rcfilters-savedqueries-new-name-label' ),
+ align: 'top'
+ } );
+
+ this.setAsDefaultCheckbox = new OO.ui.CheckboxInputWidget();
+ checkBoxLayout = new OO.ui.FieldLayout( this.setAsDefaultCheckbox, {
+ label: mw.msg( 'rcfilters-savedqueries-setdefault' ),
+ align: 'inline'
+ } );
+
+ this.applyButton = new OO.ui.ButtonWidget( {
+ label: mw.msg( 'rcfilters-savedqueries-apply-label' ),
+ classes: [ 'mw-rcfilters-ui-saveFiltersPopupButtonWidget-popup-buttons-apply' ],
+ flags: [ 'primary', 'progressive' ]
+ } );
+ this.cancelButton = new OO.ui.ButtonWidget( {
+ label: mw.msg( 'rcfilters-savedqueries-cancel-label' ),
+ classes: [ 'mw-rcfilters-ui-saveFiltersPopupButtonWidget-popup-buttons-cancel' ]
+ } );
+
+ $popupContent
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-saveFiltersPopupButtonWidget-popup-layout' )
+ .append( layout.$element ),
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-saveFiltersPopupButtonWidget-popup-options' )
+ .append( checkBoxLayout.$element ),
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-saveFiltersPopupButtonWidget-popup-buttons' )
+ .append(
+ this.cancelButton.$element,
+ this.applyButton.$element
+ )
+ );
+
+ // Events
+ this.popup.connect( this, {
+ ready: 'onPopupReady'
+ } );
+ this.input.connect( this, {
+ change: 'onInputChange',
+ enter: 'onInputEnter'
+ } );
+ this.input.$input.on( {
+ keyup: this.onInputKeyup.bind( this )
+ } );
+ this.setAsDefaultCheckbox.connect( this, { change: 'onSetAsDefaultChange' } );
+ this.cancelButton.connect( this, { click: 'onCancelButtonClick' } );
+ this.applyButton.connect( this, { click: 'onApplyButtonClick' } );
+
+ // Initialize
+ this.applyButton.setDisabled( !this.input.getValue() );
+ this.$element
+ .addClass( 'mw-rcfilters-ui-saveFiltersPopupButtonWidget' );
+ };
+
+ /* Initialization */
+ OO.inheritClass( mw.rcfilters.ui.SaveFiltersPopupButtonWidget, OO.ui.PopupButtonWidget );
+
+ /**
+ * Respond to input enter event
+ */
+ mw.rcfilters.ui.SaveFiltersPopupButtonWidget.prototype.onInputEnter = function () {
+ this.apply();
+ };
+
+ /**
+ * Respond to input change event
+ *
+ * @param {string} value Input value
+ */
+ mw.rcfilters.ui.SaveFiltersPopupButtonWidget.prototype.onInputChange = function ( value ) {
+ value = value.trim();
+
+ this.applyButton.setDisabled( !value );
+ };
+
+ /**
+ * Respond to input keyup event, this is the way to intercept 'escape' key
+ *
+ * @param {jQuery.Event} e Event data
+ * @return {boolean} false
+ */
+ mw.rcfilters.ui.SaveFiltersPopupButtonWidget.prototype.onInputKeyup = function ( e ) {
+ if ( e.which === OO.ui.Keys.ESCAPE ) {
+ this.popup.toggle( false );
+ return false;
+ }
+ };
+
+ /**
+ * Respond to popup ready event
+ */
+ mw.rcfilters.ui.SaveFiltersPopupButtonWidget.prototype.onPopupReady = function () {
+ this.input.focus();
+ };
+
+ /**
+ * Respond to "set as default" checkbox change
+ * @param {boolean} checked State of the checkbox
+ */
+ mw.rcfilters.ui.SaveFiltersPopupButtonWidget.prototype.onSetAsDefaultChange = function ( checked ) {
+ var messageKey = checked ?
+ 'rcfilters-savedqueries-apply-and-setdefault-label' :
+ 'rcfilters-savedqueries-apply-label';
+
+ this.applyButton
+ .setIcon( checked ? 'pushPin' : null )
+ .setLabel( mw.msg( messageKey ) );
+ };
+
+ /**
+ * Respond to cancel button click event
+ */
+ mw.rcfilters.ui.SaveFiltersPopupButtonWidget.prototype.onCancelButtonClick = function () {
+ this.popup.toggle( false );
+ };
+
+ /**
+ * Respond to apply button click event
+ */
+ mw.rcfilters.ui.SaveFiltersPopupButtonWidget.prototype.onApplyButtonClick = function () {
+ this.apply();
+ };
+
+ /**
+ * Apply and add the new quick link
+ */
+ mw.rcfilters.ui.SaveFiltersPopupButtonWidget.prototype.apply = function () {
+ var label = this.input.getValue().trim();
+
+ // This condition is more for sanity-check, since the
+ // apply button should be disabled if the label is empty
+ if ( label ) {
+ this.controller.saveCurrentQuery( label, this.setAsDefaultCheckbox.isSelected() );
+ this.input.setValue( '' );
+ this.setAsDefaultCheckbox.setSelected( false );
+ this.popup.toggle( false );
+
+ this.emit( 'saveCurrent' );
+ }
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SavedLinksListItemWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SavedLinksListItemWidget.js
new file mode 100644
index 00000000..71e3b55c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SavedLinksListItemWidget.js
@@ -0,0 +1,329 @@
+( function ( mw ) {
+ /**
+ * Quick links menu option widget
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.LabelElement
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.TitledElement
+ *
+ * @constructor
+ * @param {mw.rcfilters.dm.SavedQueryItemModel} model View model
+ * @param {Object} [config] Configuration object
+ * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget = function MwRcfiltersUiSavedLinksListWidget( model, config ) {
+ config = config || {};
+
+ this.model = model;
+
+ // Parent
+ mw.rcfilters.ui.SavedLinksListItemWidget.parent.call( this, $.extend( {
+ data: this.model.getID()
+ }, config ) );
+
+ // Mixin constructors
+ OO.ui.mixin.LabelElement.call( this, $.extend( {
+ label: this.model.getLabel()
+ }, config ) );
+ OO.ui.mixin.IconElement.call( this, $.extend( {
+ icon: ''
+ }, config ) );
+ OO.ui.mixin.TitledElement.call( this, $.extend( {
+ title: this.model.getLabel()
+ }, config ) );
+
+ this.edit = false;
+ this.$overlay = config.$overlay || this.$element;
+
+ this.popupButton = new OO.ui.ButtonWidget( {
+ classes: [ 'mw-rcfilters-ui-savedLinksListItemWidget-button' ],
+ icon: 'ellipsis',
+ framed: false
+ } );
+ this.menu = new OO.ui.MenuSelectWidget( {
+ classes: [ 'mw-rcfilters-ui-savedLinksListItemWidget-menu' ],
+ widget: this.popupButton,
+ width: 200,
+ horizontalPosition: 'end',
+ $floatableContainer: this.popupButton.$element,
+ items: [
+ new OO.ui.MenuOptionWidget( {
+ data: 'edit',
+ icon: 'edit',
+ label: mw.msg( 'rcfilters-savedqueries-rename' )
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'delete',
+ icon: 'close',
+ label: mw.msg( 'rcfilters-savedqueries-remove' )
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ data: 'default',
+ icon: 'pushPin',
+ label: mw.msg( 'rcfilters-savedqueries-setdefault' )
+ } )
+ ]
+ } );
+
+ this.editInput = new OO.ui.TextInputWidget( {
+ classes: [ 'mw-rcfilters-ui-savedLinksListItemWidget-input' ]
+ } );
+ this.saveButton = new OO.ui.ButtonWidget( {
+ icon: 'check',
+ flags: [ 'primary', 'progressive' ]
+ } );
+ this.toggleEdit( false );
+
+ // Events
+ this.model.connect( this, { update: 'onModelUpdate' } );
+ this.popupButton.connect( this, { click: 'onPopupButtonClick' } );
+ this.menu.connect( this, {
+ choose: 'onMenuChoose'
+ } );
+ this.saveButton.connect( this, { click: 'save' } );
+ this.editInput.connect( this, {
+ change: 'onInputChange',
+ enter: 'save'
+ } );
+ this.editInput.$input.on( {
+ blur: this.onInputBlur.bind( this ),
+ keyup: this.onInputKeyup.bind( this )
+ } );
+ this.$element.on( { click: this.onClick.bind( this ) } );
+ this.$label.on( { click: this.onClick.bind( this ) } );
+ this.$icon.on( { click: this.onDefaultIconClick.bind( this ) } );
+ // Prevent propagation on mousedown for the save button
+ // so the menu doesn't close
+ this.saveButton.$element.on( { mousedown: function () { return false; } } );
+
+ // Initialize
+ this.toggleDefault( !!this.model.isDefault() );
+ this.$overlay.append( this.menu.$element );
+ this.$element
+ .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget' )
+ .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-query-' + this.model.getID() )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-table' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-row' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-content' )
+ .append(
+ this.$label
+ .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-label' ),
+ this.editInput.$element,
+ this.saveButton.$element
+ ),
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-savedLinksListItemWidget-icon' )
+ .append( this.$icon ),
+ this.popupButton.$element
+ .addClass( 'mw-rcfilters-ui-cell' )
+ )
+ )
+ );
+ };
+
+ /* Initialization */
+ OO.inheritClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.Widget );
+ OO.mixinClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.mixin.LabelElement );
+ OO.mixinClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.mixin.IconElement );
+ OO.mixinClass( mw.rcfilters.ui.SavedLinksListItemWidget, OO.ui.mixin.TitledElement );
+
+ /* Events */
+
+ /**
+ * @event delete
+ *
+ * The delete option was selected for this item
+ */
+
+ /**
+ * @event default
+ * @param {boolean} default Item is default
+ *
+ * The 'make default' option was selected for this item
+ */
+
+ /**
+ * @event edit
+ * @param {string} newLabel New label for the query
+ *
+ * The label has been edited
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to model update event
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onModelUpdate = function () {
+ this.setLabel( this.model.getLabel() );
+ this.toggleDefault( this.model.isDefault() );
+ };
+
+ /**
+ * Respond to click on the element or label
+ *
+ * @fires click
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onClick = function () {
+ if ( !this.editing ) {
+ this.emit( 'click' );
+ }
+ };
+
+ /**
+ * Respond to click on the 'default' icon. Open the submenu where the
+ * default state can be changed.
+ *
+ * @return {boolean} false
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onDefaultIconClick = function () {
+ this.menu.toggle();
+ return false;
+ };
+
+ /**
+ * Respond to popup button click event
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onPopupButtonClick = function () {
+ this.menu.toggle();
+ };
+
+ /**
+ * Respond to menu choose event
+ *
+ * @param {OO.ui.MenuOptionWidget} item Chosen item
+ * @fires delete
+ * @fires default
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onMenuChoose = function ( item ) {
+ var action = item.getData();
+
+ if ( action === 'edit' ) {
+ this.toggleEdit( true );
+ } else if ( action === 'delete' ) {
+ this.emit( 'delete' );
+ } else if ( action === 'default' ) {
+ this.emit( 'default', !this.default );
+ }
+ // Reset selected
+ this.menu.selectItem( null );
+ // Close the menu
+ this.menu.toggle( false );
+ };
+
+ /**
+ * Respond to input keyup event, this is the way to intercept 'escape' key
+ *
+ * @param {jQuery.Event} e Event data
+ * @return {boolean} false
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onInputKeyup = function ( e ) {
+ if ( e.which === OO.ui.Keys.ESCAPE ) {
+ // Return the input to the original label
+ this.editInput.setValue( this.getLabel() );
+ this.toggleEdit( false );
+ return false;
+ }
+ };
+
+ /**
+ * Respond to blur event on the input
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onInputBlur = function () {
+ this.save();
+
+ // Whether the save succeeded or not, the input-blur event
+ // means we need to cancel editing mode
+ this.toggleEdit( false );
+ };
+
+ /**
+ * Respond to input change event
+ *
+ * @param {string} value Input value
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.onInputChange = function ( value ) {
+ value = value.trim();
+
+ this.saveButton.setDisabled( !value );
+ };
+
+ /**
+ * Save the name of the query
+ *
+ * @param {string} [value] The value to save
+ * @fires edit
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.save = function () {
+ var value = this.editInput.getValue().trim();
+
+ if ( value ) {
+ this.emit( 'edit', value );
+ this.toggleEdit( false );
+ }
+ };
+
+ /**
+ * Toggle edit mode on this widget
+ *
+ * @param {boolean} isEdit Widget is in edit mode
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.toggleEdit = function ( isEdit ) {
+ isEdit = isEdit === undefined ? !this.editing : isEdit;
+
+ if ( this.editing !== isEdit ) {
+ this.$element.toggleClass( 'mw-rcfilters-ui-savedLinksListItemWidget-edit', isEdit );
+ this.editInput.setValue( this.getLabel() );
+
+ this.editInput.toggle( isEdit );
+ this.$label.toggleClass( 'oo-ui-element-hidden', isEdit );
+ this.$icon.toggleClass( 'oo-ui-element-hidden', isEdit );
+ this.popupButton.toggle( !isEdit );
+ this.saveButton.toggle( isEdit );
+
+ if ( isEdit ) {
+ this.editInput.$input.focus();
+ }
+ this.editing = isEdit;
+ }
+ };
+
+ /**
+ * Toggle default this widget
+ *
+ * @param {boolean} isDefault This item is default
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.toggleDefault = function ( isDefault ) {
+ isDefault = isDefault === undefined ? !this.default : isDefault;
+
+ if ( this.default !== isDefault ) {
+ this.default = isDefault;
+ this.setIcon( this.default ? 'pushPin' : '' );
+ this.menu.getItemFromData( 'default' ).setLabel(
+ this.default ?
+ mw.msg( 'rcfilters-savedqueries-unsetdefault' ) :
+ mw.msg( 'rcfilters-savedqueries-setdefault' )
+ );
+ }
+ };
+
+ /**
+ * Get item ID
+ *
+ * @return {string} Query identifier
+ */
+ mw.rcfilters.ui.SavedLinksListItemWidget.prototype.getID = function () {
+ return this.model.getID();
+ };
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SavedLinksListWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SavedLinksListWidget.js
new file mode 100644
index 00000000..7eda90a8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.SavedLinksListWidget.js
@@ -0,0 +1,156 @@
+( function ( mw ) {
+ /**
+ * Quick links widget
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller Controller
+ * @param {mw.rcfilters.dm.SavedQueriesModel} model View model
+ * @param {Object} [config] Configuration object
+ * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
+ */
+ mw.rcfilters.ui.SavedLinksListWidget = function MwRcfiltersUiSavedLinksListWidget( controller, model, config ) {
+ var $labelNoEntries = $( '<div>' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-savedLinksListWidget-placeholder-title' )
+ .text( mw.msg( 'rcfilters-quickfilters-placeholder-title' ) ),
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-savedLinksListWidget-placeholder-description' )
+ .text( mw.msg( 'rcfilters-quickfilters-placeholder-description' ) )
+ );
+
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.SavedLinksListWidget.parent.call( this, config );
+
+ this.controller = controller;
+ this.model = model;
+ this.$overlay = config.$overlay || this.$element;
+
+ this.placeholderItem = new OO.ui.DecoratedOptionWidget( {
+ classes: [ 'mw-rcfilters-ui-savedLinksListWidget-placeholder' ],
+ label: $labelNoEntries,
+ icon: 'unClip'
+ } );
+ // The only reason we're using "ButtonGroupWidget" here is that
+ // straight-out "GroupWidget" is a mixin and cannot be initialized
+ // on its own, so we need something to be its widget.
+ this.menu = new OO.ui.ButtonGroupWidget( {
+ classes: [ 'mw-rcfilters-ui-savedLinksListWidget-menu' ],
+ items: [ this.placeholderItem ]
+ } );
+ this.button = new OO.ui.PopupButtonWidget( {
+ classes: [ 'mw-rcfilters-ui-savedLinksListWidget-button' ],
+ label: mw.msg( 'rcfilters-quickfilters' ),
+ icon: 'unClip',
+ indicator: 'down',
+ $overlay: this.$overlay,
+ popup: {
+ width: 300,
+ anchor: false,
+ align: 'backwards',
+ $autoCloseIgnore: this.$overlay,
+ $content: this.menu.$element
+ }
+ } );
+
+ this.menu.aggregate( {
+ click: 'menuItemClick',
+ 'delete': 'menuItemDelete',
+ 'default': 'menuItemDefault',
+ edit: 'menuItemEdit'
+ } );
+
+ // Events
+ this.model.connect( this, {
+ add: 'onModelAddItem',
+ remove: 'onModelRemoveItem'
+ } );
+ this.menu.connect( this, {
+ menuItemClick: 'onMenuItemClick',
+ menuItemDelete: 'onMenuItemRemove',
+ menuItemDefault: 'onMenuItemDefault',
+ menuItemEdit: 'onMenuItemEdit'
+ } );
+
+ this.placeholderItem.toggle( this.model.isEmpty() );
+ // Initialize
+ this.$element
+ .addClass( 'mw-rcfilters-ui-savedLinksListWidget' )
+ .append( this.button.$element );
+ };
+
+ /* Initialization */
+ OO.inheritClass( mw.rcfilters.ui.SavedLinksListWidget, OO.ui.Widget );
+
+ /* Methods */
+
+ /**
+ * Respond to menu item click event
+ *
+ * @param {mw.rcfilters.ui.SavedLinksListItemWidget} item Menu item
+ */
+ mw.rcfilters.ui.SavedLinksListWidget.prototype.onMenuItemClick = function ( item ) {
+ this.controller.applySavedQuery( item.getID() );
+ this.button.popup.toggle( false );
+ };
+
+ /**
+ * Respond to menu item remove event
+ *
+ * @param {mw.rcfilters.ui.SavedLinksListItemWidget} item Menu item
+ */
+ mw.rcfilters.ui.SavedLinksListWidget.prototype.onMenuItemRemove = function ( item ) {
+ this.controller.removeSavedQuery( item.getID() );
+ };
+
+ /**
+ * Respond to menu item default event
+ *
+ * @param {mw.rcfilters.ui.SavedLinksListItemWidget} item Menu item
+ * @param {boolean} isDefault Item is default
+ */
+ mw.rcfilters.ui.SavedLinksListWidget.prototype.onMenuItemDefault = function ( item, isDefault ) {
+ this.controller.setDefaultSavedQuery( isDefault ? item.getID() : null );
+ };
+
+ /**
+ * Respond to menu item edit event
+ *
+ * @param {mw.rcfilters.ui.SavedLinksListItemWidget} item Menu item
+ * @param {string} newLabel New label
+ */
+ mw.rcfilters.ui.SavedLinksListWidget.prototype.onMenuItemEdit = function ( item, newLabel ) {
+ this.controller.renameSavedQuery( item.getID(), newLabel );
+ };
+
+ /**
+ * Respond to menu add item event
+ *
+ * @param {mw.rcfilters.ui.SavedLinksListItemWidget} item Menu item
+ */
+ mw.rcfilters.ui.SavedLinksListWidget.prototype.onModelAddItem = function ( item ) {
+ if ( this.menu.getItemFromData( item.getID() ) ) {
+ return;
+ }
+
+ this.menu.addItems( [
+ new mw.rcfilters.ui.SavedLinksListItemWidget( item, { $overlay: this.$overlay } )
+ ] );
+ this.placeholderItem.toggle( this.model.isEmpty() );
+ };
+
+ /**
+ * Respond to menu remove item event
+ *
+ * @param {mw.rcfilters.ui.SavedLinksListItemWidget} item Menu item
+ */
+ mw.rcfilters.ui.SavedLinksListWidget.prototype.onModelRemoveItem = function ( item ) {
+ this.menu.removeItems( [ this.menu.getItemFromData( item.getID() ) ] );
+ this.placeholderItem.toggle( this.model.isEmpty() );
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.TagItemWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.TagItemWidget.js
new file mode 100644
index 00000000..81889b26
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.TagItemWidget.js
@@ -0,0 +1,200 @@
+( function ( mw, $ ) {
+ /**
+ * Extend OOUI's TagItemWidget to also display a popup on hover.
+ *
+ * @class
+ * @extends OO.ui.TagItemWidget
+ * @mixins OO.ui.mixin.PopupElement
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller
+ * @param {mw.rcfilters.dm.FilterItem} model Item model
+ * @param {Object} config Configuration object
+ * @cfg {jQuery} [$overlay] A jQuery object serving as overlay for popups
+ */
+ mw.rcfilters.ui.TagItemWidget = function MwRcfiltersUiTagItemWidget( controller, model, config ) {
+ // Configuration initialization
+ config = config || {};
+
+ this.controller = controller;
+ this.model = model;
+ this.selected = false;
+
+ mw.rcfilters.ui.TagItemWidget.parent.call( this, $.extend( {
+ data: this.model.getName(),
+ label: $( '<div>' ).html( this.model.getPrefixedLabel() ).contents()
+ }, config ) );
+
+ this.$overlay = config.$overlay || this.$element;
+ this.popupLabel = new OO.ui.LabelWidget();
+
+ // Mixin constructors
+ OO.ui.mixin.PopupElement.call( this, $.extend( {
+ popup: {
+ padded: false,
+ align: 'center',
+ position: 'above',
+ $content: $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-tagItemWidget-popup-content' )
+ .append( this.popupLabel.$element ),
+ $floatableContainer: this.$element,
+ classes: [ 'mw-rcfilters-ui-tagItemWidget-popup' ]
+ }
+ }, config ) );
+
+ this.popupTimeoutShow = null;
+ this.popupTimeoutHide = null;
+
+ this.$highlight = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-tagItemWidget-highlight' );
+
+ // Add title attribute with the item label to 'x' button
+ this.closeButton.setTitle( mw.msg( 'rcfilters-tag-remove', this.model.getLabel() ) );
+
+ // Events
+ this.model.connect( this, { update: 'onModelUpdate' } );
+
+ // Initialization
+ this.$overlay.append( this.popup.$element );
+ this.$element
+ .addClass( 'mw-rcfilters-ui-tagItemWidget' )
+ .prepend( this.$highlight )
+ .attr( 'aria-haspopup', 'true' )
+ .on( 'mouseenter', this.onMouseEnter.bind( this ) )
+ .on( 'mouseleave', this.onMouseLeave.bind( this ) );
+
+ this.setCurrentMuteState();
+ this.setHighlightColor();
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.TagItemWidget, OO.ui.TagItemWidget );
+ OO.mixinClass( mw.rcfilters.ui.TagItemWidget, OO.ui.mixin.PopupElement );
+
+ /* Methods */
+
+ /**
+ * Respond to model update event
+ */
+ mw.rcfilters.ui.TagItemWidget.prototype.onModelUpdate = function () {
+ this.setCurrentMuteState();
+
+ // Update label if needed
+ this.setLabel( $( '<div>' ).html( this.model.getPrefixedLabel() ).contents() );
+
+ this.setHighlightColor();
+ };
+
+ mw.rcfilters.ui.TagItemWidget.prototype.setHighlightColor = function () {
+ var selectedColor = this.model.isHighlightEnabled() ? this.model.getHighlightColor() : null;
+
+ this.$highlight
+ .attr( 'data-color', selectedColor )
+ .toggleClass(
+ 'mw-rcfilters-ui-tagItemWidget-highlight-highlighted',
+ !!selectedColor
+ );
+ };
+
+ /**
+ * Set the current mute state for this item
+ */
+ mw.rcfilters.ui.TagItemWidget.prototype.setCurrentMuteState = function () {};
+
+ /**
+ * Respond to mouse enter event
+ */
+ mw.rcfilters.ui.TagItemWidget.prototype.onMouseEnter = function () {
+ var labelText = this.model.getStateMessage();
+
+ if ( labelText ) {
+ this.popupLabel.setLabel( labelText );
+
+ // Set timeout for the popup to show
+ this.popupTimeoutShow = setTimeout( function () {
+ this.popup.toggle( true );
+ }.bind( this ), 500 );
+
+ // Cancel the hide timeout
+ clearTimeout( this.popupTimeoutHide );
+ this.popupTimeoutHide = null;
+ }
+ };
+
+ /**
+ * Respond to mouse leave event
+ */
+ mw.rcfilters.ui.TagItemWidget.prototype.onMouseLeave = function () {
+ this.popupTimeoutHide = setTimeout( function () {
+ this.popup.toggle( false );
+ }.bind( this ), 250 );
+
+ // Clear the show timeout
+ clearTimeout( this.popupTimeoutShow );
+ this.popupTimeoutShow = null;
+ };
+
+ /**
+ * Set selected state on this widget
+ *
+ * @param {boolean} [isSelected] Widget is selected
+ */
+ mw.rcfilters.ui.TagItemWidget.prototype.toggleSelected = function ( isSelected ) {
+ isSelected = isSelected !== undefined ? isSelected : !this.selected;
+
+ if ( this.selected !== isSelected ) {
+ this.selected = isSelected;
+
+ this.$element.toggleClass( 'mw-rcfilters-ui-tagItemWidget-selected', this.selected );
+ }
+ };
+
+ /**
+ * Get the selected state of this widget
+ *
+ * @return {boolean} Tag is selected
+ */
+ mw.rcfilters.ui.TagItemWidget.prototype.isSelected = function () {
+ return this.selected;
+ };
+
+ /**
+ * Get item name
+ *
+ * @return {string} Filter name
+ */
+ mw.rcfilters.ui.TagItemWidget.prototype.getName = function () {
+ return this.model.getName();
+ };
+
+ /**
+ * Get item model
+ *
+ * @return {string} Filter model
+ */
+ mw.rcfilters.ui.TagItemWidget.prototype.getModel = function () {
+ return this.model;
+ };
+
+ /**
+ * Get item view
+ *
+ * @return {string} Filter view
+ */
+ mw.rcfilters.ui.TagItemWidget.prototype.getView = function () {
+ return this.model.getGroupModel().getView();
+ };
+
+ /**
+ * Remove and destroy external elements of this widget
+ */
+ mw.rcfilters.ui.TagItemWidget.prototype.destroy = function () {
+ // Destroy the popup
+ this.popup.$element.detach();
+
+ // Disconnect events
+ this.model.disconnect( this );
+ this.closeButton.disconnect( this );
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ValuePickerWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ValuePickerWidget.js
new file mode 100644
index 00000000..ac0e50d5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ValuePickerWidget.js
@@ -0,0 +1,110 @@
+( function ( mw ) {
+ /**
+ * Widget defining the behavior used to choose from a set of values
+ * in a single_value group
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.LabelElement
+ *
+ * @constructor
+ * @param {mw.rcfilters.dm.FilterGroup} model Group model
+ * @param {Object} [config] Configuration object
+ * @cfg {Function} [itemFilter] A filter function for the items from the
+ * model. If not given, all items will be included. The function must
+ * handle item models and return a boolean whether the item is included
+ * or not. Example: function ( itemModel ) { return itemModel.isSelected(); }
+ */
+ mw.rcfilters.ui.ValuePickerWidget = function MwRcfiltersUiValuePickerWidget( model, config ) {
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.ValuePickerWidget.parent.call( this, config );
+ // Mixin constructors
+ OO.ui.mixin.LabelElement.call( this, config );
+
+ this.model = model;
+ this.itemFilter = config.itemFilter || function () { return true; };
+
+ // Build the selection from the item models
+ this.selectWidget = new OO.ui.ButtonSelectWidget();
+ this.initializeSelectWidget();
+
+ // Events
+ this.model.connect( this, { update: 'onModelUpdate' } );
+ this.selectWidget.connect( this, { choose: 'onSelectWidgetChoose' } );
+
+ // Initialize
+ this.$element
+ .addClass( 'mw-rcfilters-ui-valuePickerWidget' )
+ .append(
+ this.$label
+ .addClass( 'mw-rcfilters-ui-valuePickerWidget-title' ),
+ this.selectWidget.$element
+ );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.ValuePickerWidget, OO.ui.Widget );
+ OO.mixinClass( mw.rcfilters.ui.ValuePickerWidget, OO.ui.mixin.LabelElement );
+
+ /* Events */
+
+ /**
+ * @event choose
+ * @param {string} name Item name
+ *
+ * An item has been chosen
+ */
+
+ /* Methods */
+
+ /**
+ * Respond to model update event
+ */
+ mw.rcfilters.ui.ValuePickerWidget.prototype.onModelUpdate = function () {
+ this.selectCurrentModelItem();
+ };
+
+ /**
+ * Respond to select widget choose event
+ *
+ * @param {OO.ui.ButtonOptionWidget} chosenItem Chosen item
+ * @fires choose
+ */
+ mw.rcfilters.ui.ValuePickerWidget.prototype.onSelectWidgetChoose = function ( chosenItem ) {
+ this.emit( 'choose', chosenItem.getData() );
+ };
+
+ /**
+ * Initialize the select widget
+ */
+ mw.rcfilters.ui.ValuePickerWidget.prototype.initializeSelectWidget = function () {
+ var items = this.model.getItems()
+ .filter( this.itemFilter )
+ .map( function ( filterItem ) {
+ return new OO.ui.ButtonOptionWidget( {
+ data: filterItem.getName(),
+ label: filterItem.getLabel()
+ } );
+ } );
+
+ this.selectWidget.clearItems();
+ this.selectWidget.addItems( items );
+
+ this.selectCurrentModelItem();
+ };
+
+ /**
+ * Select the current item that corresponds with the model item
+ * that is currently selected
+ */
+ mw.rcfilters.ui.ValuePickerWidget.prototype.selectCurrentModelItem = function () {
+ var selectedItem = this.model.getSelectedItems()[ 0 ];
+
+ if ( selectedItem ) {
+ this.selectWidget.selectItemByData( selectedItem.getName() );
+ }
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ViewSwitchWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ViewSwitchWidget.js
new file mode 100644
index 00000000..fef85672
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.ViewSwitchWidget.js
@@ -0,0 +1,76 @@
+( function ( mw ) {
+ /**
+ * A widget for the footer for the default view, allowing to switch views
+ *
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller Controller
+ * @param {mw.rcfilters.dm.FiltersViewModel} model View model
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.ViewSwitchWidget = function MwRcfiltersUiViewSwitchWidget( controller, model, config ) {
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.ViewSwitchWidget.parent.call( this, config );
+
+ this.controller = controller;
+ this.model = model;
+
+ this.buttons = new OO.ui.ButtonGroupWidget( {
+ items: [
+ new OO.ui.ButtonWidget( {
+ data: 'namespaces',
+ icon: 'article',
+ label: mw.msg( 'namespaces' )
+ } ),
+ new OO.ui.ButtonWidget( {
+ data: 'tags',
+ icon: 'tag',
+ label: mw.msg( 'rcfilters-view-tags' )
+ } )
+ ]
+ } );
+
+ // Events
+ this.model.connect( this, { update: 'onModelUpdate' } );
+ this.buttons.aggregate( { click: 'buttonClick' } );
+ this.buttons.connect( this, { buttonClick: 'onButtonClick' } );
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-viewSwitchWidget' )
+ .append(
+ new OO.ui.LabelWidget( {
+ label: mw.msg( 'rcfilters-advancedfilters' )
+ } ).$element,
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-viewSwitchWidget-buttons' )
+ .append( this.buttons.$element )
+ );
+ };
+
+ /* Initialize */
+
+ OO.inheritClass( mw.rcfilters.ui.ViewSwitchWidget, OO.ui.Widget );
+
+ /**
+ * Respond to model update event
+ */
+ mw.rcfilters.ui.ViewSwitchWidget.prototype.onModelUpdate = function () {
+ var currentView = this.model.getCurrentView();
+
+ this.buttons.getItems().forEach( function ( buttonWidget ) {
+ buttonWidget.setActive( buttonWidget.getData() === currentView );
+ } );
+ };
+
+ /**
+ * Respond to button switch click
+ *
+ * @param {OO.ui.ButtonWidget} buttonWidget Clicked button
+ */
+ mw.rcfilters.ui.ViewSwitchWidget.prototype.onButtonClick = function ( buttonWidget ) {
+ this.controller.switchView( buttonWidget.getData() );
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.WatchlistTopSectionWidget.js b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.WatchlistTopSectionWidget.js
new file mode 100644
index 00000000..7d78565c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.WatchlistTopSectionWidget.js
@@ -0,0 +1,82 @@
+( function ( mw ) {
+ /**
+ * Top section (between page title and filters) on Special:Watchlist
+ *
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {mw.rcfilters.Controller} controller
+ * @param {mw.rcfilters.dm.ChangesListViewModel} changesListModel
+ * @param {mw.rcfilters.ui.SavedLinksListWidget} savedLinksListWidget
+ * @param {jQuery} $watchlistDetails Content of the 'details' section that includes watched pages count
+ * @param {Object} [config] Configuration object
+ */
+ mw.rcfilters.ui.WatchlistTopSectionWidget = function MwRcfiltersUiWatchlistTopSectionWidget(
+ controller, changesListModel, savedLinksListWidget, $watchlistDetails, config
+ ) {
+ var editWatchlistButton,
+ markSeenButton,
+ $topTable,
+ $bottomTable,
+ $separator;
+ config = config || {};
+
+ // Parent
+ mw.rcfilters.ui.WatchlistTopSectionWidget.parent.call( this, config );
+
+ editWatchlistButton = new OO.ui.ButtonWidget( {
+ label: mw.msg( 'rcfilters-watchlist-edit-watchlist-button' ),
+ icon: 'edit',
+ href: mw.config.get( 'wgStructuredChangeFiltersEditWatchlistUrl' )
+ } );
+ markSeenButton = new mw.rcfilters.ui.MarkSeenButtonWidget( controller, changesListModel );
+
+ $topTable = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-table' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-row' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-watchlistTopSectionWidget-watchlistDetails' )
+ .append( $watchlistDetails )
+ )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-watchlistTopSectionWidget-editWatchlistButton' )
+ .append( editWatchlistButton.$element )
+ )
+ );
+
+ $bottomTable = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-table' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-row' )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .append( markSeenButton.$element )
+ )
+ .append(
+ $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-cell' )
+ .addClass( 'mw-rcfilters-ui-watchlistTopSectionWidget-savedLinks' )
+ .append( savedLinksListWidget.$element )
+ )
+ );
+
+ $separator = $( '<div>' )
+ .addClass( 'mw-rcfilters-ui-watchlistTopSectionWidget-separator' );
+
+ this.$element
+ .addClass( 'mw-rcfilters-ui-watchlistTopSectionWidget' )
+ .append( $topTable, $separator, $bottomTable );
+ };
+
+ /* Initialization */
+
+ OO.inheritClass( mw.rcfilters.ui.WatchlistTopSectionWidget, OO.ui.Widget );
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.router/index.js b/www/wiki/resources/src/mediawiki.router/index.js
new file mode 100644
index 00000000..737ef5f6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.router/index.js
@@ -0,0 +1,4 @@
+( function () {
+ var Router = require( 'oojs-router' );
+ module.exports = new Router();
+}() );
diff --git a/www/wiki/resources/src/mediawiki.skinning/content.css b/www/wiki/resources/src/mediawiki.skinning/content.css
new file mode 100644
index 00000000..5ded184f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/content.css
@@ -0,0 +1,265 @@
+/**
+ * MediaWiki style sheet for general styles on complex content
+ *
+ * Styles for complex things which are a standard part of page content
+ * (ie: the CSS classing built into the system), like the TOC.
+ */
+
+/* Table of Contents */
+#toc,
+.toc,
+.mw-warning,
+.toccolours {
+ border: 1px solid #a2a9b1;
+ background-color: #f8f9fa;
+ padding: 5px;
+ font-size: 95%;
+}
+
+/**
+ * We want to display the ToC element with intrinsic width in block mode. The fit-content
+ * value for width is however not supported by large groups of browsers.
+ *
+ * We use display:table. Even though it should only contain other table-* display
+ * elements, there are no known problems with using this.
+ *
+ * Because IE < 8 and other older browsers don't support display:table, we fallback to
+ * using inline-block mode, which features at least intrinsic width, but won't clear preceding
+ * inline elements. In practice inline elements surrounding the TOC are uncommon enough that
+ * this is an acceptable sacrifice.
+ */
+#toc,
+.toc {
+ display: inline-block;
+ display: table;
+
+ /* IE7 and earlier */
+ zoom: 1;
+ *display: inline; /* stylelint-disable declaration-block-no-duplicate-properties */
+
+ padding: 7px;
+}
+
+/* CSS for backwards-compatibility with cached page renders and creative uses in wikitext */
+table#toc,
+table.toc {
+ border-collapse: collapse;
+}
+
+/* Remove additional paddings inside table-cells that are not present in <div>s */
+table#toc td,
+table.toc td {
+ padding: 0;
+}
+
+#toc h2,
+.toc h2 {
+ display: inline;
+ border: 0;
+ padding: 0;
+ font-size: 100%;
+ font-weight: bold;
+}
+
+#toc #toctitle,
+.toc #toctitle,
+#toc .toctitle,
+.toc .toctitle {
+ text-align: center;
+}
+
+#toc ul,
+.toc ul {
+ list-style-type: none;
+ list-style-image: none;
+ margin-left: 0;
+ padding: 0;
+ text-align: left;
+}
+
+#toc ul ul,
+.toc ul ul {
+ margin: 0 0 0 2em;
+}
+
+/* Separate columns for tocnumber and toctext */
+/* Ignored by IE7 and lower */
+.tocnumber,
+.toctext {
+ display: table-cell;
+ /*
+ Text decorations are not propagated to the contents of inline blocks and inline tables,
+ according to <https://www.w3.org/TR/css-text-decor-3/#line-decoration>, and 'display: table-cell'
+ generates an inline table when used without any parent table-rows and tables.
+ */
+ text-decoration: inherit;
+}
+
+/* Space between the columns for tocnumber and toctext */
+.tocnumber {
+ padding-left: 0;
+ padding-right: 0.5em;
+ color: #222;
+}
+/* @noflip */
+.mw-content-ltr .tocnumber {
+ padding-left: 0;
+ padding-right: 0.5em;
+}
+
+/* @noflip */
+.mw-content-rtl .tocnumber {
+ padding-left: 0.5em;
+ padding-right: 0;
+}
+
+/* Warning */
+.mw-warning {
+ margin-left: 50px;
+ margin-right: 50px;
+ text-align: center;
+}
+
+/* Images */
+/* @noflip */
+div.floatright,
+table.floatright {
+ margin: 0 0 0.5em 0.5em;
+}
+
+div.floatright p {
+ font-style: italic;
+}
+
+/* @noflip */
+div.floatleft,
+table.floatleft {
+ margin: 0 0.5em 0.5em 0;
+}
+
+div.floatleft p {
+ font-style: italic;
+}
+
+/* Thumbnails */
+div.thumb {
+ margin-bottom: 0.5em;
+ width: auto;
+ background-color: transparent;
+}
+
+div.thumbinner {
+ border: 1px solid #c8ccd1;
+ padding: 3px;
+ background-color: #f8f9fa;
+ font-size: 94%;
+ text-align: center;
+ /* new block formatting context,
+ * to clear background from floating content */
+ overflow: hidden;
+}
+
+html .thumbimage {
+ background-color: #fff;
+ border: 1px solid #c8ccd1;
+}
+
+html .thumbcaption {
+ border: 0;
+ line-height: 1.4em;
+ padding: 3px;
+ font-size: 94%;
+ /* Default styles when there's no .mw-content-ltr or .mw-content-rtl, overridden below */
+ text-align: left;
+}
+
+div.magnify {
+ /* Default styles when there's no .mw-content-ltr or .mw-content-rtl, overridden below */
+ float: right;
+ margin-left: 3px;
+}
+
+div.magnify a {
+ display: block;
+ /* Hide the text… */
+ text-indent: 15px;
+ white-space: nowrap;
+ overflow: hidden;
+ /* …and replace it with the image */
+ width: 15px;
+ height: 11px;
+ /* Default styles when there's no .mw-content-ltr or .mw-content-rtl, overridden below */
+
+ /* Use same SVG support hack as mediawiki.legacy's shared.css */
+ background-image: url( images/magnify-clip-ltr.png );
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/magnify-clip-ltr.svg );
+ /* Don't annoy people who copy-paste everything too much */
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+img.thumbborder {
+ border: 1px solid #eaecf0;
+}
+
+/* Directionality-specific styles for thumbnails - their positioning depends on content language */
+
+/* @noflip */
+.mw-content-ltr .thumbcaption {
+ text-align: left;
+}
+
+/* @noflip */
+.mw-content-ltr .magnify {
+ float: right;
+ margin-left: 3px;
+ margin-right: 0;
+}
+
+/* @noflip */
+.mw-content-ltr div.magnify a {
+ /* Use same SVG support hack as mediawiki.legacy's shared.css */
+ background-image: url( images/magnify-clip-ltr.png );
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/magnify-clip-ltr.svg );
+}
+
+/* @noflip */
+.mw-content-rtl .thumbcaption {
+ text-align: right;
+}
+
+/* @noflip */
+.mw-content-rtl .magnify {
+ float: left;
+ margin-left: 0;
+ margin-right: 3px;
+}
+
+/* @noflip */
+.mw-content-rtl div.magnify a {
+ /* Use same SVG support hack as mediawiki.legacy's shared.css */
+ background-image: url( images/magnify-clip-rtl.png );
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/magnify-clip-rtl.svg );
+}
+
+/* @noflip */
+div.tright {
+ margin: 0.5em 0 1.3em 1.4em;
+}
+
+/* @noflip */
+div.tleft {
+ margin: 0.5em 1.4em 1.3em 0;
+}
+
+/* Hide elements that are marked as "empty" according to legacy Tidy rules,
+ * except if a client script removes the mw-hide-empty-elt class from the body
+ */
+body.mw-hide-empty-elt .mw-empty-elt {
+ display: none;
+}
diff --git a/www/wiki/resources/src/mediawiki.skinning/content.externallinks.css b/www/wiki/resources/src/mediawiki.skinning/content.externallinks.css
new file mode 100644
index 00000000..cd674ef9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/content.externallinks.css
@@ -0,0 +1,103 @@
+/*!
+ * Icons and colors for external links.
+ */
+
+/* T68091 is blocking is from converting this file to LESS
+ * and using the .background-image-svg mixin. */
+
+/* SVG support using a transparent gradient to guarantee cross-browser
+ * compatibility ( browsers able to understand gradient syntax support also SVG ).
+ * http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique */
+
+.mw-body-content a.external,
+.link-https {
+ background: url( images/external-ltr.png ) center right no-repeat;
+ /* @embed */
+ background-image: -webkit-linear-gradient( transparent, transparent ), url( images/external-ltr.svg );
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/external-ltr.svg );
+ padding-right: 15px;
+}
+
+.mw-body-content a.external[href^='mailto:'],
+.link-mailto {
+ background: url( images/mail.png ) center right no-repeat;
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/mail.svg );
+ padding-right: 15px;
+}
+
+.mw-body-content a.external[href^='ftp://'],
+.link-ftp {
+ background: url( images/ftp-ltr.png ) center right no-repeat;
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/ftp-ltr.svg );
+ padding-right: 15px;
+}
+
+.mw-body-content a.external[href^='irc://'],
+.mw-body-content a.external[href^='ircs://'],
+.link-irc {
+ background: url( images/chat-ltr.png ) center right no-repeat;
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/chat-ltr.svg );
+ padding-right: 15px;
+}
+
+.mw-body-content a.external[href$='.ogg'],
+.mw-body-content a.external[href$='.OGG'],
+.mw-body-content a.external[href$='.mid'],
+.mw-body-content a.external[href$='.MID'],
+.mw-body-content a.external[href$='.midi'],
+.mw-body-content a.external[href$='.MIDI'],
+.mw-body-content a.external[href$='.mp3'],
+.mw-body-content a.external[href$='.MP3'],
+.mw-body-content a.external[href$='.wav'],
+.mw-body-content a.external[href$='.WAV'],
+.mw-body-content a.external[href$='.wma'],
+.mw-body-content a.external[href$='.WMA'],
+.link-audio {
+ background: url( images/audio-ltr.png ) center right no-repeat;
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/audio-ltr.svg );
+ padding-right: 15px;
+}
+
+.mw-body-content a.external[href$='.ogm'],
+.mw-body-content a.external[href$='.OGM'],
+.mw-body-content a.external[href$='.avi'],
+.mw-body-content a.external[href$='.AVI'],
+.mw-body-content a.external[href$='.mpeg'],
+.mw-body-content a.external[href$='.MPEG'],
+.mw-body-content a.external[href$='.mpg'],
+.mw-body-content a.external[href$='.MPG'],
+.link-video {
+ background: url( images/video.png ) center right no-repeat;
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/video.svg );
+ padding-right: 15px;
+}
+
+.mw-body-content a.external[href$='.pdf'],
+.mw-body-content a.external[href$='.PDF'],
+.mw-body-content a.external[href*='.pdf#'],
+.mw-body-content a.external[href*='.PDF#'],
+.mw-body-content a.external[href*='.pdf?'],
+.mw-body-content a.external[href*='.PDF?'],
+.link-document {
+ background: url( images/document-ltr.png ) center right no-repeat;
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/document-ltr.svg );
+ padding-right: 15px;
+}
+
+/* Interwiki styling */
+.mw-body-content a.extiw,
+.mw-body-content a.extiw:active {
+ color: #36b;
+}
+
+/* External link color */
+.mw-body-content a.external {
+ color: #36b;
+}
diff --git a/www/wiki/resources/src/mediawiki.skinning/content.parsoid.less b/www/wiki/resources/src/mediawiki.skinning/content.parsoid.less
new file mode 100644
index 00000000..654b6555
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/content.parsoid.less
@@ -0,0 +1,228 @@
+/**
+ * Style Parsoid HTML+RDFa output consistent with wikitext from PHP parser.
+ */
+
+/*
+ * Auto-numbered external links
+ * Parsoid renders those as link without content, and lets CSS do the
+ * counting. This way the counting style can be customized, and counts update
+ * automatically when content is modified.
+ */
+.mw-parser-output {
+ counter-reset: mw-numbered-ext-link;
+}
+
+.mw-parser-output a[rel~='mw:ExtLink']:empty:after {
+ content: '[' counter( mw-numbered-ext-link ) ']';
+ counter-increment: mw-numbered-ext-link;
+}
+
+/**
+ * References
+ *
+ * Parser and Extension:Cite output reference numbers for <sup>[1]</sup> for <ref> tags.
+ *
+ * Markup:
+ * Cake is good<sup>[2]</sup>
+ * The cake is a lie<span class="reference">[1]</span>
+ *
+ * Styleguide 1.1.
+ */
+span.reference {
+ font-size: 80%;
+ line-height: 1;
+ vertical-align: super;
+ unicode-bidi: -moz-isolate;
+ unicode-bidi: isolate;
+}
+
+sup,
+sub {
+ line-height: 1;
+}
+
+/**
+ * Block media items
+ */
+figure[typeof*='mw:Image'],
+figure[typeof*='mw:Video'],
+figure[typeof*='mw:Audio'] {
+ margin: 0;
+
+ a {
+ border: 0;
+ }
+
+ &.mw-halign-right {
+ /* @noflip */
+ margin: 0.5em 0 1.3em 1.4em;
+ /* @noflip */
+ clear: right;
+ /* @noflip */
+ float: right;
+ }
+
+ &.mw-halign-left {
+ /* @noflip */
+ margin: 0.5em 1.4em 1.3em 0;
+ /* @noflip */
+ clear: left;
+ /* @noflip */
+ float: left;
+ }
+
+ &.mw-halign-none {
+ margin: 0;
+ clear: none;
+ float: none;
+ }
+
+ &.mw-halign-center {
+ margin: 0 auto 0.5em auto;
+ display: table;
+ border-collapse: collapse;
+ clear: none;
+ float: none;
+ }
+
+ /* Hide the caption for frameless and plain floated images */
+ > figcaption {
+ display: none;
+ }
+}
+
+figure[typeof~='mw:Image/Thumb'],
+figure[typeof~='mw:Video/Thumb'],
+figure[typeof~='mw:Audio/Thumb'],
+figure[typeof~='mw:Image/Frame'],
+figure[typeof~='mw:Video/Frame'],
+figure[typeof~='mw:Audio/Frame'] {
+ display: table;
+ text-align: center;
+ border: 1px solid #c8ccd1;
+ border-collapse: separate;
+ border-spacing: 3px;
+ background-color: #f8f9fa;
+ width: 1px; // From https://stackoverflow.com/a/6536025
+
+ // Avoid !important
+ &.mw-halign-center {
+ border-collapse: separate;
+ }
+
+ // Default to right alignment. This is needed since Parsoid only specifies the
+ // alignment class when the alignment is explicitly set.
+ margin: 0.5em 0 1.3em 1.4em;
+ clear: right;
+ float: right;
+
+ > *:first-child {
+ > img,
+ > video {
+ border: 1px solid #c8ccd1;
+ background: #fff;
+ }
+ }
+
+ > figcaption {
+ display: block;
+
+ /* In mw-core the font-size is duplicated, 94% in thumbiner
+ * and again 94% in thumbcaption. 88.4% for font size of the
+ * caption results in the same behavior. */
+ font-size: 88.4%;
+ line-height: 1.4em;
+ text-align: left;
+
+ /* taken from .thumbcaption, plus .thumbinner */
+ padding: 3px;
+ }
+}
+
+figure[typeof*='mw:Image/Thumb'],
+figure[typeof*='mw:Video/Thumb'],
+figure[typeof*='mw:Audio/Thumb'] {
+ > a:after {
+ content: '';
+ width: 15px;
+ height: 11px;
+ margin: 3px;
+ margin-bottom: 0;
+
+ .mw-content-ltr & {
+ /* @noflip */
+ float: right;
+ /* @noflip */
+ background-image: url( images/magnify-clip-ltr.png );
+ /* @noflip */
+ background-image: linear-gradient( transparent, transparent ), url( images/magnify-clip-ltr.svg );
+ }
+
+ .mw-content-rtl & {
+ /* @noflip */
+ float: left;
+ /* @noflip */
+ background-image: url( images/magnify-clip-rtl.png );
+ /* @noflip */
+ background-image: linear-gradient( transparent, transparent ), url( images/magnify-clip-rtl.svg );
+ }
+ }
+}
+
+/* Same as img.thumbborder in content.css */
+.mw-image-border > *:first-child {
+ > img,
+ > video {
+ border: 1px solid #eaecf0;
+ }
+}
+
+/**
+ * Avoid the need to calculate paddings individually
+ * https://stackoverflow.com/a/7310398
+ */
+.mw-gallery-traditional .gallerybox .thumb {
+ &:before {
+ content: '';
+ vertical-align: middle;
+ display: inline-block;
+ height: 100%;
+ }
+ > * {
+ vertical-align: middle;
+ display: inline-block;
+ }
+}
+
+/**
+ * Inline media items
+ */
+*:first-child {
+ > img,
+ > video {
+ .mw-valign-middle > & {
+ vertical-align: middle;
+ }
+ .mw-valign-baseline > & {
+ vertical-align: baseline;
+ }
+ .mw-valign-sub > & {
+ vertical-align: sub;
+ }
+ .mw-valign-super > & {
+ vertical-align: super;
+ }
+ .mw-valign-top > & {
+ vertical-align: top;
+ }
+ .mw-valign-text-top > & {
+ vertical-align: text-top;
+ }
+ .mw-valign-bottom > & {
+ vertical-align: bottom;
+ }
+ .mw-valign-text-bottom > & {
+ vertical-align: text-bottom;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.skinning/elements.css b/www/wiki/resources/src/mediawiki.skinning/elements.css
new file mode 100644
index 00000000..d204d5d5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/elements.css
@@ -0,0 +1,285 @@
+/**
+ * MediaWiki style sheet for general styles on basic content elements
+ *
+ * Styles for basic elements: links, lists, etc...
+ *
+ * This style sheet is used by the Monobook and Vector skins.
+ */
+
+/* Links */
+a {
+ text-decoration: none;
+ color: #0645ad;
+ background: none;
+}
+
+a:not( [href] ) {
+ cursor: pointer; /* Always cursor:pointer even without href */
+}
+
+a:visited {
+ color: #0b0080;
+}
+
+a:active {
+ color: #faa700;
+}
+
+a:hover,
+a:focus {
+ text-decoration: underline;
+}
+
+a:lang( ar ),
+a:lang( kk-arab ),
+a:lang( mzn ),
+a:lang( ps ),
+a:lang( ur ) {
+ text-decoration: none;
+}
+
+a.stub {
+ color: #723;
+}
+
+a.new,
+#p-personal a.new {
+ color: #ba0000;
+}
+
+a.new:visited,
+#p-personal a.new:visited {
+ color: #a55858;
+}
+
+/* Interwiki Styling */
+.mw-body-content a.extiw,
+.mw-body-content a.extiw:active {
+ color: #36b;
+}
+
+.mw-body-content a.extiw:visited {
+ color: #636;
+}
+
+.mw-body-content a.extiw:active {
+ color: #b63;
+}
+
+/* External links */
+.mw-body-content a.external {
+ color: #36b;
+}
+
+.mw-body-content a.external:visited {
+ color: #636; /* T5112 */
+}
+
+.mw-body-content a.external:active {
+ color: #b63;
+}
+
+.mw-body-content a.external.free {
+ word-wrap: break-word;
+}
+
+/* Inline Elements */
+img {
+ border: 0;
+ vertical-align: middle;
+}
+
+hr {
+ height: 1px;
+ color: #a2a9b1;
+ background-color: #a2a9b1;
+ border: 0;
+ margin: 0.2em 0;
+}
+
+/* Structural Elements */
+h1,
+h2,
+h3,
+h4,
+h5,
+h6 {
+ color: #000;
+ background: none;
+ font-weight: normal;
+ margin: 0;
+ overflow: hidden;
+ padding-top: 0.5em;
+ padding-bottom: 0.17em;
+ border-bottom: 1px solid #a2a9b1;
+}
+
+h1 {
+ font-size: 188%;
+}
+
+h2 {
+ font-size: 150%;
+}
+
+h3,
+h4,
+h5,
+h6 {
+ border-bottom: 0;
+ font-weight: bold;
+}
+
+h3 {
+ font-size: 128%;
+}
+
+h4 {
+ font-size: 116%;
+}
+
+h5 {
+ font-size: 108%;
+}
+
+h6 {
+ font-size: 100%;
+}
+
+/* Some space under the headers in the content area */
+h1,
+h2 {
+ margin-bottom: 0.6em;
+}
+
+h3,
+h4,
+h5 {
+ margin-bottom: 0.3em;
+}
+
+p {
+ margin: 0.4em 0 0.5em 0;
+}
+
+p img {
+ margin: 0;
+}
+
+ul {
+ list-style-type: square;
+ margin: 0.3em 0 0 1.6em;
+ padding: 0;
+}
+
+ol {
+ margin: 0.3em 0 0 3.2em;
+ padding: 0;
+ list-style-image: none;
+}
+
+li {
+ margin-bottom: 0.1em;
+}
+
+dt {
+ font-weight: bold;
+ margin-bottom: 0.1em;
+}
+
+dl {
+ margin-top: 0.2em;
+ margin-bottom: 0.5em;
+}
+
+dd {
+ margin-left: 1.6em;
+ margin-bottom: 0.1em;
+}
+
+pre,
+code,
+tt,
+kbd,
+samp,
+.mw-code {
+ /*
+ * Some browsers will render the monospace text too small, namely Firefox, Chrome and Safari.
+ * Specifying any valid, second value will trigger correct behavior without forcing a different font.
+ */
+ font-family: monospace, 'Courier';
+}
+
+code {
+ color: #000;
+ background-color: #f8f9fa;
+ border: 1px solid #eaecf0;
+ border-radius: 2px;
+ padding: 1px 4px;
+}
+
+pre,
+.mw-code {
+ color: #000;
+ background-color: #f8f9fa;
+ border: 1px solid #eaecf0;
+ padding: 1em;
+ /* Wrap lines in overflow. T2260, T103780 */
+ white-space: pre-wrap;
+}
+
+/* Tables */
+table {
+ font-size: 100%;
+}
+
+/* Forms */
+fieldset {
+ border: 1px solid #2a4b8d;
+ margin: 1em 0 1em 0;
+ padding: 0 1em 1em;
+}
+
+fieldset.nested {
+ margin: 0 0 0.5em 0;
+ padding: 0 0.5em 0.5em;
+}
+
+legend {
+ padding: 0.5em;
+ font-size: 95%;
+}
+
+form {
+ border: 0;
+ margin: 0;
+}
+
+textarea {
+ width: 100%;
+ padding: 0.1em;
+ display: block;
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+}
+
+/* Emulate Center */
+.center {
+ width: 100%;
+ text-align: center;
+}
+
+*.center * {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+/* Small for tables and similar */
+.small {
+ font-size: 94%;
+}
+
+table.small {
+ font-size: 100%;
+}
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/audio-ltr.png b/www/wiki/resources/src/mediawiki.skinning/images/audio-ltr.png
new file mode 100644
index 00000000..c6ae166f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/audio-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/audio-ltr.svg b/www/wiki/resources/src/mediawiki.skinning/images/audio-ltr.svg
new file mode 100644
index 00000000..e27a5f53
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/audio-ltr.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m43.47,259.4-3,3-3,0,0,4,3,0,3,3zm-1,2.5,0,5-1.5-1.5-2.5,0,0-2,2.5,0z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m43.9,262.5c0-0.6213,0.6213-1.243,1.243-0.6213,0,0,0.6213,0.6213,0.6213,2.485s-0.6213,2.485-0.6213,2.485c-0.6213,0.6213-1.243,0-1.243-0.6213,0,0,0.6213-0.6213,0.6213-1.864s-0.6213-1.864-0.6213-1.864z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m45.76,261.2c0-0.6213,0.6213-1.243,1.243-0.6213,0,0,1.243,1.243,1.243,3.728s-1.243,3.728-1.243,3.728c-0.6213,0.6213-1.243,0-1.243-0.6213,0,0,1.243-1.243,1.243-3.107s-1.243-3.107-1.243-3.107z"/>
+</g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/audio-rtl.png b/www/wiki/resources/src/mediawiki.skinning/images/audio-rtl.png
new file mode 100644
index 00000000..5a70289f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/audio-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/audio-rtl.svg b/www/wiki/resources/src/mediawiki.skinning/images/audio-rtl.svg
new file mode 100644
index 00000000..683bbcd7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/audio-rtl.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m42.47,259.4,3,3,3,0,0,4-3,0-3,3zm1,2.5,0,5,1.5-1.5,2.5,0,0-2-2.5,0z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m42.04,262.5c0-0.6213-0.6213-1.243-1.243-0.6213,0,0-0.6213,0.6213-0.6213,2.485s0.6213,2.485,0.6213,2.485c0.6213,0.6213,1.243,0,1.243-0.6213,0,0-0.6213-0.6213-0.6213-1.864s0.6213-1.864,0.6213-1.864z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m40.17,261.2c0-0.6213-0.6213-1.243-1.243-0.6213,0,0-1.243,1.243-1.243,3.728s1.243,3.728,1.243,3.728c0.6213,0.6213,1.243,0,1.243-0.6213,0,0-1.243-1.243-1.243-3.107s1.243-3.107,1.243-3.107z"/>
+</g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/chat-ltr.png b/www/wiki/resources/src/mediawiki.skinning/images/chat-ltr.png
new file mode 100644
index 00000000..7c928250
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/chat-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/chat-ltr.svg b/www/wiki/resources/src/mediawiki.skinning/images/chat-ltr.svg
new file mode 100644
index 00000000..bd5329e0
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/chat-ltr.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m38.09,260.4-0.6213,0.6213,0,5.757,0.6213,0.6213,1.689,0-0.6213,2.728,4.311-2.728,4.379,0,0.6213-0.6213,0-5.757-0.6213-0.6213zm0.3787,1,9,0,0,5-4,0-2.902,1.897,0.9021-1.897-3,0z"/>
+</g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/chat-rtl.png b/www/wiki/resources/src/mediawiki.skinning/images/chat-rtl.png
new file mode 100644
index 00000000..5411b14e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/chat-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/chat-rtl.svg b/www/wiki/resources/src/mediawiki.skinning/images/chat-rtl.svg
new file mode 100644
index 00000000..b86218f3
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/chat-rtl.svg
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m47.85,260.4,0.6213,0.6213,0,5.757-0.6213,0.6213-1.689,0,0.6213,2.728-4.311-2.728-4.379,0-0.6213-0.6213,0-5.757,0.6213-0.6213zm-0.3787,1-9,0,0,5,4,0,2.902,1.897-0.9021-1.897,3,0z"/>
+</g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/document-ltr.png b/www/wiki/resources/src/mediawiki.skinning/images/document-ltr.png
new file mode 100644
index 00000000..039b780b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/document-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/document-ltr.svg b/www/wiki/resources/src/mediawiki.skinning/images/document-ltr.svg
new file mode 100644
index 00000000..43960980
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/document-ltr.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<path style="opacity:1;fill:#15a5ea;" d="m7.5,2,0,3,2.5,0,1-1-2.5,0,0-3z"/>
+<path style="opacity:1;fill:#3366bb;" d="m3,1,0,10,8,0,0-7-2.5-3zm1,1,4,0,2,2.5,0,5.5-6,0z"/>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/document-rtl.png b/www/wiki/resources/src/mediawiki.skinning/images/document-rtl.png
new file mode 100644
index 00000000..3fd177e9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/document-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/document-rtl.svg b/www/wiki/resources/src/mediawiki.skinning/images/document-rtl.svg
new file mode 100644
index 00000000..c37dadca
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/document-rtl.svg
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<path style="opacity:1;fill:#15a5ea;" d="m5.5,2,0,3-2.5,0-1-1,2.5,0,0-3z"/>
+<path style="opacity:1;fill:#3366bb;" d="m10,1,0,10-8,0,0-7,2.5-3zm-1,1-4,0-2,2.5,0,5.5,6,0z"/>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/external link icons.svg b/www/wiki/resources/src/mediawiki.skinning/images/external link icons.svg
new file mode 100644
index 00000000..6a67993d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/external link icons.svg
@@ -0,0 +1,697 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="13"
+ height="110"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.5 r10040"
+ sodipodi:docname="external link icons.svg">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="15.999999"
+ inkscape:cx="10.40536"
+ inkscape:cy="65.686256"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer5"
+ showgrid="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1283"
+ inkscape:window-height="711"
+ inkscape:window-x="1790"
+ inkscape:window-y="-6"
+ inkscape:window-maximized="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3246"
+ empspacing="4"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="0px"
+ originy="-27.999997px" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="base"
+ style="display:none"
+ transform="translate(-505,-869.36218)">
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646"
+ width="13"
+ height="12.999996"
+ x="505"
+ y="885.36218" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646-4"
+ width="13"
+ height="12.999998"
+ x="505"
+ y="901.36218" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646-4-6"
+ width="13"
+ height="12.999996"
+ x="505"
+ y="917.36218"
+ inkscape:export-filename="/home/rahah/elvidishu/steak/unreal/dev/skins/external link icons/mail.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646-4-6-9"
+ width="13"
+ height="12.999996"
+ x="505"
+ y="933.36218" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646-4-6-6"
+ width="13"
+ height="12.999996"
+ x="505"
+ y="950.36218" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646-4-6-2"
+ width="13"
+ height="12.999998"
+ x="505"
+ y="966.36218" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ id="rect4646-44"
+ width="13"
+ height="12.999996"
+ x="505"
+ y="869.36218" />
+ </g>
+ <g
+ inkscape:label="sketch 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-505,-869.36218)"
+ style="display:none"
+ sodipodi:insensitive="true">
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507,870.36218 0,5 3,0 4,4 0,-13 -4,4 z"
+ id="path3194"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 517,869.36218 c 1,2 1,5 0,7"
+ id="path3196"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 520,867.36218 c 2,2 2,9 0,11"
+ id="path3198"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,989.90562 0,15.99988 13,0 0,-10.99988 -5,-5 z"
+ id="path3200"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 506.93861,918.90546 0,11.5 15,0 0,-11.5 z"
+ id="path3202"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 506.93861,918.90546 7.5,6 7.5,-6"
+ id="path3204"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,890.90546 3,0"
+ id="path3212"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,893.90546 3,0"
+ id="path3214"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,899.90546 3,0"
+ id="path3218"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,902.90546 3,0"
+ id="path3220"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 517.93861,890.90546 3,0"
+ id="path3222"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,896.90546 13,0"
+ id="path3224"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 517.93861,893.90546 3,0"
+ id="path3226"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 517.93861,899.90546 3,0"
+ id="path3230"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 517.93861,902.90546 3,0"
+ id="path3232"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 510.93861,890.90546 0,12 7,0 0,-12 z"
+ id="path3206"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,888.90546 0,16"
+ id="path3208"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 520.93861,888.90546 0,16"
+ id="path3210"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 515.93861,989.90562 0,5 5,0"
+ id="path3234"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 513.93861,969.40546 c -2,0 -5,0 -7,0 l 0,10.99995 11,5e-5 c 0,-2.33332 0,-4.66668 0,-7"
+ id="path3236"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none"
+ d="m 513.93861,976.40546 5,-4 3,3 0,-10 -10,0 3,3 -4,5"
+ id="path3242"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 506.93861,940.40546 15,0 0,10 -6,0 -6,4 1,-4 -4,0 z"
+ id="path3244"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 509.93861,972.40546 c 2,1 4,3 5,5"
+ id="path4641"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer4"
+ inkscape:label="sketch 2"
+ style="display:none"
+ transform="translate(0,-6.0000106)">
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 8.4921988,1.0623917 -4.0641234,4.064123 -3.2512987,0 0,5.6897733 3.2512987,0 4.0641234,4.064124 z m -1.6256494,4.064124 0,5.6897733 -1.6256493,-1.6256493 -2.438474,-1e-6 0,-2.438474 2.438474,1e-6 z"
+ id="path4755-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 9.3050235,5.1265157 c 0,-0.812824 0.8128245,-1.625649 1.6256495,-0.812824 0,0 0.812825,0.812824 0.812825,3.251298 0,2.4384743 -0.812825,3.2512993 -0.812825,3.2512993 -0.812825,0.812825 -1.6256495,0 -1.6256495,-0.812825 0,0 0.8128245,-0.8128243 0.8128245,-2.4384743 0,-1.625649 -0.8128245,-2.438474 -0.8128245,-2.438474 z"
+ id="path4760-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 11.743498,3.5008667 c 0,-0.812825 0.812824,-1.625649 1.625649,-0.812825 0,0 1.625649,1.62565 1.625649,4.876948 0,3.2512993 -1.625649,4.8769483 -1.625649,4.8769483 -0.812825,0.812825 -1.625649,0 -1.625649,-0.812824 0,0 1.625649,-1.62565 1.625649,-4.0641243 0,-2.438474 -1.625649,-4.064123 -1.625649,-4.064123 z"
+ id="path4762-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2.8024261,23.008658 0,0.812825 10.5667209,0 0,-0.812825 z"
+ id="path4772"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2.8024261,33.575379 10.5667209,0 0,-0.812825 -10.5667209,0 z"
+ id="path4774"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2.8024261,25.447132 0,0.812824 2.438474,0 0,-0.812824 z m 8.1282469,0 0,0.812824 2.438474,0 0,-0.812824 z"
+ id="path4782"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2.8024261,30.32408 0,0.812824 2.438474,0 0,-0.812824 z m 8.1282469,0 0,0.812824 2.438474,0 0,-0.812824 z"
+ id="path4778"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2.8024261,28.698431 10.5667209,0 0,-0.812825 -10.5667209,0 z"
+ id="path4780"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 5.2409001,27.479194 0,1.625649 5.6897729,0 0,-1.625649 z"
+ id="path4793"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 4.4280754,23.008658 0,10.56672 7.3154226,0 0,-10.56672 z m 1.6256494,1.625649 4.0641232,0 0,7.315422 -4.0641232,0 z"
+ id="path4768"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 1.9896014,21.383009 1.6256493,0 0,13.818019 -1.6256493,0 z"
+ id="path4764"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 12.556322,21.383009 1.62565,0 0,13.818019 -1.62565,0 z"
+ id="path4766"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 1.9896014,44.954923 6.096185,5.689773 6.0961856,-5.689773 -0.812825,-0.812825 -1.625649,0.813196 -3.6577116,3.251298 -3.657711,-3.251298 -1.6256493,-0.813196 z"
+ id="path4800-4"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 1.1767767,43.329273 0,11.379545 13.8180193,0 0,-11.379545 z m 1.6256494,1.625649 10.5667209,0 0,8.128247 -10.5667209,0 z"
+ id="path4795-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 1.9896014,62.024243 -0.8128247,0.812824 0,8.128247 0.8128247,0.812825 2.438474,0 -0.8128247,3.251297 5.6897728,-3.251297 4.8769485,0 0.812824,-0.812825 0,-8.128247 -0.812824,-0.812824 z m 0.8128247,1.625649 10.5667209,0 0,6.502598 -4.0641235,0 -3.5815088,2.133664 0.9144278,-2.133664 -3.8355164,0 z"
+ id="path4802-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 4.4280754,82.344856 10.5667206,0 0,10.56672 -3.251298,-3.25129 -3.2512992,2.43847 -0.8128247,-0.81282 4.0641239,-3.2513 1.625649,1.62565 0,-5.68978 -5.6897729,0 1.6256494,1.62565 -3.2512987,4.06413 -0.8128247,-0.81283 2.438474,-3.2513 z"
+ id="path4807-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 8.4921988,85.596156 -7.3154221,0 0,10.56672 10.5667213,0 0,-7.31542 -1.62565,0.81283 0,4.87694 -7.3154219,0 0,-7.31542 4.876948,0 z"
+ id="path4809-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 8.4921988,103.47831 0,4.87694 4.8769482,0 0,-1.62565 -3.251299,0 0,-3.25129 z"
+ id="path4818-67"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 1.9896014,102.66548 0,13.81802 12.1923706,0 0,-10.13799 -3.657711,-3.68003 z m 1.6256493,1.62565 6.5025973,0 2.438474,2.43847 0,8.12825 -8.9410713,0 z"
+ id="path4813-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 3.6152507,88.847456 c 0,-0.81282 0.8128247,-0.81282 0.8128247,-0.81282 2.438474,0.81282 4.0641234,2.43847 4.8769481,4.87694 0,0 0,0.81283 -0.8128247,0.81283 -1.6256494,-2.43847 -2.438474,-3.2513 -4.8769481,-4.87695 z"
+ id="path4822-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer"
+ style="display:none"
+ transform="translate(-10,-26.000007)">
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 19,20.999995 -4,4 -3,0 0,6 3,0 4,4 z m -1,2.5 0,9 -2.6,-2.5 -2.4,0 0,-4 2.5,0 z"
+ id="path4755"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none"
+ d="m 19.75,24.999995 c 0,-1 0.75,-1 0.75,-1 0,0 1.5,1.029412 1.5,3.5 0,2.470588 -1.5,3.5 -1.5,3.5 0,0 -0.75,0 -0.75,-1 0,0 1,-0.852941 1,-2.5 0,-1.647059 -1,-2.5 -1,-2.5 z"
+ id="path4760"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none"
+ d="m 22.25,23.999995 c 0,-1 0.75,-1 0.75,-1 0,0 2,1.205882 2,4.5 0,3.294118 -2,4.5 -2,4.5 0,0 -0.75,0 -0.75,-1 0,0 1.5,-1.029412 1.5,-3.5 0,-2.470588 -1.5,-3.5 -1.5,-3.5 z"
+ id="path4762"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 31.4375,79.875 -1,1 0,10 1,1 3,0 -1,4 7,-4 6,0 1,-1 0,-10 -1,-1 z m 1,2 13,0 0,8 -5,0 -4.40625,2.625 1.125,-2.625 -4.71875,0 z"
+ id="path4802"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 35.125,98.8125 13,0 0,13 -4,-4 -4,3 -1,-1 5,-4 2,2 0,-7 -7,0 2,2 -4,5 -1,-1 3,-4 z"
+ id="path4807"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 40.125,102.8125 -9,0 0,13 13,0 0,-9 -2,1 0,6 -9,0 0,-9 6,0 z"
+ id="path4809"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none"
+ d="m 34.125,106.8125 c 0,-1 1,-1 1,-1 3,1 5,3 6,6 0,0 0,1 -1,1 -2,-3 -3,-4 -6,-6 z"
+ id="path4822"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 12,50.499995 0,1 3,0 0,-1 -3,0 z m 9,0 0,1 3,0 0,-1 -3,0 z"
+ id="rect4841"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 12,44.499995 0,1 3,0 0,-1 -3,0 z m 9,0 0,1 3,0 0,-1 -3,0 z"
+ id="rect4843"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 12,52.999995 0,1 3,0 0,-1 z m 9,0 0,1 3,0 0,-1 z"
+ id="rect4843-1"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 12,41.999995 0,1 3,0 0,-1 z m 9,0 0,1 3,0 0,-1 z"
+ id="rect4843-17"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 12,47.499995 0,1 3,0 0,-1 z m 9,0 0,1 3,0 0,-1 z"
+ id="rect4841-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <rect
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4835"
+ width="7"
+ height="2"
+ x="4"
+ y="27"
+ transform="translate(10,19.999995)" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 2,21 1,0 0,14 -1,0 z"
+ id="path4826"
+ inkscape:connector-curvature="0"
+ transform="translate(10,19.999995)"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 13,21 1,0 0,14 -1,0 z"
+ id="path4828"
+ inkscape:connector-curvature="0"
+ transform="translate(10,19.999995)"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 4,22 0,12 8,0 0,-12 z m 1,1 6,0 0,10 -6,0 z"
+ transform="translate(10,19.999995)"
+ id="path4830"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <rect
+ style="fill:#3366bb;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4837"
+ width="8"
+ height="1"
+ x="4"
+ y="22"
+ transform="translate(10,19.999995)" />
+ <rect
+ style="fill:#3366bb;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4839"
+ width="8"
+ height="1"
+ x="4"
+ y="33"
+ transform="translate(10,19.999995)" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none"
+ d="m 12,64.999995 6,5 6,-5 0.53033,-1.45299 -1.28033,0.45299 -5.25,4.5 -5.25,-4.5 -1.236136,-0.53033 z"
+ id="path4910"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 11,62.999995 0,10 14,0 0,-10 z m 1,1 12,0 0,8 -12,0 z"
+ id="path4905"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 19,121 0,5 5,0 -1,-1 -3,0 0,-3 z"
+ id="path4818-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 12,121 0,14 12,0 0,-10 -4,-4 z m 1,1 6.5,0 3.5,3.5 0,8.5 -10,0 z"
+ id="path4813-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccc" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer5"
+ inkscape:label="Layer#1"
+ style="opacity:0.98999999"
+ transform="translate(0,-6.0000106)">
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 7,23.000004 -3,3 -3,0 0,4 3,0 3,3 z m -1,2.500001 0,5 -1.5,-1.500001 -2.5,0 0,-2 2.5,0 z"
+ id="path4755-9-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 7.4319858,26.075368 c 0,-0.621323 0.6213237,-1.242647 1.2426477,-0.621323 0,0 0.6213228,0.621323 0.6213228,2.485294 0,1.863971 -0.6213228,2.485294 -0.6213228,2.485294 -0.621324,0.621324 -1.2426477,0 -1.2426477,-0.621323 0,0 0.6213237,-0.621324 0.6213237,-1.863971 0,-1.242648 -0.6213237,-1.863971 -0.6213237,-1.863971 z"
+ id="path4760-1-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 9.2959563,24.832721 c 0,-0.621324 0.6213228,-1.242647 1.2426477,-0.621324 0,0 1.242646,1.242648 1.242646,3.727942 0,2.485294 -1.242646,3.727941 -1.242646,3.727941 -0.6213249,0.621324 -1.2426477,0 -1.2426477,-0.621323 0,0 1.2426477,-1.242647 1.2426477,-3.106618 0,-1.863971 -1.2426477,-3.106618 -1.2426477,-3.106618 z"
+ id="path4762-8-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+ d="m 2.4916056,40.000004 0,0.621323 8.0979164,0 0,-0.621323 z"
+ id="path4772-4"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+ d="m 2.4916056,48.000004 8.0979164,0 0,-0.621324 -8.0979164,0 z"
+ id="path4774-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+ d="m 2.4916056,41.919118 0,0.621323 1.8687499,0 0,-0.621323 z m 6.2291665,0 0,0.621323 1.8687499,0 0,-0.621323 z"
+ id="path4782-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+ d="m 2.4916056,45.589344 0,0.621322 1.8687499,0 0,-0.621322 z m 6.2291665,0 0,0.621322 1.8687499,0 0,-0.621322 z"
+ id="path4778-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+ d="m 2.4916056,44.404412 8.0979164,0 0,-0.621323 -8.0979164,0 z"
+ id="path4780-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 4.3603555,43.472427 0,1.242647 4.3604166,0 0,-1.242647 z"
+ id="path4793-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 4,40.000004 0,8 5,0 0,-8 z m 1,1 3,0 0,6 -3,0 z"
+ id="path4768-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2,39.000004 1,0 0,10 -1,0 z"
+ id="path4764-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 10,39.000004 1,0 0,10 -1,0 z"
+ id="path4766-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="M 1.8400738,58.055766 6.5000005,62.405031 11.159927,58.055766 10.538604,57.434442 9.2959563,58.056049 6.5000005,60.541343 3.7040445,58.056049 2.4613977,57.434442 z"
+ id="path4800-4-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:export-filename="/home/rahah/elvidishu/steak/unreal/dev/skins/external link icons/mail.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 1,57.000008 0,8 11,0 0,-8 z m 1,1 9,0 0,6 -9,0 z"
+ id="path4795-8-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc"
+ inkscape:export-filename="/home/rahah/elvidishu/steak/unreal/dev/skins/external link icons/mail.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="M 1.6213238,72.000004 1,72.621328 l 0,5.757352 0.6213238,0.621324 1.6894529,0 L 2.6894528,81.727943 7,79.000004 l 4.378677,0 L 12,78.37868 12,72.621328 11.378677,72.000004 z m 0.3786762,1 9,0 0,5 -4,0 L 4.0978858,79.896603 5,78.000004 l -3,0 z"
+ id="path4802-8-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 5,88.000004 7,0 0,7 -2,-2 -3,2 0,-1 3,-2.249999 1,1 0,-3.750001 -3.75,0 1,1 -2.25,3 -1,0 2,-3 z"
+ id="path4807-5-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 7,90.000004 -5,0 0,8 8,0 0,-5 -1,0 0,4 -6,0 0,-6 4,0 z"
+ id="path4809-7-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 7.5,105.00001 0,3 2.5,0 1,-1 -2.5,0 0,-3 z"
+ id="path4818-67-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 3,104 0,10 8,1e-5 0,-7 -2.5,-3 z m 1,1 4,1e-5 2,2.50001 0,5.49999 -6,0 z"
+ id="path4813-2-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 4.0827206,92.533089 c 0,-0.621319 0.6213239,-0.621319 0.6213239,-0.621319 1.8639706,0.621319 3.1066175,1.863968 3.7279413,3.727935 0,0 0,0.621328 -0.6213238,0.621328 C 6.5680151,94.397065 5.9466913,93.775738 4.0827206,92.533089 z"
+ id="path4822-8-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3465ba;fill-opacity:1;stroke:none;display:inline"
+ d="m 1,8.500006 0,7.5001 1,-0.9872 0,-6.0129 2,0 2,1 4,-2e-4 0,2.0002 1,0 0,-2.5 -0.5,-0.5002 -4.5,2e-4 -2,-1 -2.5,0 z"
+ id="path3209"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccc" />
+ <path
+ style="fill:#16a4e8;fill-opacity:1;stroke:none;display:inline"
+ d="m 6,11.000106 -1,-10e-5 -2.5,0 -0.5,0.5 -1,4.5001 10,-10e-5 0,-4.4998 -0.5,-0.5 z m 0,1 4,-10e-5 0,3 -7.75,-1e-4 0.75,-3.0001 2,0 z"
+ id="path3215"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccc" />
+ <path
+ style="fill:#3465ba;fill-opacity:1;stroke:none;display:inline"
+ d="m 2,17.000006 0,1 8,0 0,-1 z"
+ id="path3247"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3465ba;fill-opacity:1;stroke:none;display:inline"
+ d="m 5,15.500006 0,2 2,0 0,-2 c 0,-0.5 -2,-0.5 -2,0 z"
+ id="path3249"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/external-link-icons.svg b/www/wiki/resources/src/mediawiki.skinning/images/external-link-icons.svg
new file mode 100644
index 00000000..6a67993d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/external-link-icons.svg
@@ -0,0 +1,697 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ width="13"
+ height="110"
+ id="svg2"
+ version="1.1"
+ inkscape:version="0.48.5 r10040"
+ sodipodi:docname="external link icons.svg">
+ <defs
+ id="defs4" />
+ <sodipodi:namedview
+ id="base"
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1.0"
+ inkscape:pageopacity="0.0"
+ inkscape:pageshadow="2"
+ inkscape:zoom="15.999999"
+ inkscape:cx="10.40536"
+ inkscape:cy="65.686256"
+ inkscape:document-units="px"
+ inkscape:current-layer="layer5"
+ showgrid="true"
+ fit-margin-top="0"
+ fit-margin-left="0"
+ fit-margin-right="0"
+ fit-margin-bottom="0"
+ inkscape:window-width="1283"
+ inkscape:window-height="711"
+ inkscape:window-x="1790"
+ inkscape:window-y="-6"
+ inkscape:window-maximized="0">
+ <inkscape:grid
+ type="xygrid"
+ id="grid3246"
+ empspacing="4"
+ visible="true"
+ enabled="true"
+ snapvisiblegridlinesonly="true"
+ originx="0px"
+ originy="-27.999997px" />
+ </sodipodi:namedview>
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ inkscape:groupmode="layer"
+ id="layer2"
+ inkscape:label="base"
+ style="display:none"
+ transform="translate(-505,-869.36218)">
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646"
+ width="13"
+ height="12.999996"
+ x="505"
+ y="885.36218" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646-4"
+ width="13"
+ height="12.999998"
+ x="505"
+ y="901.36218" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646-4-6"
+ width="13"
+ height="12.999996"
+ x="505"
+ y="917.36218"
+ inkscape:export-filename="/home/rahah/elvidishu/steak/unreal/dev/skins/external link icons/mail.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646-4-6-9"
+ width="13"
+ height="12.999996"
+ x="505"
+ y="933.36218" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646-4-6-6"
+ width="13"
+ height="12.999996"
+ x="505"
+ y="950.36218" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4646-4-6-2"
+ width="13"
+ height="12.999998"
+ x="505"
+ y="966.36218" />
+ <rect
+ style="fill:#b3b3b3;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ id="rect4646-44"
+ width="13"
+ height="12.999996"
+ x="505"
+ y="869.36218" />
+ </g>
+ <g
+ inkscape:label="sketch 1"
+ inkscape:groupmode="layer"
+ id="layer1"
+ transform="translate(-505,-869.36218)"
+ style="display:none"
+ sodipodi:insensitive="true">
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507,870.36218 0,5 3,0 4,4 0,-13 -4,4 z"
+ id="path3194"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 517,869.36218 c 1,2 1,5 0,7"
+ id="path3196"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 520,867.36218 c 2,2 2,9 0,11"
+ id="path3198"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,989.90562 0,15.99988 13,0 0,-10.99988 -5,-5 z"
+ id="path3200"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 506.93861,918.90546 0,11.5 15,0 0,-11.5 z"
+ id="path3202"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 506.93861,918.90546 7.5,6 7.5,-6"
+ id="path3204"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,890.90546 3,0"
+ id="path3212"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,893.90546 3,0"
+ id="path3214"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,899.90546 3,0"
+ id="path3218"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,902.90546 3,0"
+ id="path3220"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 517.93861,890.90546 3,0"
+ id="path3222"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,896.90546 13,0"
+ id="path3224"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 517.93861,893.90546 3,0"
+ id="path3226"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 517.93861,899.90546 3,0"
+ id="path3230"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 517.93861,902.90546 3,0"
+ id="path3232"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 510.93861,890.90546 0,12 7,0 0,-12 z"
+ id="path3206"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 507.93861,888.90546 0,16"
+ id="path3208"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 520.93861,888.90546 0,16"
+ id="path3210"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 515.93861,989.90562 0,5 5,0"
+ id="path3234"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 513.93861,969.40546 c -2,0 -5,0 -7,0 l 0,10.99995 11,5e-5 c 0,-2.33332 0,-4.66668 0,-7"
+ id="path3236"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;marker-start:none"
+ d="m 513.93861,976.40546 5,-4 3,3 0,-10 -10,0 3,3 -4,5"
+ id="path3242"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:none;stroke:#0066ff;stroke-width:1.5;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 506.93861,940.40546 15,0 0,10 -6,0 -6,4 1,-4 -4,0 z"
+ id="path3244"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccc" />
+ <path
+ style="fill:none;stroke:#5b9dff;stroke-width:1.5;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ d="m 509.93861,972.40546 c 2,1 4,3 5,5"
+ id="path4641"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer4"
+ inkscape:label="sketch 2"
+ style="display:none"
+ transform="translate(0,-6.0000106)">
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 8.4921988,1.0623917 -4.0641234,4.064123 -3.2512987,0 0,5.6897733 3.2512987,0 4.0641234,4.064124 z m -1.6256494,4.064124 0,5.6897733 -1.6256493,-1.6256493 -2.438474,-1e-6 0,-2.438474 2.438474,1e-6 z"
+ id="path4755-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 9.3050235,5.1265157 c 0,-0.812824 0.8128245,-1.625649 1.6256495,-0.812824 0,0 0.812825,0.812824 0.812825,3.251298 0,2.4384743 -0.812825,3.2512993 -0.812825,3.2512993 -0.812825,0.812825 -1.6256495,0 -1.6256495,-0.812825 0,0 0.8128245,-0.8128243 0.8128245,-2.4384743 0,-1.625649 -0.8128245,-2.438474 -0.8128245,-2.438474 z"
+ id="path4760-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 11.743498,3.5008667 c 0,-0.812825 0.812824,-1.625649 1.625649,-0.812825 0,0 1.625649,1.62565 1.625649,4.876948 0,3.2512993 -1.625649,4.8769483 -1.625649,4.8769483 -0.812825,0.812825 -1.625649,0 -1.625649,-0.812824 0,0 1.625649,-1.62565 1.625649,-4.0641243 0,-2.438474 -1.625649,-4.064123 -1.625649,-4.064123 z"
+ id="path4762-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2.8024261,23.008658 0,0.812825 10.5667209,0 0,-0.812825 z"
+ id="path4772"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2.8024261,33.575379 10.5667209,0 0,-0.812825 -10.5667209,0 z"
+ id="path4774"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2.8024261,25.447132 0,0.812824 2.438474,0 0,-0.812824 z m 8.1282469,0 0,0.812824 2.438474,0 0,-0.812824 z"
+ id="path4782"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2.8024261,30.32408 0,0.812824 2.438474,0 0,-0.812824 z m 8.1282469,0 0,0.812824 2.438474,0 0,-0.812824 z"
+ id="path4778"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2.8024261,28.698431 10.5667209,0 0,-0.812825 -10.5667209,0 z"
+ id="path4780"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 5.2409001,27.479194 0,1.625649 5.6897729,0 0,-1.625649 z"
+ id="path4793"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 4.4280754,23.008658 0,10.56672 7.3154226,0 0,-10.56672 z m 1.6256494,1.625649 4.0641232,0 0,7.315422 -4.0641232,0 z"
+ id="path4768"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 1.9896014,21.383009 1.6256493,0 0,13.818019 -1.6256493,0 z"
+ id="path4764"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 12.556322,21.383009 1.62565,0 0,13.818019 -1.62565,0 z"
+ id="path4766"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 1.9896014,44.954923 6.096185,5.689773 6.0961856,-5.689773 -0.812825,-0.812825 -1.625649,0.813196 -3.6577116,3.251298 -3.657711,-3.251298 -1.6256493,-0.813196 z"
+ id="path4800-4"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 1.1767767,43.329273 0,11.379545 13.8180193,0 0,-11.379545 z m 1.6256494,1.625649 10.5667209,0 0,8.128247 -10.5667209,0 z"
+ id="path4795-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 1.9896014,62.024243 -0.8128247,0.812824 0,8.128247 0.8128247,0.812825 2.438474,0 -0.8128247,3.251297 5.6897728,-3.251297 4.8769485,0 0.812824,-0.812825 0,-8.128247 -0.812824,-0.812824 z m 0.8128247,1.625649 10.5667209,0 0,6.502598 -4.0641235,0 -3.5815088,2.133664 0.9144278,-2.133664 -3.8355164,0 z"
+ id="path4802-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 4.4280754,82.344856 10.5667206,0 0,10.56672 -3.251298,-3.25129 -3.2512992,2.43847 -0.8128247,-0.81282 4.0641239,-3.2513 1.625649,1.62565 0,-5.68978 -5.6897729,0 1.6256494,1.62565 -3.2512987,4.06413 -0.8128247,-0.81283 2.438474,-3.2513 z"
+ id="path4807-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 8.4921988,85.596156 -7.3154221,0 0,10.56672 10.5667213,0 0,-7.31542 -1.62565,0.81283 0,4.87694 -7.3154219,0 0,-7.31542 4.876948,0 z"
+ id="path4809-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 8.4921988,103.47831 0,4.87694 4.8769482,0 0,-1.62565 -3.251299,0 0,-3.25129 z"
+ id="path4818-67"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 1.9896014,102.66548 0,13.81802 12.1923706,0 0,-10.13799 -3.657711,-3.68003 z m 1.6256493,1.62565 6.5025973,0 2.438474,2.43847 0,8.12825 -8.9410713,0 z"
+ id="path4813-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 3.6152507,88.847456 c 0,-0.81282 0.8128247,-0.81282 0.8128247,-0.81282 2.438474,0.81282 4.0641234,2.43847 4.8769481,4.87694 0,0 0,0.81283 -0.8128247,0.81283 -1.6256494,-2.43847 -2.438474,-3.2513 -4.8769481,-4.87695 z"
+ id="path4822-8"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer3"
+ inkscape:label="Layer"
+ style="display:none"
+ transform="translate(-10,-26.000007)">
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 19,20.999995 -4,4 -3,0 0,6 3,0 4,4 z m -1,2.5 0,9 -2.6,-2.5 -2.4,0 0,-4 2.5,0 z"
+ id="path4755"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none"
+ d="m 19.75,24.999995 c 0,-1 0.75,-1 0.75,-1 0,0 1.5,1.029412 1.5,3.5 0,2.470588 -1.5,3.5 -1.5,3.5 0,0 -0.75,0 -0.75,-1 0,0 1,-0.852941 1,-2.5 0,-1.647059 -1,-2.5 -1,-2.5 z"
+ id="path4760"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none"
+ d="m 22.25,23.999995 c 0,-1 0.75,-1 0.75,-1 0,0 2,1.205882 2,4.5 0,3.294118 -2,4.5 -2,4.5 0,0 -0.75,0 -0.75,-1 0,0 1.5,-1.029412 1.5,-3.5 0,-2.470588 -1.5,-3.5 -1.5,-3.5 z"
+ id="path4762"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 31.4375,79.875 -1,1 0,10 1,1 3,0 -1,4 7,-4 6,0 1,-1 0,-10 -1,-1 z m 1,2 13,0 0,8 -5,0 -4.40625,2.625 1.125,-2.625 -4.71875,0 z"
+ id="path4802"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 35.125,98.8125 13,0 0,13 -4,-4 -4,3 -1,-1 5,-4 2,2 0,-7 -7,0 2,2 -4,5 -1,-1 3,-4 z"
+ id="path4807"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 40.125,102.8125 -9,0 0,13 13,0 0,-9 -2,1 0,6 -9,0 0,-9 6,0 z"
+ id="path4809"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none"
+ d="m 34.125,106.8125 c 0,-1 1,-1 1,-1 3,1 5,3 6,6 0,0 0,1 -1,1 -2,-3 -3,-4 -6,-6 z"
+ id="path4822"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 12,50.499995 0,1 3,0 0,-1 -3,0 z m 9,0 0,1 3,0 0,-1 -3,0 z"
+ id="rect4841"
+ inkscape:connector-curvature="0" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ d="m 12,44.499995 0,1 3,0 0,-1 -3,0 z m 9,0 0,1 3,0 0,-1 -3,0 z"
+ id="rect4843"
+ inkscape:connector-curvature="0" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 12,52.999995 0,1 3,0 0,-1 z m 9,0 0,1 3,0 0,-1 z"
+ id="rect4843-1"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 12,41.999995 0,1 3,0 0,-1 z m 9,0 0,1 3,0 0,-1 z"
+ id="rect4843-17"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline"
+ d="m 12,47.499995 0,1 3,0 0,-1 z m 9,0 0,1 3,0 0,-1 z"
+ id="rect4841-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <rect
+ style="fill:#15a5ea;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4835"
+ width="7"
+ height="2"
+ x="4"
+ y="27"
+ transform="translate(10,19.999995)" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 2,21 1,0 0,14 -1,0 z"
+ id="path4826"
+ inkscape:connector-curvature="0"
+ transform="translate(10,19.999995)"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 13,21 1,0 0,14 -1,0 z"
+ id="path4828"
+ inkscape:connector-curvature="0"
+ transform="translate(10,19.999995)"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 4,22 0,12 8,0 0,-12 z m 1,1 6,0 0,10 -6,0 z"
+ transform="translate(10,19.999995)"
+ id="path4830"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <rect
+ style="fill:#3366bb;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4837"
+ width="8"
+ height="1"
+ x="4"
+ y="22"
+ transform="translate(10,19.999995)" />
+ <rect
+ style="fill:#3366bb;fill-opacity:1;fill-rule:evenodd;stroke:none"
+ id="rect4839"
+ width="8"
+ height="1"
+ x="4"
+ y="33"
+ transform="translate(10,19.999995)" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none"
+ d="m 12,64.999995 6,5 6,-5 0.53033,-1.45299 -1.28033,0.45299 -5.25,4.5 -5.25,-4.5 -1.236136,-0.53033 z"
+ id="path4910"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none"
+ d="m 11,62.999995 0,10 14,0 0,-10 z m 1,1 12,0 0,8 -12,0 z"
+ id="path4905"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 19,121 0,5 5,0 -1,-1 -3,0 0,-3 z"
+ id="path4818-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 12,121 0,14 12,0 0,-10 -4,-4 z m 1,1 6.5,0 3.5,3.5 0,8.5 -10,0 z"
+ id="path4813-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccc" />
+ </g>
+ <g
+ inkscape:groupmode="layer"
+ id="layer5"
+ inkscape:label="Layer#1"
+ style="opacity:0.98999999"
+ transform="translate(0,-6.0000106)">
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 7,23.000004 -3,3 -3,0 0,4 3,0 3,3 z m -1,2.500001 0,5 -1.5,-1.500001 -2.5,0 0,-2 2.5,0 z"
+ id="path4755-9-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 7.4319858,26.075368 c 0,-0.621323 0.6213237,-1.242647 1.2426477,-0.621323 0,0 0.6213228,0.621323 0.6213228,2.485294 0,1.863971 -0.6213228,2.485294 -0.6213228,2.485294 -0.621324,0.621324 -1.2426477,0 -1.2426477,-0.621323 0,0 0.6213237,-0.621324 0.6213237,-1.863971 0,-1.242648 -0.6213237,-1.863971 -0.6213237,-1.863971 z"
+ id="path4760-1-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 9.2959563,24.832721 c 0,-0.621324 0.6213228,-1.242647 1.2426477,-0.621324 0,0 1.242646,1.242648 1.242646,3.727942 0,2.485294 -1.242646,3.727941 -1.242646,3.727941 -0.6213249,0.621324 -1.2426477,0 -1.2426477,-0.621323 0,0 1.2426477,-1.242647 1.2426477,-3.106618 0,-1.863971 -1.2426477,-3.106618 -1.2426477,-3.106618 z"
+ id="path4762-8-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccsccsc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+ d="m 2.4916056,40.000004 0,0.621323 8.0979164,0 0,-0.621323 z"
+ id="path4772-4"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+ d="m 2.4916056,48.000004 8.0979164,0 0,-0.621324 -8.0979164,0 z"
+ id="path4774-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+ d="m 2.4916056,41.919118 0,0.621323 1.8687499,0 0,-0.621323 z m 6.2291665,0 0,0.621323 1.8687499,0 0,-0.621323 z"
+ id="path4782-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+ d="m 2.4916056,45.589344 0,0.621322 1.8687499,0 0,-0.621322 z m 6.2291665,0 0,0.621322 1.8687499,0 0,-0.621322 z"
+ id="path4778-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:0.99215686;stroke:none;display:inline"
+ d="m 2.4916056,44.404412 8.0979164,0 0,-0.621323 -8.0979164,0 z"
+ id="path4780-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 4.3603555,43.472427 0,1.242647 4.3604166,0 0,-1.242647 z"
+ id="path4793-0"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 4,40.000004 0,8 5,0 0,-8 z m 1,1 3,0 0,6 -3,0 z"
+ id="path4768-5"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 2,39.000004 1,0 0,10 -1,0 z"
+ id="path4764-1"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 10,39.000004 1,0 0,10 -1,0 z"
+ id="path4766-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="M 1.8400738,58.055766 6.5000005,62.405031 11.159927,58.055766 10.538604,57.434442 9.2959563,58.056049 6.5000005,60.541343 3.7040445,58.056049 2.4613977,57.434442 z"
+ id="path4800-4-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccc"
+ inkscape:export-filename="/home/rahah/elvidishu/steak/unreal/dev/skins/external link icons/mail.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 1,57.000008 0,8 11,0 0,-8 z m 1,1 9,0 0,6 -9,0 z"
+ id="path4795-8-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccc"
+ inkscape:export-filename="/home/rahah/elvidishu/steak/unreal/dev/skins/external link icons/mail.png"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="M 1.6213238,72.000004 1,72.621328 l 0,5.757352 0.6213238,0.621324 1.6894529,0 L 2.6894528,81.727943 7,79.000004 l 4.378677,0 L 12,78.37868 12,72.621328 11.378677,72.000004 z m 0.3786762,1 9,0 0,5 -4,0 L 4.0978858,79.896603 5,78.000004 l -3,0 z"
+ id="path4802-8-9"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 5,88.000004 7,0 0,7 -2,-2 -3,2 0,-1 3,-2.249999 1,1 0,-3.750001 -3.75,0 1,1 -2.25,3 -1,0 2,-3 z"
+ id="path4807-5-6"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 7,90.000004 -5,0 0,8 8,0 0,-5 -1,0 0,4 -6,0 0,-6 4,0 z"
+ id="path4809-7-3"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 7.5,105.00001 0,3 2.5,0 1,-1 -2.5,0 0,-3 z"
+ id="path4818-67-7"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccc" />
+ <path
+ style="fill:#3366bb;fill-opacity:1;stroke:none;display:inline"
+ d="m 3,104 0,10 8,1e-5 0,-7 -2.5,-3 z m 1,1 4,1e-5 2,2.50001 0,5.49999 -6,0 z"
+ id="path4813-2-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccc" />
+ <path
+ style="fill:#15a5ea;fill-opacity:1;stroke:none;display:inline"
+ d="m 4.0827206,92.533089 c 0,-0.621319 0.6213239,-0.621319 0.6213239,-0.621319 1.8639706,0.621319 3.1066175,1.863968 3.7279413,3.727935 0,0 0,0.621328 -0.6213238,0.621328 C 6.5680151,94.397065 5.9466913,93.775738 4.0827206,92.533089 z"
+ id="path4822-8-2"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3465ba;fill-opacity:1;stroke:none;display:inline"
+ d="m 1,8.500006 0,7.5001 1,-0.9872 0,-6.0129 2,0 2,1 4,-2e-4 0,2.0002 1,0 0,-2.5 -0.5,-0.5002 -4.5,2e-4 -2,-1 -2.5,0 z"
+ id="path3209"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccccccccccccc" />
+ <path
+ style="fill:#16a4e8;fill-opacity:1;stroke:none;display:inline"
+ d="m 6,11.000106 -1,-10e-5 -2.5,0 -0.5,0.5 -1,4.5001 10,-10e-5 0,-4.4998 -0.5,-0.5 z m 0,1 4,-10e-5 0,3 -7.75,-1e-4 0.75,-3.0001 2,0 z"
+ id="path3215"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cccccccccccccccc" />
+ <path
+ style="fill:#3465ba;fill-opacity:1;stroke:none;display:inline"
+ d="m 2,17.000006 0,1 8,0 0,-1 z"
+ id="path3247"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ <path
+ style="fill:#3465ba;fill-opacity:1;stroke:none;display:inline"
+ d="m 5,15.500006 0,2 2,0 0,-2 c 0,-0.5 -2,-0.5 -2,0 z"
+ id="path3249"
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="ccccc" />
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/external-ltr.png b/www/wiki/resources/src/mediawiki.skinning/images/external-ltr.png
new file mode 100644
index 00000000..c0f64dc5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/external-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/external-ltr.svg b/www/wiki/resources/src/mediawiki.skinning/images/external-ltr.svg
new file mode 100644
index 00000000..e914b7da
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/external-ltr.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m41.47,259.4,7,0,0,7-2-2-3,2,0-1,3-2.25,1,1,0-3.75-3.75,0,1,1-2.25,3-1,0,2-3z"/>
+<path style="opacity:1;fill:#3366bb;" d="m43.47,261.4-5,0,0,8,8,0,0-5-1,0,0,4-6,0,0-6,4,0z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m40.55,263.9c0-0.6213,0.6213-0.6213,0.6213-0.6213,1.864,0.6213,3.107,1.864,3.728,3.728,0,0,0,0.6213-0.6213,0.6213-1.243-1.864-1.864-2.485-3.728-3.728z"/>
+</g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/external-rtl.png b/www/wiki/resources/src/mediawiki.skinning/images/external-rtl.png
new file mode 100644
index 00000000..feea1151
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/external-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/external-rtl.svg b/www/wiki/resources/src/mediawiki.skinning/images/external-rtl.svg
new file mode 100644
index 00000000..698c6163
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/external-rtl.svg
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.467808,-258.39005)">
+<path style="opacity:1;fill:#3366bb;" d="m44.47,259.4-7,0,0,7,2-2,3,2,0-1-3-2.25-1,1,0-3.75,3.75,0-1,1,2.25,3,1,0-2-3z"/>
+<path style="opacity:1;fill:#3366bb;" d="m42.47,261.4,5,0,0,8-8,0,0-5,1,0,0,4,6,0,0-6-4,0z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m45.39,263.9c0-0.6213-0.6213-0.6213-0.6213-0.6213-1.864,0.6213-3.107,1.864-3.728,3.728l0.6213,0.6213c1.243-1.864,1.864-2.485,3.728-3.728z"/>
+</g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/ftp-ltr.png b/www/wiki/resources/src/mediawiki.skinning/images/ftp-ltr.png
new file mode 100644
index 00000000..0052cf22
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/ftp-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/ftp-ltr.svg b/www/wiki/resources/src/mediawiki.skinning/images/ftp-ltr.svg
new file mode 100644
index 00000000..3a90c311
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/ftp-ltr.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-136.35715,-374.43362)">
+<path style="opacity:1;fill:#3465ba;" d="m137.4,376.9,0,7.5,1-0.9872,0-6.013,2,0,2,1,4-0.0002,0,2,1,0,0-2.5-0.5-0.5002-4.5,0.0002-2-1-2.5,0z"/>
+<path style="opacity:1;fill:#16a4e8;" d="m142.4,379.4-1-0.0001-2.5,0-0.5,0.5-1,4.5,10-0.0001,0-4.5-0.5-0.5zm0,1,4-0.0001,0,3-7.75-0.0001,0.75-3,2,0z"/>
+<path style="opacity:1;fill:#3465ba;" d="m138.4,385.4,0,1,8,0,0-1z"/>
+<path style="opacity:1;fill:#3465ba;" d="m141.4,383.9,0,2,2,0,0-2c0-0.5-2-0.5-2,0z"/>
+</g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/ftp-rtl.png b/www/wiki/resources/src/mediawiki.skinning/images/ftp-rtl.png
new file mode 100644
index 00000000..f5620311
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/ftp-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/ftp-rtl.svg b/www/wiki/resources/src/mediawiki.skinning/images/ftp-rtl.svg
new file mode 100644
index 00000000..29e4b445
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/ftp-rtl.svg
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-136.35715,-374.43362)">
+<path style="opacity:1;fill:#3465ba;" d="m148.4,376.9,0,7.5-1-0.9872,0-6.013-2,0-2,1-4-0.0002,0,2-1,0,0-2.5,0.5-0.5002,4.5,0.0002,2-1,2.5,0z"/>
+<path style="opacity:1;fill:#16a4e8;" d="m143.4,379.4,1-0.0001,2.5,0,0.5,0.5,1,4.5-10-0.0001,0-4.5,0.5-0.5zm0,1-4-0.0001,0,3,7.75-0.0001-0.75-3-2,0z"/>
+<path style="opacity:1;fill:#3465ba;" d="m147.4,385.4,0,1-8,0,0-1z"/>
+<path style="opacity:1;fill:#3465ba;" d="m144.4,383.9,0,2-2,0,0-2c0-0.5,2-0.5,2,0z"/>
+</g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-ltr.png b/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-ltr.png
new file mode 100644
index 00000000..2704514e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-ltr.svg b/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-ltr.svg
new file mode 100644
index 00000000..4d3dcb65
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-ltr.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11 15" width="15" height="11">
+ <g id="magnify-clip" fill="#fff" stroke="#000">
+ <path id="bigbox" d="M1.509 1.865h10.99v7.919h-10.99z"/>
+ <path id="smallbox" d="M-1.499 6.868h5.943v4.904h-5.943z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-rtl.png b/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-rtl.png
new file mode 100644
index 00000000..c8b26455
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-rtl.svg b/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-rtl.svg
new file mode 100644
index 00000000..582e4ae7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/magnify-clip-rtl.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 11 15" width="15" height="11">
+ <g id="magnify-clip" fill="#fff" stroke="#000">
+ <path id="bigbox" d="M9.491 1.865h-10.99v7.919h10.99z"/>
+ <path id="smallbox" d="M12.499 6.868h-5.943v4.904h5.943z"/>
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/mail.png b/www/wiki/resources/src/mediawiki.skinning/images/mail.png
new file mode 100644
index 00000000..fbab74aa
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/mail.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/mail.svg b/www/wiki/resources/src/mediawiki.skinning/images/mail.svg
new file mode 100644
index 00000000..5e534fed
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/mail.svg
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.47,-257.4)">
+<path style="fill:#15a5ea;" d="m38.31,261.4,4.66,4.349,4.66-4.349-0.6213-0.6213-1.243,0.6216-2.796,2.485-2.796-2.485-1.243-0.6216z"/>
+<path style="fill:#3366bb;" d="m37.47,260.4,0,8,11,0,0-8zm1,1,9,0,0,6-9,0z"/>
+</g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/video.png b/www/wiki/resources/src/mediawiki.skinning/images/video.png
new file mode 100644
index 00000000..b81f8982
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/video.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.skinning/images/video.svg b/www/wiki/resources/src/mediawiki.skinning/images/video.svg
new file mode 100644
index 00000000..d52d0db1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/images/video.svg
@@ -0,0 +1,14 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" height="13" width="13" version="1.1" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
+<g transform="translate(-36.4678,-258.39)">
+<path style="opacity:1;fill-opacity:1;fill:#15a5ea;" d="m38.96,260.4,0,0.6213,8.098,0,0-0.6213z"/>
+<path style="opacity:1;fill-opacity:1;fill:#15a5ea;" d="m38.96,268.4,8.098,0,0-0.6213-8.098,0z"/>
+<path style="opacity:1;fill-opacity:1;fill:#15a5ea;" d="m38.96,262.3,0,0.6213,1.869,0,0-0.6213zm6.229,0,0,0.6213,1.869,0,0-0.6213z"/>
+<path style="opacity:1;fill-opacity:1;fill:#15a5ea;" d="m38.96,266,0,0.6213,1.869,0,0-0.6213zm6.229,0,0,0.6213,1.869,0,0-0.6213z"/>
+<path style="opacity:1;fill-opacity:1;fill:#15a5ea;" d="m38.96,264.8,8.098,0,0-0.6213-8.098,0z"/>
+<path style="opacity:1;fill:#15a5ea;" d="m40.83,263.9,0,1.243,4.36,0,0-1.243z"/>
+<path style="opacity:1;fill:#3366bb;" d="m40.47,260.4,0,8,5,0,0-8zm1,1,3,0,0,6-3,0z"/>
+<path style="opacity:1;fill:#3366bb;" d="m38.47,259.4,1,0,0,10-1,0z"/>
+<path style="opacity:1;fill:#3366bb;" d="m46.47,259.4,1,0,0,10-1,0z"/>
+</g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki.skinning/interface.css b/www/wiki/resources/src/mediawiki.skinning/interface.css
new file mode 100644
index 00000000..3e0d2b94
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.skinning/interface.css
@@ -0,0 +1,81 @@
+/**
+ * MediaWiki style sheet for common core styles on interfaces
+ *
+ * Styles for the Monobook/Vector pattern of laying out common interfaces.
+ * These ids/classes are not built into the system,
+ * they are outputted by the actual MonoBook/Vector code by convention.
+ */
+
+/* Categories */
+.catlinks {
+ border: 1px solid #a2a9b1;
+ background-color: #f8f9fa;
+ padding: 5px;
+ margin-top: 1em;
+ clear: both;
+}
+
+textarea {
+ /* Support Firefox: Border rule required to override system appearance on Linux */
+ border: 1px solid #a2a9b1;
+}
+
+.editOptions {
+ background-color: #eaecf0;
+ border: 1px solid #c8ccd1;
+ border-top: 0;
+ padding: 1em 1em 1.5em 1em;
+ margin-bottom: 2em;
+}
+
+.usermessage {
+ background-color: #ffce7b;
+ border: 1px solid #ffa500;
+ color: #000;
+ font-weight: bold;
+ margin: 2em 0 1em;
+ padding: 0.5em 1em;
+ vertical-align: middle;
+}
+
+#siteNotice {
+ position: relative;
+ text-align: center;
+ margin: 0;
+}
+
+#localNotice {
+ margin-bottom: 0.9em;
+}
+
+.firstHeading {
+ margin-bottom: 0.1em;
+ /* These two rules hack around T4013 (fix for more limited T13325).
+ * When T4013 is fixed properly, they should be removed. */
+ line-height: 1.2em;
+ padding-bottom: 0;
+}
+
+/* Sub-navigation */
+#siteSub {
+ display: none;
+}
+
+#jump-to-nav {
+ /* Negate #contentSub's margin and replicate it so that the jump to links don't affect the spacing */
+ margin-top: -1.4em;
+ margin-bottom: 1.4em;
+}
+
+#contentSub,
+#contentSub2 {
+ font-size: 84%;
+ line-height: 1.2em;
+ margin: 0 0 1.4em 1em;
+ color: #54595d;
+ width: auto;
+}
+
+span.subpages {
+ display: block;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/images/glyph-people-large.png b/www/wiki/resources/src/mediawiki.special/images/glyph-people-large.png
new file mode 100644
index 00000000..cba3cafb
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/images/glyph-people-large.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.special/images/icon-contributors.png b/www/wiki/resources/src/mediawiki.special/images/icon-contributors.png
new file mode 100644
index 00000000..30bf53a8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/images/icon-contributors.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.special/images/icon-edits.png b/www/wiki/resources/src/mediawiki.special/images/icon-edits.png
new file mode 100644
index 00000000..17508f9f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/images/icon-edits.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.special/images/icon-lock.png b/www/wiki/resources/src/mediawiki.special/images/icon-lock.png
new file mode 100644
index 00000000..03f0eecd
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/images/icon-lock.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.special/images/icon-pages.png b/www/wiki/resources/src/mediawiki.special/images/icon-pages.png
new file mode 100644
index 00000000..8e37278b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/images/icon-pages.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.css
new file mode 100644
index 00000000..750a567f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.css
@@ -0,0 +1,109 @@
+.mw-apisandbox-fullscreen {
+ overflow: hidden;
+}
+
+.mw-apisandbox-toolbar {
+ text-align: right;
+ padding: 0.5em;
+}
+
+.mw-apisandbox-popup .oo-ui-popupWidget-body > .oo-ui-widget {
+ vertical-align: middle;
+}
+
+/* So DateTimeInputWidget's calendar popup works... */
+.mw-apisandbox-popup .oo-ui-popupWidget-popup,
+.mw-apisandbox-popup .oo-ui-popupWidget-body {
+ overflow: visible;
+}
+
+.mw-apisandbox-fullscreen #mw-apisandbox-ui {
+ position: fixed;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ right: 0;
+ background: #fff;
+ z-index: 100;
+}
+
+.mw-apisandbox-fullscreen .mw-apisandbox-container {
+ border-width: 1px 0 0 0;
+ border-radius: 0;
+}
+
+.mw-apisandbox-spacer {
+ display: inline-block;
+ height: 1px;
+ width: 5em;
+}
+
+.mw-apisandbox-help-field {
+ border-bottom: 1px solid rgba( 0, 0, 0, 0.1 );
+}
+
+.mw-apisandbox-help-field:last-child {
+ border-bottom: 0;
+}
+
+.mw-apisandbox-optionalWidget {
+ width: 100%;
+}
+
+.mw-apisandbox-optionalWidget.oo-ui-widget-disabled {
+ position: relative;
+ z-index: 0; /* New stacking context to prevent the overlay from leaking out */
+}
+
+.mw-apisandbox-optionalWidget-overlay {
+ position: absolute;
+ left: 0;
+ right: 0;
+ top: 0;
+ bottom: 0;
+ z-index: 2;
+ cursor: pointer;
+}
+
+.mw-apisandbox-optionalWidget-fields {
+ display: table;
+ width: 100%;
+}
+
+.mw-apisandbox-optionalWidget-widget,
+.mw-apisandbox-optionalWidget-checkbox {
+ display: table-cell;
+ vertical-align: middle;
+}
+
+.mw-apisandbox-optionalWidget-checkbox {
+ width: 1%; /* Will be expanded by content */
+ white-space: nowrap;
+ padding-left: 0.5em;
+}
+
+.oo-ui-textInputWidget.oo-ui-widget-enabled > .oo-ui-indicatorElement-indicator.mw-apisandbox-clickable-indicator {
+ cursor: pointer;
+}
+
+.mw-apisandbox-textInputCode .oo-ui-inputWidget-input {
+ font-family: monospace, monospace;
+ font-size: 0.8125em;
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+}
+
+.mw-apisandbox-widget-field .oo-ui-textInputWidget {
+ /* Leave at least enough space for icon, indicator, and a sliver of text */
+ min-width: 6em;
+}
+
+.apihelp-deprecated {
+ font-weight: bold;
+ color: #d33;
+}
+
+.apihelp-deprecated-value .oo-ui-labelElement-label {
+ text-decoration: line-through;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.js
new file mode 100644
index 00000000..7e9ad7f6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.js
@@ -0,0 +1,1953 @@
+/* eslint-disable no-use-before-define */
+( function ( $, mw, OO ) {
+ 'use strict';
+ var ApiSandbox, Util, WidgetMethods, Validators,
+ $content, panel, booklet, oldhash, windowManager, fullscreenButton,
+ formatDropdown,
+ api = new mw.Api(),
+ bookletPages = [],
+ availableFormats = {},
+ resultPage = null,
+ suppressErrors = true,
+ updatingBooklet = false,
+ pages = {},
+ moduleInfoCache = {},
+ baseRequestParams;
+
+ WidgetMethods = {
+ textInputWidget: {
+ getApiValue: function () {
+ return this.getValue();
+ },
+ setApiValue: function ( v ) {
+ if ( v === undefined ) {
+ v = this.paramInfo[ 'default' ];
+ }
+ this.setValue( v );
+ },
+ apiCheckValid: function () {
+ var that = this;
+ return this.getValidity().then( function () {
+ return $.Deferred().resolve( true ).promise();
+ }, function () {
+ return $.Deferred().resolve( false ).promise();
+ } ).done( function ( ok ) {
+ ok = ok || suppressErrors;
+ that.setIcon( ok ? null : 'alert' );
+ that.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() );
+ } );
+ }
+ },
+
+ dateTimeInputWidget: {
+ getValidity: function () {
+ if ( !Util.apiBool( this.paramInfo.required ) || this.getApiValue() !== '' ) {
+ return $.Deferred().resolve().promise();
+ } else {
+ return $.Deferred().reject().promise();
+ }
+ }
+ },
+
+ tokenWidget: {
+ alertTokenError: function ( code, error ) {
+ windowManager.openWindow( 'errorAlert', {
+ title: Util.parseMsg( 'apisandbox-results-fixtoken-fail', this.paramInfo.tokentype ),
+ message: error,
+ actions: [
+ {
+ action: 'accept',
+ label: OO.ui.msg( 'ooui-dialog-process-dismiss' ),
+ flags: 'primary'
+ }
+ ]
+ } );
+ },
+ fetchToken: function () {
+ this.pushPending();
+ return api.getToken( this.paramInfo.tokentype )
+ .done( this.setApiValue.bind( this ) )
+ .fail( this.alertTokenError.bind( this ) )
+ .always( this.popPending.bind( this ) );
+ },
+ setApiValue: function ( v ) {
+ WidgetMethods.textInputWidget.setApiValue.call( this, v );
+ if ( v === '123ABC' ) {
+ this.fetchToken();
+ }
+ }
+ },
+
+ passwordWidget: {
+ getApiValueForDisplay: function () {
+ return '';
+ }
+ },
+
+ toggleSwitchWidget: {
+ getApiValue: function () {
+ return this.getValue() ? 1 : undefined;
+ },
+ setApiValue: function ( v ) {
+ this.setValue( Util.apiBool( v ) );
+ },
+ apiCheckValid: function () {
+ return $.Deferred().resolve( true ).promise();
+ }
+ },
+
+ dropdownWidget: {
+ getApiValue: function () {
+ var item = this.getMenu().getSelectedItem();
+ return item === null ? undefined : item.getData();
+ },
+ setApiValue: function ( v ) {
+ var menu = this.getMenu();
+
+ if ( v === undefined ) {
+ v = this.paramInfo[ 'default' ];
+ }
+ if ( v === undefined ) {
+ menu.selectItem();
+ } else {
+ menu.selectItemByData( String( v ) );
+ }
+ },
+ apiCheckValid: function () {
+ var ok = this.getApiValue() !== undefined || suppressErrors;
+ this.setIcon( ok ? null : 'alert' );
+ this.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() );
+ return $.Deferred().resolve( ok ).promise();
+ }
+ },
+
+ capsuleWidget: {
+ getApiValue: function () {
+ var items = this.getItemsData();
+ if ( items.join( '' ).indexOf( '|' ) === -1 ) {
+ return items.join( '|' );
+ } else {
+ return '\x1f' + items.join( '\x1f' );
+ }
+ },
+ setApiValue: function ( v ) {
+ if ( v === undefined || v === '' || v === '\x1f' ) {
+ this.setItemsFromData( [] );
+ } else {
+ v = String( v );
+ if ( v.indexOf( '\x1f' ) !== 0 ) {
+ this.setItemsFromData( v.split( '|' ) );
+ } else {
+ this.setItemsFromData( v.substr( 1 ).split( '\x1f' ) );
+ }
+ }
+ },
+ apiCheckValid: function () {
+ var ok = true,
+ pi = this.paramInfo;
+
+ if ( !suppressErrors ) {
+ ok = this.getApiValue() !== undefined && !(
+ pi.allspecifier !== undefined &&
+ this.getItemsData().length > 1 &&
+ this.getItemsData().indexOf( pi.allspecifier ) !== -1
+ );
+ }
+
+ this.setIcon( ok ? null : 'alert' );
+ this.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() );
+ return $.Deferred().resolve( ok ).promise();
+ },
+ createItemWidget: function ( data, label ) {
+ var item = OO.ui.CapsuleMultiselectWidget.prototype.createItemWidget.call( this, data, label );
+ if ( this.paramInfo.deprecatedvalues &&
+ this.paramInfo.deprecatedvalues.indexOf( data ) >= 0
+ ) {
+ item.$element.addClass( 'apihelp-deprecated-value' );
+ }
+ return item;
+ }
+ },
+
+ optionalWidget: {
+ getApiValue: function () {
+ return this.isDisabled() ? undefined : this.widget.getApiValue();
+ },
+ setApiValue: function ( v ) {
+ this.setDisabled( v === undefined );
+ this.widget.setApiValue( v );
+ },
+ apiCheckValid: function () {
+ if ( this.isDisabled() ) {
+ return $.Deferred().resolve( true ).promise();
+ } else {
+ return this.widget.apiCheckValid();
+ }
+ }
+ },
+
+ submoduleWidget: {
+ single: function () {
+ var v = this.isDisabled() ? this.paramInfo[ 'default' ] : this.getApiValue();
+ return v === undefined ? [] : [ { value: v, path: this.paramInfo.submodules[ v ] } ];
+ },
+ multi: function () {
+ var map = this.paramInfo.submodules,
+ v = this.isDisabled() ? this.paramInfo[ 'default' ] : this.getApiValue();
+ return v === undefined || v === '' ? [] : $.map( String( v ).split( '|' ), function ( v ) {
+ return { value: v, path: map[ v ] };
+ } );
+ }
+ },
+
+ uploadWidget: {
+ getApiValueForDisplay: function () {
+ return '...';
+ },
+ getApiValue: function () {
+ return this.getValue();
+ },
+ setApiValue: function () {
+ // Can't, sorry.
+ },
+ apiCheckValid: function () {
+ var ok = this.getValue() !== null || suppressErrors;
+ this.setIcon( ok ? null : 'alert' );
+ this.setIconTitle( ok ? '' : mw.message( 'apisandbox-alert-field' ).plain() );
+ return $.Deferred().resolve( ok ).promise();
+ }
+ }
+ };
+
+ Validators = {
+ generic: function () {
+ return !Util.apiBool( this.paramInfo.required ) || this.getApiValue() !== '';
+ }
+ };
+
+ /**
+ * @class mw.special.ApiSandbox.Util
+ * @private
+ */
+ Util = {
+ /**
+ * Fetch API module info
+ *
+ * @param {string} module Module to fetch data for
+ * @return {jQuery.Promise}
+ */
+ fetchModuleInfo: function ( module ) {
+ var apiPromise,
+ deferred = $.Deferred();
+
+ if ( moduleInfoCache.hasOwnProperty( module ) ) {
+ return deferred
+ .resolve( moduleInfoCache[ module ] )
+ .promise( { abort: function () {} } );
+ } else {
+ apiPromise = api.post( {
+ action: 'paraminfo',
+ modules: module,
+ helpformat: 'html',
+ uselang: mw.config.get( 'wgUserLanguage' )
+ } ).done( function ( data ) {
+ var info;
+
+ if ( data.warnings && data.warnings.paraminfo ) {
+ deferred.reject( '???', data.warnings.paraminfo[ '*' ] );
+ return;
+ }
+
+ info = data.paraminfo.modules;
+ if ( !info || info.length !== 1 || info[ 0 ].path !== module ) {
+ deferred.reject( '???', 'No module data returned' );
+ return;
+ }
+
+ moduleInfoCache[ module ] = info[ 0 ];
+ deferred.resolve( info[ 0 ] );
+ } ).fail( function ( code, details ) {
+ if ( code === 'http' ) {
+ details = 'HTTP error: ' + details.exception;
+ } else if ( details.error ) {
+ details = details.error.info;
+ }
+ deferred.reject( code, details );
+ } );
+ return deferred
+ .promise( { abort: apiPromise.abort } );
+ }
+ },
+
+ /**
+ * Mark all currently-in-use tokens as bad
+ */
+ markTokensBad: function () {
+ var page, subpages, i,
+ checkPages = [ pages.main ];
+
+ while ( checkPages.length ) {
+ page = checkPages.shift();
+
+ if ( page.tokenWidget ) {
+ api.badToken( page.tokenWidget.paramInfo.tokentype );
+ }
+
+ subpages = page.getSubpages();
+ for ( i = 0; i < subpages.length; i++ ) {
+ if ( pages.hasOwnProperty( subpages[ i ].key ) ) {
+ checkPages.push( pages[ subpages[ i ].key ] );
+ }
+ }
+ }
+ },
+
+ /**
+ * Test an API boolean
+ *
+ * @param {Mixed} value
+ * @return {boolean}
+ */
+ apiBool: function ( value ) {
+ return value !== undefined && value !== false;
+ },
+
+ /**
+ * Create a widget for a parameter.
+ *
+ * @param {Object} pi Parameter info from API
+ * @param {Object} opts Additional options
+ * @return {OO.ui.Widget}
+ */
+ createWidgetForParameter: function ( pi, opts ) {
+ var widget, innerWidget, finalWidget, items, $button, $content, func,
+ multiMode = 'none';
+
+ opts = opts || {};
+
+ switch ( pi.type ) {
+ case 'boolean':
+ widget = new OO.ui.ToggleSwitchWidget();
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.toggleSwitchWidget );
+ pi.required = true; // Avoid wrapping in the non-required widget
+ break;
+
+ case 'string':
+ case 'user':
+ if ( pi.tokentype ) {
+ widget = new TextInputWithIndicatorWidget( {
+ input: {
+ indicator: 'previous',
+ indicatorTitle: mw.message( 'apisandbox-fetch-token' ).text(),
+ required: Util.apiBool( pi.required )
+ }
+ } );
+ } else if ( Util.apiBool( pi.multi ) ) {
+ widget = new OO.ui.CapsuleMultiselectWidget( {
+ allowArbitrary: true,
+ allowDuplicates: Util.apiBool( pi.allowsduplicates ),
+ $overlay: $( '#mw-apisandbox-ui' )
+ } );
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.capsuleWidget );
+ } else {
+ widget = new OO.ui.TextInputWidget( {
+ required: Util.apiBool( pi.required )
+ } );
+ }
+ if ( !Util.apiBool( pi.multi ) ) {
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.textInputWidget );
+ widget.setValidation( Validators.generic );
+ }
+ if ( pi.tokentype ) {
+ $.extend( widget, WidgetMethods.tokenWidget );
+ widget.input.paramInfo = pi;
+ $.extend( widget.input, WidgetMethods.textInputWidget );
+ $.extend( widget.input, WidgetMethods.tokenWidget );
+ widget.on( 'indicator', widget.fetchToken, [], widget );
+ }
+ break;
+
+ case 'text':
+ widget = new OO.ui.MultilineTextInputWidget( {
+ required: Util.apiBool( pi.required )
+ } );
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.textInputWidget );
+ widget.setValidation( Validators.generic );
+ break;
+
+ case 'password':
+ widget = new OO.ui.TextInputWidget( {
+ type: 'password',
+ required: Util.apiBool( pi.required )
+ } );
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.textInputWidget );
+ $.extend( widget, WidgetMethods.passwordWidget );
+ widget.setValidation( Validators.generic );
+ multiMode = 'enter';
+ break;
+
+ case 'integer':
+ widget = new OO.ui.NumberInputWidget( {
+ required: Util.apiBool( pi.required ),
+ isInteger: true
+ } );
+ widget.setIcon = widget.input.setIcon.bind( widget.input );
+ widget.setIconTitle = widget.input.setIconTitle.bind( widget.input );
+ widget.getValidity = widget.input.getValidity.bind( widget.input );
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.textInputWidget );
+ if ( Util.apiBool( pi.enforcerange ) ) {
+ widget.setRange( pi.min || -Infinity, pi.max || Infinity );
+ }
+ multiMode = 'enter';
+ break;
+
+ case 'limit':
+ widget = new OO.ui.TextInputWidget( {
+ required: Util.apiBool( pi.required )
+ } );
+ widget.setValidation( function ( value ) {
+ var n, pi = this.paramInfo;
+
+ if ( value === 'max' ) {
+ return true;
+ } else {
+ n = +value;
+ return !isNaN( n ) && isFinite( n ) &&
+ Math.floor( n ) === n &&
+ n >= pi.min && n <= pi.apiSandboxMax;
+ }
+ } );
+ pi.min = pi.min || 0;
+ pi.apiSandboxMax = mw.config.get( 'apihighlimits' ) ? pi.highmax : pi.max;
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.textInputWidget );
+ multiMode = 'enter';
+ break;
+
+ case 'timestamp':
+ widget = new mw.widgets.datetime.DateTimeInputWidget( {
+ formatter: {
+ format: '${year|0}-${month|0}-${day|0}T${hour|0}:${minute|0}:${second|0}${zone|short}'
+ },
+ required: Util.apiBool( pi.required ),
+ clearable: false
+ } );
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.textInputWidget );
+ $.extend( widget, WidgetMethods.dateTimeInputWidget );
+ multiMode = 'indicator';
+ break;
+
+ case 'upload':
+ widget = new OO.ui.SelectFileWidget();
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.uploadWidget );
+ break;
+
+ case 'namespace':
+ items = $.map( mw.config.get( 'wgFormattedNamespaces' ), function ( name, ns ) {
+ if ( ns === '0' ) {
+ name = mw.message( 'blanknamespace' ).text();
+ }
+ return new OO.ui.MenuOptionWidget( { data: ns, label: name } );
+ } ).sort( function ( a, b ) {
+ return a.data - b.data;
+ } );
+ if ( Util.apiBool( pi.multi ) ) {
+ if ( pi.allspecifier !== undefined ) {
+ items.unshift( new OO.ui.MenuOptionWidget( {
+ data: pi.allspecifier,
+ label: mw.message( 'apisandbox-multivalue-all-namespaces', pi.allspecifier ).text()
+ } ) );
+ }
+
+ widget = new OO.ui.CapsuleMultiselectWidget( {
+ menu: { items: items },
+ $overlay: $( '#mw-apisandbox-ui' )
+ } );
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.capsuleWidget );
+ } else {
+ widget = new OO.ui.DropdownWidget( {
+ menu: { items: items },
+ $overlay: $( '#mw-apisandbox-ui' )
+ } );
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.dropdownWidget );
+ }
+ break;
+
+ default:
+ if ( !Array.isArray( pi.type ) ) {
+ throw new Error( 'Unknown parameter type ' + pi.type );
+ }
+
+ items = $.map( pi.type, function ( v ) {
+ var config = {
+ data: String( v ),
+ label: String( v ),
+ classes: []
+ };
+ if ( pi.deprecatedvalues && pi.deprecatedvalues.indexOf( v ) >= 0 ) {
+ config.classes.push( 'apihelp-deprecated-value' );
+ }
+ return new OO.ui.MenuOptionWidget( config );
+ } );
+ if ( Util.apiBool( pi.multi ) ) {
+ if ( pi.allspecifier !== undefined ) {
+ items.unshift( new OO.ui.MenuOptionWidget( {
+ data: pi.allspecifier,
+ label: mw.message( 'apisandbox-multivalue-all-values', pi.allspecifier ).text()
+ } ) );
+ }
+
+ widget = new OO.ui.CapsuleMultiselectWidget( {
+ menu: { items: items },
+ $overlay: $( '#mw-apisandbox-ui' )
+ } );
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.capsuleWidget );
+ if ( Util.apiBool( pi.submodules ) ) {
+ widget.getSubmodules = WidgetMethods.submoduleWidget.multi;
+ widget.on( 'change', ApiSandbox.updateUI );
+ }
+ } else {
+ widget = new OO.ui.DropdownWidget( {
+ menu: { items: items },
+ $overlay: $( '#mw-apisandbox-ui' )
+ } );
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.dropdownWidget );
+ if ( Util.apiBool( pi.submodules ) ) {
+ widget.getSubmodules = WidgetMethods.submoduleWidget.single;
+ widget.getMenu().on( 'select', ApiSandbox.updateUI );
+ }
+ if ( pi.deprecatedvalues ) {
+ widget.getMenu().on( 'select', function ( item ) {
+ this.$element.toggleClass(
+ 'apihelp-deprecated-value',
+ pi.deprecatedvalues.indexOf( item.data ) >= 0
+ );
+ }, [], widget );
+ }
+ }
+
+ break;
+ }
+
+ if ( Util.apiBool( pi.multi ) && multiMode !== 'none' ) {
+ innerWidget = widget;
+ switch ( multiMode ) {
+ case 'enter':
+ $content = innerWidget.$element;
+ break;
+
+ case 'indicator':
+ $button = innerWidget.$indicator;
+ $button.css( 'cursor', 'pointer' );
+ $button.attr( 'tabindex', 0 );
+ $button.parent().append( $button );
+ innerWidget.setIndicator( 'next' );
+ $content = innerWidget.$element;
+ break;
+
+ default:
+ throw new Error( 'Unknown multiMode "' + multiMode + '"' );
+ }
+
+ widget = new OO.ui.CapsuleMultiselectWidget( {
+ allowArbitrary: true,
+ allowDuplicates: Util.apiBool( pi.allowsduplicates ),
+ $overlay: $( '#mw-apisandbox-ui' ),
+ popup: {
+ classes: [ 'mw-apisandbox-popup' ],
+ $content: $content
+ }
+ } );
+ widget.paramInfo = pi;
+ $.extend( widget, WidgetMethods.capsuleWidget );
+
+ func = function () {
+ if ( !innerWidget.isDisabled() ) {
+ innerWidget.apiCheckValid().done( function ( ok ) {
+ if ( ok ) {
+ widget.addItemsFromData( [ innerWidget.getApiValue() ] );
+ innerWidget.setApiValue( undefined );
+ }
+ } );
+ return false;
+ }
+ };
+ switch ( multiMode ) {
+ case 'enter':
+ innerWidget.connect( null, { enter: func } );
+ break;
+
+ case 'indicator':
+ $button.on( {
+ click: func,
+ keypress: function ( e ) {
+ if ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) {
+ func();
+ }
+ }
+ } );
+ break;
+ }
+ }
+
+ if ( Util.apiBool( pi.required ) || opts.nooptional ) {
+ finalWidget = widget;
+ } else {
+ finalWidget = new OptionalWidget( widget );
+ finalWidget.paramInfo = pi;
+ $.extend( finalWidget, WidgetMethods.optionalWidget );
+ if ( widget.getSubmodules ) {
+ finalWidget.getSubmodules = widget.getSubmodules.bind( widget );
+ finalWidget.on( 'disable', function () { setTimeout( ApiSandbox.updateUI ); } );
+ }
+ finalWidget.setDisabled( true );
+ }
+
+ widget.setApiValue( pi[ 'default' ] );
+
+ return finalWidget;
+ },
+
+ /**
+ * Parse an HTML string and call Util.fixupHTML()
+ *
+ * @param {string} html HTML to parse
+ * @return {jQuery}
+ */
+ parseHTML: function ( html ) {
+ var $ret = $( $.parseHTML( html ) );
+ return Util.fixupHTML( $ret );
+ },
+
+ /**
+ * Parse an i18n message and call Util.fixupHTML()
+ *
+ * @param {string} key Key of message to get
+ * @param {...Mixed} parameters Values for $N replacements
+ * @return {jQuery}
+ */
+ parseMsg: function () {
+ var $ret = mw.message.apply( mw.message, arguments ).parseDom();
+ return Util.fixupHTML( $ret );
+ },
+
+ /**
+ * Fix HTML for ApiSandbox display
+ *
+ * Fixes are:
+ * - Add target="_blank" to any links
+ *
+ * @param {jQuery} $html DOM to process
+ * @return {jQuery}
+ */
+ fixupHTML: function ( $html ) {
+ $html.filter( 'a' ).add( $html.find( 'a' ) )
+ .filter( '[href]:not([target])' )
+ .attr( 'target', '_blank' );
+ return $html;
+ },
+
+ /**
+ * Format a request and return a bunch of menu option widgets
+ *
+ * @param {Object} displayParams Query parameters, sanitized for display.
+ * @param {Object} rawParams Query parameters. You should probably use displayParams instead.
+ * @return {OO.ui.MenuOptionWidget[]} Each item's data should be an OO.ui.FieldLayout
+ */
+ formatRequest: function ( displayParams, rawParams ) {
+ var jsonInput,
+ items = [
+ new OO.ui.MenuOptionWidget( {
+ label: Util.parseMsg( 'apisandbox-request-format-url-label' ),
+ data: new OO.ui.FieldLayout(
+ new OO.ui.TextInputWidget( {
+ readOnly: true,
+ value: mw.util.wikiScript( 'api' ) + '?' + $.param( displayParams )
+ } ), {
+ label: Util.parseMsg( 'apisandbox-request-url-label' )
+ }
+ )
+ } ),
+ new OO.ui.MenuOptionWidget( {
+ label: Util.parseMsg( 'apisandbox-request-format-json-label' ),
+ data: new OO.ui.FieldLayout(
+ jsonInput = new OO.ui.MultilineTextInputWidget( {
+ classes: [ 'mw-apisandbox-textInputCode' ],
+ readOnly: true,
+ autosize: true,
+ maxRows: 6,
+ value: JSON.stringify( displayParams, null, '\t' )
+ } ), {
+ label: Util.parseMsg( 'apisandbox-request-json-label' )
+ }
+ ).on( 'toggle', function ( visible ) {
+ if ( visible ) {
+ // Call updatePosition instead of adjustSize
+ // because the latter has weird caching
+ // behavior and the former bypasses it.
+ jsonInput.updatePosition();
+ }
+ } )
+ } )
+ ];
+
+ mw.hook( 'apisandbox.formatRequest' ).fire( items, displayParams, rawParams );
+
+ return items;
+ },
+
+ /**
+ * Event handler for when formatDropdown's selection changes
+ */
+ onFormatDropdownChange: function () {
+ var i,
+ menu = formatDropdown.getMenu(),
+ items = menu.getItems(),
+ selectedField = menu.getSelectedItem() ? menu.getSelectedItem().getData() : null;
+
+ for ( i = 0; i < items.length; i++ ) {
+ items[ i ].getData().toggle( items[ i ].getData() === selectedField );
+ }
+ }
+ };
+
+ /**
+ * Interface to ApiSandbox UI
+ *
+ * @class mw.special.ApiSandbox
+ */
+ ApiSandbox = {
+ /**
+ * Initialize the UI
+ *
+ * Automatically called on $.ready()
+ */
+ init: function () {
+ var $toolbar;
+
+ ApiSandbox.isFullscreen = false;
+
+ $content = $( '#mw-apisandbox' );
+
+ windowManager = new OO.ui.WindowManager();
+ $( 'body' ).append( windowManager.$element );
+ windowManager.addWindows( {
+ errorAlert: new OO.ui.MessageDialog()
+ } );
+
+ fullscreenButton = new OO.ui.ButtonWidget( {
+ label: mw.message( 'apisandbox-fullscreen' ).text(),
+ title: mw.message( 'apisandbox-fullscreen-tooltip' ).text()
+ } ).on( 'click', ApiSandbox.toggleFullscreen );
+
+ $toolbar = $( '<div>' )
+ .addClass( 'mw-apisandbox-toolbar' )
+ .append(
+ fullscreenButton.$element,
+ new OO.ui.ButtonWidget( {
+ label: mw.message( 'apisandbox-submit' ).text(),
+ flags: [ 'primary', 'progressive' ]
+ } ).on( 'click', ApiSandbox.sendRequest ).$element,
+ new OO.ui.ButtonWidget( {
+ label: mw.message( 'apisandbox-reset' ).text(),
+ flags: 'destructive'
+ } ).on( 'click', ApiSandbox.resetUI ).$element
+ );
+
+ booklet = new OO.ui.BookletLayout( {
+ outlined: true,
+ autoFocus: false
+ } );
+
+ panel = new OO.ui.PanelLayout( {
+ classes: [ 'mw-apisandbox-container' ],
+ content: [ booklet ],
+ expanded: false,
+ framed: true
+ } );
+
+ pages.main = new ApiSandbox.PageLayout( { key: 'main', path: 'main' } );
+
+ // Parse the current hash string
+ if ( !ApiSandbox.loadFromHash() ) {
+ ApiSandbox.updateUI();
+ }
+
+ // If the hashchange event exists, use it. Otherwise, fake it.
+ // And, of course, IE has to be dumb.
+ if ( 'onhashchange' in window &&
+ ( document.documentMode === undefined || document.documentMode >= 8 )
+ ) {
+ $( window ).on( 'hashchange', ApiSandbox.loadFromHash );
+ } else {
+ setInterval( function () {
+ if ( oldhash !== location.hash ) {
+ ApiSandbox.loadFromHash();
+ }
+ }, 1000 );
+ }
+
+ $content
+ .empty()
+ .append( $( '<p>' ).append( Util.parseMsg( 'apisandbox-intro' ) ) )
+ .append(
+ $( '<div>', { id: 'mw-apisandbox-ui' } )
+ .append( $toolbar )
+ .append( panel.$element )
+ );
+
+ $( window ).on( 'resize', ApiSandbox.resizePanel );
+
+ ApiSandbox.resizePanel();
+ },
+
+ /**
+ * Toggle "fullscreen" mode
+ */
+ toggleFullscreen: function () {
+ var $body = $( document.body ),
+ $ui = $( '#mw-apisandbox-ui' );
+
+ ApiSandbox.isFullscreen = !ApiSandbox.isFullscreen;
+
+ $body.toggleClass( 'mw-apisandbox-fullscreen', ApiSandbox.isFullscreen );
+ $ui.toggleClass( 'mw-body-content', ApiSandbox.isFullscreen );
+ if ( ApiSandbox.isFullscreen ) {
+ fullscreenButton.setLabel( mw.message( 'apisandbox-unfullscreen' ).text() );
+ fullscreenButton.setTitle( mw.message( 'apisandbox-unfullscreen-tooltip' ).text() );
+ $body.append( $ui );
+ } else {
+ fullscreenButton.setLabel( mw.message( 'apisandbox-fullscreen' ).text() );
+ fullscreenButton.setTitle( mw.message( 'apisandbox-fullscreen-tooltip' ).text() );
+ $content.append( $ui );
+ }
+ ApiSandbox.resizePanel();
+ },
+
+ /**
+ * Set the height of the panel based on the current viewport.
+ */
+ resizePanel: function () {
+ var height = $( window ).height(),
+ contentTop = $content.offset().top;
+
+ if ( ApiSandbox.isFullscreen ) {
+ height -= panel.$element.offset().top - $( '#mw-apisandbox-ui' ).offset().top;
+ panel.$element.height( height - 1 );
+ } else {
+ // Subtract the height of the intro text
+ height -= panel.$element.offset().top - contentTop;
+
+ panel.$element.height( height - 10 );
+ $( window ).scrollTop( contentTop - 5 );
+ }
+ },
+
+ /**
+ * Update the current query when the page hash changes
+ *
+ * @return {boolean} Successful
+ */
+ loadFromHash: function () {
+ var params, m, re,
+ hash = location.hash;
+
+ if ( oldhash === hash ) {
+ return false;
+ }
+ oldhash = hash;
+ if ( hash === '' ) {
+ return false;
+ }
+
+ // I'm surprised this doesn't seem to exist in jQuery or mw.util.
+ params = {};
+ hash = hash.replace( /\+/g, '%20' );
+ re = /([^&=#]+)=?([^&#]*)/g;
+ while ( ( m = re.exec( hash ) ) ) {
+ params[ decodeURIComponent( m[ 1 ] ) ] = decodeURIComponent( m[ 2 ] );
+ }
+
+ ApiSandbox.updateUI( params );
+ return true;
+ },
+
+ /**
+ * Update the pages in the booklet
+ *
+ * @param {Object} [params] Optional query parameters to load
+ */
+ updateUI: function ( params ) {
+ var i, page, subpages, j, removePages,
+ addPages = [];
+
+ if ( !$.isPlainObject( params ) ) {
+ params = undefined;
+ }
+
+ if ( updatingBooklet ) {
+ return;
+ }
+ updatingBooklet = true;
+ try {
+ if ( params !== undefined ) {
+ pages.main.loadQueryParams( params );
+ }
+ addPages.push( pages.main );
+ if ( resultPage !== null ) {
+ addPages.push( resultPage );
+ }
+ pages.main.apiCheckValid();
+
+ i = 0;
+ while ( addPages.length ) {
+ page = addPages.shift();
+ if ( bookletPages[ i ] !== page ) {
+ for ( j = i; j < bookletPages.length; j++ ) {
+ if ( bookletPages[ j ].getName() === page.getName() ) {
+ bookletPages.splice( j, 1 );
+ }
+ }
+ bookletPages.splice( i, 0, page );
+ booklet.addPages( [ page ], i );
+ }
+ i++;
+
+ if ( page.getSubpages ) {
+ subpages = page.getSubpages();
+ for ( j = 0; j < subpages.length; j++ ) {
+ if ( !pages.hasOwnProperty( subpages[ j ].key ) ) {
+ subpages[ j ].indentLevel = page.indentLevel + 1;
+ pages[ subpages[ j ].key ] = new ApiSandbox.PageLayout( subpages[ j ] );
+ }
+ if ( params !== undefined ) {
+ pages[ subpages[ j ].key ].loadQueryParams( params );
+ }
+ addPages.splice( j, 0, pages[ subpages[ j ].key ] );
+ pages[ subpages[ j ].key ].apiCheckValid();
+ }
+ }
+ }
+
+ if ( bookletPages.length > i ) {
+ removePages = bookletPages.splice( i, bookletPages.length - i );
+ booklet.removePages( removePages );
+ }
+
+ if ( !booklet.getCurrentPageName() ) {
+ booklet.selectFirstSelectablePage();
+ }
+ } finally {
+ updatingBooklet = false;
+ }
+ },
+
+ /**
+ * Reset button handler
+ */
+ resetUI: function () {
+ suppressErrors = true;
+ pages = {
+ main: new ApiSandbox.PageLayout( { key: 'main', path: 'main' } )
+ };
+ resultPage = null;
+ ApiSandbox.updateUI();
+ },
+
+ /**
+ * Submit button handler
+ *
+ * @param {Object} [params] Use this set of params instead of those in the form fields.
+ * The form fields will be updated to match.
+ */
+ sendRequest: function ( params ) {
+ var page, subpages, i, query, $result, $focus,
+ progress, $progressText, progressLoading,
+ deferreds = [],
+ paramsAreForced = !!params,
+ displayParams = {},
+ checkPages = [ pages.main ];
+
+ // Blur any focused widget before submit, because
+ // OO.ui.ButtonWidget doesn't take focus itself (T128054)
+ $focus = $( '#mw-apisandbox-ui' ).find( document.activeElement );
+ if ( $focus.length ) {
+ $focus[ 0 ].blur();
+ }
+
+ suppressErrors = false;
+
+ // save widget state in params (or load from it if we are forced)
+ if ( paramsAreForced ) {
+ ApiSandbox.updateUI( params );
+ }
+ params = {};
+ while ( checkPages.length ) {
+ page = checkPages.shift();
+ deferreds.push( page.apiCheckValid() );
+ page.getQueryParams( params, displayParams );
+ subpages = page.getSubpages();
+ for ( i = 0; i < subpages.length; i++ ) {
+ if ( pages.hasOwnProperty( subpages[ i ].key ) ) {
+ checkPages.push( pages[ subpages[ i ].key ] );
+ }
+ }
+ }
+
+ if ( !paramsAreForced ) {
+ // forced params means we are continuing a query; the base query should be preserved
+ baseRequestParams = $.extend( {}, params );
+ }
+
+ $.when.apply( $, deferreds ).done( function () {
+ var formatItems, menu, selectedLabel;
+
+ if ( $.inArray( false, arguments ) !== -1 ) {
+ windowManager.openWindow( 'errorAlert', {
+ title: Util.parseMsg( 'apisandbox-submit-invalid-fields-title' ),
+ message: Util.parseMsg( 'apisandbox-submit-invalid-fields-message' ),
+ actions: [
+ {
+ action: 'accept',
+ label: OO.ui.msg( 'ooui-dialog-process-dismiss' ),
+ flags: 'primary'
+ }
+ ]
+ } );
+ return;
+ }
+
+ query = $.param( displayParams );
+
+ formatItems = Util.formatRequest( displayParams, params );
+
+ // Force a 'fm' format with wrappedhtml=1, if available
+ if ( params.format !== undefined ) {
+ if ( availableFormats.hasOwnProperty( params.format + 'fm' ) ) {
+ params.format = params.format + 'fm';
+ }
+ if ( params.format.substr( -2 ) === 'fm' ) {
+ params.wrappedhtml = 1;
+ }
+ }
+
+ progressLoading = false;
+ $progressText = $( '<span>' ).text( mw.message( 'apisandbox-sending-request' ).text() );
+ progress = new OO.ui.ProgressBarWidget( {
+ progress: false,
+ $content: $progressText
+ } );
+
+ $result = $( '<div>' )
+ .append( progress.$element );
+
+ resultPage = page = new OO.ui.PageLayout( '|results|' );
+ page.setupOutlineItem = function () {
+ this.outlineItem.setLabel( mw.message( 'apisandbox-results' ).text() );
+ };
+
+ if ( !formatDropdown ) {
+ formatDropdown = new OO.ui.DropdownWidget( {
+ menu: { items: [] },
+ $overlay: $( '#mw-apisandbox-ui' )
+ } );
+ formatDropdown.getMenu().on( 'select', Util.onFormatDropdownChange );
+ }
+
+ menu = formatDropdown.getMenu();
+ selectedLabel = menu.getSelectedItem() ? menu.getSelectedItem().getLabel() : '';
+ if ( typeof selectedLabel !== 'string' ) {
+ selectedLabel = selectedLabel.text();
+ }
+ menu.clearItems().addItems( formatItems );
+ menu.chooseItem( menu.getItemFromLabel( selectedLabel ) || menu.getFirstSelectableItem() );
+
+ // Fire the event to update field visibilities
+ Util.onFormatDropdownChange();
+
+ page.$element.empty()
+ .append(
+ new OO.ui.FieldLayout(
+ formatDropdown, {
+ label: Util.parseMsg( 'apisandbox-request-selectformat-label' )
+ }
+ ).$element,
+ $.map( formatItems, function ( item ) {
+ return item.getData().$element;
+ } ),
+ $result
+ );
+ ApiSandbox.updateUI();
+ booklet.setPage( '|results|' );
+
+ location.href = oldhash = '#' + query;
+
+ api.post( params, {
+ contentType: 'multipart/form-data',
+ dataType: 'text',
+ xhr: function () {
+ var xhr = new window.XMLHttpRequest();
+ xhr.upload.addEventListener( 'progress', function ( e ) {
+ if ( !progressLoading ) {
+ if ( e.lengthComputable ) {
+ progress.setProgress( e.loaded * 100 / e.total );
+ } else {
+ progress.setProgress( false );
+ }
+ }
+ } );
+ xhr.addEventListener( 'progress', function ( e ) {
+ if ( !progressLoading ) {
+ progressLoading = true;
+ $progressText.text( mw.message( 'apisandbox-loading-results' ).text() );
+ }
+ if ( e.lengthComputable ) {
+ progress.setProgress( e.loaded * 100 / e.total );
+ } else {
+ progress.setProgress( false );
+ }
+ } );
+ return xhr;
+ }
+ } )
+ .then( null, function ( code, data, result, jqXHR ) {
+ var deferred = $.Deferred();
+
+ if ( code !== 'http' ) {
+ // Not really an error, work around mw.Api thinking it is.
+ deferred.resolve( result, jqXHR );
+ } else {
+ // Just forward it.
+ deferred.reject.apply( deferred, arguments );
+ }
+ return deferred.promise();
+ } )
+ .then( function ( data, jqXHR ) {
+ var m, loadTime, button, clear,
+ ct = jqXHR.getResponseHeader( 'Content-Type' ),
+ loginSuppressed = jqXHR.getResponseHeader( 'MediaWiki-Login-Suppressed' ) || 'false';
+
+ $result.empty();
+ if ( loginSuppressed !== 'false' ) {
+ $( '<div>' )
+ .addClass( 'warning' )
+ .append( Util.parseMsg( 'apisandbox-results-login-suppressed' ) )
+ .appendTo( $result );
+ }
+ if ( /^text\/mediawiki-api-prettyprint-wrapped(?:;|$)/.test( ct ) ) {
+ data = JSON.parse( data );
+ if ( data.modules.length ) {
+ mw.loader.load( data.modules );
+ }
+ if ( data.status && data.status !== 200 ) {
+ $( '<div>' )
+ .addClass( 'api-pretty-header api-pretty-status' )
+ .append( Util.parseMsg( 'api-format-prettyprint-status', data.status, data.statustext ) )
+ .appendTo( $result );
+ }
+ $result.append( Util.parseHTML( data.html ) );
+ loadTime = data.time;
+ } else if ( ( m = data.match( /<pre[ >][\s\S]*<\/pre>/ ) ) ) {
+ $result.append( Util.parseHTML( m[ 0 ] ) );
+ if ( ( m = data.match( /"wgBackendResponseTime":\s*(\d+)/ ) ) ) {
+ loadTime = parseInt( m[ 1 ], 10 );
+ }
+ } else {
+ $( '<pre>' )
+ .addClass( 'api-pretty-content' )
+ .text( data )
+ .appendTo( $result );
+ }
+ if ( paramsAreForced || data[ 'continue' ] ) {
+ $result.append(
+ $( '<div>' ).append(
+ new OO.ui.ButtonWidget( {
+ label: mw.message( 'apisandbox-continue' ).text()
+ } ).on( 'click', function () {
+ ApiSandbox.sendRequest( $.extend( {}, baseRequestParams, data[ 'continue' ] ) );
+ } ).setDisabled( !data[ 'continue' ] ).$element,
+ ( clear = new OO.ui.ButtonWidget( {
+ label: mw.message( 'apisandbox-continue-clear' ).text()
+ } ).on( 'click', function () {
+ ApiSandbox.updateUI( baseRequestParams );
+ clear.setDisabled( true );
+ booklet.setPage( '|results|' );
+ } ).setDisabled( !paramsAreForced ) ).$element,
+ new OO.ui.PopupButtonWidget( {
+ $overlay: $( '#mw-apisandbox-ui' ),
+ framed: false,
+ icon: 'info',
+ popup: {
+ $content: $( '<div>' ).append( Util.parseMsg( 'apisandbox-continue-help' ) ),
+ padded: true,
+ width: 'auto'
+ }
+ } ).$element
+ )
+ );
+ }
+ if ( typeof loadTime === 'number' ) {
+ $result.append(
+ $( '<div>' ).append(
+ new OO.ui.LabelWidget( {
+ label: mw.message( 'apisandbox-request-time', loadTime ).text()
+ } ).$element
+ )
+ );
+ }
+
+ if ( jqXHR.getResponseHeader( 'MediaWiki-API-Error' ) === 'badtoken' ) {
+ // Flush all saved tokens in case one of them is the bad one.
+ Util.markTokensBad();
+ button = new OO.ui.ButtonWidget( {
+ label: mw.message( 'apisandbox-results-fixtoken' ).text()
+ } );
+ button.on( 'click', ApiSandbox.fixTokenAndResend )
+ .on( 'click', button.setDisabled, [ true ], button )
+ .$element.appendTo( $result );
+ }
+ }, function ( code, data ) {
+ var details = 'HTTP error: ' + data.exception;
+ $result.empty()
+ .append(
+ new OO.ui.LabelWidget( {
+ label: mw.message( 'apisandbox-results-error', details ).text(),
+ classes: [ 'error' ]
+ } ).$element
+ );
+ } );
+ } );
+ },
+
+ /**
+ * Handler for the "Correct token and resubmit" button
+ *
+ * Used on a 'badtoken' error, it re-fetches token parameters for all
+ * pages and then re-submits the query.
+ */
+ fixTokenAndResend: function () {
+ var page, subpages, i, k,
+ ok = true,
+ tokenWait = { dummy: true },
+ checkPages = [ pages.main ],
+ success = function ( k ) {
+ delete tokenWait[ k ];
+ if ( ok && $.isEmptyObject( tokenWait ) ) {
+ ApiSandbox.sendRequest();
+ }
+ },
+ failure = function ( k ) {
+ delete tokenWait[ k ];
+ ok = false;
+ };
+
+ while ( checkPages.length ) {
+ page = checkPages.shift();
+
+ if ( page.tokenWidget ) {
+ k = page.apiModule + page.tokenWidget.paramInfo.name;
+ tokenWait[ k ] = page.tokenWidget.fetchToken();
+ tokenWait[ k ]
+ .done( success.bind( page.tokenWidget, k ) )
+ .fail( failure.bind( page.tokenWidget, k ) );
+ }
+
+ subpages = page.getSubpages();
+ for ( i = 0; i < subpages.length; i++ ) {
+ if ( pages.hasOwnProperty( subpages[ i ].key ) ) {
+ checkPages.push( pages[ subpages[ i ].key ] );
+ }
+ }
+ }
+
+ success( 'dummy', '' );
+ },
+
+ /**
+ * Reset validity indicators for all widgets
+ */
+ updateValidityIndicators: function () {
+ var page, subpages, i,
+ checkPages = [ pages.main ];
+
+ while ( checkPages.length ) {
+ page = checkPages.shift();
+ page.apiCheckValid();
+ subpages = page.getSubpages();
+ for ( i = 0; i < subpages.length; i++ ) {
+ if ( pages.hasOwnProperty( subpages[ i ].key ) ) {
+ checkPages.push( pages[ subpages[ i ].key ] );
+ }
+ }
+ }
+ }
+ };
+
+ /**
+ * PageLayout for API modules
+ *
+ * @class
+ * @private
+ * @extends OO.ui.PageLayout
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+ ApiSandbox.PageLayout = function ( config ) {
+ config = $.extend( { prefix: '' }, config );
+ this.displayText = config.key;
+ this.apiModule = config.path;
+ this.prefix = config.prefix;
+ this.paramInfo = null;
+ this.apiIsValid = true;
+ this.loadFromQueryParams = null;
+ this.widgets = {};
+ this.tokenWidget = null;
+ this.indentLevel = config.indentLevel ? config.indentLevel : 0;
+ ApiSandbox.PageLayout[ 'super' ].call( this, config.key, config );
+ this.loadParamInfo();
+ };
+ OO.inheritClass( ApiSandbox.PageLayout, OO.ui.PageLayout );
+ ApiSandbox.PageLayout.prototype.setupOutlineItem = function () {
+ this.outlineItem.setLevel( this.indentLevel );
+ this.outlineItem.setLabel( this.displayText );
+ this.outlineItem.setIcon( this.apiIsValid || suppressErrors ? null : 'alert' );
+ this.outlineItem.setIconTitle(
+ this.apiIsValid || suppressErrors ? '' : mw.message( 'apisandbox-alert-page' ).plain()
+ );
+ };
+
+ /**
+ * Fetch module information for this page's module, then create UI
+ */
+ ApiSandbox.PageLayout.prototype.loadParamInfo = function () {
+ var dynamicFieldset, dynamicParamNameWidget,
+ that = this,
+ removeDynamicParamWidget = function ( name, layout ) {
+ dynamicFieldset.removeItems( [ layout ] );
+ delete that.widgets[ name ];
+ },
+ addDynamicParamWidget = function () {
+ var name, layout, widget, button;
+
+ // Check name is filled in
+ name = dynamicParamNameWidget.getValue().trim();
+ if ( name === '' ) {
+ dynamicParamNameWidget.focus();
+ return;
+ }
+
+ if ( that.widgets[ name ] !== undefined ) {
+ windowManager.openWindow( 'errorAlert', {
+ title: Util.parseMsg( 'apisandbox-dynamic-error-exists', name ),
+ actions: [
+ {
+ action: 'accept',
+ label: OO.ui.msg( 'ooui-dialog-process-dismiss' ),
+ flags: 'primary'
+ }
+ ]
+ } );
+ return;
+ }
+
+ widget = Util.createWidgetForParameter( {
+ name: name,
+ type: 'string',
+ 'default': ''
+ }, {
+ nooptional: true
+ } );
+ button = new OO.ui.ButtonWidget( {
+ icon: 'trash',
+ flags: 'destructive'
+ } );
+ layout = new OO.ui.ActionFieldLayout(
+ widget,
+ button,
+ {
+ label: name,
+ align: 'left'
+ }
+ );
+ button.on( 'click', removeDynamicParamWidget, [ name, layout ] );
+ that.widgets[ name ] = widget;
+ dynamicFieldset.addItems( [ layout ], dynamicFieldset.getItems().length - 1 );
+ widget.focus();
+
+ dynamicParamNameWidget.setValue( '' );
+ };
+
+ this.$element.empty()
+ .append( new OO.ui.ProgressBarWidget( {
+ progress: false,
+ text: mw.message( 'apisandbox-loading', this.displayText ).text()
+ } ).$element );
+
+ Util.fetchModuleInfo( this.apiModule )
+ .done( function ( pi ) {
+ var prefix, i, j, descriptionContainer, widget, widgetField, helpField, tmp, flag, count,
+ items = [],
+ deprecatedItems = [],
+ buttons = [],
+ filterFmModules = function ( v ) {
+ return v.substr( -2 ) !== 'fm' ||
+ !availableFormats.hasOwnProperty( v.substr( 0, v.length - 2 ) );
+ },
+ widgetLabelOnClick = function () {
+ var f = this.getField();
+ if ( $.isFunction( f.setDisabled ) ) {
+ f.setDisabled( false );
+ }
+ if ( $.isFunction( f.focus ) ) {
+ f.focus();
+ }
+ };
+
+ // This is something of a hack. We always want the 'format' and
+ // 'action' parameters from the main module to be specified,
+ // and for 'format' we also want to simplify the dropdown since
+ // we always send the 'fm' variant.
+ if ( that.apiModule === 'main' ) {
+ for ( i = 0; i < pi.parameters.length; i++ ) {
+ if ( pi.parameters[ i ].name === 'action' ) {
+ pi.parameters[ i ].required = true;
+ delete pi.parameters[ i ][ 'default' ];
+ }
+ if ( pi.parameters[ i ].name === 'format' ) {
+ tmp = pi.parameters[ i ].type;
+ for ( j = 0; j < tmp.length; j++ ) {
+ availableFormats[ tmp[ j ] ] = true;
+ }
+ pi.parameters[ i ].type = $.grep( tmp, filterFmModules );
+ pi.parameters[ i ][ 'default' ] = 'json';
+ pi.parameters[ i ].required = true;
+ }
+ }
+ }
+
+ // Hide the 'wrappedhtml' parameter on format modules
+ if ( pi.group === 'format' ) {
+ pi.parameters = $.grep( pi.parameters, function ( p ) {
+ return p.name !== 'wrappedhtml';
+ } );
+ }
+
+ that.paramInfo = pi;
+
+ items.push( new OO.ui.FieldLayout(
+ new OO.ui.Widget( {} ).toggle( false ), {
+ align: 'top',
+ label: Util.parseHTML( pi.description )
+ }
+ ) );
+
+ if ( pi.helpurls.length ) {
+ buttons.push( new OO.ui.PopupButtonWidget( {
+ $overlay: $( '#mw-apisandbox-ui' ),
+ label: mw.message( 'apisandbox-helpurls' ).text(),
+ icon: 'help',
+ popup: {
+ width: 'auto',
+ padded: true,
+ $content: $( '<ul>' ).append( $.map( pi.helpurls, function ( link ) {
+ return $( '<li>' ).append( $( '<a>', {
+ href: link,
+ target: '_blank',
+ text: link
+ } ) );
+ } ) )
+ }
+ } ) );
+ }
+
+ if ( pi.examples.length ) {
+ buttons.push( new OO.ui.PopupButtonWidget( {
+ $overlay: $( '#mw-apisandbox-ui' ),
+ label: mw.message( 'apisandbox-examples' ).text(),
+ icon: 'code',
+ popup: {
+ width: 'auto',
+ padded: true,
+ $content: $( '<ul>' ).append( $.map( pi.examples, function ( example ) {
+ var a = $( '<a>', {
+ href: '#' + example.query,
+ html: example.description
+ } );
+ a.find( 'a' ).contents().unwrap(); // Can't nest links
+ return $( '<li>' ).append( a );
+ } ) )
+ }
+ } ) );
+ }
+
+ if ( buttons.length ) {
+ items.push( new OO.ui.FieldLayout(
+ new OO.ui.ButtonGroupWidget( {
+ items: buttons
+ } ), { align: 'top' }
+ ) );
+ }
+
+ if ( pi.parameters.length ) {
+ prefix = that.prefix + pi.prefix;
+ for ( i = 0; i < pi.parameters.length; i++ ) {
+ widget = Util.createWidgetForParameter( pi.parameters[ i ] );
+ that.widgets[ prefix + pi.parameters[ i ].name ] = widget;
+ if ( pi.parameters[ i ].tokentype ) {
+ that.tokenWidget = widget;
+ }
+
+ descriptionContainer = $( '<div>' );
+
+ tmp = Util.parseHTML( pi.parameters[ i ].description );
+ tmp.filter( 'dl' ).makeCollapsible( {
+ collapsed: true
+ } ).children( '.mw-collapsible-toggle' ).each( function () {
+ var $this = $( this );
+ $this.parent().prev( 'p' ).append( $this );
+ } );
+ descriptionContainer.append( $( '<div>', { addClass: 'description', append: tmp } ) );
+
+ if ( pi.parameters[ i ].info && pi.parameters[ i ].info.length ) {
+ for ( j = 0; j < pi.parameters[ i ].info.length; j++ ) {
+ descriptionContainer.append( $( '<div>', {
+ addClass: 'info',
+ append: Util.parseHTML( pi.parameters[ i ].info[ j ] )
+ } ) );
+ }
+ }
+ flag = true;
+ count = 1e100;
+ switch ( pi.parameters[ i ].type ) {
+ case 'namespace':
+ flag = false;
+ count = mw.config.get( 'wgFormattedNamespaces' ).length;
+ break;
+
+ case 'limit':
+ if ( pi.parameters[ i ].highmax !== undefined ) {
+ descriptionContainer.append( $( '<div>', {
+ addClass: 'info',
+ append: [
+ Util.parseMsg(
+ 'api-help-param-limit2', pi.parameters[ i ].max, pi.parameters[ i ].highmax
+ ),
+ ' ',
+ Util.parseMsg( 'apisandbox-param-limit' )
+ ]
+ } ) );
+ } else {
+ descriptionContainer.append( $( '<div>', {
+ addClass: 'info',
+ append: [
+ Util.parseMsg( 'api-help-param-limit', pi.parameters[ i ].max ),
+ ' ',
+ Util.parseMsg( 'apisandbox-param-limit' )
+ ]
+ } ) );
+ }
+ break;
+
+ case 'integer':
+ tmp = '';
+ if ( pi.parameters[ i ].min !== undefined ) {
+ tmp += 'min';
+ }
+ if ( pi.parameters[ i ].max !== undefined ) {
+ tmp += 'max';
+ }
+ if ( tmp !== '' ) {
+ descriptionContainer.append( $( '<div>', {
+ addClass: 'info',
+ append: Util.parseMsg(
+ 'api-help-param-integer-' + tmp,
+ Util.apiBool( pi.parameters[ i ].multi ) ? 2 : 1,
+ pi.parameters[ i ].min, pi.parameters[ i ].max
+ )
+ } ) );
+ }
+ break;
+
+ default:
+ if ( Array.isArray( pi.parameters[ i ].type ) ) {
+ flag = false;
+ count = pi.parameters[ i ].type.length;
+ }
+ break;
+ }
+ if ( Util.apiBool( pi.parameters[ i ].multi ) ) {
+ tmp = [];
+ if ( flag && !( widget instanceof OO.ui.CapsuleMultiselectWidget ) &&
+ !(
+ widget instanceof OptionalWidget &&
+ widget.widget instanceof OO.ui.CapsuleMultiselectWidget
+ )
+ ) {
+ tmp.push( mw.message( 'api-help-param-multi-separate' ).parse() );
+ }
+ if ( count > pi.parameters[ i ].lowlimit ) {
+ tmp.push(
+ mw.message( 'api-help-param-multi-max',
+ pi.parameters[ i ].lowlimit, pi.parameters[ i ].highlimit
+ ).parse()
+ );
+ }
+ if ( tmp.length ) {
+ descriptionContainer.append( $( '<div>', {
+ addClass: 'info',
+ append: Util.parseHTML( tmp.join( ' ' ) )
+ } ) );
+ }
+ }
+ helpField = new OO.ui.FieldLayout(
+ new OO.ui.Widget( {
+ $content: '\xa0',
+ classes: [ 'mw-apisandbox-spacer' ]
+ } ), {
+ align: 'inline',
+ classes: [ 'mw-apisandbox-help-field' ],
+ label: descriptionContainer
+ }
+ );
+
+ widgetField = new OO.ui.FieldLayout(
+ widget,
+ {
+ align: 'left',
+ classes: [ 'mw-apisandbox-widget-field' ],
+ label: prefix + pi.parameters[ i ].name
+ }
+ );
+
+ // We need our own click handler on the widget label to
+ // turn off the disablement.
+ widgetField.$label.on( 'click', widgetLabelOnClick.bind( widgetField ) );
+
+ // Don't grey out the label when the field is disabled,
+ // it makes it too hard to read and our "disabled"
+ // isn't really disabled.
+ widgetField.onFieldDisable( false );
+ widgetField.onFieldDisable = $.noop;
+
+ if ( Util.apiBool( pi.parameters[ i ].deprecated ) ) {
+ deprecatedItems.push( widgetField, helpField );
+ } else {
+ items.push( widgetField, helpField );
+ }
+ }
+ }
+
+ if ( !pi.parameters.length && !Util.apiBool( pi.dynamicparameters ) ) {
+ items.push( new OO.ui.FieldLayout(
+ new OO.ui.Widget( {} ).toggle( false ), {
+ align: 'top',
+ label: Util.parseMsg( 'apisandbox-no-parameters' )
+ }
+ ) );
+ }
+
+ that.$element.empty();
+
+ new OO.ui.FieldsetLayout( {
+ label: that.displayText
+ } ).addItems( items )
+ .$element.appendTo( that.$element );
+
+ if ( Util.apiBool( pi.dynamicparameters ) ) {
+ dynamicFieldset = new OO.ui.FieldsetLayout();
+ dynamicParamNameWidget = new OO.ui.TextInputWidget( {
+ placeholder: mw.message( 'apisandbox-dynamic-parameters-add-placeholder' ).text()
+ } ).on( 'enter', addDynamicParamWidget );
+ dynamicFieldset.addItems( [
+ new OO.ui.FieldLayout(
+ new OO.ui.Widget( {} ).toggle( false ), {
+ align: 'top',
+ label: Util.parseHTML( pi.dynamicparameters )
+ }
+ ),
+ new OO.ui.ActionFieldLayout(
+ dynamicParamNameWidget,
+ new OO.ui.ButtonWidget( {
+ icon: 'add',
+ flags: 'progressive'
+ } ).on( 'click', addDynamicParamWidget ),
+ {
+ label: mw.message( 'apisandbox-dynamic-parameters-add-label' ).text(),
+ align: 'left'
+ }
+ )
+ ] );
+ $( '<fieldset>' )
+ .append(
+ $( '<legend>' ).text( mw.message( 'apisandbox-dynamic-parameters' ).text() ),
+ dynamicFieldset.$element
+ )
+ .appendTo( that.$element );
+ }
+
+ if ( deprecatedItems.length ) {
+ tmp = new OO.ui.FieldsetLayout().addItems( deprecatedItems ).toggle( false );
+ $( '<fieldset>' )
+ .append(
+ $( '<legend>' ).append(
+ new OO.ui.ToggleButtonWidget( {
+ label: mw.message( 'apisandbox-deprecated-parameters' ).text()
+ } ).on( 'change', tmp.toggle, [], tmp ).$element
+ ),
+ tmp.$element
+ )
+ .appendTo( that.$element );
+ }
+
+ // Load stored params, if any, then update the booklet if we
+ // have subpages (or else just update our valid-indicator).
+ tmp = that.loadFromQueryParams;
+ that.loadFromQueryParams = null;
+ if ( $.isPlainObject( tmp ) ) {
+ that.loadQueryParams( tmp );
+ }
+ if ( that.getSubpages().length > 0 ) {
+ ApiSandbox.updateUI( tmp );
+ } else {
+ that.apiCheckValid();
+ }
+ } ).fail( function ( code, detail ) {
+ that.$element.empty()
+ .append(
+ new OO.ui.LabelWidget( {
+ label: mw.message( 'apisandbox-load-error', that.apiModule, detail ).text(),
+ classes: [ 'error' ]
+ } ).$element,
+ new OO.ui.ButtonWidget( {
+ label: mw.message( 'apisandbox-retry' ).text()
+ } ).on( 'click', that.loadParamInfo, [], that ).$element
+ );
+ } );
+ };
+
+ /**
+ * Check that all widgets on the page are in a valid state.
+ *
+ * @return {boolean}
+ */
+ ApiSandbox.PageLayout.prototype.apiCheckValid = function () {
+ var that = this;
+
+ if ( this.paramInfo === null ) {
+ return $.Deferred().resolve( false ).promise();
+ } else {
+ return $.when.apply( $, $.map( this.widgets, function ( widget ) {
+ return widget.apiCheckValid();
+ } ) ).then( function () {
+ that.apiIsValid = $.inArray( false, arguments ) === -1;
+ if ( that.getOutlineItem() ) {
+ that.getOutlineItem().setIcon( that.apiIsValid || suppressErrors ? null : 'alert' );
+ that.getOutlineItem().setIconTitle(
+ that.apiIsValid || suppressErrors ? '' : mw.message( 'apisandbox-alert-page' ).plain()
+ );
+ }
+ return $.Deferred().resolve( that.apiIsValid ).promise();
+ } );
+ }
+ };
+
+ /**
+ * Load form fields from query parameters
+ *
+ * @param {Object} params
+ */
+ ApiSandbox.PageLayout.prototype.loadQueryParams = function ( params ) {
+ if ( this.paramInfo === null ) {
+ this.loadFromQueryParams = params;
+ } else {
+ $.each( this.widgets, function ( name, widget ) {
+ var v = params.hasOwnProperty( name ) ? params[ name ] : undefined;
+ widget.setApiValue( v );
+ } );
+ }
+ };
+
+ /**
+ * Load query params from form fields
+ *
+ * @param {Object} params Write query parameters into this object
+ * @param {Object} displayParams Write query parameters for display into this object
+ */
+ ApiSandbox.PageLayout.prototype.getQueryParams = function ( params, displayParams ) {
+ $.each( this.widgets, function ( name, widget ) {
+ var value = widget.getApiValue();
+ if ( value !== undefined ) {
+ params[ name ] = value;
+ if ( $.isFunction( widget.getApiValueForDisplay ) ) {
+ value = widget.getApiValueForDisplay();
+ }
+ displayParams[ name ] = value;
+ }
+ } );
+ };
+
+ /**
+ * Fetch a list of subpage names loaded by this page
+ *
+ * @return {Array}
+ */
+ ApiSandbox.PageLayout.prototype.getSubpages = function () {
+ var ret = [];
+ $.each( this.widgets, function ( name, widget ) {
+ var submodules, i;
+ if ( $.isFunction( widget.getSubmodules ) ) {
+ submodules = widget.getSubmodules();
+ for ( i = 0; i < submodules.length; i++ ) {
+ ret.push( {
+ key: name + '=' + submodules[ i ].value,
+ path: submodules[ i ].path,
+ prefix: widget.paramInfo.submoduleparamprefix || ''
+ } );
+ }
+ }
+ } );
+ return ret;
+ };
+
+ /**
+ * A text input with a clickable indicator
+ *
+ * @class
+ * @private
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+ function TextInputWithIndicatorWidget( config ) {
+ var k;
+
+ config = config || {};
+ TextInputWithIndicatorWidget[ 'super' ].call( this, config );
+
+ this.$indicator = $( '<span>' ).addClass( 'mw-apisandbox-clickable-indicator' );
+ OO.ui.mixin.TabIndexedElement.call(
+ this, $.extend( {}, config, { $tabIndexed: this.$indicator } )
+ );
+
+ this.input = new OO.ui.TextInputWidget( $.extend( {
+ $indicator: this.$indicator,
+ disabled: this.isDisabled()
+ }, config.input ) );
+
+ // Forward most methods for convenience
+ for ( k in this.input ) {
+ if ( $.isFunction( this.input[ k ] ) && !this[ k ] ) {
+ this[ k ] = this.input[ k ].bind( this.input );
+ }
+ }
+
+ this.$indicator.on( {
+ click: this.onIndicatorClick.bind( this ),
+ keypress: this.onIndicatorKeyPress.bind( this )
+ } );
+
+ this.$element.append( this.input.$element );
+ }
+ OO.inheritClass( TextInputWithIndicatorWidget, OO.ui.Widget );
+ OO.mixinClass( TextInputWithIndicatorWidget, OO.ui.mixin.TabIndexedElement );
+ TextInputWithIndicatorWidget.prototype.onIndicatorClick = function ( e ) {
+ if ( !this.isDisabled() && e.which === 1 ) {
+ this.emit( 'indicator' );
+ }
+ return false;
+ };
+ TextInputWithIndicatorWidget.prototype.onIndicatorKeyPress = function ( e ) {
+ if ( !this.isDisabled() && ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER ) ) {
+ this.emit( 'indicator' );
+ return false;
+ }
+ };
+ TextInputWithIndicatorWidget.prototype.setDisabled = function ( disabled ) {
+ TextInputWithIndicatorWidget[ 'super' ].prototype.setDisabled.call( this, disabled );
+ if ( this.input ) {
+ this.input.setDisabled( this.isDisabled() );
+ }
+ return this;
+ };
+
+ /**
+ * A wrapper for a widget that provides an enable/disable button
+ *
+ * @class
+ * @private
+ * @constructor
+ * @param {OO.ui.Widget} widget
+ * @param {Object} [config] Configuration options
+ */
+ function OptionalWidget( widget, config ) {
+ var k;
+
+ config = config || {};
+
+ this.widget = widget;
+ this.$overlay = config.$overlay ||
+ $( '<div>' ).addClass( 'mw-apisandbox-optionalWidget-overlay' );
+ this.checkbox = new OO.ui.CheckboxInputWidget( config.checkbox )
+ .on( 'change', this.onCheckboxChange, [], this );
+
+ OptionalWidget[ 'super' ].call( this, config );
+
+ // Forward most methods for convenience
+ for ( k in this.widget ) {
+ if ( $.isFunction( this.widget[ k ] ) && !this[ k ] ) {
+ this[ k ] = this.widget[ k ].bind( this.widget );
+ }
+ }
+
+ this.$overlay.on( 'click', this.onOverlayClick.bind( this ) );
+
+ this.$element
+ .addClass( 'mw-apisandbox-optionalWidget' )
+ .append(
+ this.$overlay,
+ $( '<div>' ).addClass( 'mw-apisandbox-optionalWidget-fields' ).append(
+ $( '<div>' ).addClass( 'mw-apisandbox-optionalWidget-widget' ).append(
+ widget.$element
+ ),
+ $( '<div>' ).addClass( 'mw-apisandbox-optionalWidget-checkbox' ).append(
+ this.checkbox.$element
+ )
+ )
+ );
+
+ this.setDisabled( widget.isDisabled() );
+ }
+ OO.inheritClass( OptionalWidget, OO.ui.Widget );
+ OptionalWidget.prototype.onCheckboxChange = function ( checked ) {
+ this.setDisabled( !checked );
+ };
+ OptionalWidget.prototype.onOverlayClick = function () {
+ this.setDisabled( false );
+ if ( $.isFunction( this.widget.focus ) ) {
+ this.widget.focus();
+ }
+ };
+ OptionalWidget.prototype.setDisabled = function ( disabled ) {
+ OptionalWidget[ 'super' ].prototype.setDisabled.call( this, disabled );
+ this.widget.setDisabled( this.isDisabled() );
+ this.checkbox.setSelected( !this.isDisabled() );
+ this.$overlay.toggle( this.isDisabled() );
+ return this;
+ };
+
+ $( ApiSandbox.init );
+
+ module.exports = ApiSandbox;
+
+}( jQuery, mediaWiki, OO ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.top.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.top.css
new file mode 100644
index 00000000..4dc4c27a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.apisandbox.top.css
@@ -0,0 +1,3 @@
+.client-js .mw-apisandbox-nojs {
+ display: none;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.block.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.block.css
new file mode 100644
index 00000000..a30a15df
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.block.css
@@ -0,0 +1,11 @@
+/*!
+ * Styling for Special:Block
+ */
+
+label[for="mw-input-wpConfirm"] {
+ font-weight: bold;
+}
+
+tr.mw-block-hideuser {
+ font-weight: bold;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.block.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.block.js
new file mode 100644
index 00000000..8d884109
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.block.js
@@ -0,0 +1,58 @@
+/*!
+ * JavaScript for Special:Block
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var $blockTarget = $( '#mw-bi-target' ),
+ $anonOnlyRow = $( '#mw-input-wpHardBlock' ).closest( 'tr' ),
+ $enableAutoblockRow = $( '#mw-input-wpAutoBlock' ).closest( 'tr' ),
+ $hideUser = $( '#mw-input-wpHideUser' ).closest( 'tr' ),
+ $watchUser = $( '#mw-input-wpWatch' ).closest( 'tr' ),
+ $expiry = $( '#mw-input-wpExpiry' ),
+ $otherExpiry = $( '#mw-input-wpExpiry-other' );
+
+ function updateBlockOptions( instant ) {
+ var blocktarget = $.trim( $blockTarget.val() ),
+ isEmpty = blocktarget === '',
+ isIp = mw.util.isIPAddress( blocktarget, true ),
+ isIpRange = isIp && blocktarget.match( /\/\d+$/ ),
+ isNonEmptyIp = isIp && !isEmpty,
+ expiryValue = $expiry.val(),
+ // infinityValues are the values the SpecialBlock class accepts as infinity (sf. wfIsInfinity)
+ infinityValues = [ 'infinite', 'indefinite', 'infinity', 'never' ],
+ isIndefinite = $.inArray( expiryValue, infinityValues ) !== -1 ||
+ ( expiryValue === 'other' && $.inArray( $otherExpiry.val(), infinityValues ) !== -1 );
+
+ if ( isNonEmptyIp ) {
+ $enableAutoblockRow.goOut( instant );
+ } else {
+ $enableAutoblockRow.goIn( instant );
+ }
+ if ( isNonEmptyIp || !isIndefinite ) {
+ $hideUser.goOut( instant );
+ } else {
+ $hideUser.goIn( instant );
+ }
+ if ( !isIp && !isEmpty ) {
+ $anonOnlyRow.goOut( instant );
+ } else {
+ $anonOnlyRow.goIn( instant );
+ }
+ if ( isIpRange && !isEmpty ) {
+ $watchUser.goOut( instant );
+ } else {
+ $watchUser.goIn( instant );
+ }
+ }
+
+ if ( $blockTarget.length ) {
+ // Bind functions so they're checked whenever stuff changes
+ $blockTarget.keyup( updateBlockOptions );
+ $expiry.change( updateBlockOptions );
+ $otherExpiry.keyup( updateBlockOptions );
+
+ // Call them now to set initial state (ie. Special:Block/Foobar?wpBlockExpiry=2+hours)
+ updateBlockOptions( /* instant= */ true );
+ }
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.blocklist.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.blocklist.css
new file mode 100644
index 00000000..b7513b60
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.blocklist.css
@@ -0,0 +1,4 @@
+.mw-htmlform-flatlist-item {
+ /* FIXME: There should be an option in OOUI to do that */
+ display: inline-block !important;
+} \ No newline at end of file
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.changecredentials.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changecredentials.js
new file mode 100644
index 00000000..95928799
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changecredentials.js
@@ -0,0 +1,55 @@
+/*!
+ * JavaScript for change credentials form.
+ */
+( function ( mw, $, OO ) {
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ var api = new mw.Api();
+
+ $root.find( '.mw-changecredentials-validate-password.oo-ui-fieldLayout' ).each( function () {
+ var currentApiPromise,
+ self = OO.ui.FieldLayout.static.infuse( $( this ) );
+
+ self.getField().setValidation( function ( password ) {
+ var d;
+
+ if ( currentApiPromise ) {
+ currentApiPromise.abort();
+ currentApiPromise = undefined;
+ }
+
+ password = $.trim( password );
+
+ if ( password === '' ) {
+ self.setErrors( [] );
+ return true;
+ }
+
+ d = $.Deferred();
+ currentApiPromise = api.post( {
+ action: 'validatepassword',
+ password: password,
+ formatversion: 2,
+ errorformat: 'html',
+ errorsuselocal: true,
+ uselang: mw.config.get( 'wgUserLanguage' )
+ } ).done( function ( resp ) {
+ var pwinfo = resp.validatepassword,
+ good = pwinfo.validity === 'Good',
+ errors = [];
+
+ currentApiPromise = undefined;
+
+ if ( !good ) {
+ pwinfo.validitymessages.map( function ( m ) {
+ errors.push( new OO.ui.HtmlSnippet( m.html ) );
+ } );
+ }
+ self.setErrors( errors );
+ d.resolve( good );
+ } ).fail( d.reject );
+
+ return d.promise( { abort: currentApiPromise.abort } );
+ } );
+ } );
+ } );
+}( mediaWiki, jQuery, OO ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.css
new file mode 100644
index 00000000..3e1bd4e8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.css
@@ -0,0 +1,41 @@
+/*!
+ * Styling for Special:Watchlist and Special:RecentChanges
+ */
+
+.mw-changeslist-line-watched .mw-title {
+ font-weight: bold;
+}
+
+/*
+ * Titles, including username links, and also tag names
+ * are prone to getting jumbled up
+ * with other titles, usernames, etc. in mixed RTL-LTR environment.
+ */
+.mw-changeslist .mw-tag-marker,
+.mw-changeslist .mw-title {
+ unicode-bidi: embed;
+}
+
+/* Colored watchlist and recent changes numbers */
+.mw-plusminus-pos {
+ color: #006400; /* dark green */
+}
+
+.mw-plusminus-neg {
+ color: #8b0000; /* dark red */
+}
+
+.mw-plusminus-null {
+ color: #a2a9b1; /* gray */
+}
+
+/*
+ * Bidi-isolate these numbers.
+ * See https://phabricator.wikimedia.org/T93484
+ */
+.mw-plusminus-pos,
+.mw-plusminus-neg,
+.mw-plusminus-null {
+ unicode-bidi: -moz-isolate;
+ unicode-bidi: isolate;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css
new file mode 100644
index 00000000..d6b06e66
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.enhanced.css
@@ -0,0 +1,65 @@
+/*!
+ * Styling for Special:Watchlist and Special:RecentChanges when preference 'usenewrc'
+ * a.k.a. Enhanced Recent Changes is enabled.
+ */
+
+table.mw-enhanced-rc {
+ border: 0;
+ border-spacing: 0;
+}
+
+table.mw-enhanced-rc th,
+table.mw-enhanced-rc td {
+ padding: 0;
+ vertical-align: top;
+}
+
+td.mw-enhanced-rc {
+ white-space: nowrap;
+ font-family: monospace, monospace;
+}
+
+.mw-enhanced-rc-time {
+ font-family: monospace, monospace;
+}
+
+table.mw-enhanced-rc td.mw-enhanced-rc-nested {
+ padding-left: 1em;
+}
+
+/* Show/hide arrows in enhanced changeslist */
+.mw-enhanced-rc .collapsible-expander {
+ float: none;
+}
+
+/* If JS is disabled, the arrows or the placeholder space shouldn't be shown */
+.client-nojs .mw-enhancedchanges-arrow-space {
+ display: none;
+}
+
+/*
+ * And if it's enabled, let's optimize the collapsing a little: hide the rows
+ * that would be hidden by jquery.makeCollapsible with CSS to save us some
+ * reflows and repaints. This doesn't work on browsers that don't fully support
+ * CSS2 (IE6), but it's okay, this will be done in JavaScript with old degraded
+ * performance instead.
+ */
+.client-js table.mw-enhanced-rc.mw-collapsed tr + tr {
+ display: none;
+}
+
+.mw-enhancedchanges-arrow-space {
+ display: inline-block;
+ *display: inline; /* IE7 and below */
+ zoom: 1;
+ width: 15px;
+ height: 15px;
+}
+
+.mw-enhanced-watched .mw-enhanced-rc-time {
+ font-weight: bold;
+}
+
+span.changedby {
+ font-size: 95%;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css
new file mode 100644
index 00000000..14f6aeee
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.css
@@ -0,0 +1,33 @@
+/*!
+ * Styling for changes list legend
+ */
+
+.mw-changeslist-legend {
+ float: right;
+ margin-left: 1em;
+ margin-bottom: 0.5em;
+ clear: right;
+ font-size: 85%;
+ line-height: 1.2em;
+ padding: 0.5em;
+ border: 1px solid #ddd;
+}
+
+.mw-changeslist-legend dl {
+ /* Parent element defines sufficient padding */
+ margin-bottom: 0;
+}
+
+.mw-changeslist-legend dt {
+ float: left;
+ margin: 0 0.5em 0 0;
+}
+
+.mw-changeslist-legend dd {
+ margin-left: 1.5em;
+}
+
+.mw-changeslist-legend dt,
+.mw-changeslist-legend dd {
+ line-height: 1.3em;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.js
new file mode 100644
index 00000000..07927626
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.legend.js
@@ -0,0 +1,24 @@
+/*!
+ * Script for changes list legend
+ */
+
+/* Remember the collapse state of the legend on recent changes and watchlist pages. */
+( function ( mw ) {
+ var
+ cookieName = 'changeslist-state',
+ // Expanded by default
+ doCollapsibleLegend = function ( $container ) {
+ $container.find( '.mw-changeslist-legend' )
+ .makeCollapsible( {
+ collapsed: mw.cookie.get( cookieName ) === 'collapsed'
+ } )
+ .on( 'beforeExpand.mw-collapsible', function () {
+ mw.cookie.set( cookieName, 'expanded' );
+ } )
+ .on( 'beforeCollapse.mw-collapsible', function () {
+ mw.cookie.set( cookieName, 'collapsed' );
+ } );
+ };
+
+ mw.hook( 'wikipage.content' ).add( doCollapsibleLegend );
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.visitedstatus.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.visitedstatus.js
new file mode 100644
index 00000000..954e074a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.changeslist.visitedstatus.js
@@ -0,0 +1,12 @@
+/*!
+ * JavaScript for Special:Watchlist
+ */
+( function ( mw, $ ) {
+ $( function () {
+ $( '.mw-changeslist-line-watched .mw-title a' ).on( 'click', function () {
+ $( this )
+ .closest( '.mw-changeslist-line-watched' )
+ .removeClass( 'mw-changeslist-line-watched' );
+ } );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less b/www/wiki/resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less
new file mode 100644
index 00000000..c951169d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.comparepages.styles.less
@@ -0,0 +1,19 @@
+@import 'mediawiki.mixins';
+
+.mw-special-ComparePages .mw-htmlform-ooui-wrapper {
+ width: 100%;
+}
+
+.mw-special-ComparePages .oo-ui-layout.oo-ui-panelLayout.oo-ui-panelLayout-padded.oo-ui-panelLayout-framed {
+ float: left;
+ width: 49%;
+ .box-sizing( border-box );
+}
+
+.mw-special-ComparePages .oo-ui-layout.oo-ui-panelLayout.oo-ui-panelLayout-padded.oo-ui-panelLayout-framed:nth-of-type(2) {
+ margin-left: 2%;
+}
+
+.mw-special-ComparePages .mw-htmlform-submit-buttons {
+ clear: both;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.contributions.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.contributions.js
new file mode 100644
index 00000000..f65a2579
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.contributions.js
@@ -0,0 +1,12 @@
+( function ( mw, $ ) {
+ $( function () {
+ var startInput = mw.widgets.DateInputWidget.static.infuse( 'mw-date-start' ),
+ endInput = mw.widgets.DateInputWidget.static.infuse( 'mw-date-end' );
+
+ startInput.on( 'deactivate', function ( userSelected ) {
+ if ( userSelected ) {
+ endInput.focus();
+ }
+ } );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.css
new file mode 100644
index 00000000..36dfee6e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.css
@@ -0,0 +1,130 @@
+/* Special:AllMessages */
+#mw-allmessagestable .allmessages-customised td.am_default {
+ background-color: #fcffc4;
+}
+
+#mw-allmessagestable tr.allmessages-customised:hover td.am_default {
+ background-color: #faff90;
+}
+
+#mw-allmessagestable td.am_actual {
+ background-color: #e2ffe2;
+}
+
+#mw-allmessagestable tr.allmessages-customised:hover + tr.allmessages-customised td.am_actual {
+ background-color: #b1ffb1;
+}
+
+/* Common for Special:Allpages and Special:PrefixIndex */
+.mw-allpages-body,
+.mw-prefixindex-body {
+ columns: 22em 3;
+ -moz-columns: 22em 3;
+ -webkit-columns: 22em 3;
+ break-inside: avoid-column;
+ page-break-inside: avoid;
+ -webkit-column-break-inside: avoid;
+}
+.allpagesredirect {
+ font-style: italic;
+}
+
+/* Special:Block */
+p.mw-ipb-conveniencelinks {
+ font-size: 90%;
+ text-align: right;
+}
+
+label[for='mw-input-wpConfirm'] {
+ font-weight: bold;
+}
+
+tr.mw-block-hideuser {
+ font-weight: bold;
+}
+
+/* Special:BlockList */
+table.mw-blocklist span.mw-usertoollinks,
+span.mw-blocklist-actions {
+ white-space: nowrap;
+ font-size: 90%;
+}
+
+/* Special:Contributions */
+.mw-uctop {
+ font-weight: bold;
+}
+.mw-contributions-form select {
+ vertical-align: middle;
+}
+
+/* Special:EditWatchlist */
+.watchlistredir {
+ font-style: italic;
+}
+
+/* Special:EmailUser */
+td#mw-emailuser-sender,
+td#mw-emailuser-recipient {
+ font-weight: bold;
+}
+
+/* Special:FileDuplicateSearch */
+#mw-fileduplicatesearch-icon {
+ float: right;
+}
+
+/* Special:ListGroupRights */
+table.mw-listgrouprights-table tr {
+ vertical-align: top;
+}
+.listgrouprights-revoked {
+ text-decoration: line-through;
+}
+
+/* Special:RevisionDelete */
+p.mw-revdel-editreasons {
+ font-size: 90%;
+ text-align: right;
+}
+
+/* Special:Specialpages */
+.mw-specialpagerestricted {
+ font-weight: bold;
+}
+
+.mw-specialpages-list {
+ -webkit-columns: 16em 2;
+ -moz-columns: 16em 2;
+ columns: 16em 2;
+}
+
+/* Special:Statistics */
+td.mw-statistics-numbers {
+ text-align: right;
+}
+
+/* Special:ProtectedPages */
+table.mw-protectedpages span.mw-usertoollinks,
+span.mw-protectedpages-length,
+span.mw-protectedpages-actions {
+ white-space: nowrap;
+ font-size: 90%;
+}
+span.mw-protectedpages-unknown {
+ color: #808080;
+ font-size: 90%;
+}
+
+/* Special:UserRights */
+.mw-userrights-disabled {
+ color: #888;
+}
+table.mw-userrights-groups * td,
+table.mw-userrights-groups * th {
+ padding-right: 1.5em;
+}
+
+table.mw-userrights-groups * th {
+ text-align: left;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.edittags.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.edittags.css
new file mode 100644
index 00000000..204009c9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.edittags.css
@@ -0,0 +1,15 @@
+/*!
+ * Styling for Special:EditTags and action=editchangetags
+ */
+#mw-edittags-tags-selector td {
+ vertical-align: top;
+}
+
+#mw-edittags-tags-selector-multi td {
+ vertical-align: top;
+ padding-right: 1.5em;
+}
+
+#mw-edittags-tag-list {
+ min-width: 20em;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.edittags.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.edittags.js
new file mode 100644
index 00000000..3e6e6843
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.edittags.js
@@ -0,0 +1,25 @@
+/*!
+ * JavaScript for Special:EditTags
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var $tagList = $( '#mw-edittags-tag-list' );
+ if ( $tagList.length ) {
+ $tagList.chosen( {
+ /* eslint-disable camelcase */
+ placeholder_text_multiple: mw.msg( 'tags-edit-chosen-placeholder' ),
+ no_results_text: mw.msg( 'tags-edit-chosen-no-results' )
+ /* eslint-enable camelcase */
+ } );
+ }
+
+ $( '#mw-edittags-remove-all' ).on( 'change', function ( e ) {
+ $( '.mw-edittags-remove-checkbox' ).prop( 'checked', e.target.checked );
+ } );
+ $( '.mw-edittags-remove-checkbox' ).on( 'change', function ( e ) {
+ if ( !e.target.checked ) {
+ $( '#mw-edittags-remove-all' ).prop( 'checked', false );
+ }
+ } );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.import.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.import.js
new file mode 100644
index 00000000..3357461f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.import.js
@@ -0,0 +1,37 @@
+/*!
+ * JavaScript for Special:Import
+ */
+( function ( $ ) {
+ var subprojectListAlreadyShown;
+ function updateImportSubprojectList() {
+ var $projectField = $( '#mw-import-table-interwiki #interwiki' ),
+ $subprojectField = $projectField.parent().find( '#subproject' ),
+ $selected = $projectField.find( ':selected' ),
+ oldValue = $subprojectField.val(),
+ option, options;
+
+ if ( $selected.attr( 'data-subprojects' ) ) {
+ options = $.map( $selected.attr( 'data-subprojects' ).split( ' ' ), function ( el ) {
+ option = document.createElement( 'option' );
+ option.appendChild( document.createTextNode( el ) );
+ option.setAttribute( 'value', el );
+ if ( oldValue === el && subprojectListAlreadyShown === true ) {
+ option.setAttribute( 'selected', 'selected' );
+ }
+ return option;
+ } );
+ $subprojectField.show().empty().append( options );
+ subprojectListAlreadyShown = true;
+ } else {
+ $subprojectField.hide();
+ }
+ }
+
+ $( function () {
+ var $projectField = $( '#mw-import-table-interwiki #interwiki' );
+ if ( $projectField.length ) {
+ $projectField.change( updateImportSubprojectList );
+ updateImportSubprojectList();
+ }
+ } );
+}( jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.js
new file mode 100644
index 00000000..630d1624
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.js
@@ -0,0 +1,9 @@
+/*!
+ * Namespace for mediawiki.special.* modules
+ */
+
+/**
+ * @class mw.special
+ * @singleton
+ */
+mediaWiki.special = {};
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.movePage.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.movePage.css
new file mode 100644
index 00000000..9428fedc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.movePage.css
@@ -0,0 +1,7 @@
+/*!
+ * Styles for Special:MovePage
+ */
+
+.movepage-wrapper {
+ width: 50em;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.movePage.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.movePage.js
new file mode 100644
index 00000000..2e980ac9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.movePage.js
@@ -0,0 +1,15 @@
+/*!
+ * JavaScript for Special:MovePage
+ */
+( function ( mw, $ ) {
+ $( function () {
+ // Infuse for pretty dropdown
+ OO.ui.infuse( $( '#wpNewTitle' ) );
+ // Limit to bytes, not characters
+ mw.widgets.visibleByteLimit( OO.ui.infuse( $( '#wpReason' ) ) );
+ // Infuse for nicer "help" popup
+ if ( $( '#wpMovetalk-field' ).length ) {
+ OO.ui.infuse( $( '#wpMovetalk-field' ) );
+ }
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.pageLanguage.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.pageLanguage.js
new file mode 100644
index 00000000..edfbe1ea
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.pageLanguage.js
@@ -0,0 +1,11 @@
+/*!
+ * JavaScript module used on Special:PageLanguage
+ */
+( function ( $, OO ) {
+ $( function () {
+ // Select the 'Language select' option if user is trying to select language
+ OO.ui.infuse( 'mw-pl-languageselector' ).on( 'change', function () {
+ OO.ui.infuse( 'mw-pl-options' ).setValue( '2' );
+ } );
+ } );
+}( jQuery, OO ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css
new file mode 100644
index 00000000..7ef75d0c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.pagesWithProp.css
@@ -0,0 +1,4 @@
+/* Distinguish actual data from information about it being hidden visually */
+.prop-value-hidden {
+ font-style: italic;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js
new file mode 100644
index 00000000..45df37ff
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.confirmClose.js
@@ -0,0 +1,63 @@
+/*!
+ * JavaScript for Special:Preferences: Enable save button and prevent the window being accidentally
+ * closed when any form field is changed.
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var allowCloseWindow;
+
+ // Check if all of the form values are unchanged
+ function isPrefsChanged() {
+ var inputs = $( '#mw-prefs-form :input[name]' ),
+ input, $input, inputType,
+ index, optIndex,
+ opt;
+
+ for ( index = 0; index < inputs.length; index++ ) {
+ input = inputs[ index ];
+ $input = $( input );
+
+ // Different types of inputs have different methods for accessing defaults
+ if ( $input.is( 'select' ) ) {
+ // <select> has the property defaultSelected for each option
+ for ( optIndex = 0; optIndex < input.options.length; optIndex++ ) {
+ opt = input.options[ optIndex ];
+ if ( opt.selected !== opt.defaultSelected ) {
+ return true;
+ }
+ }
+ } else if ( $input.is( 'input' ) ) { // <input> has defaultValue or defaultChecked
+ inputType = input.type;
+ if ( inputType === 'radio' || inputType === 'checkbox' ) {
+ if ( input.checked !== input.defaultChecked ) {
+ return true;
+ }
+ } else if ( input.value !== input.defaultValue ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // Disable the button to save preferences unless preferences have changed
+ // Check if preferences have been changed before JS has finished loading
+ if ( !isPrefsChanged() ) {
+ $( '#prefcontrol' ).prop( 'disabled', true );
+ $( '#preferences > fieldset' ).one( 'change keydown mousedown', function () {
+ $( '#prefcontrol' ).prop( 'disabled', false );
+ } );
+ }
+
+ // Set up a message to notify users if they try to leave the page without
+ // saving.
+ allowCloseWindow = mw.confirmCloseWindow( {
+ test: isPrefsChanged,
+ message: mw.msg( 'prefswarning-warning', mw.msg( 'saveprefs' ) ),
+ namespace: 'prefswarning'
+ } );
+ $( '#mw-prefs-form' ).submit( $.proxy( allowCloseWindow, 'release' ) );
+ $( '#mw-prefs-restoreprefs' ).click( $.proxy( allowCloseWindow, 'release' ) );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js
new file mode 100644
index 00000000..cee73829
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.convertmessagebox.js
@@ -0,0 +1,9 @@
+/*!
+ * JavaScript for Special:Preferences: Check for successbox to replace with notifications.
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var convertmessagebox = require( 'mediawiki.notification.convertmessagebox' );
+ convertmessagebox();
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.js
new file mode 100644
index 00000000..a756f22d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.js
@@ -0,0 +1,321 @@
+/*!
+ * JavaScript for Special:Preferences
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var $preftoc, $preferences, $fieldsets,
+ labelFunc,
+ $tzSelect, $tzTextbox, $localtimeHolder, servertime,
+ allowCloseWindow, notif;
+
+ labelFunc = function () {
+ return this.id.replace( /^mw-prefsection/g, 'preftab' );
+ };
+
+ $( '#prefsubmit' ).attr( 'id', 'prefcontrol' );
+ $preftoc = $( '#preftoc' );
+ $preferences = $( '#preferences' );
+
+ $fieldsets = $preferences.children( 'fieldset' )
+ .attr( {
+ role: 'tabpanel',
+ 'aria-labelledby': labelFunc
+ } );
+ $fieldsets.not( '#mw-prefsection-personal' )
+ .hide()
+ .attr( 'aria-hidden', 'true' );
+
+ // T115692: The following is kept for backwards compatibility with older skins
+ $preferences.addClass( 'jsprefs' );
+ $fieldsets.addClass( 'prefsection' );
+ $fieldsets.children( 'legend' ).addClass( 'mainLegend' );
+
+ // Make sure the accessibility tip is selectable so that screen reader users take notice,
+ // but hide it per default to reduce interface clutter. Also make sure it becomes visible
+ // when selected. Similar to jquery.mw-jump
+ $( '<div>' ).addClass( 'mw-navigation-hint' )
+ .text( mw.msg( 'prefs-tabs-navigation-hint' ) )
+ .attr( 'tabIndex', 0 )
+ .on( 'focus blur', function ( e ) {
+ if ( e.type === 'blur' || e.type === 'focusout' ) {
+ $( this ).css( 'height', '0' );
+ } else {
+ $( this ).css( 'height', 'auto' );
+ }
+ } ).insertBefore( $preftoc );
+
+ /**
+ * It uses document.getElementById for security reasons (HTML injections in $()).
+ *
+ * @ignore
+ * @param {string} name the name of a tab without the prefix ("mw-prefsection-")
+ * @param {string} [mode] A hash will be set according to the current
+ * open section. Set mode 'noHash' to surpress this.
+ */
+ function switchPrefTab( name, mode ) {
+ var $tab, scrollTop;
+ // Handle hash manually to prevent jumping,
+ // therefore save and restore scrollTop to prevent jumping.
+ scrollTop = $( window ).scrollTop();
+ if ( mode !== 'noHash' ) {
+ location.hash = '#mw-prefsection-' + name;
+ }
+ $( window ).scrollTop( scrollTop );
+
+ $preftoc.find( 'li' ).removeClass( 'selected' )
+ .find( 'a' ).attr( {
+ tabIndex: -1,
+ 'aria-selected': 'false'
+ } );
+
+ $tab = $( document.getElementById( 'preftab-' + name ) );
+ if ( $tab.length ) {
+ $tab.attr( {
+ tabIndex: 0,
+ 'aria-selected': 'true'
+ } )
+ .focus()
+ .parent().addClass( 'selected' );
+
+ $preferences.children( 'fieldset' ).hide().attr( 'aria-hidden', 'true' );
+ $( document.getElementById( 'mw-prefsection-' + name ) ).show().attr( 'aria-hidden', 'false' );
+ }
+ }
+
+ // Check for messageboxes (.successbox, .warningbox, .errorbox) to replace with notifications
+ if ( $( '.mw-preferences-messagebox' ).length ) {
+ // If there is a #mw-preferences-success box and javascript is enabled, use a slick notification instead!
+ if ( $( '#mw-preferences-success' ).length ) {
+ notif = mw.notification.notify( mw.message( 'savedprefs' ), { autoHide: false } );
+ // 'change' event not reliable!
+ $( '#preftoc, .prefsection' ).one( 'change keydown mousedown', function () {
+ if ( notif ) {
+ notif.close();
+ notif = null;
+ }
+ } );
+ }
+ }
+
+ // Enable keyboard users to use left and right keys to switch tabs
+ $preftoc.on( 'keydown', function ( event ) {
+ var keyLeft = 37,
+ keyRight = 39,
+ $el;
+
+ if ( event.keyCode === keyLeft ) {
+ $el = $( '#preftoc li.selected' ).prev().find( 'a' );
+ } else if ( event.keyCode === keyRight ) {
+ $el = $( '#preftoc li.selected' ).next().find( 'a' );
+ } else {
+ return;
+ }
+ if ( $el.length > 0 ) {
+ switchPrefTab( $el.attr( 'href' ).replace( '#mw-prefsection-', '' ) );
+ }
+ } );
+
+ // Jump to correct section as indicated by the hash.
+ // This function is called onload and onhashchange.
+ function detectHash() {
+ var hash = location.hash,
+ matchedElement, parentSection;
+ if ( hash.match( /^#mw-prefsection-[\w\-]+/ ) ) {
+ switchPrefTab( hash.replace( '#mw-prefsection-', '' ) );
+ } else if ( hash.match( /^#mw-[\w\-]+/ ) ) {
+ matchedElement = document.getElementById( hash.slice( 1 ) );
+ parentSection = $( matchedElement ).closest( '.prefsection' );
+ if ( parentSection.length ) {
+ // Switch to proper tab and scroll to selected item.
+ switchPrefTab( parentSection.attr( 'id' ).replace( 'mw-prefsection-', '' ), 'noHash' );
+ matchedElement.scrollIntoView();
+ }
+ }
+ }
+
+ // In browsers that support the onhashchange event we will not bind click
+ // handlers and instead let the browser do the default behavior (clicking the
+ // <a href="#.."> will naturally set the hash, handled by onhashchange.
+ // But other things that change the hash will also be caught (e.g. using
+ // the Back and Forward browser navigation).
+ // Note the special check for IE "compatibility" mode.
+ if ( 'onhashchange' in window &&
+ ( document.documentMode === undefined || document.documentMode >= 8 )
+ ) {
+ $( window ).on( 'hashchange', function () {
+ var hash = location.hash;
+ if ( hash.match( /^#mw-[\w\-]+/ ) ) {
+ detectHash();
+ } else if ( hash === '' ) {
+ switchPrefTab( 'personal', 'noHash' );
+ }
+ } )
+ // Run the function immediately to select the proper tab on startup.
+ .trigger( 'hashchange' );
+ // In older browsers we'll bind a click handler as fallback.
+ // We must not have onhashchange *and* the click handlers, otherwise
+ // the click handler calls switchPrefTab() which sets the hash value,
+ // which triggers onhashchange and calls switchPrefTab() again.
+ } else {
+ $preftoc.on( 'click', 'li a', function ( e ) {
+ switchPrefTab( $( this ).attr( 'href' ).replace( '#mw-prefsection-', '' ) );
+ e.preventDefault();
+ } );
+ // If we've reloaded the page or followed an open-in-new-window,
+ // make the selected tab visible.
+ detectHash();
+ }
+
+ // Timezone functions.
+ // Guesses Timezone from browser and updates fields onchange.
+
+ $tzSelect = $( '#mw-input-wptimecorrection' );
+ $tzTextbox = $( '#mw-input-wptimecorrection-other' );
+ $localtimeHolder = $( '#wpLocalTime' );
+ servertime = parseInt( $( 'input[name="wpServerTime"]' ).val(), 10 );
+
+ function minutesToHours( min ) {
+ var tzHour = Math.floor( Math.abs( min ) / 60 ),
+ tzMin = Math.abs( min ) % 60,
+ tzString = ( ( min >= 0 ) ? '' : '-' ) + ( ( tzHour < 10 ) ? '0' : '' ) + tzHour +
+ ':' + ( ( tzMin < 10 ) ? '0' : '' ) + tzMin;
+ return tzString;
+ }
+
+ function hoursToMinutes( hour ) {
+ var minutes,
+ arr = hour.split( ':' );
+
+ arr[ 0 ] = parseInt( arr[ 0 ], 10 );
+
+ if ( arr.length === 1 ) {
+ // Specification is of the form [-]XX
+ minutes = arr[ 0 ] * 60;
+ } else {
+ // Specification is of the form [-]XX:XX
+ minutes = Math.abs( arr[ 0 ] ) * 60 + parseInt( arr[ 1 ], 10 );
+ if ( arr[ 0 ] < 0 ) {
+ minutes *= -1;
+ }
+ }
+ // Gracefully handle non-numbers.
+ if ( isNaN( minutes ) ) {
+ return 0;
+ } else {
+ return minutes;
+ }
+ }
+
+ function updateTimezoneSelection() {
+ var minuteDiff, localTime,
+ type = $tzSelect.val();
+
+ if ( type === 'other' ) {
+ // User specified time zone manually in <input>
+ // Grab data from the textbox, parse it.
+ minuteDiff = hoursToMinutes( $tzTextbox.val() );
+ } else {
+ // Time zone not manually specified by user
+ if ( type === 'guess' ) {
+ // Get browser timezone & fill it in
+ minuteDiff = -( new Date().getTimezoneOffset() );
+ $tzTextbox.val( minutesToHours( minuteDiff ) );
+ $tzSelect.val( 'other' );
+ $tzTextbox.prop( 'disabled', false );
+ } else {
+ // Grab data from the $tzSelect value
+ minuteDiff = parseInt( type.split( '|' )[ 1 ], 10 ) || 0;
+ $tzTextbox.val( minutesToHours( minuteDiff ) );
+ }
+
+ // Set defaultValue prop on the generated box so we don't trigger the
+ // unsaved preferences check
+ $tzTextbox.prop( 'defaultValue', $tzTextbox.val() );
+ }
+
+ // Determine local time from server time and minutes difference, for display.
+ localTime = servertime + minuteDiff;
+
+ // Bring time within the [0,1440) range.
+ localTime = ( ( localTime % 1440 ) + 1440 ) % 1440;
+
+ $localtimeHolder.text( mw.language.convertNumber( minutesToHours( localTime ) ) );
+ }
+
+ if ( $tzSelect.length && $tzTextbox.length ) {
+ $tzSelect.change( updateTimezoneSelection );
+ $tzTextbox.blur( updateTimezoneSelection );
+ updateTimezoneSelection();
+ }
+
+ // Preserve the tab after saving the preferences
+ // Not using cookies, because their deletion results are inconsistent.
+ // Not using jStorage due to its enormous size (for this feature)
+ if ( window.sessionStorage ) {
+ if ( sessionStorage.getItem( 'mediawikiPreferencesTab' ) !== null ) {
+ switchPrefTab( sessionStorage.getItem( 'mediawikiPreferencesTab' ), 'noHash' );
+ }
+ // Deleting the key, the tab states should be reset until we press Save
+ sessionStorage.removeItem( 'mediawikiPreferencesTab' );
+
+ $( '#mw-prefs-form' ).submit( function () {
+ var storageData = $( $preftoc ).find( 'li.selected a' ).attr( 'id' ).replace( 'preftab-', '' );
+ sessionStorage.setItem( 'mediawikiPreferencesTab', storageData );
+ } );
+ }
+
+ // Check if all of the form values are unchanged
+ function isPrefsChanged() {
+ var inputs = $( '#mw-prefs-form :input[name]' ),
+ input, $input, inputType,
+ index, optIndex,
+ opt;
+
+ for ( index = 0; index < inputs.length; index++ ) {
+ input = inputs[ index ];
+ $input = $( input );
+
+ // Different types of inputs have different methods for accessing defaults
+ if ( $input.is( 'select' ) ) {
+ // <select> has the property defaultSelected for each option
+ for ( optIndex = 0; optIndex < input.options.length; optIndex++ ) {
+ opt = input.options[ optIndex ];
+ if ( opt.selected !== opt.defaultSelected ) {
+ return true;
+ }
+ }
+ } else if ( $input.is( 'input' ) ) { // <input> has defaultValue or defaultChecked
+ inputType = input.type;
+ if ( inputType === 'radio' || inputType === 'checkbox' ) {
+ if ( input.checked !== input.defaultChecked ) {
+ return true;
+ }
+ } else if ( input.value !== input.defaultValue ) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+ }
+
+ // Disable the button to save preferences unless preferences have changed
+ // Check if preferences have been changed before JS has finished loading
+ if ( !isPrefsChanged() ) {
+ $( '#prefcontrol' ).prop( 'disabled', true );
+ $( '#preferences > fieldset' ).one( 'change keydown mousedown', function () {
+ $( '#prefcontrol' ).prop( 'disabled', false );
+ } );
+ }
+
+ // Set up a message to notify users if they try to leave the page without
+ // saving.
+ allowCloseWindow = mw.confirmCloseWindow( {
+ test: isPrefsChanged,
+ message: mw.msg( 'prefswarning-warning', mw.msg( 'saveprefs' ) ),
+ namespace: 'prefswarning'
+ } );
+ $( '#mw-prefs-form' ).submit( $.proxy( allowCloseWindow, 'release' ) );
+ $( '#mw-prefs-restoreprefs' ).click( $.proxy( allowCloseWindow, 'release' ) );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.styles.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.styles.css
new file mode 100644
index 00000000..33b630a9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.styles.css
@@ -0,0 +1,47 @@
+/* Reuses colors from mediawiki.legacy/shared.css */
+.mw-email-not-authenticated .mw-input,
+.mw-email-none .mw-input {
+ border: 1px solid #fde29b;
+ background-color: #fdf1d1;
+ color: #000;
+}
+/* Authenticated email field has its own class too. Unstyled by default */
+/*
+.mw-email-authenticated .mw-input { }
+*/
+/* This breaks due to nolabel styling */
+#preferences > fieldset td.mw-label {
+ width: 20%;
+}
+
+#preferences > fieldset table {
+ width: 100%;
+}
+#preferences > fieldset table.mw-htmlform-matrix {
+ width: auto;
+}
+
+/* The CSS below is also for JS enabled version, because we want to prevent FOUC */
+
+/*
+ * Hide, but keep accessible for screen-readers.
+ * Like .mw-jump, #jump-to-nav from shared.css
+ */
+.client-js .mw-navigation-hint {
+ overflow: hidden;
+ height: 0;
+ zoom: 1;
+}
+
+.client-nojs #preftoc {
+ display: none;
+}
+
+.client-js #preferences > fieldset {
+ display: none;
+}
+
+/* Only the 1st tab is shown by default in JS mode */
+.client-js #preferences #mw-prefsection-personal {
+ display: block;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js
new file mode 100644
index 00000000..dcfad271
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.tabs.js
@@ -0,0 +1,165 @@
+/*!
+ * JavaScript for Special:Preferences: Tab navigation.
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var $preftoc, $preferences, $fieldsets, labelFunc, previousTab;
+
+ labelFunc = function () {
+ return this.id.replace( /^mw-prefsection/g, 'preftab' );
+ };
+
+ $preftoc = $( '#preftoc' );
+ $preferences = $( '#preferences' );
+
+ $fieldsets = $preferences.children( 'fieldset' )
+ .attr( {
+ role: 'tabpanel',
+ 'aria-labelledby': labelFunc
+ } );
+ $fieldsets.not( '#mw-prefsection-personal' )
+ .hide()
+ .attr( 'aria-hidden', 'true' );
+
+ // T115692: The following is kept for backwards compatibility with older skins
+ $preferences.addClass( 'jsprefs' );
+ $fieldsets.addClass( 'prefsection' );
+ $fieldsets.children( 'legend' ).addClass( 'mainLegend' );
+
+ // Make sure the accessibility tip is selectable so that screen reader users take notice,
+ // but hide it per default to reduce interface clutter. Also make sure it becomes visible
+ // when selected. Similar to jquery.mw-jump
+ $( '<div>' ).addClass( 'mw-navigation-hint' )
+ .text( mw.msg( 'prefs-tabs-navigation-hint' ) )
+ .attr( 'tabIndex', 0 )
+ .on( 'focus blur', function ( e ) {
+ if ( e.type === 'blur' || e.type === 'focusout' ) {
+ $( this ).css( 'height', '0' );
+ } else {
+ $( this ).css( 'height', 'auto' );
+ }
+ } ).insertBefore( $preftoc );
+
+ /**
+ * It uses document.getElementById for security reasons (HTML injections in $()).
+ *
+ * @ignore
+ * @param {string} name the name of a tab without the prefix ("mw-prefsection-")
+ * @param {string} [mode] A hash will be set according to the current
+ * open section. Set mode 'noHash' to surpress this.
+ */
+ function switchPrefTab( name, mode ) {
+ var $tab, scrollTop;
+ // Handle hash manually to prevent jumping,
+ // therefore save and restore scrollTop to prevent jumping.
+ scrollTop = $( window ).scrollTop();
+ if ( mode !== 'noHash' ) {
+ location.hash = '#mw-prefsection-' + name;
+ }
+ $( window ).scrollTop( scrollTop );
+
+ $preftoc.find( 'li' ).removeClass( 'selected' )
+ .find( 'a' ).attr( {
+ tabIndex: -1,
+ 'aria-selected': 'false'
+ } );
+
+ $tab = $( document.getElementById( 'preftab-' + name ) );
+ if ( $tab.length ) {
+ $tab.attr( {
+ tabIndex: 0,
+ 'aria-selected': 'true'
+ } ).focus()
+ .parent().addClass( 'selected' );
+
+ $preferences.children( 'fieldset' ).hide().attr( 'aria-hidden', 'true' );
+ $( document.getElementById( 'mw-prefsection-' + name ) ).show().attr( 'aria-hidden', 'false' );
+ }
+ }
+
+ // Enable keyboard users to use left and right keys to switch tabs
+ $preftoc.on( 'keydown', function ( event ) {
+ var keyLeft = 37,
+ keyRight = 39,
+ $el;
+
+ if ( event.keyCode === keyLeft ) {
+ $el = $( '#preftoc li.selected' ).prev().find( 'a' );
+ } else if ( event.keyCode === keyRight ) {
+ $el = $( '#preftoc li.selected' ).next().find( 'a' );
+ } else {
+ return;
+ }
+ if ( $el.length > 0 ) {
+ switchPrefTab( $el.attr( 'href' ).replace( '#mw-prefsection-', '' ) );
+ }
+ } );
+
+ // Jump to correct section as indicated by the hash.
+ // This function is called onload and onhashchange.
+ function detectHash() {
+ var hash = location.hash,
+ matchedElement, parentSection;
+ if ( hash.match( /^#mw-prefsection-[\w]+$/ ) ) {
+ mw.storage.session.remove( 'mwpreferences-prevTab' );
+ switchPrefTab( hash.replace( '#mw-prefsection-', '' ) );
+ } else if ( hash.match( /^#mw-[\w-]+$/ ) ) {
+ matchedElement = document.getElementById( hash.slice( 1 ) );
+ parentSection = $( matchedElement ).parent().closest( '[id^="mw-prefsection-"]' );
+ if ( parentSection.length ) {
+ mw.storage.session.remove( 'mwpreferences-prevTab' );
+ // Switch to proper tab and scroll to selected item.
+ switchPrefTab( parentSection.attr( 'id' ).replace( 'mw-prefsection-', '' ), 'noHash' );
+ matchedElement.scrollIntoView();
+ }
+ }
+ }
+
+ // In browsers that support the onhashchange event we will not bind click
+ // handlers and instead let the browser do the default behavior (clicking the
+ // <a href="#.."> will naturally set the hash, handled by onhashchange.
+ // But other things that change the hash will also be caught (e.g. using
+ // the Back and Forward browser navigation).
+ // Note the special check for IE "compatibility" mode.
+ if ( 'onhashchange' in window &&
+ ( document.documentMode === undefined || document.documentMode >= 8 )
+ ) {
+ $( window ).on( 'hashchange', function () {
+ var hash = location.hash;
+ if ( hash.match( /^#mw-[\w-]+/ ) ) {
+ detectHash();
+ } else if ( hash === '' ) {
+ switchPrefTab( 'personal', 'noHash' );
+ }
+ } )
+ // Run the function immediately to select the proper tab on startup.
+ .trigger( 'hashchange' );
+ // In older browsers we'll bind a click handler as fallback.
+ // We must not have onhashchange *and* the click handlers, otherwise
+ // the click handler calls switchPrefTab() which sets the hash value,
+ // which triggers onhashchange and calls switchPrefTab() again.
+ } else {
+ $preftoc.on( 'click', 'li a', function ( e ) {
+ switchPrefTab( $( this ).attr( 'href' ).replace( '#mw-prefsection-', '' ) );
+ e.preventDefault();
+ } );
+ // If we've reloaded the page or followed an open-in-new-window,
+ // make the selected tab visible.
+ detectHash();
+ }
+
+ // Restore the active tab after saving the preferences
+ previousTab = mw.storage.session.get( 'mwpreferences-prevTab' );
+ if ( previousTab ) {
+ switchPrefTab( previousTab, 'noHash' );
+ // Deleting the key, the tab states should be reset until we press Save
+ mw.storage.session.remove( 'mwpreferences-prevTab' );
+ }
+
+ $( '#mw-prefs-form' ).on( 'submit', function () {
+ var value = $( $preftoc ).find( 'li.selected a' ).attr( 'id' ).replace( 'preftab-', '' );
+ mw.storage.session.set( 'mwpreferences-prevTab', value );
+ } );
+
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js
new file mode 100644
index 00000000..58a5f84a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.preferences.timezone.js
@@ -0,0 +1,92 @@
+/*!
+ * JavaScript for Special:Preferences: Timezone field enhancements.
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var
+ $tzSelect, $tzTextbox, $localtimeHolder, servertime;
+
+ // Timezone functions.
+ // Guesses Timezone from browser and updates fields onchange.
+
+ $tzSelect = $( '#mw-input-wptimecorrection' );
+ $tzTextbox = $( '#mw-input-wptimecorrection-other' );
+ $localtimeHolder = $( '#wpLocalTime' );
+ servertime = parseInt( $( 'input[name="wpServerTime"]' ).val(), 10 );
+
+ function minutesToHours( min ) {
+ var tzHour = Math.floor( Math.abs( min ) / 60 ),
+ tzMin = Math.abs( min ) % 60,
+ tzString = ( ( min >= 0 ) ? '' : '-' ) + ( ( tzHour < 10 ) ? '0' : '' ) + tzHour +
+ ':' + ( ( tzMin < 10 ) ? '0' : '' ) + tzMin;
+ return tzString;
+ }
+
+ function hoursToMinutes( hour ) {
+ var minutes,
+ arr = hour.split( ':' );
+
+ arr[ 0 ] = parseInt( arr[ 0 ], 10 );
+
+ if ( arr.length === 1 ) {
+ // Specification is of the form [-]XX
+ minutes = arr[ 0 ] * 60;
+ } else {
+ // Specification is of the form [-]XX:XX
+ minutes = Math.abs( arr[ 0 ] ) * 60 + parseInt( arr[ 1 ], 10 );
+ if ( arr[ 0 ] < 0 ) {
+ minutes *= -1;
+ }
+ }
+ // Gracefully handle non-numbers.
+ if ( isNaN( minutes ) ) {
+ return 0;
+ } else {
+ return minutes;
+ }
+ }
+
+ function updateTimezoneSelection() {
+ var minuteDiff, localTime,
+ type = $tzSelect.val();
+
+ if ( type === 'other' ) {
+ // User specified time zone manually in <input>
+ // Grab data from the textbox, parse it.
+ minuteDiff = hoursToMinutes( $tzTextbox.val() );
+ } else {
+ // Time zone not manually specified by user
+ if ( type === 'guess' ) {
+ // Get browser timezone & fill it in
+ minuteDiff = -( new Date().getTimezoneOffset() );
+ $tzTextbox.val( minutesToHours( minuteDiff ) );
+ $tzSelect.val( 'other' );
+ $tzTextbox.prop( 'disabled', false );
+ } else {
+ // Grab data from the $tzSelect value
+ minuteDiff = parseInt( type.split( '|' )[ 1 ], 10 ) || 0;
+ $tzTextbox.val( minutesToHours( minuteDiff ) );
+ }
+
+ // Set defaultValue prop on the generated box so we don't trigger the
+ // unsaved preferences check
+ $tzTextbox.prop( 'defaultValue', $tzTextbox.val() );
+ }
+
+ // Determine local time from server time and minutes difference, for display.
+ localTime = servertime + minuteDiff;
+
+ // Bring time within the [0,1440) range.
+ localTime = ( ( localTime % 1440 ) + 1440 ) % 1440;
+
+ $localtimeHolder.text( mw.language.convertNumber( minutesToHours( localTime ) ) );
+ }
+
+ if ( $tzSelect.length && $tzTextbox.length ) {
+ $tzSelect.change( updateTimezoneSelection );
+ $tzTextbox.blur( updateTimezoneSelection );
+ updateTimezoneSelection();
+ }
+
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.recentchanges.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.recentchanges.js
new file mode 100644
index 00000000..29c0feaf
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.recentchanges.js
@@ -0,0 +1,38 @@
+/*!
+ * JavaScript for Special:RecentChanges
+ */
+( function ( mw, $ ) {
+ var rc, $checkboxes, $select;
+
+ /**
+ * @class mw.special.recentchanges
+ * @singleton
+ */
+ rc = {
+ /**
+ * Handler to disable/enable the namespace selector checkboxes when the
+ * special 'all' namespace is selected/unselected respectively.
+ */
+ updateCheckboxes: function () {
+ // The option element for the 'all' namespace has an empty value
+ var isAllNS = $select.val() === '';
+
+ // Iterates over checkboxes and propagate the selected option
+ $checkboxes.prop( 'disabled', isAllNS );
+ },
+
+ init: function () {
+ $select = $( '#namespace' );
+ $checkboxes = $( '#nsassociated, #nsinvert' );
+
+ // Bind to change event, and trigger once to set the initial state of the checkboxes.
+ rc.updateCheckboxes();
+ $select.change( rc.updateCheckboxes );
+ }
+ };
+
+ $( rc.init );
+
+ module.exports = rc;
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.commonsInterwikiWidget.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.commonsInterwikiWidget.js
new file mode 100644
index 00000000..648bf675
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.commonsInterwikiWidget.js
@@ -0,0 +1,78 @@
+( function ( mw, $ ) {
+
+ var api = new mw.Api(),
+ pageUrl = new mw.Uri(),
+ imagesText = new mw.Message( mw.messages, 'searchprofile-images' ),
+ moreResultsText = new mw.Message( mw.messages, 'search-interwiki-more-results' );
+
+ function itemTemplate( results ) {
+
+ var resultOutput = '', i, result, imageCaption, imageThumbnailSrc;
+
+ for ( i = 0; i < results.length; i++ ) {
+ result = results[ i ];
+ imageCaption = mw.html.element( 'span', { 'class': 'iw-result__mini-gallery__caption' }, result.title );
+ imageThumbnailSrc = ( result.thumbnail ) ? result.thumbnail.source : '';
+ resultOutput += '<div class="iw-result__mini-gallery">' +
+ /* escaping response content */
+ mw.html.element( 'a', {
+ href: '/wiki/' + result.title,
+ 'class': 'iw-result__mini-gallery__image',
+ style: 'background-image: url(' + imageThumbnailSrc + ');'
+ }, new mw.html.Raw( imageCaption ) ) +
+ '</div>';
+ }
+
+ return resultOutput;
+ }
+
+ function itemWrapperTemplate( pageQuery, itemTemplateOutput ) {
+
+ return '<li class="iw-resultset iw-resultset--image" data-iw-resultset-pos="0">' +
+ '<div class="iw-result__header">' +
+ '<strong>' + imagesText.escaped() + '</strong>' +
+ '</div>' +
+ '<div class="iw-result__content">' +
+ /* template output has been sanitized by mw.html.element */
+ itemTemplateOutput +
+ '</div>' +
+ '<div class="iw-result__footer">' +
+ '<a href="/w/index.php?title=Special:Search&search=' + encodeURIComponent( pageQuery ) + '&fulltext=1&profile=images">' +
+ moreResultsText.escaped() +
+ '</a>' +
+ '</div>' +
+ '</li>';
+
+ }
+
+ api.get( {
+ action: 'query',
+ generator: 'search',
+ gsrsearch: pageUrl.query.search,
+ gsrnamespace: mw.config.get( 'wgNamespaceIds' ).file,
+ gsrlimit: 3,
+ prop: 'pageimages',
+ pilimit: 3,
+ piprop: 'thumbnail',
+ pithumbsize: 300,
+ formatversion: 2
+ } ).done( function ( resp ) {
+ var results = ( resp.query && resp.query.pages ) ? resp.query.pages : false,
+ multimediaWidgetTemplate;
+
+ if ( !results ) {
+ return;
+ }
+
+ results.sort( function ( a, b ) {
+ return a.index - b.index;
+ } );
+
+ multimediaWidgetTemplate = itemWrapperTemplate( pageUrl.query.search, itemTemplate( results ) );
+ /* we really only need to wait for document ready for DOM manipulation */
+ $( function () {
+ $( '.iw-results' ).append( multimediaWidgetTemplate );
+ } );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.css
new file mode 100644
index 00000000..aad784e2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.css
@@ -0,0 +1,9 @@
+#mw-search-togglebox {
+ float: right;
+}
+#mw-search-togglebox label {
+ margin-right: 0.25em;
+}
+#mw-search-togglebox input {
+ margin-left: 0.25em;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.interwikiwidget.styles.less b/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.interwikiwidget.styles.less
new file mode 100644
index 00000000..8ec2735e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.interwikiwidget.styles.less
@@ -0,0 +1,121 @@
+/* interwiki search results */
+/*==========================*/
+
+@import 'mediawiki.ui/variables.less';
+@import 'mediawiki.mixins';
+
+.mw-searchresults-has-iw {
+
+ .iw-headline {
+ font-weight: bold;
+ }
+
+ .iw-results {
+ list-style: none;
+ margin: 0;
+ }
+
+ .iw-resultset {
+ .box-sizing(border-box);
+ padding: 0.5em;
+ vertical-align: top;
+ width: 100%;
+ float: left;
+ background-color: @colorGray15;
+ margin-bottom: 1em;
+ word-break: break-word;
+ }
+
+ .iw-result__title {
+ font-size: 108%; /* matching regular search title */
+ }
+
+ .iw-result:after,
+ .iw-result__content:after { /* clearfix */
+ visibility: hidden;
+ display: block;
+ font-size: 0;
+ content: ' ';
+ clear: both;
+ height: 0;
+ }
+
+ .iw-result__footer {
+ float: right;
+ font-size: 97%; /* matching main search result font-size */
+ margin-top: 0.5em;
+ }
+ .iw-result__footer a {
+ vertical-align: middle;
+ font-style: italic;
+ }
+
+ .oo-ui-icon-favicon {
+ padding-right: 1em;
+ }
+
+ /* image search result */
+ .iw-result__mini-gallery {
+ position: relative;
+ float: left;
+ width: 100%;
+ height: 200px;
+ .box-sizing(border-box);
+ padding: 0.25rem;
+ }
+
+ /* second and third images are small */
+ .iw-result__mini-gallery:nth-child( 2 ),
+ .iw-result__mini-gallery:nth-child( 3 ) { /* stylelint-disable-line indentation */
+ width: 50%;
+ height: 100px;
+ }
+
+ .iw-result__mini-gallery__image {
+ display: block;
+ position: relative;
+ width: 100%;
+ height: 100%;
+ background-size: 100% auto;
+ background-size: cover;
+ background-repeat: no-repeat;
+ background-position: center center;
+ }
+
+ /* image gallery text */
+ .iw-result__mini-gallery__image > .iw-result__mini-gallery__caption {
+ visibility: hidden;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ text-align: center;
+ color: #fff;
+ font-size: 0.8em;
+ padding: 0.5em;
+ background-color: rgba( 0, 0, 0, 0.5 );
+ }
+
+ .iw-result__mini-gallery__image:hover > .iw-result__mini-gallery__caption {
+ visibility: visible;
+ }
+
+ /* tablet and up */
+
+ @media only screen and ( min-width: @deviceWidthTablet ) {
+
+ #mw-interwiki-results {
+ width: 30%;
+ display: inline-block; /* used to align interwiki sidebar with the top of the main search results */
+ margin-left: 8%; /* since inline-block causes whitespace issues, this is 8 instead of 10% */
+ }
+ .mw-search-createlink,
+ .mw-search-nonefound,
+ .mw-search-results,
+ .mw-search-interwiki-header {
+ float: left;
+ width: 60%;
+ clear: left;
+ max-width: 60%;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.js
new file mode 100644
index 00000000..e809f2ea
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.js
@@ -0,0 +1,60 @@
+/*!
+ * JavaScript for Special:Search
+ */
+( function ( mw, $ ) {
+ $( function () {
+ var $checkboxes, $headerLinks, updateHeaderLinks, searchWidget;
+
+ // Emulate HTML5 autofocus behavior in non HTML5 compliant browsers
+ if ( !( 'autofocus' in document.createElement( 'input' ) ) ) {
+ $( 'input[autofocus]' ).eq( 0 ).focus();
+ }
+
+ // Create check all/none button
+ $checkboxes = $( '#powersearch input[id^=mw-search-ns]' );
+ $( '#mw-search-togglebox' ).append(
+ $( '<label>' )
+ .text( mw.msg( 'powersearch-togglelabel' ) )
+ ).append(
+ $( '<input>' ).attr( 'type', 'button' )
+ .attr( 'id', 'mw-search-toggleall' )
+ .prop( 'value', mw.msg( 'powersearch-toggleall' ) )
+ .click( function () {
+ $checkboxes.prop( 'checked', true );
+ } )
+ ).append(
+ $( '<input>' ).attr( 'type', 'button' )
+ .attr( 'id', 'mw-search-togglenone' )
+ .prop( 'value', mw.msg( 'powersearch-togglenone' ) )
+ .click( function () {
+ $checkboxes.prop( 'checked', false );
+ } )
+ );
+
+ // Change the header search links to what user entered
+ $headerLinks = $( '.search-types a' );
+ searchWidget = OO.ui.infuse( 'searchText' );
+ updateHeaderLinks = function ( value ) {
+ $headerLinks.each( function () {
+ var parts = $( this ).attr( 'href' ).split( 'search=' ),
+ lastpart = '',
+ prefix = 'search=';
+ if ( parts.length > 1 && parts[ 1 ].indexOf( '&' ) !== -1 ) {
+ lastpart = parts[ 1 ].slice( parts[ 1 ].indexOf( '&' ) );
+ } else {
+ prefix = '&search=';
+ }
+ this.href = parts[ 0 ] + prefix + encodeURIComponent( value ) + lastpart;
+ } );
+ };
+ searchWidget.on( 'change', updateHeaderLinks );
+ updateHeaderLinks( searchWidget.getValue() );
+
+ // When saving settings, use the proper request method (POST instead of GET).
+ $( '#mw-search-powersearch-remember' ).change( function () {
+ this.form.method = this.checked ? 'post' : 'get';
+ } ).trigger( 'change' );
+
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.styles.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.styles.css
new file mode 100644
index 00000000..ea9b987d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.search.styles.css
@@ -0,0 +1,166 @@
+/* Special:Search */
+
+/*
+ * Fixes sister projects box moving down the extract
+ * of the first result (bug #16886).
+ * It only happens when the window is small and
+ * This changes slightly the layout for big screens
+ * where there was space for the extracts and the
+ * sister projects and thus it showed like in any
+ * other browser.
+ *
+ * This will only affect IE 7 and lower
+ */
+.searchresult {
+ display: inline !ie;
+}
+.searchresults {
+ margin: 1em 0 1em 0.4em;
+}
+/* needs extra specificity to override `.mw-body p` selector */
+.mw-body .mw-search-nonefound {
+ margin: 0;
+}
+
+.searchdidyoumean em,
+.searchmatch {
+ font-weight: bold;
+}
+
+.mw-search-results {
+ margin: 0;
+ max-width: 38em;
+}
+
+.mw-search-visualclear {
+ clear: both;
+}
+.mw-search-results li {
+ padding-bottom: 1.2em;
+ list-style: none;
+ list-style-image: none;
+}
+.mw-search-results li a {
+ font-size: 108%;
+}
+.mw-search-result-data {
+ color: #008000;
+ font-size: 97%;
+}
+.mw-search-profile-tabs {
+ background-color: #f8f9fa;
+ margin-top: 1em;
+ border: 1px solid #c8ccd1;
+ border-radius: 2px;
+}
+.search-types {
+ float: left;
+ padding-left: 0.25em;
+}
+.search-types ul {
+ margin: 0;
+ padding: 0;
+ list-style: none;
+}
+.search-types li {
+ float: left;
+ margin: 0;
+ padding: 0;
+}
+.search-types a {
+ display: block;
+ padding: 0.5em;
+}
+.search-types .current a {
+ color: #222;
+ cursor: default;
+}
+.search-types .current a:hover {
+ text-decoration: none;
+}
+.results-info {
+ float: right;
+ padding: 0.5em;
+ padding-right: 0.75em;
+ color: #54595d;
+ font-size: 95%;
+}
+#mw-search-top-table div.oo-ui-actionFieldLayout {
+ float: left;
+ width: 100%;
+}
+
+/* Advanced options menu */
+/*==========================*/
+
+#mw-searchoptions {
+ /* Support: Firefox, needs `clear: both` on `fieldset` when zoom level > 100%, see T176499 */
+ clear: both;
+ padding: 0.5em 0.75em 0.75em 0.75em;
+ background-color: #f8f9fa;
+ margin: -1px 0 0;
+ border: 1px solid #c8ccd1;
+ border-radius: 0 0 2px 2px;
+}
+#mw-searchoptions legend {
+ display: none;
+}
+#mw-searchoptions h4 {
+ padding: 0;
+ margin: 0;
+ float: left;
+}
+#mw-searchoptions table {
+ float: left;
+ margin-right: 3em;
+ border-collapse: collapse;
+}
+#mw-searchoptions table td {
+ padding: 0 1em 0 0;
+ white-space: nowrap;
+}
+#mw-searchoptions .divider {
+ clear: both;
+ border-bottom: 1px solid #eaecf0;
+ padding-top: 0.5em;
+ margin-bottom: 0.5em;
+}
+#mw-search-menu {
+ padding-left: 6em;
+ font-size: 85%;
+}
+
+#mw-search-interwiki {
+ float: right;
+ width: 18em;
+ border: 1px solid #a2a9b1;
+ margin-top: 2ex;
+}
+
+.searchalttitle,
+#mw-search-interwiki li {
+ font-size: 95%;
+}
+.mw-search-interwiki-more {
+ float: right;
+ font-size: 90%;
+}
+#mw-search-interwiki-caption {
+ text-align: center;
+ font-weight: bold;
+ font-size: 95%;
+}
+.mw-search-interwiki-project {
+ font-size: 97%;
+ text-align: left;
+ padding: 0.15em 0.15em 0.2em 0.2em;
+ background-color: #eaecf0;
+ border-top: 1px solid #c8ccd1;
+}
+
+.searchdidyoumean {
+ font-size: 127%;
+ margin-top: 0.8em;
+ /* Note that this color won't affect the link, as desired. */
+ color: #d33;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.undelete.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.undelete.js
new file mode 100644
index 00000000..4629d57a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.undelete.js
@@ -0,0 +1,10 @@
+/*!
+ * JavaScript for Special:Undelete
+ */
+jQuery( function ( $ ) {
+ $( '#mw-undelete-invert' ).click( function () {
+ $( '.mw-undelete-revlist input[type="checkbox"]' ).prop( 'checked', function ( i, val ) {
+ return !val;
+ } );
+ } );
+} );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.unwatchedPages.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.unwatchedPages.css
new file mode 100644
index 00000000..054f45fc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.unwatchedPages.css
@@ -0,0 +1,9 @@
+.mw-watched-item {
+ text-decoration: line-through;
+}
+
+.mw-watch-link-disabled {
+ pointer-events: none;
+ /* Fallback for older browsers not supporting pointer-events: none */
+ cursor: default;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.unwatchedPages.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.unwatchedPages.js
new file mode 100644
index 00000000..7628ff88
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.unwatchedPages.js
@@ -0,0 +1,52 @@
+/*!
+ * JavaScript for Special:UnwatchedPages
+ */
+( function ( mw, $ ) {
+ $( function () {
+ $( 'a.mw-watch-link' ).click( function ( e ) {
+ var promise,
+ api = new mw.Api(),
+ $link = $( this ),
+ $subjectLink = $link.closest( 'li' ).children( 'a' ).eq( 0 ),
+ title = mw.util.getParamValue( 'title', $link.attr( 'href' ) );
+ // nice format
+ title = mw.Title.newFromText( title ).toText();
+ // Disable link whilst we're busy to avoid double handling
+ if ( $link.data( 'mwDisabled' ) ) {
+ // mw-watch-link-disabled disables pointer-events which prevents the click event
+ // from happening in the first place. In older browsers we kill the event here.
+ return false;
+ }
+ $link.data( 'mwDisabled', true ).addClass( 'mw-watch-link-disabled' );
+
+ // Use the class to determine whether to watch or unwatch
+ if ( !$subjectLink.hasClass( 'mw-watched-item' ) ) {
+ $link.text( mw.msg( 'watching' ) );
+ promise = api.watch( title ).done( function () {
+ $subjectLink.addClass( 'mw-watched-item' );
+ $link.text( mw.msg( 'unwatch' ) );
+ mw.notify( mw.msg( 'addedwatchtext-short', title ) );
+ } ).fail( function () {
+ $link.text( mw.msg( 'watch' ) );
+ mw.notify( mw.msg( 'watcherrortext', title ), { type: 'error' } );
+ } );
+ } else {
+ $link.text( mw.msg( 'unwatching' ) );
+ promise = api.unwatch( title ).done( function () {
+ $subjectLink.removeClass( 'mw-watched-item' );
+ $link.text( mw.msg( 'watch' ) );
+ mw.notify( mw.msg( 'removedwatchtext-short', title ) );
+ } ).fail( function () {
+ $link.text( mw.msg( 'unwatch' ) );
+ mw.notify( mw.msg( 'watcherrortext', title ), { type: 'error' } );
+ } );
+ }
+
+ promise.always( function () {
+ $link.data( 'mwDisabled', false ).removeClass( 'mw-watch-link-disabled' );
+ } );
+
+ e.preventDefault();
+ } );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.css
new file mode 100644
index 00000000..b916248e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.css
@@ -0,0 +1,10 @@
+/*!
+ * Styling for Special:Upload
+ */
+.mw-destfile-warning {
+ border: 1px solid #fde29b;
+ padding: .5em 1em;
+ margin-bottom: 1em;
+ color: #705000;
+ background-color: #fdf1d1;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.js
new file mode 100644
index 00000000..0ddf7fe3
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.js
@@ -0,0 +1,615 @@
+/**
+ * JavaScript for Special:Upload
+ *
+ * @private
+ * @class mw.special.upload
+ * @singleton
+ */
+
+/* eslint-disable no-use-before-define */
+/* global Uint8Array */
+
+( function ( mw, $ ) {
+ var uploadWarning, uploadLicense,
+ ajaxUploadDestCheck = mw.config.get( 'wgAjaxUploadDestCheck' ),
+ $license = $( '#wpLicense' );
+
+ window.wgUploadWarningObj = uploadWarning = {
+ responseCache: { '': '&nbsp;' },
+ nameToCheck: '',
+ typing: false,
+ delay: 500, // ms
+ timeoutID: false,
+
+ keypress: function () {
+ if ( !ajaxUploadDestCheck ) {
+ return;
+ }
+
+ // Find file to upload
+ if ( !$( '#wpDestFile' ).length || !$( '#wpDestFile-warning' ).length ) {
+ return;
+ }
+
+ this.nameToCheck = $( '#wpDestFile' ).val();
+
+ // Clear timer
+ if ( this.timeoutID ) {
+ clearTimeout( this.timeoutID );
+ }
+ // Check response cache
+ if ( this.responseCache.hasOwnProperty( this.nameToCheck ) ) {
+ this.setWarning( this.responseCache[ this.nameToCheck ] );
+ return;
+ }
+
+ this.timeoutID = setTimeout( function () {
+ uploadWarning.timeout();
+ }, this.delay );
+ },
+
+ checkNow: function ( fname ) {
+ if ( !ajaxUploadDestCheck ) {
+ return;
+ }
+ if ( this.timeoutID ) {
+ clearTimeout( this.timeoutID );
+ }
+ this.nameToCheck = fname;
+ this.timeout();
+ },
+
+ timeout: function () {
+ var $spinnerDestCheck, title;
+ if ( !ajaxUploadDestCheck || this.nameToCheck === '' ) {
+ return;
+ }
+ $spinnerDestCheck = $.createSpinner().insertAfter( '#wpDestFile' );
+ title = mw.Title.newFromText( this.nameToCheck, mw.config.get( 'wgNamespaceIds' ).file );
+
+ ( new mw.Api() ).get( {
+ formatversion: 2,
+ action: 'query',
+ // If title is empty, user input is invalid, the API call will produce details about why
+ titles: title ? title.getPrefixedText() : this.nameToCheck,
+ prop: 'imageinfo',
+ iiprop: 'uploadwarning'
+ } ).done( function ( result ) {
+ var
+ resultOut = '',
+ page = result.query.pages[ 0 ];
+ if ( page.imageinfo ) {
+ resultOut = page.imageinfo[ 0 ].html;
+ } else if ( page.invalidreason ) {
+ resultOut = mw.html.escape( page.invalidreason );
+ }
+ uploadWarning.processResult( resultOut, uploadWarning.nameToCheck );
+ } ).always( function () {
+ $spinnerDestCheck.remove();
+ } );
+ },
+
+ processResult: function ( result, fileName ) {
+ this.setWarning( result );
+ this.responseCache[ fileName ] = result;
+ },
+
+ setWarning: function ( warning ) {
+ var $warningBox = $( '#wpDestFile-warning' ),
+ $warning = $( $.parseHTML( warning ) );
+ mw.hook( 'wikipage.content' ).fire( $warning );
+ $warningBox.empty().append( $warning );
+
+ // Set a value in the form indicating that the warning is acknowledged and
+ // doesn't need to be redisplayed post-upload
+ if ( !warning ) {
+ $( '#wpDestFileWarningAck' ).val( '' );
+ $warningBox.removeAttr( 'class' );
+ } else {
+ $( '#wpDestFileWarningAck' ).val( '1' );
+ $warningBox.attr( 'class', 'mw-destfile-warning' );
+ }
+
+ }
+ };
+
+ uploadLicense = {
+
+ responseCache: { '': '' },
+
+ fetchPreview: function ( license ) {
+ var $spinnerLicense;
+ if ( !mw.config.get( 'wgAjaxLicensePreview' ) ) {
+ return;
+ }
+ if ( this.responseCache.hasOwnProperty( license ) ) {
+ this.showPreview( this.responseCache[ license ] );
+ return;
+ }
+
+ $spinnerLicense = $.createSpinner().insertAfter( '#wpLicense' );
+
+ ( new mw.Api() ).get( {
+ formatversion: 2,
+ action: 'parse',
+ text: '{{' + license + '}}',
+ title: $( '#wpDestFile' ).val() || 'File:Sample.jpg',
+ prop: 'text',
+ pst: true
+ } ).done( function ( result ) {
+ uploadLicense.processResult( result, license );
+ } ).always( function () {
+ $spinnerLicense.remove();
+ } );
+ },
+
+ processResult: function ( result, license ) {
+ this.responseCache[ license ] = result.parse.text;
+ this.showPreview( this.responseCache[ license ] );
+ },
+
+ showPreview: function ( preview ) {
+ $( '#mw-license-preview' ).html( preview );
+ }
+
+ };
+
+ $( function () {
+ // AJAX wpDestFile warnings
+ if ( ajaxUploadDestCheck ) {
+ // Insert an event handler that fetches upload warnings when wpDestFile
+ // has been changed
+ $( '#wpDestFile' ).change( function () {
+ uploadWarning.checkNow( $( this ).val() );
+ } );
+ // Insert a row where the warnings will be displayed just below the
+ // wpDestFile row
+ $( '#mw-htmlform-description tbody' ).append(
+ $( '<tr>' ).append(
+ $( '<td>' )
+ .attr( 'id', 'wpDestFile-warning' )
+ .attr( 'colspan', 2 )
+ )
+ );
+ }
+
+ if ( mw.config.get( 'wgAjaxLicensePreview' ) && $license.length ) {
+ // License selector check
+ $license.change( function () {
+ // We might show a preview
+ uploadLicense.fetchPreview( $license.val() );
+ } );
+
+ // License selector table row
+ $license.closest( 'tr' ).after(
+ $( '<tr>' ).append(
+ $( '<td>' ),
+ $( '<td>' ).attr( 'id', 'mw-license-preview' )
+ )
+ );
+ }
+
+ // fillDestFile setup
+ $.each( mw.config.get( 'wgUploadSourceIds' ), function ( index, sourceId ) {
+ $( '#' + sourceId ).change( function () {
+ var path, slash, backslash, fname;
+ if ( !mw.config.get( 'wgUploadAutoFill' ) ) {
+ return;
+ }
+ // Remove any previously flagged errors
+ $( '#mw-upload-permitted' ).attr( 'class', '' );
+ $( '#mw-upload-prohibited' ).attr( 'class', '' );
+
+ path = $( this ).val();
+ // Find trailing part
+ slash = path.lastIndexOf( '/' );
+ backslash = path.lastIndexOf( '\\' );
+ if ( slash === -1 && backslash === -1 ) {
+ fname = path;
+ } else if ( slash > backslash ) {
+ fname = path.slice( slash + 1 );
+ } else {
+ fname = path.slice( backslash + 1 );
+ }
+
+ // Clear the filename if it does not have a valid extension.
+ // URLs are less likely to have a useful extension, so don't include them in the
+ // extension check.
+ if (
+ mw.config.get( 'wgCheckFileExtensions' ) &&
+ mw.config.get( 'wgStrictFileExtensions' ) &&
+ mw.config.get( 'wgFileExtensions' ) &&
+ $( this ).attr( 'id' ) !== 'wpUploadFileURL'
+ ) {
+ if (
+ fname.lastIndexOf( '.' ) === -1 ||
+ $.inArray(
+ fname.slice( fname.lastIndexOf( '.' ) + 1 ).toLowerCase(),
+ $.map( mw.config.get( 'wgFileExtensions' ), function ( element ) {
+ return element.toLowerCase();
+ } )
+ ) === -1
+ ) {
+ // Not a valid extension
+ // Clear the upload and set mw-upload-permitted to error
+ $( this ).val( '' );
+ $( '#mw-upload-permitted' ).attr( 'class', 'error' );
+ $( '#mw-upload-prohibited' ).attr( 'class', 'error' );
+ // Clear wpDestFile as well
+ $( '#wpDestFile' ).val( '' );
+
+ return false;
+ }
+ }
+
+ // Replace spaces by underscores
+ fname = fname.replace( / /g, '_' );
+ // Capitalise first letter if needed
+ if ( mw.config.get( 'wgCapitalizeUploads' ) ) {
+ fname = fname[ 0 ].toUpperCase() + fname.slice( 1 );
+ }
+
+ // Output result
+ if ( $( '#wpDestFile' ).length ) {
+ // Call decodeURIComponent function to remove possible URL-encoded characters
+ // from the file name (T32390). Especially likely with upload-form-url.
+ // decodeURIComponent can throw an exception if input is invalid utf-8
+ try {
+ $( '#wpDestFile' ).val( decodeURIComponent( fname ) );
+ } catch ( err ) {
+ $( '#wpDestFile' ).val( fname );
+ }
+ uploadWarning.checkNow( fname );
+ }
+ } );
+ } );
+ } );
+
+ // Add a preview to the upload form
+ $( function () {
+ /**
+ * Is the FileAPI available with sufficient functionality?
+ *
+ * @return {boolean}
+ */
+ function hasFileAPI() {
+ return window.FileReader !== undefined;
+ }
+
+ /**
+ * Check if this is a recognizable image type...
+ * Also excludes files over 10M to avoid going insane on memory usage.
+ *
+ * TODO: Is there a way we can ask the browser what's supported in `<img>`s?
+ *
+ * TODO: Put SVG back after working around Firefox 7 bug <https://phabricator.wikimedia.org/T33643>
+ *
+ * @param {File} file
+ * @return {boolean}
+ */
+ function fileIsPreviewable( file ) {
+ var known = [ 'image/png', 'image/gif', 'image/jpeg', 'image/svg+xml' ],
+ tooHuge = 10 * 1024 * 1024;
+ return ( $.inArray( file.type, known ) !== -1 ) && file.size > 0 && file.size < tooHuge;
+ }
+
+ /**
+ * Format a file size attractively.
+ *
+ * TODO: Match numeric formatting
+ *
+ * @param {number} s
+ * @return {string}
+ */
+ function prettySize( s ) {
+ var sizeMsgs = [ 'size-bytes', 'size-kilobytes', 'size-megabytes', 'size-gigabytes' ];
+ while ( s >= 1024 && sizeMsgs.length > 1 ) {
+ s /= 1024;
+ sizeMsgs = sizeMsgs.slice( 1 );
+ }
+ return mw.msg( sizeMsgs[ 0 ], Math.round( s ) );
+ }
+
+ /**
+ * Show a thumbnail preview of PNG, JPEG, GIF, and SVG files prior to upload
+ * in browsers supporting HTML5 FileAPI.
+ *
+ * As of this writing, known good:
+ *
+ * - Firefox 3.6+
+ * - Chrome 7.something
+ *
+ * TODO: Check file size limits and warn of likely failures
+ *
+ * @param {File} file
+ */
+ function showPreview( file ) {
+ var $canvas,
+ ctx,
+ meta,
+ previewSize = 180,
+ $spinner = $.createSpinner( { size: 'small', type: 'block' } )
+ .css( { width: previewSize, height: previewSize } ),
+ thumb = mw.template.get( 'mediawiki.special.upload', 'thumbnail.html' ).render();
+
+ thumb
+ .find( '.filename' ).text( file.name ).end()
+ .find( '.fileinfo' ).text( prettySize( file.size ) ).end()
+ .find( '.thumbinner' ).prepend( $spinner ).end();
+
+ $canvas = $( '<canvas>' ).attr( { width: previewSize, height: previewSize } );
+ ctx = $canvas[ 0 ].getContext( '2d' );
+ $( '#mw-htmlform-source' ).parent().prepend( thumb );
+
+ fetchPreview( file, function ( dataURL ) {
+ var img = new Image(),
+ rotation = 0;
+
+ if ( meta && meta.tiff && meta.tiff.Orientation ) {
+ rotation = ( 360 - ( function () {
+ // See includes/media/Bitmap.php
+ switch ( meta.tiff.Orientation.value ) {
+ case 8:
+ return 90;
+ case 3:
+ return 180;
+ case 6:
+ return 270;
+ default:
+ return 0;
+ }
+ }() ) ) % 360;
+ }
+
+ img.onload = function () {
+ var info, width, height, x, y, dx, dy, logicalWidth, logicalHeight;
+
+ // Fit the image within the previewSizexpreviewSize box
+ if ( img.width > img.height ) {
+ width = previewSize;
+ height = img.height / img.width * previewSize;
+ } else {
+ height = previewSize;
+ width = img.width / img.height * previewSize;
+ }
+ // Determine the offset required to center the image
+ dx = ( 180 - width ) / 2;
+ dy = ( 180 - height ) / 2;
+ switch ( rotation ) {
+ // If a rotation is applied, the direction of the axis
+ // changes as well. You can derive the values below by
+ // drawing on paper an axis system, rotate it and see
+ // where the positive axis direction is
+ case 0:
+ x = dx;
+ y = dy;
+ logicalWidth = img.width;
+ logicalHeight = img.height;
+ break;
+ case 90:
+
+ x = dx;
+ y = dy - previewSize;
+ logicalWidth = img.height;
+ logicalHeight = img.width;
+ break;
+ case 180:
+ x = dx - previewSize;
+ y = dy - previewSize;
+ logicalWidth = img.width;
+ logicalHeight = img.height;
+ break;
+ case 270:
+ x = dx - previewSize;
+ y = dy;
+ logicalWidth = img.height;
+ logicalHeight = img.width;
+ break;
+ }
+
+ ctx.clearRect( 0, 0, 180, 180 );
+ ctx.rotate( rotation / 180 * Math.PI );
+ ctx.drawImage( img, x, y, width, height );
+ $spinner.replaceWith( $canvas );
+
+ // Image size
+ info = mw.msg( 'widthheight', logicalWidth, logicalHeight ) +
+ ', ' + prettySize( file.size );
+
+ $( '#mw-upload-thumbnail .fileinfo' ).text( info );
+ };
+ img.onerror = function () {
+ // Can happen for example for invalid SVG files
+ clearPreview();
+ };
+ img.src = dataURL;
+ }, mw.config.get( 'wgFileCanRotate' ) ? function ( data ) {
+ try {
+ meta = mw.libs.jpegmeta( data, file.fileName );
+ // eslint-disable-next-line no-underscore-dangle, camelcase
+ meta._binary_data = null;
+ } catch ( e ) {
+ meta = null;
+ }
+ } : null );
+ }
+
+ /**
+ * Start loading a file into memory; when complete, pass it as a
+ * data URL to the callback function. If the callbackBinary is set it will
+ * first be read as binary and afterwards as data URL. Useful if you want
+ * to do preprocessing on the binary data first.
+ *
+ * @param {File} file
+ * @param {Function} callback
+ * @param {Function} callbackBinary
+ */
+ function fetchPreview( file, callback, callbackBinary ) {
+ var reader = new FileReader();
+ if ( callbackBinary && 'readAsBinaryString' in reader ) {
+ // To fetch JPEG metadata we need a binary string; start there.
+ // TODO
+ reader.onload = function () {
+ callbackBinary( reader.result );
+
+ // Now run back through the regular code path.
+ fetchPreview( file, callback );
+ };
+ reader.readAsBinaryString( file );
+ } else if ( callbackBinary && 'readAsArrayBuffer' in reader ) {
+ // readAsArrayBuffer replaces readAsBinaryString
+ // However, our JPEG metadata library wants a string.
+ // So, this is going to be an ugly conversion.
+ reader.onload = function () {
+ var i,
+ buffer = new Uint8Array( reader.result ),
+ string = '';
+ for ( i = 0; i < buffer.byteLength; i++ ) {
+ string += String.fromCharCode( buffer[ i ] );
+ }
+ callbackBinary( string );
+
+ // Now run back through the regular code path.
+ fetchPreview( file, callback );
+ };
+ reader.readAsArrayBuffer( file );
+ } else if ( 'URL' in window && 'createObjectURL' in window.URL ) {
+ // Supported in Firefox 4.0 and above <https://developer.mozilla.org/en/DOM/window.URL.createObjectURL>
+ // WebKit has it in a namespace for now but that's ok. ;)
+ //
+ // Lifetime of this URL is until document close, which is fine
+ // for Special:Upload -- if this code gets used on longer-running
+ // pages, add a revokeObjectURL() when it's no longer needed.
+ //
+ // Prefer this over readAsDataURL for Firefox 7 due to bug reading
+ // some SVG files from data URIs <https://bugzilla.mozilla.org/show_bug.cgi?id=694165>
+ callback( window.URL.createObjectURL( file ) );
+ } else {
+ // This ends up decoding the file to base-64 and back again, which
+ // feels horribly inefficient.
+ reader.onload = function () {
+ callback( reader.result );
+ };
+ reader.readAsDataURL( file );
+ }
+ }
+
+ /**
+ * Clear the file upload preview area.
+ */
+ function clearPreview() {
+ $( '#mw-upload-thumbnail' ).remove();
+ }
+
+ /**
+ * Check if the file does not exceed the maximum size
+ *
+ * @param {File} file
+ * @return {boolean}
+ */
+ function checkMaxUploadSize( file ) {
+ var maxSize, $error;
+
+ function getMaxUploadSize( type ) {
+ var sizes = mw.config.get( 'wgMaxUploadSize' );
+
+ if ( sizes[ type ] !== undefined ) {
+ return sizes[ type ];
+ }
+ return sizes[ '*' ];
+ }
+
+ $( '.mw-upload-source-error' ).remove();
+
+ maxSize = getMaxUploadSize( 'file' );
+ if ( file.size > maxSize ) {
+ $error = $( '<p class="error mw-upload-source-error" id="wpSourceTypeFile-error">' +
+ mw.message( 'largefileserver', file.size, maxSize ).escaped() + '</p>' );
+
+ $( '#wpUploadFile' ).after( $error );
+
+ return false;
+ }
+
+ return true;
+ }
+
+ /* Initialization */
+ if ( hasFileAPI() ) {
+ // Update thumbnail when the file selection control is updated.
+ $( '#wpUploadFile' ).change( function () {
+ var file;
+ clearPreview();
+ if ( this.files && this.files.length ) {
+ // Note: would need to be updated to handle multiple files.
+ file = this.files[ 0 ];
+
+ if ( !checkMaxUploadSize( file ) ) {
+ return;
+ }
+
+ if ( fileIsPreviewable( file ) ) {
+ showPreview( file );
+ }
+ }
+ } );
+ }
+ } );
+
+ // Disable all upload source fields except the selected one
+ $( function () {
+ var $rows = $( '.mw-htmlform-field-UploadSourceField' );
+
+ $rows.on( 'change', 'input[type="radio"]', function ( e ) {
+ var currentRow = e.delegateTarget;
+
+ if ( !this.checked ) {
+ return;
+ }
+
+ $( '.mw-upload-source-error' ).remove();
+
+ // Enable selected upload method
+ $( currentRow ).find( 'input' ).prop( 'disabled', false );
+
+ // Disable inputs of other upload methods
+ // (except for the radio button to re-enable it)
+ $rows
+ .not( currentRow )
+ .find( 'input[type!="radio"]' )
+ .prop( 'disabled', true );
+ } );
+
+ // Set initial state
+ if ( !$( '#wpSourceTypeurl' ).prop( 'checked' ) ) {
+ $( '#wpUploadFileURL' ).prop( 'disabled', true );
+ }
+ } );
+
+ $( function () {
+ // Prevent losing work
+ var allowCloseWindow,
+ $uploadForm = $( '#mw-upload-form' );
+
+ if ( !mw.user.options.get( 'useeditwarning' ) ) {
+ // If the user doesn't want edit warnings, don't set things up.
+ return;
+ }
+
+ $uploadForm.data( 'origtext', $uploadForm.serialize() );
+
+ allowCloseWindow = mw.confirmCloseWindow( {
+ test: function () {
+ return $( '#wpUploadFile' ).get( 0 ).files.length !== 0 ||
+ $uploadForm.data( 'origtext' ) !== $uploadForm.serialize();
+ },
+
+ message: mw.msg( 'editwarning-warning' ),
+ namespace: 'uploadwarning'
+ } );
+
+ $uploadForm.submit( function () {
+ allowCloseWindow.release();
+ } );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.styles.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.styles.css
new file mode 100644
index 00000000..626a7e8b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.upload.styles.css
@@ -0,0 +1,15 @@
+/*!
+ * Styling for Special:Upload
+ */
+.mw-destfile-warning {
+ border: 1px solid #fde29b;
+ padding: 0.5em 1em;
+ margin-bottom: 1em;
+ color: #705000;
+ background-color: #fdf1d1;
+}
+
+p.mw-upload-editlicenses {
+ font-size: 90%;
+ text-align: right;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.common.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.common.css
new file mode 100644
index 00000000..23662492
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.common.css
@@ -0,0 +1,75 @@
+/* User login and signup forms */
+.mw-ui-vform .mw-form-related-link-container {
+ margin-bottom: 0.5em;
+ text-align: center;
+}
+
+.mw-ui-vform .mw-secure {
+ /* @embed */
+ background: url( images/icon-lock.png ) no-repeat left center;
+ margin: 0 0 0 1px;
+ padding: 0 0 0 11px;
+}
+
+/*
+ * When inside the VForm style, disable the border that Vector and other skins
+ * put on the div surrounding the login/create account form.
+ * Also disable the margin and padding that Vector puts around the form.
+ */
+.mw-ui-container #userloginForm,
+.mw-ui-container #userlogin {
+ border: 0;
+ margin: 0;
+ padding: 0;
+}
+
+/* Reposition and resize language links, which appear on a per-wiki basis */
+.mw-ui-container #languagelinks {
+ margin-bottom: 2em;
+ font-size: 0.8em;
+}
+
+/* Put some space under template's header, which may contain CAPTCHA HTML. */
+section.mw-form-header {
+ margin-bottom: 10px;
+}
+
+/* shuffled CAPTCHA */
+#wpCaptchaWord {
+ margin-top: 6px;
+}
+
+.fancycaptcha-captcha-container {
+ background-color: #f8f9fa;
+ margin-bottom: 15px;
+ border: 1px solid #c8ccd1;
+ border-radius: 2px;
+ padding: 8px;
+ text-align: center;
+}
+
+.mw-createacct-captcha-assisted {
+ display: block;
+ margin-top: 0.5em;
+}
+
+/* Put a border around the fancycaptcha-image-container. */
+.fancycaptcha-captcha-and-reload {
+ border: 1px solid #c8ccd1;
+ border-radius: 2px 2px 0 0;
+ /* Other display formats end up too wide */
+ display: table-cell;
+ width: 270px;
+ background-color: #fff;
+}
+
+.fancycaptcha-captcha-container .mw-ui-input {
+ margin-top: -1px;
+ border-color: #c8ccd1;
+ border-radius: 0 0 2px 2px;
+}
+
+/* Make the fancycaptcha-image-container full-width within its parent. */
+.fancycaptcha-image-container {
+ width: 100%;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.login.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.login.css
new file mode 100644
index 00000000..cf77a969
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.login.css
@@ -0,0 +1,29 @@
+/* The login form invites users to create an account */
+#mw-createaccount-cta {
+ width: 20em;
+ /* @embed */
+ background: url( images/glyph-people-large.png ) no-repeat 50%;
+ margin: 0 auto;
+ padding-top: 7.8em;
+ font-weight: bold;
+}
+
+/* Login Button, following `ButtonWidget (progressive)‎` from OOjs UI */
+#mw-createaccount-join {
+ background-color: #f8f9fa;
+ color: #36c;
+}
+#mw-createaccount-join:hover {
+ background-color: #fff;
+ border-color: #859ecc;
+ box-shadow: none;
+}
+#mw-createaccount-join:active {
+ background-color: #eff3fa;
+ color: #2a4b8d;
+ border-color: #2a4b8d;
+}
+#mw-createaccount-join:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css
new file mode 100644
index 00000000..19aee1e7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.css
@@ -0,0 +1,66 @@
+/* Disable the underline that Vector puts on h2 headings, and bold them. */
+.mw-ui-container h2 {
+ border: 0;
+ font-weight: bold;
+}
+
+/* Benefits column CSS to the right (if it fits) of the form. */
+.mw-ui-container #userloginForm {
+ float: left;
+ /* Override the right margin of the form to give space in case a benefits
+ * column appears to the side. */
+ margin-right: 100px;
+}
+
+div.mw-createacct-benefits-container {
+ /* Keeps this column compact and close to the form, but tends to squish contents. */
+ float: left;
+}
+
+div.mw-createacct-benefits-container h2 {
+ margin-bottom: 30px;
+}
+
+.mw-number-text.icon-edits {
+ /* @embed */
+ background: url( images/icon-edits.png ) no-repeat left center;
+}
+
+.mw-number-text.icon-pages {
+ /* @embed */
+ background: url( images/icon-pages.png ) no-repeat left center;
+}
+
+.mw-number-text.icon-contributors {
+ /* @embed */
+ background: url( images/icon-contributors.png ) no-repeat left center;
+}
+
+/*
+ * Special font for numbers in benefits, same as Vector's @content-heading-font-family.
+ * Needs an ID so that it's more specific than Vector's div#content h3.
+ */
+#bodyContent div.mw-number-text h3 {
+ top: 0;
+ margin: 0;
+ padding: 0;
+ color: #252525;
+ font-family: 'Linux Libertine', 'Georgia', 'Times', serif;
+ font-weight: normal;
+ font-size: 2.2em;
+ line-height: 1.2;
+ text-align: center;
+}
+
+/* Contains a number and explanatory text, with space for an icon */
+div.mw-number-text {
+ display: block;
+ font-size: 1.2em;
+ color: #444;
+ margin-top: 1em;
+ /* 80px wide icon plus "margin" */
+ padding: 0 0 0 95px;
+ /* Matches max icon height, ensures icon emblem is visible */
+ min-height: 75px;
+ text-align: center;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js
new file mode 100644
index 00000000..10e19e72
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userlogin.signup.js
@@ -0,0 +1,122 @@
+/*!
+ * JavaScript for signup form.
+ */
+( function ( mw, $ ) {
+ // When sending password by email, hide the password input fields.
+ $( function () {
+ // Always required if checked, otherwise it depends, so we use the original
+ var $emailLabel = $( 'label[for="wpEmail"]' ),
+ originalText = $emailLabel.text(),
+ requiredText = mw.message( 'createacct-emailrequired' ).text(),
+ $createByMailCheckbox = $( '#wpCreateaccountMail' ),
+ $beforePwds = $( '.mw-row-password:first' ).prev(),
+ $pwds;
+
+ function updateForCheckbox() {
+ var checked = $createByMailCheckbox.prop( 'checked' );
+ if ( checked ) {
+ $pwds = $( '.mw-row-password' ).detach();
+ $emailLabel.text( requiredText );
+ } else {
+ if ( $pwds ) {
+ $beforePwds.after( $pwds );
+ $pwds = null;
+ }
+ $emailLabel.text( originalText );
+ }
+ }
+
+ $createByMailCheckbox.on( 'change', updateForCheckbox );
+ updateForCheckbox();
+ } );
+
+ // Check if the username is invalid or already taken
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ var $usernameInput = $root.find( '#wpName2' ),
+ $passwordInput = $root.find( '#wpPassword2' ),
+ $emailInput = $root.find( '#wpEmail' ),
+ $realNameInput = $root.find( '#wpRealName' ),
+ api = new mw.Api(),
+ usernameChecker, passwordChecker;
+
+ function checkUsername( username ) {
+ // We could just use .then() if we didn't have to pass on .abort()…
+ var d, apiPromise;
+
+ d = $.Deferred();
+ apiPromise = api.get( {
+ action: 'query',
+ list: 'users',
+ ususers: username,
+ usprop: 'cancreate',
+ formatversion: 2,
+ errorformat: 'html',
+ errorsuselocal: true,
+ uselang: mw.config.get( 'wgUserLanguage' )
+ } )
+ .done( function ( resp ) {
+ var userinfo = resp.query.users[ 0 ];
+
+ if ( resp.query.users.length !== 1 || userinfo.invalid ) {
+ d.resolve( { valid: false, messages: [ mw.message( 'noname' ).parseDom() ] } );
+ } else if ( userinfo.userid !== undefined ) {
+ d.resolve( { valid: false, messages: [ mw.message( 'userexists' ).parseDom() ] } );
+ } else if ( !userinfo.cancreate ) {
+ d.resolve( {
+ valid: false,
+ messages: userinfo.cancreateerror ? userinfo.cancreateerror.map( function ( m ) {
+ return m.html;
+ } ) : []
+ } );
+ } else {
+ d.resolve( { valid: true, messages: [] } );
+ }
+ } )
+ .fail( d.reject );
+
+ return d.promise( { abort: apiPromise.abort } );
+ }
+
+ function checkPassword() {
+ // We could just use .then() if we didn't have to pass on .abort()…
+ var apiPromise,
+ d = $.Deferred();
+
+ if ( $.trim( $usernameInput.val() ) === '' ) {
+ d.resolve( { valid: true, messages: [] } );
+ return d.promise();
+ }
+
+ apiPromise = api.post( {
+ action: 'validatepassword',
+ user: $usernameInput.val(),
+ password: $passwordInput.val(),
+ email: $emailInput.val() || '',
+ realname: $realNameInput.val() || '',
+ formatversion: 2,
+ errorformat: 'html',
+ errorsuselocal: true,
+ uselang: mw.config.get( 'wgUserLanguage' )
+ } )
+ .done( function ( resp ) {
+ var pwinfo = resp.validatepassword || {};
+
+ d.resolve( {
+ valid: pwinfo.validity === 'Good',
+ messages: pwinfo.validitymessages ? pwinfo.validitymessages.map( function ( m ) {
+ return m.html;
+ } ) : []
+ } );
+ } )
+ .fail( d.reject );
+
+ return d.promise( { abort: apiPromise.abort } );
+ }
+
+ usernameChecker = new mw.htmlform.Checker( $usernameInput, checkUsername );
+ usernameChecker.attach();
+
+ passwordChecker = new mw.htmlform.Checker( $passwordInput, checkPassword );
+ passwordChecker.attach( $usernameInput.add( $emailInput ).add( $realNameInput ) );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.userrights.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userrights.css
new file mode 100644
index 00000000..a4b4087d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userrights.css
@@ -0,0 +1,12 @@
+/*!
+ * Styling for Special:UserRights
+ */
+.mw-userrights-nested {
+ margin-left: 1.2em;
+}
+
+.mw-userrights-nested span {
+ margin-left: 0.3em;
+ display: inline-block;
+ vertical-align: middle;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.userrights.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userrights.js
new file mode 100644
index 00000000..3f864dd5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.userrights.js
@@ -0,0 +1,18 @@
+/*!
+ * JavaScript for Special:UserRights
+ */
+( function ( $ ) {
+ var convertmessagebox = require( 'mediawiki.notification.convertmessagebox' );
+ // Replace successbox with notifications
+ convertmessagebox();
+
+ // Dynamically show/hide the expiry selection underneath each checkbox
+ $( '#mw-userrights-form2 input[type=checkbox]' ).on( 'change', function ( e ) {
+ $( '#mw-userrights-nested-' + e.target.id ).toggle( e.target.checked );
+ } ).trigger( 'change' );
+
+ // Also dynamically show/hide the "other time" input under each dropdown
+ $( '.mw-userrights-nested select' ).on( 'change', function ( e ) {
+ $( e.target.parentNode ).find( 'input' ).toggle( $( e.target ).val() === 'other' );
+ } ).trigger( 'change' );
+}( jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.version.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.version.css
new file mode 100644
index 00000000..ebb6b486
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.version.css
@@ -0,0 +1,26 @@
+/*!
+ * Styling for Special:Version
+ */
+.mw-version-ext-name,
+.mw-version-library-name {
+ font-weight: bold;
+}
+
+.mw-version-ext-license,
+.mw-version-ext-vcs-timestamp {
+ white-space: nowrap;
+}
+
+th.mw-version-ext-col-label {
+ font-size: 0.9em;
+}
+
+.mw-version-ext-vcs-version {
+ unicode-bidi: embed;
+}
+
+.mw-version-credits {
+ column-width: 18em;
+ -moz-column-width: 18em;
+ -webkit-column-width: 18em;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.watchlist.css b/www/wiki/resources/src/mediawiki.special/mediawiki.special.watchlist.css
new file mode 100644
index 00000000..c9861c25
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.watchlist.css
@@ -0,0 +1,15 @@
+/*!
+ * Styling for elements generated by JavaScript on Special:Watchlist
+ */
+.mw-changelist-line-inner-unwatched {
+ text-decoration: line-through;
+ opacity: 0.5;
+}
+
+span.mw-changeslist-line-prefix {
+ display: inline-block;
+}
+/* This can be either a span or a table cell */
+.mw-changeslist-line-prefix {
+ width: 1.25em;
+}
diff --git a/www/wiki/resources/src/mediawiki.special/mediawiki.special.watchlist.js b/www/wiki/resources/src/mediawiki.special/mediawiki.special.watchlist.js
new file mode 100644
index 00000000..535ca937
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/mediawiki.special.watchlist.js
@@ -0,0 +1,155 @@
+/*!
+ * JavaScript for Special:Watchlist
+ */
+( function ( mw, $, OO ) {
+ $( function () {
+ var api = new mw.Api(), $progressBar, $resetForm = $( '#mw-watchlist-resetbutton' );
+
+ // If the user wants to reset their watchlist, use an API call to do so (no reload required)
+ // Adapted from a user script by User:NQ of English Wikipedia
+ // (User:NQ/WatchlistResetConfirm.js)
+ $resetForm.submit( function ( event ) {
+ var $button = $resetForm.find( 'input[name=mw-watchlist-reset-submit]' );
+
+ event.preventDefault();
+
+ // Disable reset button to prevent multiple concurrent requests
+ $button.prop( 'disabled', true );
+
+ if ( !$progressBar ) {
+ $progressBar = new OO.ui.ProgressBarWidget( { progress: false } ).$element;
+ $progressBar.css( {
+ position: 'absolute', width: '100%'
+ } );
+ }
+ // Show progress bar
+ $resetForm.append( $progressBar );
+
+ // Use action=setnotificationtimestamp to mark all as visited,
+ // then set all watchlist lines accordingly
+ api.postWithToken( 'csrf', {
+ formatversion: 2, action: 'setnotificationtimestamp', entirewatchlist: true
+ } ).done( function () {
+ // Enable button again
+ $button.prop( 'disabled', false );
+ // Hide the button because further clicks can not generate any visual changes
+ $button.css( 'visibility', 'hidden' );
+ $progressBar.detach();
+ $( '.mw-changeslist-line-watched' )
+ .removeClass( 'mw-changeslist-line-watched' )
+ .addClass( 'mw-changeslist-line-not-watched' );
+ } ).fail( function () {
+ // On error, fall back to server-side reset
+ // First remove this submit listener and then re-submit the form
+ $resetForm.off( 'submit' ).submit();
+ } );
+ } );
+
+ // if the user wishes to reload the watchlist whenever a filter changes
+ if ( mw.user.options.get( 'watchlistreloadautomatically' ) ) {
+ // add a listener on all form elements in the header form
+ $( '#mw-watchlist-form input, #mw-watchlist-form select' ).on( 'change', function () {
+ // submit the form when one of the input fields is modified
+ $( '#mw-watchlist-form' ).submit();
+ } );
+ }
+
+ if ( mw.user.options.get( 'watchlistunwatchlinks' ) ) {
+ // Watch/unwatch toggle link:
+ // If a page is on the watchlist, a '×' is shown which, when clicked, removes the page from the watchlist.
+ // After unwatching a page, the '×' becomes a '+', which if clicked re-watches the page.
+ // Unwatched page entries are struck through and have lowered opacity.
+ $( '.mw-unwatch-link, .mw-watch-link' ).click( function ( event ) {
+ var $unwatchLink = $( this ), // EnhancedChangesList uses <table> for each row, while OldChangesList uses <li> for each row
+ $watchlistLine = $unwatchLink.closest( 'li, table' )
+ .find( '[data-target-page]' ),
+ pageTitle = $watchlistLine.data( 'targetPage' ),
+ isTalk = mw.Title.newFromText( pageTitle ).getNamespaceId() % 2 === 1;
+
+ // Utility function for looping through each watchlist line that matches
+ // a certain page or its associated page (e.g. Talk)
+ function forEachMatchingTitle( title, callback ) {
+
+ var titleObj = mw.Title.newFromText( title ),
+ pageNamespaceId = titleObj.getNamespaceId(),
+ isTalk = pageNamespaceId % 2 === 1,
+ associatedTitle = mw.Title.makeTitle( isTalk ? pageNamespaceId - 1 : pageNamespaceId + 1,
+ titleObj.getMainText() ).getPrefixedText();
+ $( '.mw-changeslist-line' ).each( function () {
+ var $this = $( this ), $row, $unwatchLink;
+
+ $this.find( '[data-target-page]' ).each( function () {
+ var $this = $( this ), rowTitle = $this.data( 'targetPage' );
+ if ( rowTitle === title || rowTitle === associatedTitle ) {
+
+ // EnhancedChangesList groups log entries by performer rather than target page. Therefore...
+ // * If using OldChangesList, use the <li>
+ // * If using EnhancedChangesList and $this is part of a grouped log entry, use the <td> sub-entry
+ // * If using EnhancedChangesList and $this is not part of a grouped log entry, use the <table> grouped entry
+ $row =
+ $this.closest(
+ 'li, table.mw-collapsible.mw-changeslist-log td[data-target-page], table' );
+ $unwatchLink = $row.find( '.mw-unwatch-link, .mw-watch-link' );
+
+ callback( rowTitle, $row, $unwatchLink );
+ }
+ } );
+ } );
+ }
+
+ // Depending on whether we are watching or unwatching, for each entry of the page (and its associated page i.e. Talk),
+ // change the text, tooltip, and non-JS href of the (un)watch button, and update the styling of the watchlist entry.
+ if ( $unwatchLink.hasClass( 'mw-unwatch-link' ) ) {
+ api.unwatch( pageTitle )
+ .done( function () {
+ forEachMatchingTitle( pageTitle,
+ function ( rowPageTitle, $row, $rowUnwatchLink ) {
+ $rowUnwatchLink
+ .text( mw.msg( 'watchlist-unwatch-undo' ) )
+ .attr( 'title', mw.msg( 'tooltip-ca-watch' ) )
+ .attr( 'href',
+ mw.util.getUrl( rowPageTitle, { action: 'watch' } ) )
+ .removeClass( 'mw-unwatch-link loading' )
+ .addClass( 'mw-watch-link' );
+ $row.find(
+ '.mw-changeslist-line-inner, .mw-enhanced-rc-nested' )
+ .addBack( '.mw-enhanced-rc-nested' ) // For matching log sub-entry
+ .addClass( 'mw-changelist-line-inner-unwatched' );
+ } );
+
+ mw.notify(
+ mw.message( isTalk ? 'removedwatchtext-talk' : 'removedwatchtext',
+ pageTitle ), { tag: 'watch-self' } );
+ } );
+ } else {
+ api.watch( pageTitle )
+ .then( function () {
+ forEachMatchingTitle( pageTitle,
+ function ( rowPageTitle, $row, $rowUnwatchLink ) {
+ $rowUnwatchLink
+ .text( mw.msg( 'watchlist-unwatch' ) )
+ .attr( 'title', mw.msg( 'tooltip-ca-unwatch' ) )
+ .attr( 'href',
+ mw.util.getUrl( rowPageTitle, { action: 'unwatch' } ) )
+ .removeClass( 'mw-watch-link loading' )
+ .addClass( 'mw-unwatch-link' );
+ $row.find( '.mw-changelist-line-inner-unwatched' )
+ .addBack( '.mw-enhanced-rc-nested' )
+ .removeClass( 'mw-changelist-line-inner-unwatched' );
+ } );
+
+ mw.notify(
+ mw.message( isTalk ? 'addedwatchtext-talk' : 'addedwatchtext',
+ pageTitle ), { tag: 'watch-self' } );
+ } );
+ }
+
+ event.preventDefault();
+ event.stopPropagation();
+ $unwatchLink.blur();
+ } );
+ }
+ } );
+
+}( mediaWiki, jQuery, OO )
+);
diff --git a/www/wiki/resources/src/mediawiki.special/templates/thumbnail.html b/www/wiki/resources/src/mediawiki.special/templates/thumbnail.html
new file mode 100644
index 00000000..bf0e7014
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.special/templates/thumbnail.html
@@ -0,0 +1,8 @@
+<div id="mw-upload-thumbnail" class="thumb tright">
+ <div class="thumbinner">
+ <div class="thumbcaption">
+ <div class="filename"></div>
+ <div class="fileinfo"></div>
+ </div>
+ </div>
+</div>
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_bold.png b/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_bold.png
new file mode 100644
index 00000000..50e2ff03
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_bold.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_headline.png b/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_headline.png
new file mode 100644
index 00000000..2e3e7819
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_headline.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_italic.png b/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_italic.png
new file mode 100644
index 00000000..6b54fb61
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_italic.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_link.png b/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_link.png
new file mode 100644
index 00000000..4434e7f5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_link.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_nowiki.png b/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_nowiki.png
new file mode 100644
index 00000000..c9378de1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/ar/button_nowiki.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_bold.png b/www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_bold.png
new file mode 100644
index 00000000..df6700dd
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_bold.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_italic.png b/www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_italic.png
new file mode 100644
index 00000000..872c00f1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_italic.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_link.png b/www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_link.png
new file mode 100644
index 00000000..d3dd88e6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/be-tarask/button_link.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/de/button_bold.png b/www/wiki/resources/src/mediawiki.toolbar/images/de/button_bold.png
new file mode 100644
index 00000000..8e6b389a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/de/button_bold.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/de/button_italic.png b/www/wiki/resources/src/mediawiki.toolbar/images/de/button_italic.png
new file mode 100644
index 00000000..5e3cd111
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/de/button_italic.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/en/button_bold.png b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_bold.png
new file mode 100644
index 00000000..e582fb1a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_bold.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/en/button_extlink.png b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_extlink.png
new file mode 100644
index 00000000..458943c1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_extlink.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/en/button_headline.png b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_headline.png
new file mode 100644
index 00000000..7d64a164
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_headline.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/en/button_hr.png b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_hr.png
new file mode 100644
index 00000000..47e1ca40
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_hr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/en/button_image.png b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_image.png
new file mode 100644
index 00000000..69192965
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_image.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/en/button_italic.png b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_italic.png
new file mode 100644
index 00000000..820efe26
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_italic.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/en/button_link.png b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_link.png
new file mode 100644
index 00000000..5dd362cf
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_link.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/en/button_media.png b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_media.png
new file mode 100644
index 00000000..80c3156c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_media.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/en/button_nowiki.png b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_nowiki.png
new file mode 100644
index 00000000..05a977af
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_nowiki.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/en/button_sig.png b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_sig.png
new file mode 100644
index 00000000..2cbcc0b3
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/en/button_sig.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_bold.png b/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_bold.png
new file mode 100644
index 00000000..54893430
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_bold.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_headline.png b/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_headline.png
new file mode 100644
index 00000000..4d48a5d1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_headline.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_italic.png b/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_italic.png
new file mode 100644
index 00000000..41098c7d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_italic.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_link.png b/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_link.png
new file mode 100644
index 00000000..8c2d85a7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_link.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_nowiki.png b/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_nowiki.png
new file mode 100644
index 00000000..c9378de1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/fa/button_nowiki.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/ksh/LICENSE b/www/wiki/resources/src/mediawiki.toolbar/images/ksh/LICENSE
new file mode 100644
index 00000000..640bbff8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/ksh/LICENSE
@@ -0,0 +1,7 @@
+
+button_italic.png
+-------------------
+Source : https://commons.wikimedia.org/wiki/Image:Button_S_italic.png
+License: Public domain
+Author : Purodha Blissenbach, https://ksh.wikipedia.org/wiki/User:Purodha
+
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/ksh/button_italic.png b/www/wiki/resources/src/mediawiki.toolbar/images/ksh/button_italic.png
new file mode 100644
index 00000000..34268d9a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/ksh/button_italic.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/ru/LICENSE b/www/wiki/resources/src/mediawiki.toolbar/images/ru/LICENSE
new file mode 100644
index 00000000..bedcec66
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/ru/LICENSE
@@ -0,0 +1,17 @@
+button_bold.png
+---------------
+Source : http://commons.wikimedia.org/wiki/Image:Button_bold_ukr.png
+License: Public domain
+Author : Alexey Belomoev
+
+button_italic.png
+------------------------
+Source : http://commons.wikimedia.org/wiki/Image:Button_italic_ukr.png
+License: Public domain
+Author : Alexey Belomoev
+
+button_link.png
+-----------------
+Source : http://commons.wikimedia.org/wiki/Image:Button_internal_link_ukr.png
+License: GPL
+Author : Saproj, Erik Möller
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/ru/button_bold.png b/www/wiki/resources/src/mediawiki.toolbar/images/ru/button_bold.png
new file mode 100644
index 00000000..a7dceb16
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/ru/button_bold.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/ru/button_italic.png b/www/wiki/resources/src/mediawiki.toolbar/images/ru/button_italic.png
new file mode 100644
index 00000000..44a0a741
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/ru/button_italic.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/images/ru/button_link.png b/www/wiki/resources/src/mediawiki.toolbar/images/ru/button_link.png
new file mode 100644
index 00000000..36b90596
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/images/ru/button_link.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.toolbar/toolbar.js b/www/wiki/resources/src/mediawiki.toolbar/toolbar.js
new file mode 100644
index 00000000..d55ed80c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/toolbar.js
@@ -0,0 +1,208 @@
+/**
+ * Interface for the classic edit toolbar.
+ *
+ * @class mw.toolbar
+ * @singleton
+ */
+( function ( mw, $ ) {
+ var toolbar, isReady, $toolbar, queue, slice, $currentFocused;
+
+ /**
+ * Internal helper that does the actual insertion of the button into the toolbar.
+ *
+ * For backwards-compatibility, passing `imageFile`, `speedTip`, `tagOpen`, `tagClose`,
+ * `sampleText` and `imageId` as separate arguments (in this order) is also supported.
+ *
+ * @private
+ *
+ * @param {Object} button Object with the following properties.
+ * You are required to provide *either* the `onClick` parameter, or the three parameters
+ * `tagOpen`, `tagClose` and `sampleText`, but not both (they're mutually exclusive).
+ * @param {string} [button.imageFile] Image to use for the button.
+ * @param {string} button.speedTip Tooltip displayed when user mouses over the button.
+ * @param {Function} [button.onClick] Function to be executed when the button is clicked.
+ * @param {string} [button.tagOpen]
+ * @param {string} [button.tagClose]
+ * @param {string} [button.sampleText] Alternative to `onClick`. `tagOpen`, `tagClose` and
+ * `sampleText` together provide the markup that should be inserted into page text at
+ * current cursor position.
+ * @param {string} [button.imageId] `id` attribute of the button HTML element. Can be
+ * used to define the image with CSS if it's not provided as `imageFile`.
+ * @param {string} [speedTip]
+ * @param {string} [tagOpen]
+ * @param {string} [tagClose]
+ * @param {string} [sampleText]
+ * @param {string} [imageId]
+ */
+ function insertButton( button, speedTip, tagOpen, tagClose, sampleText, imageId ) {
+ var $button;
+
+ // Backwards compatibility
+ if ( typeof button !== 'object' ) {
+ button = {
+ imageFile: button,
+ speedTip: speedTip,
+ tagOpen: tagOpen,
+ tagClose: tagClose,
+ sampleText: sampleText,
+ imageId: imageId
+ };
+ }
+
+ if ( button.imageFile ) {
+ $button = $( '<img>' ).attr( {
+ src: button.imageFile,
+ alt: button.speedTip,
+ title: button.speedTip,
+ id: button.imageId || undefined,
+ 'class': 'mw-toolbar-editbutton'
+ } );
+ } else {
+ $button = $( '<div>' ).attr( {
+ title: button.speedTip,
+ id: button.imageId || undefined,
+ 'class': 'mw-toolbar-editbutton'
+ } );
+ }
+
+ $button.click( function ( e ) {
+ if ( button.onClick !== undefined ) {
+ button.onClick( e );
+ } else {
+ toolbar.insertTags( button.tagOpen, button.tagClose, button.sampleText );
+ }
+
+ return false;
+ } );
+
+ $toolbar.append( $button );
+ }
+
+ isReady = false;
+ $toolbar = false;
+
+ /**
+ * @private
+ * @property {Array}
+ * Contains button objects (and for backwards compatibilty, it can
+ * also contains an arguments array for insertButton).
+ */
+ queue = [];
+ slice = queue.slice;
+
+ toolbar = {
+
+ /**
+ * Add buttons to the toolbar.
+ *
+ * Takes care of race conditions and time-based dependencies by placing buttons in a queue if
+ * this method is called before the toolbar is created.
+ *
+ * For backwards-compatibility, passing `imageFile`, `speedTip`, `tagOpen`, `tagClose`,
+ * `sampleText` and `imageId` as separate arguments (in this order) is also supported.
+ *
+ * @inheritdoc #insertButton
+ */
+ addButton: function () {
+ if ( isReady ) {
+ insertButton.apply( toolbar, arguments );
+ } else {
+ // Convert arguments list to array
+ queue.push( slice.call( arguments ) );
+ }
+ },
+
+ /**
+ * Add multiple buttons to the toolbar (see also #addButton).
+ *
+ * Example usage:
+ *
+ * addButtons( [ { .. }, { .. }, { .. } ] );
+ * addButtons( { .. }, { .. } );
+ *
+ * @param {...Object|Array} [buttons] An array of button objects or the first
+ * button object in a list of variadic arguments.
+ */
+ addButtons: function ( buttons ) {
+ if ( !Array.isArray( buttons ) ) {
+ buttons = slice.call( arguments );
+ }
+ if ( isReady ) {
+ $.each( buttons, function () {
+ insertButton( this );
+ } );
+ } else {
+ // Push each button into the queue
+ queue.push.apply( queue, buttons );
+ }
+ },
+
+ /**
+ * Apply tagOpen/tagClose to selection in currently focused textarea.
+ *
+ * Uses `sampleText` if selection is empty.
+ *
+ * @param {string} tagOpen
+ * @param {string} tagClose
+ * @param {string} sampleText
+ */
+ insertTags: function ( tagOpen, tagClose, sampleText ) {
+ if ( $currentFocused && $currentFocused.length ) {
+ $currentFocused.textSelection(
+ 'encapsulateSelection', {
+ pre: tagOpen,
+ peri: sampleText,
+ post: tagClose
+ }
+ );
+ }
+ }
+ };
+
+ // Legacy (for compatibility with the code previously in skins/common.edit.js)
+ mw.log.deprecate( window, 'addButton', toolbar.addButton, 'Use mw.toolbar.addButton instead.' );
+ mw.log.deprecate( window, 'insertTags', toolbar.insertTags, 'Use mw.toolbar.insertTags instead.' );
+
+ // For backwards compatibility. Used to be called from EditPage.php, maybe other places as well.
+ toolbar.init = $.noop;
+
+ // Expose API publicly
+ // @deprecated since MW 1.29
+ mw.log.deprecate( mw, 'toolbar', toolbar, null, 'mw.toolbar' );
+
+ $( function () {
+ var i, button;
+
+ // Used to determine where to insert tags
+ $currentFocused = $( '#wpTextbox1' );
+
+ // Populate the selector cache for $toolbar
+ $toolbar = $( '#toolbar' );
+
+ for ( i = 0; i < queue.length; i++ ) {
+ button = queue[ i ];
+ if ( Array.isArray( button ) ) {
+ // Forwarded arguments array from mw.toolbar.addButton
+ insertButton.apply( toolbar, button );
+ } else {
+ // Raw object from mw.toolbar.addButtons
+ insertButton( button );
+ }
+ }
+
+ // Clear queue
+ queue.length = 0;
+
+ // This causes further calls to addButton to go to insertion directly
+ // instead of to the queue.
+ // It is important that this is after the one and only loop through
+ // the queue
+ isReady = true;
+
+ // Apply to dynamically created textboxes as well as normal ones
+ $( document ).on( 'focus', 'textarea, input:text', function () {
+ $currentFocused = $( this );
+ } );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki.toolbar/toolbar.less b/www/wiki/resources/src/mediawiki.toolbar/toolbar.less
new file mode 100644
index 00000000..93ea294b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.toolbar/toolbar.less
@@ -0,0 +1,42 @@
+@import 'mediawiki.mixins';
+
+#mw-editbutton-bold {
+ .background-image('images/@{button-bold}');
+}
+
+#mw-editbutton-italic {
+ .background-image('images/@{button-italic}');
+}
+
+#mw-editbutton-link {
+ .background-image('images/@{button-link}');
+}
+
+#mw-editbutton-extlink {
+ .background-image('images/@{button-extlink}');
+}
+
+#mw-editbutton-headline {
+ .background-image('images/@{button-headline}');
+}
+
+#mw-editbutton-image {
+ .background-image('images/@{button-image}');
+}
+
+#mw-editbutton-media {
+ .background-image('images/@{button-media}');
+}
+
+#mw-editbutton-nowiki {
+ .background-image('images/@{button-nowiki}');
+}
+
+// Who decided to make only this single one different than the name of the data item?
+#mw-editbutton-signature {
+ .background-image('images/@{button-sig}');
+}
+
+#mw-editbutton-hr {
+ .background-image('images/@{button-hr}');
+}
diff --git a/www/wiki/resources/src/mediawiki.ui/components/anchors.less b/www/wiki/resources/src/mediawiki.ui/components/anchors.less
new file mode 100644
index 00000000..8e97c3ed
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/anchors.less
@@ -0,0 +1,75 @@
+@import 'mediawiki.mixins';
+@import 'mediawiki.ui/variables';
+@import 'mediawiki.ui/mixins';
+
+// Helpers
+.mixin-mw-ui-anchor-styles( @mainColor ) {
+ color: @mainColor;
+
+ &:hover {
+ color: lighten( @mainColor, @colorLightenPercentage );
+ }
+
+ &:focus,
+ &:active {
+ color: darken( @mainColor, @colorDarkenPercentage );
+ outline: 0;
+ }
+
+ // Quiet mode is gray at first
+ &.mw-ui-quiet {
+ .mixin-mw-ui-anchor-styles-quiet( @mainColor );
+ }
+}
+
+/*
+Anchors
+
+The anchor base type can be applied to `a` elements when a basic context styling needs to be given to a link, without
+having to assign it as a button type. `.mw-ui-anchor` only changes the text color, and should not be used in combination
+with other base classes, such as `.mw-ui-button`.
+
+Markup:
+<a href="#" class="mw-ui-anchor mw-ui-progressive">Progressive</a>
+<a href="#" class="mw-ui-anchor mw-ui-destructive">Destructive</a>
+
+.mw-ui-quiet - Quiet until interaction.
+
+Styleguide 6.2.
+*/
+
+// Setup compound anchor selectors (such as .mw-ui-anchor.mw-ui-progressive)
+.mw-ui-anchor {
+ &.mw-ui-progressive {
+ .mixin-mw-ui-anchor-styles( @colorProgressive );
+ }
+
+ &.mw-ui-destructive {
+ .mixin-mw-ui-anchor-styles( @colorDestructive );
+ }
+}
+
+/*
+Quiet anchors
+
+Use quiet anchors when they are less important and alongside other progressive/destructive
+anchors. Use of quiet anchors is not recommended on mobile/tablet due to lack of hover state.
+
+Markup:
+<a href="#" class="mw-ui-anchor mw-ui-progressive mw-ui-quiet">Progressive</a>
+<a href="#" class="mw-ui-anchor mw-ui-destructive mw-ui-quiet">Destructive</a>
+
+Styleguide 6.2.1.
+*/
+.mixin-mw-ui-anchor-styles-quiet( @mainColor ) {
+ color: @colorTextLight;
+ text-decoration: none;
+
+ &:hover {
+ color: @mainColor;
+ }
+ &:focus,
+ &:active {
+ color: darken( @mainColor, @colorDarkenPercentage );
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.ui/components/buttons.less b/www/wiki/resources/src/mediawiki.ui/components/buttons.less
new file mode 100644
index 00000000..d94a9835
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/buttons.less
@@ -0,0 +1,269 @@
+@import 'mediawiki.mixins';
+@import 'mediawiki.ui/variables';
+@import 'mediawiki.ui/mixins';
+
+// Buttons
+//
+// All buttons start with mw-ui-button class, modified by other classes.
+// It can be any element. Due to a lack of a CSS reset, the exact styling of
+// the button depends on what type of element is used.
+// There are two kinds of buttons, the default is a "Call to Action" with an obvious border
+// and there is a quiet kind without a border.
+//
+// Styleguide 2.
+
+// Neutral button styling
+//
+// These are the main actions on the page/workflow. The page should have only one of progressive and destructive buttons, the rest being quiet.
+//
+// Markup:
+// <div>
+// <button class="mw-ui-button">.mw-ui-button</button>
+// </div>
+// <div>
+// <button class="mw-ui-button" disabled>.mw-ui-button</button>
+// </div>
+//
+// Styleguide 2.1.
+.mw-ui-button {
+ // Inherit the font rather than apply user agent stylesheet (T72072)
+ font-family: inherit;
+ font-size: 1em;
+ // Container layout
+ display: inline-block;
+ min-width: 4em;
+ max-width: 28.75em; // equivalent to 460px, @see T95367
+ padding: 0.546875em 1em;
+ line-height: 1.286;
+ margin: 0;
+ border-radius: @borderRadius;
+ .box-sizing( border-box );
+
+ // Disable weird iOS styling
+ -webkit-appearance: none;
+
+ // IE 6 & 7 hack
+ // https://stackoverflow.com/a/5838575/365238
+ *display: inline; /* stylelint-disable-line declaration-block-no-duplicate-properties */
+ zoom: 1;
+
+ // Ensure that buttons and inputs are nicely aligned when they have differing heights
+ vertical-align: middle;
+
+ // Content styling
+ .button-colors( @colorGray15, #fff, #d9d9d9 );
+ text-align: center;
+ font-weight: bold;
+
+ // Interaction styling
+ cursor: pointer;
+
+ &:focus {
+ outline-width: 0;
+
+ // Remove the inner border and padding in Firefox.
+ &::-moz-focus-inner {
+ border-color: transparent;
+ padding: 0;
+ }
+ }
+
+ // `:not()` is used exclusively for `transition`s as both are not supported by IE < 9
+ &:not( :disabled ) {
+ .transition( ~'background-color 100ms, color 100ms, border-color 100ms, box-shadow 100ms' );
+ }
+
+ &:disabled {
+ text-shadow: none;
+ cursor: default;
+ }
+
+ // Styling for specific button types
+ // -----------------------------------------
+
+ // Big buttons
+ //
+ // Not all buttons are equal. You can emphasise certain actions over others
+ // using the mw-ui-big class.
+ //
+ // Markup:
+ // <div>
+ // <button class="mw-ui-button mw-ui-big">.mw-ui-button</button>
+ // </div>
+ // <div>
+ // <button class="mw-ui-button mw-ui-progressive mw-ui-big">.mw-ui-progressive</button>
+ // </div>
+ // <div>
+ // <button class="mw-ui-button mw-ui-destructive mw-ui-big">.mw-ui-destructive</button>
+ // </div>
+ //
+ // Styleguide 2.1.6.
+ &.mw-ui-big {
+ font-size: 1.3em;
+ }
+
+ // Block buttons
+ //
+ // Some buttons might need to be stacked.
+ //
+ // Markup:
+ // <div>
+ // <button class="mw-ui-button mw-ui-block">.mw-ui-button</button>
+ // </div>
+ // <div>
+ // <button class="mw-ui-button mw-ui-progressive mw-ui-block">.mw-ui-progressive</button>
+ // </div>
+ // <div>
+ // <button class="mw-ui-button mw-ui-destructive mw-ui-block">.mw-ui-destructive</button>
+ // </div>
+ //
+ // Styleguide 2.1.5.
+ &.mw-ui-block {
+ display: block;
+ width: 100%;
+ margin-left: auto;
+ margin-right: auto;
+ }
+
+ // Progressive buttons
+ //
+ // Use progressive buttons for actions which lead to a next step in the process.
+ //
+ // Markup:
+ // <div>
+ // <button class="mw-ui-button mw-ui-progressive">.mw-ui-progressive</button>
+ // </div>
+ // <div>
+ // <button class="mw-ui-button mw-ui-progressive" disabled>.mw-ui-progressive</button>
+ // </div>
+ //
+ // Styleguide 2.1.1.
+ &.mw-ui-progressive {
+ .button-colors-primary( @colorProgressive, @colorProgressiveHighlight, @colorProgressiveActive );
+
+ &.mw-ui-quiet {
+ .button-colors-quiet( @colorProgressive, @colorProgressiveHighlight, @colorProgressiveActive );
+ }
+ }
+
+ // Destructive buttons
+ //
+ // Use destructive buttons for actions that remove or limit, such as deleting a page or blocking a user.
+ // This should not be used for cancel buttons.
+ //
+ // Markup:
+ // <div>
+ // <button class="mw-ui-button mw-ui-destructive">.mw-ui-destructive</button>
+ // </div>
+ // <div>
+ // <button class="mw-ui-button mw-ui-destructive" disabled>.mw-ui-destructive</button>
+ // </div>
+ //
+ // Styleguide 2.1.2.
+ &.mw-ui-destructive {
+ .button-colors-primary( @colorDestructive, @colorDestructiveHighlight, @colorDestructiveActive );
+
+ &.mw-ui-quiet {
+ .button-colors-quiet( @colorDestructive, @colorDestructiveHighlight, @colorDestructiveActive );
+ }
+ }
+
+ // Quiet buttons
+ //
+ // Use quiet buttons when they are less important and alongside other progressive or destructive buttons. It should be used for an action that exits the user from the current view/workflow.
+ // Its use is not recommended on mobile/tablet due to lack of hover state.
+ //
+ // Markup:
+ // <div>
+ // <button class="mw-ui-button mw-ui-quiet">.mw-ui-button</button>
+ // </div>
+ // <div>
+ // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet">.mw-ui-destructive</button>
+ // </div>
+ // <div>
+ // <button class="mw-ui-button mw-ui-destructive mw-ui-quiet" disabled>.mw-ui-destructive</button>
+ // </div>
+ // <div>
+ // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet">.mw-ui-progressive</button>
+ // </div>
+ // <div>
+ // <button class="mw-ui-button mw-ui-progressive mw-ui-quiet" disabled>.mw-ui-progressive</button>
+ // </div>
+ //
+ // Styleguide 2.1.3.
+ &.mw-ui-quiet {
+ background: transparent;
+ border: 0;
+ text-shadow: none;
+ .button-colors-quiet( @colorButtonText, @colorButtonTextHighlight, @colorButtonTextActive );
+
+ &:hover,
+ &:focus {
+ box-shadow: none;
+ }
+
+ &:active,
+ &:disabled {
+ background: transparent;
+ }
+ }
+}
+
+input.mw-ui-button,
+button.mw-ui-button {
+ // Buttons in Firefox have extra height
+ &::-moz-focus-inner {
+ margin-top: -1px;
+ margin-bottom: -1px;
+ }
+}
+
+a.mw-ui-button {
+ text-decoration: none;
+
+ // This overrides an underline declaration on a:hover and a:focus in
+ // commonElements.css, which the class alone isn't specific enough to do.
+ &:hover,
+ &:focus {
+ text-decoration: none;
+ }
+}
+
+// Button groups
+//
+// Group of buttons. Make sure you clear the floating after using a mw-ui-button-group.
+//
+// Markup:
+// <div class="mw-ui-button-group">
+// <div class="mw-ui-button is-on">A</div>
+// <div class="mw-ui-button">B</div>
+// <div class="mw-ui-button">C</div>
+// <div class="mw-ui-button">D</div>
+// </div><div style="clear:both"></div>
+//
+// Styleguide 2.2.
+.mw-ui-button-group {
+ & > * {
+ min-width: 48px;
+ border-radius: 0;
+ float: left;
+
+ &:first-child {
+ border-top-left-radius: @borderRadius;
+ border-bottom-left-radius: @borderRadius;
+ }
+
+ &:not( :first-child ) {
+ border-left: 0;
+ }
+
+ &:last-child {
+ border-top-right-radius: @borderRadius;
+ border-bottom-right-radius: @borderRadius;
+ }
+ }
+
+ & .is-on .button {
+ cursor: default;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.ui/components/checkbox.less b/www/wiki/resources/src/mediawiki.ui/components/checkbox.less
new file mode 100644
index 00000000..c1626db6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/checkbox.less
@@ -0,0 +1,156 @@
+@import 'mediawiki.mixins';
+@import 'mediawiki.ui/variables';
+
+// Checkbox
+//
+// Styling checkboxes in a way that works cross browser is a tricky problem to solve.
+// In MediaWiki UI put a checkbox and label inside a mw-ui-checkbox div.
+// This renders in all browsers except IE 6-8 which do not support the `:checked` selector;
+// these are kept backwards-compatible using the `:not( #noop )` selector.
+// You should give the checkbox and label matching `id` and `for` attributes, respectively.
+//
+// Markup:
+// <div class="mw-ui-checkbox">
+// <input type="checkbox" id="kss-example-3">
+// <label for="kss-example-3">Standard checkbox</label>
+// </div>
+// <div class="mw-ui-checkbox">
+// <input type="checkbox" id="kss-example-3-checked" checked>
+// <label for="kss-example-3-checked">Standard checked checkbox</label>
+// </div>
+// <div class="mw-ui-checkbox">
+// <input type="checkbox" id="kss-example-3-disabled" disabled>
+// <label for="kss-example-3-disabled">Disabled checkbox</label>
+// </div>
+// <div class="mw-ui-checkbox">
+// <input type="checkbox" id="kss-example-3-disabled-checked" disabled checked>
+// <label for="kss-example-3-disabled-checked">Disabled checked checkbox</label>
+// </div>
+//
+// Styleguide 3.
+.mw-ui-checkbox {
+ display: inline-block;
+ line-height: @sizeInputBinary;
+ vertical-align: middle;
+}
+
+// We use the `:not` selector to cancel out styling on IE 8 and below
+// We also disable this styling on JavaScript disabled devices. This fixes the issue with
+// Opera Mini where checking/unchecking doesn't apply styling but potentially leaves other
+// more capable browsers with unstyled checkboxes.
+.client-js .mw-ui-checkbox:not( #noop ) {
+ display: table;
+ // Position relatively so we can make use of absolute pseudo elements
+ position: relative;
+
+ * {
+ // Reset font sizes, see T74727
+ font: inherit;
+ vertical-align: middle;
+ }
+
+ [type='checkbox'] {
+ display: table-cell;
+ position: relative;
+ // Ensure the invisible input takes up the required `width` & `height`
+ width: @sizeInputBinary;
+ height: @sizeInputBinary;
+ // Support: Firefox mobile to override user-agent stylesheet, see T73750
+ max-width: none;
+ margin: 0;
+ // Hide `input[type=checkbox]` and instead style the label that follows
+ // Support: VoiceOver. Use `opacity` so that VoiceOver can still identify the checkbox
+ opacity: 0;
+ // Render *on top of* the label, so that it's still clickable, see T98905
+ z-index: 1;
+
+ & + label {
+ display: table-cell;
+ padding-left: 0.4em;
+ }
+
+ // Pseudo `:before` element of the label after the checkbox now looks like a checkbox
+ & + label:before {
+ content: '';
+ background-color: #fff;
+ background-origin: border-box;
+ background-position: center center;
+ background-repeat: no-repeat;
+ .background-size( 0, 0 );
+ .box-sizing( border-box );
+ position: absolute;
+ // Ensure alignment of checkbox to middle of the text in long labels, see T85241
+ top: 50%;
+ left: 0;
+ width: @sizeInputBinary;
+ height: @sizeInputBinary;
+ margin-top: -( @sizeInputBinary / 2 );
+ border: 1px solid @colorGray7;
+ border-radius: @borderRadius;
+ }
+
+ // Apply a checkmark on the pseudo `:before` element when the input is checked
+ &:checked + label:before {
+ .background-image-svg( 'images/checkbox-checked.svg', 'images/checkbox-checked.png' );
+ .background-size( 90%, 90% );
+ }
+
+ &:enabled {
+ cursor: pointer;
+
+ & + label {
+ cursor: pointer;
+ }
+
+ & + label:before {
+ cursor: pointer;
+ .transition( ~'background-color 100ms, color 100ms, border-color 100ms, box-shadow 100ms' );
+ }
+
+ // `:focus` has to come first, otherwise a specificity race with `:hover:focus` etc is necessary
+ &:focus + label:before {
+ border-color: @colorProgressive;
+ box-shadow: @boxShadowWidgetFocus;
+ }
+
+ &:hover + label:before {
+ border-color: @colorProgressive;
+ }
+
+ &:active + label:before {
+ background-color: @colorProgressiveActive;
+ border-color: @borderColorInputBinaryActive;
+ box-shadow: @boxShadowInputBinaryActive;
+ }
+
+ &:checked {
+ & + label:before {
+ background-color: @backgroundColorInputBinaryChecked;
+ border-color: @borderColorInputBinaryChecked;
+ }
+
+ &:focus + label:before {
+ background-color: @backgroundColorInputBinaryChecked;
+ border-color: @borderColorInputBinaryChecked;
+ box-shadow: @boxShadowProgressiveFocus;
+ }
+
+ &:hover + label:before {
+ background-color: @colorProgressiveHighlight;
+ border-color: @colorProgressiveHighlight;
+ }
+
+ &:active + label:before {
+ background-color: @backgroundColorInputBinaryActive;
+ border-color: @borderColorInputBinaryActive;
+ }
+ }
+ }
+
+ // disabled checkboxes have a gray background
+ &:disabled + label:before {
+ background-color: @colorGray12;
+ border-color: @colorGray12;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.ui/components/forms.less b/www/wiki/resources/src/mediawiki.ui/components/forms.less
new file mode 100644
index 00000000..d3c76d09
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/forms.less
@@ -0,0 +1,173 @@
+// Form elements and layouts
+
+@import 'mediawiki.mixins';
+@import 'mediawiki.ui/variables';
+@import 'mediawiki.ui/mixins';
+
+// --------------------------------------------------------------------------
+// Layouts
+// --------------------------------------------------------------------------
+
+// The FancyCaptcha image CAPTCHA used on WMF wikis drives the width of the
+// 'VForm' design, the form can't be narrower than this.
+@captchaContainerWidth: 290px;
+@defaultFormWidth: @captchaContainerWidth;
+
+// Forms
+//
+// Styleguide 5.
+
+// VForm
+//
+// Style a compact vertical stacked form ("VForm") and the elements in divs
+// within it. See button and inputs section on guidance of how and when to use them.
+//
+// Markup:
+// <form class="mw-ui-vform">
+// <div class="mw-ui-vform-field">This is a form example.</div>
+// <div class="mw-ui-vform-field">
+// <label>Username </label>
+// <input class="mw-ui-input" value="input">
+// </div>
+// <div class="mw-ui-vform-field">
+// <button class="mw-ui-button mw-ui-progressive">Button in vform</button>
+// </div>
+// </form>
+//
+// Styleguide 5.1.
+.mw-ui-vform {
+ .box-sizing( border-box );
+
+ width: @defaultFormWidth;
+
+ // MW currently doesn't use the type attribute everywhere on inputs.
+ select,
+ .mw-ui-button {
+ display: block;
+ .box-sizing( border-box );
+ margin: 0;
+ width: 100%;
+ }
+
+ // Give dropdown lists the same spacing as input fields for consistency.
+ // Values taken from .agora-field-styling() in mixins/form.less
+ select {
+ padding: 0.35em 0.5em;
+ vertical-align: middle;
+ }
+
+ > label {
+ display: block;
+ .box-sizing( border-box );
+ .agora-label-styling();
+ width: auto;
+ margin: 0 0 0.2em;
+ padding: 0;
+ }
+
+ // Override input styling just for checkboxes and radio inputs.
+ input[type='radio'] {
+ display: inline;
+ .box-sizing( content-box );
+ width: auto;
+ }
+
+ // Styles for information boxes
+ //
+ // Regular HTMLForm uses .error class, some special pages like
+ // SpecialUserlogin (login and create account) use .errorbox.
+ //
+ // Markup:
+ // <form class="mw-ui-vform">
+ // <div class="errorbox">An error occurred</div>
+ // <div class="warningbox">A warning to be noted</div>
+ // <div class="successbox">Action successful!</div>
+ // <div class="error">A different kind of error</div>
+ // <div class="error">
+ // <ul><li>There are problems with some of your input.</li></ul>
+ // </div>
+ // <div class="mw-ui-vform-field">
+ // <input type="text" value="input" class="mw-ui-input">
+ // </div>
+ // <div class="mw-ui-vform-field">
+ // <select>
+ // <option value="1">Option 1</option>
+ // <option value="2">Option 2</option>
+ // </select>
+ // <span class="error">The value you specified is not a valid option.</span>
+ // </div>
+ // <div class="mw-ui-vform-field">
+ // <button class="mw-ui-button">Button in vform</button>
+ // </div>
+ // </form>
+ //
+ // Styleguide 5.2.
+ .error,
+ .warning,
+ .errorbox,
+ .warningbox,
+ .successbox {
+ .box-sizing( border-box );
+ font-size: 0.9em;
+ margin: 0 0 1em 0;
+ padding: 0.5em;
+ word-wrap: break-word;
+ }
+
+ // Colours taken from those for .errorbox in shared.css
+ .error {
+ color: @colorErrorText;
+ border: 1px solid #fac5c5;
+ background-color: #fae3e3;
+ }
+
+ // Colours taken from those for .warningbox in shared.css
+ .warning {
+ color: @colorWarningText;
+ border: 1px solid #fde29b;
+ background-color: #fdf1d1;
+ }
+
+ // This specifies styling for individual field validation error messages.
+ // Show them below the fields to prevent line break glitches, and leave
+ // some space between the field and the error message box.
+ .mw-ui-vform-field .error {
+ display: block;
+ margin-top: 5px;
+ }
+
+}
+
+// --------------------------------------------------------------------------
+// Elements
+// --------------------------------------------------------------------------
+
+// A wrapper for a single form field: the <input> / <select> / <button> element,
+// help text, labels, associated error/warning/success messages, and so on.
+// Elements with this class are generated by HTMLFormField in core MediaWiki.
+//
+// (We use a broad definition of 'field' here: a purely textual information
+// block is also a "field".)
+.mw-ui-vform-field {
+ display: block;
+ margin: 0 0 15px;
+ padding: 0;
+ width: 100%;
+}
+
+// Apply mw-ui-label to individual elements to style them.
+// You generally don't need to use this class if <label> is within an Agora
+// form container such as mw-ui-vform
+.mw-ui-label {
+ .agora-label-styling();
+}
+
+// Nesting an input inside a label with this class
+// improves alignment, e.g.
+//
+// <label class="mw-ui-radio-label">
+// <input type="radio">The label text
+// </label>
+.mw-ui-radio-label {
+ .agora-inline-label-styling();
+}
diff --git a/www/wiki/resources/src/mediawiki.ui/components/icons.less b/www/wiki/resources/src/mediawiki.ui/components/icons.less
new file mode 100644
index 00000000..a7ce2e76
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/icons.less
@@ -0,0 +1,107 @@
+@import 'mediawiki.mixins';
+@import 'mediawiki.ui/variables';
+
+// Mixins
+.mixin-mw-ui-icon-bgimage( @iconSvg, @iconPng ) {
+ &.mw-ui-icon {
+ &:before {
+ .background-image-svg( @iconSvg, @iconPng );
+ }
+ }
+}
+
+// Icons
+//
+// To use icons you must be using a browser that supports pseudo elements.
+// This includes support for IE 8.
+// http://caniuse.com/#feat=css-gencontent
+//
+// For elements that are intended to have both an icon and text, browsers that
+// do not support pseudo-selectors will degrade to text-only.
+//
+// However, icon-only elements do not yet degrade to text-only elements in these
+// browsers.
+//
+// Styleguide 6.
+
+.mw-ui-icon {
+ position: relative;
+ line-height: @iconSize;
+ min-height: @iconSize;
+ min-width: @iconSize;
+
+ // Standalone icons
+ //
+ // Markup:
+ // <div class="mw-ui-icon mw-ui-icon-element mw-ui-icon-ok">OK</div><br>
+ // <div class="mw-ui-icon mw-ui-icon-element mw-ui-icon-ok mw-ui-button mw-ui-progressive">OK</div><br>
+ // <button class="mw-ui-icon mw-ui-icon-ok mw-ui-icon-element mw-ui-button mw-ui-quiet" title="">Close</button>
+ //
+ // Styleguide 6.1.1.
+ &.mw-ui-icon-element {
+ @marginIcon: 2 * @iconGutterWidth;
+ @width: @iconSize + @marginIcon;
+ @sizeIconLarge: ( @iconSize * 1.75) + @marginIcon;
+
+ text-indent: -999px;
+ overflow: hidden;
+ width: @width;
+ min-width: @width;
+ max-width: @width;
+
+ &:before {
+ left: 0;
+ right: 0;
+ position: absolute;
+ margin: 0 @iconGutterWidth;
+ }
+
+ &.mw-ui-icon-large {
+ width: @sizeIconLarge;
+ min-width: @sizeIconLarge;
+ max-width: @sizeIconLarge;
+ line-height: @sizeIconLarge;
+ min-height: @sizeIconLarge;
+
+ &:before {
+ min-height: @sizeIconLarge;
+ }
+ }
+ }
+
+ &.mw-ui-icon-before:before,
+ &.mw-ui-icon-element:before {
+ background-position: 50% 50%;
+ background-repeat: no-repeat;
+ background-size: 100% auto;
+ float: left;
+ display: block;
+ min-height: @iconSize;
+ content: '';
+ }
+
+ // Icons with text
+ //
+ // Markup:
+ // <div class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ok">OK</div>
+ // <div class="mw-ui-icon mw-ui-icon-before mw-ui-icon-ok mw-ui-progressive mw-ui-button">OK</div>
+ //
+ // Styleguide 6.1.2
+ &.mw-ui-icon-before {
+ &:before {
+ position: relative;
+ width: @iconSize;
+ margin-right: @iconGutterWidth;
+ }
+ }
+
+ // Icons small for elements like indicators
+ //
+ // Markup:
+ // <div class="mw-ui-icon mw-ui-icon-small mw-ui-icon-help"></div>
+ //
+ // Styleguide 6.1.3
+ &.mw-ui-icon-small:before {
+ background-size: 66.67% auto; // 66.67% of 24px equals 16px
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.ui/components/images/checkbox-checked.png b/www/wiki/resources/src/mediawiki.ui/components/images/checkbox-checked.png
new file mode 100644
index 00000000..708bb396
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/images/checkbox-checked.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.ui/components/images/checkbox-checked.svg b/www/wiki/resources/src/mediawiki.ui/components/images/checkbox-checked.svg
new file mode 100644
index 00000000..7f3299a8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/images/checkbox-checked.svg
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g fill="#fff">
+ <path d="M17 7.5L9.5 15 6 11.5 4.5 13l5 5L20 7.5c-.706-.706-2.294-.706-3 0z" id="check"/>
+</g></svg>
diff --git a/www/wiki/resources/src/mediawiki.ui/components/images/checked.png b/www/wiki/resources/src/mediawiki.ui/components/images/checked.png
new file mode 100644
index 00000000..672a8244
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/images/checked.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.ui/components/images/checked.svg b/www/wiki/resources/src/mediawiki.ui/components/images/checked.svg
new file mode 100644
index 00000000..aca2b2b0
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/images/checked.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M4 12l5 5L20 5" stroke="#00B78C" stroke-width="3" fill="none"/></svg>
diff --git a/www/wiki/resources/src/mediawiki.ui/components/images/checked_disabled.png b/www/wiki/resources/src/mediawiki.ui/components/images/checked_disabled.png
new file mode 100644
index 00000000..8217815d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/images/checked_disabled.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.ui/components/images/checked_disabled.svg b/www/wiki/resources/src/mediawiki.ui/components/images/checked_disabled.svg
new file mode 100644
index 00000000..ba4010ee
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/images/checked_disabled.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><path d="M4 12l5 5L20 5" stroke="#fff" stroke-width="3" fill="none"/></svg>
diff --git a/www/wiki/resources/src/mediawiki.ui/components/images/radio_checked.png b/www/wiki/resources/src/mediawiki.ui/components/images/radio_checked.png
new file mode 100644
index 00000000..adee2c98
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/images/radio_checked.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.ui/components/images/radio_checked.svg b/www/wiki/resources/src/mediawiki.ui/components/images/radio_checked.svg
new file mode 100644
index 00000000..c8b9b625
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/images/radio_checked.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><circle fill="#00AF89" cx="12" cy="12" r="6"/></svg>
diff --git a/www/wiki/resources/src/mediawiki.ui/components/images/radio_disabled.png b/www/wiki/resources/src/mediawiki.ui/components/images/radio_disabled.png
new file mode 100644
index 00000000..75989e66
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/images/radio_disabled.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.ui/components/images/radio_disabled.svg b/www/wiki/resources/src/mediawiki.ui/components/images/radio_disabled.svg
new file mode 100644
index 00000000..ec8ffe3e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/images/radio_disabled.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24"><circle fill="#fff" cx="12" cy="12" r="6"/></svg>
diff --git a/www/wiki/resources/src/mediawiki.ui/components/inputs.less b/www/wiki/resources/src/mediawiki.ui/components/inputs.less
new file mode 100644
index 00000000..74dc0b75
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/inputs.less
@@ -0,0 +1,147 @@
+// Inputs
+
+@import 'mediawiki.mixins';
+@import 'mediawiki.ui/variables';
+@import 'mediawiki.ui/mixins';
+
+// Text inputs
+//
+// Apply the mw-ui-input class to input and textarea fields.
+//
+// Styleguide 1.
+
+// mw-ui-input
+//
+// Style an input using MediaWiki UI.
+// Currently in draft status and subject to change.
+// When focused a progressive highlight appears to the left of the field.
+//
+// Markup:
+// <input class="mw-ui-input" placeholder="Enter your name">
+// <textarea class="mw-ui-input">Text here</textarea>
+//
+// Styleguide 1.1.
+.mw-ui-input {
+ background-color: #fff;
+ color: @colorGray1;
+ .box-sizing( border-box );
+ display: block;
+ width: 100%;
+ border: 1px solid @colorFieldBorder;
+ border-radius: @borderRadius;
+ padding: 0.625em 0.625em 0.546875em;
+ // necessary for smooth transition
+ box-shadow: inset 0 0 0 0.1em #fff;
+ font-family: inherit;
+ font-size: inherit;
+ line-height: 1.172em;
+ vertical-align: middle;
+
+ // Normalize & style placeholder text, see T139034
+ /* stylelint-disable indentation */
+ .mixin-placeholder( {
+ color: @colorGray7;
+ opacity: 1;
+ } );
+ /* stylelint-enable indentation */
+
+ // Firefox: Remove red outline when `required` attribute set and invalid content.
+ // See https://developer.mozilla.org/en-US/docs/Web/CSS/:invalid
+ // This should come before `:focus` so latter rules take preference.
+ &:invalid {
+ box-shadow: none;
+ }
+
+ &:hover {
+ border-color: @colorGray7;
+ }
+
+ &:focus {
+ border-color: @colorProgressive;
+ box-shadow: inset 0 0 0 1px @colorProgressive;
+ outline: 0;
+ }
+
+ // `:not()` is used exclusively for `transition`s as both are not supported by IE < 9.
+ &:not( :disabled ) {
+ .transition( ~'color 100ms, border-color 100ms, box-shadow 100ms' );
+ }
+
+ &:disabled {
+ border-color: @colorGray14;
+ color: @colorGray12;
+ }
+
+ // Normalize styling for `<input type="search">`
+ &[type='search'] {
+ // Correct the odd appearance in Chrome and Safari 5
+ -webkit-appearance: textfield;
+
+ // Remove proprietary clear button in IE 10-11, Edge 12+
+ &::-ms-clear {
+ display: none;
+ }
+
+ // Remove the inner padding and cancel buttons in Chrome on OS X and Safari on OS X
+ &::-webkit-search-cancel-button,
+ &::-webkit-search-decoration {
+ -webkit-appearance: none;
+ }
+ }
+}
+
+textarea.mw-ui-input {
+ min-height: 8em;
+}
+
+// mw-ui-input-inline
+//
+// Use mw-ui-input-inline with mw-ui-input in cases where you want a button to line up with the input.
+//
+// Markup:
+// <input class="mw-ui-input mw-ui-input-inline">
+// <button class="mw-ui-button mw-ui-progressive">Submit</button>
+//
+// Styleguide 1.2.
+input[type='number'],
+.mw-ui-input-inline {
+ display: inline-block;
+ width: auto;
+ // Make sure we limit `width` to parent element because
+ // in case of text `input` fields, `width: auto;` equals `size` attribute.
+ max-width: 100%;
+}
+
+// mw-ui-input-large
+//
+// Use mw-ui-input-large with mw-ui-input in cases where there are multiple inputs on a screen and you
+// want to draw attention to one instance. For example, replying with a subject line and more text.
+// Currently in draft status and subject to change. When used on an input field, the text is styled
+// in a large font. When used alongside another mw-ui-input large they are pushed together to form one
+// contiguous block.
+//
+// Markup:
+// <input value="input" class="mw-ui-input mw-ui-input-large" value="input" placeholder="Enter subject">
+// <textarea class="mw-ui-input mw-ui-input-large" placeholder="Provide additional details"></textarea>
+//
+// Styleguide 1.3.
+.mw-ui-input-large {
+ margin-top: 0;
+ margin-bottom: 0;
+
+ // When two large inputs are together, we make them flush by hiding one of the borders
+ & + .mw-ui-input-large {
+ margin-top: -1px;
+ }
+ // When focusing, make the input relative to raise it above any attached inputs to unhide its borders
+ &:focus {
+ position: relative;
+ }
+}
+
+input.mw-ui-input-large {
+ font-size: 1.75em;
+ font-weight: bold;
+ line-height: 1.25em;
+ padding: 0.3673em 0.3265em 0.3265em;
+}
diff --git a/www/wiki/resources/src/mediawiki.ui/components/radio.less b/www/wiki/resources/src/mediawiki.ui/components/radio.less
new file mode 100644
index 00000000..3d82e8ed
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/radio.less
@@ -0,0 +1,150 @@
+@import 'mediawiki.mixins';
+@import 'mediawiki.ui/variables';
+
+// Radio
+//
+// Styling radios in a way that works cross browser is a tricky problem to solve.
+// In MediaWiki UI put a radio and label inside a mw-ui-radio div.
+// This renders in all browsers except IE 6-8 which do not support the :checked selector;
+// these are kept backwards-compatible using the `:not( #noop )` selector.
+// You should give the radio and label matching "id" and "for" attributes, respectively.
+//
+// Markup:
+// <div class="mw-ui-radio">
+// <input type="radio" id="kss-example-4" name="kss-example-4">
+// <label for="kss-example-4">Standard radio</label>
+// </div>
+// <div class="mw-ui-radio">
+// <input type="radio" id="kss-example-4-checked" name="kss-example-4" checked>
+// <label for="kss-example-4-checked">Standard checked radio</label>
+// </div>
+// <div class="mw-ui-radio">
+// <input type="radio" id="kss-example-4-disabled" name="kss-example-4-disabled" disabled>
+// <label for="kss-example-4-disabled">Disabled radio</label>
+// </div>
+// <div class="mw-ui-radio">
+// <input type="radio" id="kss-example-4-disabled-checked" name="kss-example-4-disabled" disabled checked>
+// <label for="kss-example-4-disabled-checked">Disabled checked radio</label>
+// </div>
+//
+// Styleguide 4.
+.mw-ui-radio {
+ display: inline-block;
+ vertical-align: middle;
+}
+
+// We use the not selector to cancel out styling on IE 8 and below.
+// We also disable this styling on JavaScript disabled devices. This fixes the issue with
+// Opera Mini where checking/unchecking doesn't apply styling but potentially leaves other
+// more capable browsers with unstyled radio buttons.
+.client-js .mw-ui-radio:not( #noop ) {
+ // Position relatively so we can make use of absolute pseudo elements
+ position: relative;
+ line-height: @sizeInputBinary;
+
+ * {
+ // reset font sizes (see T74727)
+ font: inherit;
+ vertical-align: middle;
+ }
+
+ [type='radio'] {
+ // ensure the invisible radio takes up the required width
+ width: @sizeInputBinary;
+ height: @sizeInputBinary;
+ // This is needed for Firefox mobile (See T73750 to workaround default Firefox stylesheet)
+ max-width: none;
+ margin: 0;
+ // Hide `input[type=radio]` and instead style the label that follows
+ // Support: VoiceOver. Use `opacity` so that VoiceOver can still identify the radio
+ opacity: 0;
+
+ & + label {
+ padding-left: 0.4em;
+
+ // Pseudo `:before` element of the label after the radio now looks like a radio
+ &:before {
+ content: '';
+ background-color: #fff;
+ .box-sizing( border-box );
+ position: absolute;
+ left: 0;
+ width: @sizeInputBinary;
+ height: @sizeInputBinary;
+ border: 1px solid @colorGray7;
+ border-radius: 100%;
+ }
+
+ // Needed for `:focus` state's inner white circle
+ &:after {
+ content: ' ';
+ position: absolute;
+ top: 2px; // `px` unit due to pixel rounding error when using `@sizeInputBinary / 4`
+ left: 2px;
+ width: 1.14285em; // equals `@sizeInputBinary - 4px`
+ height: 1.14285em;
+ border: 1px solid transparent;
+ border-radius: 100%;
+ }
+ }
+
+ // Apply a dot on the pseudo `:before` element when the input is checked
+ &:checked + label:before {
+ border-width: @borderWidthRadioChecked;
+ }
+
+ &:enabled {
+ cursor: pointer;
+
+ & + label:before {
+ cursor: pointer;
+ .transition( ~'background-color 100ms, color 100ms, border-color 100ms' );
+ }
+
+ &:hover + label:before {
+ border-color: @colorProgressive;
+ }
+
+ &:active + label:before {
+ background-color: @colorProgressiveActive;
+ border-color: @borderColorInputBinaryActive;
+ }
+
+ &:checked {
+ & + label:before {
+ border-color: @borderColorInputBinaryChecked;
+ }
+
+ &:focus + label:after {
+ border-color: #fff;
+ }
+
+ &:hover + label:before {
+ border-color: @colorProgressiveHighlight;
+ }
+
+ &:active {
+ & + label:before {
+ border-color: @borderColorInputBinaryActive;
+ box-shadow: @boxShadowInputBinaryActive;
+ }
+
+ & + label:after {
+ border-color: @borderColorInputBinaryActive;
+ }
+ }
+ }
+ }
+
+ &:disabled {
+ & + label:before {
+ background-color: @colorGray12;
+ border-color: @colorGray12;
+ }
+
+ &:checked + label:before {
+ background-color: #fff;
+ }
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.ui/components/text.less b/www/wiki/resources/src/mediawiki.ui/components/text.less
new file mode 100644
index 00000000..a07aa684
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/text.less
@@ -0,0 +1,36 @@
+@import 'mediawiki.mixins';
+@import 'mediawiki.ui/variables';
+@import 'mediawiki.ui/mixins';
+
+/*
+Text & Anchors
+
+Allows you to give text a context as to the type of action it is indicating.
+
+Styleguide 6.
+*/
+
+/*
+Text
+
+Context classes may be used on elements with only plain-text content with the mw-ui-text base. When the context classes
+are used on interactive and block-level elements, the appropriate alternative base type classes should also be used. For
+example, mw-ui-anchor with A, or mw-ui-button with buttons.
+
+Markup:
+<span class="mw-ui-text mw-ui-progressive">Progressive</span>
+<span class="mw-ui-text mw-ui-destructive">Destructive</span>
+
+Styleguide 6.1.
+*/
+
+.mw-ui-text {
+ // The selector order is like this on purpose; IE 6 ignores the second selector,
+ // so we don't want to accidentally apply this color on all mw-ui-CONTEXT classes
+ &.mw-ui-progressive {
+ color: @colorProgressive;
+ }
+ &.mw-ui-destructive {
+ color: @colorDestructive;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.ui/components/utilities.less b/www/wiki/resources/src/mediawiki.ui/components/utilities.less
new file mode 100644
index 00000000..0bbb440f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/components/utilities.less
@@ -0,0 +1,47 @@
+// Utilities
+//
+// Other things which effect the behaviour of components
+
+// Flush left
+//
+// Used when you want to push an element to the left of its containing element
+//
+// Markup:
+// <div class="mw-ui-vform-field">
+// <label>Username <a href="#" class="mw-ui-flush-left">?</a></label>
+// <input>
+// </div>
+.mw-ui-flush-left {
+ float: left;
+ margin-left: 0;
+ padding-left: 0;
+}
+
+// Flush right
+//
+// Used when you want to push an element to the right of its containing element
+//
+// Markup:
+// <div class="mw-ui-vform-field">
+// <label>Username <a href="#" class="mw-ui-flush-right">?</a></label>
+// <input>
+// </div>
+.mw-ui-flush-right {
+ float: right;
+ padding-right: 0;
+ margin-right: 0;
+}
+
+// Center block
+//
+// Centers the element in its containing element
+//
+// Markup:
+// <div>
+// <button class="mw-ui-center-block">click me</button>
+// </div>
+.mw-ui-center-block {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
diff --git a/www/wiki/resources/src/mediawiki.ui/default.less b/www/wiki/resources/src/mediawiki.ui/default.less
new file mode 100644
index 00000000..0589d39b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/default.less
@@ -0,0 +1,5 @@
+/**
+ * Provide Agora appearance for mw-ui-* classes.
+ */
+@import 'components/forms';
+@import 'components/utilities';
diff --git a/www/wiki/resources/src/mediawiki.ui/styleguide.md b/www/wiki/resources/src/mediawiki.ui/styleguide.md
new file mode 100644
index 00000000..61691c79
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.ui/styleguide.md
@@ -0,0 +1,11 @@
+#mediawiki.ui
+
+This is the living style guide for mediawiki.ui. It is generated from the mediawiki.ui LESS source code programmatically. Please use it as a reference when developing code for MediaWiki to ensure your design is consistent with others across the site. Note this document is a work in progress and subject to change.
+
+##Design Philosophy
+
+###Inviting
+Our aesthetics should be clean and encourage interaction.
+
+###Worldly
+We are thoughtful and are aware of cultural differences. We are careful about words, color usage, and images that might offend. We are also aware of limited connectivity in some areas of the world and are thoughtful of image sizes and loading speed. We work to support accessibility.
diff --git a/www/wiki/resources/src/mediawiki.widgets.datetime/CalendarWidget.js b/www/wiki/resources/src/mediawiki.widgets.datetime/CalendarWidget.js
new file mode 100644
index 00000000..54a5a850
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets.datetime/CalendarWidget.js
@@ -0,0 +1,596 @@
+( function ( $, mw ) {
+
+ /**
+ * CalendarWidget displays a calendar that can be used to select a date. It
+ * uses {@link mw.widgets.datetime.DateTimeFormatter DateTimeFormatter} to get the details of
+ * the calendar.
+ *
+ * This widget is mainly intended to be used as a popup from a
+ * {@link mw.widgets.datetime.DateTimeInputWidget DateTimeInputWidget}, but may also be used
+ * standalone.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.TabIndexedElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object|mw.widgets.datetime.DateTimeFormatter} [formatter={}] Configuration options for
+ * mw.widgets.datetime.ProlepticGregorianDateTimeFormatter, or an mw.widgets.datetime.DateTimeFormatter
+ * instance to use.
+ * @cfg {OO.ui.Widget|null} [widget=null] Widget associated with the calendar.
+ * Specifying this configures the calendar to be used as a popup from the
+ * specified widget (e.g. absolute positioning, automatic hiding when clicked
+ * outside).
+ * @cfg {Date|null} [min=null] Minimum allowed date
+ * @cfg {Date|null} [max=null] Maximum allowed date
+ * @cfg {Date} [focusedDate] Initially focused date.
+ * @cfg {Date|Date[]|null} [selected=null] Selected date(s).
+ */
+ mw.widgets.datetime.CalendarWidget = function MwWidgetsDatetimeCalendarWidget( config ) {
+ var $colgroup, $headTR, headings, i;
+
+ // Configuration initialization
+ config = $.extend( {
+ min: null,
+ max: null,
+ focusedDate: new Date(),
+ selected: null,
+ formatter: {}
+ }, config );
+
+ // Parent constructor
+ mw.widgets.datetime.CalendarWidget[ 'super' ].call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$element } ) );
+
+ // Properties
+ if ( config.min instanceof Date && config.min.getTime() >= -62167219200000 ) {
+ this.min = config.min;
+ } else {
+ this.min = new Date( -62167219200000 ); // 0000-01-01T00:00:00.000Z
+ }
+ if ( config.max instanceof Date && config.max.getTime() <= 253402300799999 ) {
+ this.max = config.max;
+ } else {
+ this.max = new Date( 253402300799999 ); // 9999-12-31T12:59:59.999Z
+ }
+
+ if ( config.focusedDate instanceof Date ) {
+ this.focusedDate = config.focusedDate;
+ } else {
+ this.focusedDate = new Date();
+ }
+
+ this.selected = [];
+
+ if ( config.formatter instanceof mw.widgets.datetime.DateTimeFormatter ) {
+ this.formatter = config.formatter;
+ } else if ( $.isPlainObject( config.formatter ) ) {
+ this.formatter = new mw.widgets.datetime.ProlepticGregorianDateTimeFormatter( config.formatter );
+ } else {
+ throw new Error( '"formatter" must be an mw.widgets.datetime.DateTimeFormatter or a plain object' );
+ }
+
+ this.calendarData = null;
+
+ this.widget = config.widget;
+ this.$widget = config.widget ? config.widget.$element : null;
+ this.onDocumentMouseDownHandler = this.onDocumentMouseDown.bind( this );
+
+ this.$head = $( '<div>' );
+ this.$header = $( '<span>' );
+ this.$table = $( '<table>' );
+ this.cols = [];
+ this.colNullable = [];
+ this.headings = [];
+ this.$tableBody = $( '<tbody>' );
+ this.rows = [];
+ this.buttons = {};
+ this.minWidth = 1;
+ this.daysPerWeek = 0;
+
+ // Events
+ this.$element.on( {
+ keydown: this.onKeyDown.bind( this )
+ } );
+ this.formatter.connect( this, {
+ local: 'onLocalChange'
+ } );
+ if ( this.$widget ) {
+ this.checkFocusHandler = this.checkFocus.bind( this );
+ this.$element.on( {
+ focusout: this.onFocusOut.bind( this )
+ } );
+ this.$widget.on( {
+ focusout: this.onFocusOut.bind( this )
+ } );
+ }
+
+ // Initialization
+ this.$head
+ .addClass( 'mw-widgets-datetime-calendarWidget-heading' )
+ .append(
+ new OO.ui.ButtonWidget( {
+ icon: 'previous',
+ framed: false,
+ classes: [ 'mw-widgets-datetime-calendarWidget-previous' ],
+ tabIndex: -1
+ } ).connect( this, { click: 'onPrevClick' } ).$element,
+ new OO.ui.ButtonWidget( {
+ icon: 'next',
+ framed: false,
+ classes: [ 'mw-widgets-datetime-calendarWidget-next' ],
+ tabIndex: -1
+ } ).connect( this, { click: 'onNextClick' } ).$element,
+ this.$header
+ );
+ $colgroup = $( '<colgroup>' );
+ $headTR = $( '<tr>' );
+ this.$table
+ .addClass( 'mw-widgets-datetime-calendarWidget-grid' )
+ .append( $colgroup )
+ .append( $( '<thead>' ).append( $headTR ) )
+ .append( this.$tableBody );
+
+ headings = this.formatter.getCalendarHeadings();
+ for ( i = 0; i < headings.length; i++ ) {
+ this.cols[ i ] = $( '<col>' );
+ this.headings[ i ] = $( '<th>' );
+ this.colNullable[ i ] = headings[ i ] === null;
+ if ( headings[ i ] !== null ) {
+ this.headings[ i ].text( headings[ i ] );
+ this.minWidth = Math.max( this.minWidth, headings[ i ].length );
+ this.daysPerWeek++;
+ }
+ $colgroup.append( this.cols[ i ] );
+ $headTR.append( this.headings[ i ] );
+ }
+
+ this.setSelected( config.selected );
+ this.$element
+ .addClass( 'mw-widgets-datetime-calendarWidget' )
+ .append( this.$head, this.$table );
+
+ if ( this.widget ) {
+ this.$element.addClass( 'mw-widgets-datetime-calendarWidget-dependent' );
+
+ // Initially hidden - using #toggle may cause errors if subclasses override toggle with methods
+ // that reference properties not initialized at that time of parent class construction
+ // TODO: Find a better way to handle post-constructor setup
+ this.visible = false;
+ this.$element.addClass( 'oo-ui-element-hidden' );
+ } else {
+ this.updateUI();
+ }
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.datetime.CalendarWidget, OO.ui.Widget );
+ OO.mixinClass( mw.widgets.datetime.CalendarWidget, OO.ui.mixin.TabIndexedElement );
+
+ /* Events */
+
+ /**
+ * A `change` event is emitted when the selected dates change
+ *
+ * @event change
+ */
+
+ /**
+ * A `focusChange` event is emitted when the focused date changes
+ *
+ * @event focusChange
+ */
+
+ /**
+ * A `page` event is emitted when the current "month" changes
+ *
+ * @event page
+ */
+
+ /* Methods */
+
+ /**
+ * Return the current selected dates
+ *
+ * @return {Date[]}
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.getSelected = function () {
+ return this.selected;
+ };
+
+ // eslint-disable-next-line valid-jsdoc
+ /**
+ * Set the selected dates
+ *
+ * @param {Date|Date[]|null} dates
+ * @fires change
+ * @chainable
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.setSelected = function ( dates ) {
+ var i, changed = false;
+
+ if ( dates instanceof Date ) {
+ dates = [ dates ];
+ } else if ( Array.isArray( dates ) ) {
+ dates = $.grep( dates, function ( dt ) { return dt instanceof Date; } );
+ dates.sort();
+ } else {
+ dates = [];
+ }
+
+ if ( this.selected.length !== dates.length ) {
+ changed = true;
+ } else {
+ for ( i = 0; i < dates.length; i++ ) {
+ if ( dates[ i ].getTime() !== this.selected[ i ].getTime() ) {
+ changed = true;
+ break;
+ }
+ }
+ }
+
+ if ( changed ) {
+ this.selected = dates;
+ this.emit( 'change', dates );
+ this.updateUI();
+ }
+
+ return this;
+ };
+
+ /**
+ * Return the currently-focused date
+ *
+ * @return {Date}
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.getFocusedDate = function () {
+ return this.focusedDate;
+ };
+
+ // eslint-disable-next-line valid-jsdoc
+ /**
+ * Set the currently-focused date
+ *
+ * @param {Date} date
+ * @fires page
+ * @chainable
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.setFocusedDate = function ( date ) {
+ var changePage = false,
+ updateUI = false;
+
+ if ( this.focusedDate.getTime() === date.getTime() ) {
+ return this;
+ }
+
+ if ( !this.formatter.sameCalendarGrid( this.focusedDate, date ) ) {
+ changePage = true;
+ updateUI = true;
+ } else if (
+ !this.formatter.timePartIsEqual( this.focusedDate, date ) ||
+ !this.formatter.datePartIsEqual( this.focusedDate, date )
+ ) {
+ updateUI = true;
+ }
+
+ this.focusedDate = date;
+ this.emit( 'focusChanged', this.focusedDate );
+ if ( changePage ) {
+ this.emit( 'page', date );
+ }
+ if ( updateUI ) {
+ this.updateUI();
+ }
+
+ return this;
+ };
+
+ /**
+ * Adjust a date
+ *
+ * @protected
+ * @param {Date} date Date to adjust
+ * @param {string} component Component: 'month', 'week', or 'day'
+ * @param {number} delta Integer, usually -1 or 1
+ * @param {boolean} [enforceRange=true] Whether to enforce this.min and this.max
+ * @return {Date}
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.adjustDate = function ( date, component, delta ) {
+ var newDate,
+ data = this.calendarData;
+
+ if ( !data ) {
+ return date;
+ }
+
+ switch ( component ) {
+ case 'month':
+ newDate = this.formatter.adjustComponent( date, data.monthComponent, delta, 'overflow' );
+ break;
+
+ case 'week':
+ if ( data.weekComponent === undefined ) {
+ newDate = this.formatter.adjustComponent(
+ date, data.dayComponent, delta * this.daysPerWeek, 'overflow' );
+ } else {
+ newDate = this.formatter.adjustComponent( date, data.weekComponent, delta, 'overflow' );
+ }
+ break;
+
+ case 'day':
+ newDate = this.formatter.adjustComponent( date, data.dayComponent, delta, 'overflow' );
+ break;
+
+ default:
+ throw new Error( 'Unknown component' );
+ }
+
+ while ( newDate < this.min ) {
+ newDate = this.formatter.adjustComponent( newDate, data.dayComponent, 1, 'overflow' );
+ }
+ while ( newDate > this.max ) {
+ newDate = this.formatter.adjustComponent( newDate, data.dayComponent, -1, 'overflow' );
+ }
+
+ return newDate;
+ };
+
+ /**
+ * Update the user interface
+ *
+ * @protected
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.updateUI = function () {
+ var r, c, row, day, k, $cell,
+ width = this.minWidth,
+ nullCols = [],
+ focusedDate = this.getFocusedDate(),
+ selected = this.getSelected(),
+ datePartIsEqual = this.formatter.datePartIsEqual.bind( this.formatter ),
+ isSelected = function ( dt ) {
+ return datePartIsEqual( this, dt );
+ };
+
+ this.calendarData = this.formatter.getCalendarData( focusedDate );
+
+ this.$header.text( this.calendarData.header );
+
+ for ( c = 0; c < this.colNullable.length; c++ ) {
+ nullCols[ c ] = this.colNullable[ c ];
+ if ( nullCols[ c ] ) {
+ for ( r = 0; r < this.calendarData.rows.length; r++ ) {
+ if ( this.calendarData.rows[ r ][ c ] ) {
+ nullCols[ c ] = false;
+ break;
+ }
+ }
+ }
+ }
+
+ this.$tableBody.children().detach();
+ for ( r = 0; r < this.calendarData.rows.length; r++ ) {
+ if ( !this.rows[ r ] ) {
+ this.rows[ r ] = $( '<tr>' );
+ } else {
+ this.rows[ r ].children().detach();
+ }
+ this.$tableBody.append( this.rows[ r ] );
+ row = this.calendarData.rows[ r ];
+ for ( c = 0; c < row.length; c++ ) {
+ day = row[ c ];
+ if ( day === null ) {
+ k = 'empty-' + r + '-' + c;
+ if ( !this.buttons[ k ] ) {
+ this.buttons[ k ] = $( '<td>' );
+ }
+ $cell = this.buttons[ k ];
+ $cell.toggleClass( 'oo-ui-element-hidden', nullCols[ c ] );
+ } else {
+ k = ( day.extra ? day.extra : '' ) + day.display;
+ width = Math.max( width, day.display.length );
+ if ( !this.buttons[ k ] ) {
+ this.buttons[ k ] = new OO.ui.ButtonWidget( {
+ $element: $( '<td>' ),
+ classes: [
+ 'mw-widgets-datetime-calendarWidget-cell',
+ day.extra ? 'mw-widgets-datetime-calendarWidget-extra' : ''
+ ],
+ framed: true,
+ label: day.display,
+ tabIndex: -1
+ } );
+ this.buttons[ k ].connect( this, { click: [ 'onDayClick', this.buttons[ k ] ] } );
+ }
+ this.buttons[ k ]
+ .setData( day.date )
+ .setDisabled( day.date < this.min || day.date > this.max );
+ $cell = this.buttons[ k ].$element;
+ $cell.toggleClass( 'mw-widgets-datetime-calendarWidget-focused',
+ this.formatter.datePartIsEqual( focusedDate, day.date ) );
+ $cell.toggleClass( 'mw-widgets-datetime-calendarWidget-selected',
+ selected.some( isSelected, day.date ) );
+ }
+ this.rows[ r ].append( $cell );
+ }
+ }
+
+ for ( c = 0; c < this.cols.length; c++ ) {
+ if ( nullCols[ c ] ) {
+ this.cols[ c ].width( 0 );
+ } else {
+ this.cols[ c ].width( width + 'em' );
+ }
+ this.cols[ c ].toggleClass( 'oo-ui-element-hidden', nullCols[ c ] );
+ this.headings[ c ].toggleClass( 'oo-ui-element-hidden', nullCols[ c ] );
+ }
+ };
+
+ /**
+ * Handles formatter 'local' flag changing
+ *
+ * @protected
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.onLocalChange = function () {
+ if ( this.formatter.localChangesDatePart( this.getFocusedDate() ) ) {
+ this.emit( 'page', this.getFocusedDate() );
+ }
+
+ this.updateUI();
+ };
+
+ /**
+ * Handles previous button click
+ *
+ * @protected
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.onPrevClick = function () {
+ this.setFocusedDate( this.adjustDate( this.getFocusedDate(), 'month', -1 ) );
+ if ( !this.$widget || OO.ui.contains( this.$element[ 0 ], document.activeElement, true ) ) {
+ this.$element.focus();
+ }
+ };
+
+ /**
+ * Handles next button click
+ *
+ * @protected
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.onNextClick = function () {
+ this.setFocusedDate( this.adjustDate( this.getFocusedDate(), 'month', 1 ) );
+ if ( !this.$widget || OO.ui.contains( this.$element[ 0 ], document.activeElement, true ) ) {
+ this.$element.focus();
+ }
+ };
+
+ /**
+ * Handles day button click
+ *
+ * @protected
+ * @param {OO.ui.ButtonWidget} $button
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.onDayClick = function ( $button ) {
+ this.setFocusedDate( $button.getData() );
+ this.setSelected( [ $button.getData() ] );
+ if ( !this.$widget || OO.ui.contains( this.$element[ 0 ], document.activeElement, true ) ) {
+ this.$element.focus();
+ }
+ };
+
+ /**
+ * Handles document mouse down events.
+ *
+ * @protected
+ * @param {jQuery.Event} e Mouse down event
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.onDocumentMouseDown = function ( e ) {
+ if ( this.$widget &&
+ !OO.ui.contains( this.$element[ 0 ], e.target, true ) &&
+ !OO.ui.contains( this.$widget[ 0 ], e.target, true )
+ ) {
+ this.toggle( false );
+ }
+ };
+
+ /**
+ * Handles key presses.
+ *
+ * @protected
+ * @param {jQuery.Event} e Key down event
+ * @return {boolean} False to cancel the default event
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.onKeyDown = function ( e ) {
+ var focusedDate = this.getFocusedDate();
+
+ if ( !this.isDisabled() ) {
+ switch ( e.which ) {
+ case OO.ui.Keys.ENTER:
+ case OO.ui.Keys.SPACE:
+ this.setSelected( [ focusedDate ] );
+ return false;
+
+ case OO.ui.Keys.LEFT:
+ this.setFocusedDate( this.adjustDate( focusedDate, 'day', -1 ) );
+ return false;
+
+ case OO.ui.Keys.RIGHT:
+ this.setFocusedDate( this.adjustDate( focusedDate, 'day', 1 ) );
+ return false;
+
+ case OO.ui.Keys.UP:
+ this.setFocusedDate( this.adjustDate( focusedDate, 'week', -1 ) );
+ return false;
+
+ case OO.ui.Keys.DOWN:
+ this.setFocusedDate( this.adjustDate( focusedDate, 'week', 1 ) );
+ return false;
+
+ case OO.ui.Keys.PAGEUP:
+ this.setFocusedDate( this.adjustDate( focusedDate, 'month', -1 ) );
+ return false;
+
+ case OO.ui.Keys.PAGEDOWN:
+ this.setFocusedDate( this.adjustDate( focusedDate, 'month', 1 ) );
+ return false;
+ }
+ }
+ };
+
+ /**
+ * Handles focusout events in dependent mode
+ *
+ * @private
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.onFocusOut = function () {
+ setTimeout( this.checkFocusHandler );
+ };
+
+ /**
+ * When we or our widget lost focus, check if the calendar should be hidden.
+ *
+ * @private
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.checkFocus = function () {
+ var containers = [ this.$element[ 0 ], this.$widget[ 0 ] ],
+ activeElement = document.activeElement;
+
+ if ( !activeElement || !OO.ui.contains( containers, activeElement, true ) ) {
+ this.toggle( false );
+ }
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.CalendarWidget.prototype.toggle = function ( visible ) {
+ var change;
+
+ visible = ( visible === undefined ? !this.visible : !!visible );
+ change = visible !== this.isVisible();
+
+ // Parent method
+ mw.widgets.datetime.CalendarWidget[ 'super' ].prototype.toggle.call( this, visible );
+
+ if ( change ) {
+ if ( visible ) {
+ // Auto-hide
+ if ( this.$widget ) {
+ this.getElementDocument().addEventListener(
+ 'mousedown', this.onDocumentMouseDownHandler, true
+ );
+ }
+ this.updateUI();
+ } else {
+ this.getElementDocument().removeEventListener(
+ 'mousedown', this.onDocumentMouseDownHandler, true
+ );
+ }
+ }
+
+ return this;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets.datetime/CalendarWidget.less b/www/wiki/resources/src/mediawiki.widgets.datetime/CalendarWidget.less
new file mode 100644
index 00000000..093c58b2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets.datetime/CalendarWidget.less
@@ -0,0 +1,75 @@
+/* stylelint-disable no-duplicate-selectors */
+@import 'mediawiki.widgets.datetime.definitions';
+
+.mw-widgets-datetime-calendarWidget {
+ display: inline-block;
+ position: relative;
+ vertical-align: middle;
+ padding: 0.5em;
+
+ &.mw-widgets-datetime-calendarWidget-dependent {
+ display: block;
+ position: absolute;
+ z-index: 4;
+ }
+
+ &-grid {
+ table-layout: fixed;
+
+ .mw-widgets-datetime-calendarWidget-cell {
+ display: table-cell;
+ white-space: nowrap;
+ }
+ }
+
+ background-color: #fff;
+ border: 1px solid #ccc;
+
+ &.mw-widgets-datetime-calendarWidget-dependent {
+ margin-top: -1px;
+ border-top: 1px solid #fff;
+ }
+
+ &-heading {
+ text-align: center;
+ vertical-align: middle;
+ font-weight: bold;
+ white-space: nowrap;
+
+ .mw-widgets-datetime-calendarWidget-previous {
+ float: left;
+ }
+ .mw-widgets-datetime-calendarWidget-next {
+ float: right;
+ }
+ }
+
+ &-grid {
+ margin: 0 auto;
+
+ .mw-widgets-datetime-calendarWidget-cell {
+ text-align: center;
+
+ .oo-ui-buttonElement-button {
+ width: 100%;
+ border: 1px dotted rgba( 255, 255, 255, 0 );
+ .oo-ui-box-sizing( border-box );
+ }
+
+ &.mw-widgets-datetime-calendarWidget-extra .oo-ui-buttonElement-button .oo-ui-labelElement-label {
+ color: #bbb;
+ }
+
+ &.mw-widgets-datetime-calendarWidget-selected .oo-ui-buttonElement-button {
+ background-color: #def;
+ .oo-ui-labelElement-label {
+ color: #38f;
+ }
+ }
+ }
+ }
+
+ &:focus &-grid &-cell&-focused .oo-ui-buttonElement-button {
+ border-color: rgba( 0, 0, 0, 0.3 );
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeFormatter.js b/www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeFormatter.js
new file mode 100644
index 00000000..a7a3bd30
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeFormatter.js
@@ -0,0 +1,627 @@
+( function ( $, mw ) {
+
+ /**
+ * Provides various methods needed for formatting dates and times.
+ *
+ * @class
+ * @abstract
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [format='@default'] May be a key from the {@link #static-formats static formats},
+ * or a format specification as defined by {@link #method-parseFieldSpec parseFieldSpec}
+ * and {@link #method-getFieldForTag getFieldForTag}.
+ * @cfg {boolean} [local=false] Whether dates are local time or UTC
+ * @cfg {string[]} [fullZones] Time zone indicators. Array of 2 strings, for
+ * UTC and local time.
+ * @cfg {string[]} [shortZones] Abbreviated time zone indicators. Array of 2
+ * strings, for UTC and local time.
+ * @cfg {Date} [defaultDate] Default date, for filling unspecified components.
+ * Defaults to the current date and time (with 0 milliseconds).
+ */
+ mw.widgets.datetime.DateTimeFormatter = function MwWidgetsDatetimeDateTimeFormatter( config ) {
+ this.constructor.static.setupDefaults();
+
+ config = $.extend( {
+ format: '@default',
+ local: false,
+ fullZones: this.constructor.static.fullZones,
+ shortZones: this.constructor.static.shortZones
+ }, config );
+
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+
+ // Properties
+ if ( this.constructor.static.formats[ config.format ] ) {
+ this.format = this.constructor.static.formats[ config.format ];
+ } else {
+ this.format = config.format;
+ }
+ this.local = !!config.local;
+ this.fullZones = config.fullZones;
+ this.shortZones = config.shortZones;
+ if ( config.defaultDate instanceof Date ) {
+ this.defaultDate = config.defaultDate;
+ } else {
+ this.defaultDate = new Date();
+ if ( this.local ) {
+ this.defaultDate.setMilliseconds( 0 );
+ } else {
+ this.defaultDate.setUTCMilliseconds( 0 );
+ }
+ }
+ };
+
+ /* Setup */
+
+ OO.initClass( mw.widgets.datetime.DateTimeFormatter );
+ OO.mixinClass( mw.widgets.datetime.DateTimeFormatter, OO.EventEmitter );
+
+ /* Static */
+
+ /**
+ * Default format specifications. See the {@link #format format} parameter.
+ *
+ * @static
+ * @inheritable
+ * @property {Object}
+ */
+ mw.widgets.datetime.DateTimeFormatter.static.formats = {};
+
+ /**
+ * Default time zone indicators
+ *
+ * @static
+ * @inheritable
+ * @property {string[]}
+ */
+ mw.widgets.datetime.DateTimeFormatter.static.fullZones = null;
+
+ /**
+ * Default abbreviated time zone indicators
+ *
+ * @static
+ * @inheritable
+ * @property {string[]}
+ */
+ mw.widgets.datetime.DateTimeFormatter.static.shortZones = null;
+
+ mw.widgets.datetime.DateTimeFormatter.static.setupDefaults = function () {
+ if ( !this.fullZones ) {
+ this.fullZones = [
+ mw.msg( 'timezone-utc' ),
+ mw.msg( 'timezone-local' )
+ ];
+ }
+ if ( !this.shortZones ) {
+ this.shortZones = [
+ 'Z',
+ this.fullZones[ 1 ].substr( 0, 1 ).toUpperCase()
+ ];
+ if ( this.shortZones[ 1 ] === 'Z' ) {
+ this.shortZones[ 1 ] = 'L';
+ }
+ }
+ };
+
+ /* Events */
+
+ /**
+ * A `local` event is emitted when the 'local' flag is changed.
+ *
+ * @event local
+ */
+
+ /* Methods */
+
+ /**
+ * Whether dates are in local time or UTC
+ *
+ * @return {boolean} True if local time
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.getLocal = function () {
+ return this.local;
+ };
+
+ // eslint-disable-next-line valid-jsdoc
+ /**
+ * Toggle whether dates are in local time or UTC
+ *
+ * @param {boolean} [flag] Set the flag instead of toggling it
+ * @fires local
+ * @chainable
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.toggleLocal = function ( flag ) {
+ if ( flag === undefined ) {
+ flag = !this.local;
+ } else {
+ flag = !!flag;
+ }
+ if ( this.local !== flag ) {
+ this.local = flag;
+ this.emit( 'local', this.local );
+ }
+ return this;
+ };
+
+ /**
+ * Get the default date
+ *
+ * @return {Date}
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.getDefaultDate = function () {
+ return new Date( this.defaultDate.getTime() );
+ };
+
+ /**
+ * Fetch the field specification array for this object.
+ *
+ * See {@link #parseFieldSpec parseFieldSpec} for details on the return value structure.
+ *
+ * @return {Array}
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.getFieldSpec = function () {
+ return this.parseFieldSpec( this.format );
+ };
+
+ /**
+ * Parse a format string into a field specification
+ *
+ * The input is a string containing tags formatted as ${tag|param|param...}
+ * (for editable fields) and $!{tag|param|param...} (for non-editable fields).
+ * Most tags are defined by {@link #getFieldForTag getFieldForTag}, but a few
+ * are defined here:
+ * - ${intercalary|X|text}: Text that is only displayed when the 'intercalary'
+ * component is X.
+ * - ${not-intercalary|X|text}: Text that is displayed unless the 'intercalary'
+ * component is X.
+ *
+ * Elements of the returned array are strings or objects. Strings are meant to
+ * be displayed as-is. Objects are as returned by {@link #getFieldForTag getFieldForTag}.
+ *
+ * @protected
+ * @param {string} format
+ * @return {Array}
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.parseFieldSpec = function ( format ) {
+ var m, last, tag, params, spec,
+ ret = [],
+ re = /(.*?)(\$(!?)\{([^}]+)\})/g;
+
+ last = 0;
+ while ( ( m = re.exec( format ) ) !== null ) {
+ last = re.lastIndex;
+
+ if ( m[ 1 ] !== '' ) {
+ ret.push( m[ 1 ] );
+ }
+
+ params = m[ 4 ].split( '|' );
+ tag = params.shift();
+ spec = this.getFieldForTag( tag, params );
+ if ( spec ) {
+ if ( m[ 3 ] === '!' ) {
+ spec.editable = false;
+ }
+ ret.push( spec );
+ } else {
+ ret.push( m[ 2 ] );
+ }
+ }
+ if ( last < format.length ) {
+ ret.push( format.substr( last ) );
+ }
+
+ return ret;
+ };
+
+ /**
+ * Turn a tag into a field specification object
+ *
+ * Fields implemented here are:
+ * - ${intercalary|X|text}: Text that is only displayed when the 'intercalary'
+ * component is X.
+ * - ${not-intercalary|X|text}: Text that is displayed unless the 'intercalary'
+ * component is X.
+ * - ${zone|#}: Timezone offset, "+0000" format.
+ * - ${zone|:}: Timezone offset, "+00:00" format.
+ * - ${zone|short}: Timezone from 'shortZones' configuration setting.
+ * - ${zone|full}: Timezone from 'fullZones' configuration setting.
+ *
+ * @protected
+ * @abstract
+ * @param {string} tag
+ * @param {string[]} params
+ * @return {Object|null} Field specification object, or null if the tag+params are unrecognized.
+ * @return {string|null} return.component Date component corresponding to this field, if any.
+ * @return {boolean} return.editable Whether this field is editable.
+ * @return {string} return.type What kind of field this is:
+ * - 'static': The field is a static string; component will be null.
+ * - 'number': The field is generally numeric.
+ * - 'string': The field is generally textual.
+ * - 'boolean': The field is a boolean.
+ * - 'toggleLocal': The field represents {@link #getLocal this.getLocal()}.
+ * Editing should directly call {@link #toggleLocal this.toggleLocal()}.
+ * @return {boolean} return.calendarComponent Whether this field is part of a calendar, e.g.
+ * part of the date instead of the time.
+ * @return {number} return.size Maximum number of characters in the field (when
+ * the 'intercalary' component is falsey). If 0, the field should be hidden entirely.
+ * @return {Object.<string,number>} return.intercalarySize Map from
+ * 'intercalary' component values to overridden sizes.
+ * @return {string} return.value For type='static', the string to display.
+ * @return {function(Mixed): string} return.formatValue A function to format a
+ * component value as a display string.
+ * @return {function(string): Mixed} return.parseValue A function to parse a
+ * display string into a component value. If parsing fails, returns undefined.
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.getFieldForTag = function ( tag, params ) {
+ var c, spec = null;
+
+ switch ( tag ) {
+ case 'intercalary':
+ case 'not-intercalary':
+ if ( params.length < 2 || !params[ 0 ] ) {
+ return null;
+ }
+ spec = {
+ component: null,
+ calendarComponent: false,
+ editable: false,
+ type: 'static',
+ value: params.slice( 1 ).join( '|' ),
+ size: 0,
+ intercalarySize: {}
+ };
+ if ( tag === 'intercalary' ) {
+ spec.intercalarySize[ params[ 0 ] ] = spec.value.length;
+ } else {
+ spec.size = spec.value.length;
+ spec.intercalarySize[ params[ 0 ] ] = 0;
+ }
+ return spec;
+
+ case 'zone':
+ switch ( params[ 0 ] ) {
+ case '#':
+ case ':':
+ c = params[ 0 ] === '#' ? '' : ':';
+ return {
+ component: 'zone',
+ calendarComponent: false,
+ editable: true,
+ type: 'toggleLocal',
+ size: 5 + c.length,
+ formatValue: function ( v ) {
+ var o, r;
+ if ( v ) {
+ o = new Date().getTimezoneOffset();
+ r = String( Math.abs( o ) % 60 );
+ while ( r.length < 2 ) {
+ r = '0' + r;
+ }
+ r = String( Math.floor( Math.abs( o ) / 60 ) ) + c + r;
+ while ( r.length < 4 + c.length ) {
+ r = '0' + r;
+ }
+ return ( o <= 0 ? '+' : '−' ) + r;
+ } else {
+ return '+00' + c + '00';
+ }
+ },
+ parseValue: function ( v ) {
+ var m;
+ v = String( v ).trim();
+ if ( ( m = /^([+-−])([0-9]{1,2}):?([0-9]{2})$/.test( v ) ) ) {
+ return ( m[ 2 ] * 60 + m[ 3 ] ) * ( m[ 1 ] === '+' ? -1 : 1 );
+ } else {
+ return undefined;
+ }
+ }
+ };
+
+ case 'short':
+ case 'full':
+ spec = {
+ component: 'zone',
+ calendarComponent: false,
+ editable: true,
+ type: 'toggleLocal',
+ values: params[ 0 ] === 'short' ? this.shortZones : this.fullZones,
+ formatValue: this.formatSpecValue,
+ parseValue: this.parseSpecValue
+ };
+ spec.size = Math.max.apply(
+ null, $.map( spec.values, function ( v ) { return v.length; } )
+ );
+ return spec;
+ }
+ return null;
+
+ default:
+ return null;
+ }
+ };
+
+ /**
+ * Format a value for a field specification
+ *
+ * 'this' must be the field specification object. The intention is that you
+ * could just assign this function as the 'formatValue' for each field spec.
+ *
+ * Besides the publicly-documented fields, uses the following:
+ * - values: Enumerated values for the field
+ * - zeropad: Whether to pad the number with zeros.
+ *
+ * @protected
+ * @param {Mixed} v
+ * @return {string}
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.formatSpecValue = function ( v ) {
+ if ( v === undefined || v === null ) {
+ return '';
+ }
+
+ if ( typeof v === 'boolean' || this.type === 'toggleLocal' ) {
+ v = v ? 1 : 0;
+ }
+
+ if ( this.values ) {
+ return this.values[ v ];
+ }
+
+ v = String( v );
+ if ( this.zeropad ) {
+ while ( v.length < this.size ) {
+ v = '0' + v;
+ }
+ }
+ return v;
+ };
+
+ /**
+ * Parse a value for a field specification
+ *
+ * 'this' must be the field specification object. The intention is that you
+ * could just assign this function as the 'parseValue' for each field spec.
+ *
+ * Besides the publicly-documented fields, uses the following:
+ * - values: Enumerated values for the field
+ *
+ * @protected
+ * @param {string} v
+ * @return {number|string|null}
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.parseSpecValue = function ( v ) {
+ var k, re;
+
+ if ( v === '' ) {
+ return null;
+ }
+
+ if ( !this.values ) {
+ v = +v;
+ if ( this.type === 'boolean' || this.type === 'toggleLocal' ) {
+ return isNaN( v ) ? undefined : !!v;
+ } else {
+ return isNaN( v ) ? undefined : v;
+ }
+ }
+
+ if ( v.normalize ) {
+ v = v.normalize();
+ }
+ re = new RegExp( '^\\s*' + v.replace( /([\\{}()|.?*+\-^$\[\]])/g, '\\$1' ), 'i' ); // eslint-disable-line no-useless-escape
+ for ( k in this.values ) {
+ k = +k;
+ if ( !isNaN( k ) && re.test( this.values[ k ] ) ) {
+ if ( this.type === 'boolean' || this.type === 'toggleLocal' ) {
+ return !!k;
+ } else {
+ return k;
+ }
+ }
+ }
+ return undefined;
+ };
+
+ /**
+ * Get components from a Date object
+ *
+ * Most specific components are defined by the subclass. "Global" components
+ * are:
+ * - intercalary: {string} Non-falsey values are used to indicate intercalary days.
+ * - zone: {number} Timezone offset in minutes.
+ *
+ * @abstract
+ * @param {Date|null} date
+ * @return {Object} Components
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.getComponentsFromDate = function ( date ) {
+ // Should be overridden by subclass
+ return {
+ zone: this.local ? date.getTimezoneOffset() : 0
+ };
+ };
+
+ /**
+ * Get a Date object from components
+ *
+ * @param {Object} components Date components
+ * @return {Date}
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.getDateFromComponents = function ( /* components */ ) {
+ // Should be overridden by subclass
+ return new Date();
+ };
+
+ /**
+ * Adjust a date
+ *
+ * @param {Date|null} date To be adjusted
+ * @param {string} component To adjust
+ * @param {number} delta Adjustment amount
+ * @param {string} mode Adjustment mode:
+ * - 'overflow': "Jan 32" => "Feb 1", "Jan 33" => "Feb 2", "Feb 0" => "Jan 31", etc.
+ * - 'wrap': "Jan 32" => "Jan 1", "Jan 33" => "Jan 2", "Jan 0" => "Jan 31", etc.
+ * - 'clip': "Jan 32" => "Jan 31", "Feb 32" => "Feb 28" (or 29), "Feb 0" => "Feb 1", etc.
+ * @return {Date} Adjusted date
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.adjustComponent = function ( date /* , component, delta, mode */ ) {
+ // Should be overridden by subclass
+ return date;
+ };
+
+ /**
+ * Get the column headings (weekday abbreviations) for a calendar grid
+ *
+ * Null-valued columns are hidden if getCalendarData() returns no "day" object
+ * for all days in that column.
+ *
+ * @abstract
+ * @return {Array} string or null
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.getCalendarHeadings = function () {
+ // Should be overridden by subclass
+ return [];
+ };
+
+ /**
+ * Test whether two dates are in the same calendar grid
+ *
+ * @abstract
+ * @param {Date} date1
+ * @param {Date} date2
+ * @return {boolean}
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.sameCalendarGrid = function ( date1, date2 ) {
+ // Should be overridden by subclass
+ return date1.getTime() === date2.getTime();
+ };
+
+ /**
+ * Test whether the date parts of two Dates are equal
+ *
+ * @param {Date} date1
+ * @param {Date} date2
+ * @return {boolean}
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.datePartIsEqual = function ( date1, date2 ) {
+ if ( this.local ) {
+ return (
+ date1.getFullYear() === date2.getFullYear() &&
+ date1.getMonth() === date2.getMonth() &&
+ date1.getDate() === date2.getDate()
+ );
+ } else {
+ return (
+ date1.getUTCFullYear() === date2.getUTCFullYear() &&
+ date1.getUTCMonth() === date2.getUTCMonth() &&
+ date1.getUTCDate() === date2.getUTCDate()
+ );
+ }
+ };
+
+ /**
+ * Test whether the time parts of two Dates are equal
+ *
+ * @param {Date} date1
+ * @param {Date} date2
+ * @return {boolean}
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.timePartIsEqual = function ( date1, date2 ) {
+ if ( this.local ) {
+ return (
+ date1.getHours() === date2.getHours() &&
+ date1.getMinutes() === date2.getMinutes() &&
+ date1.getSeconds() === date2.getSeconds() &&
+ date1.getMilliseconds() === date2.getMilliseconds()
+ );
+ } else {
+ return (
+ date1.getUTCHours() === date2.getUTCHours() &&
+ date1.getUTCMinutes() === date2.getUTCMinutes() &&
+ date1.getUTCSeconds() === date2.getUTCSeconds() &&
+ date1.getUTCMilliseconds() === date2.getUTCMilliseconds()
+ );
+ }
+ };
+
+ /**
+ * Test whether toggleLocal() changes the date part
+ *
+ * @param {Date} date
+ * @return {boolean}
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.localChangesDatePart = function ( date ) {
+ return (
+ date.getUTCFullYear() !== date.getFullYear() ||
+ date.getUTCMonth() !== date.getMonth() ||
+ date.getUTCDate() !== date.getDate()
+ );
+ };
+
+ /**
+ * Create a new Date by merging the date part from one with the time part from
+ * another.
+ *
+ * @param {Date} datepart
+ * @param {Date} timepart
+ * @return {Date}
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.mergeDateAndTime = function ( datepart, timepart ) {
+ var ret = new Date( datepart.getTime() );
+
+ if ( this.local ) {
+ ret.setHours(
+ timepart.getHours(),
+ timepart.getMinutes(),
+ timepart.getSeconds(),
+ timepart.getMilliseconds()
+ );
+ } else {
+ ret.setUTCHours(
+ timepart.getUTCHours(),
+ timepart.getUTCMinutes(),
+ timepart.getUTCSeconds(),
+ timepart.getUTCMilliseconds()
+ );
+ }
+
+ return ret;
+ };
+
+ /**
+ * Get data for a calendar grid
+ *
+ * A "day" object is:
+ * - display: {string} Display text for the day.
+ * - date: {Date} Date to use when the day is selected.
+ * - extra: {string|null} 'prev' or 'next' on days used to fill out the weeks
+ * at the start and end of the month.
+ *
+ * In any one result object, 'extra' + 'display' will always be unique.
+ *
+ * @abstract
+ * @param {Date|null} current Current date
+ * @return {Object} Data
+ * @return {string} return.header String to display as the calendar header
+ * @return {string} return.monthComponent Component to adjust by ±1 to change months.
+ * @return {string} return.dayComponent Component to adjust by ±1 to change days.
+ * @return {string} [return.weekComponent] Component to adjust by ±1 to change
+ * weeks. If omitted, the dayComponent should be adjusted by ±the number of
+ * non-nullable columns returned by this.getCalendarHeadings() to change weeks.
+ * @return {Array} return.rows Array of arrays of "day" objects or null/undefined.
+ */
+ mw.widgets.datetime.DateTimeFormatter.prototype.getCalendarData = function ( /* components */ ) {
+ // Should be overridden by subclass
+ return {
+ header: '',
+ monthComponent: 'month',
+ dayComponent: 'day',
+ rows: []
+ };
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js b/www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js
new file mode 100644
index 00000000..9233eef2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js
@@ -0,0 +1,837 @@
+( function ( $, mw ) {
+
+ /**
+ * DateTimeInputWidgets can be used to input a date, a time, or a date and
+ * time, in either UTC or the user's local timezone.
+ * Please see the [OOjs UI documentation on MediaWiki] [1] for more information and examples.
+ *
+ * This widget can be used inside a HTML form, such as a OO.ui.FormLayout.
+ *
+ * @example
+ * // Example of a text input widget
+ * var dateTimeInput = new mw.widgets.datetime.DateTimeInputWidget( {} )
+ * $( 'body' ).append( dateTimeInput.$element );
+ *
+ * [1]: https://www.mediawiki.org/wiki/OOjs_UI/Widgets/Inputs
+ *
+ * @class
+ * @extends OO.ui.InputWidget
+ * @mixins OO.ui.mixin.IconElement
+ * @mixins OO.ui.mixin.IndicatorElement
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [type='datetime'] Whether to act like a 'date', 'time', or 'datetime' input.
+ * Affects values stored in the relevant <input> and the formatting and
+ * interpretation of values passed to/from getValue() and setValue(). It's up
+ * to the user to configure the DateTimeFormatter correctly.
+ * @cfg {Object|mw.widgets.datetime.DateTimeFormatter} [formatter={}] Configuration options for
+ * mw.widgets.datetime.ProlepticGregorianDateTimeFormatter (with 'format' defaulting to
+ * '@date', '@time', or '@datetime' depending on 'type'), or an
+ * mw.widgets.datetime.DateTimeFormatter instance to use.
+ * @cfg {Object|null} [calendar={}] Configuration options for
+ * mw.widgets.datetime.CalendarWidget; note certain settings will be forced based on the
+ * settings passed to this widget. Set null to disable the calendar.
+ * @cfg {boolean} [required=false] Whether a value is required.
+ * @cfg {boolean} [clearable=true] Whether to provide for blanking the value.
+ * @cfg {Date|null} [value=null] Default value for the widget
+ * @cfg {Date|string|null} [min=null] Minimum allowed date
+ * @cfg {Date|string|null} [max=null] Maximum allowed date
+ */
+ mw.widgets.datetime.DateTimeInputWidget = function MwWidgetsDatetimeDateTimeInputWidget( config ) {
+ // Configuration initialization
+ config = $.extend( {
+ type: 'datetime',
+ clearable: true,
+ required: false,
+ min: null,
+ max: null,
+ formatter: {},
+ calendar: {}
+ }, config );
+
+ // See InputWidget#reusePreInfuseDOM about config.$input
+ if ( config.$input ) {
+ config.$input.addClass( 'oo-ui-element-hidden' );
+ }
+
+ if ( $.isPlainObject( config.formatter ) && config.formatter.format === undefined ) {
+ config.formatter.format = '@' + config.type;
+ }
+
+ // Early properties
+ this.type = config.type;
+
+ // Parent constructor
+ mw.widgets.datetime.DateTimeInputWidget[ 'super' ].call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.IndicatorElement.call( this, config );
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ // Properties
+ this.$handle = $( '<span>' );
+ this.$fields = $( '<span>' );
+ this.fields = [];
+ this.clearable = !!config.clearable;
+ this.required = !!config.required;
+
+ if ( typeof config.min === 'string' ) {
+ config.min = this.parseDateValue( config.min );
+ }
+ if ( config.min instanceof Date && config.min.getTime() >= -62167219200000 ) {
+ this.min = config.min;
+ } else {
+ this.min = new Date( -62167219200000 ); // 0000-01-01T00:00:00.000Z
+ }
+
+ if ( typeof config.max === 'string' ) {
+ config.max = this.parseDateValue( config.max );
+ }
+ if ( config.max instanceof Date && config.max.getTime() <= 253402300799999 ) {
+ this.max = config.max;
+ } else {
+ this.max = new Date( 253402300799999 ); // 9999-12-31T12:59:59.999Z
+ }
+
+ switch ( this.type ) {
+ case 'date':
+ this.min.setUTCHours( 0, 0, 0, 0 );
+ this.max.setUTCHours( 23, 59, 59, 999 );
+ break;
+ case 'time':
+ this.min.setUTCFullYear( 1970, 0, 1 );
+ this.max.setUTCFullYear( 1970, 0, 1 );
+ break;
+ }
+ if ( this.min > this.max ) {
+ throw new Error(
+ '"min" (' + this.min.toISOString() + ') must not be greater than ' +
+ '"max" (' + this.max.toISOString() + ')'
+ );
+ }
+
+ if ( config.formatter instanceof mw.widgets.datetime.DateTimeFormatter ) {
+ this.formatter = config.formatter;
+ } else if ( $.isPlainObject( config.formatter ) ) {
+ this.formatter = new mw.widgets.datetime.ProlepticGregorianDateTimeFormatter( config.formatter );
+ } else {
+ throw new Error( '"formatter" must be an mw.widgets.datetime.DateTimeFormatter or a plain object' );
+ }
+
+ if ( this.type === 'time' || config.calendar === null ) {
+ this.calendar = null;
+ } else {
+ config.calendar = $.extend( {}, config.calendar, {
+ formatter: this.formatter,
+ widget: this,
+ min: this.min,
+ max: this.max
+ } );
+ this.calendar = new mw.widgets.datetime.CalendarWidget( config.calendar );
+ }
+
+ // Events
+ this.$handle.on( {
+ click: this.onHandleClick.bind( this )
+ } );
+ this.connect( this, {
+ change: 'onChange'
+ } );
+ this.formatter.connect( this, {
+ local: 'onChange'
+ } );
+ if ( this.calendar ) {
+ this.calendar.connect( this, {
+ change: 'onCalendarChange'
+ } );
+ }
+
+ // Initialization
+ this.setTabIndex( -1 );
+
+ this.$fields.addClass( 'mw-widgets-datetime-dateTimeInputWidget-fields' );
+ this.setupFields();
+
+ this.$handle
+ .addClass( 'mw-widgets-datetime-dateTimeInputWidget-handle' )
+ .append( this.$icon, this.$indicator, this.$fields );
+
+ this.$element
+ .addClass( 'mw-widgets-datetime-dateTimeInputWidget' )
+ .append( this.$handle );
+
+ if ( this.calendar ) {
+ this.$element.append( this.calendar.$element );
+ }
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.datetime.DateTimeInputWidget, OO.ui.InputWidget );
+ OO.mixinClass( mw.widgets.datetime.DateTimeInputWidget, OO.ui.mixin.IconElement );
+ OO.mixinClass( mw.widgets.datetime.DateTimeInputWidget, OO.ui.mixin.IndicatorElement );
+ OO.mixinClass( mw.widgets.datetime.DateTimeInputWidget, OO.ui.mixin.PendingElement );
+
+ /* Static properties */
+
+ mw.widgets.datetime.DateTimeInputWidget.static.supportsSimpleLabel = false;
+
+ /* Events */
+
+ /* Methods */
+
+ /**
+ * Get the currently focused field, if any
+ *
+ * @private
+ * @return {jQuery}
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.getFocusedField = function () {
+ return this.$fields.find( this.getElementDocument().activeElement );
+ };
+
+ /**
+ * Convert a date string to a Date
+ *
+ * @private
+ * @param {string} value
+ * @return {Date|null}
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.parseDateValue = function ( value ) {
+ var date, m;
+
+ value = String( value );
+ switch ( this.type ) {
+ case 'date':
+ value = value + 'T00:00:00Z';
+ break;
+ case 'time':
+ value = '1970-01-01T' + value + 'Z';
+ break;
+ }
+ m = /^(\d{4,})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{1,3}))?Z$/.exec( value );
+ if ( m ) {
+ if ( m[ 7 ] ) {
+ while ( m[ 7 ].length < 3 ) {
+ m[ 7 ] += '0';
+ }
+ } else {
+ m[ 7 ] = 0;
+ }
+ date = new Date();
+ date.setUTCFullYear( m[ 1 ], m[ 2 ] - 1, m[ 3 ] );
+ date.setUTCHours( m[ 4 ], m[ 5 ], m[ 6 ], m[ 7 ] );
+ if ( date.getTime() < -62167219200000 || date.getTime() > 253402300799999 ||
+ date.getUTCFullYear() !== +m[ 1 ] ||
+ date.getUTCMonth() + 1 !== +m[ 2 ] ||
+ date.getUTCDate() !== +m[ 3 ] ||
+ date.getUTCHours() !== +m[ 4 ] ||
+ date.getUTCMinutes() !== +m[ 5 ] ||
+ date.getUTCSeconds() !== +m[ 6 ] ||
+ date.getUTCMilliseconds() !== +m[ 7 ]
+ ) {
+ date = null;
+ }
+ } else {
+ date = null;
+ }
+
+ return date;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.cleanUpValue = function ( value ) {
+ var date, pad;
+
+ if ( value === '' ) {
+ return '';
+ }
+
+ if ( value instanceof Date ) {
+ date = value;
+ } else {
+ date = this.parseDateValue( value );
+ }
+
+ if ( date instanceof Date ) {
+ pad = function ( v, l ) {
+ v = String( v );
+ while ( v.length < l ) {
+ v = '0' + v;
+ }
+ return v;
+ };
+
+ switch ( this.type ) {
+ case 'date':
+ value = pad( date.getUTCFullYear(), 4 ) +
+ '-' + pad( date.getUTCMonth() + 1, 2 ) +
+ '-' + pad( date.getUTCDate(), 2 );
+ break;
+
+ case 'time':
+ value = pad( date.getUTCHours(), 2 ) +
+ ':' + pad( date.getUTCMinutes(), 2 ) +
+ ':' + pad( date.getUTCSeconds(), 2 ) +
+ '.' + pad( date.getUTCMilliseconds(), 3 );
+ value = value.replace( /\.?0+$/, '' );
+ break;
+
+ default:
+ value = date.toISOString();
+ break;
+ }
+ } else {
+ value = '';
+ }
+
+ return value;
+ };
+
+ /**
+ * Get the value of the input as a Date object
+ *
+ * @return {Date|null}
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.getValueAsDate = function () {
+ return this.parseDateValue( this.getValue() );
+ };
+
+ /**
+ * Set up the UI fields
+ *
+ * @private
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.setupFields = function () {
+ var i, $field, spec, placeholder, sz, maxlength,
+ spanValFunc = function ( v ) {
+ if ( v === undefined ) {
+ return this.data( 'mw-widgets-datetime-dateTimeInputWidget-value' );
+ } else {
+ v = String( v );
+ this.data( 'mw-widgets-datetime-dateTimeInputWidget-value', v );
+ if ( v === '' ) {
+ v = this.data( 'mw-widgets-datetime-dateTimeInputWidget-placeholder' );
+ }
+ this.text( v );
+ return this;
+ }
+ },
+ reduceFunc = function ( k, v ) {
+ maxlength = Math.max( maxlength, v );
+ },
+ disabled = this.isDisabled(),
+ specs = this.formatter.getFieldSpec();
+
+ this.$fields.empty();
+ this.clearButton = null;
+ this.fields = [];
+
+ for ( i = 0; i < specs.length; i++ ) {
+ spec = specs[ i ];
+ if ( typeof spec === 'string' ) {
+ $( '<span>' )
+ .addClass( 'mw-widgets-datetime-dateTimeInputWidget-field' )
+ .text( spec )
+ .appendTo( this.$fields );
+ continue;
+ }
+
+ placeholder = '';
+ while ( placeholder.length < spec.size ) {
+ placeholder += '_';
+ }
+
+ if ( spec.type === 'number' ) {
+ // Numbers ''should'' be the same width. But we need some extra for
+ // IE, apparently.
+ sz = ( spec.size * 1.15 ) + 'ch';
+ } else {
+ // Add a little for padding
+ sz = ( spec.size * 1.15 ) + 'ch';
+ }
+ if ( spec.editable && spec.type !== 'static' ) {
+ if ( spec.type === 'boolean' || spec.type === 'toggleLocal' ) {
+ $field = $( '<span>' )
+ .attr( {
+ tabindex: disabled ? -1 : 0
+ } )
+ .width( sz )
+ .data( 'mw-widgets-datetime-dateTimeInputWidget-placeholder', placeholder );
+ $field.on( {
+ keydown: this.onFieldKeyDown.bind( this, $field ),
+ focus: this.onFieldFocus.bind( this, $field ),
+ click: this.onFieldClick.bind( this, $field ),
+ 'wheel mousewheel DOMMouseScroll': this.onFieldWheel.bind( this, $field )
+ } );
+ $field.val = spanValFunc;
+ } else {
+ maxlength = spec.size;
+ if ( spec.intercalarySize ) {
+ $.each( spec.intercalarySize, reduceFunc );
+ }
+ $field = $( '<input>' ).attr( 'type', 'text' )
+ .attr( {
+ tabindex: disabled ? -1 : 0,
+ size: spec.size,
+ maxlength: maxlength
+ } )
+ .prop( {
+ disabled: disabled,
+ placeholder: placeholder
+ } )
+ .width( sz );
+ $field.on( {
+ keydown: this.onFieldKeyDown.bind( this, $field ),
+ click: this.onFieldClick.bind( this, $field ),
+ focus: this.onFieldFocus.bind( this, $field ),
+ blur: this.onFieldBlur.bind( this, $field ),
+ change: this.onFieldChange.bind( this, $field ),
+ 'wheel mousewheel DOMMouseScroll': this.onFieldWheel.bind( this, $field )
+ } );
+ }
+ $field.addClass( 'mw-widgets-datetime-dateTimeInputWidget-editField' );
+ } else {
+ $field = $( '<span>' )
+ .width( sz )
+ .data( 'mw-widgets-datetime-dateTimeInputWidget-placeholder', placeholder );
+ if ( spec.type !== 'static' ) {
+ $field.prop( 'tabIndex', -1 );
+ $field.on( 'focus', this.onFieldFocus.bind( this, $field ) );
+ }
+ if ( spec.type === 'static' ) {
+ $field.text( spec.value );
+ } else {
+ $field.val = spanValFunc;
+ }
+ }
+
+ this.fields.push( $field );
+ $field
+ .addClass( 'mw-widgets-datetime-dateTimeInputWidget-field' )
+ .data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec', spec )
+ .appendTo( this.$fields );
+ }
+
+ if ( this.clearable ) {
+ this.clearButton = new OO.ui.ButtonWidget( {
+ classes: [ 'mw-widgets-datetime-dateTimeInputWidget-field', 'mw-widgets-datetime-dateTimeInputWidget-clearButton' ],
+ framed: false,
+ icon: 'trash',
+ disabled: disabled
+ } ).connect( this, {
+ click: 'onClearClick'
+ } );
+ this.$fields.append( this.clearButton.$element );
+ }
+
+ this.updateFieldsFromValue();
+ };
+
+ /**
+ * Update the UI fields from the current value
+ *
+ * @private
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.updateFieldsFromValue = function () {
+ var i, $field, spec, intercalary, sz,
+ date = this.getValueAsDate();
+
+ if ( date === null ) {
+ this.components = null;
+
+ for ( i = 0; i < this.fields.length; i++ ) {
+ $field = this.fields[ i ];
+ spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
+
+ $field
+ .removeClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid oo-ui-element-hidden' )
+ .val( '' );
+
+ if ( spec.intercalarySize ) {
+ if ( spec.type === 'number' ) {
+ // Numbers ''should'' be the same width. But we need some extra for
+ // IE, apparently.
+ $field.width( ( spec.size * 1.15 ) + 'ch' );
+ } else {
+ // Add a little for padding
+ $field.width( ( spec.size * 1.15 ) + 'ch' );
+ }
+ }
+ }
+
+ this.setFlags( { invalid: this.required } );
+ } else {
+ this.components = this.formatter.getComponentsFromDate( date );
+ intercalary = this.components.intercalary;
+
+ for ( i = 0; i < this.fields.length; i++ ) {
+ $field = this.fields[ i ];
+ $field.removeClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid' );
+ spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
+ if ( spec.type !== 'static' ) {
+ $field.val( spec.formatValue( this.components[ spec.component ] ) );
+ }
+ if ( spec.intercalarySize ) {
+ if ( intercalary && spec.intercalarySize[ intercalary ] !== undefined ) {
+ sz = spec.intercalarySize[ intercalary ];
+ } else {
+ sz = spec.size;
+ }
+ $field.toggleClass( 'oo-ui-element-hidden', sz <= 0 );
+ if ( spec.type === 'number' ) {
+ // Numbers ''should'' be the same width. But we need some extra for
+ // IE, apparently.
+ this.fields[ i ].width( ( sz * 1.15 ) + 'ch' );
+ } else {
+ // Add a little for padding
+ this.fields[ i ].width( ( sz * 1.15 ) + 'ch' );
+ }
+ }
+ }
+
+ this.setFlags( { invalid: date < this.min || date > this.max } );
+ }
+
+ this.$element.toggleClass( 'mw-widgets-datetime-dateTimeInputWidget-empty', date === null );
+ };
+
+ /**
+ * Update the value with data from the UI fields
+ *
+ * @private
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.updateValueFromFields = function () {
+ var i, v, $field, spec, curDate, newDate,
+ components = {},
+ anyInvalid = false,
+ anyEmpty = false,
+ allEmpty = true;
+
+ for ( i = 0; i < this.fields.length; i++ ) {
+ $field = this.fields[ i ];
+ spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
+ if ( spec.editable ) {
+ $field.removeClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid' );
+ v = $field.val();
+ if ( v === '' ) {
+ $field.addClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid' );
+ anyEmpty = true;
+ } else {
+ allEmpty = false;
+ v = spec.parseValue( v );
+ if ( v === undefined ) {
+ $field.addClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid' );
+ anyInvalid = true;
+ } else {
+ components[ spec.component ] = v;
+ }
+ }
+ }
+ }
+
+ if ( allEmpty ) {
+ for ( i = 0; i < this.fields.length; i++ ) {
+ this.fields[ i ].removeClass( 'mw-widgets-datetime-dateTimeInputWidget-invalid' );
+ }
+ } else if ( anyEmpty ) {
+ anyInvalid = true;
+ }
+
+ if ( !anyInvalid ) {
+ curDate = this.getValueAsDate();
+ newDate = this.formatter.getDateFromComponents( components );
+ if ( !curDate || !newDate || curDate.getTime() !== newDate.getTime() ) {
+ this.setValue( newDate );
+ }
+ }
+ };
+
+ /**
+ * Handle change event
+ *
+ * @private
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.onChange = function () {
+ var date;
+
+ this.updateFieldsFromValue();
+
+ if ( this.calendar ) {
+ date = this.getValueAsDate();
+ this.calendar.setSelected( date );
+ if ( date ) {
+ this.calendar.setFocusedDate( date );
+ }
+ }
+ };
+
+ /**
+ * Handle clear button click event
+ *
+ * @private
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.onClearClick = function () {
+ this.blur();
+ this.setValue( '' );
+ };
+
+ /**
+ * Handle click on the widget background
+ *
+ * @private
+ * @param {jQuery.Event} e Click event
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.onHandleClick = function () {
+ this.focus();
+ };
+
+ /**
+ * Handle key down events on our field inputs.
+ *
+ * @private
+ * @param {jQuery} $field
+ * @param {jQuery.Event} e Key down event
+ * @return {boolean} False to cancel the default event
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldKeyDown = function ( $field, e ) {
+ var spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
+
+ if ( !this.isDisabled() ) {
+ switch ( e.which ) {
+ case OO.ui.Keys.ENTER:
+ case OO.ui.Keys.SPACE:
+ if ( spec.type === 'boolean' ) {
+ this.setValue(
+ this.formatter.adjustComponent( this.getValueAsDate(), spec.component, 1, 'wrap' )
+ );
+ return false;
+ } else if ( spec.type === 'toggleLocal' ) {
+ this.formatter.toggleLocal();
+ }
+ break;
+
+ case OO.ui.Keys.UP:
+ case OO.ui.Keys.DOWN:
+ if ( spec.type === 'toggleLocal' ) {
+ this.formatter.toggleLocal();
+ } else {
+ this.setValue(
+ this.formatter.adjustComponent( this.getValueAsDate(), spec.component,
+ e.keyCode === OO.ui.Keys.UP ? -1 : 1, 'wrap' )
+ );
+ }
+ if ( $field.is( ':input' ) ) {
+ $field.select();
+ }
+ return false;
+ }
+ }
+ };
+
+ /**
+ * Handle focus events on our field inputs.
+ *
+ * @private
+ * @param {jQuery} $field
+ * @param {jQuery.Event} e Focus event
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldFocus = function ( $field ) {
+ var spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
+
+ if ( !this.isDisabled() ) {
+ if ( this.getValueAsDate() === null ) {
+ this.setValue( this.formatter.getDefaultDate() );
+ }
+ if ( $field.is( ':input' ) ) {
+ $field.select();
+ }
+
+ if ( this.calendar ) {
+ this.calendar.toggle( !!spec.calendarComponent );
+ }
+ }
+ };
+
+ /**
+ * Handle click events on our field inputs.
+ *
+ * @private
+ * @param {jQuery} $field
+ * @param {jQuery.Event} e Click event
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldClick = function ( $field ) {
+ var spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
+
+ if ( !this.isDisabled() ) {
+ if ( spec.type === 'boolean' ) {
+ this.setValue(
+ this.formatter.adjustComponent( this.getValueAsDate(), spec.component, 1, 'wrap' )
+ );
+ } else if ( spec.type === 'toggleLocal' ) {
+ this.formatter.toggleLocal();
+ }
+ }
+ };
+
+ /**
+ * Handle blur events on our field inputs.
+ *
+ * @private
+ * @param {jQuery} $field
+ * @param {jQuery.Event} e Blur event
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldBlur = function ( $field ) {
+ var v, date,
+ spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
+
+ this.updateValueFromFields();
+
+ // Normalize
+ date = this.getValueAsDate();
+ if ( !date ) {
+ $field.val( '' );
+ } else {
+ v = spec.formatValue( this.formatter.getComponentsFromDate( date )[ spec.component ] );
+ if ( v !== $field.val() ) {
+ $field.val( v );
+ }
+ }
+ };
+
+ /**
+ * Handle change events on our field inputs.
+ *
+ * @private
+ * @param {jQuery} $field
+ * @param {jQuery.Event} e Change event
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldChange = function () {
+ this.updateValueFromFields();
+ };
+
+ /**
+ * Handle wheel events on our field inputs.
+ *
+ * @private
+ * @param {jQuery} $field
+ * @param {jQuery.Event} e Change event
+ * @return {boolean} False to cancel the default event
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.onFieldWheel = function ( $field, e ) {
+ var delta = 0,
+ spec = $field.data( 'mw-widgets-datetime-dateTimeInputWidget-fieldSpec' );
+
+ if ( this.isDisabled() || !this.getFocusedField().length ) {
+ return;
+ }
+
+ // Standard 'wheel' event
+ if ( e.originalEvent.deltaMode !== undefined ) {
+ this.sawWheelEvent = true;
+ }
+ if ( e.originalEvent.deltaY ) {
+ delta = -e.originalEvent.deltaY;
+ } else if ( e.originalEvent.deltaX ) {
+ delta = e.originalEvent.deltaX;
+ }
+
+ // Non-standard events
+ if ( !this.sawWheelEvent ) {
+ if ( e.originalEvent.wheelDeltaX ) {
+ delta = -e.originalEvent.wheelDeltaX;
+ } else if ( e.originalEvent.wheelDeltaY ) {
+ delta = e.originalEvent.wheelDeltaY;
+ } else if ( e.originalEvent.wheelDelta ) {
+ delta = e.originalEvent.wheelDelta;
+ } else if ( e.originalEvent.detail ) {
+ delta = -e.originalEvent.detail;
+ }
+ }
+
+ if ( delta && spec ) {
+ if ( spec.type === 'toggleLocal' ) {
+ this.formatter.toggleLocal();
+ } else {
+ this.setValue(
+ this.formatter.adjustComponent( this.getValueAsDate(), spec.component, delta < 0 ? -1 : 1, 'wrap' )
+ );
+ }
+ return false;
+ }
+ };
+
+ /**
+ * Handle calendar change event
+ *
+ * @private
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.onCalendarChange = function () {
+ var curDate = this.getValueAsDate(),
+ newDate = this.calendar.getSelected()[ 0 ];
+
+ if ( newDate ) {
+ if ( !curDate || newDate.getTime() !== curDate.getTime() ) {
+ this.setValue( newDate );
+ }
+ }
+ };
+
+ /**
+ * @inheritdoc
+ * @private
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.getInputElement = function () {
+ return $( '<input>' ).attr( 'type', 'hidden' );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.setDisabled = function ( disabled ) {
+ mw.widgets.datetime.DateTimeInputWidget[ 'super' ].prototype.setDisabled.call( this, disabled );
+
+ // Flag all our fields as disabled
+ if ( this.$fields ) {
+ this.$fields.find( 'input' ).prop( 'disabled', this.isDisabled() );
+ this.$fields.find( '[tabindex]' ).attr( 'tabindex', this.isDisabled() ? -1 : 0 );
+ }
+
+ if ( this.clearButton ) {
+ this.clearButton.setDisabled( disabled );
+ }
+
+ return this;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.focus = function () {
+ if ( !this.getFocusedField().length ) {
+ this.$fields.find( '.mw-widgets-datetime-dateTimeInputWidget-editField' ).first().focus();
+ }
+ return this;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.blur = function () {
+ this.getFocusedField().blur();
+ return this;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.DateTimeInputWidget.prototype.simulateLabelClick = function () {
+ this.focus();
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.less b/www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.less
new file mode 100644
index 00000000..f205da3b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.less
@@ -0,0 +1,155 @@
+/* stylelint-disable no-duplicate-selectors */
+@import 'mediawiki.widgets.datetime.definitions';
+
+.mw-widgets-datetime-dateTimeInputWidget {
+ display: inline-block;
+ position: relative;
+ vertical-align: middle;
+
+ &-fields {
+ position: relative;
+ display: table;
+ z-index: 2;
+ .oo-ui-unselectable();
+
+ > .mw-widgets-datetime-dateTimeInputWidget-field {
+ .oo-ui-box-sizing(border-box);
+
+ display: table-cell;
+ white-space: pre;
+ }
+ }
+
+ &-handle {
+ width: 100%;
+ display: inline-block;
+ overflow: hidden;
+
+ // Needed for proper behavior with overflow: hidden.
+ vertical-align: bottom;
+
+ .oo-ui-unselectable();
+ .oo-ui-box-sizing(border-box);
+
+ > .oo-ui-indicatorElement-indicator,
+ > .oo-ui-iconElement-icon {
+ position: absolute;
+ background-position: center center;
+ background-repeat: no-repeat;
+ z-index: 1;
+ }
+ }
+
+ margin: 0.25em 0;
+ width: 100%;
+ max-width: 50em;
+
+ .oo-ui-inline-spacing(0.5em);
+
+ &-handle {
+ height: 2.5em;
+ border: 1px solid #ccc;
+ padding: 0 1em;
+ margin: 0;
+ background-color: #fff;
+ color: #000;
+ box-shadow: inset 0 0 0 0 @progressive;
+ border-radius: 0.1em;
+ .oo-ui-transition(box-shadow @quick-ease);
+ .oo-ui-box-sizing(border-box);
+
+ > .oo-ui-indicatorElement-indicator {
+ right: 0;
+ }
+
+ > .oo-ui-iconElement-icon {
+ left: 0.25em;
+ }
+
+ > .oo-ui-indicatorElement-indicator {
+ top: 0;
+ width: @indicator-size;
+ height: @indicator-size;
+ margin: 0.775em;
+ }
+
+ > .oo-ui-iconElement-icon {
+ top: 0;
+ width: @icon-size;
+ height: @icon-size;
+ margin: 0.3em;
+ }
+ }
+
+ &-empty &-handle {
+ color: #777;
+ }
+
+ &-field {
+ padding: 0;
+ margin: 0;
+ font-size: inherit;
+ font-family: inherit;
+ background-color: transparent;
+ color: inherit;
+ border: 0;
+ box-shadow: none;
+ text-align: center;
+ vertical-align: middle;
+ .oo-ui-box-sizing(border-box);
+ }
+
+ &.oo-ui-widget-disabled {
+ .mw-widgets-datetime-dateTimeInputWidget-handle {
+ color: #ccc;
+ text-shadow: 0 1px 1px #fff;
+ border-color: #ddd;
+ background-color: #f3f3f3;
+
+ > .oo-ui-iconElement-icon,
+ > .oo-ui-indicatorElement-indicator {
+ opacity: 0.2;
+ }
+ }
+ }
+
+ &.oo-ui-widget-enabled {
+ .mw-widgets-datetime-dateTimeInputWidget-editField:hover {
+ background-color: #eee;
+ }
+
+ &.oo-ui-flaggedElement-invalid {
+ .mw-widgets-datetime-dateTimeInputWidget-handle {
+ border-color: #f00;
+ box-shadow: inset 0 0 0 0 #f00;
+ }
+
+ .mw-widgets-datetime-dateTimeInputWidget-handle:focus {
+ border-color: #f00;
+ box-shadow: inset 0 0 0 0.1em #f00;
+ }
+ }
+ }
+
+ input.mw-widgets-datetime-dateTimeInputWidget-field {
+ padding: 0.5em 0;
+ }
+
+ &-editField.mw-widgets-datetime-dateTimeInputWidget-invalid {
+ border: 1px solid #f00;
+ box-shadow: inset 0 0 0 0 #f00;
+
+ &:focus {
+ border: 1px solid #f00;
+ box-shadow: inset 0 0 0 0.1em #f00;
+ }
+ }
+
+ &.oo-ui-iconElement .mw-widgets-datetime-dateTimeInputWidget-handle {
+ padding-left: 3em;
+ }
+
+ &.oo-ui-indicatorElement .mw-widgets-datetime-dateTimeInputWidget-handle {
+ padding-right: 2em;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets.datetime/DiscordianDateTimeFormatter.js b/www/wiki/resources/src/mediawiki.widgets.datetime/DiscordianDateTimeFormatter.js
new file mode 100644
index 00000000..6db2d062
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets.datetime/DiscordianDateTimeFormatter.js
@@ -0,0 +1,569 @@
+( function ( $, mw ) {
+
+ /**
+ * Provides various methods needed for formatting dates and times. This
+ * implementation implments the [Discordian calendar][1], mainly for testing with
+ * something very different from the usual Gregorian calendar.
+ *
+ * Being intended mainly for testing, niceties like i18n and better
+ * configurability have been omitted.
+ *
+ * [1]: https://en.wikipedia.org/wiki/Discordian_calendar
+ *
+ * @class
+ * @extends mw.widgets.datetime.DateTimeFormatter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+ mw.widgets.datetime.DiscordianDateTimeFormatter = function MwWidgetsDatetimeDiscordianDateTimeFormatter( config ) {
+ config = $.extend( {}, config );
+
+ // Parent constructor
+ mw.widgets.datetime.DiscordianDateTimeFormatter[ 'super' ].call( this, config );
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.datetime.DiscordianDateTimeFormatter, mw.widgets.datetime.DateTimeFormatter );
+
+ /* Static */
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.DiscordianDateTimeFormatter.static.formats = {
+ '@time': '${hour|0}:${minute|0}:${second|0}',
+ '@date': '$!{dow|full}${not-intercalary|1|, }${season|full}${not-intercalary|1| }${day|#}, ${year|#}',
+ '@datetime': '$!{dow|full}${not-intercalary|1|, }${season|full}${not-intercalary|1| }${day|#}, ${year|#} ${hour|0}:${minute|0}:${second|0} $!{zone|short}',
+ '@default': '$!{dow|full}${not-intercalary|1|, }${season|full}${not-intercalary|1| }${day|#}, ${year|#} ${hour|0}:${minute|0}:${second|0} $!{zone|short}'
+ };
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ *
+ * Additional fields implemented here are:
+ * - ${year|#}: Year as a number
+ * - ${season|#}: Season as a number
+ * - ${season|full}: Season as a string
+ * - ${day|#}: Day of the month as a number
+ * - ${day|0}: Day of the month as a number with leading 0
+ * - ${dow|full}: Day of the week as a string
+ * - ${hour|#}: Hour as a number
+ * - ${hour|0}: Hour as a number with leading 0
+ * - ${minute|#}: Minute as a number
+ * - ${minute|0}: Minute as a number with leading 0
+ * - ${second|#}: Second as a number
+ * - ${second|0}: Second as a number with leading 0
+ * - ${millisecond|#}: Millisecond as a number
+ * - ${millisecond|0}: Millisecond as a number, zero-padded to 3 digits
+ */
+ mw.widgets.datetime.DiscordianDateTimeFormatter.prototype.getFieldForTag = function ( tag, params ) {
+ var spec = null;
+
+ switch ( tag + '|' + params[ 0 ] ) {
+ case 'year|#':
+ spec = {
+ component: 'Year',
+ calendarComponent: true,
+ type: 'number',
+ size: 4,
+ zeropad: false
+ };
+ break;
+
+ case 'season|#':
+ spec = {
+ component: 'Season',
+ calendarComponent: true,
+ type: 'number',
+ size: 1,
+ intercalarySize: { 1: 0 },
+ zeropad: false
+ };
+ break;
+
+ case 'season|full':
+ spec = {
+ component: 'Season',
+ calendarComponent: true,
+ type: 'string',
+ intercalarySize: { 1: 0 },
+ values: {
+ 1: 'Chaos',
+ 2: 'Discord',
+ 3: 'Confusion',
+ 4: 'Bureaucracy',
+ 5: 'The Aftermath'
+ }
+ };
+ break;
+
+ case 'dow|full':
+ spec = {
+ component: 'DOW',
+ calendarComponent: true,
+ editable: false,
+ type: 'string',
+ intercalarySize: { 1: 0 },
+ values: {
+ '-1': 'N/A',
+ 0: 'Sweetmorn',
+ 1: 'Boomtime',
+ 2: 'Pungenday',
+ 3: 'Prickle-Prickle',
+ 4: 'Setting Orange'
+ }
+ };
+ break;
+
+ case 'day|#':
+ case 'day|0':
+ spec = {
+ component: 'Day',
+ calendarComponent: true,
+ type: 'string',
+ size: 2,
+ intercalarySize: { 1: 13 },
+ zeropad: params[ 0 ] === '0',
+ formatValue: function ( v ) {
+ if ( v === 'tib' ) {
+ return 'St. Tib\'s Day';
+ }
+ return mw.widgets.datetime.DateTimeFormatter.prototype.formatSpecValue.call( this, v );
+ },
+ parseValue: function ( v ) {
+ if ( /^\s*(st.?\s*)?tib('?s)?(\s*day)?\s*$/i.test( v ) ) {
+ return 'tib';
+ }
+ return mw.widgets.datetime.DateTimeFormatter.prototype.parseSpecValue.call( this, v );
+ }
+ };
+ break;
+
+ case 'hour|#':
+ case 'hour|0':
+ case 'minute|#':
+ case 'minute|0':
+ case 'second|#':
+ case 'second|0':
+ spec = {
+ component: tag.charAt( 0 ).toUpperCase() + tag.slice( 1 ),
+ calendarComponent: false,
+ type: 'number',
+ size: 2,
+ zeropad: params[ 0 ] === '0'
+ };
+ break;
+
+ case 'millisecond|#':
+ case 'millisecond|0':
+ spec = {
+ component: 'Millisecond',
+ calendarComponent: false,
+ type: 'number',
+ size: 3,
+ zeropad: params[ 0 ] === '0'
+ };
+ break;
+
+ default:
+ return mw.widgets.datetime.DiscordianDateTimeFormatter[ 'super' ].prototype.getFieldForTag.call( this, tag, params );
+ }
+
+ if ( spec ) {
+ if ( spec.editable === undefined ) {
+ spec.editable = true;
+ }
+ if ( spec.component !== 'Day' ) {
+ spec.formatValue = this.formatSpecValue;
+ spec.parseValue = this.parseSpecValue;
+ }
+ if ( spec.values ) {
+ spec.size = Math.max.apply(
+ null, $.map( spec.values, function ( v ) { return v.length; } )
+ );
+ }
+ }
+
+ return spec;
+ };
+
+ /**
+ * Get components from a Date object
+ *
+ * Components are:
+ * - Year {number}
+ * - Season {number} 1-5
+ * - Day {number|string} 1-73 or 'tib'
+ * - DOW {number} 0-4, or -1 on St. Tib's Day
+ * - Hour {number} 0-23
+ * - Minute {number} 0-59
+ * - Second {number} 0-59
+ * - Millisecond {number} 0-999
+ * - intercalary {string} '1' on St. Tib's Day
+ *
+ * @param {Date|null} date
+ * @return {Object} Components
+ */
+ mw.widgets.datetime.DiscordianDateTimeFormatter.prototype.getComponentsFromDate = function ( date ) {
+ var ret, day, month,
+ monthDays = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 ];
+
+ if ( !( date instanceof Date ) ) {
+ date = this.defaultDate;
+ }
+
+ if ( this.local ) {
+ day = date.getDate();
+ month = date.getMonth();
+ ret = {
+ Year: date.getFullYear() + 1166,
+ Hour: date.getHours(),
+ Minute: date.getMinutes(),
+ Second: date.getSeconds(),
+ Millisecond: date.getMilliseconds(),
+ zone: date.getTimezoneOffset()
+ };
+ } else {
+ day = date.getUTCDate();
+ month = date.getUTCMonth();
+ ret = {
+ Year: date.getUTCFullYear() + 1166,
+ Hour: date.getUTCHours(),
+ Minute: date.getUTCMinutes(),
+ Second: date.getUTCSeconds(),
+ Millisecond: date.getUTCMilliseconds(),
+ zone: 0
+ };
+ }
+
+ if ( month === 1 && day === 29 ) {
+ ret.Season = 1;
+ ret.Day = 'tib';
+ ret.DOW = -1;
+ ret.intercalary = '1';
+ } else {
+ day = monthDays[ month ] + day - 1;
+ ret.Season = Math.floor( day / 73 ) + 1;
+ ret.Day = ( day % 73 ) + 1;
+ ret.DOW = day % 5;
+ ret.intercalary = '';
+ }
+
+ return ret;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.DiscordianDateTimeFormatter.prototype.adjustComponent = function ( date, component, delta, mode ) {
+ return this.getDateFromComponents(
+ this.adjustComponentInternal(
+ this.getComponentsFromDate( date ), component, delta, mode
+ )
+ );
+ };
+
+ /**
+ * Adjust the components directly
+ *
+ * @private
+ * @param {Object} components Modified in place
+ * @param {string} component
+ * @param {number} delta
+ * @param {string} mode
+ * @return {Object} components
+ */
+ mw.widgets.datetime.DiscordianDateTimeFormatter.prototype.adjustComponentInternal = function ( components, component, delta, mode ) {
+ var i, min, max, range, next, preTib, postTib, wasTib;
+
+ if ( delta === 0 ) {
+ return components;
+ }
+
+ switch ( component ) {
+ case 'Year':
+ min = 1166;
+ max = 11165;
+ next = null;
+ break;
+ case 'Season':
+ min = 1;
+ max = 5;
+ next = 'Year';
+ break;
+ case 'Week':
+ if ( components.Day === 'tib' ) {
+ components.Day = 59; // Could choose either one...
+ components.Season = 1;
+ }
+ min = 1;
+ max = 73;
+ next = 'Season';
+ break;
+ case 'Day':
+ min = 1;
+ max = 73;
+ next = 'Season';
+ break;
+ case 'Hour':
+ min = 0;
+ max = 23;
+ next = 'Day';
+ break;
+ case 'Minute':
+ min = 0;
+ max = 59;
+ next = 'Hour';
+ break;
+ case 'Second':
+ min = 0;
+ max = 59;
+ next = 'Minute';
+ break;
+ case 'Millisecond':
+ min = 0;
+ max = 999;
+ next = 'Second';
+ break;
+ default:
+ return components;
+ }
+
+ switch ( mode ) {
+ case 'overflow':
+ case 'clip':
+ case 'wrap':
+ }
+
+ if ( component === 'Day' ) {
+ i = Math.abs( delta );
+ delta = delta < 0 ? -1 : 1;
+ preTib = delta > 0 ? 59 : 60;
+ postTib = delta > 0 ? 60 : 59;
+ while ( i-- > 0 ) {
+ if ( components.Day === preTib && components.Season === 1 && this.isLeapYear( components.Year ) ) {
+ components.Day = 'tib';
+ } else if ( components.Day === 'tib' ) {
+ components.Day = postTib;
+ components.Season = 1;
+ } else {
+ components.Day += delta;
+ if ( components.Day < min ) {
+ switch ( mode ) {
+ case 'overflow':
+ components.Day = max;
+ this.adjustComponentInternal( components, 'Season', -1, mode );
+ break;
+ case 'wrap':
+ components.Day = max;
+ break;
+ case 'clip':
+ components.Day = min;
+ i = 0;
+ break;
+ }
+ }
+ if ( components.Day > max ) {
+ switch ( mode ) {
+ case 'overflow':
+ components.Day = min;
+ this.adjustComponentInternal( components, 'Season', 1, mode );
+ break;
+ case 'wrap':
+ components.Day = min;
+ break;
+ case 'clip':
+ components.Day = max;
+ i = 0;
+ break;
+ }
+ }
+ }
+ }
+ } else {
+ if ( component === 'Week' ) {
+ component = 'Day';
+ delta *= 5;
+ }
+ if ( components.Day === 'tib' ) {
+ // For sanity
+ components.Season = 1;
+ }
+ switch ( mode ) {
+ case 'overflow':
+ if ( components.Day === 'tib' && ( component === 'Season' || component === 'Year' ) ) {
+ components.Day = 59; // Could choose either one...
+ wasTib = true;
+ } else {
+ wasTib = false;
+ }
+ i = Math.abs( delta );
+ delta = delta < 0 ? -1 : 1;
+ while ( i-- > 0 ) {
+ components[ component ] += delta;
+ if ( components[ component ] < min ) {
+ components[ component ] = max;
+ components = this.adjustComponentInternal( components, next, -1, mode );
+ }
+ if ( components[ component ] > max ) {
+ components[ component ] = min;
+ components = this.adjustComponentInternal( components, next, 1, mode );
+ }
+ }
+ if ( wasTib && components.Season === 1 && this.isLeapYear( components.Year ) ) {
+ components.Day = 'tib';
+ }
+ break;
+ case 'wrap':
+ range = max - min + 1;
+ components[ component ] += delta;
+ while ( components[ component ] < min ) {
+ components[ component ] += range;
+ }
+ while ( components[ component ] > max ) {
+ components[ component ] -= range;
+ }
+ break;
+ case 'clip':
+ components[ component ] += delta;
+ if ( components[ component ] < min ) {
+ components[ component ] = min;
+ }
+ if ( components[ component ] > max ) {
+ components[ component ] = max;
+ }
+ break;
+ }
+ if ( components.Day === 'tib' &&
+ ( components.Season !== 1 || !this.isLeapYear( components.Year ) )
+ ) {
+ components.Day = 59; // Could choose either one...
+ }
+ }
+
+ return components;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.DiscordianDateTimeFormatter.prototype.getDateFromComponents = function ( components ) {
+ var month, day, days,
+ date = new Date(),
+ monthDays = [ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 ];
+
+ components = $.extend( {}, this.getComponentsFromDate( null ), components );
+ if ( components.Day === 'tib' ) {
+ month = 1;
+ day = 29;
+ } else {
+ days = components.Season * 73 + components.Day - 74;
+ month = 0;
+ while ( days >= monthDays[ month + 1 ] ) {
+ month++;
+ }
+ day = days - monthDays[ month ] + 1;
+ }
+
+ if ( components.zone ) {
+ // Can't just use the constructor because that's stupid about ancient years.
+ date.setFullYear( components.Year - 1166, month, day );
+ date.setHours( components.Hour, components.Minute, components.Second, components.Millisecond );
+ } else {
+ // Date.UTC() is stupid about ancient years too.
+ date.setUTCFullYear( components.Year - 1166, month, day );
+ date.setUTCHours( components.Hour, components.Minute, components.Second, components.Millisecond );
+ }
+
+ return date;
+ };
+
+ /**
+ * Get whether the year is a leap year
+ *
+ * @private
+ * @param {number} year
+ * @return {boolean}
+ */
+ mw.widgets.datetime.DiscordianDateTimeFormatter.prototype.isLeapYear = function ( year ) {
+ year -= 1166;
+ if ( year % 4 ) {
+ return false;
+ } else if ( year % 100 ) {
+ return true;
+ }
+ return ( year % 400 ) === 0;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.DiscordianDateTimeFormatter.prototype.getCalendarHeadings = function () {
+ return [ 'SM', 'BT', 'PD', 'PP', null, 'SO' ];
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.DiscordianDateTimeFormatter.prototype.sameCalendarGrid = function ( date1, date2 ) {
+ var components1 = this.getComponentsFromDate( date1 ),
+ components2 = this.getComponentsFromDate( date2 );
+
+ return components1.Year === components2.Year && components1.Season === components2.Season;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.DiscordianDateTimeFormatter.prototype.getCalendarData = function ( date ) {
+ var dt, components, season, i, row,
+ ret = {
+ dayComponent: 'Day',
+ weekComponent: 'Week',
+ monthComponent: 'Season'
+ },
+ seasons = [ 'Chaos', 'Discord', 'Confusion', 'Bureaucracy', 'The Aftermath' ],
+ seasonStart = [ 0, -3, -1, -4, -2 ];
+
+ if ( !( date instanceof Date ) ) {
+ date = this.defaultDate;
+ }
+
+ components = this.getComponentsFromDate( date );
+ components.Day = 1;
+ season = components.Season;
+
+ ret.header = seasons[ season - 1 ] + ' ' + components.Year;
+
+ if ( seasonStart[ season - 1 ] ) {
+ this.adjustComponentInternal( components, 'Day', seasonStart[ season - 1 ], 'overflow' );
+ }
+
+ ret.rows = [];
+ do {
+ row = [];
+ for ( i = 0; i < 6; i++ ) {
+ dt = this.getDateFromComponents( components );
+ row[ i ] = {
+ display: components.Day === 'tib' ? 'Tib' : String( components.Day ),
+ date: dt,
+ extra: components.Season < season ? 'prev' : components.Season > season ? 'next' : null
+ };
+
+ this.adjustComponentInternal( components, 'Day', 1, 'overflow' );
+ if ( components.Day !== 'tib' && i === 3 ) {
+ row[ ++i ] = null;
+ }
+ }
+
+ ret.rows.push( row );
+ } while ( components.Season === season );
+
+ return ret;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets.datetime/ProlepticGregorianDateTimeFormatter.js b/www/wiki/resources/src/mediawiki.widgets.datetime/ProlepticGregorianDateTimeFormatter.js
new file mode 100644
index 00000000..0346cc1e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets.datetime/ProlepticGregorianDateTimeFormatter.js
@@ -0,0 +1,675 @@
+( function ( $, mw ) {
+
+ /**
+ * Provides various methods needed for formatting dates and times. This
+ * implementation implements the proleptic Gregorian calendar over years
+ * 0000–9999.
+ *
+ * @class
+ * @extends mw.widgets.datetime.DateTimeFormatter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} [fullMonthNames] Mapping 1–12 to full month names.
+ * @cfg {Object} [shortMonthNames] Mapping 1–12 to abbreviated month names.
+ * If {@link #fullMonthNames fullMonthNames} is given and this is not,
+ * defaults to the first three characters from that setting.
+ * @cfg {Object} [fullDayNames] Mapping 0–6 to full day of week names. 0 is Sunday, 6 is Saturday.
+ * @cfg {Object} [shortDayNames] Mapping 0–6 to abbreviated day of week names. 0 is Sunday, 6 is Saturday.
+ * If {@link #fullDayNames fullDayNames} is given and this is not, defaults to
+ * the first three characters from that setting.
+ * @cfg {string[]} [dayLetters] Weekday column headers for a calendar. Array of 7 strings.
+ * If {@link #fullDayNames fullDayNames} or {@link #shortDayNames shortDayNames}
+ * are given and this is not, defaults to the first character from
+ * shortDayNames.
+ * @cfg {string[]} [hour12Periods] AM and PM texts. Array of 2 strings, AM and PM.
+ * @cfg {number} [weekStartsOn=0] What day the week starts on: 0 is Sunday, 1 is Monday, 6 is Saturday.
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter = function MwWidgetsDatetimeProlepticGregorianDateTimeFormatter( config ) {
+ this.constructor.static.setupDefaults();
+
+ config = $.extend( {
+ weekStartsOn: 0,
+ hour12Periods: this.constructor.static.hour12Periods
+ }, config );
+
+ if ( config.fullMonthNames && !config.shortMonthNames ) {
+ config.shortMonthNames = {};
+ $.each( config.fullMonthNames, function ( k, v ) {
+ config.shortMonthNames[ k ] = v.substr( 0, 3 );
+ } );
+ }
+ if ( config.shortDayNames && !config.dayLetters ) {
+ config.dayLetters = [];
+ $.each( config.shortDayNames, function ( k, v ) {
+ config.dayLetters[ k ] = v.substr( 0, 1 );
+ } );
+ }
+ if ( config.fullDayNames && !config.dayLetters ) {
+ config.dayLetters = [];
+ $.each( config.fullDayNames, function ( k, v ) {
+ config.dayLetters[ k ] = v.substr( 0, 1 );
+ } );
+ }
+ if ( config.fullDayNames && !config.shortDayNames ) {
+ config.shortDayNames = {};
+ $.each( config.fullDayNames, function ( k, v ) {
+ config.shortDayNames[ k ] = v.substr( 0, 3 );
+ } );
+ }
+ config = $.extend( {
+ fullMonthNames: this.constructor.static.fullMonthNames,
+ shortMonthNames: this.constructor.static.shortMonthNames,
+ fullDayNames: this.constructor.static.fullDayNames,
+ shortDayNames: this.constructor.static.shortDayNames,
+ dayLetters: this.constructor.static.dayLetters
+ }, config );
+
+ // Parent constructor
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter[ 'super' ].call( this, config );
+
+ // Properties
+ this.weekStartsOn = config.weekStartsOn % 7;
+ this.fullMonthNames = config.fullMonthNames;
+ this.shortMonthNames = config.shortMonthNames;
+ this.fullDayNames = config.fullDayNames;
+ this.shortDayNames = config.shortDayNames;
+ this.dayLetters = config.dayLetters;
+ this.hour12Periods = config.hour12Periods;
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.datetime.ProlepticGregorianDateTimeFormatter, mw.widgets.datetime.DateTimeFormatter );
+
+ /* Static */
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.formats = {
+ '@time': '${hour|0}:${minute|0}:${second|0}',
+ '@date': '$!{dow|short} ${day|#} ${month|short} ${year|#}',
+ '@datetime': '$!{dow|short} ${day|#} ${month|short} ${year|#} ${hour|0}:${minute|0}:${second|0} $!{zone|short}',
+ '@default': '$!{dow|short} ${day|#} ${month|short} ${year|#} ${hour|0}:${minute|0}:${second|0} $!{zone|short}'
+ };
+
+ /**
+ * Default full month names.
+ *
+ * @static
+ * @inheritable
+ * @property {Object}
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.fullMonthNames = null;
+
+ /**
+ * Default abbreviated month names.
+ *
+ * @static
+ * @inheritable
+ * @property {Object}
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.shortMonthNames = null;
+
+ /**
+ * Default full day of week names.
+ *
+ * @static
+ * @inheritable
+ * @property {Object}
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.fullDayNames = null;
+
+ /**
+ * Default abbreviated day of week names.
+ *
+ * @static
+ * @inheritable
+ * @property {Object}
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.shortDayNames = null;
+
+ /**
+ * Default day letters.
+ *
+ * @static
+ * @inheritable
+ * @property {string[]}
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.dayLetters = null;
+
+ /**
+ * Default AM/PM indicators
+ *
+ * @static
+ * @inheritable
+ * @property {string[]}
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.hour12Periods = null;
+
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.static.setupDefaults = function () {
+ mw.widgets.datetime.DateTimeFormatter.static.setupDefaults.call( this );
+
+ if ( this.fullMonthNames && !this.shortMonthNames ) {
+ this.shortMonthNames = {};
+ $.each( this.fullMonthNames, function ( k, v ) {
+ this.shortMonthNames[ k ] = v.substr( 0, 3 );
+ }.bind( this ) );
+ }
+ if ( this.shortDayNames && !this.dayLetters ) {
+ this.dayLetters = [];
+ $.each( this.shortDayNames, function ( k, v ) {
+ this.dayLetters[ k ] = v.substr( 0, 1 );
+ }.bind( this ) );
+ }
+ if ( this.fullDayNames && !this.dayLetters ) {
+ this.dayLetters = [];
+ $.each( this.fullDayNames, function ( k, v ) {
+ this.dayLetters[ k ] = v.substr( 0, 1 );
+ }.bind( this ) );
+ }
+ if ( this.fullDayNames && !this.shortDayNames ) {
+ this.shortDayNames = {};
+ $.each( this.fullDayNames, function ( k, v ) {
+ this.shortDayNames[ k ] = v.substr( 0, 3 );
+ }.bind( this ) );
+ }
+
+ if ( !this.fullMonthNames ) {
+ this.fullMonthNames = {
+ 1: mw.msg( 'january' ),
+ 2: mw.msg( 'february' ),
+ 3: mw.msg( 'march' ),
+ 4: mw.msg( 'april' ),
+ 5: mw.msg( 'may_long' ),
+ 6: mw.msg( 'june' ),
+ 7: mw.msg( 'july' ),
+ 8: mw.msg( 'august' ),
+ 9: mw.msg( 'september' ),
+ 10: mw.msg( 'october' ),
+ 11: mw.msg( 'november' ),
+ 12: mw.msg( 'december' )
+ };
+ }
+ if ( !this.shortMonthNames ) {
+ this.shortMonthNames = {
+ 1: mw.msg( 'jan' ),
+ 2: mw.msg( 'feb' ),
+ 3: mw.msg( 'mar' ),
+ 4: mw.msg( 'apr' ),
+ 5: mw.msg( 'may' ),
+ 6: mw.msg( 'jun' ),
+ 7: mw.msg( 'jul' ),
+ 8: mw.msg( 'aug' ),
+ 9: mw.msg( 'sep' ),
+ 10: mw.msg( 'oct' ),
+ 11: mw.msg( 'nov' ),
+ 12: mw.msg( 'dec' )
+ };
+ }
+
+ if ( !this.fullDayNames ) {
+ this.fullDayNames = {
+ 0: mw.msg( 'sunday' ),
+ 1: mw.msg( 'monday' ),
+ 2: mw.msg( 'tuesday' ),
+ 3: mw.msg( 'wednesday' ),
+ 4: mw.msg( 'thursday' ),
+ 5: mw.msg( 'friday' ),
+ 6: mw.msg( 'saturday' )
+ };
+ }
+ if ( !this.shortDayNames ) {
+ this.shortDayNames = {
+ 0: mw.msg( 'sun' ),
+ 1: mw.msg( 'mon' ),
+ 2: mw.msg( 'tue' ),
+ 3: mw.msg( 'wed' ),
+ 4: mw.msg( 'thu' ),
+ 5: mw.msg( 'fri' ),
+ 6: mw.msg( 'sat' )
+ };
+ }
+ if ( !this.dayLetters ) {
+ this.dayLetters = [];
+ $.each( this.shortDayNames, function ( k, v ) {
+ this.dayLetters[ k ] = v.substr( 0, 1 );
+ }.bind( this ) );
+ }
+
+ if ( !this.hour12Periods ) {
+ this.hour12Periods = [
+ mw.msg( 'period-am' ),
+ mw.msg( 'period-pm' )
+ ];
+ }
+ };
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ *
+ * Additional fields implemented here are:
+ * - ${year|#}: Year as a number
+ * - ${year|0}: Year as a number, zero-padded to 4 digits
+ * - ${month|#}: Month as a number
+ * - ${month|0}: Month as a number with leading 0
+ * - ${month|short}: Month from 'shortMonthNames' configuration setting
+ * - ${month|full}: Month from 'fullMonthNames' configuration setting
+ * - ${day|#}: Day of the month as a number
+ * - ${day|0}: Day of the month as a number with leading 0
+ * - ${dow|short}: Day of the week from 'shortDayNames' configuration setting
+ * - ${dow|full}: Day of the week from 'fullDayNames' configuration setting
+ * - ${hour|#}: Hour as a number
+ * - ${hour|0}: Hour as a number with leading 0
+ * - ${hour|12}: Hour in a 12-hour clock as a number
+ * - ${hour|012}: Hour in a 12-hour clock as a number, with leading 0
+ * - ${hour|period}: Value from 'hour12Periods' configuration setting
+ * - ${minute|#}: Minute as a number
+ * - ${minute|0}: Minute as a number with leading 0
+ * - ${second|#}: Second as a number
+ * - ${second|0}: Second as a number with leading 0
+ * - ${millisecond|#}: Millisecond as a number
+ * - ${millisecond|0}: Millisecond as a number, zero-padded to 3 digits
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.prototype.getFieldForTag = function ( tag, params ) {
+ var spec = null;
+
+ switch ( tag + '|' + params[ 0 ] ) {
+ case 'year|#':
+ case 'year|0':
+ spec = {
+ component: 'year',
+ calendarComponent: true,
+ type: 'number',
+ size: 4,
+ zeropad: params[ 0 ] === '0'
+ };
+ break;
+
+ case 'month|short':
+ case 'month|full':
+ spec = {
+ component: 'month',
+ calendarComponent: true,
+ type: 'string',
+ values: params[ 0 ] === 'short' ? this.shortMonthNames : this.fullMonthNames
+ };
+ break;
+
+ case 'dow|short':
+ case 'dow|full':
+ spec = {
+ component: 'dow',
+ calendarComponent: true,
+ editable: false,
+ type: 'string',
+ values: params[ 0 ] === 'short' ? this.shortDayNames : this.fullDayNames
+ };
+ break;
+
+ case 'month|#':
+ case 'month|0':
+ case 'day|#':
+ case 'day|0':
+ spec = {
+ component: tag,
+ calendarComponent: true,
+ type: 'number',
+ size: 2,
+ zeropad: params[ 0 ] === '0'
+ };
+ break;
+
+ case 'hour|#':
+ case 'hour|0':
+ case 'minute|#':
+ case 'minute|0':
+ case 'second|#':
+ case 'second|0':
+ spec = {
+ component: tag,
+ calendarComponent: false,
+ type: 'number',
+ size: 2,
+ zeropad: params[ 0 ] === '0'
+ };
+ break;
+
+ case 'hour|12':
+ case 'hour|012':
+ spec = {
+ component: 'hour12',
+ calendarComponent: false,
+ type: 'number',
+ size: 2,
+ zeropad: params[ 0 ] === '012'
+ };
+ break;
+
+ case 'hour|period':
+ spec = {
+ component: 'hour12period',
+ calendarComponent: false,
+ type: 'boolean',
+ values: this.hour12Periods
+ };
+ break;
+
+ case 'millisecond|#':
+ case 'millisecond|0':
+ spec = {
+ component: 'millisecond',
+ calendarComponent: false,
+ type: 'number',
+ size: 3,
+ zeropad: params[ 0 ] === '0'
+ };
+ break;
+
+ default:
+ return mw.widgets.datetime.ProlepticGregorianDateTimeFormatter[ 'super' ].prototype.getFieldForTag.call( this, tag, params );
+ }
+
+ if ( spec ) {
+ if ( spec.editable === undefined ) {
+ spec.editable = true;
+ }
+ spec.formatValue = this.formatSpecValue;
+ spec.parseValue = this.parseSpecValue;
+ if ( spec.values ) {
+ spec.size = Math.max.apply(
+ null, $.map( spec.values, function ( v ) { return v.length; } )
+ );
+ }
+ }
+
+ return spec;
+ };
+
+ /**
+ * Get components from a Date object
+ *
+ * Components are:
+ * - year {number}
+ * - month {number} (1-12)
+ * - day {number} (1-31)
+ * - dow {number} (0-6, 0 is Sunday)
+ * - hour {number} (0-23)
+ * - hour12 {number} (1-12)
+ * - hour12period {boolean}
+ * - minute {number} (0-59)
+ * - second {number} (0-59)
+ * - millisecond {number} (0-999)
+ * - zone {number}
+ *
+ * @param {Date|null} date
+ * @return {Object} Components
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.prototype.getComponentsFromDate = function ( date ) {
+ var ret;
+
+ if ( !( date instanceof Date ) ) {
+ date = this.defaultDate;
+ }
+
+ if ( this.local ) {
+ ret = {
+ year: date.getFullYear(),
+ month: date.getMonth() + 1,
+ day: date.getDate(),
+ dow: date.getDay() % 7,
+ hour: date.getHours(),
+ minute: date.getMinutes(),
+ second: date.getSeconds(),
+ millisecond: date.getMilliseconds(),
+ zone: date.getTimezoneOffset()
+ };
+ } else {
+ ret = {
+ year: date.getUTCFullYear(),
+ month: date.getUTCMonth() + 1,
+ day: date.getUTCDate(),
+ dow: date.getUTCDay() % 7,
+ hour: date.getUTCHours(),
+ minute: date.getUTCMinutes(),
+ second: date.getUTCSeconds(),
+ millisecond: date.getUTCMilliseconds(),
+ zone: 0
+ };
+ }
+
+ ret.hour12period = ret.hour >= 12 ? 1 : 0;
+ ret.hour12 = ret.hour % 12;
+ if ( ret.hour12 === 0 ) {
+ ret.hour12 = 12;
+ }
+
+ return ret;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.prototype.getDateFromComponents = function ( components ) {
+ var date = new Date();
+
+ components = $.extend( {}, components );
+ if ( components.hour === undefined && components.hour12 !== undefined && components.hour12period !== undefined ) {
+ components.hour = ( components.hour12 % 12 ) + ( components.hour12period ? 12 : 0 );
+ }
+ components = $.extend( {}, this.getComponentsFromDate( null ), components );
+
+ if ( components.zone ) {
+ // Can't just use the constructor because that's stupid about ancient years.
+ date.setFullYear( components.year, components.month - 1, components.day );
+ date.setHours( components.hour, components.minute, components.second, components.millisecond );
+ } else {
+ // Date.UTC() is stupid about ancient years too.
+ date.setUTCFullYear( components.year, components.month - 1, components.day );
+ date.setUTCHours( components.hour, components.minute, components.second, components.millisecond );
+ }
+
+ return date;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.prototype.adjustComponent = function ( date, component, delta, mode ) {
+ var min, max, range, components;
+
+ if ( !( date instanceof Date ) ) {
+ date = this.defaultDate;
+ }
+ components = this.getComponentsFromDate( date );
+
+ switch ( component ) {
+ case 'year':
+ min = 0;
+ max = 9999;
+ break;
+ case 'month':
+ min = 1;
+ max = 12;
+ break;
+ case 'day':
+ min = 1;
+ max = this.getDaysInMonth( components.month, components.year );
+ break;
+ case 'hour':
+ min = 0;
+ max = 23;
+ break;
+ case 'minute':
+ case 'second':
+ min = 0;
+ max = 59;
+ break;
+ case 'millisecond':
+ min = 0;
+ max = 999;
+ break;
+ case 'hour12period':
+ component = 'hour';
+ min = 0;
+ max = 23;
+ delta *= 12;
+ break;
+ case 'hour12':
+ component = 'hour';
+ min = components.hour12period ? 12 : 0;
+ max = components.hour12period ? 23 : 11;
+ break;
+ default:
+ return new Date( date.getTime() );
+ }
+
+ components[ component ] += delta;
+ range = max - min + 1;
+ switch ( mode ) {
+ case 'overflow':
+ // Date() will mostly handle it automatically. But months need
+ // manual handling to prevent e.g. Jan 31 => Mar 3.
+ if ( component === 'month' || component === 'year' ) {
+ while ( components.month < 1 ) {
+ components[ component ] += 12;
+ components.year--;
+ }
+ while ( components.month > 12 ) {
+ components[ component ] -= 12;
+ components.year++;
+ }
+ }
+ break;
+ case 'wrap':
+ while ( components[ component ] < min ) {
+ components[ component ] += range;
+ }
+ while ( components[ component ] > max ) {
+ components[ component ] -= range;
+ }
+ break;
+ case 'clip':
+ if ( components[ component ] < min ) {
+ components[ component ] = min;
+ }
+ if ( components[ component ] < max ) {
+ components[ component ] = max;
+ }
+ break;
+ }
+ if ( component === 'month' || component === 'year' ) {
+ components.day = Math.min( components.day, this.getDaysInMonth( components.month, components.year ) );
+ }
+
+ return this.getDateFromComponents( components );
+ };
+
+ /**
+ * Get the number of days in a month
+ *
+ * @protected
+ * @param {number} month
+ * @param {number} year
+ * @return {number}
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.prototype.getDaysInMonth = function ( month, year ) {
+ switch ( month ) {
+ case 4:
+ case 6:
+ case 9:
+ case 11:
+ return 30;
+ case 2:
+ if ( year % 4 ) {
+ return 28;
+ } else if ( year % 100 ) {
+ return 29;
+ }
+ return ( year % 400 ) ? 28 : 29;
+ default:
+ return 31;
+ }
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.prototype.getCalendarHeadings = function () {
+ var a = this.dayLetters;
+
+ if ( this.weekStartsOn ) {
+ return a.slice( this.weekStartsOn ).concat( a.slice( 0, this.weekStartsOn ) );
+ } else {
+ return a.slice( 0 ); // clone
+ }
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.prototype.sameCalendarGrid = function ( date1, date2 ) {
+ if ( this.local ) {
+ return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth();
+ } else {
+ return date1.getUTCFullYear() === date2.getUTCFullYear() && date1.getUTCMonth() === date2.getUTCMonth();
+ }
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.datetime.ProlepticGregorianDateTimeFormatter.prototype.getCalendarData = function ( date ) {
+ var dt, t, d, e, i, row,
+ getDate = this.local ? 'getDate' : 'getUTCDate',
+ setDate = this.local ? 'setDate' : 'setUTCDate',
+ ret = {
+ dayComponent: 'day',
+ monthComponent: 'month'
+ };
+
+ if ( !( date instanceof Date ) ) {
+ date = this.defaultDate;
+ }
+
+ dt = new Date( date.getTime() );
+ dt[ setDate ]( 1 );
+ t = dt.getTime();
+
+ if ( this.local ) {
+ ret.header = this.fullMonthNames[ dt.getMonth() + 1 ] + ' ' + dt.getFullYear();
+ d = dt.getDay() % 7;
+ e = this.getDaysInMonth( dt.getMonth() + 1, dt.getFullYear() );
+ } else {
+ ret.header = this.fullMonthNames[ dt.getUTCMonth() + 1 ] + ' ' + dt.getUTCFullYear();
+ d = dt.getUTCDay() % 7;
+ e = this.getDaysInMonth( dt.getUTCMonth() + 1, dt.getUTCFullYear() );
+ }
+
+ if ( this.weekStartsOn ) {
+ d = ( d + 7 - this.weekStartsOn ) % 7;
+ }
+ d = 1 - d;
+
+ ret.rows = [];
+ while ( d <= e ) {
+ row = [];
+ for ( i = 0; i < 7; i++, d++ ) {
+ dt = new Date( t );
+ dt[ setDate ]( d );
+ row[ i ] = {
+ display: String( dt[ getDate ]() ),
+ date: dt,
+ extra: d < 1 ? 'prev' : d > e ? 'next' : null
+ };
+ }
+ ret.rows.push( row );
+ }
+
+ return ret;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.definitions.less b/www/wiki/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.definitions.less
new file mode 100644
index 00000000..fa45d5ac
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.definitions.less
@@ -0,0 +1,37 @@
+/*!
+ * OOJS-UI defines used by the existing CSS (will make it easier to put this
+ * widget in OOJS-UI once OOJS-UI is capable of handling it)
+ */
+
+.oo-ui-box-sizing( @type: border-box ) {
+ -webkit-box-sizing: @type;
+ -moz-box-sizing: @type;
+ box-sizing: @type;
+}
+
+.oo-ui-unselectable() {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.oo-ui-inline-spacing( @spacing, @cancelled-spacing: 0 ) {
+ margin-right: @spacing;
+ &:last-child {
+ margin-right: @cancelled-spacing;
+ }
+}
+
+.oo-ui-transition( @value1, @value2: X, ... ) {
+ @value: ~`'@{arguments}'.replace(/[\[\]]|\,\sX/g, '')`; // stylelint-disable-line function-comma-space-after, function-parentheses-space-inside, function-whitespace-after, value-keyword-case
+ -webkit-transition: @value;
+ -moz-transition: @value;
+ transition: @value;
+}
+
+@indicator-size: unit( 12 / 16 / 0.8, em );
+@icon-size: unit( 24 / 16 / 0.8, em );
+@quick-ease: 100ms ease;
+@progressive: #36c;
diff --git a/www/wiki/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.js b/www/wiki/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.js
new file mode 100644
index 00000000..8d4be8c5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets.datetime/mediawiki.widgets.datetime.js
@@ -0,0 +1,2 @@
+// Create the namespace object
+mediaWiki.widgets.datetime = {};
diff --git a/www/wiki/resources/src/mediawiki.widgets.visibleByteLimit/mediawiki.widgets.visibleByteLimit.js b/www/wiki/resources/src/mediawiki.widgets.visibleByteLimit/mediawiki.widgets.visibleByteLimit.js
new file mode 100644
index 00000000..5678a80e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets.visibleByteLimit/mediawiki.widgets.visibleByteLimit.js
@@ -0,0 +1,21 @@
+/**
+ * Add a visible byte limit label to a TextInputWidget
+ *
+ * Uses jQuery.byteLimit to enforce the limit.
+
+ * @param {OO.ui.TextInputWidget} textInputWidget Text input widget
+ * @param {number} [limit] Byte limit, defaults to $input's maxlength
+ */
+mediaWiki.widgets.visibleByteLimit = function ( textInputWidget, limit ) {
+ limit = limit || +textInputWidget.$input.attr( 'maxlength' );
+
+ function updateCount() {
+ textInputWidget.setLabel( ( limit - $.byteLength( textInputWidget.getValue() ) ).toString() );
+ }
+ textInputWidget.on( 'change', updateCount );
+ // Initialise value
+ updateCount();
+
+ // Actually enforce limit
+ textInputWidget.$input.byteLimit( limit );
+};
diff --git a/www/wiki/resources/src/mediawiki.widgets/AUTHORS.txt b/www/wiki/resources/src/mediawiki.widgets/AUTHORS.txt
new file mode 100644
index 00000000..f723a026
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/AUTHORS.txt
@@ -0,0 +1,10 @@
+Authors (alphabetically)
+
+Alex Monk <krenair@wikimedia.org>
+Bartosz Dziewoński <bdziewonski@wikimedia.org>
+Ed Sanders <esanders@wikimedia.org>
+James D. Forrester <jforrester@wikimedia.org>
+Roan Kattouw <roan@wikimedia.org>
+Sucheta Ghoshal <sghoshal@wikimedia.org>
+Timo Tijhof <krinklemail@gmail.com>
+Trevor Parscal <trevor@wikimedia.org>
diff --git a/www/wiki/resources/src/mediawiki.widgets/LICENSE.txt b/www/wiki/resources/src/mediawiki.widgets/LICENSE.txt
new file mode 100644
index 00000000..b03ca801
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/LICENSE.txt
@@ -0,0 +1,25 @@
+Copyright (c) 2011-2015 MediaWiki Widgets Team and others under the
+terms of The MIT License (MIT), as follows:
+
+This software consists of voluntary contributions made by many
+individuals (AUTHORS.txt) For exact contribution history, see the
+revision history and logs, available at https://gerrit.wikimedia.org
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/www/wiki/resources/src/mediawiki.widgets/MediaSearch/broken-image.png b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/broken-image.png
new file mode 100644
index 00000000..f5be9584
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/broken-image.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsProvider.js b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsProvider.js
new file mode 100644
index 00000000..dd07b928
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsProvider.js
@@ -0,0 +1,229 @@
+/*!
+ * MediaWiki Widgets - APIResultsProvider class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org
+ */
+( function ( $, mw ) {
+
+ /**
+ * API Results Provider object.
+ *
+ * @class
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {string} apiurl The URL to the api
+ * @param {Object} [config] Configuration options
+ * @cfg {number} fetchLimit The default number of results to fetch
+ * @cfg {string} lang The language of the API
+ * @cfg {number} offset Initial offset, if relevant, to call results from
+ * @cfg {Object} ajaxSettings The settings for the ajax call
+ * @cfg {Object} staticParams The data parameters that are static and should
+ * always be sent to the API request, as opposed to user parameters.
+ * @cfg {Object} userParams Initial user parameters to be sent as data to
+ * the API request. These can change per request, like the search query term
+ * or sizing parameters for images, etc.
+ */
+ mw.widgets.APIResultsProvider = function MwWidgetsAPIResultsProvider( apiurl, config ) {
+ config = config || {};
+
+ this.setAPIurl( apiurl );
+ this.setDefaultFetchLimit( config.fetchLimit || 30 );
+ this.setLang( config.lang );
+ this.setOffset( config.offset || 0 );
+ this.setAjaxSettings( config.ajaxSettings || {} );
+
+ this.staticParams = config.staticParams || {};
+ this.userParams = config.userParams || {};
+
+ this.toggleDepleted( false );
+
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+ };
+
+ /* Setup */
+ OO.mixinClass( mw.widgets.APIResultsProvider, OO.EventEmitter );
+
+ /* Methods */
+
+ /**
+ * Get results from the source
+ *
+ * @param {number} howMany Number of results to ask for
+ * @return {jQuery.Promise} Promise that is resolved into an array
+ * of available results, or is rejected if no results are available.
+ */
+ mw.widgets.APIResultsProvider.prototype.getResults = function () {
+ var xhr,
+ deferred = $.Deferred(),
+ allParams = $.extend( {}, this.getStaticParams(), this.getUserParams() );
+
+ xhr = $.getJSON( this.getAPIurl(), allParams )
+ .done( function ( data ) {
+ if (
+ $.type( data ) !== 'array' ||
+ (
+ $.type( data ) === 'array' &&
+ data.length === 0
+ )
+ ) {
+ deferred.resolve();
+ } else {
+ deferred.resolve( data );
+ }
+ } );
+ return deferred.promise( { abort: xhr.abort } );
+ };
+
+ /**
+ * Set API url
+ *
+ * @param {string} apiurl API url
+ */
+ mw.widgets.APIResultsProvider.prototype.setAPIurl = function ( apiurl ) {
+ this.apiurl = apiurl;
+ };
+
+ /**
+ * Set api url
+ *
+ * @return {string} API url
+ */
+ mw.widgets.APIResultsProvider.prototype.getAPIurl = function () {
+ return this.apiurl;
+ };
+
+ /**
+ * Get the static, non-changing data parameters sent to the API
+ *
+ * @return {Object} Data parameters
+ */
+ mw.widgets.APIResultsProvider.prototype.getStaticParams = function () {
+ return this.staticParams;
+ };
+
+ /**
+ * Get the user-inputted dynamic data parameters sent to the API
+ *
+ * @return {Object} Data parameters
+ */
+ mw.widgets.APIResultsProvider.prototype.getUserParams = function () {
+ return this.userParams;
+ };
+
+ /**
+ * Set the data parameters sent to the API
+ *
+ * @param {Object} params User defined data parameters
+ */
+ mw.widgets.APIResultsProvider.prototype.setUserParams = function ( params ) {
+ // Asymmetrically compare (params is subset of this.userParams)
+ if ( !OO.compare( params, this.userParams, true ) ) {
+ this.userParams = $.extend( {}, this.userParams, params );
+ this.reset();
+ }
+ };
+
+ /**
+ * Reset the provider
+ */
+ mw.widgets.APIResultsProvider.prototype.reset = function () {
+ // Reset offset
+ this.setOffset( 0 );
+ // Reset depleted status
+ this.toggleDepleted( false );
+ };
+
+ /**
+ * Get fetch limit or 'page' size. This is the number
+ * of results per request.
+ *
+ * @return {number} limit
+ */
+ mw.widgets.APIResultsProvider.prototype.getDefaultFetchLimit = function () {
+ return this.limit;
+ };
+
+ /**
+ * Set limit
+ *
+ * @param {number} limit Default number of results to fetch from the API
+ */
+ mw.widgets.APIResultsProvider.prototype.setDefaultFetchLimit = function ( limit ) {
+ this.limit = limit;
+ };
+
+ /**
+ * Get provider API language
+ *
+ * @return {string} Provider API language
+ */
+ mw.widgets.APIResultsProvider.prototype.getLang = function () {
+ return this.lang;
+ };
+
+ /**
+ * Set provider API language
+ *
+ * @param {string} lang Provider API language
+ */
+ mw.widgets.APIResultsProvider.prototype.setLang = function ( lang ) {
+ this.lang = lang;
+ };
+
+ /**
+ * Get result offset
+ *
+ * @return {number} Offset Results offset for the upcoming request
+ */
+ mw.widgets.APIResultsProvider.prototype.getOffset = function () {
+ return this.offset;
+ };
+
+ /**
+ * Set result offset
+ *
+ * @param {number} offset Results offset for the upcoming request
+ */
+ mw.widgets.APIResultsProvider.prototype.setOffset = function ( offset ) {
+ this.offset = offset;
+ };
+
+ /**
+ * Check whether the provider is depleted and has no more results
+ * to hand off.
+ *
+ * @return {boolean} The provider is depleted
+ */
+ mw.widgets.APIResultsProvider.prototype.isDepleted = function () {
+ return this.depleted;
+ };
+
+ /**
+ * Toggle depleted state
+ *
+ * @param {boolean} isDepleted The provider is depleted
+ */
+ mw.widgets.APIResultsProvider.prototype.toggleDepleted = function ( isDepleted ) {
+ this.depleted = isDepleted !== undefined ? isDepleted : !this.depleted;
+ };
+
+ /**
+ * Get the default ajax settings
+ *
+ * @return {Object} Ajax settings
+ */
+ mw.widgets.APIResultsProvider.prototype.getAjaxSettings = function () {
+ return this.ajaxSettings;
+ };
+
+ /**
+ * Get the default ajax settings
+ *
+ * @param {Object} settings Ajax settings
+ */
+ mw.widgets.APIResultsProvider.prototype.setAjaxSettings = function ( settings ) {
+ this.ajaxSettings = settings;
+ };
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsQueue.js b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsQueue.js
new file mode 100644
index 00000000..3bc1d51b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.APIResultsQueue.js
@@ -0,0 +1,224 @@
+/*!
+ * MediaWiki Widgets - APIResultsQueue class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see http://ve.mit-license.org
+ */
+( function ( $, mw ) {
+
+ /**
+ * API Results Queue object.
+ *
+ * @class
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} limit The default number of results to fetch
+ * @cfg {number} threshold The default number of extra results
+ * that the queue should always strive to have on top of the
+ * individual requests for items.
+ */
+ mw.widgets.APIResultsQueue = function MwWidgetsAPIResultsQueue( config ) {
+ config = config || {};
+
+ this.fileRepoPromise = null;
+ this.providers = [];
+ this.providerPromises = [];
+ this.queue = [];
+
+ this.params = {};
+
+ this.limit = config.limit || 20;
+ this.setThreshold( config.threshold || 10 );
+
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+ };
+
+ /* Setup */
+ OO.mixinClass( mw.widgets.APIResultsQueue, OO.EventEmitter );
+
+ /* Methods */
+
+ /**
+ * Set up the queue and its resources.
+ * This should be overridden if there are any setup steps to perform.
+ *
+ * @return {jQuery.Promise} Promise that resolves when the resources
+ * are set up. Note: The promise must have an .abort() functionality.
+ */
+ mw.widgets.APIResultsQueue.prototype.setup = function () {
+ return $.Deferred().resolve().promise( { abort: $.noop } );
+ };
+
+ /**
+ * Get items from the queue
+ *
+ * @param {number} [howMany] How many items to retrieve. Defaults to the
+ * default limit supplied on initialization.
+ * @return {jQuery.Promise} Promise that resolves into an array of items.
+ */
+ mw.widgets.APIResultsQueue.prototype.get = function ( howMany ) {
+ var fetchingPromise = null,
+ me = this;
+
+ howMany = howMany || this.limit;
+
+ // Check if the queue has enough items
+ if ( this.queue.length < howMany + this.threshold ) {
+ // Call for more results
+ fetchingPromise = this.queryProviders( howMany + this.threshold )
+ .then( function ( items ) {
+ // Add to the queue
+ me.queue = me.queue.concat.apply( me.queue, items );
+ } );
+ }
+
+ return $.when( fetchingPromise )
+ .then( function () {
+ return me.queue.splice( 0, howMany );
+ } );
+
+ };
+
+ /**
+ * Get results from all providers
+ *
+ * @param {number} [howMany] How many items to retrieve. Defaults to the
+ * default limit supplied on initialization.
+ * @return {jQuery.Promise} Promise that is resolved into an array
+ * of fetched items. Note: The promise must have an .abort() functionality.
+ */
+ mw.widgets.APIResultsQueue.prototype.queryProviders = function ( howMany ) {
+ var i, len,
+ queue = this;
+
+ // Make sure there are resources set up
+ return this.setup()
+ .then( function () {
+ // Abort previous requests
+ for ( i = 0, len = queue.providerPromises.length; i < len; i++ ) {
+ queue.providerPromises[ i ].abort();
+ }
+ queue.providerPromises = [];
+ // Set up the query to all providers
+ for ( i = 0, len = queue.providers.length; i < len; i++ ) {
+ if ( !queue.providers[ i ].isDepleted() ) {
+ queue.providerPromises.push(
+ queue.providers[ i ].getResults( howMany )
+ );
+ }
+ }
+
+ return $.when.apply( $, queue.providerPromises )
+ .then( Array.prototype.concat.bind( [] ) );
+ } );
+ };
+
+ /**
+ * Set the search query for all the providers.
+ *
+ * This also makes sure to abort any previous promises.
+ *
+ * @param {Object} params API search parameters
+ */
+ mw.widgets.APIResultsQueue.prototype.setParams = function ( params ) {
+ var i, len;
+ if ( !OO.compare( params, this.params, true ) ) {
+ this.reset();
+ this.params = $.extend( this.params, params );
+ // Reset queue
+ this.queue = [];
+ // Reset promises
+ for ( i = 0, len = this.providerPromises.length; i < len; i++ ) {
+ this.providerPromises[ i ].abort();
+ }
+ // Change queries
+ for ( i = 0, len = this.providers.length; i < len; i++ ) {
+ this.providers[ i ].setUserParams( this.params );
+ }
+ }
+ };
+
+ /**
+ * Reset the queue and all its providers
+ */
+ mw.widgets.APIResultsQueue.prototype.reset = function () {
+ var i, len;
+ // Reset queue
+ this.queue = [];
+ // Reset promises
+ for ( i = 0, len = this.providerPromises.length; i < len; i++ ) {
+ this.providerPromises[ i ].abort();
+ }
+ // Change queries
+ for ( i = 0, len = this.providers.length; i < len; i++ ) {
+ this.providers[ i ].reset();
+ }
+ };
+
+ /**
+ * Get the data parameters sent to the API
+ *
+ * @return {Object} params API search parameters
+ */
+ mw.widgets.APIResultsQueue.prototype.getParams = function () {
+ return this.params;
+ };
+
+ /**
+ * Set the providers
+ *
+ * @param {mw.widgets.APIResultsProvider[]} providers An array of providers
+ */
+ mw.widgets.APIResultsQueue.prototype.setProviders = function ( providers ) {
+ this.providers = providers;
+ };
+
+ /**
+ * Add a provider to the group
+ *
+ * @param {mw.widgets.APIResultsProvider} provider A provider object
+ */
+ mw.widgets.APIResultsQueue.prototype.addProvider = function ( provider ) {
+ this.providers.push( provider );
+ };
+
+ /**
+ * Set the providers
+ *
+ * @return {mw.widgets.APIResultsProvider[]} providers An array of providers
+ */
+ mw.widgets.APIResultsQueue.prototype.getProviders = function () {
+ return this.providers;
+ };
+
+ /**
+ * Get the queue size
+ *
+ * @return {number} Queue size
+ */
+ mw.widgets.APIResultsQueue.prototype.getQueueSize = function () {
+ return this.queue.length;
+ };
+
+ /**
+ * Set queue threshold
+ *
+ * @param {number} threshold Queue threshold, below which we will
+ * request more items
+ */
+ mw.widgets.APIResultsQueue.prototype.setThreshold = function ( threshold ) {
+ this.threshold = threshold;
+ };
+
+ /**
+ * Get queue threshold
+ *
+ * @return {number} threshold Queue threshold, below which we will
+ * request more items
+ */
+ mw.widgets.APIResultsQueue.prototype.getThreshold = function () {
+ return this.threshold;
+ };
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceProvider.js b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceProvider.js
new file mode 100644
index 00000000..d767109c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceProvider.js
@@ -0,0 +1,322 @@
+/*!
+ * MediaWiki Widgets - MediaResourceProvider class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * MediaWiki media resource provider.
+ *
+ * @class
+ * @extends mw.widgets.APIResultsProvider
+ *
+ * @constructor
+ * @param {string} apiurl The API url
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [scriptDirUrl] The url of the API script
+ */
+ mw.widgets.MediaResourceProvider = function MwWidgetsMediaResourceProvider( apiurl, config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.widgets.MediaResourceProvider.super.call( this, apiurl, config );
+
+ // Fetching configuration
+ this.scriptDirUrl = config.scriptDirUrl;
+ this.isLocal = config.local !== undefined;
+
+ if ( this.isLocal ) {
+ this.setAPIurl( mw.util.wikiScript( 'api' ) );
+ } else {
+ // If 'apiurl' is set, use that. Otherwise, build the url
+ // from scriptDirUrl and /api.php suffix
+ this.setAPIurl( this.getAPIurl() || ( this.scriptDirUrl + '/api.php' ) );
+ }
+
+ this.siteInfoPromise = null;
+ this.thumbSizes = [];
+ this.imageSizes = [];
+ };
+
+ /* Inheritance */
+ OO.inheritClass( mw.widgets.MediaResourceProvider, mw.widgets.APIResultsProvider );
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.MediaResourceProvider.prototype.getStaticParams = function () {
+ return $.extend(
+ {},
+ // Parent method
+ mw.widgets.MediaResourceProvider.super.prototype.getStaticParams.call( this ),
+ {
+ action: 'query',
+ iiprop: 'dimensions|url|mediatype|extmetadata|timestamp|user',
+ iiextmetadatalanguage: this.getLang(),
+ prop: 'imageinfo'
+ }
+ );
+ };
+
+ /**
+ * Initialize the source and get the site info.
+ *
+ * Connect to the api url and retrieve the siteinfo parameters
+ * that are required for fetching results.
+ *
+ * @return {jQuery.Promise} Promise that resolves when the class
+ * properties are set.
+ */
+ mw.widgets.MediaResourceProvider.prototype.loadSiteInfo = function () {
+ var provider = this;
+
+ if ( !this.siteInfoPromise ) {
+ this.siteInfoPromise = new mw.Api().get( {
+ action: 'query',
+ meta: 'siteinfo'
+ } )
+ .then( function ( data ) {
+ provider.setImageSizes( data.query.general.imagelimits || [] );
+ provider.setThumbSizes( data.query.general.thumblimits || [] );
+ provider.setUserParams( {
+ // Standard width per resource
+ iiurlwidth: provider.getStandardWidth()
+ } );
+ } );
+ }
+ return this.siteInfoPromise;
+ };
+
+ /**
+ * Override parent method and get results from the source
+ *
+ * @param {number} [howMany] The number of items to pull from the API
+ * @return {jQuery.Promise} Promise that is resolved into an array
+ * of available results, or is rejected if no results are available.
+ */
+ mw.widgets.MediaResourceProvider.prototype.getResults = function ( howMany ) {
+ var xhr,
+ aborted = false,
+ provider = this;
+
+ return this.loadSiteInfo()
+ .then( function () {
+ if ( aborted ) {
+ return $.Deferred().reject();
+ }
+ xhr = provider.fetchAPIresults( howMany );
+ return xhr;
+ } )
+ .then(
+ function ( results ) {
+ if ( !results || results.length === 0 ) {
+ provider.toggleDepleted( true );
+ return [];
+ }
+ return results;
+ },
+ // Process failed, return an empty promise
+ function () {
+ provider.toggleDepleted( true );
+ return $.Deferred().resolve( [] );
+ }
+ )
+ .promise( { abort: function () {
+ aborted = true;
+ if ( xhr ) {
+ xhr.abort();
+ }
+ } } );
+ };
+
+ /**
+ * Get continuation API data
+ *
+ * @param {number} howMany The number of results to retrieve
+ * @return {Object} API request data
+ */
+ mw.widgets.MediaResourceProvider.prototype.getContinueData = function () {
+ return {};
+ };
+
+ /**
+ * Set continuation data for the next page
+ *
+ * @param {Object} continueData Continuation data
+ */
+ mw.widgets.MediaResourceProvider.prototype.setContinue = function () {
+ };
+
+ /**
+ * Sort the results
+ *
+ * @param {Object[]} results API results
+ * @return {Object[]} Sorted results
+ */
+ mw.widgets.MediaResourceProvider.prototype.sort = function ( results ) {
+ return results;
+ };
+
+ /**
+ * Call the API for search results.
+ *
+ * @param {number} howMany The number of results to retrieve
+ * @return {jQuery.Promise} Promise that resolves with an array of objects that contain
+ * the fetched data.
+ */
+ mw.widgets.MediaResourceProvider.prototype.fetchAPIresults = function ( howMany ) {
+ var xhr, api,
+ provider = this;
+
+ if ( !this.isValid() ) {
+ return $.Deferred().reject().promise( { abort: $.noop } );
+ }
+
+ api = this.isLocal ? new mw.Api() : new mw.ForeignApi( this.getAPIurl(), { anonymous: true } );
+ xhr = api.get( $.extend( {}, this.getStaticParams(), this.getUserParams(), this.getContinueData( howMany ) ) );
+ return xhr
+ .then( function ( data ) {
+ var page, newObj, raw,
+ results = [];
+
+ if ( data.error ) {
+ provider.toggleDepleted( true );
+ return [];
+ }
+
+ if ( data.continue ) {
+ // Update the offset for next time
+ provider.setContinue( data.continue );
+ } else {
+ // This is the last available set of results. Mark as depleted!
+ provider.toggleDepleted( true );
+ }
+
+ // If the source returned no results, it will not have a
+ // query property
+ if ( data.query ) {
+ raw = data.query.pages;
+ if ( raw ) {
+ // Strip away the page ids
+ for ( page in raw ) {
+ if ( !raw[ page ].imageinfo ) {
+ // The search may give us pages that belong to the File:
+ // namespace but have no files in them, either because
+ // they were deleted or imported wrongly, or just started
+ // as pages. In that case, the response will not include
+ // imageinfo. Skip those files.
+ continue;
+ }
+ newObj = raw[ page ].imageinfo[ 0 ];
+ newObj.title = raw[ page ].title;
+ newObj.index = raw[ page ].index;
+ results.push( newObj );
+ }
+ }
+ }
+ return provider.sort( results );
+ } )
+ .promise( { abort: xhr.abort } );
+ };
+
+ /**
+ * Set name
+ *
+ * @param {string} name
+ */
+ mw.widgets.MediaResourceProvider.prototype.setName = function ( name ) {
+ this.name = name;
+ };
+
+ /**
+ * Get name
+ *
+ * @return {string} name
+ */
+ mw.widgets.MediaResourceProvider.prototype.getName = function () {
+ return this.name;
+ };
+
+ /**
+ * Get standard width, based on the provider source's thumb sizes.
+ *
+ * @return {number|undefined} fetchWidth
+ */
+ mw.widgets.MediaResourceProvider.prototype.getStandardWidth = function () {
+ return ( this.thumbSizes && this.thumbSizes[ this.thumbSizes.length - 1 ] ) ||
+ ( this.imageSizes && this.imageSizes[ 0 ] ) ||
+ // Fall back on a number
+ 300;
+ };
+
+ /**
+ * Get prop
+ *
+ * @return {string} prop
+ */
+ mw.widgets.MediaResourceProvider.prototype.getFetchProp = function () {
+ return this.fetchProp;
+ };
+
+ /**
+ * Set prop
+ *
+ * @param {string} prop
+ */
+ mw.widgets.MediaResourceProvider.prototype.setFetchProp = function ( prop ) {
+ this.fetchProp = prop;
+ };
+
+ /**
+ * Set thumb sizes
+ *
+ * @param {number[]} sizes Available thumbnail sizes
+ */
+ mw.widgets.MediaResourceProvider.prototype.setThumbSizes = function ( sizes ) {
+ this.thumbSizes = sizes;
+ };
+
+ /**
+ * Set image sizes
+ *
+ * @param {number[]} sizes Available image sizes
+ */
+ mw.widgets.MediaResourceProvider.prototype.setImageSizes = function ( sizes ) {
+ this.imageSizes = sizes;
+ };
+
+ /**
+ * Get thumb sizes
+ *
+ * @return {number[]} sizes Available thumbnail sizes
+ */
+ mw.widgets.MediaResourceProvider.prototype.getThumbSizes = function () {
+ return this.thumbSizes;
+ };
+
+ /**
+ * Get image sizes
+ *
+ * @return {number[]} sizes Available image sizes
+ */
+ mw.widgets.MediaResourceProvider.prototype.getImageSizes = function () {
+ return this.imageSizes;
+ };
+
+ /**
+ * Check if this source is valid.
+ *
+ * @return {boolean} Source is valid
+ */
+ mw.widgets.MediaResourceProvider.prototype.isValid = function () {
+ return this.isLocal ||
+ // If we don't have either 'apiurl' or 'scriptDirUrl'
+ // the source is invalid, and we will skip it
+ this.apiurl !== undefined ||
+ this.scriptDirUrl !== undefined;
+ };
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceQueue.js b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceQueue.js
new file mode 100644
index 00000000..34fa44b4
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResourceQueue.js
@@ -0,0 +1,68 @@
+/*!
+ * MediaWiki Widgets - MediaResourceQueue class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * MediaWiki media resource queue.
+ *
+ * @class
+ * @extends mw.widgets.APIResultsQueue
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} maxHeight The maximum height of the media, used in the
+ * search call to the API.
+ */
+ mw.widgets.MediaResourceQueue = function MwWidgetsMediaResourceQueue( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.widgets.MediaResourceQueue.super.call( this, config );
+
+ this.maxHeight = config.maxHeight || 200;
+ };
+
+ /* Inheritance */
+ OO.inheritClass( mw.widgets.MediaResourceQueue, mw.widgets.APIResultsQueue );
+
+ /**
+ * Fetch the file repos.
+ *
+ * @return {jQuery.Promise} Promise that resolves when the resources are set up
+ */
+ mw.widgets.MediaResourceQueue.prototype.getFileRepos = function () {
+ var defaultSource = [ {
+ url: mw.util.wikiScript( 'api' ),
+ local: ''
+ } ];
+
+ if ( !this.fileRepoPromise ) {
+ this.fileRepoPromise = new mw.Api().get( {
+ action: 'query',
+ meta: 'filerepoinfo'
+ } ).then(
+ function ( resp ) {
+ return resp.query && resp.query.repos || defaultSource;
+ },
+ function () {
+ return $.Deferred().resolve( defaultSource );
+ }
+ );
+ }
+
+ return this.fileRepoPromise;
+ };
+
+ /**
+ * Get image maximum height
+ *
+ * @return {string} Image max height
+ */
+ mw.widgets.MediaResourceQueue.prototype.getMaxHeight = function () {
+ return this.maxHeight;
+ };
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.css b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.css
new file mode 100644
index 00000000..e0c3d5e9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.css
@@ -0,0 +1,92 @@
+/*!
+ * MediaWiki Widgets - MediaResultWidget styles.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+.mw-widget-mediaResultWidget {
+ display: inline-block;
+ position: relative;
+ padding: 0;
+ margin: 2px;
+ overflow: hidden;
+ box-sizing: border-box;
+ text-align: center;
+}
+
+.mw-widget-mediaResultWidget-error {
+ background-color: #f8f9fa;
+}
+
+.mw-widget-mediaResultWidget-thumbnail {
+ opacity: 0;
+ display: inline-block;
+ -webkit-transition: opacity 400ms;
+ -moz-transition: opacity 400ms;
+ transition: opacity 400ms;
+}
+
+.mw-widget-mediaResultWidget-done .mw-widget-mediaResultWidget-thumbnail,
+.mw-widget-mediaResultWidget-error .mw-widget-mediaResultWidget-thumbnail {
+ opacity: 1;
+}
+
+.mw-widget-mediaResultWidget-crop {
+ background-size: cover;
+ background-position: center center;
+}
+
+.mw-widget-mediaResultWidget-overlay {
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ box-shadow: inset 0 0 0 1px #c8ccd1;
+}
+
+.mw-widget-mediaResultWidget.oo-ui-optionWidget-highlighted,
+.mw-widget-mediaResultWidget.oo-ui-optionWidget-selected {
+ box-shadow: 0 0 2px #36c;
+}
+
+.mw-widget-mediaResultWidget.oo-ui-optionWidget-highlighted .mw-widget-mediaResultWidget-overlay,
+.mw-widget-mediaResultWidget.oo-ui-optionWidget-selected .mw-widget-mediaResultWidget-overlay {
+ box-shadow: inset 0 0 0 1px #36c;
+}
+
+.mw-widget-mediaResultWidget-error .mw-widget-mediaResultWidget-thumbnail {
+ /* @embed */
+ background-image: url( broken-image.png );
+ background-size: auto;
+ background-position: center center;
+ background-repeat: no-repeat;
+}
+
+.mw-widget-mediaResultWidget .mw-widget-mediaResultWidget-nameLabel {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ overflow: hidden;
+ padding: 0.5em;
+ color: #fff;
+ text-shadow: 1px 1px #000;
+ line-height: 1.125em;
+ background-color: rgba( 0, 0, 0, 0.5 );
+ text-overflow: ellipsis;
+ text-align: left;
+}
+
+.mw-widget-mediaResultWidget.oo-ui-optionWidget-highlighted .mw-widget-mediaResultWidget-nameLabel {
+ background-color: rgba( 0, 0, 0, 0.75 );
+}
+
+.mw-widget-mediaResultWidget.oo-ui-optionWidget-selected .mw-widget-mediaResultWidget-nameLabel {
+ background-color: #000;
+}
+
+.mw-widget-mediaSearchWidget-noresults {
+ padding-top: 1em;
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.js b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.js
new file mode 100644
index 00000000..7607e842
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaResultWidget.js
@@ -0,0 +1,274 @@
+/*!
+ * MediaWiki Widgets - MediaResultWidget class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Creates an mw.widgets.MediaResultWidget object.
+ *
+ * @class
+ * @extends OO.ui.OptionWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [rowHeight] Height of the row this result is part of
+ * @cfg {number} [maxRowWidth] A limit for the width of the row this
+ * result is a part of.
+ * @cfg {number} [minWidth] Minimum width for the result
+ * @cfg {number} [maxWidth] Maximum width for the result
+ */
+ mw.widgets.MediaResultWidget = function MwWidgetsMediaResultWidget( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Parent constructor
+ mw.widgets.MediaResultWidget.super.call( this, config );
+
+ // Properties
+ this.setRowHeight( config.rowHeight || 150 );
+ this.maxRowWidth = config.maxRowWidth || 500;
+ this.minWidth = config.minWidth || this.maxRowWidth / 5;
+ this.maxWidth = config.maxWidth || this.maxRowWidth * 2 / 3;
+
+ this.imageDimensions = {};
+
+ this.isAudio = this.data.mediatype === 'AUDIO';
+
+ // Store the thumbnail url
+ this.thumbUrl = this.data.thumburl;
+ this.src = null;
+ this.row = null;
+
+ this.$thumb = $( '<img>' )
+ .addClass( 'mw-widget-mediaResultWidget-thumbnail' )
+ .on( {
+ load: this.onThumbnailLoad.bind( this ),
+ error: this.onThumbnailError.bind( this )
+ } );
+ this.$overlay = $( '<div>' )
+ .addClass( 'mw-widget-mediaResultWidget-overlay' );
+
+ this.calculateSizing( this.data );
+
+ // Get wiki default thumbnail size
+ this.defaultThumbSize = mw.config.get( 'wgVisualEditorConfig' )
+ .defaultUserOptions.defaultthumbsize;
+
+ // Initialization
+ this.setLabel( new mw.Title( this.data.title ).getNameText() );
+ this.$label.addClass( 'mw-widget-mediaResultWidget-nameLabel' );
+
+ this.$element
+ .addClass( 'mw-widget-mediaResultWidget ve-ui-texture-pending' )
+ .prepend( this.$thumb, this.$overlay );
+ };
+
+ /* Inheritance */
+
+ OO.inheritClass( mw.widgets.MediaResultWidget, OO.ui.OptionWidget );
+
+ /* Static methods */
+
+ // Copied from ve.dm.MWImageNode
+ mw.widgets.MediaResultWidget.static.resizeToBoundingBox = function ( imageDimensions, boundingBox ) {
+ var newDimensions = OO.copy( imageDimensions ),
+ scale = Math.min(
+ boundingBox.height / imageDimensions.height,
+ boundingBox.width / imageDimensions.width
+ );
+
+ if ( scale < 1 ) {
+ // Scale down
+ newDimensions = {
+ width: Math.floor( newDimensions.width * scale ),
+ height: Math.floor( newDimensions.height * scale )
+ };
+ }
+ return newDimensions;
+ };
+
+ /* Methods */
+ /** */
+ mw.widgets.MediaResultWidget.prototype.onThumbnailLoad = function () {
+ this.$thumb.first().addClass( 've-ui-texture-transparency' );
+ this.$element
+ .addClass( 'mw-widget-mediaResultWidget-done' )
+ .removeClass( 've-ui-texture-pending' );
+ };
+
+ /** */
+ mw.widgets.MediaResultWidget.prototype.onThumbnailError = function () {
+ this.$thumb.last()
+ .css( 'background-image', '' )
+ .addClass( 've-ui-texture-alert' );
+ this.$element
+ .addClass( 'mw-widget-mediaResultWidget-error' )
+ .removeClass( 've-ui-texture-pending' );
+ };
+
+ /**
+ * Resize the thumbnail and wrapper according to row height and bounding boxes, if given.
+ *
+ * @param {Object} originalDimensions Original image dimensions with width and height values
+ * @param {Object} [boundingBox] Specific bounding box, if supplied
+ */
+ mw.widgets.MediaResultWidget.prototype.calculateSizing = function ( originalDimensions, boundingBox ) {
+ var wrapperPadding,
+ imageDimensions = {};
+
+ boundingBox = boundingBox || {};
+
+ if ( this.isAudio ) {
+ // HACK: We are getting the wrong information from the
+ // API about audio files. Set their thumbnail to square 120px
+ imageDimensions = {
+ width: 120,
+ height: 120
+ };
+ } else {
+ // Get the image within the bounding box
+ imageDimensions = this.constructor.static.resizeToBoundingBox(
+ // Image original dimensions
+ {
+ width: originalDimensions.width || originalDimensions.thumbwidth,
+ height: originalDimensions.height || originalDimensions.thumbwidth
+ },
+ // Bounding box
+ {
+ width: boundingBox.width || this.getImageMaxWidth(),
+ height: boundingBox.height || this.getRowHeight()
+ }
+ );
+ }
+ this.imageDimensions = imageDimensions;
+ // Set the thumbnail size
+ this.$thumb.css( this.imageDimensions );
+
+ // Set the box size
+ wrapperPadding = this.calculateWrapperPadding( this.imageDimensions );
+ this.$element.css( wrapperPadding );
+ };
+
+ /**
+ * Replace the empty .src attribute of the image with the
+ * actual src.
+ */
+ mw.widgets.MediaResultWidget.prototype.lazyLoad = function () {
+ if ( !this.hasSrc() ) {
+ this.src = this.thumbUrl;
+ this.$thumb.attr( 'src', this.thumbUrl );
+ }
+ };
+
+ /**
+ * Retrieve the store dimensions object
+ *
+ * @return {Object} Thumb dimensions
+ */
+ mw.widgets.MediaResultWidget.prototype.getDimensions = function () {
+ return this.dimensions;
+ };
+
+ /**
+ * Resize thumbnail and element according to the resize factor
+ *
+ * @param {number} resizeFactor The resizing factor for the image
+ */
+ mw.widgets.MediaResultWidget.prototype.resizeThumb = function ( resizeFactor ) {
+ var boundingBox,
+ imageOriginalWidth = this.imageDimensions.width,
+ wrapperWidth = this.$element.width();
+ // Set the new row height
+ this.setRowHeight( Math.ceil( this.getRowHeight() * resizeFactor ) );
+
+ boundingBox = {
+ width: Math.ceil( this.imageDimensions.width * resizeFactor ),
+ height: this.getRowHeight()
+ };
+
+ this.calculateSizing( this.data, boundingBox );
+
+ // We need to adjust the wrapper this time to fit the "perfect"
+ // dimensions, regardless of how small the image is
+ if ( imageOriginalWidth < wrapperWidth ) {
+ boundingBox.width = wrapperWidth * resizeFactor;
+ }
+ this.$element.css( this.calculateWrapperPadding( boundingBox ) );
+ };
+
+ /**
+ * Adjust the wrapper padding for small images
+ *
+ * @param {Object} thumbDimensions Thumbnail dimensions
+ * @return {Object} Css styling for the wrapper
+ */
+ mw.widgets.MediaResultWidget.prototype.calculateWrapperPadding = function ( thumbDimensions ) {
+ var css = {
+ height: this.rowHeight,
+ width: thumbDimensions.width,
+ lineHeight: this.getRowHeight() + 'px'
+ };
+
+ // Check if the image is too thin so we can make a bit of space around it
+ if ( thumbDimensions.width < this.minWidth ) {
+ css.width = this.minWidth;
+ }
+
+ return css;
+ };
+
+ /**
+ * Set the row height for all size calculations
+ *
+ * @return {number} rowHeight Row height
+ */
+ mw.widgets.MediaResultWidget.prototype.getRowHeight = function () {
+ return this.rowHeight;
+ };
+
+ /**
+ * Set the row height for all size calculations
+ *
+ * @param {number} rowHeight Row height
+ */
+ mw.widgets.MediaResultWidget.prototype.setRowHeight = function ( rowHeight ) {
+ this.rowHeight = rowHeight;
+ };
+
+ mw.widgets.MediaResultWidget.prototype.setImageMaxWidth = function ( width ) {
+ this.maxWidth = width;
+ };
+ mw.widgets.MediaResultWidget.prototype.getImageMaxWidth = function () {
+ return this.maxWidth;
+ };
+
+ /**
+ * Set the row this result is in.
+ *
+ * @param {number} row Row number
+ */
+ mw.widgets.MediaResultWidget.prototype.setRow = function ( row ) {
+ this.row = row;
+ };
+
+ /**
+ * Get the row this result is in.
+ *
+ * @return {number} row Row number
+ */
+ mw.widgets.MediaResultWidget.prototype.getRow = function () {
+ return this.row;
+ };
+
+ /**
+ * Check if the image has a src attribute already
+ *
+ * @return {boolean} Thumbnail has its source attribute set
+ */
+ mw.widgets.MediaResultWidget.prototype.hasSrc = function () {
+ return !!this.src;
+ };
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchProvider.js b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchProvider.js
new file mode 100644
index 00000000..a46d9110
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchProvider.js
@@ -0,0 +1,69 @@
+/*!
+ * MediaWiki Widgets - MediaSearchProvider class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * MediaWiki media search provider.
+ *
+ * @class
+ * @extends mw.widgets.MediaResourceProvider
+ *
+ * @constructor
+ * @param {string} apiurl The API url
+ * @param {Object} [config] Configuration options
+ */
+ mw.widgets.MediaSearchProvider = function MwWidgetsMediaSearchProvider( apiurl, config ) {
+ config = config || {};
+
+ config.staticParams = $.extend( {
+ generator: 'search',
+ gsrnamespace: mw.config.get( 'wgNamespaceIds' ).file
+ }, config.staticParams );
+
+ // Parent constructor
+ mw.widgets.MediaSearchProvider.super.call( this, apiurl, config );
+ };
+
+ /* Inheritance */
+ OO.inheritClass( mw.widgets.MediaSearchProvider, mw.widgets.MediaResourceProvider );
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.MediaSearchProvider.prototype.getContinueData = function ( howMany ) {
+ return {
+ gsroffset: this.getOffset(),
+ gsrlimit: howMany || this.getDefaultFetchLimit()
+ };
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.MediaSearchProvider.prototype.setContinue = function ( continueData ) {
+ // Update the offset for next time
+ this.setOffset( continueData.gsroffset );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.MediaSearchProvider.prototype.sort = function ( results ) {
+ return results.sort( function ( a, b ) {
+ return a.index - b.index;
+ } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.MediaSearchProvider.prototype.isValid = function () {
+ return this.getUserParams().gsrsearch && mw.widgets.MediaSearchProvider.super.prototype.isValid.call( this );
+ };
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchQueue.js b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchQueue.js
new file mode 100644
index 00000000..7ee98bb6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchQueue.js
@@ -0,0 +1,82 @@
+/*!
+ * MediaWiki Widgets - MediaSearchQueue class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * MediaWiki media resource queue.
+ *
+ * @class
+ * @extends mw.widgets.MediaResourceQueue
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} maxHeight The maximum height of the media, used in the
+ * search call to the API.
+ */
+ mw.widgets.MediaSearchQueue = function MwWidgetsMediaSearchQueue( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.widgets.MediaSearchQueue.super.call( this, config );
+
+ this.searchQuery = '';
+ };
+
+ /* Inheritance */
+ OO.inheritClass( mw.widgets.MediaSearchQueue, mw.widgets.MediaResourceQueue );
+
+ /**
+ * Override parent method to set up the providers according to
+ * the file repos
+ *
+ * @return {jQuery.Promise} Promise that resolves when the resources are set up
+ */
+ mw.widgets.MediaSearchQueue.prototype.setup = function () {
+ var i, len,
+ queue = this;
+
+ return this.getFileRepos().then( function ( sources ) {
+ if ( queue.providers.length === 0 ) {
+ // Set up the providers
+ for ( i = 0, len = sources.length; i < len; i++ ) {
+ queue.providers.push( new mw.widgets.MediaSearchProvider(
+ sources[ i ].apiurl,
+ {
+ name: sources[ i ].name,
+ local: sources[ i ].local,
+ scriptDirUrl: sources[ i ].scriptDirUrl,
+ userParams: {
+ gsrsearch: queue.getSearchQuery()
+ },
+ staticParams: {
+ iiurlheight: queue.getMaxHeight()
+ }
+ } )
+ );
+ }
+ }
+ } );
+ };
+
+ /**
+ * Set the search query
+ *
+ * @param {string} searchQuery API search query
+ */
+ mw.widgets.MediaSearchQueue.prototype.setSearchQuery = function ( searchQuery ) {
+ this.setParams( { gsrsearch: searchQuery } );
+ };
+
+ /**
+ * Get the search query
+ *
+ * @return {string} API search query
+ */
+ mw.widgets.MediaSearchQueue.prototype.getSearchQuery = function () {
+ return this.getParams().gsrsearch;
+ };
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.css b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.css
new file mode 100644
index 00000000..3d28ef8f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.css
@@ -0,0 +1,10 @@
+/*!
+ * MediaWiki Widgets - MediaSearchWidget styles.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+.mw-widget-mediaSearchWidget .oo-ui-searchWidget-query .oo-ui-inputWidget {
+ max-width: none;
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.js b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.js
new file mode 100644
index 00000000..08266f09
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/MediaSearch/mw.widgets.MediaSearchWidget.js
@@ -0,0 +1,473 @@
+/*!
+ * MediaWiki Widgets - MediaSearchWidget class.
+ *
+ * @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Creates an mw.widgets.MediaSearchWidget object.
+ *
+ * @class
+ * @extends OO.ui.SearchWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @param {number} [size] Vertical size of thumbnails
+ */
+ mw.widgets.MediaSearchWidget = function MwWidgetsMediaSearchWidget( config ) {
+ // Configuration initialization
+ config = $.extend( {
+ placeholder: mw.msg( 'mw-widgets-mediasearch-input-placeholder' )
+ }, config );
+
+ // Parent constructor
+ mw.widgets.MediaSearchWidget.super.call( this, config );
+
+ // Properties
+ this.providers = {};
+ this.lastQueryValue = '';
+ this.searchQueue = new mw.widgets.MediaSearchQueue( {
+ limit: this.constructor.static.limit,
+ threshold: this.constructor.static.threshold
+ } );
+
+ this.queryTimeout = null;
+ this.itemCache = {};
+ this.promises = [];
+ this.lang = config.lang || 'en';
+ this.$panels = config.$panels;
+
+ this.externalLinkUrlProtocolsRegExp = new RegExp(
+ '^(' + mw.config.get( 'wgUrlProtocols' ) + ')',
+ 'i'
+ );
+
+ // Masonry fit properties
+ this.rows = [];
+ this.rowHeight = config.rowHeight || 200;
+ this.layoutQueue = [];
+ this.numItems = 0;
+ this.currentItemCache = [];
+
+ this.resultsSize = {};
+
+ this.selected = null;
+
+ this.noItemsMessage = new OO.ui.LabelWidget( {
+ label: mw.msg( 'mw-widgets-mediasearch-noresults' ),
+ classes: [ 'mw-widget-mediaSearchWidget-noresults' ]
+ } );
+ this.noItemsMessage.toggle( false );
+
+ // Events
+ this.$results.on( 'scroll', this.onResultsScroll.bind( this ) );
+ this.$query.append( this.noItemsMessage.$element );
+ this.results.connect( this, {
+ change: 'onResultsChange',
+ remove: 'onResultsRemove'
+ } );
+
+ this.resizeHandler = OO.ui.debounce( this.afterResultsResize.bind( this ), 500 );
+
+ // Initialization
+ this.$element.addClass( 'mw-widget-mediaSearchWidget' );
+ };
+
+ /* Inheritance */
+
+ OO.inheritClass( mw.widgets.MediaSearchWidget, OO.ui.SearchWidget );
+
+ /* Static properties */
+
+ mw.widgets.MediaSearchWidget.static.limit = 10;
+
+ mw.widgets.MediaSearchWidget.static.threshold = 5;
+
+ /* Methods */
+
+ /**
+ * Respond to window resize and check if the result display should
+ * be updated.
+ */
+ mw.widgets.MediaSearchWidget.prototype.afterResultsResize = function () {
+ var items = this.currentItemCache;
+
+ if (
+ items.length > 0 &&
+ (
+ this.resultsSize.width !== this.$results.width() ||
+ this.resultsSize.height !== this.$results.height()
+ )
+ ) {
+ this.resetRows();
+ this.itemCache = {};
+ this.processQueueResults( items );
+ if ( this.results.getItems().length > 0 ) {
+ this.lazyLoadResults();
+ }
+
+ // Cache the size
+ this.resultsSize = {
+ width: this.$results.width(),
+ height: this.$results.height()
+ };
+ }
+ };
+
+ /**
+ * Teardown the widget; disconnect the window resize event.
+ */
+ mw.widgets.MediaSearchWidget.prototype.teardown = function () {
+ $( window ).off( 'resize', this.resizeHandler );
+ };
+
+ /**
+ * Setup the widget; activate the resize event.
+ */
+ mw.widgets.MediaSearchWidget.prototype.setup = function () {
+ $( window ).on( 'resize', this.resizeHandler );
+ };
+
+ /**
+ * Query all sources for media.
+ *
+ * @method
+ */
+ mw.widgets.MediaSearchWidget.prototype.queryMediaQueue = function () {
+ var search = this,
+ value = this.getQueryValue();
+
+ if ( value === '' ) {
+ return;
+ }
+
+ this.query.pushPending();
+ search.noItemsMessage.toggle( false );
+
+ this.searchQueue.setSearchQuery( value );
+ this.searchQueue.get( this.constructor.static.limit )
+ .then( function ( items ) {
+ if ( items.length > 0 ) {
+ search.processQueueResults( items );
+ search.currentItemCache = search.currentItemCache.concat( items );
+ }
+
+ search.query.popPending();
+ search.noItemsMessage.toggle( search.results.getItems().length === 0 );
+ if ( search.results.getItems().length > 0 ) {
+ search.lazyLoadResults();
+ }
+
+ } );
+ };
+
+ /**
+ * Process the media queue giving more items
+ *
+ * @method
+ * @param {Object[]} items Given items by the media queue
+ */
+ mw.widgets.MediaSearchWidget.prototype.processQueueResults = function ( items ) {
+ var i, len, title,
+ resultWidgets = [],
+ inputSearchQuery = this.getQueryValue(),
+ queueSearchQuery = this.searchQueue.getSearchQuery();
+
+ if ( inputSearchQuery === '' || queueSearchQuery !== inputSearchQuery ) {
+ return;
+ }
+
+ for ( i = 0, len = items.length; i < len; i++ ) {
+ title = new mw.Title( items[ i ].title ).getMainText();
+ // Do not insert duplicates
+ if ( !Object.prototype.hasOwnProperty.call( this.itemCache, title ) ) {
+ this.itemCache[ title ] = true;
+ resultWidgets.push(
+ new mw.widgets.MediaResultWidget( {
+ data: items[ i ],
+ rowHeight: this.rowHeight,
+ maxWidth: this.results.$element.width() / 3,
+ minWidth: 30,
+ rowWidth: this.results.$element.width()
+ } )
+ );
+ }
+ }
+ this.results.addItems( resultWidgets );
+
+ };
+
+ /**
+ * Get the sanitized query value from the input
+ *
+ * @return {string} Query value
+ */
+ mw.widgets.MediaSearchWidget.prototype.getQueryValue = function () {
+ var queryValue = this.query.getValue().trim();
+
+ if ( queryValue.match( this.externalLinkUrlProtocolsRegExp ) ) {
+ queryValue = queryValue.match( /.+\/([^/]+)/ )[ 1 ];
+ }
+ return queryValue;
+ };
+
+ /**
+ * Handle search value change
+ *
+ * @param {string} value New value
+ */
+ mw.widgets.MediaSearchWidget.prototype.onQueryChange = function () {
+ // Get the sanitized query value
+ var queryValue = this.getQueryValue();
+
+ if ( queryValue === this.lastQueryValue ) {
+ return;
+ }
+
+ // Parent method
+ mw.widgets.MediaSearchWidget.super.prototype.onQueryChange.apply( this, arguments );
+
+ // Reset
+ this.itemCache = {};
+ this.currentItemCache = [];
+ this.resetRows();
+
+ // Empty the results queue
+ this.layoutQueue = [];
+
+ // Change resource queue query
+ this.searchQueue.setSearchQuery( queryValue );
+ this.lastQueryValue = queryValue;
+
+ // Queue
+ clearTimeout( this.queryTimeout );
+ this.queryTimeout = setTimeout( this.queryMediaQueue.bind( this ), 350 );
+ };
+
+ /**
+ * Handle results scroll events.
+ *
+ * @param {jQuery.Event} e Scroll event
+ */
+ mw.widgets.MediaSearchWidget.prototype.onResultsScroll = function () {
+ var position = this.$results.scrollTop() + this.$results.outerHeight(),
+ threshold = this.results.$element.outerHeight() - this.rowHeight * 3;
+
+ // Check if we need to ask for more results
+ if ( !this.query.isPending() && position > threshold ) {
+ this.queryMediaQueue();
+ }
+
+ this.lazyLoadResults();
+ };
+
+ /**
+ * Lazy-load the images that are visible.
+ */
+ mw.widgets.MediaSearchWidget.prototype.lazyLoadResults = function () {
+ var i, elementTop,
+ items = this.results.getItems(),
+ resultsScrollTop = this.$results.scrollTop(),
+ position = resultsScrollTop + this.$results.outerHeight();
+
+ // Lazy-load results
+ for ( i = 0; i < items.length; i++ ) {
+ elementTop = items[ i ].$element.position().top;
+ if ( elementTop <= position && !items[ i ].hasSrc() ) {
+ // Load the image
+ items[ i ].lazyLoad();
+ }
+ }
+ };
+
+ /**
+ * Reset all the rows; destroy the jQuery elements and reset
+ * the rows array.
+ */
+ mw.widgets.MediaSearchWidget.prototype.resetRows = function () {
+ var i, len;
+
+ for ( i = 0, len = this.rows.length; i < len; i++ ) {
+ this.rows[ i ].$element.remove();
+ }
+
+ this.rows = [];
+ this.itemCache = {};
+ };
+
+ /**
+ * Find an available row at the end. Either we will need to create a new
+ * row or use the last available row if it isn't full.
+ *
+ * @return {number} Row index
+ */
+ mw.widgets.MediaSearchWidget.prototype.getAvailableRow = function () {
+ var row;
+
+ if ( this.rows.length === 0 ) {
+ row = 0;
+ } else {
+ row = this.rows.length - 1;
+ }
+
+ if ( !this.rows[ row ] ) {
+ // Create new row
+ this.rows[ row ] = {
+ isFull: false,
+ width: 0,
+ items: [],
+ $element: $( '<div>' )
+ .addClass( 'mw-widget-mediaResultWidget-row' )
+ .css( {
+ overflow: 'hidden'
+ } )
+ .data( 'row', row )
+ .attr( 'data-full', false )
+ };
+ // Append to results
+ this.results.$element.append( this.rows[ row ].$element );
+ } else if ( this.rows[ row ].isFull ) {
+ row++;
+ // Create new row
+ this.rows[ row ] = {
+ isFull: false,
+ width: 0,
+ items: [],
+ $element: $( '<div>' )
+ .addClass( 'mw-widget-mediaResultWidget-row' )
+ .css( {
+ overflow: 'hidden'
+ } )
+ .data( 'row', row )
+ .attr( 'data-full', false )
+ };
+ // Append to results
+ this.results.$element.append( this.rows[ row ].$element );
+ }
+
+ return row;
+ };
+
+ /**
+ * Respond to change results event in the results widget.
+ * Override the way SelectWidget and GroupElement append the items
+ * into the group so we can append them in groups of rows.
+ *
+ * @param {mw.widgets.MediaResultWidget[]} items An array of item elements
+ */
+ mw.widgets.MediaSearchWidget.prototype.onResultsChange = function ( items ) {
+ var search = this;
+
+ if ( !items.length ) {
+ return;
+ }
+
+ // Add method to a queue; this queue will only run when the widget
+ // is visible
+ this.layoutQueue.push( function () {
+ var i, j, ilen, jlen, itemWidth, row, effectiveWidth,
+ resizeFactor,
+ maxRowWidth = search.results.$element.width() - 15;
+
+ // Go over the added items
+ row = search.getAvailableRow();
+ for ( i = 0, ilen = items.length; i < ilen; i++ ) {
+
+ // Check item has just been added
+ if ( items[ i ].row !== null ) {
+ continue;
+ }
+
+ itemWidth = items[ i ].$element.outerWidth( true );
+
+ // Add items to row until it is full
+ if ( search.rows[ row ].width + itemWidth >= maxRowWidth ) {
+ // Mark this row as full
+ search.rows[ row ].isFull = true;
+ search.rows[ row ].$element.attr( 'data-full', true );
+
+ // Find the resize factor
+ effectiveWidth = search.rows[ row ].width;
+ resizeFactor = maxRowWidth / effectiveWidth;
+
+ search.rows[ row ].$element.attr( 'data-effectiveWidth', effectiveWidth );
+ search.rows[ row ].$element.attr( 'data-resizeFactor', resizeFactor );
+ search.rows[ row ].$element.attr( 'data-row', row );
+
+ // Resize all images in the row to fit the width
+ for ( j = 0, jlen = search.rows[ row ].items.length; j < jlen; j++ ) {
+ search.rows[ row ].items[ j ].resizeThumb( resizeFactor );
+ }
+
+ // find another row
+ row = search.getAvailableRow();
+ }
+
+ // Add the cumulative
+ search.rows[ row ].width += itemWidth;
+
+ // Store reference to the item and to the row
+ search.rows[ row ].items.push( items[ i ] );
+ items[ i ].setRow( row );
+
+ // Append the item
+ search.rows[ row ].$element.append( items[ i ].$element );
+
+ }
+
+ // If we have less than 4 rows, call for more images
+ if ( search.rows.length < 4 ) {
+ search.queryMediaQueue();
+ }
+ } );
+ this.runLayoutQueue();
+ };
+
+ /**
+ * Run layout methods from the queue only if the element is visible.
+ */
+ mw.widgets.MediaSearchWidget.prototype.runLayoutQueue = function () {
+ var i, len;
+
+ if ( this.$element.is( ':visible' ) ) {
+ for ( i = 0, len = this.layoutQueue.length; i < len; i++ ) {
+ this.layoutQueue.pop()();
+ }
+ }
+ };
+
+ /**
+ * Respond to removing results event in the results widget.
+ * Clear the relevant rows.
+ *
+ * @param {OO.ui.OptionWidget[]} items Removed items
+ */
+ mw.widgets.MediaSearchWidget.prototype.onResultsRemove = function ( items ) {
+ if ( items.length > 0 ) {
+ // In the case of the media search widget, if any items are removed
+ // all are removed (new search)
+ this.resetRows();
+ this.currentItemCache = [];
+ }
+ };
+
+ /**
+ * Set language for the search results.
+ *
+ * @param {string} lang Language
+ */
+ mw.widgets.MediaSearchWidget.prototype.setLang = function ( lang ) {
+ this.lang = lang;
+ };
+
+ /**
+ * Get language for the search results.
+ *
+ * @return {string} lang Language
+ */
+ mw.widgets.MediaSearchWidget.prototype.getLang = function () {
+ return this.lang;
+ };
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.js
new file mode 100644
index 00000000..b91617e7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.js
@@ -0,0 +1,591 @@
+/*!
+ * MediaWiki Widgets – CalendarWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+/* global moment */
+( function ( $, mw ) {
+
+ /**
+ * Creates an mw.widgets.CalendarWidget object.
+ *
+ * You will most likely want to use mw.widgets.DateInputWidget instead of CalendarWidget directly.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ * @mixins OO.ui.mixin.TabIndexedElement
+ * @mixins OO.ui.mixin.FloatableElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [lazyInitOnToggle=false] Don't build most of the interface until
+ * `.toggle( true )` is called. Meant to be used when the calendar is not immediately visible.
+ * @cfg {string} [precision='day'] Date precision to use, 'day' or 'month'
+ * @cfg {string|null} [date=null] Day or month date (depending on `precision`), in the format
+ * 'YYYY-MM-DD' or 'YYYY-MM'. When null, the calendar will show today's date, but not select
+ * it.
+ */
+ mw.widgets.CalendarWidget = function MWWCalendarWidget( config ) {
+ // Config initialization
+ config = config || {};
+
+ // Parent constructor
+ mw.widgets.CalendarWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.TabIndexedElement.call( this, $.extend( {}, config, { $tabIndexed: this.$element } ) );
+ OO.ui.mixin.FloatableElement.call( this, config );
+
+ // Properties
+ this.lazyInitOnToggle = !!config.lazyInitOnToggle;
+ this.precision = config.precision || 'day';
+ // Currently selected date (day or month)
+ this.date = null;
+ // Current UI state (date and precision we're displaying right now)
+ this.moment = null;
+ this.displayLayer = this.getDisplayLayers()[ 0 ]; // 'month', 'year', 'duodecade'
+
+ this.$header = $( '<div>' ).addClass( 'mw-widget-calendarWidget-header' );
+ this.$bodyOuterWrapper = $( '<div>' ).addClass( 'mw-widget-calendarWidget-body-outer-wrapper' );
+ this.$bodyWrapper = $( '<div>' ).addClass( 'mw-widget-calendarWidget-body-wrapper' );
+ this.$body = $( '<div>' ).addClass( 'mw-widget-calendarWidget-body' );
+
+ // Events
+ this.$element.on( {
+ focus: this.onFocus.bind( this ),
+ mousedown: this.onClick.bind( this ),
+ keydown: this.onKeyDown.bind( this )
+ } );
+
+ // Initialization
+ this.$element
+ .addClass( 'mw-widget-calendarWidget' )
+ .append( this.$header, this.$bodyOuterWrapper.append( this.$bodyWrapper.append( this.$body ) ) );
+ if ( !this.lazyInitOnToggle ) {
+ this.buildHeaderButtons();
+ }
+ this.setDate( config.date !== undefined ? config.date : null );
+ };
+
+ /* Inheritance */
+
+ OO.inheritClass( mw.widgets.CalendarWidget, OO.ui.Widget );
+ OO.mixinClass( mw.widgets.CalendarWidget, OO.ui.mixin.TabIndexedElement );
+ OO.mixinClass( mw.widgets.CalendarWidget, OO.ui.mixin.FloatableElement );
+
+ /* Events */
+
+ /**
+ * @event change
+ *
+ * A change event is emitted when the chosen date changes.
+ *
+ * @param {string} date Day or month date, in the format 'YYYY-MM-DD' or 'YYYY-MM'
+ */
+
+ /* Methods */
+
+ /**
+ * Get the date format ('YYYY-MM-DD' or 'YYYY-MM', depending on precision), which is used
+ * internally and for dates accepted by #setDate and returned by #getDate.
+ *
+ * @private
+ * @return {string} Format
+ */
+ mw.widgets.CalendarWidget.prototype.getDateFormat = function () {
+ return {
+ day: 'YYYY-MM-DD',
+ month: 'YYYY-MM'
+ }[ this.precision ];
+ };
+
+ /**
+ * Get the date precision this calendar uses, 'day' or 'month'.
+ *
+ * @private
+ * @return {string} Precision, 'day' or 'month'
+ */
+ mw.widgets.CalendarWidget.prototype.getPrecision = function () {
+ return this.precision;
+ };
+
+ /**
+ * Get list of possible display layers.
+ *
+ * @private
+ * @return {string[]} Layers
+ */
+ mw.widgets.CalendarWidget.prototype.getDisplayLayers = function () {
+ return [ 'month', 'year', 'duodecade' ].slice( this.precision === 'month' ? 1 : 0 );
+ };
+
+ /**
+ * Update the calendar.
+ *
+ * @private
+ * @param {string|null} [fade=null] Direction in which to fade out current calendar contents,
+ * 'previous', 'next', 'up' or 'down'; or 'auto', which has the same result as 'previous' or
+ * 'next' depending on whether the current date is later or earlier than the previous.
+ */
+ mw.widgets.CalendarWidget.prototype.updateUI = function ( fade ) {
+ var items, today, selected, currentMonth, currentYear, currentDay, i, needsFade,
+ $bodyWrapper = this.$bodyWrapper;
+
+ if ( this.lazyInitOnToggle ) {
+ // We're being called from the constructor and not being shown yet, do nothing
+ return;
+ }
+
+ if (
+ this.displayLayer === this.previousDisplayLayer &&
+ this.date === this.previousDate &&
+ this.previousMoment &&
+ this.previousMoment.isSame( this.moment, this.precision === 'month' ? 'month' : 'day' )
+ ) {
+ // Already displayed
+ return;
+ }
+
+ if ( fade === 'auto' ) {
+ if ( !this.previousMoment ) {
+ fade = null;
+ } else if ( this.previousMoment.isBefore( this.moment, this.precision === 'month' ? 'month' : 'day' ) ) {
+ fade = 'next';
+ } else if ( this.previousMoment.isAfter( this.moment, this.precision === 'month' ? 'month' : 'day' ) ) {
+ fade = 'previous';
+ } else {
+ fade = null;
+ }
+ }
+
+ items = [];
+ if ( this.$oldBody ) {
+ this.$oldBody.remove();
+ }
+ this.$oldBody = this.$body.addClass( 'mw-widget-calendarWidget-old-body' );
+ // Clone without children
+ this.$body = $( this.$body[ 0 ].cloneNode( false ) )
+ .removeClass( 'mw-widget-calendarWidget-old-body' )
+ .toggleClass( 'mw-widget-calendarWidget-body-month', this.displayLayer === 'month' )
+ .toggleClass( 'mw-widget-calendarWidget-body-year', this.displayLayer === 'year' )
+ .toggleClass( 'mw-widget-calendarWidget-body-duodecade', this.displayLayer === 'duodecade' );
+
+ today = moment();
+ selected = moment( this.getDate(), this.getDateFormat() );
+
+ switch ( this.displayLayer ) {
+ case 'month':
+ this.labelButton.setLabel( this.moment.format( 'MMMM YYYY' ) );
+ this.upButton.toggle( true );
+
+ // First week displayed is the first week spanned by the month, unless it begins on Monday, in
+ // which case first week displayed is the previous week. This makes the calendar "balanced"
+ // and also neatly handles 28-day February sometimes spanning only 4 weeks.
+ currentDay = moment( this.moment ).startOf( 'month' ).subtract( 1, 'day' ).startOf( 'week' );
+
+ // Day-of-week labels. Localisation-independent: works with weeks starting on Saturday, Sunday
+ // or Monday.
+ for ( i = 0; i < 7; i++ ) {
+ items.push(
+ $( '<div>' )
+ .addClass( 'mw-widget-calendarWidget-day-heading' )
+ .text( currentDay.format( 'dd' ) )
+ );
+ currentDay.add( 1, 'day' );
+ }
+ currentDay.subtract( 7, 'days' );
+
+ // Actual calendar month. Always displays 6 weeks, for consistency (months can span 4 to 6
+ // weeks).
+ for ( i = 0; i < 42; i++ ) {
+ items.push(
+ $( '<div>' )
+ .addClass( 'mw-widget-calendarWidget-item mw-widget-calendarWidget-day' )
+ .toggleClass( 'mw-widget-calendarWidget-day-additional', !currentDay.isSame( this.moment, 'month' ) )
+ .toggleClass( 'mw-widget-calendarWidget-day-today', currentDay.isSame( today, 'day' ) )
+ .toggleClass( 'mw-widget-calendarWidget-item-selected', currentDay.isSame( selected, 'day' ) )
+ .text( currentDay.format( 'D' ) )
+ .data( 'date', currentDay.date() )
+ .data( 'month', currentDay.month() )
+ .data( 'year', currentDay.year() )
+ );
+ currentDay.add( 1, 'day' );
+ }
+ break;
+
+ case 'year':
+ this.labelButton.setLabel( this.moment.format( 'YYYY' ) );
+ this.upButton.toggle( true );
+
+ currentMonth = moment( this.moment ).startOf( 'year' );
+ for ( i = 0; i < 12; i++ ) {
+ items.push(
+ $( '<div>' )
+ .addClass( 'mw-widget-calendarWidget-item mw-widget-calendarWidget-month' )
+ .toggleClass( 'mw-widget-calendarWidget-item-selected', currentMonth.isSame( selected, 'month' ) )
+ .text( currentMonth.format( 'MMMM' ) )
+ .data( 'month', currentMonth.month() )
+ );
+ currentMonth.add( 1, 'month' );
+ }
+ // Shuffle the array to display months in columns rather than rows:
+ // | Jan | Jul |
+ // | Feb | Aug |
+ // | Mar | Sep |
+ // | Apr | Oct |
+ // | May | Nov |
+ // | Jun | Dec |
+ items = [
+ items[ 0 ], items[ 6 ],
+ items[ 1 ], items[ 7 ],
+ items[ 2 ], items[ 8 ],
+ items[ 3 ], items[ 9 ],
+ items[ 4 ], items[ 10 ],
+ items[ 5 ], items[ 11 ]
+ ];
+ break;
+
+ case 'duodecade':
+ this.labelButton.setLabel( null );
+ this.upButton.toggle( false );
+
+ currentYear = moment( { year: Math.floor( this.moment.year() / 20 ) * 20 } );
+ for ( i = 0; i < 20; i++ ) {
+ items.push(
+ $( '<div>' )
+ .addClass( 'mw-widget-calendarWidget-item mw-widget-calendarWidget-year' )
+ .toggleClass( 'mw-widget-calendarWidget-item-selected', currentYear.isSame( selected, 'year' ) )
+ .text( currentYear.format( 'YYYY' ) )
+ .data( 'year', currentYear.year() )
+ );
+ currentYear.add( 1, 'year' );
+ }
+ break;
+ }
+
+ this.$body.append.apply( this.$body, items );
+
+ $bodyWrapper
+ .removeClass( 'mw-widget-calendarWidget-body-wrapper-fade-up' )
+ .removeClass( 'mw-widget-calendarWidget-body-wrapper-fade-down' )
+ .removeClass( 'mw-widget-calendarWidget-body-wrapper-fade-previous' )
+ .removeClass( 'mw-widget-calendarWidget-body-wrapper-fade-next' );
+
+ needsFade = this.previousDisplayLayer !== this.displayLayer;
+ if ( this.displayLayer === 'month' ) {
+ needsFade = needsFade || !this.moment.isSame( this.previousMoment, 'month' );
+ } else if ( this.displayLayer === 'year' ) {
+ needsFade = needsFade || !this.moment.isSame( this.previousMoment, 'year' );
+ } else if ( this.displayLayer === 'duodecade' ) {
+ needsFade = needsFade || (
+ Math.floor( this.moment.year() / 20 ) * 20 !==
+ Math.floor( this.previousMoment.year() / 20 ) * 20
+ );
+ }
+
+ if ( fade && needsFade ) {
+ this.$oldBody.find( '.mw-widget-calendarWidget-item-selected' )
+ .removeClass( 'mw-widget-calendarWidget-item-selected' );
+ if ( fade === 'previous' || fade === 'up' ) {
+ this.$body.insertBefore( this.$oldBody );
+ } else if ( fade === 'next' || fade === 'down' ) {
+ this.$body.insertAfter( this.$oldBody );
+ }
+ setTimeout( function () {
+ $bodyWrapper.addClass( 'mw-widget-calendarWidget-body-wrapper-fade-' + fade );
+ } );
+ } else {
+ this.$oldBody.replaceWith( this.$body );
+ }
+
+ this.previousMoment = moment( this.moment );
+ this.previousDisplayLayer = this.displayLayer;
+ this.previousDate = this.date;
+
+ this.$body.on( 'click', this.onBodyClick.bind( this ) );
+ };
+
+ /**
+ * Construct and display buttons to navigate the calendar.
+ *
+ * @private
+ */
+ mw.widgets.CalendarWidget.prototype.buildHeaderButtons = function () {
+ this.labelButton = new OO.ui.ButtonWidget( {
+ tabIndex: -1,
+ label: '',
+ framed: false,
+ classes: [ 'mw-widget-calendarWidget-labelButton' ]
+ } );
+ this.upButton = new OO.ui.ButtonWidget( {
+ tabIndex: -1,
+ framed: false,
+ icon: 'collapse',
+ classes: [ 'mw-widget-calendarWidget-upButton' ]
+ } );
+ this.prevButton = new OO.ui.ButtonWidget( {
+ tabIndex: -1,
+ framed: false,
+ icon: 'previous',
+ classes: [ 'mw-widget-calendarWidget-prevButton' ]
+ } );
+ this.nextButton = new OO.ui.ButtonWidget( {
+ tabIndex: -1,
+ framed: false,
+ icon: 'next',
+ classes: [ 'mw-widget-calendarWidget-nextButton' ]
+ } );
+
+ this.labelButton.connect( this, { click: 'onUpButtonClick' } );
+ this.upButton.connect( this, { click: 'onUpButtonClick' } );
+ this.prevButton.connect( this, { click: 'onPrevButtonClick' } );
+ this.nextButton.connect( this, { click: 'onNextButtonClick' } );
+
+ this.$header.append(
+ this.prevButton.$element,
+ this.nextButton.$element,
+ this.upButton.$element,
+ this.labelButton.$element
+ );
+ };
+
+ /**
+ * Handle click events on the "up" button, switching to less precise view.
+ *
+ * @private
+ */
+ mw.widgets.CalendarWidget.prototype.onUpButtonClick = function () {
+ var
+ layers = this.getDisplayLayers(),
+ currentLayer = layers.indexOf( this.displayLayer );
+ if ( currentLayer !== layers.length - 1 ) {
+ // One layer up
+ this.displayLayer = layers[ currentLayer + 1 ];
+ this.updateUI( 'up' );
+ } else {
+ this.updateUI();
+ }
+ };
+
+ /**
+ * Handle click events on the "previous" button, switching to previous pane.
+ *
+ * @private
+ */
+ mw.widgets.CalendarWidget.prototype.onPrevButtonClick = function () {
+ switch ( this.displayLayer ) {
+ case 'month':
+ this.moment.subtract( 1, 'month' );
+ break;
+ case 'year':
+ this.moment.subtract( 1, 'year' );
+ break;
+ case 'duodecade':
+ this.moment.subtract( 20, 'years' );
+ break;
+ }
+ this.updateUI( 'previous' );
+ };
+
+ /**
+ * Handle click events on the "next" button, switching to next pane.
+ *
+ * @private
+ */
+ mw.widgets.CalendarWidget.prototype.onNextButtonClick = function () {
+ switch ( this.displayLayer ) {
+ case 'month':
+ this.moment.add( 1, 'month' );
+ break;
+ case 'year':
+ this.moment.add( 1, 'year' );
+ break;
+ case 'duodecade':
+ this.moment.add( 20, 'years' );
+ break;
+ }
+ this.updateUI( 'next' );
+ };
+
+ /**
+ * Handle click events anywhere in the body of the widget, which contains the matrix of days,
+ * months or years to choose. Maybe change the pane or switch to more precise view, depending on
+ * what gets clicked.
+ *
+ * @private
+ * @param {jQuery.Event} e Click event
+ */
+ mw.widgets.CalendarWidget.prototype.onBodyClick = function ( e ) {
+ var
+ $target = $( e.target ),
+ layers = this.getDisplayLayers(),
+ currentLayer = layers.indexOf( this.displayLayer );
+ if ( $target.data( 'year' ) !== undefined ) {
+ this.moment.year( $target.data( 'year' ) );
+ }
+ if ( $target.data( 'month' ) !== undefined ) {
+ this.moment.month( $target.data( 'month' ) );
+ }
+ if ( $target.data( 'date' ) !== undefined ) {
+ this.moment.date( $target.data( 'date' ) );
+ }
+ if ( currentLayer === 0 ) {
+ this.setDateFromMoment();
+ this.updateUI( 'auto' );
+ } else {
+ // One layer down
+ this.displayLayer = layers[ currentLayer - 1 ];
+ this.updateUI( 'down' );
+ }
+ };
+
+ /**
+ * Set the date.
+ *
+ * @param {string|null} [date=null] Day or month date, in the format 'YYYY-MM-DD' or 'YYYY-MM'.
+ * When null, the calendar will show today's date, but not select it. When invalid, the date
+ * is not changed.
+ */
+ mw.widgets.CalendarWidget.prototype.setDate = function ( date ) {
+ var mom = date !== null ? moment( date, this.getDateFormat() ) : moment();
+ if ( mom.isValid() ) {
+ this.moment = mom;
+ if ( date !== null ) {
+ this.setDateFromMoment();
+ } else if ( this.date !== null ) {
+ this.date = null;
+ this.emit( 'change', this.date );
+ }
+ this.displayLayer = this.getDisplayLayers()[ 0 ];
+ this.updateUI();
+ }
+ };
+
+ /**
+ * Reset the user interface of this widget to reflect selected date.
+ */
+ mw.widgets.CalendarWidget.prototype.resetUI = function () {
+ this.moment = this.getDate() !== null ? moment( this.getDate(), this.getDateFormat() ) : moment();
+ this.displayLayer = this.getDisplayLayers()[ 0 ];
+ this.updateUI();
+ };
+
+ /**
+ * Set the date from moment object.
+ *
+ * @private
+ */
+ mw.widgets.CalendarWidget.prototype.setDateFromMoment = function () {
+ // Switch to English locale to avoid number formatting. We want the internal value to be
+ // '2015-07-24' and not '٢٠١٥-٠٧-٢٤' even if the UI language is Arabic.
+ var newDate = moment( this.moment ).locale( 'en' ).format( this.getDateFormat() );
+ if ( this.date !== newDate ) {
+ this.date = newDate;
+ this.emit( 'change', this.date );
+ }
+ };
+
+ /**
+ * Get current date, in the format 'YYYY-MM-DD' or 'YYYY-MM', depending on precision. Digits will
+ * not be localised.
+ *
+ * @return {string|null} Date string
+ */
+ mw.widgets.CalendarWidget.prototype.getDate = function () {
+ return this.date;
+ };
+
+ /**
+ * Handle focus events.
+ *
+ * @private
+ */
+ mw.widgets.CalendarWidget.prototype.onFocus = function () {
+ this.displayLayer = this.getDisplayLayers()[ 0 ];
+ this.updateUI( 'down' );
+ };
+
+ /**
+ * Handle mouse click events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse click event
+ * @return {boolean} False to cancel the default event
+ */
+ mw.widgets.CalendarWidget.prototype.onClick = function ( e ) {
+ if ( !this.isDisabled() && e.which === 1 ) {
+ // Prevent unintended focussing
+ return false;
+ }
+ };
+
+ /**
+ * Handle key down events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key down event
+ * @return {boolean} False to cancel the default event
+ */
+ mw.widgets.CalendarWidget.prototype.onKeyDown = function ( e ) {
+ var
+ dir = OO.ui.Element.static.getDir( this.$element ),
+ nextDirectionKey = dir === 'ltr' ? OO.ui.Keys.RIGHT : OO.ui.Keys.LEFT,
+ prevDirectionKey = dir === 'ltr' ? OO.ui.Keys.LEFT : OO.ui.Keys.RIGHT,
+ changed = true;
+
+ if ( !this.isDisabled() ) {
+ switch ( e.which ) {
+ case prevDirectionKey:
+ this.moment.subtract( 1, this.precision === 'month' ? 'month' : 'day' );
+ break;
+ case nextDirectionKey:
+ this.moment.add( 1, this.precision === 'month' ? 'month' : 'day' );
+ break;
+ case OO.ui.Keys.UP:
+ this.moment.subtract( 1, this.precision === 'month' ? 'month' : 'week' );
+ break;
+ case OO.ui.Keys.DOWN:
+ this.moment.add( 1, this.precision === 'month' ? 'month' : 'week' );
+ break;
+ case OO.ui.Keys.PAGEUP:
+ this.moment.subtract( 1, this.precision === 'month' ? 'year' : 'month' );
+ break;
+ case OO.ui.Keys.PAGEDOWN:
+ this.moment.add( 1, this.precision === 'month' ? 'year' : 'month' );
+ break;
+ default:
+ changed = false;
+ break;
+ }
+
+ if ( changed ) {
+ this.displayLayer = this.getDisplayLayers()[ 0 ];
+ this.setDateFromMoment();
+ this.updateUI( 'auto' );
+ return false;
+ }
+ }
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.CalendarWidget.prototype.toggle = function ( visible ) {
+ if ( this.lazyInitOnToggle && visible ) {
+ this.lazyInitOnToggle = false;
+ this.buildHeaderButtons();
+ this.updateUI();
+ }
+
+ // Parent method
+ mw.widgets.CalendarWidget.parent.prototype.toggle.call( this, visible );
+
+ if ( this.$floatableContainer ) {
+ this.togglePositioning( this.isVisible() );
+ }
+
+ return this;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less
new file mode 100644
index 00000000..395f80bc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CalendarWidget.less
@@ -0,0 +1,254 @@
+/*!
+ * MediaWiki Widgets – CalendarWidget styles.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/* stylelint-disable no-duplicate-selectors */
+@import 'mediawiki.mixins';
+
+@calendarWidth: 21em;
+@calendarHeight: 14em;
+
+.mw-widget-calendarWidget {
+ width: @calendarWidth;
+}
+
+.mw-widget-calendarWidget-header {
+ position: relative;
+ line-height: 2.5;
+}
+
+.mw-widget-calendarWidget-header .oo-ui-buttonWidget {
+ margin-right: 0;
+}
+
+.mw-widget-calendarWidget-header .mw-widget-calendarWidget-labelButton {
+ margin: 0 auto;
+ display: block;
+ width: @calendarWidth - 2 * 3em;
+
+ .oo-ui-buttonElement-button {
+ width: @calendarWidth - 2 * 3em;
+ text-align: center;
+ }
+}
+
+.mw-widget-calendarWidget-upButton {
+ position: absolute;
+ right: 3em;
+}
+
+.mw-widget-calendarWidget-prevButton {
+ float: left;
+}
+
+.mw-widget-calendarWidget-nextButton {
+ float: right;
+}
+
+.mw-widget-calendarWidget-body-outer-wrapper {
+ clear: both;
+ position: relative;
+ overflow: hidden;
+ // Fit 7 days, 3em each
+ width: @calendarWidth;
+ // Fit 6 weeks + heading line, 2em each
+ height: @calendarHeight;
+}
+
+.mw-widget-calendarWidget-body-wrapper {
+ .mw-widget-calendarWidget-body {
+ display: inline-block;
+ // Fit 7 days, 3em each
+ width: @calendarWidth;
+ // Fit 6 weeks + heading line, 2em each
+ height: @calendarHeight;
+ }
+
+ .mw-widget-calendarWidget-body:not( .mw-widget-calendarWidget-old-body ):first-child {
+ margin-top: -@calendarHeight; /* stylelint-disable-line value-keyword-case */
+ margin-left: -@calendarWidth; /* stylelint-disable-line value-keyword-case */
+ }
+
+ .mw-widget-calendarWidget-body:not( .mw-widget-calendarWidget-old-body ):last-child {
+ margin-top: 0;
+ margin-left: 0;
+ }
+}
+
+.mw-widget-calendarWidget-body-wrapper-fade-previous {
+ width: @calendarWidth * 2;
+ height: @calendarHeight;
+
+ .mw-widget-calendarWidget-body:first-child {
+ margin-top: 0 !important; /* stylelint-disable-line declaration-no-important */
+ margin-left: 0 !important; /* stylelint-disable-line declaration-no-important */
+ .transition( margin-left 500ms );
+ }
+}
+
+.mw-widget-calendarWidget-body-wrapper-fade-next {
+ width: @calendarWidth * 2;
+ height: @calendarHeight;
+
+ .mw-widget-calendarWidget-body:first-child {
+ margin-left: -@calendarWidth !important; /* stylelint-disable-line value-keyword-case, declaration-no-important */
+ margin-top: 0 !important; /* stylelint-disable-line declaration-no-important */
+ .transition( margin-left 500ms );
+ }
+}
+
+.mw-widget-calendarWidget-body-wrapper-fade-up {
+ width: @calendarWidth;
+ height: @calendarHeight * 2;
+
+ .mw-widget-calendarWidget-body {
+ display: block;
+ }
+
+ .mw-widget-calendarWidget-body:first-child {
+ margin-left: 0 !important; /* stylelint-disable-line declaration-no-important */
+ margin-top: 0 !important; /* stylelint-disable-line declaration-no-important */
+ .transition( margin-top 500ms );
+ }
+}
+
+.mw-widget-calendarWidget-body-wrapper-fade-down {
+ width: @calendarWidth;
+ height: @calendarHeight * 2;
+
+ .mw-widget-calendarWidget-body {
+ display: block;
+ }
+
+ .mw-widget-calendarWidget-body:first-child {
+ margin-left: 0 !important; /* stylelint-disable-line declaration-no-important */
+ margin-top: -@calendarHeight !important; /* stylelint-disable-line value-keyword-case, declaration-no-important */
+ .transition( margin-top 500ms );
+ }
+}
+
+.mw-widget-calendarWidget-day,
+.mw-widget-calendarWidget-day-heading,
+.mw-widget-calendarWidget-month,
+.mw-widget-calendarWidget-year {
+ display: inline-block;
+ vertical-align: middle;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ text-align: center;
+}
+
+.mw-widget-calendarWidget-day,
+.mw-widget-calendarWidget-day-heading {
+ // 7x7 grid
+ width: @calendarWidth / 7;
+ line-height: @calendarHeight / 7;
+ // Don't overlap the hacked-up fake box-shadow border we get when focussed
+ &:nth-child( 7n ) {
+ width: @calendarWidth / 7 - 0.2em;
+ margin-right: 0.2em;
+ }
+ &:nth-child( 7n+1 ) {
+ width: @calendarWidth / 7 - 0.2em;
+ margin-left: 0.2em;
+ }
+ &:nth-child( 42 ) ~ & {
+ line-height: @calendarHeight / 7 - 0.2em;
+ margin-bottom: 0.2em;
+ }
+}
+
+.mw-widget-calendarWidget-month {
+ // 2x6 grid
+ width: @calendarWidth / 2;
+ line-height: @calendarHeight / 6;
+ // Don't overlap the hacked-up fake box-shadow border we get when focussed
+ &:nth-child( 2n ) {
+ width: @calendarWidth / 2 - 0.2em;
+ margin-right: 0.2em;
+ }
+ &:nth-child( 2n+1 ) {
+ width: @calendarWidth / 2 - 0.2em;
+ margin-left: 0.2em;
+ }
+ &:nth-child( 10 ) ~ & {
+ line-height: @calendarHeight / 6 - 0.2em;
+ margin-bottom: 0.2em;
+ }
+}
+
+.mw-widget-calendarWidget-year {
+ // 5x4 grid
+ width: @calendarWidth / 5;
+ line-height: @calendarHeight / 4;
+ // Don't overlap the hacked-up fake box-shadow border we get when focussed
+ &:nth-child( 5n ) {
+ width: @calendarWidth / 5 - 0.2em;
+ margin-right: 0.2em;
+ }
+ &:nth-child( 5n+1 ) {
+ width: @calendarWidth / 5 - 0.2em;
+ margin-left: 0.2em;
+ }
+ &:nth-child( 15 ) ~ & {
+ line-height: @calendarHeight / 4 - 0.2em;
+ margin-bottom: 0.2em;
+ }
+}
+
+.mw-widget-calendarWidget-item {
+ cursor: pointer;
+}
+
+/* Theme-specific */
+.mw-widget-calendarWidget {
+ .box-sizing( border-box );
+ border: 1px solid #a2a9b1;
+ .transition( ~'border-color 100ms, box-shadow 100ms' );
+
+ &:focus {
+ border-color: #36c;
+ box-shadow: inset 0 0 0 1px #36c;
+ outline: 0;
+ }
+
+ &-day {
+ color: #222;
+ border-radius: 2px;
+ }
+
+ &-day-heading {
+ color: #54595d;
+ font-weight: bold;
+ }
+
+ &-day-additional {
+ color: #a2a9b1;
+
+ &:hover {
+ color: #222;
+ }
+ }
+
+ &-day-today {
+ box-shadow: inset 0 0 0 1px #36c;
+ }
+
+ &-item {
+ .transition( ~'background-color 250ms, color 250ms' );
+
+ &:hover {
+ background-color: #36c;
+ color: #fff;
+ }
+
+ &-selected {
+ background-color: #2a4b8d;
+ color: #fff;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js
new file mode 100644
index 00000000..488d9e09
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategoryCapsuleItemWidget.js
@@ -0,0 +1,205 @@
+/*!
+ * MediaWiki Widgets - CategoryCapsuleItemWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * @class mw.widgets.PageExistenceCache
+ * @private
+ * @param {mw.Api} [api]
+ */
+ function PageExistenceCache( api ) {
+ this.api = api || new mw.Api();
+ this.processExistenceCheckQueueDebounced = OO.ui.debounce( this.processExistenceCheckQueue );
+ this.currentRequest = null;
+ this.existenceCache = {};
+ this.existenceCheckQueue = {};
+ }
+
+ /**
+ * Check for existence of pages in the queue.
+ *
+ * @private
+ */
+ PageExistenceCache.prototype.processExistenceCheckQueue = function () {
+ var queue, titles,
+ cache = this;
+ if ( this.currentRequest ) {
+ // Don't fire off a million requests at the same time
+ this.currentRequest.always( function () {
+ cache.currentRequest = null;
+ cache.processExistenceCheckQueueDebounced();
+ } );
+ return;
+ }
+ queue = this.existenceCheckQueue;
+ this.existenceCheckQueue = {};
+ titles = Object.keys( queue ).filter( function ( title ) {
+ if ( cache.existenceCache.hasOwnProperty( title ) ) {
+ queue[ title ].resolve( cache.existenceCache[ title ] );
+ }
+ return !cache.existenceCache.hasOwnProperty( title );
+ } );
+ if ( !titles.length ) {
+ return;
+ }
+ this.currentRequest = this.api.get( {
+ formatversion: 2,
+ action: 'query',
+ prop: [ 'info' ],
+ titles: titles
+ } ).done( function ( response ) {
+ var
+ normalized = {},
+ pages = {};
+ $.each( response.query.normalized || [], function ( index, data ) {
+ normalized[ data.fromencoded ? decodeURIComponent( data.from ) : data.from ] = data.to;
+ } );
+ $.each( response.query.pages, function ( index, page ) {
+ pages[ page.title ] = !page.missing;
+ } );
+ $.each( titles, function ( index, title ) {
+ var normalizedTitle = title;
+ while ( normalized[ normalizedTitle ] ) {
+ normalizedTitle = normalized[ normalizedTitle ];
+ }
+ cache.existenceCache[ title ] = pages[ normalizedTitle ];
+ queue[ title ].resolve( cache.existenceCache[ title ] );
+ } );
+ } );
+ };
+
+ /**
+ * Register a request to check whether a page exists.
+ *
+ * @private
+ * @param {mw.Title} title
+ * @return {jQuery.Promise} Promise resolved with true if the page exists or false otherwise
+ */
+ PageExistenceCache.prototype.checkPageExistence = function ( title ) {
+ var key = title.getPrefixedText();
+ if ( !this.existenceCheckQueue[ key ] ) {
+ this.existenceCheckQueue[ key ] = $.Deferred();
+ }
+ this.processExistenceCheckQueueDebounced();
+ return this.existenceCheckQueue[ key ].promise();
+ };
+
+ /**
+ * @class mw.widgets.ForeignTitle
+ * @private
+ * @extends mw.Title
+ *
+ * @constructor
+ * @param {string} title
+ * @param {number} [namespace]
+ */
+ function ForeignTitle( title, namespace ) {
+ // We only need to handle categories here... but we don't know the target language.
+ // So assume that any namespace-like prefix is the 'Category' namespace...
+ title = title.replace( /^(.+?)_*:_*(.*)$/, 'Category:$2' ); // HACK
+ ForeignTitle.parent.call( this, title, namespace );
+ }
+ OO.inheritClass( ForeignTitle, mw.Title );
+ ForeignTitle.prototype.getNamespacePrefix = function () {
+ // We only need to handle categories here...
+ return 'Category:'; // HACK
+ };
+
+ /**
+ * Category selector capsule item widget. Extends OO.ui.CapsuleItemWidget with the ability to link
+ * to the given page, and to show its existence status (i.e., whether it is a redlink).
+ *
+ * @class mw.widgets.CategoryCapsuleItemWidget
+ * @uses mw.Api
+ * @extends OO.ui.CapsuleItemWidget
+ *
+ * @constructor
+ * @param {Object} config Configuration options
+ * @cfg {mw.Title} title Page title to use (required)
+ * @cfg {string} [apiUrl] API URL, if not the current wiki's API
+ */
+ mw.widgets.CategoryCapsuleItemWidget = function MWWCategoryCapsuleItemWidget( config ) {
+ var widget = this;
+ // Parent constructor
+ mw.widgets.CategoryCapsuleItemWidget.parent.call( this, $.extend( {
+ data: config.title.getMainText(),
+ label: config.title.getMainText()
+ }, config ) );
+
+ // Properties
+ this.title = config.title;
+ this.apiUrl = config.apiUrl || '';
+ this.$link = $( '<a>' )
+ .text( this.label )
+ .attr( 'target', '_blank' )
+ .on( 'click', function ( e ) {
+ // CapsuleMultiselectWidget really wants to prevent you from clicking the link, don't let it
+ e.stopPropagation();
+ } );
+
+ // Initialize
+ this.setMissing( false );
+ this.$label.replaceWith( this.$link );
+ this.setLabelElement( this.$link );
+
+ if ( !this.constructor.static.pageExistenceCaches[ this.apiUrl ] ) {
+ this.constructor.static.pageExistenceCaches[ this.apiUrl ] =
+ new PageExistenceCache( new mw.ForeignApi( this.apiUrl ) );
+ }
+ this.constructor.static.pageExistenceCaches[ this.apiUrl ]
+ .checkPageExistence( new ForeignTitle( this.title.getPrefixedText() ) )
+ .done( function ( exists ) {
+ widget.setMissing( !exists );
+ } );
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.CategoryCapsuleItemWidget, OO.ui.CapsuleItemWidget );
+
+ /* Static Properties */
+
+ /**
+ * Map of API URLs to PageExistenceCache objects.
+ *
+ * @static
+ * @inheritable
+ * @property {Object}
+ */
+ mw.widgets.CategoryCapsuleItemWidget.static.pageExistenceCaches = {
+ '': new PageExistenceCache()
+ };
+
+ /* Methods */
+
+ /**
+ * Update label link href and CSS classes to reflect page existence status.
+ *
+ * @private
+ * @param {boolean} missing Whether the page is missing (does not exist)
+ */
+ mw.widgets.CategoryCapsuleItemWidget.prototype.setMissing = function ( missing ) {
+ var
+ title = new ForeignTitle( this.title.getPrefixedText() ), // HACK
+ prefix = this.apiUrl.replace( '/w/api.php', '' ); // HACK
+
+ this.missing = missing;
+
+ if ( !missing ) {
+ this.$link
+ .attr( 'href', prefix + title.getUrl() )
+ .attr( 'title', title.getPrefixedText() )
+ .removeClass( 'new' );
+ } else {
+ this.$link
+ .attr( 'href', prefix + title.getUrl( { action: 'edit', redlink: 1 } ) )
+ .attr( 'title', mw.msg( 'red-link-title', title.getPrefixedText() ) )
+ .addClass( 'new' );
+ }
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategoryMultiselectWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategoryMultiselectWidget.js
new file mode 100644
index 00000000..5f680303
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategoryMultiselectWidget.js
@@ -0,0 +1,416 @@
+/*!
+ * MediaWiki Widgets - CategoryMultiselectWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+ var NS_CATEGORY = mw.config.get( 'wgNamespaceIds' ).category;
+
+ /**
+ * Category selector widget. Displays an OO.ui.CapsuleMultiselectWidget
+ * and autocompletes with available categories.
+ *
+ * mw.loader.using( 'mediawiki.widgets.CategoryMultiselectWidget', function () {
+ * var selector = new mw.widgets.CategoryMultiselectWidget( {
+ * searchTypes: [
+ * mw.widgets.CategoryMultiselectWidget.SearchType.OpenSearch,
+ * mw.widgets.CategoryMultiselectWidget.SearchType.InternalSearch
+ * ]
+ * } );
+ *
+ * $( 'body' ).append( selector.$element );
+ *
+ * selector.setSearchTypes( [ mw.widgets.CategoryMultiselectWidget.SearchType.SubCategories ] );
+ * } );
+ *
+ * @class mw.widgets.CategoryMultiselectWidget
+ * @uses mw.Api
+ * @extends OO.ui.CapsuleMultiselectWidget
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {mw.Api} [api] Instance of mw.Api (or subclass thereof) to use for queries
+ * @cfg {number} [limit=10] Maximum number of results to load
+ * @cfg {mw.widgets.CategoryMultiselectWidget.SearchType[]} [searchTypes=[mw.widgets.CategoryMultiselectWidget.SearchType.OpenSearch]]
+ * Default search API to use when searching.
+ */
+ mw.widgets.CategoryMultiselectWidget = function MWCategoryMultiselectWidget( config ) {
+ // Config initialization
+ config = $.extend( {
+ limit: 10,
+ searchTypes: [ mw.widgets.CategoryMultiselectWidget.SearchType.OpenSearch ]
+ }, config );
+ this.limit = config.limit;
+ this.searchTypes = config.searchTypes;
+ this.validateSearchTypes();
+
+ // Parent constructor
+ mw.widgets.CategoryMultiselectWidget.parent.call( this, $.extend( true, {}, config, {
+ menu: {
+ filterFromInput: false
+ },
+ placeholder: mw.msg( 'mw-widgets-categoryselector-add-category-placeholder' ),
+ // This allows the user to both select non-existent categories, and prevents the selector from
+ // being wiped from #onMenuItemsChange when we change the available options in the dropdown
+ allowArbitrary: true
+ } ) );
+
+ // Mixin constructors
+ OO.ui.mixin.PendingElement.call( this, $.extend( {}, config, { $pending: this.$handle } ) );
+
+ // Event handler to call the autocomplete methods
+ this.$input.on( 'change input cut paste', OO.ui.debounce( this.updateMenuItems.bind( this ), 100 ) );
+
+ // Initialize
+ this.api = config.api || new mw.Api();
+ this.searchCache = {};
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.CategoryMultiselectWidget, OO.ui.CapsuleMultiselectWidget );
+ OO.mixinClass( mw.widgets.CategoryMultiselectWidget, OO.ui.mixin.PendingElement );
+
+ /* Methods */
+
+ /**
+ * Gets new items based on the input by calling
+ * {@link #getNewMenuItems getNewItems} and updates the menu
+ * after removing duplicates based on the data value.
+ *
+ * @private
+ * @method
+ */
+ mw.widgets.CategoryMultiselectWidget.prototype.updateMenuItems = function () {
+ this.getMenu().clearItems();
+ this.getNewMenuItems( this.$input.val() ).then( function ( items ) {
+ var existingItems, filteredItems,
+ menu = this.getMenu();
+
+ // Never show the menu if the input lost focus in the meantime
+ if ( !this.$input.is( ':focus' ) ) {
+ return;
+ }
+
+ // Array of strings of the data of OO.ui.MenuOptionsWidgets
+ existingItems = menu.getItems().map( function ( item ) {
+ return item.data;
+ } );
+
+ // Remove if items' data already exists
+ filteredItems = items.filter( function ( item ) {
+ return existingItems.indexOf( item ) === -1;
+ } );
+
+ // Map to an array of OO.ui.MenuOptionWidgets
+ filteredItems = filteredItems.map( function ( item ) {
+ return new OO.ui.MenuOptionWidget( {
+ data: item,
+ label: item
+ } );
+ } );
+
+ menu.addItems( filteredItems ).toggle( true );
+ }.bind( this ) );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.CategoryMultiselectWidget.prototype.clearInput = function () {
+ mw.widgets.CategoryMultiselectWidget.parent.prototype.clearInput.call( this );
+ // Abort all pending requests, we won't need their results
+ this.api.abort();
+ };
+
+ /**
+ * Searches for categories based on the input.
+ *
+ * @private
+ * @method
+ * @param {string} input The input used to prefix search categories
+ * @return {jQuery.Promise} Resolves with an array of categories
+ */
+ mw.widgets.CategoryMultiselectWidget.prototype.getNewMenuItems = function ( input ) {
+ var i,
+ promises = [],
+ deferred = $.Deferred();
+
+ if ( $.trim( input ) === '' ) {
+ deferred.resolve( [] );
+ return deferred.promise();
+ }
+
+ // Abort all pending requests, we won't need their results
+ this.api.abort();
+ for ( i = 0; i < this.searchTypes.length; i++ ) {
+ promises.push( this.searchCategories( input, this.searchTypes[ i ] ) );
+ }
+
+ this.pushPending();
+
+ $.when.apply( $, promises ).done( function () {
+ var categoryNames,
+ allData = [],
+ dataSets = Array.prototype.slice.apply( arguments );
+
+ // Collect values from all results
+ allData = allData.concat.apply( allData, dataSets );
+
+ categoryNames = allData
+ // Remove duplicates
+ .filter( function ( value, index, self ) {
+ return self.indexOf( value ) === index;
+ } )
+ // Get Title objects
+ .map( function ( name ) {
+ return mw.Title.newFromText( name );
+ } )
+ // Keep only titles from 'Category' namespace
+ .filter( function ( title ) {
+ return title && title.getNamespaceId() === NS_CATEGORY;
+ } )
+ // Convert back to strings, strip 'Category:' prefix
+ .map( function ( title ) {
+ return title.getMainText();
+ } );
+
+ deferred.resolve( categoryNames );
+
+ } ).always( this.popPending.bind( this ) );
+
+ return deferred.promise();
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.CategoryMultiselectWidget.prototype.createItemWidget = function ( data ) {
+ var title = mw.Title.makeTitle( NS_CATEGORY, data );
+ if ( !title ) {
+ return null;
+ }
+ return new mw.widgets.CategoryCapsuleItemWidget( {
+ apiUrl: this.api.apiUrl || undefined,
+ title: title
+ } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.CategoryMultiselectWidget.prototype.getItemFromData = function ( data ) {
+ // This is a bit of a hack... We have to canonicalize the data in the same way that
+ // #createItemWidget and CategoryCapsuleItemWidget will do, otherwise we won't find duplicates.
+ var title = mw.Title.makeTitle( NS_CATEGORY, data );
+ if ( !title ) {
+ return null;
+ }
+ return OO.ui.mixin.GroupElement.prototype.getItemFromData.call( this, title.getMainText() );
+ };
+
+ /**
+ * Validates the values in `this.searchType`.
+ *
+ * @private
+ * @return {boolean}
+ */
+ mw.widgets.CategoryMultiselectWidget.prototype.validateSearchTypes = function () {
+ var validSearchTypes = false,
+ searchTypeEnumCount = Object.keys( mw.widgets.CategoryMultiselectWidget.SearchType ).length;
+
+ // Check if all values are in the SearchType enum
+ validSearchTypes = this.searchTypes.every( function ( searchType ) {
+ return searchType > -1 && searchType < searchTypeEnumCount;
+ } );
+
+ if ( validSearchTypes === false ) {
+ throw new Error( 'Unknown searchType in searchTypes' );
+ }
+
+ // If the searchTypes has mw.widgets.CategoryMultiselectWidget.SearchType.SubCategories
+ // it can be the only search type.
+ if ( this.searchTypes.indexOf( mw.widgets.CategoryMultiselectWidget.SearchType.SubCategories ) > -1 &&
+ this.searchTypes.length > 1
+ ) {
+ throw new Error( 'Can\'t have additional search types with mw.widgets.CategoryMultiselectWidget.SearchType.SubCategories' );
+ }
+
+ // If the searchTypes has mw.widgets.CategoryMultiselectWidget.SearchType.ParentCategories
+ // it can be the only search type.
+ if ( this.searchTypes.indexOf( mw.widgets.CategoryMultiselectWidget.SearchType.ParentCategories ) > -1 &&
+ this.searchTypes.length > 1
+ ) {
+ throw new Error( 'Can\'t have additional search types with mw.widgets.CategoryMultiselectWidget.SearchType.ParentCategories' );
+ }
+
+ return true;
+ };
+
+ /**
+ * Sets and validates the value of `this.searchType`.
+ *
+ * @param {mw.widgets.CategoryMultiselectWidget.SearchType[]} searchTypes
+ */
+ mw.widgets.CategoryMultiselectWidget.prototype.setSearchTypes = function ( searchTypes ) {
+ this.searchTypes = searchTypes;
+ this.validateSearchTypes();
+ };
+
+ /**
+ * Searches categories based on input and searchType.
+ *
+ * @private
+ * @method
+ * @param {string} input The input used to prefix search categories
+ * @param {mw.widgets.CategoryMultiselectWidget.SearchType} searchType
+ * @return {jQuery.Promise} Resolves with an array of categories
+ */
+ mw.widgets.CategoryMultiselectWidget.prototype.searchCategories = function ( input, searchType ) {
+ var deferred = $.Deferred(),
+ cacheKey = input + searchType.toString();
+
+ // Check cache
+ if ( this.searchCache[ cacheKey ] !== undefined ) {
+ return this.searchCache[ cacheKey ];
+ }
+
+ switch ( searchType ) {
+ case mw.widgets.CategoryMultiselectWidget.SearchType.OpenSearch:
+ this.api.get( {
+ formatversion: 2,
+ action: 'opensearch',
+ namespace: NS_CATEGORY,
+ limit: this.limit,
+ search: input
+ } ).done( function ( res ) {
+ var categories = res[ 1 ];
+ deferred.resolve( categories );
+ } ).fail( deferred.reject.bind( deferred ) );
+ break;
+
+ case mw.widgets.CategoryMultiselectWidget.SearchType.InternalSearch:
+ this.api.get( {
+ formatversion: 2,
+ action: 'query',
+ list: 'allpages',
+ apnamespace: NS_CATEGORY,
+ aplimit: this.limit,
+ apfrom: input,
+ apprefix: input
+ } ).done( function ( res ) {
+ var categories = res.query.allpages.map( function ( page ) {
+ return page.title;
+ } );
+ deferred.resolve( categories );
+ } ).fail( deferred.reject.bind( deferred ) );
+ break;
+
+ case mw.widgets.CategoryMultiselectWidget.SearchType.Exists:
+ if ( input.indexOf( '|' ) > -1 ) {
+ deferred.resolve( [] );
+ break;
+ }
+
+ this.api.get( {
+ formatversion: 2,
+ action: 'query',
+ prop: 'info',
+ titles: 'Category:' + input
+ } ).done( function ( res ) {
+ var categories = [];
+
+ $.each( res.query.pages, function ( index, page ) {
+ if ( !page.missing ) {
+ categories.push( page.title );
+ }
+ } );
+
+ deferred.resolve( categories );
+ } ).fail( deferred.reject.bind( deferred ) );
+ break;
+
+ case mw.widgets.CategoryMultiselectWidget.SearchType.SubCategories:
+ if ( input.indexOf( '|' ) > -1 ) {
+ deferred.resolve( [] );
+ break;
+ }
+
+ this.api.get( {
+ formatversion: 2,
+ action: 'query',
+ list: 'categorymembers',
+ cmtype: 'subcat',
+ cmlimit: this.limit,
+ cmtitle: 'Category:' + input
+ } ).done( function ( res ) {
+ var categories = res.query.categorymembers.map( function ( category ) {
+ return category.title;
+ } );
+ deferred.resolve( categories );
+ } ).fail( deferred.reject.bind( deferred ) );
+ break;
+
+ case mw.widgets.CategoryMultiselectWidget.SearchType.ParentCategories:
+ if ( input.indexOf( '|' ) > -1 ) {
+ deferred.resolve( [] );
+ break;
+ }
+
+ this.api.get( {
+ formatversion: 2,
+ action: 'query',
+ prop: 'categories',
+ cllimit: this.limit,
+ titles: 'Category:' + input
+ } ).done( function ( res ) {
+ var categories = [];
+
+ $.each( res.query.pages, function ( index, page ) {
+ if ( !page.missing && Array.isArray( page.categories ) ) {
+ categories.push.apply( categories, page.categories.map( function ( category ) {
+ return category.title;
+ } ) );
+ }
+ } );
+
+ deferred.resolve( categories );
+ } ).fail( deferred.reject.bind( deferred ) );
+ break;
+
+ default:
+ throw new Error( 'Unknown searchType' );
+ }
+
+ // Cache the result
+ this.searchCache[ cacheKey ] = deferred.promise();
+
+ return deferred.promise();
+ };
+
+ /**
+ * @enum mw.widgets.CategoryMultiselectWidget.SearchType
+ * Types of search available.
+ */
+ mw.widgets.CategoryMultiselectWidget.SearchType = {
+ /** Search using action=opensearch */
+ OpenSearch: 0,
+
+ /** Search using action=query */
+ InternalSearch: 1,
+
+ /** Search for existing categories with the exact title */
+ Exists: 2,
+
+ /** Search only subcategories */
+ SubCategories: 3,
+
+ /** Search only parent categories */
+ ParentCategories: 4
+ };
+
+ // For backwards compatibility. See T161285.
+ mw.widgets.CategorySelector = mw.widgets.CategoryMultiselectWidget;
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategorySelector.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategorySelector.js
new file mode 100644
index 00000000..5d7d115a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.CategorySelector.js
@@ -0,0 +1,399 @@
+/*!
+ * MediaWiki Widgets - CategorySelector class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+ var CSP,
+ NS_CATEGORY = mw.config.get( 'wgNamespaceIds' ).category;
+
+ /**
+ * Category selector widget. Displays an OO.ui.CapsuleMultiSelectWidget
+ * and autocompletes with available categories.
+ *
+ * var selector = new mw.widgets.CategorySelector( {
+ * searchTypes: [
+ * mw.widgets.CategorySelector.SearchType.OpenSearch,
+ * mw.widgets.CategorySelector.SearchType.InternalSearch
+ * ]
+ * } );
+ *
+ * $( '#content' ).append( selector.$element );
+ *
+ * selector.setSearchTypes( [ mw.widgets.CategorySelector.SearchType.SubCategories ] );
+ *
+ * @class mw.widgets.CategorySelector
+ * @uses mw.Api
+ * @extends OO.ui.CapsuleMultiSelectWidget
+ * @mixins OO.ui.mixin.PendingElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {mw.Api} [api] Instance of mw.Api (or subclass thereof) to use for queries
+ * @cfg {number} [limit=10] Maximum number of results to load
+ * @cfg {mw.widgets.CategorySelector.SearchType[]} [searchTypes=[mw.widgets.CategorySelector.SearchType.OpenSearch]]
+ * Default search API to use when searching.
+ */
+ function CategorySelector( config ) {
+ // Config initialization
+ config = $.extend( {
+ limit: 10,
+ searchTypes: [ CategorySelector.SearchType.OpenSearch ]
+ }, config );
+ this.limit = config.limit;
+ this.searchTypes = config.searchTypes;
+ this.validateSearchTypes();
+
+ // Parent constructor
+ mw.widgets.CategorySelector.parent.call( this, $.extend( true, {}, config, {
+ menu: {
+ filterFromInput: false
+ },
+ // This allows the user to both select non-existent categories, and prevents the selector from
+ // being wiped from #onMenuItemsChange when we change the available options in the dropdown
+ allowArbitrary: true
+ } ) );
+
+ // Mixin constructors
+ OO.ui.mixin.PendingElement.call( this, $.extend( {}, config, { $pending: this.$handle } ) );
+
+ // Event handler to call the autocomplete methods
+ this.$input.on( 'change input cut paste', OO.ui.debounce( this.updateMenuItems.bind( this ), 100 ) );
+
+ // Initialize
+ this.api = config.api || new mw.Api();
+ }
+
+ /* Setup */
+
+ OO.inheritClass( CategorySelector, OO.ui.CapsuleMultiSelectWidget );
+ OO.mixinClass( CategorySelector, OO.ui.mixin.PendingElement );
+ CSP = CategorySelector.prototype;
+
+ /* Methods */
+
+ /**
+ * Gets new items based on the input by calling
+ * {@link #getNewMenuItems getNewItems} and updates the menu
+ * after removing duplicates based on the data value.
+ *
+ * @private
+ * @method
+ */
+ CSP.updateMenuItems = function () {
+ this.getMenu().clearItems();
+ this.getNewMenuItems( this.$input.val() ).then( function ( items ) {
+ var existingItems, filteredItems,
+ menu = this.getMenu();
+
+ // Never show the menu if the input lost focus in the meantime
+ if ( !this.$input.is( ':focus' ) ) {
+ return;
+ }
+
+ // Array of strings of the data of OO.ui.MenuOptionsWidgets
+ existingItems = menu.getItems().map( function ( item ) {
+ return item.data;
+ } );
+
+ // Remove if items' data already exists
+ filteredItems = items.filter( function ( item ) {
+ return existingItems.indexOf( item ) === -1;
+ } );
+
+ // Map to an array of OO.ui.MenuOptionWidgets
+ filteredItems = filteredItems.map( function ( item ) {
+ return new OO.ui.MenuOptionWidget( {
+ data: item,
+ label: item
+ } );
+ } );
+
+ menu.addItems( filteredItems ).toggle( true );
+ }.bind( this ) );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ CSP.clearInput = function () {
+ CategorySelector.parent.prototype.clearInput.call( this );
+ // Abort all pending requests, we won't need their results
+ this.api.abort();
+ };
+
+ /**
+ * Searches for categories based on the input.
+ *
+ * @private
+ * @method
+ * @param {string} input The input used to prefix search categories
+ * @return {jQuery.Promise} Resolves with an array of categories
+ */
+ CSP.getNewMenuItems = function ( input ) {
+ var i,
+ promises = [],
+ deferred = $.Deferred();
+
+ if ( $.trim( input ) === '' ) {
+ deferred.resolve( [] );
+ return deferred.promise();
+ }
+
+ // Abort all pending requests, we won't need their results
+ this.api.abort();
+ for ( i = 0; i < this.searchTypes.length; i++ ) {
+ promises.push( this.searchCategories( input, this.searchTypes[ i ] ) );
+ }
+
+ this.pushPending();
+
+ $.when.apply( $, promises ).done( function () {
+ var categoryNames,
+ allData = [],
+ dataSets = Array.prototype.slice.apply( arguments );
+
+ // Collect values from all results
+ allData = allData.concat.apply( allData, dataSets );
+
+ categoryNames = allData
+ // Remove duplicates
+ .filter( function ( value, index, self ) {
+ return self.indexOf( value ) === index;
+ } )
+ // Get Title objects
+ .map( function ( name ) {
+ return mw.Title.newFromText( name );
+ } )
+ // Keep only titles from 'Category' namespace
+ .filter( function ( title ) {
+ return title && title.getNamespaceId() === NS_CATEGORY;
+ } )
+ // Convert back to strings, strip 'Category:' prefix
+ .map( function ( title ) {
+ return title.getMainText();
+ } );
+
+ deferred.resolve( categoryNames );
+
+ } ).always( this.popPending.bind( this ) );
+
+ return deferred.promise();
+ };
+
+ /**
+ * @inheritdoc
+ */
+ CSP.createItemWidget = function ( data ) {
+ return new mw.widgets.CategoryCapsuleItemWidget( {
+ apiUrl: this.api.apiUrl || undefined,
+ title: mw.Title.makeTitle( NS_CATEGORY, data )
+ } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ CSP.getItemFromData = function ( data ) {
+ // This is a bit of a hack... We have to canonicalize the data in the same way that
+ // #createItemWidget and CategoryCapsuleItemWidget will do, otherwise we won't find duplicates.
+ data = mw.Title.makeTitle( NS_CATEGORY, data ).getMainText();
+ return OO.ui.mixin.GroupElement.prototype.getItemFromData.call( this, data );
+ };
+
+ /**
+ * Validates the values in `this.searchType`.
+ *
+ * @private
+ * @return {boolean}
+ */
+ CSP.validateSearchTypes = function () {
+ var validSearchTypes = false,
+ searchTypeEnumCount = Object.keys( CategorySelector.SearchType ).length;
+
+ // Check if all values are in the SearchType enum
+ validSearchTypes = this.searchTypes.every( function ( searchType ) {
+ return searchType > -1 && searchType < searchTypeEnumCount;
+ } );
+
+ if ( validSearchTypes === false ) {
+ throw new Error( 'Unknown searchType in searchTypes' );
+ }
+
+ // If the searchTypes has CategorySelector.SearchType.SubCategories
+ // it can be the only search type.
+ if ( this.searchTypes.indexOf( CategorySelector.SearchType.SubCategories ) > -1 &&
+ this.searchTypes.length > 1
+ ) {
+ throw new Error( 'Can\'t have additional search types with CategorySelector.SearchType.SubCategories' );
+ }
+
+ // If the searchTypes has CategorySelector.SearchType.ParentCategories
+ // it can be the only search type.
+ if ( this.searchTypes.indexOf( CategorySelector.SearchType.ParentCategories ) > -1 &&
+ this.searchTypes.length > 1
+ ) {
+ throw new Error( 'Can\'t have additional search types with CategorySelector.SearchType.ParentCategories' );
+ }
+
+ return true;
+ };
+
+ /**
+ * Sets and validates the value of `this.searchType`.
+ *
+ * @param {mw.widgets.CategorySelector.SearchType[]} searchTypes
+ */
+ CSP.setSearchTypes = function ( searchTypes ) {
+ this.searchTypes = searchTypes;
+ this.validateSearchTypes();
+ };
+
+ /**
+ * Searches categories based on input and searchType.
+ *
+ * @private
+ * @method
+ * @param {string} input The input used to prefix search categories
+ * @param {mw.widgets.CategorySelector.SearchType} searchType
+ * @return {jQuery.Promise} Resolves with an array of categories
+ */
+ CSP.searchCategories = function ( input, searchType ) {
+ var deferred = $.Deferred();
+
+ switch ( searchType ) {
+ case CategorySelector.SearchType.OpenSearch:
+ this.api.get( {
+ formatversion: 2,
+ action: 'opensearch',
+ namespace: NS_CATEGORY,
+ limit: this.limit,
+ search: input
+ } ).done( function ( res ) {
+ var categories = res[ 1 ];
+ deferred.resolve( categories );
+ } ).fail( deferred.reject.bind( deferred ) );
+ break;
+
+ case CategorySelector.SearchType.InternalSearch:
+ this.api.get( {
+ formatversion: 2,
+ action: 'query',
+ list: 'allpages',
+ apnamespace: NS_CATEGORY,
+ aplimit: this.limit,
+ apfrom: input,
+ apprefix: input
+ } ).done( function ( res ) {
+ var categories = res.query.allpages.map( function ( page ) {
+ return page.title;
+ } );
+ deferred.resolve( categories );
+ } ).fail( deferred.reject.bind( deferred ) );
+ break;
+
+ case CategorySelector.SearchType.Exists:
+ if ( input.indexOf( '|' ) > -1 ) {
+ deferred.resolve( [] );
+ break;
+ }
+
+ this.api.get( {
+ formatversion: 2,
+ action: 'query',
+ prop: 'info',
+ titles: 'Category:' + input
+ } ).done( function ( res ) {
+ var categories = [];
+
+ $.each( res.query.pages, function ( index, page ) {
+ if ( !page.missing ) {
+ categories.push( page.title );
+ }
+ } );
+
+ deferred.resolve( categories );
+ } ).fail( deferred.reject.bind( deferred ) );
+ break;
+
+ case CategorySelector.SearchType.SubCategories:
+ if ( input.indexOf( '|' ) > -1 ) {
+ deferred.resolve( [] );
+ break;
+ }
+
+ this.api.get( {
+ formatversion: 2,
+ action: 'query',
+ list: 'categorymembers',
+ cmtype: 'subcat',
+ cmlimit: this.limit,
+ cmtitle: 'Category:' + input
+ } ).done( function ( res ) {
+ var categories = res.query.categorymembers.map( function ( category ) {
+ return category.title;
+ } );
+ deferred.resolve( categories );
+ } ).fail( deferred.reject.bind( deferred ) );
+ break;
+
+ case CategorySelector.SearchType.ParentCategories:
+ if ( input.indexOf( '|' ) > -1 ) {
+ deferred.resolve( [] );
+ break;
+ }
+
+ this.api.get( {
+ formatversion: 2,
+ action: 'query',
+ prop: 'categories',
+ cllimit: this.limit,
+ titles: 'Category:' + input
+ } ).done( function ( res ) {
+ var categories = [];
+
+ $.each( res.query.pages, function ( index, page ) {
+ if ( !page.missing ) {
+ if ( $.isArray( page.categories ) ) {
+ categories.push.apply( categories, page.categories.map( function ( category ) {
+ return category.title;
+ } ) );
+ }
+ }
+ } );
+
+ deferred.resolve( categories );
+ } ).fail( deferred.reject.bind( deferred ) );
+ break;
+
+ default:
+ throw new Error( 'Unknown searchType' );
+ }
+
+ return deferred.promise();
+ };
+
+ /**
+ * @enum mw.widgets.CategorySelector.SearchType
+ * Types of search available.
+ */
+ CategorySelector.SearchType = {
+ /** Search using action=opensearch */
+ OpenSearch: 0,
+
+ /** Search using action=query */
+ InternalSearch: 1,
+
+ /** Search for existing categories with the exact title */
+ Exists: 2,
+
+ /** Search only subcategories */
+ SubCategories: 3,
+
+ /** Search only parent categories */
+ ParentCategories: 4
+ };
+
+ mw.widgets.CategorySelector = CategorySelector;
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexNamespaceInputWidget.base.css b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexNamespaceInputWidget.base.css
new file mode 100644
index 00000000..b60883e9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexNamespaceInputWidget.base.css
@@ -0,0 +1,26 @@
+/*!
+ * MediaWiki Widgets - base ComplexNamespaceInputWidget styles.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+.mw-widget-complexNamespaceInputWidget .mw-widget-namespaceInputWidget,
+.mw-widget-complexNamespaceInputWidget .oo-ui-fieldLayout {
+ display: inline-block;
+ margin-right: 1em;
+}
+
+/* TODO FieldLayout is not supposed to be used the way we use it here */
+.mw-widget-complexNamespaceInputWidget .oo-ui-fieldLayout {
+ vertical-align: middle;
+ margin-bottom: 0;
+}
+
+.mw-widget-complexNamespaceInputWidget .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline.oo-ui-labelElement > .oo-ui-fieldLayout-body > .oo-ui-labelElement-label {
+ padding-left: 0.5em;
+}
+
+.mw-widget-complexNamespaceInputWidget .mw-widget-namespaceInputWidget {
+ max-width: 20em;
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexNamespaceInputWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexNamespaceInputWidget.js
new file mode 100644
index 00000000..9edd0bd9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexNamespaceInputWidget.js
@@ -0,0 +1,136 @@
+/*!
+ * MediaWiki Widgets - ComplexNamespaceInputWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Namespace input widget. Displays a dropdown box with the choice of available namespaces, plus
+ * two checkboxes to include associated namespace or to invert selection.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} namespace Configuration for the NamespaceInputWidget dropdown with list
+ * of namespaces
+ * @cfg {string} namespace.includeAllValue If specified, add a "all namespaces"
+ * option to the dropdown, and use this as the input value for it
+ * @cfg {Object} invert Configuration for the "invert selection" CheckboxInputWidget. If
+ * null, the checkbox will not be generated.
+ * @cfg {Object} associated Configuration for the "include associated namespace"
+ * CheckboxInputWidget. If null, the checkbox will not be generated.
+ * @cfg {Object} invertLabel Configuration for the FieldLayout with label wrapping the
+ * "invert selection" checkbox
+ * @cfg {string} invertLabel.label Label text for the label
+ * @cfg {Object} associatedLabel Configuration for the FieldLayout with label wrapping
+ * the "include associated namespace" checkbox
+ * @cfg {string} associatedLabel.label Label text for the label
+ */
+ mw.widgets.ComplexNamespaceInputWidget = function MwWidgetsComplexNamespaceInputWidget( config ) {
+ // Configuration initialization
+ config = $.extend(
+ {
+ // Config options for nested widgets
+ namespace: {},
+ invert: {},
+ invertLabel: {},
+ associated: {},
+ associatedLabel: {}
+ },
+ config
+ );
+
+ // Parent constructor
+ mw.widgets.ComplexNamespaceInputWidget.parent.call( this, config );
+
+ // Properties
+ this.config = config;
+
+ this.namespace = new mw.widgets.NamespaceInputWidget( config.namespace );
+ if ( config.associated !== null ) {
+ this.associated = new OO.ui.CheckboxInputWidget( $.extend(
+ { value: '1' },
+ config.associated
+ ) );
+ // TODO Should use a LabelWidget? But they don't work like HTML <label>s yet
+ this.associatedLabel = new OO.ui.FieldLayout(
+ this.associated,
+ $.extend(
+ { align: 'inline' },
+ config.associatedLabel
+ )
+ );
+ }
+ if ( config.invert !== null ) {
+ this.invert = new OO.ui.CheckboxInputWidget( $.extend(
+ { value: '1' },
+ config.invert
+ ) );
+ // TODO Should use a LabelWidget? But they don't work like HTML <label>s yet
+ this.invertLabel = new OO.ui.FieldLayout(
+ this.invert,
+ $.extend(
+ { align: 'inline' },
+ config.invertLabel
+ )
+ );
+ }
+
+ // Events
+ this.namespace.connect( this, { change: 'updateCheckboxesState' } );
+
+ // Initialization
+ this.$element
+ .addClass( 'mw-widget-complexNamespaceInputWidget' )
+ .append(
+ this.namespace.$element,
+ this.invert ? this.invertLabel.$element : '',
+ this.associated ? this.associatedLabel.$element : ''
+ );
+ this.updateCheckboxesState();
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.ComplexNamespaceInputWidget, OO.ui.Widget );
+
+ /* Methods */
+
+ /**
+ * Update the disabled state of checkboxes when the value of namespace dropdown changes.
+ *
+ * @private
+ */
+ mw.widgets.ComplexNamespaceInputWidget.prototype.updateCheckboxesState = function () {
+ var disabled = this.namespace.getValue() === this.namespace.allValue;
+ if ( this.invert ) {
+ this.invert.setDisabled( disabled );
+ }
+ if ( this.associated ) {
+ this.associated.setDisabled( disabled );
+ }
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.ComplexNamespaceInputWidget.prototype.setDisabled = function ( disabled ) {
+ mw.widgets.ComplexNamespaceInputWidget.parent.prototype.setDisabled.call( this, disabled );
+ if ( this.namespace ) {
+ this.namespace.setDisabled( disabled );
+ }
+ if ( this.invert ) {
+ this.invert.setDisabled( disabled );
+ }
+
+ if ( this.associated ) {
+ this.associated.setDisabled( disabled );
+ }
+ return this;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.base.css b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.base.css
new file mode 100644
index 00000000..73a50d8f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.base.css
@@ -0,0 +1,20 @@
+/*!
+ * MediaWiki Widgets - base ComplexTitleInputWidget styles.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+.mw-widget-complexTitleInputWidget .mw-widget-namespaceInputWidget,
+.mw-widget-complexTitleInputWidget .mw-widget-titleInputWidget {
+ display: inline-block;
+}
+
+.mw-widget-complexTitleInputWidget .mw-widget-namespaceInputWidget {
+ max-width: 20em;
+ margin-right: 0.5em;
+}
+
+.mw-widget-complexTitleInputWidget .mw-widget-titleInputWidget {
+ max-width: 29.5em;
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.js
new file mode 100644
index 00000000..a01fbde1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.ComplexTitleInputWidget.js
@@ -0,0 +1,121 @@
+/*!
+ * MediaWiki Widgets - ComplexTitleInputWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Like TitleInputWidget, but the namespace has to be input through a separate dropdown field.
+ *
+ * @class
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} namespace Configuration for the NamespaceInputWidget dropdown with list of
+ * namespaces
+ * @cfg {Object} title Configuration for the TitleInputWidget text field
+ */
+ mw.widgets.ComplexTitleInputWidget = function MwWidgetsComplexTitleInputWidget( config ) {
+ // Parent constructor
+ mw.widgets.ComplexTitleInputWidget.parent.call( this, config );
+
+ // Properties
+ this.namespace = new mw.widgets.NamespaceInputWidget( config.namespace );
+ this.title = new mw.widgets.TitleInputWidget( $.extend(
+ {},
+ config.title,
+ {
+ relative: true,
+ namespace: config.namespace.value || null
+ }
+ ) );
+
+ // Events
+ this.namespace.connect( this, { change: 'updateTitleNamespace' } );
+
+ // Initialization
+ this.$element
+ .addClass( 'mw-widget-complexTitleInputWidget' )
+ .append(
+ this.namespace.$element,
+ this.title.$element
+ );
+ this.updateTitleNamespace();
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.ComplexTitleInputWidget, OO.ui.Widget );
+
+ /* Static Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.ComplexTitleInputWidget.static.reusePreInfuseDOM = function ( node, config ) {
+ config = mw.widgets.ComplexTitleInputWidget.parent.static.reusePreInfuseDOM( node, config );
+ config.namespace = mw.widgets.NamespaceInputWidget.static.reusePreInfuseDOM(
+ $( node ).find( '.mw-widget-namespaceInputWidget' ),
+ config.namespace
+ );
+ config.title = mw.widgets.TitleInputWidget.static.reusePreInfuseDOM(
+ $( node ).find( '.mw-widget-titleInputWidget' ),
+ config.title
+ );
+ return config;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.ComplexTitleInputWidget.static.gatherPreInfuseState = function ( node, config ) {
+ var state = mw.widgets.ComplexTitleInputWidget.parent.static.gatherPreInfuseState( node, config );
+ state.namespace = mw.widgets.NamespaceInputWidget.static.gatherPreInfuseState(
+ $( node ).find( '.mw-widget-namespaceInputWidget' ),
+ config.namespace
+ );
+ state.title = mw.widgets.TitleInputWidget.static.gatherPreInfuseState(
+ $( node ).find( '.mw-widget-titleInputWidget' ),
+ config.title
+ );
+ return state;
+ };
+
+ /* Methods */
+
+ /**
+ * Update the namespace to use for search suggestions of the title when the value of namespace
+ * dropdown changes.
+ */
+ mw.widgets.ComplexTitleInputWidget.prototype.updateTitleNamespace = function () {
+ this.title.setNamespace( Number( this.namespace.getValue() ) );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.ComplexTitleInputWidget.prototype.restorePreInfuseState = function ( state ) {
+ mw.widgets.ComplexTitleInputWidget.parent.prototype.restorePreInfuseState.call( this, state );
+ this.namespace.restorePreInfuseState( state.namespace );
+ this.title.restorePreInfuseState( state.title );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.ComplexTitleInputWidget.prototype.setDisabled = function ( disabled ) {
+ mw.widgets.ComplexTitleInputWidget.parent.prototype.setDisabled.call( this, disabled );
+ if ( this.namespace ) {
+ this.namespace.setDisabled( disabled );
+ }
+
+ if ( this.title ) {
+ this.title.setDisabled( disabled );
+ }
+ return this;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js
new file mode 100644
index 00000000..f10c93db
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.js
@@ -0,0 +1,697 @@
+/*!
+ * MediaWiki Widgets – DateInputWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+/* global moment */
+( function ( $, mw ) {
+
+ /**
+ * Creates an mw.widgets.DateInputWidget object.
+ *
+ * @example
+ * // Date input widget showcase
+ * var fieldset = new OO.ui.FieldsetLayout( {
+ * items: [
+ * new OO.ui.FieldLayout(
+ * new mw.widgets.DateInputWidget(),
+ * {
+ * align: 'top',
+ * label: 'Select date'
+ * }
+ * ),
+ * new OO.ui.FieldLayout(
+ * new mw.widgets.DateInputWidget( { precision: 'month' } ),
+ * {
+ * align: 'top',
+ * label: 'Select month'
+ * }
+ * ),
+ * new OO.ui.FieldLayout(
+ * new mw.widgets.DateInputWidget( {
+ * inputFormat: 'DD.MM.YYYY',
+ * displayFormat: 'Do [of] MMMM [anno Domini] YYYY'
+ * } ),
+ * {
+ * align: 'top',
+ * label: 'Select date (custom formats)'
+ * }
+ * )
+ * ]
+ * } );
+ * $( 'body' ).append( fieldset.$element );
+ *
+ * The value is stored in 'YYYY-MM-DD' or 'YYYY-MM' format:
+ *
+ * @example
+ * // Accessing values in a date input widget
+ * var dateInput = new mw.widgets.DateInputWidget();
+ * var $label = $( '<p>' );
+ * $( 'body' ).append( $label, dateInput.$element );
+ * dateInput.on( 'change', function () {
+ * // The value will always be a valid date or empty string, malformed input is ignored
+ * var date = dateInput.getValue();
+ * $label.text( 'Selected date: ' + ( date || '(none)' ) );
+ * } );
+ *
+ * @class
+ * @extends OO.ui.TextInputWidget
+ * @mixins OO.ui.mixin.IndicatorElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string} [precision='day'] Date precision to use, 'day' or 'month'
+ * @cfg {string} [value] Day or month date (depending on `precision`), in the format 'YYYY-MM-DD'
+ * or 'YYYY-MM'. If not given or empty string, no date is selected.
+ * @cfg {string} [inputFormat] Date format string to use for the textual input field. Displayed
+ * while the widget is active, and the user can type in a date in this format. Should be short
+ * and easy to type. When not given, defaults to 'YYYY-MM-DD' or 'YYYY-MM', depending on
+ * `precision`.
+ * @cfg {string} [displayFormat] Date format string to use for the clickable label. Displayed
+ * while the widget is inactive. Should be as unambiguous as possible (for example, prefer to
+ * spell out the month, rather than rely on the order), even if that makes it longer. When not
+ * given, the default is language-specific.
+ * @cfg {boolean} [longDisplayFormat=false] If a custom displayFormat is not specified, use
+ * unabbreviated day of the week and month names in the default language-specific displayFormat.
+ * @cfg {string} [placeholderLabel=No date selected] Placeholder text shown when the widget is not
+ * selected. Default text taken from message `mw-widgets-dateinput-no-date`.
+ * @cfg {string} [placeholderDateFormat] User-visible date format string displayed in the textual input
+ * field when it's empty. Should be the same as `inputFormat`, but translated to the user's
+ * language. When not given, defaults to a translated version of 'YYYY-MM-DD' or 'YYYY-MM',
+ * depending on `precision`.
+ * @cfg {boolean} [required=false] Mark the field as required. Implies `indicator: 'required'`.
+ * @cfg {string} [mustBeAfter] Validates the date to be after this. In the 'YYYY-MM-DD' format.
+ * @cfg {string} [mustBeBefore] Validates the date to be before this. In the 'YYYY-MM-DD' format.
+ * @cfg {jQuery} [$overlay] Render the calendar into a separate layer. This configuration is
+ * useful in cases where the expanded calendar is larger than its container. The specified
+ * overlay layer is usually on top of the container and has a larger area. By default, the
+ * calendar uses relative positioning.
+ */
+ mw.widgets.DateInputWidget = function MWWDateInputWidget( config ) {
+ var placeholderDateFormat, mustBeAfter, mustBeBefore;
+
+ // Config initialization
+ config = $.extend( {
+ precision: 'day',
+ longDisplayFormat: false,
+ required: false,
+ placeholderLabel: mw.msg( 'mw-widgets-dateinput-no-date' )
+ }, config );
+ if ( config.required ) {
+ if ( config.indicator === undefined ) {
+ config.indicator = 'required';
+ }
+ }
+
+ if ( config.placeholderDateFormat ) {
+ placeholderDateFormat = config.placeholderDateFormat;
+ } else if ( config.inputFormat ) {
+ // We have no way to display a translated placeholder for custom formats
+ placeholderDateFormat = '';
+ } else {
+ // Messages: mw-widgets-dateinput-placeholder-day, mw-widgets-dateinput-placeholder-month
+ placeholderDateFormat = mw.msg( 'mw-widgets-dateinput-placeholder-' + config.precision );
+ }
+
+ // Properties (must be set before parent constructor, which calls #setValue)
+ this.$handle = $( '<div>' );
+ this.innerLabel = new OO.ui.LabelWidget();
+ this.textInput = new OO.ui.TextInputWidget( {
+ required: config.required,
+ placeholder: placeholderDateFormat,
+ validate: this.validateDate.bind( this )
+ } );
+ this.calendar = new mw.widgets.CalendarWidget( {
+ lazyInitOnToggle: true,
+ // Can't pass `$floatableContainer: this.$element` here, the latter is not set yet.
+ // Instead we call setFloatableContainer() below.
+ precision: config.precision
+ } );
+ this.inCalendar = 0;
+ this.inTextInput = 0;
+ this.closing = false;
+ this.inputFormat = config.inputFormat;
+ this.displayFormat = config.displayFormat;
+ this.longDisplayFormat = config.longDisplayFormat;
+ this.required = config.required;
+ this.placeholderLabel = config.placeholderLabel;
+ // Validate and set min and max dates as properties
+
+ if ( config.mustBeAfter !== undefined ) {
+ mustBeAfter = moment( config.mustBeAfter, 'YYYY-MM-DD' );
+ if ( mustBeAfter.isValid() ) {
+ this.mustBeAfter = mustBeAfter;
+ }
+ }
+ if ( config.mustBeBefore !== undefined ) {
+ mustBeBefore = moment( config.mustBeBefore, 'YYYY-MM-DD' );
+ if ( mustBeBefore.isValid() ) {
+ this.mustBeBefore = mustBeBefore;
+ }
+ }
+ // Parent constructor
+ mw.widgets.DateInputWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.IndicatorElement.call( this, config );
+
+ // Events
+ this.calendar.connect( this, {
+ change: 'onCalendarChange'
+ } );
+ this.textInput.connect( this, {
+ enter: 'onEnter',
+ change: 'onTextInputChange'
+ } );
+ this.$element.on( {
+ focusout: this.onBlur.bind( this )
+ } );
+ this.calendar.$element.on( {
+ click: this.onCalendarClick.bind( this ),
+ keypress: this.onCalendarKeyPress.bind( this )
+ } );
+ this.$handle.on( {
+ click: this.onClick.bind( this ),
+ keypress: this.onKeyPress.bind( this ),
+ focus: this.onFocus.bind( this )
+ } );
+
+ // Initialization
+ // Move 'tabindex' from this.$input (which is invisible) to the visible handle
+ this.setTabIndexedElement( this.$handle );
+ this.$handle
+ .append( this.innerLabel.$element, this.$indicator )
+ .addClass( 'mw-widget-dateInputWidget-handle' );
+ this.calendar.$element
+ .addClass( 'mw-widget-dateInputWidget-calendar' );
+ this.$element
+ .addClass( 'mw-widget-dateInputWidget' )
+ .append( this.$handle, this.textInput.$element, this.calendar.$element );
+
+ // config.overlay is the selector to be used for config.$overlay, specified from PHP
+ if ( config.overlay ) {
+ config.$overlay = $( config.overlay );
+ }
+
+ if ( config.$overlay ) {
+ this.calendar.setFloatableContainer( this.$element );
+ config.$overlay.append( this.calendar.$element );
+
+ // The text input and calendar are not in DOM order, so fix up focus transitions.
+ this.textInput.$input.on( 'keydown', function ( e ) {
+ if ( e.which === OO.ui.Keys.TAB ) {
+ if ( e.shiftKey ) {
+ // Tabbing backward from text input: normal browser behavior
+ $.noop();
+ } else {
+ // Tabbing forward from text input: just focus the calendar
+ this.calendar.$element.focus();
+ return false;
+ }
+ }
+ }.bind( this ) );
+ this.calendar.$element.on( 'keydown', function ( e ) {
+ if ( e.which === OO.ui.Keys.TAB ) {
+ if ( e.shiftKey ) {
+ // Tabbing backward from calendar: just focus the text input
+ this.textInput.$input.focus();
+ return false;
+ } else {
+ // Tabbing forward from calendar: focus the text input, then allow normal browser
+ // behavior to move focus to next focusable after it
+ this.textInput.$input.focus();
+ }
+ }
+ }.bind( this ) );
+ }
+
+ // Set handle label and hide stuff
+ this.updateUI();
+ this.textInput.toggle( false );
+ this.calendar.toggle( false );
+
+ // Hide unused <input> from PHP after infusion is done
+ // See InputWidget#reusePreInfuseDOM about config.$input
+ if ( config.$input ) {
+ config.$input.addClass( 'oo-ui-element-hidden' );
+ }
+ };
+
+ /* Inheritance */
+
+ OO.inheritClass( mw.widgets.DateInputWidget, OO.ui.TextInputWidget );
+ OO.mixinClass( mw.widgets.DateInputWidget, OO.ui.mixin.IndicatorElement );
+
+ /* Events */
+
+ /**
+ * Fired when the widget is deactivated (i.e. the calendar is closed). This can happen because
+ * the user selected a value, or because the user blurred the widget.
+ *
+ * @event deactivate
+ * @param {boolean} userSelected Whether the deactivation happened because the user selected a value
+ */
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ * @protected
+ */
+ mw.widgets.DateInputWidget.prototype.getInputElement = function () {
+ return $( '<input>' ).attr( 'type', 'hidden' );
+ };
+
+ /**
+ * Respond to calendar date change events.
+ *
+ * @private
+ */
+ mw.widgets.DateInputWidget.prototype.onCalendarChange = function () {
+ this.inCalendar++;
+ if ( !this.inTextInput ) {
+ // If this is caused by user typing in the input field, do not set anything.
+ // The value may be invalid (see #onTextInputChange), but displayable on the calendar.
+ this.setValue( this.calendar.getDate() );
+ }
+ this.inCalendar--;
+ };
+
+ /**
+ * Respond to text input value change events.
+ *
+ * @private
+ */
+ mw.widgets.DateInputWidget.prototype.onTextInputChange = function () {
+ var mom,
+ widget = this,
+ value = this.textInput.getValue(),
+ valid = this.isValidDate( value );
+ this.inTextInput++;
+
+ if ( value === '' ) {
+ // No date selected
+ widget.setValue( '' );
+ } else if ( valid ) {
+ // Well-formed date value, parse and set it
+ mom = moment( value, widget.getInputFormat() );
+ // Use English locale to avoid number formatting
+ widget.setValue( mom.locale( 'en' ).format( widget.getInternalFormat() ) );
+ } else {
+ // Not well-formed, but possibly partial? Try updating the calendar, but do not set the
+ // internal value. Generally this only makes sense when 'inputFormat' is little-endian (e.g.
+ // 'YYYY-MM-DD'), but that's hard to check for, and might be difficult to handle the parsing
+ // right for weird formats. So limit this trick to only when we're using the default
+ // 'inputFormat', which is the same as the internal format, 'YYYY-MM-DD'.
+ if ( widget.getInputFormat() === widget.getInternalFormat() ) {
+ widget.calendar.setDate( widget.textInput.getValue() );
+ }
+ }
+ widget.inTextInput--;
+
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.DateInputWidget.prototype.setValue = function ( value ) {
+ var oldValue = this.value;
+
+ if ( !moment( value, this.getInternalFormat() ).isValid() ) {
+ value = '';
+ }
+
+ mw.widgets.DateInputWidget.parent.prototype.setValue.call( this, value );
+
+ if ( this.value !== oldValue ) {
+ this.updateUI();
+ this.setValidityFlag();
+ }
+
+ return this;
+ };
+
+ /**
+ * Handle text input and calendar blur events.
+ *
+ * @private
+ */
+ mw.widgets.DateInputWidget.prototype.onBlur = function () {
+ var widget = this;
+ setTimeout( function () {
+ var $focussed = $( ':focus' );
+ // Deactivate unless the focus moved to something else inside this widget
+ if (
+ !OO.ui.contains( widget.$element[ 0 ], $focussed[ 0 ], true ) &&
+ // Calendar might be in an $overlay
+ !OO.ui.contains( widget.calendar.$element[ 0 ], $focussed[ 0 ], true )
+ ) {
+ widget.deactivate();
+ }
+ }, 0 );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.DateInputWidget.prototype.focus = function () {
+ this.activate();
+ return this;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.DateInputWidget.prototype.blur = function () {
+ this.deactivate();
+ return this;
+ };
+
+ /**
+ * Update the contents of the label, text input and status of calendar to reflect selected value.
+ *
+ * @private
+ */
+ mw.widgets.DateInputWidget.prototype.updateUI = function () {
+ var moment;
+ if ( this.getValue() === '' ) {
+ this.textInput.setValue( '' );
+ this.calendar.setDate( null );
+ this.innerLabel.setLabel( this.placeholderLabel );
+ this.$element.addClass( 'mw-widget-dateInputWidget-empty' );
+ } else {
+ moment = this.getMoment();
+ if ( !this.inTextInput ) {
+ this.textInput.setValue( moment.format( this.getInputFormat() ) );
+ }
+ if ( !this.inCalendar ) {
+ this.calendar.setDate( this.getValue() );
+ }
+ this.innerLabel.setLabel( moment.format( this.getDisplayFormat() ) );
+ this.$element.removeClass( 'mw-widget-dateInputWidget-empty' );
+ }
+ };
+
+ /**
+ * Deactivate this input field for data entry. Closes the calendar and hides the text field.
+ *
+ * @private
+ * @param {boolean} [userSelected] Whether we are deactivating because the user selected a value
+ */
+ mw.widgets.DateInputWidget.prototype.deactivate = function ( userSelected ) {
+ this.$element.removeClass( 'mw-widget-dateInputWidget-active' );
+ this.$handle.show();
+ this.textInput.toggle( false );
+ this.calendar.toggle( false );
+ this.setValidityFlag();
+
+ if ( userSelected ) {
+ // Prevent focusing the handle from reopening the calendar
+ this.closing = true;
+ this.$handle.focus();
+ this.closing = false;
+ }
+
+ this.emit( 'deactivate', !!userSelected );
+ };
+
+ /**
+ * Activate this input field for data entry. Opens the calendar and shows the text field.
+ *
+ * @private
+ */
+ mw.widgets.DateInputWidget.prototype.activate = function () {
+ this.calendar.resetUI();
+ this.$element.addClass( 'mw-widget-dateInputWidget-active' );
+ this.$handle.hide();
+ this.textInput.toggle( true );
+ this.calendar.toggle( true );
+
+ this.textInput.$input.focus();
+ };
+
+ /**
+ * Get the date format to be used for handle label when the input is inactive.
+ *
+ * @private
+ * @return {string} Format string
+ */
+ mw.widgets.DateInputWidget.prototype.getDisplayFormat = function () {
+ var localeData, llll, lll, ll, format;
+
+ if ( this.displayFormat !== undefined ) {
+ return this.displayFormat;
+ }
+
+ if ( this.calendar.getPrecision() === 'month' ) {
+ return 'MMMM YYYY';
+ } else {
+ // The formats Moment.js provides:
+ // * ll: Month name, day of month, year
+ // * lll: Month name, day of month, year, time
+ // * llll: Month name, day of month, day of week, year, time
+ //
+ // The format we want:
+ // * ????: Month name, day of month, day of week, year
+ //
+ // We try to construct it as 'llll - (lll - ll)' and hope for the best.
+ // This seems to work well for many languages (maybe even all?).
+
+ localeData = moment.localeData( moment.locale() );
+ llll = localeData.longDateFormat( 'llll' );
+ lll = localeData.longDateFormat( 'lll' );
+ ll = localeData.longDateFormat( 'll' );
+ format = llll.replace( lll.replace( ll, '' ), '' );
+
+ if ( this.longDisplayFormat ) {
+ format = format.replace( 'MMM', 'MMMM' ).replace( 'ddd', 'dddd' );
+ }
+
+ return format;
+ }
+ };
+
+ /**
+ * Get the date format to be used for the text field when the input is active.
+ *
+ * @private
+ * @return {string} Format string
+ */
+ mw.widgets.DateInputWidget.prototype.getInputFormat = function () {
+ if ( this.inputFormat !== undefined ) {
+ return this.inputFormat;
+ }
+
+ return {
+ day: 'YYYY-MM-DD',
+ month: 'YYYY-MM'
+ }[ this.calendar.getPrecision() ];
+ };
+
+ /**
+ * Get the date format to be used internally for the value. This is not configurable in any way,
+ * and always either 'YYYY-MM-DD' or 'YYYY-MM'.
+ *
+ * @private
+ * @return {string} Format string
+ */
+ mw.widgets.DateInputWidget.prototype.getInternalFormat = function () {
+ return {
+ day: 'YYYY-MM-DD',
+ month: 'YYYY-MM'
+ }[ this.calendar.getPrecision() ];
+ };
+
+ /**
+ * Get the Moment object for current value.
+ *
+ * @return {Object} Moment object
+ */
+ mw.widgets.DateInputWidget.prototype.getMoment = function () {
+ return moment( this.getValue(), this.getInternalFormat() );
+ };
+
+ /**
+ * Handle mouse click events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse click event
+ * @return {boolean} False to cancel the default event
+ */
+ mw.widgets.DateInputWidget.prototype.onClick = function ( e ) {
+ if ( !this.isDisabled() && e.which === 1 ) {
+ this.activate();
+ }
+ return false;
+ };
+
+ /**
+ * Handle key press events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key press event
+ * @return {boolean} False to cancel the default event
+ */
+ mw.widgets.DateInputWidget.prototype.onKeyPress = function ( e ) {
+ if ( !this.isDisabled() &&
+ ( e.which === OO.ui.Keys.SPACE || e.which === OO.ui.Keys.ENTER )
+ ) {
+ this.activate();
+ return false;
+ }
+ };
+
+ /**
+ * Handle focus events.
+ *
+ * @private
+ */
+ mw.widgets.DateInputWidget.prototype.onFocus = function () {
+ if ( !this.closing ) {
+ this.activate();
+ }
+ };
+
+ /**
+ * Handle calendar key press events.
+ *
+ * @private
+ * @param {jQuery.Event} e Key press event
+ * @return {boolean} False to cancel the default event
+ */
+ mw.widgets.DateInputWidget.prototype.onCalendarKeyPress = function ( e ) {
+ if ( !this.isDisabled() && e.which === OO.ui.Keys.ENTER ) {
+ this.deactivate( true );
+ return false;
+ }
+ };
+
+ /**
+ * Handle calendar click events.
+ *
+ * @private
+ * @param {jQuery.Event} e Mouse click event
+ * @return {boolean} False to cancel the default event
+ */
+ mw.widgets.DateInputWidget.prototype.onCalendarClick = function ( e ) {
+ var targetClass = this.calendar.getPrecision() === 'month' ?
+ 'mw-widget-calendarWidget-month' :
+ 'mw-widget-calendarWidget-day';
+ if (
+ !this.isDisabled() &&
+ e.which === 1 &&
+ $( e.target ).hasClass( targetClass )
+ ) {
+ this.deactivate( true );
+ return false;
+ }
+ };
+
+ /**
+ * Handle text input enter events.
+ *
+ * @private
+ */
+ mw.widgets.DateInputWidget.prototype.onEnter = function () {
+ this.deactivate( true );
+ };
+
+ /**
+ * @private
+ * @param {string} date Date string, to be valid, must be in 'YYYY-MM-DD' or 'YYYY-MM' format or
+ * (unless the field is required) empty
+ * @return {boolean}
+ */
+ mw.widgets.DateInputWidget.prototype.validateDate = function ( date ) {
+ var isValid;
+ if ( date === '' ) {
+ isValid = !this.required;
+ } else {
+ isValid = this.isValidDate( date ) && this.isInRange( date );
+ }
+ return isValid;
+ };
+
+ /**
+ * @private
+ * @param {string} date Date string, to be valid, must be in 'YYYY-MM-DD' or 'YYYY-MM' format
+ * @return {boolean}
+ */
+ mw.widgets.DateInputWidget.prototype.isValidDate = function ( date ) {
+ // "Half-strict mode": for example, for the format 'YYYY-MM-DD', 2015-1-3 instead of 2015-01-03
+ // is okay, but 2015-01 isn't, and neither is 2015-01-foo. Use Moment's "fuzzy" mode and check
+ // parsing flags for the details (stolen from implementation of moment#isValid).
+ var
+ mom = moment( date, this.getInputFormat() ),
+ flags = mom.parsingFlags();
+
+ return mom.isValid() && flags.charsLeftOver === 0 && flags.unusedTokens.length === 0;
+ };
+
+ /**
+ * Validates if the date is within the range configured with {@link #cfg-mustBeAfter}
+ * and {@link #cfg-mustBeBefore}.
+ *
+ * @private
+ * @param {string} date Date string, to be valid, must be empty (no date selected) or in
+ * 'YYYY-MM-DD' or 'YYYY-MM' format to be valid
+ * @return {boolean}
+ */
+ mw.widgets.DateInputWidget.prototype.isInRange = function ( date ) {
+ var momentDate, isAfter, isBefore;
+ if ( this.mustBeAfter === undefined && this.mustBeBefore === undefined ) {
+ return true;
+ }
+ momentDate = moment( date, 'YYYY-MM-DD' );
+ isAfter = ( this.mustBeAfter === undefined || momentDate.isAfter( this.mustBeAfter ) );
+ isBefore = ( this.mustBeBefore === undefined || momentDate.isBefore( this.mustBeBefore ) );
+ return isAfter && isBefore;
+ };
+
+ /**
+ * Get the validity of current value.
+ *
+ * This method returns a promise that resolves if the value is valid and rejects if
+ * it isn't. Uses {@link #validateDate}.
+ *
+ * @return {jQuery.Promise} A promise that resolves if the value is valid, rejects if not.
+ */
+ mw.widgets.DateInputWidget.prototype.getValidity = function () {
+ var isValid = this.validateDate( this.getValue() );
+
+ if ( isValid ) {
+ return $.Deferred().resolve().promise();
+ } else {
+ return $.Deferred().reject().promise();
+ }
+ };
+
+ /**
+ * Sets the 'invalid' flag appropriately.
+ *
+ * @param {boolean} [isValid] Optionally override validation result
+ */
+ mw.widgets.DateInputWidget.prototype.setValidityFlag = function ( isValid ) {
+ var widget = this,
+ setFlag = function ( valid ) {
+ if ( !valid ) {
+ widget.$input.attr( 'aria-invalid', 'true' );
+ } else {
+ widget.$input.removeAttr( 'aria-invalid' );
+ }
+ widget.setFlags( { invalid: !valid } );
+ };
+
+ if ( isValid !== undefined ) {
+ setFlag( isValid );
+ } else {
+ this.getValidity().then( function () {
+ setFlag( true );
+ }, function () {
+ setFlag( false );
+ } );
+ }
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.less b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.less
new file mode 100644
index 00000000..47f80452
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.less
@@ -0,0 +1,95 @@
+/*!
+ * MediaWiki Widgets – JS DateInputWidget styles.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+.oo-ui-unselectable() {
+ -webkit-touch-callout: none;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+@indicator-size: unit( 12 / 16 / 0.8, em );
+
+.mw-widget-dateInputWidget {
+ &-handle {
+ .oo-ui-unselectable();
+
+ > .oo-ui-labelElement-label {
+ padding: 0;
+ }
+
+ > .oo-ui-indicatorElement-indicator {
+ display: none;
+ }
+ }
+
+ &.oo-ui-indicatorElement .mw-widget-dateInputWidget-handle > .oo-ui-indicatorElement-indicator {
+ display: block;
+ position: absolute;
+ top: 0;
+ right: 0;
+ width: @indicator-size;
+ height: 100%;
+ margin: 0 0.775em;
+ }
+
+ > .oo-ui-textInputWidget {
+ z-index: 2;
+
+ & input {
+ padding-left: 1em;
+ }
+ }
+
+ &-calendar {
+ background-color: #fff;
+ position: absolute;
+ margin-top: -2px;
+ box-shadow: 0 0.15em 0 0 rgba( 0, 0, 0, 0.15 );
+ z-index: 1;
+
+ &:focus {
+ box-shadow: inset 0 0 0 1px #36c, 0 0.15em 0 0 rgba( 0, 0, 0, 0.15 );
+ z-index: 3;
+ }
+ }
+
+ &-empty {
+ .mw-widget-dateInputWidget-handle {
+ color: #54595d;
+ outline: 0;
+ }
+ }
+
+ &.oo-ui-flaggedElement-invalid {
+ .mw-widget-dateInputWidget-handle {
+ border-color: #f00;
+ box-shadow: inset 0 0 0 0 #f00;
+ }
+ }
+
+ &.oo-ui-widget-enabled {
+ .mw-widget-dateInputWidget-handle:hover {
+ border-color: #72777d;
+ }
+ }
+
+ &.oo-ui-widget-disabled {
+ .mw-widget-dateInputWidget-handle {
+ background-color: #eaecf0;
+ color: #72777d;
+ border-color: #c8ccd1;
+ text-shadow: 0 1px 1px #fff;
+ cursor: default;
+
+ > .oo-ui-indicatorElement-indicator {
+ opacity: 0.51;
+ }
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.styles.less b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.styles.less
new file mode 100644
index 00000000..18cf7239
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.DateInputWidget.styles.less
@@ -0,0 +1,53 @@
+/*!
+ * MediaWiki Widgets – PHP DateInputWidget styles.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+.oo-ui-box-sizing( @type: border-box ) {
+ -webkit-box-sizing: @type;
+ -moz-box-sizing: @type;
+ box-sizing: @type;
+}
+
+.oo-ui-inline-spacing( @spacing, @cancelled-spacing: 0 ) {
+ margin-right: @spacing;
+
+ &:last-child {
+ margin-right: @cancelled-spacing;
+ }
+}
+
+.mw-widget-dateInputWidget {
+ &.oo-ui-textInputWidget {
+ display: inline-block;
+ position: relative;
+ width: 21em;
+ margin-top: 0.25em;
+ .oo-ui-inline-spacing( 0.5em );
+ margin-bottom: 0.25em;
+ margin-left: 0;
+ }
+
+ // Note that this block applies to both the PHP widget and the JS widget
+ &-handle,
+ &.oo-ui-textInputWidget input {
+ background-color: #fff;
+ display: inline-block;
+ position: relative;
+ .oo-ui-box-sizing( border-box );
+ width: 100%;
+ cursor: pointer;
+ padding: 0.5em 1em;
+ border: 1px solid #a2a9b1;
+ border-radius: 2px;
+ outline: 0;
+ line-height: 1.275;
+ /**
+ * Ensures non-infused and infused widget have the same height.
+ * Equal to line height + top padding + bottom padding
+ */
+ height: 2.275em;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.NamespaceInputWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.NamespaceInputWidget.js
new file mode 100644
index 00000000..aa0c739f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.NamespaceInputWidget.js
@@ -0,0 +1,71 @@
+/*!
+ * MediaWiki Widgets - NamespaceInputWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Namespace input widget. Displays a dropdown box with the choice of available namespaces.
+ *
+ * @class
+ * @extends OO.ui.DropdownInputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {string|null} [includeAllValue] Value for "all namespaces" option, if any
+ * @cfg {number[]} [exclude] List of namespace numbers to exclude from the selector
+ */
+ mw.widgets.NamespaceInputWidget = function MwWidgetsNamespaceInputWidget( config ) {
+ // Configuration initialization
+ config = $.extend( {}, config, { options: this.getNamespaceDropdownOptions( config ) } );
+
+ // Parent constructor
+ mw.widgets.NamespaceInputWidget.parent.call( this, config );
+
+ // Initialization
+ this.$element.addClass( 'mw-widget-namespaceInputWidget' );
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.NamespaceInputWidget, OO.ui.DropdownInputWidget );
+
+ /* Methods */
+
+ /**
+ * @private
+ * @param {Object} [config] Configuration options
+ * @return {Object[]} Dropdown options
+ */
+ mw.widgets.NamespaceInputWidget.prototype.getNamespaceDropdownOptions = function ( config ) {
+ var options,
+ exclude = config.exclude || [],
+ mainNamespace = mw.config.get( 'wgNamespaceIds' )[ '' ];
+
+ options = $.map( mw.config.get( 'wgFormattedNamespaces' ), function ( name, ns ) {
+ if ( ns < mainNamespace || exclude.indexOf( Number( ns ) ) !== -1 ) {
+ return null; // skip
+ }
+ ns = String( ns );
+ if ( ns === String( mainNamespace ) ) {
+ name = mw.message( 'blanknamespace' ).text();
+ }
+ return { data: ns, label: name };
+ } ).sort( function ( a, b ) {
+ // wgFormattedNamespaces is an object, and so technically doesn't have to be ordered
+ return a.data - b.data;
+ } );
+
+ if ( config.includeAllValue !== null && config.includeAllValue !== undefined ) {
+ options.unshift( {
+ data: config.includeAllValue,
+ label: mw.message( 'namespacesall' ).text()
+ } );
+ }
+
+ return options;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.css b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.css
new file mode 100644
index 00000000..3da5d318
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.css
@@ -0,0 +1,3 @@
+.mw-widget-searchInputWidget {
+ display: inline-block;
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js
new file mode 100644
index 00000000..08997aa4
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js
@@ -0,0 +1,258 @@
+/*!
+ * MediaWiki Widgets - SearchInputWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Creates a mw.widgets.SearchInputWidget object.
+ *
+ * @class
+ * @extends mw.widgets.TitleInputWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [pushPending=false] Visually mark the input field as "pending", while
+ * requesting suggestions.
+ * @cfg {boolean} [performSearchOnClick=true] If true, the script will start a search when-
+ * ever a user hits a suggestion. If false, the text of the suggestion is inserted into the
+ * text field only.
+ * @cfg {string} [dataLocation='header'] Where the search input field will be
+ * used (header or content).
+ */
+ mw.widgets.SearchInputWidget = function MwWidgetsSearchInputWidget( config ) {
+ // The parent constructors will detach this from the DOM, and won't
+ // be reattached until after this function is completed. As such
+ // grab a handle here. If no config.$input is passed tracking of
+ // form submissions won't work.
+ var $form = config.$input ? config.$input.closest( 'form' ) : $();
+
+ config = $.extend( {
+ icon: 'search',
+ maxLength: undefined,
+ performSearchOnClick: true,
+ dataLocation: 'header',
+ namespace: 0
+ }, config );
+
+ // Parent constructor
+ mw.widgets.SearchInputWidget.parent.call( this, config );
+
+ // Initialization
+ this.$element.addClass( 'mw-widget-searchInputWidget' );
+ this.lookupMenu.$element.addClass( 'mw-widget-searchWidget-menu' );
+ this.lastLookupItems = [];
+ if ( !config.pushPending ) {
+ this.pushPending = false;
+ }
+ if ( config.dataLocation ) {
+ this.dataLocation = config.dataLocation;
+ }
+ if ( config.performSearchOnClick ) {
+ this.performSearchOnClick = config.performSearchOnClick;
+ }
+ this.setLookupsDisabled( !this.suggestions );
+
+ $form.on( 'submit', function () {
+ mw.track( 'mw.widgets.SearchInputWidget', {
+ action: 'submit-form',
+ numberOfResults: this.lastLookupItems.length,
+ $form: $form,
+ inputLocation: this.dataLocation || 'header',
+ index: this.lastLookupItems.indexOf(
+ this.$input.val()
+ )
+ } );
+ }.bind( this ) );
+
+ this.$element.addClass( 'oo-ui-textInputWidget-type-search' );
+ this.updateSearchIndicator();
+ this.connect( this, {
+ disable: 'onDisable'
+ } );
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.SearchInputWidget, mw.widgets.TitleInputWidget );
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ * @protected
+ */
+ mw.widgets.SearchInputWidget.prototype.getInputElement = function () {
+ return $( '<input>' ).attr( 'type', 'search' );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.SearchInputWidget.prototype.onIndicatorMouseDown = function ( e ) {
+ if ( e.which === OO.ui.MouseButtons.LEFT ) {
+ // Clear the text field
+ this.setValue( '' );
+ this.$input[ 0 ].focus();
+ return false;
+ }
+ };
+
+ /**
+ * Update the 'clear' indicator displayed on type: 'search' text
+ * fields, hiding it when the field is already empty or when it's not
+ * editable.
+ */
+ mw.widgets.SearchInputWidget.prototype.updateSearchIndicator = function () {
+ if ( this.getValue() === '' || this.isDisabled() || this.isReadOnly() ) {
+ this.setIndicator( null );
+ } else {
+ this.setIndicator( 'clear' );
+ }
+ };
+
+ /**
+ * @see OO.ui.SearchInputWidget#onChange
+ */
+ mw.widgets.SearchInputWidget.prototype.onChange = function () {
+ mw.widgets.SearchInputWidget.parent.prototype.onChange.call( this );
+ this.updateSearchIndicator();
+ };
+
+ /**
+ * Handle disable events.
+ *
+ * @param {boolean} disabled Element is disabled
+ * @private
+ */
+ mw.widgets.SearchInputWidget.prototype.onDisable = function () {
+ this.updateSearchIndicator();
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.SearchInputWidget.prototype.setReadOnly = function ( state ) {
+ mw.widgets.SearchInputWidget.parent.prototype.setReadOnly.call( this, state );
+ this.updateSearchIndicator();
+ return this;
+ };
+
+ /**
+ * @inheritdoc mw.widgets.TitleWidget
+ */
+ mw.widgets.SearchInputWidget.prototype.getSuggestionsPromise = function () {
+ var api = this.getApi(),
+ promise,
+ self = this;
+
+ // reuse the searchSuggest function from mw.searchSuggest
+ promise = mw.searchSuggest.request( api, this.getQueryValue(), $.noop, this.limit, this.getNamespace() );
+
+ // tracking purposes
+ promise.done( function ( data, jqXHR ) {
+ self.requestType = jqXHR.getResponseHeader( 'X-OpenSearch-Type' );
+ } );
+
+ return promise;
+ };
+
+ /**
+ * @inheritdoc mw.widgets.TitleInputWidget
+ */
+ mw.widgets.SearchInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
+ var resp;
+
+ // mw.widgets.TitleInputWidget uses response.query, which doesn't exist for opensearch,
+ // so return the whole response (titles only, and links)
+ resp = {
+ data: response || {},
+ metadata: {
+ type: this.requestType || 'unknown',
+ query: this.getQueryValue()
+ }
+ };
+ this.requestType = undefined;
+
+ return resp;
+ };
+
+ /**
+ * @inheritdoc mw.widgets.TitleWidget
+ */
+ mw.widgets.SearchInputWidget.prototype.getOptionsFromData = function ( data ) {
+ var items = [],
+ self = this;
+
+ // mw.widgets.TitleWidget does a lot more work here, because the TitleOptionWidgets can
+ // differ a lot, depending on the returned data from the request. With the request used here
+ // we get only the search results.
+ $.each( data.data[ 1 ], function ( i, result ) {
+ items.push( new mw.widgets.TitleOptionWidget(
+ // data[ 3 ][ i ] is the link for this result
+ self.getOptionWidgetData( result, null, data.data[ 3 ][ i ] )
+ ) );
+ } );
+
+ mw.track( 'mw.widgets.SearchInputWidget', {
+ action: 'impression-results',
+ numberOfResults: items.length,
+ resultSetType: data.metadata.type,
+ query: data.metadata.query,
+ inputLocation: this.dataLocation || 'header'
+ } );
+
+ return items;
+ };
+
+ /**
+ * @inheritdoc mw.widgets.TitleWidget
+ *
+ * @param {string} title
+ * @param {Object} data
+ * @param {string} url The Url to the result
+ */
+ mw.widgets.SearchInputWidget.prototype.getOptionWidgetData = function ( title, data, url ) {
+ // the values used in mw.widgets-TitleWidget doesn't exist here, that's why
+ // the values are hard-coded here
+ return {
+ data: title,
+ url: url,
+ imageUrl: null,
+ description: null,
+ missing: false,
+ redirect: false,
+ disambiguation: false,
+ query: this.getQueryValue()
+ };
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.SearchInputWidget.prototype.onLookupMenuItemChoose = function () {
+ mw.widgets.SearchInputWidget.parent.prototype.onLookupMenuItemChoose.apply( this, arguments );
+
+ if ( this.performSearchOnClick ) {
+ this.$element.closest( 'form' ).submit();
+ }
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.SearchInputWidget.prototype.getLookupMenuOptionsFromData = function () {
+ var items = mw.widgets.SearchInputWidget.parent.prototype.getLookupMenuOptionsFromData.apply(
+ this, arguments
+ );
+
+ this.lastLookupItems = items.map( function ( item ) {
+ return item.data;
+ } );
+
+ return items;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SelectWithInputWidget.base.css b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SelectWithInputWidget.base.css
new file mode 100644
index 00000000..8c495a5f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SelectWithInputWidget.base.css
@@ -0,0 +1,20 @@
+/*!
+ * MediaWiki Widgets - base SelectWithInput styles.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+.mw-widget-selectWithInputWidget .oo-ui-dropdownInputWidget,
+.mw-widget-selectWithInputWidget .oo-ui-textInputWidget {
+ display: inline-block;
+}
+
+.mw-widget-selectWithInputWidget .oo-ui-dropdownInputWidget {
+ max-width: 20em;
+ margin-right: 0.5em;
+}
+
+.mw-widget-selectWithInputWidget .oo-ui-textInputWidget {
+ max-width: 29.5em;
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SelectWithInputWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SelectWithInputWidget.js
new file mode 100644
index 00000000..19603513
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.SelectWithInputWidget.js
@@ -0,0 +1,145 @@
+/*!
+ * MediaWiki Widgets - SelectWithInputWidget class.
+ *
+ * @copyright 2011-2017 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Select with input widget. Displays an OO.ui.TextInputWidget along with
+ * an OO.ui.DropdownInputWidget.
+ * TODO Explain the OTHER option
+ *
+ * mw.loader.using( 'mediawiki.widgets.SelectWithInputWidget', function () {
+ * var swi = new mw.widgets.SelectWithInputWidget( {
+ * or: true,
+ * dropdowninput: {
+ * options: [
+ * { data: 'other', label: 'Other' },
+ * { data: 'a', label: 'First' },
+ * { data: 'b', label: 'Second' },
+ * { data: 'c', label: 'Third' }
+ * ]
+ * },
+ * textinput: {
+ * }
+ * } );
+ *
+ * $( 'body' ).append( swi.$element );
+ * } );
+ *
+ * @class mw.widgets.SelectWithInputWidget
+ * @extends OO.ui.Widget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Object} [dropdowninput] Config for the dropdown
+ * @cfg {Object} [textinput] Config for the text input
+ * @cfg {boolean} [or=false] Config for whether the widget is dropdown AND input
+ * or dropdown OR input
+ */
+ mw.widgets.SelectWithInputWidget = function MwWidgetsSelectWithInputWidget( config ) {
+ // Config initialization
+ config = $.extend( { or: false }, config );
+
+ // Properties
+ this.textinput = new OO.ui.TextInputWidget( config.textinput );
+ this.dropdowninput = new OO.ui.DropdownInputWidget( config.dropdowninput );
+ this.or = config.or;
+
+ // Events
+ this.dropdowninput.on( 'change', this.onChange.bind( this ) );
+
+ // Parent constructor
+ mw.widgets.SelectWithInputWidget.parent.call( this, config );
+
+ // Initialization
+ this.$element
+ .addClass( 'mw-widget-selectWithInputWidget' )
+ .append(
+ this.dropdowninput.$element,
+ this.textinput.$element
+ );
+ this.onChange();
+ };
+
+ /* Setup */
+ OO.inheritClass( mw.widgets.SelectWithInputWidget, OO.ui.Widget );
+
+ /* Static Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.SelectWithInputWidget.static.reusePreInfuseDOM = function ( node, config ) {
+ config = mw.widgets.SelectWithInputWidget.parent.static.reusePreInfuseDOM( node, config );
+ config.dropdowninput = OO.ui.DropdownInputWidget.static.reusePreInfuseDOM(
+ $( node ).find( '.oo-ui-dropdownInputWidget' ),
+ config.dropdowninput
+ );
+ config.textinput = OO.ui.TextInputWidget.static.reusePreInfuseDOM(
+ $( node ).find( '.oo-ui-textInputWidget' ),
+ config.textinput
+ );
+ return config;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.SelectWithInputWidget.static.gatherPreInfuseState = function ( node, config ) {
+ var state = mw.widgets.SelectWithInputWidget.parent.static.gatherPreInfuseState( node, config );
+ state.dropdowninput = OO.ui.DropdownInputWidget.static.gatherPreInfuseState(
+ $( node ).find( '.oo-ui-dropdownInputWidget' ),
+ config.dropdowninput
+ );
+ state.textinput = OO.ui.TextInputWidget.static.gatherPreInfuseState(
+ $( node ).find( '.oo-ui-textInputWidget' ),
+ config.textinput
+ );
+ return state;
+ };
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.SelectWithInputWidget.prototype.restorePreInfuseState = function ( state ) {
+ mw.widgets.SelectWithInputWidget.parent.prototype.restorePreInfuseState.call( this, state );
+ this.dropdowninput.restorePreInfuseState( state.dropdowninput );
+ this.textinput.restorePreInfuseState( state.textinput );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.SelectWithInputWidget.prototype.setDisabled = function ( disabled ) {
+ var textinputIsHidden = this.or && this.dropdowninput.getValue() !== 'other';
+ mw.widgets.SelectWithInputWidget.parent.prototype.setDisabled.call( this, disabled );
+ this.dropdowninput.setDisabled( disabled );
+ // It is impossible to submit a form with hidden fields failing validation, e.g. one that
+ // is required. However, validity is not checked for disabled fields, as these are not
+ // submitted with the form. So we should also disable fields when hiding them.
+ this.textinput.setDisabled( textinputIsHidden || disabled );
+ };
+
+ /**
+ * Handle change events on the DropdownInput
+ *
+ * @param {string|undefined} value
+ * @private
+ */
+ mw.widgets.SelectWithInputWidget.prototype.onChange = function ( value ) {
+ if ( this.or ) {
+ value = value || this.dropdowninput.getValue();
+ this.textinput.$element.toggle( value === 'other' );
+ // It is impossible to submit a form with hidden fields failing validation, e.g. one that
+ // is required. However, validity is not checked for disabled fields, as these are not
+ // submitted with the form. So we should also disable fields when hiding them.
+ this.textinput.setDisabled( value !== 'other' || this.isDisabled() );
+ }
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.js
new file mode 100644
index 00000000..cdcf5a23
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.js
@@ -0,0 +1,158 @@
+/*!
+ * MediaWiki Widgets - StashedFileWidget class.
+ *
+ * @copyright 2011-2016 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw, OO ) {
+
+ /**
+ * Accepts a stashed file and displays the information for purposes of
+ * publishing the file at the behest of the user.
+ *
+ * Example use:
+ * var widget = new mw.widgets.StashedFileWidget( {
+ * filekey: '12r9e4rugeec.ddtmmp.1.jpg',
+ * } );
+ *
+ * widget.getValue(); // '12r9e4rugeec.ddtmmp.1.jpg'
+ * widget.setValue( '12r9epfbnskk.knfiy7.1.jpg' );
+ * widget.getValue(); // '12r9epfbnskk.knfiy7.1.jpg'
+ *
+ * Note that this widget will not finish an upload for you. Use mw.Upload
+ * and mw.Upload#setFilekey, then mw.Upload#finishStashUpload to accomplish
+ * that.
+ *
+ * @class mw.widgets.StashedFileWidget
+ * @extends OO.ui.Widget
+ */
+
+ /**
+ * @constructor
+ * @param {Object} config Configuration options
+ * @cfg {string} filekey The filekey of the stashed file.
+ * @cfg {Object} [api] API to use for thumbnails.
+ */
+ mw.widgets.StashedFileWidget = function MWWStashedFileWidget( config ) {
+ if ( !config.api ) {
+ config.api = new mw.Api();
+ }
+
+ // Parent constructor
+ mw.widgets.StashedFileWidget.parent.call( this, config );
+
+ // Mixin constructors
+ OO.ui.mixin.IconElement.call( this, config );
+ OO.ui.mixin.LabelElement.call( this, config );
+ OO.ui.mixin.PendingElement.call( this, config );
+
+ // Properties
+ this.api = config.api;
+ this.$info = $( '<span>' );
+ this.setValue( config.filekey );
+ this.$label.addClass( 'mw-widgets-stashedFileWidget-label' );
+ this.$info
+ .addClass( 'mw-widgets-stashedFileWidget-info' )
+ .append( this.$icon, this.$label );
+
+ this.$thumbnail = $( '<div>' ).addClass( 'mw-widgets-stashedFileWidget-thumbnail' );
+ this.setPendingElement( this.$thumbnail );
+
+ this.$thumbContain = $( '<div>' )
+ .addClass( 'mw-widgets-stashedFileWidget-thumbnail-container' )
+ .append( this.$thumbnail, this.$info );
+
+ this.$element
+ .addClass( 'mw-widgets-stashedFileWidget' )
+ .append( this.$thumbContain );
+
+ this.updateUI();
+ };
+
+ OO.inheritClass( mw.widgets.StashedFileWidget, OO.ui.Widget );
+ OO.mixinClass( mw.widgets.StashedFileWidget, OO.ui.mixin.IconElement );
+ OO.mixinClass( mw.widgets.StashedFileWidget, OO.ui.mixin.LabelElement );
+ OO.mixinClass( mw.widgets.StashedFileWidget, OO.ui.mixin.PendingElement );
+
+ /**
+ * Get the current filekey.
+ *
+ * @return {string|null}
+ */
+ mw.widgets.StashedFileWidget.prototype.getValue = function () {
+ return this.filekey;
+ };
+
+ /**
+ * Set the filekey.
+ *
+ * @param {string|null} filekey
+ */
+ mw.widgets.StashedFileWidget.prototype.setValue = function ( filekey ) {
+ if ( filekey !== this.filekey ) {
+ this.filekey = filekey;
+ this.updateUI();
+ this.emit( 'change', this.filekey );
+ }
+ };
+
+ mw.widgets.StashedFileWidget.prototype.updateUI = function () {
+ var $label, $filetype;
+
+ if ( this.filekey ) {
+ this.$element.removeClass( 'mw-widgets-stashedFileWidget-empty' );
+ $label = $( [] );
+ $filetype = $( '<span>' )
+ .addClass( 'mw-widgets-stashedFileWidget-fileType' );
+
+ $label = $label.add(
+ $( '<span>' )
+ .addClass( 'mw-widgets-stashedFileWidget-filekey' )
+ .text( this.filekey )
+ ).add( $filetype );
+
+ this.setLabel( $label );
+
+ this.pushPending();
+ this.loadAndGetImageUrl().done( function ( url, mime ) {
+ this.$thumbnail.css( 'background-image', 'url( ' + url + ' )' );
+ if ( mime ) {
+ $filetype.text( mime );
+ this.setLabel( $label );
+ }
+ }.bind( this ) ).fail( function () {
+ this.$thumbnail.append(
+ new OO.ui.IconWidget( {
+ icon: 'attachment',
+ classes: [ 'mw-widgets-stashedFileWidget-noThumbnail-icon' ]
+ } ).$element
+ );
+ }.bind( this ) ).always( function () {
+ this.popPending();
+ }.bind( this ) );
+ } else {
+ this.$element.addClass( 'mw-widgets-stashedFileWidget-empty' );
+ this.setLabel( '' );
+ }
+ };
+
+ mw.widgets.StashedFileWidget.prototype.loadAndGetImageUrl = function () {
+ var filekey = this.filekey;
+
+ if ( filekey ) {
+ return this.api.get( {
+ action: 'query',
+ prop: 'stashimageinfo',
+ siifilekey: filekey,
+ siiprop: [ 'size', 'url', 'mime' ],
+ siiurlwidth: 220
+ } ).then( function ( data ) {
+ var sii = data.query.stashimageinfo[ 0 ];
+
+ return $.Deferred().resolve( sii.thumburl, sii.mime );
+ } );
+ }
+
+ return $.Deferred().reject( 'No filekey' );
+ };
+}( jQuery, mediaWiki, OO ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.less b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.less
new file mode 100644
index 00000000..8be1e869
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.StashedFileWidget.less
@@ -0,0 +1,162 @@
+@import 'mediawiki.mixins';
+
+.mw-widgets-stashedFileWidget {
+ display: inline-block;
+ vertical-align: middle;
+ width: 100%;
+ max-width: 50em;
+ margin-right: 0.5em;
+
+ &:last-child {
+ margin-right: 0;
+ }
+
+ &.oo-ui-iconElement .mw-widgets-stashedFileWidget-info .mw-widgets-stashedFileWidget-label {
+ left: 2.875em;
+ }
+
+ &.oo-ui-indicatorElement .mw-widgets-stashedFileWidget-info .mw-widgets-stashedFileWidget-label {
+ right: 4.4625em;
+ }
+}
+
+.mw-widgets-stashedFileWidget-info {
+ height: 2.4em;
+ background-color: #fff;
+ border: 1px solid #c8ccd1;
+ border-radius: 2px;
+ width: 100%;
+ display: table-cell;
+ vertical-align: middle;
+ position: relative;
+ overflow: hidden;
+ .box-sizing( border-box );
+
+ > .mw-widgets-stashedFileWidget-label {
+ line-height: 2.3em;
+ margin: 0;
+ overflow: hidden;
+ white-space: nowrap;
+ .box-sizing( border-box );
+ text-overflow: ellipsis;
+ left: 0.5em;
+ right: 2.375em;
+ position: absolute;
+ top: 0;
+ bottom: 0;
+
+ > .mw-widgets-stashedFileWidget-fileName {
+ float: left;
+ }
+ > .mw-widgets-stashedFileWidget-fileType {
+ color: #72777d;
+ float: right;
+ }
+ }
+
+ > .oo-ui-indicatorElement-indicator,
+ > .oo-ui-iconElement-icon {
+ position: absolute;
+ top: 0;
+ height: 2.3em;
+ }
+
+ > .oo-ui-indicatorElement-indicator {
+ right: 0;
+ width: 0.9375em;
+ margin-right: 0.775em;
+ }
+
+ > .oo-ui-iconElement-icon {
+ width: 1.875em;
+ margin-left: 0.5em;
+ }
+
+ &.oo-ui-widget-disabled {
+ .mw-widgets-stashedFileWidget-info {
+ background-color: #eaecf0;
+ color: #72777d;
+ border-color: #c8ccd1;
+ text-shadow: 0 1px 1px #fff;
+
+ > .oo-ui-iconElement-icon,
+ > .oo-ui-indicatorElement-indicator {
+ opacity: 0.15;
+ }
+ }
+ }
+}
+
+.mw-widgets-stashedFileWidget-thumbnail-container {
+ cursor: default;
+ height: 5.5em;
+ text-align: left;
+ padding: 0;
+ background-color: #fff;
+ border: 1px solid #c8ccd1;
+ margin-bottom: 0.5em;
+ vertical-align: middle;
+ overflow: hidden;
+ border-radius: 2px;
+
+ .mw-widgets-stashedFileWidget-thumbnail {
+ height: 5.5em;
+ width: 5.5em;
+ position: absolute;
+ background-size: cover;
+ background-position: center center;
+
+ &.oo-ui-pendingElement-pending {
+ background-size: auto;
+ }
+
+ > .mw-widgets-stashedFileWidget-noThumbnail-icon {
+ opacity: 0.4;
+ background-color: #c8ccd1;
+ height: 5.5em;
+ width: 5.5em;
+ }
+ }
+
+ .mw-widgets-stashedFileWidget-info {
+ border: 0;
+ background: none;
+ display: block;
+ height: 100%;
+ width: auto;
+ margin-left: 5.5em;
+
+ > .mw-widgets-stashedFileWidget-label {
+ position: relative;
+
+ > .mw-widgets-stashedFileWidget-fileName,
+ > .mw-widgets-stashedFileWidget-fileType {
+ display: block;
+ float: none;
+ }
+ }
+ }
+}
+
+.mw-widgets-stashedFileWidget-empty {
+ .mw-widgets-stashedFileWidget-thumbnail-container {
+ text-align: center;
+
+ .mw-widgets-stashedFileWidget-thumbnail,
+ .mw-widgets-stashedFileWidget-info {
+ margin: 0;
+ display: none;
+ }
+ }
+
+ .mw-widgets-stashedFileWidget-label {
+ color: #c8ccd1;
+ right: 0.5em;
+ }
+
+ &.oo-ui-indicatorElement {
+ .mw-widgets-stashedFileWidget-label {
+ right: 2em;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleInputWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleInputWidget.js
new file mode 100644
index 00000000..a78ad82b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleInputWidget.js
@@ -0,0 +1,139 @@
+/*!
+ * MediaWiki Widgets - TitleInputWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Creates an mw.widgets.TitleInputWidget object.
+ *
+ * @class
+ * @extends OO.ui.TextInputWidget
+ * @mixins mw.widgets.TitleWidget
+ * @mixins OO.ui.mixin.LookupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {boolean} [suggestions=true] Display search suggestions
+ * @cfg {RegExp|Function|string} [validate] Perform title validation
+ */
+ mw.widgets.TitleInputWidget = function MwWidgetsTitleInputWidget( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.widgets.TitleInputWidget.parent.call( this, $.extend( {}, config, {
+ validate: config.validate !== undefined ? config.validate : this.isQueryValid.bind( this ),
+ autocomplete: false
+ } ) );
+
+ // Mixin constructors
+ mw.widgets.TitleWidget.call( this, config );
+ OO.ui.mixin.LookupElement.call( this, config );
+
+ // Properties
+ this.suggestions = config.suggestions !== undefined ? config.suggestions : true;
+
+ // Initialization
+ this.$element.addClass( 'mw-widget-titleInputWidget' );
+ this.lookupMenu.$element.addClass( 'mw-widget-titleWidget-menu' );
+ if ( this.showImages ) {
+ this.lookupMenu.$element.addClass( 'mw-widget-titleWidget-menu-withImages' );
+ }
+ if ( this.showDescriptions ) {
+ this.lookupMenu.$element.addClass( 'mw-widget-titleWidget-menu-withDescriptions' );
+ }
+ this.setLookupsDisabled( !this.suggestions );
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.TitleInputWidget, OO.ui.TextInputWidget );
+ OO.mixinClass( mw.widgets.TitleInputWidget, mw.widgets.TitleWidget );
+ OO.mixinClass( mw.widgets.TitleInputWidget, OO.ui.mixin.LookupElement );
+
+ /* Methods */
+
+ /**
+ * @inheritdoc mw.widgets.TitleWidget
+ */
+ mw.widgets.TitleInputWidget.prototype.getQueryValue = function () {
+ return this.getValue();
+ };
+
+ /**
+ * @inheritdoc mw.widgets.TitleWidget
+ */
+ mw.widgets.TitleInputWidget.prototype.setNamespace = function ( namespace ) {
+ // Mixin method
+ mw.widgets.TitleWidget.prototype.setNamespace.call( this, namespace );
+
+ this.lookupCache = {};
+ this.closeLookupMenu();
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.TitleInputWidget.prototype.getLookupRequest = function () {
+ return this.getSuggestionsPromise();
+ };
+
+ /**
+ * @inheritdoc OO.ui.mixin.LookupElement
+ */
+ mw.widgets.TitleInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
+ return response.query || {};
+ };
+
+ /**
+ * @inheritdoc OO.ui.mixin.LookupElement
+ */
+ mw.widgets.TitleInputWidget.prototype.getLookupMenuOptionsFromData = function ( response ) {
+ return this.getOptionsFromData( response );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.TitleInputWidget.prototype.onLookupMenuItemChoose = function ( item ) {
+ this.closeLookupMenu();
+ this.setLookupsDisabled( true );
+ this.setValue( item.getData() );
+ this.setLookupsDisabled( !this.suggestions );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.TitleInputWidget.prototype.focus = function () {
+ var retval;
+
+ // Prevent programmatic focus from opening the menu
+ this.setLookupsDisabled( true );
+
+ // Parent method
+ retval = mw.widgets.TitleInputWidget.parent.prototype.focus.apply( this, arguments );
+
+ this.setLookupsDisabled( !this.suggestions );
+
+ return retval;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.TitleInputWidget.prototype.cleanUpValue = function ( value ) {
+ var widget = this;
+
+ // Parent method
+ value = mw.widgets.TitleInputWidget.parent.prototype.cleanUpValue.call( this, value );
+
+ return $.trimByteLength( this.value, value, this.maxLength, function ( value ) {
+ var title = widget.getTitle( value );
+ return title ? title.getMain() : value;
+ } ).newVal;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleOptionWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleOptionWidget.js
new file mode 100644
index 00000000..51508ab5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleOptionWidget.js
@@ -0,0 +1,100 @@
+/*!
+ * MediaWiki Widgets - TitleOptionWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Creates a mw.widgets.TitleOptionWidget object.
+ *
+ * @class
+ * @extends OO.ui.MenuOptionWidget
+ *
+ * @constructor
+ * @param {Object} config Configuration options
+ * @cfg {string} data Label to display
+ * @cfg {string} url URL of page
+ * @cfg {string} [imageUrl] Thumbnail image URL with URL encoding
+ * @cfg {string} [description] Page description
+ * @cfg {boolean} [missing] Page doesn't exist
+ * @cfg {boolean} [redirect] Page is a redirect
+ * @cfg {boolean} [disambiguation] Page is a disambiguation page
+ * @cfg {string} [query] Matching query string
+ */
+ mw.widgets.TitleOptionWidget = function MwWidgetsTitleOptionWidget( config ) {
+ var icon;
+
+ if ( config.missing ) {
+ icon = 'page-not-found';
+ } else if ( config.redirect ) {
+ icon = 'page-redirect';
+ } else if ( config.disambiguation ) {
+ icon = 'page-disambiguation';
+ } else {
+ icon = 'page-existing';
+ }
+
+ // Config initialization
+ config = $.extend( {
+ icon: icon,
+ label: config.data,
+ autoFitLabel: false,
+ $label: $( '<a>' )
+ }, config );
+
+ // Parent constructor
+ mw.widgets.TitleOptionWidget.parent.call( this, config );
+
+ // Initialization
+ this.$label.attr( 'href', config.url );
+ this.$element.addClass( 'mw-widget-titleOptionWidget' );
+
+ // OOUI OptionWidgets make an effort to not be tab accessible, but
+ // adding a link inside them would undo that. So, explicitly make it
+ // not tabbable.
+ this.$label.attr( 'tabindex', '-1' );
+
+ // Allow opening the link in new tab, but not regular navigation.
+ this.$label.on( 'click', function ( e ) {
+ // Don't interfere with special clicks (e.g. to open in new tab)
+ if ( !( e.which !== 1 || e.altKey || e.ctrlKey || e.shiftKey || e.metaKey ) ) {
+ e.preventDefault();
+ }
+ } );
+
+ // Highlight matching parts of link suggestion
+ this.$label
+ .highlightText( config.query )
+ .attr( 'title', config.data );
+
+ if ( config.missing ) {
+ this.$label.addClass( 'new' );
+ } else if ( config.redirect ) {
+ this.$label.addClass( 'mw-redirect' );
+ } else if ( config.disambiguation ) {
+ this.$label.addClass( 'mw-disambig' );
+ }
+
+ if ( config.imageUrl ) {
+ this.$icon
+ .addClass( 'mw-widget-titleOptionWidget-hasImage' )
+ .css( 'background-image', 'url(' + config.imageUrl + ')' );
+ }
+
+ if ( config.description ) {
+ this.$element.append(
+ $( '<span>' )
+ .addClass( 'mw-widget-titleOptionWidget-description' )
+ .text( config.description )
+ .attr( 'title', config.description )
+ );
+ }
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.TitleOptionWidget, OO.ui.MenuOptionWidget );
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleSearchWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleSearchWidget.js
new file mode 100644
index 00000000..5ba9481a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleSearchWidget.js
@@ -0,0 +1,105 @@
+/*!
+ * MediaWiki Widgets - TitleSearchWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Creates an mw.widgets.TitleSearchWidget object.
+ *
+ * @class
+ * @extends OO.ui.SearchWidget
+ * @mixins OO.ui.mixin.RequestManager
+ * @mixins mw.widgets.TitleWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ */
+ mw.widgets.TitleSearchWidget = function MwWidgetsTitleSearchWidget( config ) {
+ config = config || {};
+
+ // Parent constructor
+ mw.widgets.TitleSearchWidget.parent.call( this, config );
+
+ // Mixin constructors
+ mw.widgets.TitleWidget.call( this, config );
+ OO.ui.mixin.RequestManager.call( this, config );
+
+ this.query.setValidation( this.isQueryValid.bind( this ) );
+
+ // Events
+ this.results.connect( this, { choose: 'onTitleSearchResultsChoose' } );
+
+ // Initialization
+ this.$element.addClass( 'mw-widget-titleSearchWidget' );
+ this.results.$element.addClass( 'mw-widget-titleWidget-menu' );
+ if ( this.showImages ) {
+ this.results.$element.addClass( 'mw-widget-titleWidget-menu-withImages' );
+ }
+ if ( this.showDescriptions ) {
+ this.results.$element.addClass( 'mw-widget-titleWidget-menu-withDescriptions' );
+ }
+ if ( this.maxLength !== undefined ) {
+ this.getQuery().$input.attr( 'maxlength', this.maxLength );
+ }
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.TitleSearchWidget, OO.ui.SearchWidget );
+ OO.mixinClass( mw.widgets.TitleSearchWidget, OO.ui.mixin.RequestManager );
+ OO.mixinClass( mw.widgets.TitleSearchWidget, mw.widgets.TitleWidget );
+
+ /* Methods */
+
+ /**
+ * @inheritdoc mw.widgets.TitleWidget
+ */
+ mw.widgets.TitleSearchWidget.prototype.getQueryValue = function () {
+ return this.getQuery().getValue();
+ };
+
+ /**
+ * Handle choose events from the result widget
+ *
+ * @param {OO.ui.OptionWidget} item Chosen item
+ */
+ mw.widgets.TitleSearchWidget.prototype.onTitleSearchResultsChoose = function ( item ) {
+ this.getQuery().setValue( item.getData() );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.TitleSearchWidget.prototype.onQueryChange = function () {
+ var widget = this;
+
+ this.getRequestData().done( function ( data ) {
+ // Parent method
+ mw.widgets.TitleSearchWidget.parent.prototype.onQueryChange.call( widget );
+ widget.results.addItems( widget.getOptionsFromData( data ) );
+ } );
+ };
+
+ /**
+ * @inheritdoc OO.ui.mixin.RequestManager
+ */
+ mw.widgets.TitleSearchWidget.prototype.getRequestQuery = function () {
+ return this.getQueryValue();
+ };
+ /**
+ * @inheritdoc OO.ui.mixin.RequestManager
+ */
+ mw.widgets.TitleSearchWidget.prototype.getRequest = function () {
+ return this.getSuggestionsPromise();
+ };
+ /**
+ * @inheritdoc OO.ui.mixin.RequestManager
+ */
+ mw.widgets.TitleSearchWidget.prototype.getRequestCacheDataFromResponse = function ( response ) {
+ return response.query || {};
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js
new file mode 100644
index 00000000..9703eeac
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.js
@@ -0,0 +1,343 @@
+/*!
+ * MediaWiki Widgets - TitleWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Mixin for title widgets
+ *
+ * @class
+ * @abstract
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [limit=10] Number of results to show
+ * @cfg {number} [namespace] Namespace to prepend to queries
+ * @cfg {number} [maxLength=255] Maximum query length
+ * @cfg {boolean} [relative=true] If a namespace is set, display titles relative to it
+ * @cfg {boolean} [suggestions=true] Display search suggestions
+ * @cfg {boolean} [showRedirectTargets=true] Show the targets of redirects
+ * @cfg {boolean} [showImages] Show page images
+ * @cfg {boolean} [showDescriptions] Show page descriptions
+ * @cfg {boolean} [excludeCurrentPage] Exclude the current page from suggestions
+ * @cfg {boolean} [validateTitle=true] Whether the input must be a valid title (if set to true,
+ * the widget will marks itself red for invalid inputs, including an empty query).
+ * @cfg {Object} [cache] Result cache which implements a 'set' method, taking keyed values as an argument
+ * @cfg {mw.Api} [api] API object to use, creates a default mw.Api instance if not specified
+ */
+ mw.widgets.TitleWidget = function MwWidgetsTitleWidget( config ) {
+ // Config initialization
+ config = $.extend( {
+ maxLength: 255,
+ limit: 10
+ }, config );
+
+ // Properties
+ this.limit = config.limit;
+ this.maxLength = config.maxLength;
+ this.namespace = config.namespace !== undefined ? config.namespace : null;
+ this.relative = config.relative !== undefined ? config.relative : true;
+ this.suggestions = config.suggestions !== undefined ? config.suggestions : true;
+ this.showRedirectTargets = config.showRedirectTargets !== false;
+ this.showImages = !!config.showImages;
+ this.showDescriptions = !!config.showDescriptions;
+ this.excludeCurrentPage = !!config.excludeCurrentPage;
+ this.validateTitle = config.validateTitle !== undefined ? config.validateTitle : true;
+ this.cache = config.cache;
+ this.api = config.api || new mw.Api();
+
+ // Initialization
+ this.$element.addClass( 'mw-widget-titleWidget' );
+ };
+
+ /* Setup */
+
+ OO.initClass( mw.widgets.TitleWidget );
+
+ /* Static properties */
+
+ mw.widgets.TitleWidget.static.interwikiPrefixesPromiseCache = {};
+
+ /* Methods */
+
+ /**
+ * Get the current value of the search query
+ *
+ * @abstract
+ * @return {string} Search query
+ */
+ mw.widgets.TitleWidget.prototype.getQueryValue = null;
+
+ /**
+ * Get the namespace to prepend to titles in suggestions, if any.
+ *
+ * @return {number|null} Namespace number
+ */
+ mw.widgets.TitleWidget.prototype.getNamespace = function () {
+ return this.namespace;
+ };
+
+ /**
+ * Set the namespace to prepend to titles in suggestions, if any.
+ *
+ * @param {number|null} namespace Namespace number
+ */
+ mw.widgets.TitleWidget.prototype.setNamespace = function ( namespace ) {
+ this.namespace = namespace;
+ };
+
+ mw.widgets.TitleWidget.prototype.getInterwikiPrefixesPromise = function () {
+ var api = this.getApi(),
+ cache = this.constructor.static.interwikiPrefixesPromiseCache,
+ key = api.defaults.ajax.url;
+ if ( !cache.hasOwnProperty( key ) ) {
+ cache[ key ] = api.get( {
+ action: 'query',
+ meta: 'siteinfo',
+ siprop: 'interwikimap',
+ // Cache client-side for a day since this info is mostly static
+ maxage: 60 * 60 * 24,
+ smaxage: 60 * 60 * 24,
+ // Workaround T97096 by setting uselang=content
+ uselang: 'content'
+ } ).then( function ( data ) {
+ return $.map( data.query.interwikimap, function ( interwiki ) {
+ return interwiki.prefix;
+ } );
+ } );
+ }
+ return cache[ key ];
+ };
+
+ /**
+ * Get a promise which resolves with an API repsonse for suggested
+ * links for the current query.
+ *
+ * @return {jQuery.Promise} Suggestions promise
+ */
+ mw.widgets.TitleWidget.prototype.getSuggestionsPromise = function () {
+ var req,
+ api = this.getApi(),
+ query = this.getQueryValue(),
+ widget = this,
+ promiseAbortObject = { abort: function () {
+ // Do nothing. This is just so OOUI doesn't break due to abort being undefined.
+ } };
+
+ if ( mw.Title.newFromText( query ) ) {
+ return this.getInterwikiPrefixesPromise().then( function ( interwikiPrefixes ) {
+ var params,
+ interwiki = query.substring( 0, query.indexOf( ':' ) );
+ if (
+ interwiki && interwiki !== '' &&
+ interwikiPrefixes.indexOf( interwiki ) !== -1
+ ) {
+ return $.Deferred().resolve( { query: {
+ pages: [ {
+ title: query
+ } ]
+ } } ).promise( promiseAbortObject );
+ } else {
+ params = {
+ action: 'query',
+ prop: [ 'info', 'pageprops' ],
+ generator: 'prefixsearch',
+ gpssearch: query,
+ gpsnamespace: widget.namespace !== null ? widget.namespace : undefined,
+ gpslimit: widget.limit,
+ ppprop: 'disambiguation'
+ };
+ if ( widget.showRedirectTargets ) {
+ params.redirects = true;
+ }
+ if ( widget.showImages ) {
+ params.prop.push( 'pageimages' );
+ params.pithumbsize = 80;
+ params.pilimit = widget.limit;
+ }
+ if ( widget.showDescriptions ) {
+ params.prop.push( 'pageterms' );
+ params.wbptterms = 'description';
+ }
+ req = api.get( params );
+ promiseAbortObject.abort = req.abort.bind( req ); // TODO ew
+ return req.then( function ( ret ) {
+ if ( ret.query === undefined ) {
+ ret = api.get( { action: 'query', titles: query } );
+ promiseAbortObject.abort = ret.abort.bind( ret );
+ }
+ return ret;
+ } );
+ }
+ } ).promise( promiseAbortObject );
+ } else {
+ // Don't send invalid titles to the API.
+ // Just pretend it returned nothing so we can show the 'invalid title' section
+ return $.Deferred().resolve( {} ).promise( promiseAbortObject );
+ }
+ };
+
+ /**
+ * Get the API object for title requests
+ *
+ * @return {mw.Api} MediaWiki API
+ */
+ mw.widgets.TitleWidget.prototype.getApi = function () {
+ return this.api;
+ };
+
+ /**
+ * Get option widgets from the server response
+ *
+ * @param {Object} data Query result
+ * @return {OO.ui.OptionWidget[]} Menu items
+ */
+ mw.widgets.TitleWidget.prototype.getOptionsFromData = function ( data ) {
+ var i, len, index, pageExists, pageExistsExact, suggestionPage, page, redirect, redirects,
+ currentPageName = new mw.Title( mw.config.get( 'wgRelevantPageName' ) ).getPrefixedText(),
+ items = [],
+ titles = [],
+ titleObj = mw.Title.newFromText( this.getQueryValue() ),
+ redirectsTo = {},
+ pageData = {};
+
+ if ( data.redirects ) {
+ for ( i = 0, len = data.redirects.length; i < len; i++ ) {
+ redirect = data.redirects[ i ];
+ redirectsTo[ redirect.to ] = redirectsTo[ redirect.to ] || [];
+ redirectsTo[ redirect.to ].push( redirect.from );
+ }
+ }
+
+ for ( index in data.pages ) {
+ suggestionPage = data.pages[ index ];
+ // When excludeCurrentPage is set, don't list the current page unless the user has type the full title
+ if ( this.excludeCurrentPage && suggestionPage.title === currentPageName && suggestionPage.title !== titleObj.getPrefixedText() ) {
+ continue;
+ }
+ pageData[ suggestionPage.title ] = {
+ known: suggestionPage.known !== undefined,
+ missing: suggestionPage.missing !== undefined,
+ redirect: suggestionPage.redirect !== undefined,
+ disambiguation: OO.getProp( suggestionPage, 'pageprops', 'disambiguation' ) !== undefined,
+ imageUrl: OO.getProp( suggestionPage, 'thumbnail', 'source' ),
+ description: OO.getProp( suggestionPage, 'terms', 'description' ),
+ // Sort index
+ index: suggestionPage.index
+ };
+
+ // Throw away pages from wrong namespaces. This can happen when 'showRedirectTargets' is true
+ // and we encounter a cross-namespace redirect.
+ if ( this.namespace === null || this.namespace === suggestionPage.ns ) {
+ titles.push( suggestionPage.title );
+ }
+
+ redirects = redirectsTo[ suggestionPage.title ] || [];
+ for ( i = 0, len = redirects.length; i < len; i++ ) {
+ pageData[ redirects[ i ] ] = {
+ missing: false,
+ known: true,
+ redirect: true,
+ disambiguation: false,
+ description: mw.msg( 'mw-widgets-titleinput-description-redirect', suggestionPage.title ),
+ // Sort index, just below its target
+ index: suggestionPage.index + 0.5
+ };
+ titles.push( redirects[ i ] );
+ }
+ }
+
+ titles.sort( function ( a, b ) {
+ return pageData[ a ].index - pageData[ b ].index;
+ } );
+
+ // If not found, run value through mw.Title to avoid treating a match as a
+ // mismatch where normalisation would make them matching (T50476)
+
+ pageExistsExact = (
+ Object.prototype.hasOwnProperty.call( pageData, this.getQueryValue() ) &&
+ (
+ !pageData[ this.getQueryValue() ].missing ||
+ pageData[ this.getQueryValue() ].known
+ )
+ );
+ pageExists = pageExistsExact || (
+ titleObj &&
+ Object.prototype.hasOwnProperty.call( pageData, titleObj.getPrefixedText() ) &&
+ (
+ !pageData[ titleObj.getPrefixedText() ].missing ||
+ pageData[ titleObj.getPrefixedText() ].known
+ )
+ );
+
+ if ( this.cache ) {
+ this.cache.set( pageData );
+ }
+
+ // Offer the exact text as a suggestion if the page exists
+ if ( pageExists && !pageExistsExact ) {
+ titles.unshift( this.getQueryValue() );
+ }
+
+ for ( i = 0, len = titles.length; i < len; i++ ) {
+ page = pageData[ titles[ i ] ] || {};
+ items.push( new mw.widgets.TitleOptionWidget( this.getOptionWidgetData( titles[ i ], page ) ) );
+ }
+
+ return items;
+ };
+
+ /**
+ * Get menu option widget data from the title and page data
+ *
+ * @param {string} title Title object
+ * @param {Object} data Page data
+ * @return {Object} Data for option widget
+ */
+ mw.widgets.TitleWidget.prototype.getOptionWidgetData = function ( title, data ) {
+ var mwTitle = new mw.Title( title ),
+ description = data.description;
+ if ( data.missing && !description ) {
+ description = mw.msg( 'mw-widgets-titleinput-description-new-page' );
+ }
+ return {
+ data: this.namespace !== null && this.relative ?
+ mwTitle.getRelativeText( this.namespace ) :
+ title,
+ url: mwTitle.getUrl(),
+ imageUrl: this.showImages ? data.imageUrl : null,
+ description: this.showDescriptions ? description : null,
+ missing: data.missing,
+ redirect: data.redirect,
+ disambiguation: data.disambiguation,
+ query: this.getQueryValue()
+ };
+ };
+
+ /**
+ * Get title object corresponding to given value, or #getQueryValue if not given.
+ *
+ * @param {string} [value] Value to get a title for
+ * @return {mw.Title|null} Title object, or null if value is invalid
+ */
+ mw.widgets.TitleWidget.prototype.getTitle = function ( value ) {
+ var title = value !== undefined ? value : this.getQueryValue(),
+ // mw.Title doesn't handle null well
+ titleObj = mw.Title.newFromText( title, this.namespace !== null ? this.namespace : undefined );
+
+ return titleObj;
+ };
+
+ /**
+ * Check if the query is valid
+ *
+ * @return {boolean} The query is valid
+ */
+ mw.widgets.TitleWidget.prototype.isQueryValid = function () {
+ return this.validateTitle ? !!this.getTitle() : true;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.less b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.less
new file mode 100644
index 00000000..deca71bc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.TitleWidget.less
@@ -0,0 +1,79 @@
+/*!
+ * MediaWiki Widgets - TitleWidget styles.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+@import 'mediawiki.mixins';
+
+.mw-widget-titleWidget-menu {
+ .mw-widget-titleOptionWidget {
+ line-height: normal;
+
+ &-description {
+ color: #72777d;
+ }
+ }
+
+ &-withImages {
+ .mw-widget-titleOptionWidget {
+ .box-sizing( border-box );
+ min-height: 3.75em;
+ padding-left: 4.75em;
+
+ &:not( :last-child ) {
+ margin-bottom: 2px;
+ }
+
+ > .oo-ui-labelElement-label {
+ line-height: 2.8em;
+ }
+
+ &.oo-ui-iconElement {
+ > .oo-ui-iconElement-icon {
+ display: block;
+ width: 3.75em;
+ height: 3.75em;
+ left: 0;
+ &:not( .mw-widget-titleOptionWidget-hasImage ) {
+ background-color: #c8ccd1;
+ opacity: 0.4;
+ }
+ &.mw-widget-titleOptionWidget-hasImage {
+ border: 0;
+ background-size: cover;
+ opacity: 0.7;
+ }
+ }
+ }
+
+ &.oo-ui-optionWidget-highlighted,
+ &.oo-ui-optionWidget-selected {
+ &.oo-ui-iconElement > .mw-widget-titleOptionWidget-hasImage {
+ opacity: 1;
+ }
+ }
+ }
+ }
+
+ &-withDescriptions {
+ .mw-widget-titleOptionWidget {
+ > .oo-ui-labelElement-label {
+ line-height: 1.5em;
+ }
+
+ &-description {
+ display: block;
+ white-space: nowrap;
+ text-overflow: ellipsis;
+ overflow: hidden;
+ }
+ }
+ }
+
+ &:not( &-withDescriptions ) {
+ .mw-widget-titleOptionWidget-description {
+ display: none;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.UserInputWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.UserInputWidget.js
new file mode 100644
index 00000000..2b3a59f5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.UserInputWidget.js
@@ -0,0 +1,120 @@
+/*!
+ * MediaWiki Widgets - UserInputWidget class.
+ *
+ * @copyright 2011-2015 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * Creates a mw.widgets.UserInputWidget object.
+ *
+ * @class
+ * @extends OO.ui.TextInputWidget
+ * @mixins OO.ui.mixin.LookupElement
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {number} [limit=10] Number of results to show
+ */
+ mw.widgets.UserInputWidget = function MwWidgetsUserInputWidget( config ) {
+ // Config initialization
+ config = config || {};
+
+ // Parent constructor
+ mw.widgets.UserInputWidget.parent.call( this, $.extend( {}, config, { autocomplete: false } ) );
+
+ // Mixin constructors
+ OO.ui.mixin.LookupElement.call( this, config );
+
+ // Properties
+ this.limit = config.limit || 10;
+
+ // Initialization
+ this.$element.addClass( 'mw-widget-userInputWidget' );
+ this.lookupMenu.$element.addClass( 'mw-widget-userInputWidget-menu' );
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.UserInputWidget, OO.ui.TextInputWidget );
+ OO.mixinClass( mw.widgets.UserInputWidget, OO.ui.mixin.LookupElement );
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.UserInputWidget.prototype.onLookupMenuItemChoose = function ( item ) {
+ this.closeLookupMenu();
+ this.setLookupsDisabled( true );
+ this.setValue( item.getData() );
+ this.setLookupsDisabled( false );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.UserInputWidget.prototype.focus = function () {
+ var retval;
+
+ // Prevent programmatic focus from opening the menu
+ this.setLookupsDisabled( true );
+
+ // Parent method
+ retval = mw.widgets.UserInputWidget.parent.prototype.focus.apply( this, arguments );
+
+ this.setLookupsDisabled( false );
+
+ return retval;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.widgets.UserInputWidget.prototype.getLookupRequest = function () {
+ var inputValue = this.value;
+
+ return new mw.Api().get( {
+ action: 'query',
+ list: 'allusers',
+ // Prefix of list=allusers is case sensitive. Normalise first
+ // character to uppercase so that "fo" may yield "Foo".
+ auprefix: inputValue[ 0 ].toUpperCase() + inputValue.slice( 1 ),
+ aulimit: this.limit
+ } );
+ };
+
+ /**
+ * Get lookup cache item from server response data.
+ *
+ * @method
+ * @param {Mixed} response Response from server
+ * @return {Object}
+ */
+ mw.widgets.UserInputWidget.prototype.getLookupCacheDataFromResponse = function ( response ) {
+ return response.query.allusers || {};
+ };
+
+ /**
+ * Get list of menu items from a server response.
+ *
+ * @param {Object} data Query result
+ * @return {OO.ui.MenuOptionWidget[]} Menu items
+ */
+ mw.widgets.UserInputWidget.prototype.getLookupMenuOptionsFromData = function ( data ) {
+ var len, i, user,
+ items = [];
+
+ for ( i = 0, len = data.length; i < len; i++ ) {
+ user = data[ i ] || {};
+ items.push( new OO.ui.MenuOptionWidget( {
+ label: user.name,
+ data: user.name
+ } ) );
+ }
+
+ return items;
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki.widgets/mw.widgets.UsersMultiselectWidget.js b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.UsersMultiselectWidget.js
new file mode 100644
index 00000000..d250ad85
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki.widgets/mw.widgets.UsersMultiselectWidget.js
@@ -0,0 +1,171 @@
+/*!
+ * MediaWiki Widgets - UsersMultiselectWidget class.
+ *
+ * @copyright 2017 MediaWiki Widgets Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+( function ( $, mw ) {
+
+ /**
+ * UsersMultiselectWidget can be used to input list of users in a single
+ * line.
+ *
+ * If used inside HTML form the results will be sent as the list of
+ * newline-separated usernames.
+ *
+ * @class
+ * @extends OO.ui.MenuTagMultiselectWidget
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {mw.Api} [api] Instance of mw.Api (or subclass thereof) to use for queries
+ * @cfg {number} [limit=10] Number of results to show in autocomplete menu
+ * @cfg {string} [name] Name of input to submit results (when used in HTML forms)
+ */
+ mw.widgets.UsersMultiselectWidget = function MwWidgetsUsersMultiselectWidget( config ) {
+ // Config initialization
+ config = $.extend( {
+ limit: 10
+ }, config, {
+ // Because of using autocomplete (constantly changing menu), we need to
+ // allow adding usernames, which do not present in the menu.
+ allowArbitrary: true
+ } );
+
+ // Parent constructor
+ mw.widgets.UsersMultiselectWidget.parent.call( this, $.extend( {}, config, {} ) );
+
+ // Mixin constructors
+ OO.ui.mixin.PendingElement.call( this, $.extend( {}, config, { $pending: this.$handle } ) );
+
+ // Properties
+ this.limit = config.limit;
+
+ if ( 'name' in config ) {
+ // If used inside HTML form, then create hidden input, which will store
+ // the results.
+ this.hiddenInput = $( '<input>' )
+ .attr( 'type', 'hidden' )
+ .attr( 'name', config.name )
+ .appendTo( this.$element );
+
+ // Update with preset values
+ this.updateHiddenInput();
+ }
+
+ this.menu = this.getMenu();
+
+ // Events
+ // When list of selected usernames changes, update hidden input
+ this.connect( this, {
+ change: 'onMultiselectChange'
+ } );
+
+ // API init
+ this.api = config.api || new mw.Api();
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.widgets.UsersMultiselectWidget, OO.ui.MenuTagMultiselectWidget );
+ OO.mixinClass( mw.widgets.UsersMultiselectWidget, OO.ui.mixin.PendingElement );
+
+ /* Methods */
+
+ /**
+ * Get currently selected usernames
+ *
+ * @return {string[]} usernames
+ */
+ mw.widgets.UsersMultiselectWidget.prototype.getSelectedUsernames = function () {
+ return this.getValue();
+ };
+
+ /**
+ * Update autocomplete menu with items
+ *
+ * @private
+ */
+ mw.widgets.UsersMultiselectWidget.prototype.updateMenuItems = function () {
+ var inputValue = this.input.getValue();
+
+ if ( inputValue === this.inputValue ) {
+ // Do not restart api query if nothing has changed in the input
+ return;
+ } else {
+ this.inputValue = inputValue;
+ }
+
+ this.api.abort(); // Abort all unfinished api requests
+
+ if ( inputValue.length > 0 ) {
+ this.pushPending();
+
+ this.api.get( {
+ action: 'query',
+ list: 'allusers',
+ // Prefix of list=allusers is case sensitive. Normalise first
+ // character to uppercase so that "fo" may yield "Foo".
+ auprefix: inputValue[ 0 ].toUpperCase() + inputValue.slice( 1 ),
+ aulimit: this.limit
+ } ).done( function ( response ) {
+ var suggestions = response.query.allusers,
+ selected = this.getSelectedUsernames();
+
+ // Remove usernames, which are already selected from suggestions
+ suggestions = suggestions.map( function ( user ) {
+ if ( selected.indexOf( user.name ) === -1 ) {
+ return new OO.ui.MenuOptionWidget( {
+ data: user.name,
+ label: user.name
+ } );
+ }
+ } ).filter( function ( item ) {
+ return item !== undefined;
+ } );
+
+ // Remove all items from menu add fill it with new
+ this.menu.clearItems();
+ this.menu.addItems( suggestions );
+ // Make the menu visible; it might not be if it was previously empty
+ this.menu.toggle( true );
+
+ this.popPending();
+ }.bind( this ) ).fail( this.popPending.bind( this ) );
+ } else {
+ this.menu.clearItems();
+ }
+ };
+
+ mw.widgets.UsersMultiselectWidget.prototype.onInputChange = function () {
+ mw.widgets.UsersMultiselectWidget.parent.prototype.onInputChange.apply( this, arguments );
+
+ this.updateMenuItems();
+ };
+
+ /**
+ * If used inside HTML form, then update hiddenInput with list o
+ * newline-separated usernames.
+ *
+ * @private
+ */
+ mw.widgets.UsersMultiselectWidget.prototype.updateHiddenInput = function () {
+ if ( 'hiddenInput' in this ) {
+ this.hiddenInput.val( this.getSelectedUsernames().join( '\n' ) );
+ // Hidden inputs do not trigger onChange.
+ // @see https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/hidden
+ this.hiddenInput.trigger( 'change' );
+ }
+ };
+
+ /**
+ * React to the 'change' event.
+ *
+ * Updates the hidden input and clears the text from the text box.
+ */
+ mw.widgets.UsersMultiselectWidget.prototype.onMultiselectChange = function () {
+ this.updateHiddenInput();
+ this.input.setValue( '' );
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki/ForeignApi.js b/www/wiki/resources/src/mediawiki/ForeignApi.js
new file mode 100644
index 00000000..1a3cdd5a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/ForeignApi.js
@@ -0,0 +1,119 @@
+( function ( mw, $ ) {
+
+ /**
+ * Create an object like mw.Api, but automatically handling everything required to communicate
+ * with another MediaWiki wiki via cross-origin requests (CORS).
+ *
+ * The foreign wiki must be configured to accept requests from the current wiki. See
+ * <https://www.mediawiki.org/wiki/Manual:$wgCrossSiteAJAXdomains> for details.
+ *
+ * var api = new mw.ForeignApi( 'https://commons.wikimedia.org/w/api.php' );
+ * api.get( {
+ * action: 'query',
+ * meta: 'userinfo'
+ * } ).done( function ( data ) {
+ * console.log( data );
+ * } );
+ *
+ * To ensure that the user at the foreign wiki is logged in, pass the `assert: 'user'` parameter
+ * to #get/#post (since MW 1.23): if they are not, the API request will fail. (Note that this
+ * doesn't guarantee that it's the same user.)
+ *
+ * Authentication-related MediaWiki extensions may extend this class to ensure that the user
+ * authenticated on the current wiki will be automatically authenticated on the foreign one. These
+ * extension modules should be registered using the ResourceLoaderForeignApiModules hook. See
+ * CentralAuth for a practical example. The general pattern to extend and override the name is:
+ *
+ * function MyForeignApi() {};
+ * OO.inheritClass( MyForeignApi, mw.ForeignApi );
+ * mw.ForeignApi = MyForeignApi;
+ *
+ * @class mw.ForeignApi
+ * @extends mw.Api
+ * @since 1.26
+ *
+ * @constructor
+ * @param {string|mw.Uri} url URL pointing to another wiki's `api.php` endpoint.
+ * @param {Object} [options] See mw.Api.
+ * @param {Object} [options.anonymous=false] Perform all requests anonymously. Use this option if
+ * the target wiki may otherwise not accept cross-origin requests, or if you don't need to
+ * perform write actions or read restricted information and want to avoid the overhead.
+ *
+ * @author Bartosz Dziewoński
+ * @author Jon Robson
+ */
+ function CoreForeignApi( url, options ) {
+ if ( !url || $.isPlainObject( url ) ) {
+ throw new Error( 'mw.ForeignApi() requires a `url` parameter' );
+ }
+
+ this.apiUrl = String( url );
+ this.anonymous = options && options.anonymous;
+
+ options = $.extend( /* deep=*/ true,
+ {
+ ajax: {
+ url: this.apiUrl,
+ xhrFields: {
+ withCredentials: !this.anonymous
+ }
+ },
+ parameters: {
+ // Add 'origin' query parameter to all requests.
+ origin: this.getOrigin()
+ }
+ },
+ options
+ );
+
+ // Call parent constructor
+ CoreForeignApi.parent.call( this, options );
+ }
+
+ OO.inheritClass( CoreForeignApi, mw.Api );
+
+ /**
+ * Return the origin to use for API requests, in the required format (protocol, host and port, if
+ * any).
+ *
+ * @protected
+ * @return {string}
+ */
+ CoreForeignApi.prototype.getOrigin = function () {
+ var origin;
+ if ( this.anonymous ) {
+ return '*';
+ }
+ origin = location.protocol + '//' + location.hostname;
+ if ( location.port ) {
+ origin += ':' + location.port;
+ }
+ return origin;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ CoreForeignApi.prototype.ajax = function ( parameters, ajaxOptions ) {
+ var url, origin, newAjaxOptions;
+
+ // 'origin' query parameter must be part of the request URI, and not just POST request body
+ if ( ajaxOptions.type === 'POST' ) {
+ url = ( ajaxOptions && ajaxOptions.url ) || this.defaults.ajax.url;
+ origin = ( parameters && parameters.origin ) || this.defaults.parameters.origin;
+ url += ( url.indexOf( '?' ) !== -1 ? '&' : '?' ) +
+ // Depending on server configuration, MediaWiki may forbid periods in URLs, due to an IE 6
+ // XSS bug. So let's escape them here. See WebRequest::checkUrlExtension() and T30235.
+ 'origin=' + encodeURIComponent( origin ).replace( /\./g, '%2E' );
+ newAjaxOptions = $.extend( {}, ajaxOptions, { url: url } );
+ } else {
+ newAjaxOptions = ajaxOptions;
+ }
+
+ return CoreForeignApi.parent.prototype.ajax.call( this, parameters, newAjaxOptions );
+ };
+
+ // Expose
+ mw.ForeignApi = CoreForeignApi;
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/api.js b/www/wiki/resources/src/mediawiki/api.js
new file mode 100644
index 00000000..b4639ab4
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/api.js
@@ -0,0 +1,506 @@
+( function ( mw, $ ) {
+
+ /**
+ * @class mw.Api
+ */
+
+ /**
+ * @property {Object} defaultOptions Default options for #ajax calls. Can be overridden by passing
+ * `options` to mw.Api constructor.
+ * @property {Object} defaultOptions.parameters Default query parameters for API requests.
+ * @property {Object} defaultOptions.ajax Default options for jQuery#ajax.
+ * @property {boolean} defaultOptions.useUS Whether to use U+001F when joining multi-valued
+ * parameters (since 1.28). Default is true if ajax.url is not set, false otherwise for
+ * compatibility.
+ * @private
+ */
+ var defaultOptions = {
+ parameters: {
+ action: 'query',
+ format: 'json'
+ },
+ ajax: {
+ url: mw.util.wikiScript( 'api' ),
+ timeout: 30 * 1000, // 30 seconds
+ dataType: 'json'
+ }
+ },
+
+ // Keyed by ajax url and symbolic name for the individual request
+ promises = {};
+
+ function mapLegacyToken( action ) {
+ // Legacy types for backward-compatibility with API action=tokens.
+ var csrfActions = [
+ 'edit',
+ 'delete',
+ 'protect',
+ 'move',
+ 'block',
+ 'unblock',
+ 'email',
+ 'import',
+ 'options'
+ ];
+ if ( $.inArray( action, csrfActions ) !== -1 ) {
+ mw.track( 'mw.deprecate', 'apitoken_' + action );
+ mw.log.warn( 'Use of the "' + action + '" token is deprecated. Use "csrf" instead.' );
+ return 'csrf';
+ }
+ return action;
+ }
+
+ // Pre-populate with fake ajax promises to save http requests for tokens
+ // we already have on the page via the user.tokens module (T36733).
+ promises[ defaultOptions.ajax.url ] = {};
+ $.each( mw.user.tokens.get(), function ( key, value ) {
+ // This requires #getToken to use the same key as user.tokens.
+ // Format: token-type + "Token" (eg. csrfToken, patrolToken, watchToken).
+ promises[ defaultOptions.ajax.url ][ key ] = $.Deferred()
+ .resolve( value )
+ .promise( { abort: function () {} } );
+ } );
+
+ /**
+ * Constructor to create an object to interact with the API of a particular MediaWiki server.
+ * mw.Api objects represent the API of a particular MediaWiki server.
+ *
+ * var api = new mw.Api();
+ * api.get( {
+ * action: 'query',
+ * meta: 'userinfo'
+ * } ).done( function ( data ) {
+ * console.log( data );
+ * } );
+ *
+ * Since MW 1.25, multiple values for a parameter can be specified using an array:
+ *
+ * var api = new mw.Api();
+ * api.get( {
+ * action: 'query',
+ * meta: [ 'userinfo', 'siteinfo' ] // same effect as 'userinfo|siteinfo'
+ * } ).done( function ( data ) {
+ * console.log( data );
+ * } );
+ *
+ * Since MW 1.26, boolean values for a parameter can be specified directly. If the value is
+ * `false` or `undefined`, the parameter will be omitted from the request, as required by the API.
+ *
+ * @constructor
+ * @param {Object} [options] See #defaultOptions documentation above. Can also be overridden for
+ * each individual request by passing them to #get or #post (or directly #ajax) later on.
+ */
+ mw.Api = function ( options ) {
+ options = options || {};
+
+ // Force a string if we got a mw.Uri object
+ if ( options.ajax && options.ajax.url !== undefined ) {
+ options.ajax.url = String( options.ajax.url );
+ }
+
+ options = $.extend( { useUS: !options.ajax || !options.ajax.url }, options );
+
+ options.parameters = $.extend( {}, defaultOptions.parameters, options.parameters );
+ options.ajax = $.extend( {}, defaultOptions.ajax, options.ajax );
+
+ this.defaults = options;
+ this.requests = [];
+ };
+
+ mw.Api.prototype = {
+ /**
+ * Abort all unfinished requests issued by this Api object.
+ *
+ * @method
+ */
+ abort: function () {
+ $.each( this.requests, function ( index, request ) {
+ if ( request ) {
+ request.abort();
+ }
+ } );
+ },
+
+ /**
+ * Perform API get request
+ *
+ * @param {Object} parameters
+ * @param {Object} [ajaxOptions]
+ * @return {jQuery.Promise}
+ */
+ get: function ( parameters, ajaxOptions ) {
+ ajaxOptions = ajaxOptions || {};
+ ajaxOptions.type = 'GET';
+ return this.ajax( parameters, ajaxOptions );
+ },
+
+ /**
+ * Perform API post request
+ *
+ * @param {Object} parameters
+ * @param {Object} [ajaxOptions]
+ * @return {jQuery.Promise}
+ */
+ post: function ( parameters, ajaxOptions ) {
+ ajaxOptions = ajaxOptions || {};
+ ajaxOptions.type = 'POST';
+ return this.ajax( parameters, ajaxOptions );
+ },
+
+ /**
+ * Massage parameters from the nice format we accept into a format suitable for the API.
+ *
+ * NOTE: A value of undefined/null in an array will be represented by Array#join()
+ * as the empty string. Should we filter silently? Warn? Leave as-is?
+ *
+ * @private
+ * @param {Object} parameters (modified in-place)
+ * @param {boolean} useUS Whether to use U+001F when joining multi-valued parameters.
+ */
+ preprocessParameters: function ( parameters, useUS ) {
+ var key;
+ // Handle common MediaWiki API idioms for passing parameters
+ for ( key in parameters ) {
+ // Multiple values are pipe-separated
+ if ( Array.isArray( parameters[ key ] ) ) {
+ if ( !useUS || parameters[ key ].join( '' ).indexOf( '|' ) === -1 ) {
+ parameters[ key ] = parameters[ key ].join( '|' );
+ } else {
+ parameters[ key ] = '\x1f' + parameters[ key ].join( '\x1f' );
+ }
+ }
+ // Boolean values are only false when not given at all
+ if ( parameters[ key ] === false || parameters[ key ] === undefined ) {
+ delete parameters[ key ];
+ }
+ }
+ },
+
+ /**
+ * Perform the API call.
+ *
+ * @param {Object} parameters
+ * @param {Object} [ajaxOptions]
+ * @return {jQuery.Promise} Done: API response data and the jqXHR object.
+ * Fail: Error code
+ */
+ ajax: function ( parameters, ajaxOptions ) {
+ var token, requestIndex,
+ api = this,
+ apiDeferred = $.Deferred(),
+ xhr, key, formData;
+
+ parameters = $.extend( {}, this.defaults.parameters, parameters );
+ ajaxOptions = $.extend( {}, this.defaults.ajax, ajaxOptions );
+
+ // Ensure that token parameter is last (per [[mw:API:Edit#Token]]).
+ if ( parameters.token ) {
+ token = parameters.token;
+ delete parameters.token;
+ }
+
+ this.preprocessParameters( parameters, this.defaults.useUS );
+
+ // If multipart/form-data has been requested and emulation is possible, emulate it
+ if (
+ ajaxOptions.type === 'POST' &&
+ window.FormData &&
+ ajaxOptions.contentType === 'multipart/form-data'
+ ) {
+
+ formData = new FormData();
+
+ for ( key in parameters ) {
+ formData.append( key, parameters[ key ] );
+ }
+ // If we extracted a token parameter, add it back in.
+ if ( token ) {
+ formData.append( 'token', token );
+ }
+
+ ajaxOptions.data = formData;
+
+ // Prevent jQuery from mangling our FormData object
+ ajaxOptions.processData = false;
+ // Prevent jQuery from overriding the Content-Type header
+ ajaxOptions.contentType = false;
+ } else {
+ // This works because jQuery accepts data as a query string or as an Object
+ ajaxOptions.data = $.param( parameters );
+ // If we extracted a token parameter, add it back in.
+ if ( token ) {
+ ajaxOptions.data += '&token=' + encodeURIComponent( token );
+ }
+
+ // Depending on server configuration, MediaWiki may forbid periods in URLs, due to an IE 6
+ // XSS bug. So let's escape them here. See WebRequest::checkUrlExtension() and T30235.
+ ajaxOptions.data = ajaxOptions.data.replace( /\./g, '%2E' );
+
+ if ( ajaxOptions.contentType === 'multipart/form-data' ) {
+ // We were asked to emulate but can't, so drop the Content-Type header, otherwise
+ // it'll be wrong and the server will fail to decode the POST body
+ delete ajaxOptions.contentType;
+ }
+ }
+
+ // Make the AJAX request
+ xhr = $.ajax( ajaxOptions )
+ // If AJAX fails, reject API call with error code 'http'
+ // and details in second argument.
+ .fail( function ( xhr, textStatus, exception ) {
+ apiDeferred.reject( 'http', {
+ xhr: xhr,
+ textStatus: textStatus,
+ exception: exception
+ } );
+ } )
+ // AJAX success just means "200 OK" response, also check API error codes
+ .done( function ( result, textStatus, jqXHR ) {
+ var code;
+ if ( result === undefined || result === null || result === '' ) {
+ apiDeferred.reject( 'ok-but-empty',
+ 'OK response but empty result (check HTTP headers?)',
+ result,
+ jqXHR
+ );
+ } else if ( result.error ) {
+ // errorformat=bc
+ code = result.error.code === undefined ? 'unknown' : result.error.code;
+ apiDeferred.reject( code, result, result, jqXHR );
+ } else if ( result.errors ) {
+ // errorformat!=bc
+ code = result.errors[ 0 ].code === undefined ? 'unknown' : result.errors[ 0 ].code;
+ apiDeferred.reject( code, result, result, jqXHR );
+ } else {
+ apiDeferred.resolve( result, jqXHR );
+ }
+ } );
+
+ requestIndex = this.requests.length;
+ this.requests.push( xhr );
+ xhr.always( function () {
+ api.requests[ requestIndex ] = null;
+ } );
+ // Return the Promise
+ return apiDeferred.promise( { abort: xhr.abort } ).fail( function ( code, details ) {
+ if ( !( code === 'http' && details && details.textStatus === 'abort' ) ) {
+ mw.log( 'mw.Api error: ', code, details );
+ }
+ } );
+ },
+
+ /**
+ * Post to API with specified type of token. If we have no token, get one and try to post.
+ * If we have a cached token try using that, and if it fails, blank out the
+ * cached token and start over. For example to change an user option you could do:
+ *
+ * new mw.Api().postWithToken( 'csrf', {
+ * action: 'options',
+ * optionname: 'gender',
+ * optionvalue: 'female'
+ * } );
+ *
+ * @param {string} tokenType The name of the token, like options or edit.
+ * @param {Object} params API parameters
+ * @param {Object} [ajaxOptions]
+ * @return {jQuery.Promise} See #post
+ * @since 1.22
+ */
+ postWithToken: function ( tokenType, params, ajaxOptions ) {
+ var api = this,
+ abortedPromise = $.Deferred().reject( 'http',
+ { textStatus: 'abort', exception: 'abort' } ).promise(),
+ abortable,
+ aborted;
+
+ return api.getToken( tokenType, params.assert ).then( function ( token ) {
+ params.token = token;
+ // Request was aborted while token request was running, but we
+ // don't want to unnecessarily abort token requests, so abort
+ // a fake request instead
+ if ( aborted ) {
+ return abortedPromise;
+ }
+
+ return ( abortable = api.post( params, ajaxOptions ) ).then(
+ // If no error, return to caller as-is
+ null,
+ // Error handler
+ function ( code ) {
+ if ( code === 'badtoken' ) {
+ api.badToken( tokenType );
+ // Try again, once
+ params.token = undefined;
+ abortable = null;
+ return api.getToken( tokenType, params.assert ).then( function ( token ) {
+ params.token = token;
+ if ( aborted ) {
+ return abortedPromise;
+ }
+
+ return ( abortable = api.post( params, ajaxOptions ) );
+ } );
+ }
+
+ // Let caller handle the error code
+ return $.Deferred().rejectWith( this, arguments );
+ }
+ );
+ } ).promise( { abort: function () {
+ if ( abortable ) {
+ abortable.abort();
+ } else {
+ aborted = true;
+ }
+ } } );
+ },
+
+ /**
+ * Get a token for a certain action from the API.
+ *
+ * The assert parameter is only for internal use by #postWithToken.
+ *
+ * @since 1.22
+ * @param {string} type Token type
+ * @param {string} [assert]
+ * @return {jQuery.Promise} Received token.
+ */
+ getToken: function ( type, assert ) {
+ var apiPromise, promiseGroup, d;
+ type = mapLegacyToken( type );
+ promiseGroup = promises[ this.defaults.ajax.url ];
+ d = promiseGroup && promiseGroup[ type + 'Token' ];
+
+ if ( !promiseGroup ) {
+ promiseGroup = promises[ this.defaults.ajax.url ] = {};
+ }
+
+ if ( !d ) {
+ apiPromise = this.get( {
+ action: 'query',
+ meta: 'tokens',
+ type: type,
+ assert: assert
+ } );
+ d = apiPromise
+ .then( function ( res ) {
+ // If token type is unknown, it is omitted from the response
+ if ( !res.query.tokens[ type + 'token' ] ) {
+ return $.Deferred().reject( 'token-missing', res );
+ }
+
+ return res.query.tokens[ type + 'token' ];
+ }, function () {
+ // Clear promise. Do not cache errors.
+ delete promiseGroup[ type + 'Token' ];
+
+ // Let caller handle the error code
+ return $.Deferred().rejectWith( this, arguments );
+ } )
+ // Attach abort handler
+ .promise( { abort: apiPromise.abort } );
+
+ // Store deferred now so that we can use it again even if it isn't ready yet
+ promiseGroup[ type + 'Token' ] = d;
+ }
+
+ return d;
+ },
+
+ /**
+ * Indicate that the cached token for a certain action of the API is bad.
+ *
+ * Call this if you get a 'badtoken' error when using the token returned by #getToken.
+ * You may also want to use #postWithToken instead, which invalidates bad cached tokens
+ * automatically.
+ *
+ * @param {string} type Token type
+ * @since 1.26
+ */
+ badToken: function ( type ) {
+ var promiseGroup = promises[ this.defaults.ajax.url ];
+
+ type = mapLegacyToken( type );
+ if ( promiseGroup ) {
+ delete promiseGroup[ type + 'Token' ];
+ }
+ }
+ };
+
+ /**
+ * @static
+ * @property {Array}
+ * Very incomplete and outdated list of errors we might receive from the API. Do not use.
+ * @deprecated since 1.29
+ */
+ mw.Api.errors = [
+ // occurs when POST aborted
+ // jQuery 1.4 can't distinguish abort or lost connection from 200 OK + empty result
+ 'ok-but-empty',
+
+ // timeout
+ 'timeout',
+
+ // really a warning, but we treat it like an error
+ 'duplicate',
+ 'duplicate-archive',
+
+ // upload succeeded, but no image info.
+ // this is probably impossible, but might as well check for it
+ 'noimageinfo',
+ // remote errors, defined in API
+ 'uploaddisabled',
+ 'nomodule',
+ 'mustbeposted',
+ 'badaccess-groups',
+ 'missingresult',
+ 'missingparam',
+ 'invalid-file-key',
+ 'copyuploaddisabled',
+ 'mustbeloggedin',
+ 'empty-file',
+ 'file-too-large',
+ 'filetype-missing',
+ 'filetype-banned',
+ 'filetype-banned-type',
+ 'filename-tooshort',
+ 'illegal-filename',
+ 'verification-error',
+ 'hookaborted',
+ 'unknown-error',
+ 'internal-error',
+ 'overwrite',
+ 'badtoken',
+ 'fetchfileerror',
+ 'fileexists-shared-forbidden',
+ 'invalidtitle',
+ 'notloggedin',
+ 'autoblocked',
+ 'blocked',
+
+ // Stash-specific errors - expanded
+ 'stashfailed',
+ 'stasherror',
+ 'stashedfilenotfound',
+ 'stashpathinvalid',
+ 'stashfilestorage',
+ 'stashzerolength',
+ 'stashnotloggedin',
+ 'stashwrongowner',
+ 'stashnosuchfilekey'
+ ];
+ mw.log.deprecate( mw.Api, 'errors', mw.Api.errors, null, 'mw.Api.errors' );
+
+ /**
+ * @static
+ * @property {Array}
+ * Very incomplete and outdated list of warnings we might receive from the API. Do not use.
+ * @deprecated since 1.29
+ */
+ mw.Api.warnings = [
+ 'duplicate',
+ 'exists'
+ ];
+ mw.log.deprecate( mw.Api, 'warnings', mw.Api.warnings, null, 'mw.Api.warnings' );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/api/category.js b/www/wiki/resources/src/mediawiki/api/category.js
new file mode 100644
index 00000000..14077e02
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/api/category.js
@@ -0,0 +1,108 @@
+/**
+ * @class mw.Api.plugin.category
+ */
+( function ( mw, $ ) {
+
+ $.extend( mw.Api.prototype, {
+ /**
+ * Determine if a category exists.
+ *
+ * @param {mw.Title|string} title
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {boolean} return.done.isCategory Whether the category exists.
+ */
+ isCategory: function ( title ) {
+ var apiPromise = this.get( {
+ prop: 'categoryinfo',
+ titles: String( title )
+ } );
+
+ return apiPromise
+ .then( function ( data ) {
+ var exists = false;
+ if ( data.query && data.query.pages ) {
+ $.each( data.query.pages, function ( id, page ) {
+ if ( page.categoryinfo ) {
+ exists = true;
+ }
+ } );
+ }
+ return exists;
+ } )
+ .promise( { abort: apiPromise.abort } );
+ },
+
+ /**
+ * Get a list of categories that match a certain prefix.
+ *
+ * E.g. given "Foo", return "Food", "Foolish people", "Foosball tables"...
+ *
+ * @param {string} prefix Prefix to match.
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {string[]} return.done.categories Matched categories
+ */
+ getCategoriesByPrefix: function ( prefix ) {
+ // Fetch with allpages to only get categories that have a corresponding description page.
+ var apiPromise = this.get( {
+ list: 'allpages',
+ apprefix: prefix,
+ apnamespace: mw.config.get( 'wgNamespaceIds' ).category
+ } );
+
+ return apiPromise
+ .then( function ( data ) {
+ var texts = [];
+ if ( data.query && data.query.allpages ) {
+ $.each( data.query.allpages, function ( i, category ) {
+ texts.push( new mw.Title( category.title ).getMainText() );
+ } );
+ }
+ return texts;
+ } )
+ .promise( { abort: apiPromise.abort } );
+ },
+
+ /**
+ * Get the categories that a particular page on the wiki belongs to.
+ *
+ * @param {mw.Title|string} title
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {boolean|mw.Title[]} return.done.categories List of category titles or false
+ * if title was not found.
+ */
+ getCategories: function ( title ) {
+ var apiPromise = this.get( {
+ prop: 'categories',
+ titles: String( title )
+ } );
+
+ return apiPromise
+ .then( function ( data ) {
+ var titles = false;
+ if ( data.query && data.query.pages ) {
+ $.each( data.query.pages, function ( id, page ) {
+ if ( page.categories ) {
+ if ( titles === false ) {
+ titles = [];
+ }
+ $.each( page.categories, function ( i, cat ) {
+ titles.push( new mw.Title( cat.title ) );
+ } );
+ }
+ } );
+ }
+ return titles;
+ } )
+ .promise( { abort: apiPromise.abort } );
+ }
+ } );
+
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.category
+ */
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/api/edit.js b/www/wiki/resources/src/mediawiki/api/edit.js
new file mode 100644
index 00000000..21fad5e5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/api/edit.js
@@ -0,0 +1,193 @@
+/**
+ * @class mw.Api.plugin.edit
+ */
+( function ( mw, $ ) {
+
+ $.extend( mw.Api.prototype, {
+
+ /**
+ * Post to API with csrf token. If we have no token, get one and try to post.
+ * If we have a cached token try using that, and if it fails, blank out the
+ * cached token and start over.
+ *
+ * @param {Object} params API parameters
+ * @param {Object} [ajaxOptions]
+ * @return {jQuery.Promise} See #post
+ */
+ postWithEditToken: function ( params, ajaxOptions ) {
+ return this.postWithToken( 'csrf', params, ajaxOptions );
+ },
+
+ /**
+ * API helper to grab a csrf token.
+ *
+ * @return {jQuery.Promise} Received token.
+ */
+ getEditToken: function () {
+ return this.getToken( 'csrf' );
+ },
+
+ /**
+ * Create a new page.
+ *
+ * Example:
+ *
+ * new mw.Api().create( 'Sandbox',
+ * { summary: 'Load sand particles.' },
+ * 'Sand.'
+ * );
+ *
+ * @since 1.28
+ * @param {mw.Title|string} title Page title
+ * @param {Object} params Edit API parameters
+ * @param {string} params.summary Edit summary
+ * @param {string} content
+ * @return {jQuery.Promise} API response
+ */
+ create: function ( title, params, content ) {
+ return this.postWithEditToken( $.extend( {
+ action: 'edit',
+ title: String( title ),
+ text: content,
+ formatversion: '2',
+
+ // Protect against errors and conflicts
+ assert: mw.user.isAnon() ? undefined : 'user',
+ createonly: true
+ }, params ) ).then( function ( data ) {
+ return data.edit;
+ } );
+ },
+
+ /**
+ * Edit an existing page.
+ *
+ * To create a new page, use #create() instead.
+ *
+ * Simple transformation:
+ *
+ * new mw.Api()
+ * .edit( 'Sandbox', function ( revision ) {
+ * return revision.content.replace( 'foo', 'bar' );
+ * } )
+ * .then( function () {
+ * console.log( 'Saved! ');
+ * } );
+ *
+ * Set save parameters by returning an object instead of a string:
+ *
+ * new mw.Api().edit(
+ * 'Sandbox',
+ * function ( revision ) {
+ * return {
+ * text: revision.content.replace( 'foo', 'bar' ),
+ * summary: 'Replace "foo" with "bar".',
+ * assert: 'bot',
+ * minor: true
+ * };
+ * }
+ * )
+ * .then( function () {
+ * console.log( 'Saved! ');
+ * } );
+ *
+ * Transform asynchronously by returning a promise.
+ *
+ * new mw.Api()
+ * .edit( 'Sandbox', function ( revision ) {
+ * return Spelling
+ * .corrections( revision.content )
+ * .then( function ( report ) {
+ * return {
+ * text: report.output,
+ * summary: report.changelog
+ * };
+ * } );
+ * } )
+ * .then( function () {
+ * console.log( 'Saved! ');
+ * } );
+ *
+ * @since 1.28
+ * @param {mw.Title|string} title Page title
+ * @param {Function} transform Callback that prepares the edit
+ * @param {Object} transform.revision Current revision
+ * @param {string} transform.revision.content Current revision content
+ * @param {string|Object|jQuery.Promise} transform.return New content, object with edit
+ * API parameters, or promise providing one of those.
+ * @return {jQuery.Promise} Edit API response
+ */
+ edit: function ( title, transform ) {
+ var basetimestamp, curtimestamp,
+ api = this;
+ return api.get( {
+ action: 'query',
+ prop: 'revisions',
+ rvprop: [ 'content', 'timestamp' ],
+ titles: String( title ),
+ formatversion: '2',
+ curtimestamp: true
+ } )
+ .then( function ( data ) {
+ var page, revision;
+ if ( !data.query || !data.query.pages ) {
+ return $.Deferred().reject( 'unknown' );
+ }
+ page = data.query.pages[ 0 ];
+ if ( !page || page.missing ) {
+ return $.Deferred().reject( 'nocreate-missing' );
+ }
+ revision = page.revisions[ 0 ];
+ basetimestamp = revision.timestamp;
+ curtimestamp = data.curtimestamp;
+ return transform( {
+ timestamp: revision.timestamp,
+ content: revision.content
+ } );
+ } )
+ .then( function ( params ) {
+ var editParams = typeof params === 'object' ? params : { text: String( params ) };
+ return api.postWithEditToken( $.extend( {
+ action: 'edit',
+ title: title,
+ formatversion: '2',
+
+ // Protect against errors and conflicts
+ assert: mw.user.isAnon() ? undefined : 'user',
+ basetimestamp: basetimestamp,
+ starttimestamp: curtimestamp,
+ nocreate: true
+ }, editParams ) );
+ } )
+ .then( function ( data ) {
+ return data.edit;
+ } );
+ },
+
+ /**
+ * Post a new section to the page.
+ *
+ * @see #postWithEditToken
+ * @param {mw.Title|string} title Target page
+ * @param {string} header
+ * @param {string} message wikitext message
+ * @param {Object} [additionalParams] Additional API parameters, e.g. `{ redirect: true }`
+ * @return {jQuery.Promise}
+ */
+ newSection: function ( title, header, message, additionalParams ) {
+ return this.postWithEditToken( $.extend( {
+ action: 'edit',
+ section: 'new',
+ title: String( title ),
+ summary: header,
+ text: message
+ }, additionalParams ) );
+ }
+ } );
+
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.edit
+ */
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/api/login.js b/www/wiki/resources/src/mediawiki/api/login.js
new file mode 100644
index 00000000..2b709aae
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/api/login.js
@@ -0,0 +1,60 @@
+/**
+ * Make the two-step login easier.
+ *
+ * @author Niklas Laxström
+ * @class mw.Api.plugin.login
+ * @since 1.22
+ */
+( function ( mw, $ ) {
+ 'use strict';
+
+ $.extend( mw.Api.prototype, {
+ /**
+ * @param {string} username
+ * @param {string} password
+ * @return {jQuery.Promise} See mw.Api#post
+ */
+ login: function ( username, password ) {
+ var params, apiPromise, innerPromise,
+ api = this;
+
+ params = {
+ action: 'login',
+ lgname: username,
+ lgpassword: password
+ };
+
+ apiPromise = api.post( params );
+
+ return apiPromise
+ .then( function ( data ) {
+ params.lgtoken = data.login.token;
+ innerPromise = api.post( params )
+ .then( function ( data ) {
+ var code;
+ if ( data.login.result !== 'Success' ) {
+ // Set proper error code whenever possible
+ code = data.error && data.error.code || 'unknown';
+ return $.Deferred().reject( code, data );
+ }
+ return data;
+ } );
+ return innerPromise;
+ } )
+ .promise( {
+ abort: function () {
+ apiPromise.abort();
+ if ( innerPromise ) {
+ innerPromise.abort();
+ }
+ }
+ } );
+ }
+ } );
+
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.login
+ */
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/api/messages.js b/www/wiki/resources/src/mediawiki/api/messages.js
new file mode 100644
index 00000000..a1a49996
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/api/messages.js
@@ -0,0 +1,78 @@
+/**
+ * Allows to retrieve a specific or a set of
+ * messages to be added to mw.messages and returned
+ * by the Api.
+ *
+ * @class mw.Api.plugin.messages
+ * @since 1.27
+ */
+( function ( mw, $ ) {
+ 'use strict';
+
+ $.extend( mw.Api.prototype, {
+ /**
+ * Get a set of messages.
+ *
+ * @param {Array} messages Messages to retrieve
+ * @param {Object} [options] Additional parameters for the API call
+ * @return {jQuery.Promise}
+ */
+ getMessages: function ( messages, options ) {
+ options = options || {};
+ return this.get( $.extend( {
+ action: 'query',
+ meta: 'allmessages',
+ ammessages: messages,
+ amlang: mw.config.get( 'wgUserLanguage' ),
+ formatversion: 2
+ }, options ) ).then( function ( data ) {
+ var result = {};
+
+ $.each( data.query.allmessages, function ( i, obj ) {
+ if ( !obj.missing ) {
+ result[ obj.name ] = obj.content;
+ }
+ } );
+
+ return result;
+ } );
+ },
+
+ /**
+ * Loads a set of messages and add them to mw.messages.
+ *
+ * @param {Array} messages Messages to retrieve
+ * @param {Object} [options] Additional parameters for the API call
+ * @return {jQuery.Promise}
+ */
+ loadMessages: function ( messages, options ) {
+ return this.getMessages( messages, options ).then( $.proxy( mw.messages, 'set' ) );
+ },
+
+ /**
+ * Loads a set of messages and add them to mw.messages. Only messages that are not already known
+ * are loaded. If all messages are known, the returned promise is resolved immediately.
+ *
+ * @param {Array} messages Messages to retrieve
+ * @param {Object} [options] Additional parameters for the API call
+ * @return {jQuery.Promise}
+ */
+ loadMessagesIfMissing: function ( messages, options ) {
+ var missing = messages.filter( function ( msg ) {
+ return !mw.message( msg ).exists();
+ } );
+
+ if ( missing.length === 0 ) {
+ return $.Deferred().resolve();
+ }
+
+ return this.getMessages( missing, options ).then( $.proxy( mw.messages, 'set' ) );
+ }
+ } );
+
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.messages
+ */
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/api/options.js b/www/wiki/resources/src/mediawiki/api/options.js
new file mode 100644
index 00000000..4930c4fc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/api/options.js
@@ -0,0 +1,102 @@
+/**
+ * @class mw.Api.plugin.options
+ */
+( function ( mw, $ ) {
+
+ $.extend( mw.Api.prototype, {
+
+ /**
+ * Asynchronously save the value of a single user option using the API. See #saveOptions.
+ *
+ * @param {string} name
+ * @param {string|null} value
+ * @return {jQuery.Promise}
+ */
+ saveOption: function ( name, value ) {
+ var param = {};
+ param[ name ] = value;
+ return this.saveOptions( param );
+ },
+
+ /**
+ * Asynchronously save the values of user options using the API.
+ *
+ * If a value of `null` is provided, the given option will be reset to the default value.
+ *
+ * Any warnings returned by the API, including warnings about invalid option names or values,
+ * are ignored. However, do not rely on this behavior.
+ *
+ * If necessary, the options will be saved using several sequential API requests. Only one promise
+ * is always returned that will be resolved when all requests complete.
+ *
+ * @param {Object} options Options as a `{ name: value, … }` object
+ * @return {jQuery.Promise}
+ */
+ saveOptions: function ( options ) {
+ var name, value, bundleable,
+ grouped = [],
+ promise = $.Deferred().resolve();
+
+ for ( name in options ) {
+ value = options[ name ] === null ? null : String( options[ name ] );
+
+ // Can we bundle this option, or does it need a separate request?
+ if ( this.defaults.useUS ) {
+ bundleable = name.indexOf( '=' ) === -1;
+ } else {
+ bundleable =
+ ( value === null || value.indexOf( '|' ) === -1 ) &&
+ ( name.indexOf( '|' ) === -1 && name.indexOf( '=' ) === -1 );
+ }
+
+ if ( bundleable ) {
+ if ( value !== null ) {
+ grouped.push( name + '=' + value );
+ } else {
+ // Omitting value resets the option
+ grouped.push( name );
+ }
+ } else {
+ if ( value !== null ) {
+ promise = promise.then( function ( name, value ) {
+ return this.postWithToken( 'csrf', {
+ formatversion: 2,
+ action: 'options',
+ optionname: name,
+ optionvalue: value
+ } );
+ }.bind( this, name, value ) );
+ } else {
+ // Omitting value resets the option
+ promise = promise.then( function ( name ) {
+ return this.postWithToken( 'csrf', {
+ formatversion: 2,
+ action: 'options',
+ optionname: name
+ } );
+ }.bind( this, name ) );
+ }
+ }
+ }
+
+ if ( grouped.length ) {
+ promise = promise.then( function () {
+ return this.postWithToken( 'csrf', {
+ formatversion: 2,
+ action: 'options',
+ change: grouped
+ } );
+ }.bind( this ) );
+ }
+
+ return promise;
+ }
+
+ } );
+
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.options
+ */
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/api/parse.js b/www/wiki/resources/src/mediawiki/api/parse.js
new file mode 100644
index 00000000..f38e88b5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/api/parse.js
@@ -0,0 +1,49 @@
+/**
+ * @class mw.Api.plugin.parse
+ */
+( function ( mw, $ ) {
+
+ $.extend( mw.Api.prototype, {
+ /**
+ * Convenience method for 'action=parse'.
+ *
+ * @param {string|mw.Title} content Content to parse, either as a wikitext string or
+ * a mw.Title.
+ * @param {Object} additionalParams Parameters object to set custom settings, e.g.
+ * redirects, sectionpreview. prop should not be overridden.
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {string} return.done.data Parsed HTML of `wikitext`.
+ */
+ parse: function ( content, additionalParams ) {
+ var apiPromise,
+ config = $.extend( {
+ formatversion: 2,
+ action: 'parse',
+ contentmodel: 'wikitext'
+ }, additionalParams );
+
+ if ( mw.Title && content instanceof mw.Title ) {
+ // Parse existing page
+ config.page = content.getPrefixedDb();
+ } else {
+ // Parse wikitext from input
+ config.text = String( content );
+ }
+
+ apiPromise = this.get( config );
+
+ return apiPromise
+ .then( function ( data ) {
+ return data.parse.text;
+ } )
+ .promise( { abort: apiPromise.abort } );
+ }
+ } );
+
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.parse
+ */
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/api/rollback.js b/www/wiki/resources/src/mediawiki/api/rollback.js
new file mode 100644
index 00000000..322143dc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/api/rollback.js
@@ -0,0 +1,33 @@
+/**
+ * @class mw.Api.plugin.rollback
+ * @since 1.28
+ */
+( function ( mw, $ ) {
+
+ $.extend( mw.Api.prototype, {
+ /**
+ * Convenience method for `action=rollback`.
+ *
+ * @param {string|mw.Title} page
+ * @param {string} user
+ * @param {Object} [params] Additional parameters
+ * @return {jQuery.Promise}
+ */
+ rollback: function ( page, user, params ) {
+ return this.postWithToken( 'rollback', $.extend( {
+ action: 'rollback',
+ title: String( page ),
+ user: user,
+ uselang: mw.config.get( 'wgUserLanguage' )
+ }, params ) ).then( function ( data ) {
+ return data.rollback;
+ } );
+ }
+ } );
+
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.rollback
+ */
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/api/upload.js b/www/wiki/resources/src/mediawiki/api/upload.js
new file mode 100644
index 00000000..29bd59ae
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/api/upload.js
@@ -0,0 +1,668 @@
+/**
+ * Provides an interface for uploading files to MediaWiki.
+ *
+ * @class mw.Api.plugin.upload
+ * @singleton
+ */
+( function ( mw, $ ) {
+ var nonce = 0,
+ fieldsAllowed = {
+ stash: true,
+ filekey: true,
+ filename: true,
+ comment: true,
+ text: true,
+ watchlist: true,
+ ignorewarnings: true,
+ chunk: true,
+ offset: true,
+ filesize: true,
+ async: true
+ };
+
+ /**
+ * Get nonce for iframe IDs on the page.
+ *
+ * @private
+ * @return {number}
+ */
+ function getNonce() {
+ return nonce++;
+ }
+
+ /**
+ * Given a non-empty object, return one of its keys.
+ *
+ * @private
+ * @param {Object} obj
+ * @return {string}
+ */
+ function getFirstKey( obj ) {
+ var key;
+ for ( key in obj ) {
+ if ( obj.hasOwnProperty( key ) ) {
+ return key;
+ }
+ }
+ }
+
+ /**
+ * Get new iframe object for an upload.
+ *
+ * @private
+ * @param {string} id
+ * @return {HTMLIframeElement}
+ */
+ function getNewIframe( id ) {
+ var frame = document.createElement( 'iframe' );
+ frame.id = id;
+ frame.name = id;
+ return frame;
+ }
+
+ /**
+ * Shortcut for getting hidden inputs
+ *
+ * @private
+ * @param {string} name
+ * @param {string} val
+ * @return {jQuery}
+ */
+ function getHiddenInput( name, val ) {
+ return $( '<input>' ).attr( 'type', 'hidden' )
+ .attr( 'name', name )
+ .val( val );
+ }
+
+ /**
+ * Process the result of the form submission, returned to an iframe.
+ * This is the iframe's onload event.
+ *
+ * @param {HTMLIframeElement} iframe Iframe to extract result from
+ * @return {Object} Response from the server. The return value may or may
+ * not be an XMLDocument, this code was copied from elsewhere, so if you
+ * see an unexpected return type, please file a bug.
+ */
+ function processIframeResult( iframe ) {
+ var json,
+ doc = iframe.contentDocument || frames[ iframe.id ].document;
+
+ if ( doc.XMLDocument ) {
+ // The response is a document property in IE
+ return doc.XMLDocument;
+ }
+
+ if ( doc.body ) {
+ // Get the json string
+ // We're actually searching through an HTML doc here --
+ // according to mdale we need to do this
+ // because IE does not load JSON properly in an iframe
+ json = $( doc.body ).find( 'pre' ).text();
+
+ return JSON.parse( json );
+ }
+
+ // Response is a xml document
+ return doc;
+ }
+
+ function formDataAvailable() {
+ return window.FormData !== undefined &&
+ window.File !== undefined &&
+ window.File.prototype.slice !== undefined;
+ }
+
+ $.extend( mw.Api.prototype, {
+ /**
+ * Upload a file to MediaWiki.
+ *
+ * The file will be uploaded using AJAX and FormData, if the browser supports it, or via an
+ * iframe if it doesn't.
+ *
+ * Caveats of iframe upload:
+ * - The returned jQuery.Promise will not receive `progress` notifications during the upload
+ * - It is incompatible with uploads to a foreign wiki using mw.ForeignApi
+ * - You must pass a HTMLInputElement and not a File for it to be possible
+ *
+ * @param {HTMLInputElement|File|Blob} file HTML input type=file element with a file already inside
+ * of it, or a File object.
+ * @param {Object} data Other upload options, see action=upload API docs for more
+ * @return {jQuery.Promise}
+ */
+ upload: function ( file, data ) {
+ var isFileInput, canUseFormData;
+
+ isFileInput = file && file.nodeType === Node.ELEMENT_NODE;
+
+ if ( formDataAvailable() && isFileInput && file.files ) {
+ file = file.files[ 0 ];
+ }
+
+ if ( !file ) {
+ throw new Error( 'No file' );
+ }
+
+ // Blobs are allowed in formdata uploads, it turns out
+ canUseFormData = formDataAvailable() && ( file instanceof window.File || file instanceof window.Blob );
+
+ if ( !isFileInput && !canUseFormData ) {
+ throw new Error( 'Unsupported argument type passed to mw.Api.upload' );
+ }
+
+ if ( canUseFormData ) {
+ return this.uploadWithFormData( file, data );
+ }
+
+ return this.uploadWithIframe( file, data );
+ },
+
+ /**
+ * Upload a file to MediaWiki with an iframe and a form.
+ *
+ * This method is necessary for browsers without the File/FormData
+ * APIs, and continues to work in browsers with those APIs.
+ *
+ * The rough sketch of how this method works is as follows:
+ * 1. An iframe is loaded with no content.
+ * 2. A form is submitted with the passed-in file input and some extras.
+ * 3. The MediaWiki API receives that form data, and sends back a response.
+ * 4. The response is sent to the iframe, because we set target=(iframe id)
+ * 5. The response is parsed out of the iframe's document, and passed back
+ * through the promise.
+ *
+ * @private
+ * @param {HTMLInputElement} file The file input with a file in it.
+ * @param {Object} data Other upload options, see action=upload API docs for more
+ * @return {jQuery.Promise}
+ */
+ uploadWithIframe: function ( file, data ) {
+ var key,
+ tokenPromise = $.Deferred(),
+ api = this,
+ deferred = $.Deferred(),
+ nonce = getNonce(),
+ id = 'uploadframe-' + nonce,
+ $form = $( '<form>' ),
+ iframe = getNewIframe( id ),
+ $iframe = $( iframe );
+
+ for ( key in data ) {
+ if ( !fieldsAllowed[ key ] ) {
+ delete data[ key ];
+ }
+ }
+
+ data = $.extend( {}, this.defaults.parameters, { action: 'upload' }, data );
+ $form.addClass( 'mw-api-upload-form' );
+
+ $form.css( 'display', 'none' )
+ .attr( {
+ action: this.defaults.ajax.url,
+ method: 'POST',
+ target: id,
+ enctype: 'multipart/form-data'
+ } );
+
+ $iframe.one( 'load', function () {
+ $iframe.one( 'load', function () {
+ var result = processIframeResult( iframe );
+ deferred.notify( 1 );
+
+ if ( !result ) {
+ deferred.reject( 'ok-but-empty', 'No response from API on upload attempt.' );
+ } else if ( result.error ) {
+ if ( result.error.code === 'badtoken' ) {
+ api.badToken( 'csrf' );
+ }
+
+ deferred.reject( result.error.code, result );
+ } else if ( result.upload && result.upload.warnings ) {
+ deferred.reject( getFirstKey( result.upload.warnings ), result );
+ } else {
+ deferred.resolve( result );
+ }
+ } );
+ tokenPromise.done( function () {
+ $form.submit();
+ } );
+ } );
+
+ $iframe.on( 'error', function ( error ) {
+ deferred.reject( 'http', error );
+ } );
+
+ $iframe.prop( 'src', 'about:blank' ).hide();
+
+ file.name = 'file';
+
+ $.each( data, function ( key, val ) {
+ $form.append( getHiddenInput( key, val ) );
+ } );
+
+ if ( !data.filename && !data.stash ) {
+ throw new Error( 'Filename not included in file data.' );
+ }
+
+ if ( this.needToken() ) {
+ this.getEditToken().then( function ( token ) {
+ $form.append( getHiddenInput( 'token', token ) );
+ tokenPromise.resolve();
+ }, tokenPromise.reject );
+ } else {
+ tokenPromise.resolve();
+ }
+
+ $( 'body' ).append( $form, $iframe );
+
+ deferred.always( function () {
+ $form.remove();
+ $iframe.remove();
+ } );
+
+ return deferred.promise();
+ },
+
+ /**
+ * Uploads a file using the FormData API.
+ *
+ * @private
+ * @param {File} file
+ * @param {Object} data Other upload options, see action=upload API docs for more
+ * @return {jQuery.Promise}
+ */
+ uploadWithFormData: function ( file, data ) {
+ var key, request,
+ deferred = $.Deferred();
+
+ for ( key in data ) {
+ if ( !fieldsAllowed[ key ] ) {
+ delete data[ key ];
+ }
+ }
+
+ data = $.extend( {}, this.defaults.parameters, { action: 'upload' }, data );
+ if ( !data.chunk ) {
+ data.file = file;
+ }
+
+ if ( !data.filename && !data.stash ) {
+ throw new Error( 'Filename not included in file data.' );
+ }
+
+ // Use this.postWithEditToken() or this.post()
+ request = this[ this.needToken() ? 'postWithEditToken' : 'post' ]( data, {
+ // Use FormData (if we got here, we know that it's available)
+ contentType: 'multipart/form-data',
+ // No timeout (default from mw.Api is 30 seconds)
+ timeout: 0,
+ // Provide upload progress notifications
+ xhr: function () {
+ var xhr = $.ajaxSettings.xhr();
+ if ( xhr.upload ) {
+ // need to bind this event before we open the connection (see note at
+ // https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest#Monitoring_progress)
+ xhr.upload.addEventListener( 'progress', function ( ev ) {
+ if ( ev.lengthComputable ) {
+ deferred.notify( ev.loaded / ev.total );
+ }
+ } );
+ }
+ return xhr;
+ }
+ } )
+ .done( function ( result ) {
+ deferred.notify( 1 );
+ if ( result.upload && result.upload.warnings ) {
+ deferred.reject( getFirstKey( result.upload.warnings ), result );
+ } else {
+ deferred.resolve( result );
+ }
+ } )
+ .fail( function ( errorCode, result ) {
+ deferred.notify( 1 );
+ deferred.reject( errorCode, result );
+ } );
+
+ return deferred.promise( { abort: request.abort } );
+ },
+
+ /**
+ * Upload a file in several chunks.
+ *
+ * @param {File} file
+ * @param {Object} data Other upload options, see action=upload API docs for more
+ * @param {number} [chunkSize] Size (in bytes) per chunk (default: 5MB)
+ * @param {number} [chunkRetries] Amount of times to retry a failed chunk (default: 1)
+ * @return {jQuery.Promise}
+ */
+ chunkedUpload: function ( file, data, chunkSize, chunkRetries ) {
+ var start, end, promise, next, active,
+ deferred = $.Deferred();
+
+ chunkSize = chunkSize === undefined ? 5 * 1024 * 1024 : chunkSize;
+ chunkRetries = chunkRetries === undefined ? 1 : chunkRetries;
+
+ if ( !data.filename ) {
+ throw new Error( 'Filename not included in file data.' );
+ }
+
+ // Submit first chunk to get the filekey
+ active = promise = this.uploadChunk( file, data, 0, chunkSize, '', chunkRetries )
+ .done( chunkSize >= file.size ? deferred.resolve : null )
+ .fail( deferred.reject )
+ .progress( deferred.notify );
+
+ // Now iteratively submit the rest of the chunks
+ for ( start = chunkSize; start < file.size; start += chunkSize ) {
+ end = Math.min( start + chunkSize, file.size );
+ next = $.Deferred();
+
+ // We could simply chain one this.uploadChunk after another with
+ // .then(), but then we'd hit an `Uncaught RangeError: Maximum
+ // call stack size exceeded` at as low as 1024 calls in Firefox
+ // 47. This'll work around it, but comes with the drawback of
+ // having to properly relay the results to the returned promise.
+ // eslint-disable-next-line no-loop-func
+ promise.done( function ( start, end, next, result ) {
+ var filekey = result.upload.filekey;
+ active = this.uploadChunk( file, data, start, end, filekey, chunkRetries )
+ .done( end === file.size ? deferred.resolve : next.resolve )
+ .fail( deferred.reject )
+ .progress( deferred.notify );
+ // start, end & next must be bound to closure, or they'd have
+ // changed by the time the promises are resolved
+ }.bind( this, start, end, next ) );
+
+ promise = next;
+ }
+
+ return deferred.promise( { abort: active.abort } );
+ },
+
+ /**
+ * Uploads 1 chunk.
+ *
+ * @private
+ * @param {File} file
+ * @param {Object} data Other upload options, see action=upload API docs for more
+ * @param {number} start Chunk start position
+ * @param {number} end Chunk end position
+ * @param {string} [filekey] File key, for follow-up chunks
+ * @param {number} [retries] Amount of times to retry request
+ * @return {jQuery.Promise}
+ */
+ uploadChunk: function ( file, data, start, end, filekey, retries ) {
+ var upload,
+ api = this,
+ chunk = this.slice( file, start, end );
+
+ // When uploading in chunks, we're going to be issuing a lot more
+ // requests and there's always a chance of 1 getting dropped.
+ // In such case, it could be useful to try again: a network hickup
+ // doesn't necessarily have to result in upload failure...
+ retries = retries === undefined ? 1 : retries;
+
+ data.filesize = file.size;
+ data.chunk = chunk;
+ data.offset = start;
+
+ // filekey must only be added when uploading follow-up chunks; the
+ // first chunk should never have a filekey (it'll be generated)
+ if ( filekey && start !== 0 ) {
+ data.filekey = filekey;
+ }
+
+ upload = this.uploadWithFormData( file, data );
+ return upload.then(
+ null,
+ function ( code, result ) {
+ var retry;
+
+ // uploadWithFormData will reject uploads with warnings, but
+ // these warnings could be "harmless" or recovered from
+ // (e.g. exists-normalized, when it'll be renamed later)
+ // In the case of (only) a warning, we still want to
+ // continue the chunked upload until it completes: then
+ // reject it - at least it's been fully uploaded by then and
+ // failure handlers have a complete result object (including
+ // possibly more warnings, e.g. duplicate)
+ // This matches .upload, which also completes the upload.
+ if ( result.upload && result.upload.warnings && code in result.upload.warnings ) {
+ if ( end === file.size ) {
+ // uploaded last chunk = reject with result data
+ return $.Deferred().reject( code, result );
+ } else {
+ // still uploading chunks = resolve to keep going
+ return $.Deferred().resolve( result );
+ }
+ }
+
+ if ( retries === 0 ) {
+ return $.Deferred().reject( code, result );
+ }
+
+ // If the call flat out failed, we may want to try again...
+ retry = api.uploadChunk.bind( this, file, data, start, end, filekey, retries - 1 );
+ return api.retry( code, result, retry );
+ },
+ function ( fraction ) {
+ // Since we're only uploading small parts of a file, we
+ // need to adjust the reported progress to reflect where
+ // we actually are in the combined upload
+ return ( start + fraction * ( end - start ) ) / file.size;
+ }
+ ).promise( { abort: upload.abort } );
+ },
+
+ /**
+ * Launch the upload anew if it failed because of network issues.
+ *
+ * @private
+ * @param {string} code Error code
+ * @param {Object} result API result
+ * @param {Function} callable
+ * @return {jQuery.Promise}
+ */
+ retry: function ( code, result, callable ) {
+ var uploadPromise,
+ retryTimer,
+ deferred = $.Deferred(),
+ // Wrap around the callable, so that once it completes, it'll
+ // resolve/reject the promise we'll return
+ retry = function () {
+ uploadPromise = callable();
+ uploadPromise.then( deferred.resolve, deferred.reject );
+ };
+
+ // Don't retry if the request failed because we aborted it (or if
+ // it's another kind of request failure)
+ if ( code !== 'http' || result.textStatus === 'abort' ) {
+ return deferred.reject( code, result );
+ }
+
+ retryTimer = setTimeout( retry, 1000 );
+ return deferred.promise( { abort: function () {
+ // Clear the scheduled upload, or abort if already in flight
+ if ( retryTimer ) {
+ clearTimeout( retryTimer );
+ }
+ if ( uploadPromise.abort ) {
+ uploadPromise.abort();
+ }
+ } } );
+ },
+
+ /**
+ * Slice a chunk out of a File object.
+ *
+ * @private
+ * @param {File} file
+ * @param {number} start
+ * @param {number} stop
+ * @return {Blob}
+ */
+ slice: function ( file, start, stop ) {
+ if ( file.mozSlice ) {
+ // FF <= 12
+ return file.mozSlice( start, stop, file.type );
+ } else if ( file.webkitSlice ) {
+ // Chrome <= 20
+ return file.webkitSlice( start, stop, file.type );
+ } else {
+ // On really old browser versions (before slice was prefixed),
+ // slice() would take (start, length) instead of (start, end)
+ // We'll ignore that here...
+ return file.slice( start, stop, file.type );
+ }
+ },
+
+ /**
+ * This function will handle how uploads to stash (via uploadToStash or
+ * chunkedUploadToStash) are resolved/rejected.
+ *
+ * After a successful stash, it'll resolve with a callback which, when
+ * called, will finalize the upload in stash (with the given data, or
+ * with additional/conflicting data)
+ *
+ * A failed stash can still be recovered from as long as 'filekey' is
+ * present. In that case, it'll also resolve with the callback to
+ * finalize the upload (all warnings are then ignored.)
+ * Otherwise, it'll just reject as you'd expect, with code & result.
+ *
+ * @private
+ * @param {jQuery.Promise} uploadPromise
+ * @param {Object} data
+ * @return {jQuery.Promise}
+ * @return {Function} return.finishUpload Call this function to finish the upload.
+ * @return {Object} return.finishUpload.data Additional data for the upload.
+ * @return {jQuery.Promise} return.finishUpload.return API promise for the final upload
+ * @return {Object} return.finishUpload.return.data API return value for the final upload
+ */
+ finishUploadToStash: function ( uploadPromise, data ) {
+ var filekey,
+ api = this;
+
+ function finishUpload( moreData ) {
+ return api.uploadFromStash( filekey, $.extend( data, moreData ) );
+ }
+
+ return uploadPromise.then(
+ function ( result ) {
+ filekey = result.upload.filekey;
+ return finishUpload;
+ },
+ function ( errorCode, result ) {
+ if ( result && result.upload && result.upload.filekey ) {
+ // Ignore any warnings if 'filekey' was returned, that's all we care about
+ filekey = result.upload.filekey;
+ return $.Deferred().resolve( finishUpload );
+ }
+ return $.Deferred().reject( errorCode, result );
+ }
+ );
+ },
+
+ /**
+ * Upload a file to the stash.
+ *
+ * This function will return a promise, which when resolved, will pass back a function
+ * to finish the stash upload. You can call that function with an argument containing
+ * more, or conflicting, data to pass to the server. For example:
+ *
+ * // upload a file to the stash with a placeholder filename
+ * api.uploadToStash( file, { filename: 'testing.png' } ).done( function ( finish ) {
+ * // finish is now the function we can use to finalize the upload
+ * // pass it a new filename from user input to override the initial value
+ * finish( { filename: getFilenameFromUser() } ).done( function ( data ) {
+ * // the upload is complete, data holds the API response
+ * } );
+ * } );
+ *
+ * @param {File|HTMLInputElement} file
+ * @param {Object} [data]
+ * @return {jQuery.Promise}
+ * @return {Function} return.finishUpload Call this function to finish the upload.
+ * @return {Object} return.finishUpload.data Additional data for the upload.
+ * @return {jQuery.Promise} return.finishUpload.return API promise for the final upload
+ * @return {Object} return.finishUpload.return.data API return value for the final upload
+ */
+ uploadToStash: function ( file, data ) {
+ var promise;
+
+ if ( !data.filename ) {
+ throw new Error( 'Filename not included in file data.' );
+ }
+
+ promise = this.upload( file, { stash: true, filename: data.filename } );
+
+ return this.finishUploadToStash( promise, data );
+ },
+
+ /**
+ * Upload a file to the stash, in chunks.
+ *
+ * This function will return a promise, which when resolved, will pass back a function
+ * to finish the stash upload.
+ *
+ * @see #method-uploadToStash
+ * @param {File|HTMLInputElement} file
+ * @param {Object} [data]
+ * @param {number} [chunkSize] Size (in bytes) per chunk (default: 5MB)
+ * @param {number} [chunkRetries] Amount of times to retry a failed chunk (default: 1)
+ * @return {jQuery.Promise}
+ * @return {Function} return.finishUpload Call this function to finish the upload.
+ * @return {Object} return.finishUpload.data Additional data for the upload.
+ * @return {jQuery.Promise} return.finishUpload.return API promise for the final upload
+ * @return {Object} return.finishUpload.return.data API return value for the final upload
+ */
+ chunkedUploadToStash: function ( file, data, chunkSize, chunkRetries ) {
+ var promise;
+
+ if ( !data.filename ) {
+ throw new Error( 'Filename not included in file data.' );
+ }
+
+ promise = this.chunkedUpload(
+ file,
+ { stash: true, filename: data.filename },
+ chunkSize,
+ chunkRetries
+ );
+
+ return this.finishUploadToStash( promise, data );
+ },
+
+ /**
+ * Finish an upload in the stash.
+ *
+ * @param {string} filekey
+ * @param {Object} data
+ * @return {jQuery.Promise}
+ */
+ uploadFromStash: function ( filekey, data ) {
+ data.filekey = filekey;
+ data.action = 'upload';
+ data.format = 'json';
+
+ if ( !data.filename ) {
+ throw new Error( 'Filename not included in file data.' );
+ }
+
+ return this.postWithEditToken( data ).then( function ( result ) {
+ if ( result.upload && result.upload.warnings ) {
+ return $.Deferred().reject( getFirstKey( result.upload.warnings ), result ).promise();
+ }
+ return result;
+ } );
+ },
+
+ needToken: function () {
+ return true;
+ }
+ } );
+
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.upload
+ */
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/api/user.js b/www/wiki/resources/src/mediawiki/api/user.js
new file mode 100644
index 00000000..e7b4b6d5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/api/user.js
@@ -0,0 +1,37 @@
+/**
+ * @class mw.Api.plugin.user
+ * @since 1.27
+ */
+( function ( mw, $ ) {
+
+ $.extend( mw.Api.prototype, {
+
+ /**
+ * Get the current user's groups and rights.
+ *
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {Object} return.done.userInfo
+ * @return {string[]} return.done.userInfo.groups User groups that the current user belongs to
+ * @return {string[]} return.done.userInfo.rights Current user's rights
+ */
+ getUserInfo: function () {
+ return this.get( {
+ action: 'query',
+ meta: 'userinfo',
+ uiprop: [ 'groups', 'rights' ]
+ } ).then( function ( data ) {
+ if ( data.query && data.query.userinfo ) {
+ return data.query.userinfo;
+ }
+ return $.Deferred().reject().promise();
+ } );
+ }
+ } );
+
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.user
+ */
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/api/watch.js b/www/wiki/resources/src/mediawiki/api/watch.js
new file mode 100644
index 00000000..f50e59a9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/api/watch.js
@@ -0,0 +1,70 @@
+/**
+ * @class mw.Api.plugin.watch
+ * @since 1.19
+ */
+( function ( mw, $ ) {
+
+ /**
+ * @private
+ * @static
+ * @context mw.Api
+ *
+ * @param {string|mw.Title|string[]|mw.Title[]} pages Full page name or instance of mw.Title, or an
+ * array thereof. If an array is passed, the return value passed to the promise will also be an
+ * array of appropriate objects.
+ * @param {Object} [addParams]
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {Object|Object[]} return.done.watch Object or list of objects (depends on the `pages`
+ * parameter)
+ * @return {string} return.done.watch.title Full pagename
+ * @return {boolean} return.done.watch.watched Whether the page is now watched or unwatched
+ */
+ function doWatchInternal( pages, addParams ) {
+ // XXX: Parameter addParams is undocumented because we inherit this
+ // documentation in the public method...
+ var apiPromise = this.postWithToken( 'watch',
+ $.extend(
+ {
+ formatversion: 2,
+ action: 'watch',
+ titles: Array.isArray( pages ) ? pages.join( '|' ) : String( pages )
+ },
+ addParams
+ )
+ );
+
+ return apiPromise
+ .then( function ( data ) {
+ // If a single page was given (not an array) respond with a single item as well.
+ return Array.isArray( pages ) ? data.watch : data.watch[ 0 ];
+ } )
+ .promise( { abort: apiPromise.abort } );
+ }
+
+ $.extend( mw.Api.prototype, {
+ /**
+ * Convenience method for `action=watch`.
+ *
+ * @inheritdoc #doWatchInternal
+ */
+ watch: function ( pages ) {
+ return doWatchInternal.call( this, pages );
+ },
+
+ /**
+ * Convenience method for `action=watch&unwatch=1`.
+ *
+ * @inheritdoc #doWatchInternal
+ */
+ unwatch: function ( pages ) {
+ return doWatchInternal.call( this, pages, { unwatch: 1 } );
+ }
+ } );
+
+ /**
+ * @class mw.Api
+ * @mixins mw.Api.plugin.watch
+ */
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/autocomplete.js b/www/wiki/resources/src/mediawiki/htmlform/autocomplete.js
new file mode 100644
index 00000000..81579755
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/autocomplete.js
@@ -0,0 +1,25 @@
+/*
+ * HTMLForm enhancements:
+ * Set up autocomplete fields.
+ */
+( function ( mw, $ ) {
+
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ var $autocomplete = $root.find( '.mw-htmlform-autocomplete' );
+ if ( $autocomplete.length ) {
+ mw.loader.using( 'jquery.suggestions', function () {
+ $autocomplete.suggestions( {
+ fetch: function ( val ) {
+ var $el = $( this );
+ $el.suggestions( 'suggestions',
+ $.grep( $el.data( 'autocomplete' ), function ( v ) {
+ return v.indexOf( val ) === 0;
+ } )
+ );
+ }
+ } );
+ } );
+ }
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/autoinfuse.js b/www/wiki/resources/src/mediawiki/htmlform/autoinfuse.js
new file mode 100644
index 00000000..f2e0f4dd
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/autoinfuse.js
@@ -0,0 +1,32 @@
+/*
+ * HTMLForm enhancements:
+ * Infuse some OOjs UI HTMLForm fields (those which benefit from always being infused).
+ */
+( function ( mw, $ ) {
+
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ var $oouiNodes, modules, extraModules;
+
+ $oouiNodes = $root.find( '.mw-htmlform-field-autoinfuse' );
+ if ( $oouiNodes.length ) {
+ // The modules are preloaded (added server-side in HTMLFormField, and the individual fields
+ // which need extra ones), but this module doesn't depend on them. Wait until they're loaded.
+ modules = [ 'mediawiki.htmlform.ooui' ];
+ $oouiNodes.each( function () {
+ var data = $( this ).data( 'mw-modules' );
+ if ( data ) {
+ // We can trust this value, 'data-mw-*' attributes are banned from user content in Sanitizer
+ extraModules = data.split( ',' );
+ modules.push.apply( modules, extraModules );
+ }
+ } );
+ mw.loader.using( modules ).done( function () {
+ $oouiNodes.each( function () {
+ OO.ui.infuse( this );
+ } );
+ } );
+ }
+
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/checkmatrix.js b/www/wiki/resources/src/mediawiki/htmlform/checkmatrix.js
new file mode 100644
index 00000000..b825f12b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/checkmatrix.js
@@ -0,0 +1,16 @@
+/*
+ * HTMLForm enhancements:
+ * Show fancy tooltips for checkmatrix fields.
+ */
+( function ( mw ) {
+
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ var $matrixTooltips = $root.find( '.mw-htmlform-matrix .mw-htmlform-tooltip' );
+ if ( $matrixTooltips.length ) {
+ mw.loader.using( 'jquery.tipsy', function () {
+ $matrixTooltips.tipsy( { gravity: 's' } );
+ } );
+ }
+ } );
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/cloner.js b/www/wiki/resources/src/mediawiki/htmlform/cloner.js
new file mode 100644
index 00000000..ab81580b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/cloner.js
@@ -0,0 +1,36 @@
+/*
+ * HTMLForm enhancements:
+ * Add/remove cloner clones without having to resubmit the form.
+ */
+( function ( mw, $ ) {
+
+ var cloneCounter = 0;
+
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ $root.find( '.mw-htmlform-cloner-delete-button' ).filter( ':input' ).click( function ( ev ) {
+ ev.preventDefault();
+ $( this ).closest( 'li.mw-htmlform-cloner-li' ).remove();
+ } );
+
+ $root.find( '.mw-htmlform-cloner-create-button' ).filter( ':input' ).click( function ( ev ) {
+ var $ul, $li, html;
+
+ ev.preventDefault();
+
+ $ul = $( this ).prev( 'ul.mw-htmlform-cloner-ul' );
+
+ html = $ul.data( 'template' ).replace(
+ new RegExp( mw.RegExp.escape( $ul.data( 'uniqueId' ) ), 'g' ),
+ 'clone' + ( ++cloneCounter )
+ );
+
+ $li = $( '<li>' )
+ .addClass( 'mw-htmlform-cloner-li' )
+ .html( html )
+ .appendTo( $ul );
+
+ mw.hook( 'htmlform.enhance' ).fire( $li );
+ } );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/hide-if.js b/www/wiki/resources/src/mediawiki/htmlform/hide-if.js
new file mode 100644
index 00000000..6d3c9fd1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/hide-if.js
@@ -0,0 +1,295 @@
+/*
+ * HTMLForm enhancements:
+ * Set up 'hide-if' behaviors for form fields that have them.
+ */
+( function ( mw, $ ) {
+
+ /**
+ * Helper function for hide-if to find the nearby form field.
+ *
+ * Find the closest match for the given name, "closest" being the minimum
+ * level of parents to go to find a form field matching the given name or
+ * ending in array keys matching the given name (e.g. "baz" matches
+ * "foo[bar][baz]").
+ *
+ * @ignore
+ * @private
+ * @param {jQuery} $el
+ * @param {string} name
+ * @return {jQuery|OO.ui.Widget|null}
+ */
+ function hideIfGetField( $el, name ) {
+ var $found, $p, $widget,
+ suffix = name.replace( /^([^[]+)/, '[$1]' );
+
+ function nameFilter() {
+ return this.name === name ||
+ ( this.name === ( 'wp' + name ) ) ||
+ this.name.slice( -suffix.length ) === suffix;
+ }
+
+ for ( $p = $el.parent(); $p.length > 0; $p = $p.parent() ) {
+ $found = $p.find( '[name]' ).filter( nameFilter );
+ if ( $found.length ) {
+ $widget = $found.closest( '.oo-ui-widget[data-ooui]' );
+ if ( $widget.length ) {
+ return OO.ui.Widget.static.infuse( $widget );
+ }
+ return $found;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Helper function for hide-if to return a test function and list of
+ * dependent fields for a hide-if specification.
+ *
+ * @ignore
+ * @private
+ * @param {jQuery} $el
+ * @param {Array} spec
+ * @return {Array}
+ * @return {Array} return.0 Dependent fields, array of jQuery objects or OO.ui.Widgets
+ * @return {Function} return.1 Test function
+ */
+ function hideIfParse( $el, spec ) {
+ var op, i, l, v, field, $field, fields, func, funcs, getVal;
+
+ op = spec[ 0 ];
+ l = spec.length;
+ switch ( op ) {
+ case 'AND':
+ case 'OR':
+ case 'NAND':
+ case 'NOR':
+ funcs = [];
+ fields = [];
+ for ( i = 1; i < l; i++ ) {
+ if ( !Array.isArray( spec[ i ] ) ) {
+ throw new Error( op + ' parameters must be arrays' );
+ }
+ v = hideIfParse( $el, spec[ i ] );
+ fields = fields.concat( v[ 0 ] );
+ funcs.push( v[ 1 ] );
+ }
+
+ l = funcs.length;
+ switch ( op ) {
+ case 'AND':
+ func = function () {
+ var i;
+ for ( i = 0; i < l; i++ ) {
+ if ( !funcs[ i ]() ) {
+ return false;
+ }
+ }
+ return true;
+ };
+ break;
+
+ case 'OR':
+ func = function () {
+ var i;
+ for ( i = 0; i < l; i++ ) {
+ if ( funcs[ i ]() ) {
+ return true;
+ }
+ }
+ return false;
+ };
+ break;
+
+ case 'NAND':
+ func = function () {
+ var i;
+ for ( i = 0; i < l; i++ ) {
+ if ( !funcs[ i ]() ) {
+ return true;
+ }
+ }
+ return false;
+ };
+ break;
+
+ case 'NOR':
+ func = function () {
+ var i;
+ for ( i = 0; i < l; i++ ) {
+ if ( funcs[ i ]() ) {
+ return false;
+ }
+ }
+ return true;
+ };
+ break;
+ }
+
+ return [ fields, func ];
+
+ case 'NOT':
+ if ( l !== 2 ) {
+ throw new Error( 'NOT takes exactly one parameter' );
+ }
+ if ( !Array.isArray( spec[ 1 ] ) ) {
+ throw new Error( 'NOT parameters must be arrays' );
+ }
+ v = hideIfParse( $el, spec[ 1 ] );
+ fields = v[ 0 ];
+ func = v[ 1 ];
+ return [ fields, function () {
+ return !func();
+ } ];
+
+ case '===':
+ case '!==':
+ if ( l !== 3 ) {
+ throw new Error( op + ' takes exactly two parameters' );
+ }
+ field = hideIfGetField( $el, spec[ 1 ] );
+ if ( !field ) {
+ return [ [], function () {
+ return false;
+ } ];
+ }
+ v = spec[ 2 ];
+
+ if ( !( field instanceof jQuery ) ) {
+ // field is a OO.ui.Widget
+ if ( field.supports( 'isSelected' ) ) {
+ getVal = function () {
+ var selected = field.isSelected();
+ return selected ? field.getValue() : '';
+ };
+ } else {
+ getVal = function () {
+ return field.getValue();
+ };
+ }
+ } else {
+ $field = $( field );
+ if ( $field.prop( 'type' ) === 'radio' || $field.prop( 'type' ) === 'checkbox' ) {
+ getVal = function () {
+ var $selected = $field.filter( ':checked' );
+ return $selected.length ? $selected.val() : '';
+ };
+ } else {
+ getVal = function () {
+ return $field.val();
+ };
+ }
+ }
+
+ switch ( op ) {
+ case '===':
+ func = function () {
+ return getVal() === v;
+ };
+ break;
+ case '!==':
+ func = function () {
+ return getVal() !== v;
+ };
+ break;
+ }
+
+ return [ [ field ], func ];
+
+ default:
+ throw new Error( 'Unrecognized operation \'' + op + '\'' );
+ }
+ }
+
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ var
+ $fields = $root.find( '.mw-htmlform-hide-if' ),
+ $oouiFields = $fields.filter( '[data-ooui]' ),
+ modules = [];
+
+ if ( $oouiFields.length ) {
+ modules.push( 'mediawiki.htmlform.ooui' );
+ $oouiFields.each( function () {
+ var data, extraModules,
+ $el = $( this );
+
+ data = $el.data( 'mw-modules' );
+ if ( data ) {
+ // We can trust this value, 'data-mw-*' attributes are banned from user content in Sanitizer
+ extraModules = data.split( ',' );
+ modules.push.apply( modules, extraModules );
+ }
+ } );
+ }
+
+ mw.loader.using( modules ).done( function () {
+ $fields.each( function () {
+ var v, i, fields, test, func, spec, self,
+ $el = $( this );
+
+ if ( $el.is( '[data-ooui]' ) ) {
+ // self should be a FieldLayout that mixes in mw.htmlform.Element
+ self = OO.ui.FieldLayout.static.infuse( $el );
+ spec = self.hideIf;
+ // The original element has been replaced with infused one
+ $el = self.$element;
+ } else {
+ self = $el;
+ spec = $el.data( 'hideIf' );
+ }
+
+ if ( !spec ) {
+ return;
+ }
+
+ v = hideIfParse( $el, spec );
+ fields = v[ 0 ];
+ test = v[ 1 ];
+ // The .toggle() method works mostly the same for jQuery objects and OO.ui.Widget
+ func = function () {
+ var shouldHide = test();
+ self.toggle( !shouldHide );
+
+ // It is impossible to submit a form with hidden fields failing validation, e.g. one that
+ // is required. However, validity is not checked for disabled fields, as these are not
+ // submitted with the form. So we should also disable fields when hiding them.
+ if ( self instanceof jQuery ) {
+ // This also finds elements inside any nested fields (in case of HTMLFormFieldCloner),
+ // which is problematic. But it works because:
+ // * HTMLFormFieldCloner::createFieldsForKey() copies 'hide-if' rules to nested fields
+ // * jQuery collections like $fields are in document order, so we register event
+ // handlers for parents first
+ // * Event handlers are fired in the order they were registered, so even if the handler
+ // for parent messed up the child, the handle for child will run next and fix it
+ self.find( 'input, textarea, select' ).each( function () {
+ var $this = $( this );
+ if ( shouldHide ) {
+ if ( $this.data( 'was-disabled' ) === undefined ) {
+ $this.data( 'was-disabled', $this.prop( 'disabled' ) );
+ }
+ $this.prop( 'disabled', true );
+ } else {
+ $this.prop( 'disabled', $this.data( 'was-disabled' ) );
+ }
+ } );
+ } else {
+ // self is a OO.ui.FieldLayout
+ if ( shouldHide ) {
+ if ( self.wasDisabled === undefined ) {
+ self.wasDisabled = self.fieldWidget.isDisabled();
+ }
+ self.fieldWidget.setDisabled( true );
+ } else if ( self.wasDisabled !== undefined ) {
+ self.fieldWidget.setDisabled( self.wasDisabled );
+ }
+ }
+ };
+ for ( i = 0; i < fields.length; i++ ) {
+ // The .on() method works mostly the same for jQuery objects and OO.ui.Widget
+ fields[ i ].on( 'change', func );
+ }
+ func();
+ } );
+ } );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/htmlform.Checker.js b/www/wiki/resources/src/mediawiki/htmlform/htmlform.Checker.js
new file mode 100644
index 00000000..3f53b636
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/htmlform.Checker.js
@@ -0,0 +1,180 @@
+( function ( mw, $ ) {
+
+ mw.htmlform = {};
+
+ /**
+ * @class mw.htmlform.Checker
+ */
+
+ /**
+ * A helper class to add validation to non-OOUI HtmlForm fields.
+ *
+ * @constructor
+ * @param {jQuery} $element Form field generated by HTMLForm
+ * @param {Function} validator Validation callback
+ * @param {string} validator.value Value of the form field to be validated
+ * @param {jQuery.Promise} validator.return The promise should be resolved
+ * with an object with two properties: Boolean 'valid' to indicate success
+ * or failure of validation, and an array 'messages' to be passed to
+ * setErrors() on failure.
+ */
+ mw.htmlform.Checker = function ( $element, validator ) {
+ this.validator = validator;
+ this.$element = $element;
+
+ this.$errorBox = $element.next( '.error' );
+ if ( !this.$errorBox.length ) {
+ this.$errorBox = $( '<span>' );
+ this.$errorBox.hide();
+ $element.after( this.$errorBox );
+ }
+
+ this.currentValue = this.$element.val();
+ };
+
+ /**
+ * Attach validation events to the form element
+ *
+ * @param {jQuery} [$extraElements] Additional elements to listen for change
+ * events on.
+ * @return {mw.htmlform.Checker}
+ * @chainable
+ */
+ mw.htmlform.Checker.prototype.attach = function ( $extraElements ) {
+ var $e,
+ // We need to hook to all of these events to be sure we are
+ // notified of all changes to the value of an <input type=text>
+ // field.
+ events = 'keyup keydown change mouseup cut paste focus blur';
+
+ $e = this.$element;
+ if ( $extraElements ) {
+ $e = $e.add( $extraElements );
+ }
+ $e.on( events, $.debounce( 1000, this.validate.bind( this ) ) );
+
+ return this;
+ };
+
+ /**
+ * Validate the form element
+ * @return {jQuery.Promise}
+ */
+ mw.htmlform.Checker.prototype.validate = function () {
+ var currentRequestInternal,
+ that = this,
+ value = this.$element.val();
+
+ // Abort any pending requests.
+ if ( this.currentRequest && this.currentRequest.abort ) {
+ this.currentRequest.abort();
+ }
+
+ if ( value === '' ) {
+ this.currentValue = value;
+ this.setErrors( [] );
+ return;
+ }
+
+ this.currentRequest = currentRequestInternal = this.validator( value )
+ .done( function ( info ) {
+ var forceReplacement = value !== that.currentValue;
+
+ // Another request was fired in the meantime, the result we got here is no longer current.
+ // This shouldn't happen as we abort pending requests, but you never know.
+ if ( that.currentRequest !== currentRequestInternal ) {
+ return;
+ }
+ // If we're here, then the current request has finished, avoid calling .abort() needlessly.
+ that.currentRequest = undefined;
+
+ that.currentValue = value;
+
+ if ( info.valid ) {
+ that.setErrors( [], forceReplacement );
+ } else {
+ that.setErrors( info.messages, forceReplacement );
+ }
+ } ).fail( function () {
+ that.currentValue = null;
+ that.setErrors( [] );
+ } );
+
+ return currentRequestInternal;
+ };
+
+ /**
+ * Display errors associated with the form element
+ * @param {Array} errors Error messages. Each error message will be appended to a
+ * `<span>` or `<li>`, as with jQuery.append().
+ * @param {boolean} [forceReplacement] Set true to force a visual replacement even
+ * if the errors are the same. Ignored if errors are empty.
+ * @return {mw.htmlform.Checker}
+ * @chainable
+ */
+ mw.htmlform.Checker.prototype.setErrors = function ( errors, forceReplacement ) {
+ var $oldErrorBox, tagName, showFunc, text, replace,
+ $errorBox = this.$errorBox;
+
+ if ( errors.length === 0 ) {
+ $errorBox.slideUp( function () {
+ $errorBox
+ .removeAttr( 'class' )
+ .empty();
+ } );
+ } else {
+ // Match behavior of HTMLFormField::formatErrors(), <span> or <ul>
+ // depending on the count.
+ tagName = errors.length === 1 ? 'span' : 'ul';
+
+ // We have to animate the replacement if we're changing the tag. We
+ // also want to if told to by the caller (i.e. to make it visually
+ // obvious that the changed field value gives the same error) or if
+ // the error text changes (because it makes more sense than
+ // changing the text with no animation).
+ replace = (
+ forceReplacement || $errorBox.length > 1 ||
+ $errorBox[ 0 ].tagName.toLowerCase() !== tagName
+ );
+ if ( !replace ) {
+ text = $( '<' + tagName + '>' )
+ .append( errors.map( function ( e ) {
+ return errors.length === 1 ? e : $( '<li>' ).append( e );
+ } ) );
+ if ( text.text() !== $errorBox.text() ) {
+ replace = true;
+ }
+ }
+
+ $oldErrorBox = $errorBox;
+ if ( replace ) {
+ this.$errorBox = $errorBox = $( '<' + tagName + '>' );
+ $errorBox.hide();
+ $oldErrorBox.after( this.$errorBox );
+ }
+
+ showFunc = function () {
+ if ( $oldErrorBox !== $errorBox ) {
+ $oldErrorBox
+ .removeAttr( 'class' )
+ .detach();
+ }
+ $errorBox
+ .attr( 'class', 'error' )
+ .empty()
+ .append( errors.map( function ( e ) {
+ return errors.length === 1 ? e : $( '<li>' ).append( e );
+ } ) )
+ .slideDown();
+ };
+ if ( $oldErrorBox !== $errorBox && $oldErrorBox.hasClass( 'error' ) ) {
+ $oldErrorBox.slideUp( showFunc );
+ } else {
+ showFunc();
+ }
+ }
+
+ return this;
+ };
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/htmlform.Element.js b/www/wiki/resources/src/mediawiki/htmlform/htmlform.Element.js
new file mode 100644
index 00000000..4f672fc7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/htmlform.Element.js
@@ -0,0 +1,46 @@
+( function ( mw ) {
+
+ mw.htmlform = {};
+
+ /**
+ * Allows custom data specific to HTMLFormField to be set for OOjs UI forms. This picks up the
+ * extra config from a matching PHP widget (defined in HTMLFormElement.php) when constructed using
+ * OO.ui.infuse().
+ *
+ * Currently only supports passing 'hide-if' data.
+ *
+ * @ignore
+ * @param {Object} [config] Configuration options
+ */
+ mw.htmlform.Element = function ( config ) {
+ // Configuration initialization
+ config = config || {};
+
+ // Properties
+ this.hideIf = config.hideIf;
+
+ // Initialization
+ if ( this.hideIf ) {
+ this.$element.addClass( 'mw-htmlform-hide-if' );
+ }
+ };
+
+ mw.htmlform.FieldLayout = function ( config ) {
+ // Parent constructor
+ mw.htmlform.FieldLayout.parent.call( this, config );
+ // Mixin constructors
+ mw.htmlform.Element.call( this, config );
+ };
+ OO.inheritClass( mw.htmlform.FieldLayout, OO.ui.FieldLayout );
+ OO.mixinClass( mw.htmlform.FieldLayout, mw.htmlform.Element );
+
+ mw.htmlform.ActionFieldLayout = function ( config ) {
+ // Parent constructor
+ mw.htmlform.ActionFieldLayout.parent.call( this, config );
+ // Mixin constructors
+ mw.htmlform.Element.call( this, config );
+ };
+ OO.inheritClass( mw.htmlform.ActionFieldLayout, OO.ui.ActionFieldLayout );
+ OO.mixinClass( mw.htmlform.ActionFieldLayout, mw.htmlform.Element );
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/htmlform.js b/www/wiki/resources/src/mediawiki/htmlform/htmlform.js
new file mode 100644
index 00000000..bc835b59
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/htmlform.js
@@ -0,0 +1,14 @@
+( function ( mw, $ ) {
+
+ $( function () {
+ mw.hook( 'htmlform.enhance' ).fire( $( document ) );
+ } );
+
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ // Turn HTML5 form validation back on, in cases where it was disabled server-side (see
+ // HTMLForm::needsJSForHtml5FormValidation()) because we need extra logic implemented in JS to
+ // validate correctly. Currently, this is only used for forms containing fields with 'hide-if'.
+ $root.find( '.mw-htmlform' ).removeAttr( 'novalidate' );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/images/question.png b/www/wiki/resources/src/mediawiki/htmlform/images/question.png
new file mode 100644
index 00000000..acce58c8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/images/question.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/htmlform/images/question.svg b/www/wiki/resources/src/mediawiki/htmlform/images/question.svg
new file mode 100644
index 00000000..98fbe8dd
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/images/question.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="21.059" height="21.06"><path fill="#575757" d="M10.529 0c-5.814 0-10.529 4.714-10.529 10.529s4.715 10.53 10.529 10.53c5.816 0 10.529-4.715 10.529-10.53s-4.712-10.529-10.529-10.529zm-.002 16.767c-.861 0-1.498-.688-1.498-1.516 0-.862.637-1.534 1.498-1.534.828 0 1.5.672 1.5 1.534 0 .827-.672 1.516-1.5 1.516zm2.137-6.512c-.723.568-1 .931-1 1.739v.5h-2.205v-.603c0-1.517.449-2.136 1.154-2.688.707-.552 1.139-.845 1.139-1.637 0-.672-.414-1.051-1.24-1.051-.707 0-1.328.189-1.982.638l-1.051-1.807c.861-.604 1.93-1.034 3.342-1.034 1.912 0 3.516 1.051 3.516 3.066-.001 1.43-.794 2.188-1.673 2.877z"/></svg> \ No newline at end of file
diff --git a/www/wiki/resources/src/mediawiki/htmlform/multiselect.js b/www/wiki/resources/src/mediawiki/htmlform/multiselect.js
new file mode 100644
index 00000000..37c0554a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/multiselect.js
@@ -0,0 +1,114 @@
+/*
+ * HTMLForm enhancements:
+ * Convert multiselect fields from checkboxes to Chosen selector when requested.
+ */
+( function ( mw, $ ) {
+
+ function addMulti( $oldContainer, $container ) {
+ var name = $oldContainer.find( 'input:first-child' ).attr( 'name' ),
+ oldClass = ( ' ' + $oldContainer.attr( 'class' ) + ' ' ).replace( /(mw-htmlform-field-HTMLMultiSelectField|mw-chosen|mw-htmlform-dropdown)/g, '' ),
+ $select = $( '<select>' ),
+ dataPlaceholder = mw.message( 'htmlform-chosen-placeholder' );
+ oldClass = $.trim( oldClass );
+ $select.attr( {
+ name: name,
+ multiple: 'multiple',
+ 'data-placeholder': dataPlaceholder.plain(),
+ 'class': 'htmlform-chzn-select mw-input ' + oldClass
+ } );
+ $oldContainer.find( 'input' ).each( function () {
+ var $oldInput = $( this ),
+ checked = $oldInput.prop( 'checked' ),
+ $option = $( '<option>' );
+ $option.prop( 'value', $oldInput.prop( 'value' ) );
+ if ( checked ) {
+ $option.prop( 'selected', true );
+ }
+ $option.text( $oldInput.prop( 'value' ) );
+ $select.append( $option );
+ } );
+ $container.append( $select );
+ }
+
+ function convertCheckboxesToMulti( $oldContainer, type ) {
+ var $fieldLabel = $( '<td>' ),
+ $td = $( '<td>' ),
+ $fieldLabelText = $( '<label>' ),
+ $container;
+ if ( type === 'tr' ) {
+ addMulti( $oldContainer, $td );
+ $container = $( '<tr>' );
+ $container.append( $td );
+ } else if ( type === 'div' ) {
+ $fieldLabel = $( '<div>' );
+ $container = $( '<div>' );
+ addMulti( $oldContainer, $container );
+ }
+ $fieldLabel.attr( 'class', 'mw-label' );
+ $fieldLabelText.text( $oldContainer.find( '.mw-label label' ).text() );
+ $fieldLabel.append( $fieldLabelText );
+ $container.prepend( $fieldLabel );
+ $oldContainer.replaceWith( $container );
+ return $container;
+ }
+
+ function convertCheckboxesWidgetToCapsules( fieldLayout ) {
+ var checkboxesWidget, checkboxesOptions, capsulesOptions, capsulesWidget;
+
+ checkboxesWidget = fieldLayout.fieldWidget;
+ checkboxesOptions = checkboxesWidget.checkboxMultiselectWidget.getItems();
+ capsulesOptions = checkboxesOptions.map( function ( option ) {
+ return new OO.ui.MenuOptionWidget( {
+ data: option.getData(),
+ label: option.getLabel()
+ } );
+ } );
+ capsulesWidget = new OO.ui.CapsuleMultiselectWidget( {
+ menu: {
+ items: capsulesOptions
+ }
+ } );
+ capsulesWidget.setItemsFromData( checkboxesWidget.getValue() );
+
+ // Data from CapsuleMultiselectWidget will not be submitted with the form, so keep the original
+ // CheckboxMultiselectInputWidget up-to-date.
+ capsulesWidget.on( 'change', function () {
+ checkboxesWidget.setValue( capsulesWidget.getItemsData() );
+ } );
+
+ // Hide original widget and add new one in its place. This is a bit hacky, since the FieldLayout
+ // still thinks it's connected to the old widget.
+ checkboxesWidget.toggle( false );
+ checkboxesWidget.$element.after( capsulesWidget.$element );
+ }
+
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ var $dropdowns = $root.find( '.mw-htmlform-field-HTMLMultiSelectField.mw-htmlform-dropdown' );
+ if ( $dropdowns.length ) {
+ $dropdowns.each( function () {
+ var $el = $( this ),
+ data, modules, extraModules;
+ if ( $el.is( '[data-ooui]' ) ) {
+ // Load 'oojs-ui-widgets' for CapsuleMultiselectWidget
+ modules = [ 'mediawiki.htmlform.ooui', 'oojs-ui-widgets' ];
+ data = $el.data( 'mw-modules' );
+ if ( data ) {
+ // We can trust this value, 'data-mw-*' attributes are banned from user content in Sanitizer
+ extraModules = data.split( ',' );
+ modules.push.apply( modules, extraModules );
+ }
+ mw.loader.using( modules, function () {
+ convertCheckboxesWidgetToCapsules( OO.ui.FieldLayout.static.infuse( $el ) );
+ } );
+ } else {
+ mw.loader.using( 'jquery.chosen', function () {
+ var type = $el.is( 'tr' ) ? 'tr' : 'div',
+ $converted = convertCheckboxesToMulti( $el, type );
+ $converted.find( '.htmlform-chzn-select' ).chosen( { width: 'auto' } );
+ } );
+ }
+ } );
+ }
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/ooui.styles.css b/www/wiki/resources/src/mediawiki/htmlform/ooui.styles.css
new file mode 100644
index 00000000..dbf2b6b4
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/ooui.styles.css
@@ -0,0 +1,47 @@
+/* OOUIHTMLForm styles */
+
+.mw-htmlform-ooui .mw-htmlform-field-HTMLCheckMatrix {
+ width: 100%;
+}
+
+.mw-htmlform-ooui .mw-htmlform-matrix {
+ border-spacing: 0;
+}
+
+.mw-htmlform-ooui .mw-htmlform-matrix td {
+ padding: 0.35em 0.7em;
+ -webkit-transition: background-color 250ms;
+ -moz-transition: background-color 250ms;
+ transition: background-color 250ms;
+}
+
+.mw-htmlform-ooui .mw-htmlform-matrix tbody tr:nth-child( even ) td {
+ background-color: #f8f9fa;
+}
+
+.mw-htmlform-ooui .mw-htmlform-matrix tbody tr:not( :first-child ):hover td {
+ background-color: #eaecf0;
+}
+
+.mw-htmlform-ooui .mw-htmlform-matrix tbody tr:first-child td {
+ background-color: #fff;
+}
+
+.mw-htmlform-ooui .mw-htmlform-matrix td.first {
+ margin-right: 5%;
+ width: 39%;
+}
+
+/* Flatlist styling for PHP widgets... */
+.mw-htmlform-flatlist .oo-ui-fieldLayout-align-inline,
+/* ...and for JS widgets */
+.mw-htmlform-flatlist .oo-ui-radioOptionWidget,
+.mw-htmlform-flatlist .oo-ui-checkboxMultioptionWidget {
+ display: inline-block;
+ margin-right: 1em;
+}
+
+.mw-htmlform-ooui .htmlform-tip,
+.mw-htmlform-ooui .mw-htmlform-submit-buttons {
+ margin-top: 1em;
+}
diff --git a/www/wiki/resources/src/mediawiki/htmlform/selectandother.js b/www/wiki/resources/src/mediawiki/htmlform/selectandother.js
new file mode 100644
index 00000000..95227d01
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/selectandother.js
@@ -0,0 +1,41 @@
+/*
+ * HTMLForm enhancements:
+ * Add a dynamic max length to the reason field of SelectAndOther.
+ */
+( function ( mw, $ ) {
+
+ // cache the separator to avoid object creation on each keypress
+ var colonSeparator = mw.message( 'colon-separator' ).text();
+
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ // This checks the length together with the value from the select field
+ // When the reason list is changed and the bytelimit is longer than the allowed,
+ // nothing is done
+ $root
+ .find( '.mw-htmlform-select-and-other-field' )
+ .each( function () {
+ var $this = $( this ),
+ // find the reason list
+ $reasonList = $root.find( '#' + $this.data( 'id-select' ) ),
+ // cache the current selection to avoid expensive lookup
+ currentValReasonList = $reasonList.val();
+
+ $reasonList.change( function () {
+ currentValReasonList = $reasonList.val();
+ } );
+
+ $this.byteLimit( function ( input ) {
+ // Should be built the same as in HTMLSelectAndOtherField::loadDataFromRequest
+ var comment = currentValReasonList;
+ if ( comment === 'other' ) {
+ comment = input;
+ } else if ( input !== '' ) {
+ // Entry from drop down menu + additional comment
+ comment += colonSeparator + input;
+ }
+ return comment;
+ } );
+ } );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/selectorother.js b/www/wiki/resources/src/mediawiki/htmlform/selectorother.js
new file mode 100644
index 00000000..b6899d95
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/selectorother.js
@@ -0,0 +1,62 @@
+/*
+ * HTMLForm enhancements:
+ * Animate the SelectOrOther fields, to only show the text field when 'other' is selected.
+ */
+( function ( mw, $ ) {
+
+ /**
+ * @class jQuery.plugin.htmlform
+ */
+
+ /**
+ * jQuery plugin to fade or snap to visible state.
+ *
+ * @param {boolean} [instantToggle=false]
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.goIn = function ( instantToggle ) {
+ if ( instantToggle === true ) {
+ return this.show();
+ }
+ return this.stop( true, true ).fadeIn();
+ };
+
+ /**
+ * jQuery plugin to fade or snap to hiding state.
+ *
+ * @param {boolean} [instantToggle=false]
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.goOut = function ( instantToggle ) {
+ if ( instantToggle === true ) {
+ return this.hide();
+ }
+ return this.stop( true, true ).fadeOut();
+ };
+
+ mw.hook( 'htmlform.enhance' ).add( function ( $root ) {
+ /**
+ * @ignore
+ * @param {boolean|jQuery.Event} instant
+ */
+ function handleSelectOrOther( instant ) {
+ var $other = $root.find( '#' + $( this ).attr( 'id' ) + '-other' );
+ $other = $other.add( $other.siblings( 'br' ) );
+ if ( $( this ).val() === 'other' ) {
+ $other.goIn( instant );
+ } else {
+ $other.goOut( instant );
+ }
+ }
+
+ $root
+ .on( 'change', '.mw-htmlform-select-or-other', handleSelectOrOther )
+ .find( '.mw-htmlform-select-or-other' )
+ .each( function () {
+ handleSelectOrOther.call( this, true );
+ } );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/htmlform/styles.css b/www/wiki/resources/src/mediawiki/htmlform/styles.css
new file mode 100644
index 00000000..0f331ee0
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/htmlform/styles.css
@@ -0,0 +1,54 @@
+/* HTMLForm styles */
+
+.mw-htmlform {
+ clear: both;
+}
+
+table.mw-htmlform-nolabel td.mw-label {
+ display: none;
+}
+
+.mw-htmlform-invalid-input td.mw-input input {
+ border-color: #d33;
+}
+
+.mw-htmlform-flatlist div.mw-htmlform-flatlist-item {
+ display: inline;
+ margin-right: 1em;
+ white-space: nowrap;
+}
+
+/* HTMLCheckMatrix */
+
+.mw-htmlform-matrix td {
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+}
+
+tr.mw-htmlform-vertical-label td.mw-label {
+ text-align: left !important; /* stylelint-disable-line declaration-no-important */
+}
+
+.mw-icon-question {
+ /* SVG support using a transparent gradient to guarantee cross-browser
+ * compatibility (browsers able to understand gradient syntax support also SVG).
+ * http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique */
+ background-image: url( images/question.png );
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/question.svg );
+ background-repeat: no-repeat;
+ background-size: 13px 13px;
+ display: inline-block;
+ height: 13px;
+ width: 13px;
+ margin-left: 4px;
+}
+
+/* stylelint-disable indentation */
+.mw-icon-question:lang( ar ),
+.mw-icon-question:lang( fa ),
+.mw-icon-question:lang( ur ) {
+ -webkit-transform: scaleX( -1 );
+ -ms-transform: scaleX( -1 );
+ transform: scaleX( -1 );
+}
diff --git a/www/wiki/resources/src/mediawiki/images/arrow-collapsed-ltr.png b/www/wiki/resources/src/mediawiki/images/arrow-collapsed-ltr.png
new file mode 100644
index 00000000..80c4fbdf
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/arrow-collapsed-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/arrow-collapsed-ltr.svg b/www/wiki/resources/src/mediawiki/images/arrow-collapsed-ltr.svg
new file mode 100644
index 00000000..6233fd5e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/arrow-collapsed-ltr.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path d="M4 1.533v9.671l4.752-4.871z" fill="#797979"/></svg> \ No newline at end of file
diff --git a/www/wiki/resources/src/mediawiki/images/arrow-collapsed-rtl.png b/www/wiki/resources/src/mediawiki/images/arrow-collapsed-rtl.png
new file mode 100644
index 00000000..5f144893
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/arrow-collapsed-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/arrow-collapsed-rtl.svg b/www/wiki/resources/src/mediawiki/images/arrow-collapsed-rtl.svg
new file mode 100644
index 00000000..44d5587a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/arrow-collapsed-rtl.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path d="M8 1.533v9.671l-4.752-4.871z" fill="#797979"/></svg> \ No newline at end of file
diff --git a/www/wiki/resources/src/mediawiki/images/arrow-expanded.png b/www/wiki/resources/src/mediawiki/images/arrow-expanded.png
new file mode 100644
index 00000000..252d0067
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/arrow-expanded.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/arrow-expanded.svg b/www/wiki/resources/src/mediawiki/images/arrow-expanded.svg
new file mode 100644
index 00000000..a0d217d2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/arrow-expanded.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path d="M1.165 3.624h9.671l-4.871 4.752z" fill="#797979"/></svg> \ No newline at end of file
diff --git a/www/wiki/resources/src/mediawiki/images/arrow-sort-ascending.png b/www/wiki/resources/src/mediawiki/images/arrow-sort-ascending.png
new file mode 100644
index 00000000..d5b66c0c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/arrow-sort-ascending.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/arrow-sort-ascending.svg b/www/wiki/resources/src/mediawiki/images/arrow-sort-ascending.svg
new file mode 100644
index 00000000..1e7a0943
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/arrow-sort-ascending.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path d="M1 10h10l-5-8.658z" fill="#00a"/></svg> \ No newline at end of file
diff --git a/www/wiki/resources/src/mediawiki/images/arrow-sort-descending.png b/www/wiki/resources/src/mediawiki/images/arrow-sort-descending.png
new file mode 100644
index 00000000..ab3979e0
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/arrow-sort-descending.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/arrow-sort-descending.svg b/www/wiki/resources/src/mediawiki/images/arrow-sort-descending.svg
new file mode 100644
index 00000000..cf11adb4
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/arrow-sort-descending.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="12" height="12"><path d="M1 2h10l-5 8.658z" fill="#00a"/></svg> \ No newline at end of file
diff --git a/www/wiki/resources/src/mediawiki/images/feed-icon.png b/www/wiki/resources/src/mediawiki/images/feed-icon.png
new file mode 100644
index 00000000..8e2d49ed
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/feed-icon.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/feed-icon.svg b/www/wiki/resources/src/mediawiki/images/feed-icon.svg
new file mode 100644
index 00000000..6e5f570a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/feed-icon.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="128" height="128" viewBox="0 0 256 256"><defs><linearGradient x1=".085" y1=".085" x2=".915" y2=".915" id="a"><stop offset="0" stop-color="#E3702D"/><stop offset=".107" stop-color="#EA7D31"/><stop offset=".35" stop-color="#F69537"/><stop offset=".5" stop-color="#FB9E3A"/><stop offset=".702" stop-color="#EA7C31"/><stop offset=".887" stop-color="#DE642B"/><stop offset="1" stop-color="#D95B29"/></linearGradient></defs><rect width="256" height="256" rx="55" ry="55" fill="#CC5D15"/><rect width="246" height="246" rx="50" ry="50" x="5" y="5" fill="#F49C52"/><rect width="236" height="236" rx="47" ry="47" x="10" y="10" fill="url(#a)"/><circle cx="68" cy="189" r="24" fill="#FFF"/><path d="M160 213h-34a82 82 0 0 0-82-82v-34a116 116 0 0 1 116 116zM184 213a140 140 0 0 0-140-140v-35a175 175 0 0 1 175 175z" fill="#FFF"/></svg> \ No newline at end of file
diff --git a/www/wiki/resources/src/mediawiki/images/help.png b/www/wiki/resources/src/mediawiki/images/help.png
new file mode 100644
index 00000000..301e23b8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/help.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/help.svg b/www/wiki/resources/src/mediawiki/images/help.svg
new file mode 100644
index 00000000..3662cb58
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/help.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="utf-8"?><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><g><path d="M12.001 2.085c-5.478 0-9.916 4.438-9.916 9.916 0 5.476 4.438 9.914 9.916 9.914 5.476 0 9.914-4.438 9.914-9.914 0-5.478-4.438-9.916-9.914-9.916zm.001 18c-4.465 0-8.084-3.619-8.084-8.083 0-4.465 3.619-8.084 8.084-8.084 4.464 0 8.083 3.619 8.083 8.084 0 4.464-3.619 8.083-8.083 8.083z"/><g><path d="M11.766 6.688c-2.5 0-3.219 2.188-3.219 2.188l1.411.854s.298-.791.901-1.229c.516-.375 1.625-.625 2.219.125.701.885-.17 1.587-1.078 2.719-.953 1.186-1 3.655-1 3.655h1.969s.135-2.318 1.041-3.381c.603-.707 1.443-1.338 1.443-2.494s-1.187-2.437-3.687-2.437z"/><path d="M11 16h2v2h-2z"/></g></g></svg>
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.png b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.png
new file mode 100644
index 00000000..2a64fd03
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.svg b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.svg
new file mode 100644
index 00000000..b34fb382
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-ltr.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="30"
+ height="30"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="matrix(0.41333074,0,0,0.41333074,-183.39876,-197.95599)"
+ id="layer1">
+ <g
+ transform="translate(455.60433,484.94177)"
+ id="g3163">
+ <path
+ d="M 0,0.03543307 0,60.519684 43.192915,30.259842 z"
+ id="path3165"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ <path
+ d="m 43.157481,0.03543307 5.633859,0 0,60.48425093 -5.633859,0 z"
+ id="path3167"
+ style="fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none" />
+ </g>
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.png b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.png
new file mode 100644
index 00000000..78a493e6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.svg b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.svg
new file mode 100644
index 00000000..529e8d0f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-fastforward-rtl.svg
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="30"
+ height="30"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="matrix(0.4132798,0,0,0.4132798,-87.72955,-233.35372)"
+ id="layer1">
+ <path
+ d="m 272.96237,570.69005 0,60.4894 -43.19393,-30.2447 z"
+ id="path3023-7"
+ style="fill:#cccccc;fill-opacity:1;stroke:none" />
+ <rect
+ width="5.6406202"
+ height="60.489399"
+ x="-229.82111"
+ y="570.68774"
+ transform="scale(-1,1)"
+ id="rect3799-9"
+ style="color:#000000;fill:#cccccc;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:20;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.png b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.png
new file mode 100644
index 00000000..aa4fbf8c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.svg b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.svg
new file mode 100644
index 00000000..9fbcf20e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-ltr.svg
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="30"
+ height="30"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="matrix(0.41329555,0,0,0.41329555,-111.35036,-135.3531)"
+ id="layer1">
+ <path
+ d="m 284.11732,333.54605 0,60.4894 43.19395,-30.2447 z"
+ id="path3023-7-2"
+ style="fill:#cccccc;fill-opacity:1;stroke:none" />
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.png b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.png
new file mode 100644
index 00000000..83df0684
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.svg b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.svg
new file mode 100644
index 00000000..3130f109
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-disabled-forward-rtl.svg
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="30"
+ height="30"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="matrix(0.41329555,0,0,0.41329555,-139.69062,-163.69336)"
+ id="layer1">
+ <path
+ d="m 395.88269,402.11748 0,60.4894 -43.19395,-30.2447 z"
+ id="path3023-7-2-8"
+ style="fill:#cccccc;fill-opacity:1;stroke:none" />
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-ltr.png b/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-ltr.png
new file mode 100644
index 00000000..8904b89e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-ltr.svg b/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-ltr.svg
new file mode 100644
index 00000000..57df4c0d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-ltr.svg
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="30"
+ height="30"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="matrix(0.41327999,0,0,0.41327999,-98.356798,-226.26904)"
+ id="layer1">
+ <path
+ d="m 249.89477,553.5472 0,60.4894 43.19391,-30.2447 z"
+ id="path3023"
+ style="fill:#0000aa;fill-opacity:1;stroke:none" />
+ <rect
+ width="5.6406202"
+ height="60.489399"
+ x="293.03604"
+ y="553.54492"
+ id="rect3799"
+ style="color:#000000;fill:#0000aa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:20;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-rtl.png b/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-rtl.png
new file mode 100644
index 00000000..71d08195
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-rtl.svg b/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-rtl.svg
new file mode 100644
index 00000000..dbb473bb
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-fastforward-rtl.svg
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.1"
+ width="30"
+ height="30"
+ id="svg2"
+ inkscape:version="0.48.4 r9939"
+ sodipodi:docname="pager-arrow-fastforward-rtl.svg">
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1366"
+ inkscape:window-height="692"
+ id="namedview8"
+ showgrid="false"
+ inkscape:zoom="17.4"
+ inkscape:cx="7.0114943"
+ inkscape:cy="15"
+ inkscape:window-x="0"
+ inkscape:window-y="24"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <defs
+ id="defs4" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="matrix(0.07055556,0,0,0.07055556,-9.1581596,-2.7587241)"
+ id="layer1">
+ <path
+ d="m 485.26916,74.546776 0,354.317014 -253.00859,-177.15851 z"
+ id="path3023-2"
+ style="fill:#0000aa;fill-opacity:1;stroke:none"
+ inkscape:connector-curvature="0" />
+ <rect
+ width="33.039963"
+ height="354.31699"
+ x="-232.56898"
+ y="74.533081"
+ transform="scale(-1,1)"
+ id="rect3799-6"
+ style="color:#000000;fill:#0000aa;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:20;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-ltr.png b/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-ltr.png
new file mode 100644
index 00000000..c68a4fc5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-ltr.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-ltr.svg b/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-ltr.svg
new file mode 100644
index 00000000..1ebf9c15
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-ltr.svg
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="30"
+ height="30"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="matrix(0.41329555,0,0,0.41329555,-162.12666,-110.55537)"
+ id="layer1">
+ <path
+ d="m 406.97447,273.54605 0,60.4894 43.19391,-30.2447 z"
+ id="path3023-3-9"
+ style="fill:#0000aa;fill-opacity:1;stroke:none" />
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-rtl.png b/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-rtl.png
new file mode 100644
index 00000000..d0a7030d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-rtl.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-rtl.svg b/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-rtl.svg
new file mode 100644
index 00000000..b494409a
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/pager-arrow-forward-rtl.svg
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.1"
+ width="30"
+ height="30"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <metadata
+ id="metadata7">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <g
+ transform="matrix(0.41329555,0,0,0.41329555,-78.28671,-153.06577)"
+ id="layer1">
+ <path
+ d="m 247.31124,376.4032 0,60.4894 -43.19391,-30.2447 z"
+ id="path3023-3"
+ style="fill:#0000aa;fill-opacity:1;stroke:none" />
+ </g>
+</svg>
diff --git a/www/wiki/resources/src/mediawiki/images/question.png b/www/wiki/resources/src/mediawiki/images/question.png
new file mode 100644
index 00000000..acce58c8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/question.png
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/images/question.svg b/www/wiki/resources/src/mediawiki/images/question.svg
new file mode 100644
index 00000000..98fbe8dd
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/images/question.svg
@@ -0,0 +1 @@
+<?xml version="1.0" encoding="UTF-8"?><svg xmlns="http://www.w3.org/2000/svg" width="21.059" height="21.06"><path fill="#575757" d="M10.529 0c-5.814 0-10.529 4.714-10.529 10.529s4.715 10.53 10.529 10.53c5.816 0 10.529-4.715 10.529-10.53s-4.712-10.529-10.529-10.529zm-.002 16.767c-.861 0-1.498-.688-1.498-1.516 0-.862.637-1.534 1.498-1.534.828 0 1.5.672 1.5 1.534 0 .827-.672 1.516-1.5 1.516zm2.137-6.512c-.723.568-1 .931-1 1.739v.5h-2.205v-.603c0-1.517.449-2.136 1.154-2.688.707-.552 1.139-.845 1.139-1.637 0-.672-.414-1.051-1.24-1.051-.707 0-1.328.189-1.982.638l-1.051-1.807c.861-.604 1.93-1.034 3.342-1.034 1.912 0 3.516 1.051 3.516 3.066-.001 1.43-.794 2.188-1.673 2.877z"/></svg> \ No newline at end of file
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js b/www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js
new file mode 100644
index 00000000..ac2bb02e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.js
@@ -0,0 +1,461 @@
+/* global moment, Uint8Array */
+( function ( $, mw ) {
+
+ /**
+ * mw.ForeignStructuredUpload.BookletLayout encapsulates the process
+ * of uploading a file to MediaWiki using the mw.ForeignStructuredUpload model.
+ *
+ * var uploadDialog = new mw.Upload.Dialog( {
+ * bookletClass: mw.ForeignStructuredUpload.BookletLayout,
+ * booklet: {
+ * target: 'local'
+ * }
+ * } );
+ * var windowManager = new OO.ui.WindowManager();
+ * $( 'body' ).append( windowManager.$element );
+ * windowManager.addWindows( [ uploadDialog ] );
+ *
+ * @class mw.ForeignStructuredUpload.BookletLayout
+ * @uses mw.ForeignStructuredUpload
+ * @extends mw.Upload.BookletLayout
+ *
+ * @constructor
+ * @param {Object} config Configuration options
+ * @cfg {string} [target] Used to choose the target repository.
+ * If nothing is passed, the {@link mw.ForeignUpload#property-target default} is used.
+ */
+ mw.ForeignStructuredUpload.BookletLayout = function ( config ) {
+ config = config || {};
+ // Parent constructor
+ mw.ForeignStructuredUpload.BookletLayout.parent.call( this, config );
+
+ this.target = config.target;
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.ForeignStructuredUpload.BookletLayout, mw.Upload.BookletLayout );
+
+ /* Uploading */
+
+ /**
+ * @inheritdoc
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.initialize = function () {
+ var booklet = this;
+ return mw.ForeignStructuredUpload.BookletLayout.parent.prototype.initialize.call( this ).then(
+ function () {
+ return $.when(
+ // Point the CategoryMultiselectWidget to the right wiki
+ booklet.upload.getApi().then( function ( api ) {
+ // If this is a ForeignApi, it will have a apiUrl, otherwise we don't need to do anything
+ if ( api.apiUrl ) {
+ // Can't reuse the same object, CategoryMultiselectWidget calls #abort on its mw.Api instance
+ booklet.categoriesWidget.api = new mw.ForeignApi( api.apiUrl );
+ }
+ return $.Deferred().resolve();
+ } ),
+ // Set up booklet fields and license messages to match configuration
+ booklet.upload.loadConfig().then( function ( config ) {
+ var
+ msgPromise,
+ isLocal = booklet.upload.target === 'local',
+ fields = config.fields,
+ msgs = config.licensemessages[ isLocal ? 'local' : 'foreign' ];
+
+ // Hide disabled fields
+ booklet.descriptionField.toggle( !!fields.description );
+ booklet.categoriesField.toggle( !!fields.categories );
+ booklet.dateField.toggle( !!fields.date );
+ // Update form validity
+ booklet.onInfoFormChange();
+
+ // Load license messages from the remote wiki if we don't have these messages locally
+ // (this means that we only load messages from the foreign wiki for custom config)
+ if ( mw.message( 'upload-form-label-own-work-message-' + msgs ).exists() ) {
+ msgPromise = $.Deferred().resolve();
+ } else {
+ msgPromise = booklet.upload.apiPromise.then( function ( api ) {
+ return api.loadMessages( [
+ 'upload-form-label-own-work-message-' + msgs,
+ 'upload-form-label-not-own-work-message-' + msgs,
+ 'upload-form-label-not-own-work-local-' + msgs
+ ] );
+ } );
+ }
+
+ // Update license messages
+ return msgPromise.then( function () {
+ var $labels;
+ booklet.$ownWorkMessage.msg( 'upload-form-label-own-work-message-' + msgs );
+ booklet.$notOwnWorkMessage.msg( 'upload-form-label-not-own-work-message-' + msgs );
+ booklet.$notOwnWorkLocal.msg( 'upload-form-label-not-own-work-local-' + msgs );
+
+ $labels = $( [
+ booklet.$ownWorkMessage[ 0 ],
+ booklet.$notOwnWorkMessage[ 0 ],
+ booklet.$notOwnWorkLocal[ 0 ]
+ ] );
+
+ // Improve the behavior of links inside these labels, which may point to important
+ // things like licensing requirements or terms of use
+ $labels.find( 'a' )
+ .attr( 'target', '_blank' )
+ .on( 'click', function ( e ) {
+ // OO.ui.FieldLayout#onLabelClick is trying to prevent default on all clicks,
+ // which causes the links to not be openable. Don't let it do that.
+ e.stopPropagation();
+ } );
+ } );
+ }, function ( errorMsg ) {
+ booklet.getPage( 'upload' ).$element.msg( errorMsg );
+ return $.Deferred().resolve();
+ } )
+ );
+ }
+ ).then(
+ null,
+ // Always resolve, never reject
+ function () { return $.Deferred().resolve(); }
+ );
+ };
+
+ /**
+ * Returns a {@link mw.ForeignStructuredUpload mw.ForeignStructuredUpload}
+ * with the {@link #cfg-target target} specified in config.
+ *
+ * @protected
+ * @return {mw.Upload}
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.createUpload = function () {
+ return new mw.ForeignStructuredUpload( this.target, {
+ parameters: {
+ errorformat: 'html',
+ errorlang: mw.config.get( 'wgUserLanguage' ),
+ errorsuselocal: 1,
+ formatversion: 2
+ }
+ } );
+ };
+
+ /* Form renderers */
+
+ /**
+ * @inheritdoc
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.renderUploadForm = function () {
+ var fieldset,
+ layout = this;
+
+ // These elements are filled with text in #initialize
+ // TODO Refactor this to be in one place
+ this.$ownWorkMessage = $( '<p>' )
+ .addClass( 'mw-foreignStructuredUpload-bookletLayout-license' );
+ this.$notOwnWorkMessage = $( '<p>' );
+ this.$notOwnWorkLocal = $( '<p>' );
+
+ this.selectFileWidget = new OO.ui.SelectFileWidget( {
+ showDropTarget: true
+ } );
+ this.messageLabel = new OO.ui.LabelWidget( {
+ label: $( '<div>' ).append(
+ this.$notOwnWorkMessage,
+ this.$notOwnWorkLocal
+ )
+ } );
+ this.ownWorkCheckbox = new OO.ui.CheckboxInputWidget().on( 'change', function ( on ) {
+ layout.messageLabel.toggle( !on );
+ } );
+
+ fieldset = new OO.ui.FieldsetLayout();
+ fieldset.addItems( [
+ new OO.ui.FieldLayout( this.selectFileWidget, {
+ align: 'top'
+ } ),
+ new OO.ui.FieldLayout( this.ownWorkCheckbox, {
+ align: 'inline',
+ label: $( '<div>' ).append(
+ $( '<p>' ).text( mw.msg( 'upload-form-label-own-work' ) ),
+ this.$ownWorkMessage
+ )
+ } ),
+ new OO.ui.FieldLayout( this.messageLabel, {
+ align: 'top'
+ } )
+ ] );
+ this.uploadForm = new OO.ui.FormLayout( { items: [ fieldset ] } );
+
+ // Validation
+ this.selectFileWidget.on( 'change', this.onUploadFormChange.bind( this ) );
+ this.ownWorkCheckbox.on( 'change', this.onUploadFormChange.bind( this ) );
+
+ this.selectFileWidget.on( 'change', function () {
+ var file = layout.getFile();
+
+ // Set the date to lastModified once we have the file
+ if ( layout.getDateFromLastModified( file ) !== undefined ) {
+ layout.dateWidget.setValue( layout.getDateFromLastModified( file ) );
+ }
+
+ // Check if we have EXIF data and set to that where available
+ layout.getDateFromExif( file ).done( function ( date ) {
+ layout.dateWidget.setValue( date );
+ } );
+
+ layout.updateFilePreview();
+ } );
+
+ return this.uploadForm;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.onUploadFormChange = function () {
+ var file = this.selectFileWidget.getValue(),
+ ownWork = this.ownWorkCheckbox.isSelected(),
+ valid = !!file && ownWork;
+ this.emit( 'uploadValid', valid );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.renderInfoForm = function () {
+ var fieldset;
+
+ this.filePreview = new OO.ui.Widget( {
+ classes: [ 'mw-upload-bookletLayout-filePreview' ]
+ } );
+ this.progressBarWidget = new OO.ui.ProgressBarWidget( {
+ progress: 0
+ } );
+ this.filePreview.$element.append( this.progressBarWidget.$element );
+
+ this.filenameWidget = new OO.ui.TextInputWidget( {
+ required: true,
+ validate: /.+/
+ } );
+ this.descriptionWidget = new OO.ui.MultilineTextInputWidget( {
+ required: true,
+ validate: /\S+/,
+ autosize: true
+ } );
+ this.categoriesWidget = new mw.widgets.CategoryMultiselectWidget( {
+ // Can't be done here because we don't know the target wiki yet... done in #initialize.
+ // api: new mw.ForeignApi( ... ),
+ $overlay: this.$overlay
+ } );
+ this.dateWidget = new mw.widgets.DateInputWidget( {
+ $overlay: this.$overlay,
+ required: true,
+ mustBeBefore: moment().add( 1, 'day' ).locale( 'en' ).format( 'YYYY-MM-DD' ) // Tomorrow
+ } );
+
+ this.filenameField = new OO.ui.FieldLayout( this.filenameWidget, {
+ label: mw.msg( 'upload-form-label-infoform-name' ),
+ align: 'top',
+ classes: [ 'mw-foreignStructuredUploa-bookletLayout-small-notice' ],
+ notices: [ mw.msg( 'upload-form-label-infoform-name-tooltip' ) ]
+ } );
+ this.descriptionField = new OO.ui.FieldLayout( this.descriptionWidget, {
+ label: mw.msg( 'upload-form-label-infoform-description' ),
+ align: 'top',
+ classes: [ 'mw-foreignStructuredUploa-bookletLayout-small-notice' ],
+ notices: [ mw.msg( 'upload-form-label-infoform-description-tooltip' ) ]
+ } );
+ this.categoriesField = new OO.ui.FieldLayout( this.categoriesWidget, {
+ label: mw.msg( 'upload-form-label-infoform-categories' ),
+ align: 'top'
+ } );
+ this.dateField = new OO.ui.FieldLayout( this.dateWidget, {
+ label: mw.msg( 'upload-form-label-infoform-date' ),
+ align: 'top'
+ } );
+
+ fieldset = new OO.ui.FieldsetLayout( {
+ label: mw.msg( 'upload-form-label-infoform-title' )
+ } );
+ fieldset.addItems( [
+ this.filenameField,
+ this.descriptionField,
+ this.categoriesField,
+ this.dateField
+ ] );
+ this.infoForm = new OO.ui.FormLayout( {
+ classes: [ 'mw-upload-bookletLayout-infoForm' ],
+ items: [ this.filePreview, fieldset ]
+ } );
+
+ // Validation
+ this.filenameWidget.on( 'change', this.onInfoFormChange.bind( this ) );
+ this.descriptionWidget.on( 'change', this.onInfoFormChange.bind( this ) );
+ this.dateWidget.on( 'change', this.onInfoFormChange.bind( this ) );
+
+ this.on( 'fileUploadProgress', function ( progress ) {
+ this.progressBarWidget.setProgress( progress * 100 );
+ }.bind( this ) );
+
+ return this.infoForm;
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.onInfoFormChange = function () {
+ var layout = this,
+ validityPromises = [];
+
+ validityPromises.push( this.filenameWidget.getValidity() );
+ if ( this.descriptionField.isVisible() ) {
+ validityPromises.push( this.descriptionWidget.getValidity() );
+ }
+ if ( this.dateField.isVisible() ) {
+ validityPromises.push( this.dateWidget.getValidity() );
+ }
+
+ $.when.apply( $, validityPromises ).done( function () {
+ layout.emit( 'infoValid', true );
+ } ).fail( function () {
+ layout.emit( 'infoValid', false );
+ } );
+ };
+
+ /**
+ * @param {mw.Title} filename
+ * @return {jQuery.Promise} Resolves (on success) or rejects with OO.ui.Error
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.validateFilename = function ( filename ) {
+ return ( new mw.Api() ).get( {
+ action: 'query',
+ prop: 'info',
+ titles: filename.getPrefixedDb(),
+ formatversion: 2
+ } ).then(
+ function ( result ) {
+ // if the file already exists, reject right away, before
+ // ever firing finishStashUpload()
+ if ( !result.query.pages[ 0 ].missing ) {
+ return $.Deferred().reject( new OO.ui.Error(
+ $( '<p>' ).msg( 'fileexists', filename.getPrefixedDb() ),
+ { recoverable: false }
+ ) );
+ }
+ },
+ function () {
+ // API call failed - this could be a connection hiccup...
+ // Let's just ignore this validation step and turn this
+ // failure into a successful resolve ;)
+ return $.Deferred().resolve();
+ }
+ );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.saveFile = function () {
+ var title = mw.Title.newFromText(
+ this.getFilename(),
+ mw.config.get( 'wgNamespaceIds' ).file
+ );
+
+ return this.uploadPromise
+ .then( this.validateFilename.bind( this, title ) )
+ .then( mw.ForeignStructuredUpload.BookletLayout.parent.prototype.saveFile.bind( this ) );
+ };
+
+ /* Getters */
+
+ /**
+ * @inheritdoc
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.getText = function () {
+ var language = mw.config.get( 'wgContentLanguage' );
+ this.upload.clearDescriptions();
+ this.upload.addDescription( language, this.descriptionWidget.getValue() );
+ this.upload.setDate( this.dateWidget.getValue() );
+ this.upload.clearCategories();
+ this.upload.addCategories( this.categoriesWidget.getItemsData() );
+ return this.upload.getText();
+ };
+
+ /**
+ * Get original date from EXIF data
+ *
+ * @param {Object} file
+ * @return {jQuery.Promise} Promise resolved with the EXIF date
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.getDateFromExif = function ( file ) {
+ var fileReader,
+ deferred = $.Deferred();
+
+ if ( file && file.type === 'image/jpeg' ) {
+ fileReader = new FileReader();
+ fileReader.onload = function () {
+ var fileStr, arr, i, metadata;
+
+ if ( typeof fileReader.result === 'string' ) {
+ fileStr = fileReader.result;
+ } else {
+ // Array buffer; convert to binary string for the library.
+ arr = new Uint8Array( fileReader.result );
+ fileStr = '';
+ for ( i = 0; i < arr.byteLength; i++ ) {
+ fileStr += String.fromCharCode( arr[ i ] );
+ }
+ }
+
+ try {
+ metadata = mw.libs.jpegmeta( fileStr, file.name );
+ } catch ( e ) {
+ metadata = null;
+ }
+
+ if ( metadata !== null && metadata.exif !== undefined && metadata.exif.DateTimeOriginal ) {
+ deferred.resolve( moment( metadata.exif.DateTimeOriginal, 'YYYY:MM:DD' ).format( 'YYYY-MM-DD' ) );
+ } else {
+ deferred.reject();
+ }
+ };
+
+ if ( 'readAsBinaryString' in fileReader ) {
+ fileReader.readAsBinaryString( file );
+ } else if ( 'readAsArrayBuffer' in fileReader ) {
+ fileReader.readAsArrayBuffer( file );
+ } else {
+ // We should never get here
+ deferred.reject();
+ throw new Error( 'Cannot read thumbnail as binary string or array buffer.' );
+ }
+ }
+
+ return deferred.promise();
+ };
+
+ /**
+ * Get last modified date from file
+ *
+ * @param {Object} file
+ * @return {Object} Last modified date from file
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.getDateFromLastModified = function ( file ) {
+ if ( file && file.lastModified ) {
+ return moment( file.lastModified ).format( 'YYYY-MM-DD' );
+ }
+ };
+
+ /* Setters */
+
+ /**
+ * @inheritdoc
+ */
+ mw.ForeignStructuredUpload.BookletLayout.prototype.clear = function () {
+ mw.ForeignStructuredUpload.BookletLayout.parent.prototype.clear.call( this );
+
+ this.ownWorkCheckbox.setSelected( false );
+ this.categoriesWidget.setItemsFromData( [] );
+ this.dateWidget.setValue( '' ).setValidityFlag( true );
+ };
+
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.less b/www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.less
new file mode 100644
index 00000000..24ca434c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.BookletLayout.less
@@ -0,0 +1,19 @@
+.mw-foreignStructuredUpload-bookletLayout-license {
+ font-size: 90%;
+ line-height: 1.4em;
+ color: #54595d;
+}
+
+.mw-foreignStructuredUploa-bookletLayout-small-notice {
+ .oo-ui-fieldLayout-messages-notice {
+ .oo-ui-iconWidget {
+ display: none;
+ }
+
+ .oo-ui-labelWidget {
+ line-height: 1.2em;
+ font-size: 0.9em;
+ color: #54595d;
+ }
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js b/www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js
new file mode 100644
index 00000000..0c572d49
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.ForeignStructuredUpload.js
@@ -0,0 +1,264 @@
+( function ( mw, $, OO ) {
+ /**
+ * Used to represent an upload in progress on the frontend.
+ *
+ * This subclass will upload to a wiki using a structured metadata
+ * system similar to (or identical to) the one on Wikimedia Commons.
+ *
+ * See <https://commons.wikimedia.org/wiki/Commons:Structured_data> for
+ * a more detailed description of how that system works.
+ *
+ * **TODO: This currently only supports uploads under CC-BY-SA 4.0,
+ * and should really have support for more licenses.**
+ *
+ * @class mw.ForeignStructuredUpload
+ * @extends mw.ForeignUpload
+ *
+ * @constructor
+ * @param {string} [target]
+ * @param {Object} [apiconfig]
+ */
+ function ForeignStructuredUpload( target, apiconfig ) {
+ this.date = undefined;
+ this.descriptions = [];
+ this.categories = [];
+
+ // Config for uploads to local wiki.
+ // Can be overridden with foreign wiki config when #loadConfig is called.
+ this.config = mw.config.get( 'wgUploadDialog' );
+
+ mw.ForeignUpload.call( this, target, apiconfig );
+ }
+
+ OO.inheritClass( ForeignStructuredUpload, mw.ForeignUpload );
+
+ /**
+ * Get the configuration for the form and filepage from the foreign wiki, if any, and use it for
+ * this upload.
+ *
+ * @return {jQuery.Promise} Promise returning config object
+ */
+ ForeignStructuredUpload.prototype.loadConfig = function () {
+ var deferred,
+ upload = this;
+
+ if ( this.configPromise ) {
+ return this.configPromise;
+ }
+
+ if ( this.target === 'local' ) {
+ deferred = $.Deferred();
+ setTimeout( function () {
+ // Resolve asynchronously, so that it's harder to accidentally write synchronous code that
+ // will break for cross-wiki uploads
+ deferred.resolve( upload.config );
+ } );
+ this.configPromise = deferred.promise();
+ } else {
+ this.configPromise = this.apiPromise.then( function ( api ) {
+ // Get the config from the foreign wiki
+ return api.get( {
+ action: 'query',
+ meta: 'siteinfo',
+ siprop: 'uploaddialog',
+ // For convenient true/false booleans
+ formatversion: 2
+ } ).then( function ( resp ) {
+ // Foreign wiki might be running a pre-1.27 MediaWiki, without support for this
+ if ( resp.query && resp.query.uploaddialog ) {
+ upload.config = resp.query.uploaddialog;
+ return upload.config;
+ } else {
+ return $.Deferred().reject( 'upload-foreign-cant-load-config' );
+ }
+ }, function () {
+ return $.Deferred().reject( 'upload-foreign-cant-load-config' );
+ } );
+ } );
+ }
+
+ return this.configPromise;
+ };
+
+ /**
+ * Add categories to the upload.
+ *
+ * @param {string[]} categories Array of categories to which this upload will be added.
+ */
+ ForeignStructuredUpload.prototype.addCategories = function ( categories ) {
+ var i, category;
+
+ for ( i = 0; i < categories.length; i++ ) {
+ category = categories[ i ];
+ this.categories.push( category );
+ }
+ };
+
+ /**
+ * Empty the list of categories for the upload.
+ */
+ ForeignStructuredUpload.prototype.clearCategories = function () {
+ this.categories = [];
+ };
+
+ /**
+ * Add a description to the upload.
+ *
+ * @param {string} language The language code for the description's language. Must have a template on the target wiki to work properly.
+ * @param {string} description The description of the file.
+ */
+ ForeignStructuredUpload.prototype.addDescription = function ( language, description ) {
+ this.descriptions.push( {
+ language: language,
+ text: description
+ } );
+ };
+
+ /**
+ * Empty the list of descriptions for the upload.
+ */
+ ForeignStructuredUpload.prototype.clearDescriptions = function () {
+ this.descriptions = [];
+ };
+
+ /**
+ * Set the date of creation for the upload.
+ *
+ * @param {Date} date
+ */
+ ForeignStructuredUpload.prototype.setDate = function ( date ) {
+ this.date = date;
+ };
+
+ /**
+ * Get the text of the file page, to be created on upload. Brings together
+ * several different pieces of information to create useful text.
+ *
+ * @return {string}
+ */
+ ForeignStructuredUpload.prototype.getText = function () {
+ return this.config.format.filepage
+ // Replace "named parameters" with the given information
+ .replace( '$DESCRIPTION', this.getDescriptions() )
+ .replace( '$DATE', this.getDate() )
+ .replace( '$SOURCE', this.getSource() )
+ .replace( '$AUTHOR', this.getUser() )
+ .replace( '$LICENSE', this.getLicense() )
+ .replace( '$CATEGORIES', this.getCategories() );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ ForeignStructuredUpload.prototype.getComment = function () {
+ var
+ isLocal = this.target === 'local',
+ comment = typeof this.config.comment === 'string' ?
+ this.config.comment :
+ this.config.comment[ isLocal ? 'local' : 'foreign' ];
+ return comment
+ .replace( '$PAGENAME', mw.config.get( 'wgPageName' ) )
+ .replace( '$HOST', location.host );
+ };
+
+ /**
+ * Gets the wikitext for the creation date of this upload.
+ *
+ * @private
+ * @return {string}
+ */
+ ForeignStructuredUpload.prototype.getDate = function () {
+ if ( !this.date ) {
+ return '';
+ }
+
+ return this.date.toString();
+ };
+
+ /**
+ * Fetches the wikitext for any descriptions that have been added
+ * to the upload.
+ *
+ * @private
+ * @return {string}
+ */
+ ForeignStructuredUpload.prototype.getDescriptions = function () {
+ var i, desc, templateCalls = [];
+
+ for ( i = 0; i < this.descriptions.length; i++ ) {
+ desc = this.descriptions[ i ];
+ templateCalls.push(
+ this.config.format.description
+ .replace( '$LANGUAGE', desc.language )
+ .replace( '$TEXT', desc.text )
+ );
+ }
+
+ return templateCalls.join( '\n' );
+ };
+
+ /**
+ * Fetches the wikitext for the categories to which the upload will
+ * be added.
+ *
+ * @private
+ * @return {string}
+ */
+ ForeignStructuredUpload.prototype.getCategories = function () {
+ var i, cat, categoryLinks = [];
+
+ if ( this.categories.length === 0 ) {
+ return this.config.format.uncategorized;
+ }
+
+ for ( i = 0; i < this.categories.length; i++ ) {
+ cat = this.categories[ i ];
+ categoryLinks.push( '[[Category:' + cat + ']]' );
+ }
+
+ return categoryLinks.join( '\n' );
+ };
+
+ /**
+ * Gets the wikitext for the license of the upload.
+ *
+ * @private
+ * @return {string}
+ */
+ ForeignStructuredUpload.prototype.getLicense = function () {
+ return this.config.format.license;
+ };
+
+ /**
+ * Get the source. This should be some sort of localised text for "Own work".
+ *
+ * @private
+ * @return {string}
+ */
+ ForeignStructuredUpload.prototype.getSource = function () {
+ return this.config.format.ownwork;
+ };
+
+ /**
+ * Get the username.
+ *
+ * @private
+ * @return {string}
+ */
+ ForeignStructuredUpload.prototype.getUser = function () {
+ var username, namespace;
+ // Do not localise, we don't know the language of target wiki
+ namespace = 'User';
+ username = mw.config.get( 'wgUserName' );
+ if ( !username ) {
+ // The user is not logged in locally. However, they might be logged in on the foreign wiki.
+ // We should record their username there. (If they're not logged in there either, this will
+ // record the IP address.) It's also possible that the user opened this dialog, got an error
+ // about not being logged in, logged in in another browser tab, then continued uploading.
+ username = '{{subst:REVISIONUSER}}';
+ }
+ return '[[' + namespace + ':' + username + '|' + username + ']]';
+ };
+
+ mw.ForeignStructuredUpload = ForeignStructuredUpload;
+}( mediaWiki, jQuery, OO ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.ForeignUpload.js b/www/wiki/resources/src/mediawiki/mediawiki.ForeignUpload.js
new file mode 100644
index 00000000..08fc01d2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.ForeignUpload.js
@@ -0,0 +1,143 @@
+( function ( mw, OO, $ ) {
+ /**
+ * Used to represent an upload in progress on the frontend.
+ *
+ * Subclassed to upload to a foreign API, with no other goodies. Use
+ * this for a generic foreign image repository on your wiki farm.
+ *
+ * Note you can provide the {@link #target target} or not - if the first argument is
+ * an object, we assume you want the default, and treat it as apiconfig
+ * instead.
+ *
+ * @class mw.ForeignUpload
+ * @extends mw.Upload
+ *
+ * @constructor
+ * @param {string} [target] Used to set up the target
+ * wiki. If not remote, this class behaves identically to mw.Upload (unless further subclassed)
+ * Use the same names as set in $wgForeignFileRepos for this. Also,
+ * make sure there is an entry in the $wgForeignUploadTargets array for this name.
+ * @param {Object} [apiconfig] Passed to the constructor of mw.ForeignApi or mw.Api, as needed.
+ */
+ function ForeignUpload( target, apiconfig ) {
+ var api,
+ validTargets = mw.config.get( 'wgForeignUploadTargets' ),
+ upload = this;
+
+ if ( typeof target === 'object' ) {
+ // target probably wasn't passed in, it must
+ // be apiconfig
+ apiconfig = target;
+ target = undefined;
+ }
+
+ // * Use the given `target` first;
+ // * If not given, fall back to default (first) ForeignUploadTarget;
+ // * If none is configured, fall back to local uploads.
+ this.target = target || validTargets[ 0 ] || 'local';
+
+ // Now we have several different options.
+ // If the local wiki is the target, then we can skip a bunch of steps
+ // and just return an mw.Api object, because we don't need any special
+ // configuration for that.
+ // However, if the target is a remote wiki, we must check the API
+ // to confirm that the target is one that this site is configured to
+ // support.
+ if ( validTargets.length === 0 ) {
+ this.apiPromise = $.Deferred().reject( 'upload-dialog-disabled' );
+ } else if ( this.target === 'local' ) {
+ // If local uploads were requested, but they are disabled, fail.
+ if ( !mw.config.get( 'wgEnableUploads' ) ) {
+ this.apiPromise = $.Deferred().reject( 'uploaddisabledtext' );
+ } else {
+ // We'll ignore the CORS and centralauth stuff if the target is
+ // the local wiki.
+ this.apiPromise = $.Deferred().resolve( new mw.Api( apiconfig ) );
+ }
+ } else {
+ api = new mw.Api();
+ this.apiPromise = api.get( {
+ action: 'query',
+ meta: 'filerepoinfo',
+ friprop: [ 'name', 'scriptDirUrl', 'canUpload' ]
+ } ).then( function ( data ) {
+ var i, repo,
+ repos = data.query.repos;
+
+ // First pass - try to find the passed-in target and check
+ // that it's configured for uploads.
+ for ( i in repos ) {
+ repo = repos[ i ];
+
+ // Skip repos that are not our target, or if they
+ // are the target, cannot be uploaded to.
+ if ( repo.name === upload.target && repo.canUpload === '' ) {
+ return new mw.ForeignApi(
+ repo.scriptDirUrl + '/api.php',
+ apiconfig
+ );
+ }
+ }
+
+ return $.Deferred().reject( 'upload-foreign-cant-upload' );
+ } );
+ }
+
+ // Build the upload object without an API - this class overrides the
+ // actual API call methods to wait for the apiPromise to resolve
+ // before continuing.
+ mw.Upload.call( this, null );
+ }
+
+ OO.inheritClass( ForeignUpload, mw.Upload );
+
+ /**
+ * @property {string} target
+ * Used to specify the target repository of the upload.
+ *
+ * If you set this to something that isn't 'local', you must be sure to
+ * add that target to $wgForeignUploadTargets in LocalSettings, and the
+ * repository must be set up to use CORS and CentralAuth.
+ *
+ * Most wikis use "shared" to refer to Wikimedia Commons, we assume that
+ * in this class and in the messages linked to it.
+ *
+ * Defaults to the first available foreign upload target,
+ * or to local uploads if no foreign target is configured.
+ */
+
+ /**
+ * @inheritdoc
+ */
+ ForeignUpload.prototype.getApi = function () {
+ return this.apiPromise;
+ };
+
+ /**
+ * Override from mw.Upload to make sure the API info is found and allowed
+ *
+ * @inheritdoc
+ */
+ ForeignUpload.prototype.upload = function () {
+ var upload = this;
+ return this.apiPromise.then( function ( api ) {
+ upload.api = api;
+ return mw.Upload.prototype.upload.call( upload );
+ } );
+ };
+
+ /**
+ * Override from mw.Upload to make sure the API info is found and allowed
+ *
+ * @inheritdoc
+ */
+ ForeignUpload.prototype.uploadToStash = function () {
+ var upload = this;
+ return this.apiPromise.then( function ( api ) {
+ upload.api = api;
+ return mw.Upload.prototype.uploadToStash.call( upload );
+ } );
+ };
+
+ mw.ForeignUpload = ForeignUpload;
+}( mediaWiki, OO, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.RegExp.js b/www/wiki/resources/src/mediawiki/mediawiki.RegExp.js
new file mode 100644
index 00000000..91cdc2d1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.RegExp.js
@@ -0,0 +1,22 @@
+( function ( mw ) {
+ /**
+ * @class mw.RegExp
+ */
+ mw.RegExp = {
+ /**
+ * Escape string for safe inclusion in regular expression
+ *
+ * The following characters are escaped:
+ *
+ * \ { } ( ) | . ? * + - ^ $ [ ]
+ *
+ * @since 1.26
+ * @static
+ * @param {string} str String to escape
+ * @return {string} Escaped string
+ */
+ escape: function ( str ) {
+ return str.replace( /([\\{}()|.?*+\-^$\[\]])/g, '\\$1' ); // eslint-disable-line no-useless-escape
+ }
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.Title.js b/www/wiki/resources/src/mediawiki/mediawiki.Title.js
new file mode 100644
index 00000000..53cbd607
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.Title.js
@@ -0,0 +1,976 @@
+/*!
+ * @author Neil Kandalgaonkar, 2010
+ * @author Timo Tijhof, 2011-2013
+ * @since 1.18
+ */
+
+/* eslint-disable no-use-before-define */
+
+( function ( mw, $ ) {
+ /**
+ * Parse titles into an object structure. Note that when using the constructor
+ * directly, passing invalid titles will result in an exception. Use #newFromText to use the
+ * logic directly and get null for invalid titles which is easier to work with.
+ *
+ * Note that in the constructor and #newFromText method, `namespace` is the **default** namespace
+ * only, and can be overridden by a namespace prefix in `title`. If you do not want this behavior,
+ * use #makeTitle. Compare:
+ *
+ * new mw.Title( 'Foo', NS_TEMPLATE ).getPrefixedText(); // => 'Template:Foo'
+ * mw.Title.newFromText( 'Foo', NS_TEMPLATE ).getPrefixedText(); // => 'Template:Foo'
+ * mw.Title.makeTitle( NS_TEMPLATE, 'Foo' ).getPrefixedText(); // => 'Template:Foo'
+ *
+ * new mw.Title( 'Category:Foo', NS_TEMPLATE ).getPrefixedText(); // => 'Category:Foo'
+ * mw.Title.newFromText( 'Category:Foo', NS_TEMPLATE ).getPrefixedText(); // => 'Category:Foo'
+ * mw.Title.makeTitle( NS_TEMPLATE, 'Category:Foo' ).getPrefixedText(); // => 'Template:Category:Foo'
+ *
+ * new mw.Title( 'Template:Foo', NS_TEMPLATE ).getPrefixedText(); // => 'Template:Foo'
+ * mw.Title.newFromText( 'Template:Foo', NS_TEMPLATE ).getPrefixedText(); // => 'Template:Foo'
+ * mw.Title.makeTitle( NS_TEMPLATE, 'Template:Foo' ).getPrefixedText(); // => 'Template:Template:Foo'
+ *
+ * @class mw.Title
+ * @constructor
+ * @param {string} title Title of the page. If no second argument given,
+ * this will be searched for a namespace
+ * @param {number} [namespace=NS_MAIN] If given, will used as default namespace for the given title
+ * @throws {Error} When the title is invalid
+ */
+ function Title( title, namespace ) {
+ var parsed = parse( title, namespace );
+ if ( !parsed ) {
+ throw new Error( 'Unable to parse title' );
+ }
+
+ this.namespace = parsed.namespace;
+ this.title = parsed.title;
+ this.ext = parsed.ext;
+ this.fragment = parsed.fragment;
+ }
+
+ /* Private members */
+
+ // eslint-disable-next-line vars-on-top
+ var
+ namespaceIds = mw.config.get( 'wgNamespaceIds' ),
+
+ /**
+ * @private
+ * @static
+ * @property NS_MAIN
+ */
+ NS_MAIN = namespaceIds[ '' ],
+
+ /**
+ * @private
+ * @static
+ * @property NS_TALK
+ */
+ NS_TALK = namespaceIds.talk,
+
+ /**
+ * @private
+ * @static
+ * @property NS_SPECIAL
+ */
+ NS_SPECIAL = namespaceIds.special,
+
+ /**
+ * @private
+ * @static
+ * @property NS_MEDIA
+ */
+ NS_MEDIA = namespaceIds.media,
+
+ /**
+ * @private
+ * @static
+ * @property NS_FILE
+ */
+ NS_FILE = namespaceIds.file,
+
+ /**
+ * @private
+ * @static
+ * @property FILENAME_MAX_BYTES
+ */
+ FILENAME_MAX_BYTES = 240,
+
+ /**
+ * @private
+ * @static
+ * @property TITLE_MAX_BYTES
+ */
+ TITLE_MAX_BYTES = 255,
+
+ /**
+ * Get the namespace id from a namespace name (either from the localized, canonical or alias
+ * name).
+ *
+ * Example: On a German wiki this would return 6 for any of 'File', 'Datei', 'Image' or
+ * even 'Bild'.
+ *
+ * @private
+ * @static
+ * @method getNsIdByName
+ * @param {string} ns Namespace name (case insensitive, leading/trailing space ignored)
+ * @return {number|boolean} Namespace id or boolean false
+ */
+ getNsIdByName = function ( ns ) {
+ var id;
+
+ // Don't cast non-strings to strings, because null or undefined should not result in
+ // returning the id of a potential namespace called "Null:" (e.g. on null.example.org/wiki)
+ // Also, toLowerCase throws exception on null/undefined, because it is a String method.
+ if ( typeof ns !== 'string' ) {
+ return false;
+ }
+ // TODO: Should just use local var namespaceIds here but it
+ // breaks test which modify the config
+ id = mw.config.get( 'wgNamespaceIds' )[ ns.toLowerCase() ];
+ if ( id === undefined ) {
+ return false;
+ }
+ return id;
+ },
+
+ /**
+ * @private
+ * @method getNamespacePrefix_
+ * @param {number} namespace
+ * @return {string}
+ */
+ getNamespacePrefix = function ( namespace ) {
+ return namespace === NS_MAIN ?
+ '' :
+ ( mw.config.get( 'wgFormattedNamespaces' )[ namespace ].replace( / /g, '_' ) + ':' );
+ },
+
+ rUnderscoreTrim = /^_+|_+$/g,
+
+ rSplit = /^(.+?)_*:_*(.*)$/,
+
+ // See MediaWikiTitleCodec.php#getTitleInvalidRegex
+ rInvalid = new RegExp(
+ '[^' + mw.config.get( 'wgLegalTitleChars' ) + ']' +
+ // URL percent encoding sequences interfere with the ability
+ // to round-trip titles -- you can't link to them consistently.
+ '|%[0-9A-Fa-f]{2}' +
+ // XML/HTML character references produce similar issues.
+ '|&[A-Za-z0-9\u0080-\uFFFF]+;' +
+ '|&#[0-9]+;' +
+ '|&#x[0-9A-Fa-f]+;'
+ ),
+
+ // From MediaWikiTitleCodec::splitTitleString() in PHP
+ // Note that this is not equivalent to /\s/, e.g. underscore is included, tab is not included.
+ rWhitespace = /[ _\u00A0\u1680\u180E\u2000-\u200A\u2028\u2029\u202F\u205F\u3000]+/g,
+
+ // From MediaWikiTitleCodec::splitTitleString() in PHP
+ rUnicodeBidi = /[\u200E\u200F\u202A-\u202E]/g,
+
+ /**
+ * Slightly modified from Flinfo. Credit goes to Lupo and Flominator.
+ * @private
+ * @static
+ * @property sanitationRules
+ */
+ sanitationRules = [
+ // "signature"
+ {
+ pattern: /~{3}/g,
+ replace: '',
+ generalRule: true
+ },
+ // control characters
+ {
+ // eslint-disable-next-line no-control-regex
+ pattern: /[\x00-\x1f\x7f]/g,
+ replace: '',
+ generalRule: true
+ },
+ // URL encoding (possibly)
+ {
+ pattern: /%([0-9A-Fa-f]{2})/g,
+ replace: '% $1',
+ generalRule: true
+ },
+ // HTML-character-entities
+ {
+ pattern: /&(([A-Za-z0-9\x80-\xff]+|#[0-9]+|#x[0-9A-Fa-f]+);)/g,
+ replace: '& $1',
+ generalRule: true
+ },
+ // slash, colon (not supported by file systems like NTFS/Windows, Mac OS 9 [:], ext4 [/])
+ {
+ pattern: new RegExp( '[' + mw.config.get( 'wgIllegalFileChars', '' ) + ']', 'g' ),
+ replace: '-',
+ fileRule: true
+ },
+ // brackets, greater than
+ {
+ pattern: /[}\]>]/g,
+ replace: ')',
+ generalRule: true
+ },
+ // brackets, lower than
+ {
+ pattern: /[{[<]/g,
+ replace: '(',
+ generalRule: true
+ },
+ // everything that wasn't covered yet
+ {
+ pattern: new RegExp( rInvalid.source, 'g' ),
+ replace: '-',
+ generalRule: true
+ },
+ // directory structures
+ {
+ pattern: /^(\.|\.\.|\.\/.*|\.\.\/.*|.*\/\.\/.*|.*\/\.\.\/.*|.*\/\.|.*\/\.\.)$/g,
+ replace: '',
+ generalRule: true
+ }
+ ],
+
+ /**
+ * Internal helper for #constructor and #newFromText.
+ *
+ * Based on Title.php#secureAndSplit
+ *
+ * @private
+ * @static
+ * @method parse
+ * @param {string} title
+ * @param {number} [defaultNamespace=NS_MAIN]
+ * @return {Object|boolean}
+ */
+ parse = function ( title, defaultNamespace ) {
+ var namespace, m, id, i, fragment, ext;
+
+ namespace = defaultNamespace === undefined ? NS_MAIN : defaultNamespace;
+
+ title = title
+ // Strip Unicode bidi override characters
+ .replace( rUnicodeBidi, '' )
+ // Normalise whitespace to underscores and remove duplicates
+ .replace( rWhitespace, '_' )
+ // Trim underscores
+ .replace( rUnderscoreTrim, '' );
+
+ // Process initial colon
+ if ( title !== '' && title[ 0 ] === ':' ) {
+ // Initial colon means main namespace instead of specified default
+ namespace = NS_MAIN;
+ title = title
+ // Strip colon
+ .slice( 1 )
+ // Trim underscores
+ .replace( rUnderscoreTrim, '' );
+ }
+
+ if ( title === '' ) {
+ return false;
+ }
+
+ // Process namespace prefix (if any)
+ m = title.match( rSplit );
+ if ( m ) {
+ id = getNsIdByName( m[ 1 ] );
+ if ( id !== false ) {
+ // Ordinary namespace
+ namespace = id;
+ title = m[ 2 ];
+
+ // For Talk:X pages, make sure X has no "namespace" prefix
+ if ( namespace === NS_TALK && ( m = title.match( rSplit ) ) ) {
+ // Disallow titles like Talk:File:x (subject should roundtrip: talk:file:x -> file:x -> file_talk:x)
+ if ( getNsIdByName( m[ 1 ] ) !== false ) {
+ return false;
+ }
+ }
+ }
+ }
+
+ // Process fragment
+ i = title.indexOf( '#' );
+ if ( i === -1 ) {
+ fragment = null;
+ } else {
+ fragment = title
+ // Get segment starting after the hash
+ .slice( i + 1 )
+ // Convert to text
+ // NB: Must not be trimmed ("Example#_foo" is not the same as "Example#foo")
+ .replace( /_/g, ' ' );
+
+ title = title
+ // Strip hash
+ .slice( 0, i )
+ // Trim underscores, again (strips "_" from "bar" in "Foo_bar_#quux")
+ .replace( rUnderscoreTrim, '' );
+ }
+
+ // Reject illegal characters
+ if ( title.match( rInvalid ) ) {
+ return false;
+ }
+
+ // Disallow titles that browsers or servers might resolve as directory navigation
+ if (
+ title.indexOf( '.' ) !== -1 && (
+ title === '.' || title === '..' ||
+ title.indexOf( './' ) === 0 ||
+ title.indexOf( '../' ) === 0 ||
+ title.indexOf( '/./' ) !== -1 ||
+ title.indexOf( '/../' ) !== -1 ||
+ title.slice( -2 ) === '/.' ||
+ title.slice( -3 ) === '/..'
+ )
+ ) {
+ return false;
+ }
+
+ // Disallow magic tilde sequence
+ if ( title.indexOf( '~~~' ) !== -1 ) {
+ return false;
+ }
+
+ // Disallow titles exceeding the TITLE_MAX_BYTES byte size limit (size of underlying database field)
+ // Except for special pages, e.g. [[Special:Block/Long name]]
+ // Note: The PHP implementation also asserts that even in NS_SPECIAL, the title should
+ // be less than 512 bytes.
+ if ( namespace !== NS_SPECIAL && $.byteLength( title ) > TITLE_MAX_BYTES ) {
+ return false;
+ }
+
+ // Can't make a link to a namespace alone.
+ if ( title === '' && namespace !== NS_MAIN ) {
+ return false;
+ }
+
+ // Any remaining initial :s are illegal.
+ if ( title[ 0 ] === ':' ) {
+ return false;
+ }
+
+ // For backwards-compatibility with old mw.Title, we separate the extension from the
+ // rest of the title.
+ i = title.lastIndexOf( '.' );
+ if ( i === -1 || title.length <= i + 1 ) {
+ // Extensions are the non-empty segment after the last dot
+ ext = null;
+ } else {
+ ext = title.slice( i + 1 );
+ title = title.slice( 0, i );
+ }
+
+ return {
+ namespace: namespace,
+ title: title,
+ ext: ext,
+ fragment: fragment
+ };
+ },
+
+ /**
+ * Convert db-key to readable text.
+ *
+ * @private
+ * @static
+ * @method text
+ * @param {string} s
+ * @return {string}
+ */
+ text = function ( s ) {
+ if ( s !== null && s !== undefined ) {
+ return s.replace( /_/g, ' ' );
+ } else {
+ return '';
+ }
+ },
+
+ /**
+ * Sanitizes a string based on a rule set and a filter
+ *
+ * @private
+ * @static
+ * @method sanitize
+ * @param {string} s
+ * @param {Array} filter
+ * @return {string}
+ */
+ sanitize = function ( s, filter ) {
+ var i, ruleLength, rule, m, filterLength,
+ rules = sanitationRules;
+
+ for ( i = 0, ruleLength = rules.length; i < ruleLength; ++i ) {
+ rule = rules[ i ];
+ for ( m = 0, filterLength = filter.length; m < filterLength; ++m ) {
+ if ( rule[ filter[ m ] ] ) {
+ s = s.replace( rule.pattern, rule.replace );
+ }
+ }
+ }
+ return s;
+ },
+
+ /**
+ * Cuts a string to a specific byte length, assuming UTF-8
+ * or less, if the last character is a multi-byte one
+ *
+ * @private
+ * @static
+ * @method trimToByteLength
+ * @param {string} s
+ * @param {number} length
+ * @return {string}
+ */
+ trimToByteLength = function ( s, length ) {
+ var byteLength, chopOffChars, chopOffBytes;
+
+ // bytelength is always greater or equal to the length in characters
+ s = s.substr( 0, length );
+ while ( ( byteLength = $.byteLength( s ) ) > length ) {
+ // Calculate how many characters can be safely removed
+ // First, we need to know how many bytes the string exceeds the threshold
+ chopOffBytes = byteLength - length;
+ // A character in UTF-8 is at most 4 bytes
+ // One character must be removed in any case because the
+ // string is too long
+ chopOffChars = Math.max( 1, Math.floor( chopOffBytes / 4 ) );
+ s = s.substr( 0, s.length - chopOffChars );
+ }
+ return s;
+ },
+
+ /**
+ * Cuts a file name to a specific byte length
+ *
+ * @private
+ * @static
+ * @method trimFileNameToByteLength
+ * @param {string} name without extension
+ * @param {string} extension file extension
+ * @return {string} The full name, including extension
+ */
+ trimFileNameToByteLength = function ( name, extension ) {
+ // There is a special byte limit for file names and ... remember the dot
+ return trimToByteLength( name, FILENAME_MAX_BYTES - extension.length - 1 ) + '.' + extension;
+ };
+
+ /* Static members */
+
+ /**
+ * Constructor for Title objects with a null return instead of an exception for invalid titles.
+ *
+ * Note that `namespace` is the **default** namespace only, and can be overridden by a namespace
+ * prefix in `title`. If you do not want this behavior, use #makeTitle. See #constructor for
+ * details.
+ *
+ * @static
+ * @param {string} title
+ * @param {number} [namespace=NS_MAIN] Default namespace
+ * @return {mw.Title|null} A valid Title object or null if the title is invalid
+ */
+ Title.newFromText = function ( title, namespace ) {
+ var t, parsed = parse( title, namespace );
+ if ( !parsed ) {
+ return null;
+ }
+
+ t = Object.create( Title.prototype );
+ t.namespace = parsed.namespace;
+ t.title = parsed.title;
+ t.ext = parsed.ext;
+ t.fragment = parsed.fragment;
+
+ return t;
+ };
+
+ /**
+ * Constructor for Title objects with predefined namespace.
+ *
+ * Unlike #newFromText or #constructor, this function doesn't allow the given `namespace` to be
+ * overridden by a namespace prefix in `title`. See #constructor for details about this behavior.
+ *
+ * The single exception to this is when `namespace` is 0, indicating the main namespace. The
+ * function behaves like #newFromText in that case.
+ *
+ * @static
+ * @param {number} namespace Namespace to use for the title
+ * @param {string} title
+ * @return {mw.Title|null} A valid Title object or null if the title is invalid
+ */
+ Title.makeTitle = function ( namespace, title ) {
+ return mw.Title.newFromText( getNamespacePrefix( namespace ) + title );
+ };
+
+ /**
+ * Constructor for Title objects from user input altering that input to
+ * produce a title that MediaWiki will accept as legal
+ *
+ * @static
+ * @param {string} title
+ * @param {number} [defaultNamespace=NS_MAIN]
+ * If given, will used as default namespace for the given title.
+ * @param {Object} [options] additional options
+ * @param {boolean} [options.forUploading=true]
+ * Makes sure that a file is uploadable under the title returned.
+ * There are pages in the file namespace under which file upload is impossible.
+ * Automatically assumed if the title is created in the Media namespace.
+ * @return {mw.Title|null} A valid Title object or null if the input cannot be turned into a valid title
+ */
+ Title.newFromUserInput = function ( title, defaultNamespace, options ) {
+ var namespace, m, id, ext, parts;
+
+ // defaultNamespace is optional; check whether options moves up
+ if ( arguments.length < 3 && $.type( defaultNamespace ) === 'object' ) {
+ options = defaultNamespace;
+ defaultNamespace = undefined;
+ }
+
+ // merge options into defaults
+ options = $.extend( {
+ forUploading: true
+ }, options );
+
+ namespace = defaultNamespace === undefined ? NS_MAIN : defaultNamespace;
+
+ // Normalise additional whitespace
+ title = $.trim( title.replace( /\s/g, ' ' ) );
+
+ // Process initial colon
+ if ( title !== '' && title[ 0 ] === ':' ) {
+ // Initial colon means main namespace instead of specified default
+ namespace = NS_MAIN;
+ title = title
+ // Strip colon
+ .substr( 1 )
+ // Trim underscores
+ .replace( rUnderscoreTrim, '' );
+ }
+
+ // Process namespace prefix (if any)
+ m = title.match( rSplit );
+ if ( m ) {
+ id = getNsIdByName( m[ 1 ] );
+ if ( id !== false ) {
+ // Ordinary namespace
+ namespace = id;
+ title = m[ 2 ];
+ }
+ }
+
+ if (
+ namespace === NS_MEDIA ||
+ ( options.forUploading && ( namespace === NS_FILE ) )
+ ) {
+
+ title = sanitize( title, [ 'generalRule', 'fileRule' ] );
+
+ // Operate on the file extension
+ // Although it is possible having spaces between the name and the ".ext" this isn't nice for
+ // operating systems hiding file extensions -> strip them later on
+ parts = title.split( '.' );
+
+ if ( parts.length > 1 ) {
+
+ // Get the last part, which is supposed to be the file extension
+ ext = parts.pop();
+
+ // Remove whitespace of the name part (that W/O extension)
+ title = $.trim( parts.join( '.' ) );
+
+ // Cut, if too long and append file extension
+ title = trimFileNameToByteLength( title, ext );
+
+ } else {
+
+ // Missing file extension
+ title = $.trim( parts.join( '.' ) );
+
+ // Name has no file extension and a fallback wasn't provided either
+ return null;
+ }
+ } else {
+
+ title = sanitize( title, [ 'generalRule' ] );
+
+ // Cut titles exceeding the TITLE_MAX_BYTES byte size limit
+ // (size of underlying database field)
+ if ( namespace !== NS_SPECIAL ) {
+ title = trimToByteLength( title, TITLE_MAX_BYTES );
+ }
+ }
+
+ // Any remaining initial :s are illegal.
+ title = title.replace( /^:+/, '' );
+
+ return Title.newFromText( title, namespace );
+ };
+
+ /**
+ * Sanitizes a file name as supplied by the user, originating in the user's file system
+ * so it is most likely a valid MediaWiki title and file name after processing.
+ * Returns null on fatal errors.
+ *
+ * @static
+ * @param {string} uncleanName The unclean file name including file extension but
+ * without namespace
+ * @return {mw.Title|null} A valid Title object or null if the title is invalid
+ */
+ Title.newFromFileName = function ( uncleanName ) {
+
+ return Title.newFromUserInput( 'File:' + uncleanName, {
+ forUploading: true
+ } );
+ };
+
+ /**
+ * Get the file title from an image element
+ *
+ * var title = mw.Title.newFromImg( $( 'img:first' ) );
+ *
+ * @static
+ * @param {HTMLElement|jQuery} img The image to use as a base
+ * @return {mw.Title|null} The file title or null if unsuccessful
+ */
+ Title.newFromImg = function ( img ) {
+ var matches, i, regex, src, decodedSrc,
+
+ // thumb.php-generated thumbnails
+ thumbPhpRegex = /thumb\.php/,
+ regexes = [
+ // Thumbnails
+ /\/[a-f0-9]\/[a-f0-9]{2}\/([^\s/]+)\/[^\s/]+-[^\s/]*$/,
+
+ // Full size images
+ /\/[a-f0-9]\/[a-f0-9]{2}\/([^\s/]+)$/,
+
+ // Thumbnails in non-hashed upload directories
+ /\/([^\s/]+)\/[^\s/]+-(?:\1|thumbnail)[^\s/]*$/,
+
+ // Full-size images in non-hashed upload directories
+ /\/([^\s/]+)$/
+ ],
+
+ recount = regexes.length;
+
+ src = img.jquery ? img[ 0 ].src : img.src;
+
+ matches = src.match( thumbPhpRegex );
+
+ if ( matches ) {
+ return mw.Title.newFromText( 'File:' + mw.util.getParamValue( 'f', src ) );
+ }
+
+ decodedSrc = decodeURIComponent( src );
+
+ for ( i = 0; i < recount; i++ ) {
+ regex = regexes[ i ];
+ matches = decodedSrc.match( regex );
+
+ if ( matches && matches[ 1 ] ) {
+ return mw.Title.newFromText( 'File:' + matches[ 1 ] );
+ }
+ }
+
+ return null;
+ };
+
+ /**
+ * Whether this title exists on the wiki.
+ *
+ * @static
+ * @param {string|mw.Title} title prefixed db-key name (string) or instance of Title
+ * @return {boolean|null} Boolean if the information is available, otherwise null
+ */
+ Title.exists = function ( title ) {
+ var match,
+ obj = Title.exist.pages;
+
+ if ( typeof title === 'string' ) {
+ match = obj[ title ];
+ } else if ( title instanceof Title ) {
+ match = obj[ title.toString() ];
+ } else {
+ throw new Error( 'mw.Title.exists: title must be a string or an instance of Title' );
+ }
+
+ if ( typeof match !== 'boolean' ) {
+ return null;
+ }
+
+ return match;
+ };
+
+ /**
+ * Store page existence
+ *
+ * @static
+ * @property {Object} exist
+ * @property {Object} exist.pages Keyed by title. Boolean true value indicates page does exist.
+ *
+ * @property {Function} exist.set The setter function.
+ *
+ * Example to declare existing titles:
+ *
+ * Title.exist.set( ['User:John_Doe', ...] );
+ *
+ * Example to declare titles nonexistent:
+ *
+ * Title.exist.set( ['File:Foo_bar.jpg', ...], false );
+ *
+ * @property {string|Array} exist.set.titles Title(s) in strict prefixedDb title form
+ * @property {boolean} [exist.set.state=true] State of the given titles
+ * @return {boolean}
+ */
+ Title.exist = {
+ pages: {},
+
+ set: function ( titles, state ) {
+ var i, len,
+ pages = this.pages;
+
+ titles = Array.isArray( titles ) ? titles : [ titles ];
+ state = state === undefined ? true : !!state;
+
+ for ( i = 0, len = titles.length; i < len; i++ ) {
+ pages[ titles[ i ] ] = state;
+ }
+ return true;
+ }
+ };
+
+ /**
+ * Normalize a file extension to the common form, making it lowercase and checking some synonyms,
+ * and ensure it's clean. Extensions with non-alphanumeric characters will be discarded.
+ * Keep in sync with File::normalizeExtension() in PHP.
+ *
+ * @param {string} extension File extension (without the leading dot)
+ * @return {string} File extension in canonical form
+ */
+ Title.normalizeExtension = function ( extension ) {
+ var
+ lower = extension.toLowerCase(),
+ squish = {
+ htm: 'html',
+ jpeg: 'jpg',
+ mpeg: 'mpg',
+ tiff: 'tif',
+ ogv: 'ogg'
+ };
+ if ( squish.hasOwnProperty( lower ) ) {
+ return squish[ lower ];
+ } else if ( /^[0-9a-z]+$/.test( lower ) ) {
+ return lower;
+ } else {
+ return '';
+ }
+ };
+
+ /* Public members */
+
+ Title.prototype = {
+ constructor: Title,
+
+ /**
+ * Get the namespace number
+ *
+ * Example: 6 for "File:Example_image.svg".
+ *
+ * @return {number}
+ */
+ getNamespaceId: function () {
+ return this.namespace;
+ },
+
+ /**
+ * Get the namespace prefix (in the content language)
+ *
+ * Example: "File:" for "File:Example_image.svg".
+ * In #NS_MAIN this is '', otherwise namespace name plus ':'
+ *
+ * @return {string}
+ */
+ getNamespacePrefix: function () {
+ return getNamespacePrefix( this.namespace );
+ },
+
+ /**
+ * Get the page name without extension or namespace prefix
+ *
+ * Example: "Example_image" for "File:Example_image.svg".
+ *
+ * For the page title (full page name without namespace prefix), see #getMain.
+ *
+ * @return {string}
+ */
+ getName: function () {
+ if (
+ $.inArray( this.namespace, mw.config.get( 'wgCaseSensitiveNamespaces' ) ) !== -1 ||
+ !this.title.length
+ ) {
+ return this.title;
+ }
+ // PHP's strtoupper differs from String.toUpperCase in a number of cases
+ // Bug: T147646
+ return mw.Title.phpCharToUpper( this.title[ 0 ] ) + this.title.slice( 1 );
+ },
+
+ /**
+ * Get the page name (transformed by #text)
+ *
+ * Example: "Example image" for "File:Example_image.svg".
+ *
+ * For the page title (full page name without namespace prefix), see #getMainText.
+ *
+ * @return {string}
+ */
+ getNameText: function () {
+ return text( this.getName() );
+ },
+
+ /**
+ * Get the extension of the page name (if any)
+ *
+ * @return {string|null} Name extension or null if there is none
+ */
+ getExtension: function () {
+ return this.ext;
+ },
+
+ /**
+ * Shortcut for appendable string to form the main page name.
+ *
+ * Returns a string like ".json", or "" if no extension.
+ *
+ * @return {string}
+ */
+ getDotExtension: function () {
+ return this.ext === null ? '' : '.' + this.ext;
+ },
+
+ /**
+ * Get the main page name
+ *
+ * Example: "Example_image.svg" for "File:Example_image.svg".
+ *
+ * @return {string}
+ */
+ getMain: function () {
+ return this.getName() + this.getDotExtension();
+ },
+
+ /**
+ * Get the main page name (transformed by #text)
+ *
+ * Example: "Example image.svg" for "File:Example_image.svg".
+ *
+ * @return {string}
+ */
+ getMainText: function () {
+ return text( this.getMain() );
+ },
+
+ /**
+ * Get the full page name
+ *
+ * Example: "File:Example_image.svg".
+ * Most useful for API calls, anything that must identify the "title".
+ *
+ * @return {string}
+ */
+ getPrefixedDb: function () {
+ return this.getNamespacePrefix() + this.getMain();
+ },
+
+ /**
+ * Get the full page name (transformed by #text)
+ *
+ * Example: "File:Example image.svg" for "File:Example_image.svg".
+ *
+ * @return {string}
+ */
+ getPrefixedText: function () {
+ return text( this.getPrefixedDb() );
+ },
+
+ /**
+ * Get the page name relative to a namespace
+ *
+ * Example:
+ *
+ * - "Foo:Bar" relative to the Foo namespace becomes "Bar".
+ * - "Bar" relative to any non-main namespace becomes ":Bar".
+ * - "Foo:Bar" relative to any namespace other than Foo stays "Foo:Bar".
+ *
+ * @param {number} namespace The namespace to be relative to
+ * @return {string}
+ */
+ getRelativeText: function ( namespace ) {
+ if ( this.getNamespaceId() === namespace ) {
+ return this.getMainText();
+ } else if ( this.getNamespaceId() === NS_MAIN ) {
+ return ':' + this.getPrefixedText();
+ } else {
+ return this.getPrefixedText();
+ }
+ },
+
+ /**
+ * Get the fragment (if any).
+ *
+ * Note that this method (by design) does not include the hash character and
+ * the value is not url encoded.
+ *
+ * @return {string|null}
+ */
+ getFragment: function () {
+ return this.fragment;
+ },
+
+ /**
+ * Get the URL to this title
+ *
+ * @see mw.util#getUrl
+ * @param {Object} [params] A mapping of query parameter names to values,
+ * e.g. `{ action: 'edit' }`.
+ * @return {string}
+ */
+ getUrl: function ( params ) {
+ var fragment = this.getFragment();
+ if ( fragment ) {
+ return mw.util.getUrl( this.toString() + '#' + fragment, params );
+ } else {
+ return mw.util.getUrl( this.toString(), params );
+ }
+ },
+
+ /**
+ * Whether this title exists on the wiki.
+ *
+ * @see #static-method-exists
+ * @return {boolean|null} Boolean if the information is available, otherwise null
+ */
+ exists: function () {
+ return Title.exists( this );
+ }
+ };
+
+ /**
+ * @alias #getPrefixedDb
+ * @method
+ */
+ Title.prototype.toString = Title.prototype.getPrefixedDb;
+
+ /**
+ * @alias #getPrefixedText
+ * @method
+ */
+ Title.prototype.toText = Title.prototype.getPrefixedText;
+
+ // Expose
+ mw.Title = Title;
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js b/www/wiki/resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js
new file mode 100644
index 00000000..2b39c9ab
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.Title.phpCharToUpper.js
@@ -0,0 +1,255 @@
+// This file can't be parsed by JSDuck due to <https://github.com/tenderlove/rkelly/issues/35>.
+// (It is excluded in jsduck.json.)
+// ESLint suggests unquoting some object keys, which would render the file unparseable by Opera 12.
+/* eslint-disable quote-props */
+( function ( mw ) {
+ var toUpperMapping = {
+ 'ß': 'ß',
+ 'ʼn': 'ʼn',
+ 'Dž': 'Dž',
+ 'dž': 'Dž',
+ 'Lj': 'Lj',
+ 'lj': 'Lj',
+ 'Nj': 'Nj',
+ 'nj': 'Nj',
+ 'ǰ': 'ǰ',
+ 'Dz': 'Dz',
+ 'dz': 'Dz',
+ 'ʝ': 'Ʝ',
+ 'ͅ': 'ͅ',
+ 'ΐ': 'ΐ',
+ 'ΰ': 'ΰ',
+ 'և': 'և',
+ 'ᏸ': 'Ᏸ',
+ 'ᏹ': 'Ᏹ',
+ 'ᏺ': 'Ᏺ',
+ 'ᏻ': 'Ᏻ',
+ 'ᏼ': 'Ᏼ',
+ 'ᏽ': 'Ᏽ',
+ 'ẖ': 'ẖ',
+ 'ẗ': 'ẗ',
+ 'ẘ': 'ẘ',
+ 'ẙ': 'ẙ',
+ 'ẚ': 'ẚ',
+ 'ὐ': 'ὐ',
+ 'ὒ': 'ὒ',
+ 'ὔ': 'ὔ',
+ 'ὖ': 'ὖ',
+ 'ᾀ': 'ᾈ',
+ 'ᾁ': 'ᾉ',
+ 'ᾂ': 'ᾊ',
+ 'ᾃ': 'ᾋ',
+ 'ᾄ': 'ᾌ',
+ 'ᾅ': 'ᾍ',
+ 'ᾆ': 'ᾎ',
+ 'ᾇ': 'ᾏ',
+ 'ᾈ': 'ᾈ',
+ 'ᾉ': 'ᾉ',
+ 'ᾊ': 'ᾊ',
+ 'ᾋ': 'ᾋ',
+ 'ᾌ': 'ᾌ',
+ 'ᾍ': 'ᾍ',
+ 'ᾎ': 'ᾎ',
+ 'ᾏ': 'ᾏ',
+ 'ᾐ': 'ᾘ',
+ 'ᾑ': 'ᾙ',
+ 'ᾒ': 'ᾚ',
+ 'ᾓ': 'ᾛ',
+ 'ᾔ': 'ᾜ',
+ 'ᾕ': 'ᾝ',
+ 'ᾖ': 'ᾞ',
+ 'ᾗ': 'ᾟ',
+ 'ᾘ': 'ᾘ',
+ 'ᾙ': 'ᾙ',
+ 'ᾚ': 'ᾚ',
+ 'ᾛ': 'ᾛ',
+ 'ᾜ': 'ᾜ',
+ 'ᾝ': 'ᾝ',
+ 'ᾞ': 'ᾞ',
+ 'ᾟ': 'ᾟ',
+ 'ᾠ': 'ᾨ',
+ 'ᾡ': 'ᾩ',
+ 'ᾢ': 'ᾪ',
+ 'ᾣ': 'ᾫ',
+ 'ᾤ': 'ᾬ',
+ 'ᾥ': 'ᾭ',
+ 'ᾦ': 'ᾮ',
+ 'ᾧ': 'ᾯ',
+ 'ᾨ': 'ᾨ',
+ 'ᾩ': 'ᾩ',
+ 'ᾪ': 'ᾪ',
+ 'ᾫ': 'ᾫ',
+ 'ᾬ': 'ᾬ',
+ 'ᾭ': 'ᾭ',
+ 'ᾮ': 'ᾮ',
+ 'ᾯ': 'ᾯ',
+ 'ᾲ': 'ᾲ',
+ 'ᾳ': 'ᾼ',
+ 'ᾴ': 'ᾴ',
+ 'ᾶ': 'ᾶ',
+ 'ᾷ': 'ᾷ',
+ 'ᾼ': 'ᾼ',
+ 'ῂ': 'ῂ',
+ 'ῃ': 'ῌ',
+ 'ῄ': 'ῄ',
+ 'ῆ': 'ῆ',
+ 'ῇ': 'ῇ',
+ 'ῌ': 'ῌ',
+ 'ῒ': 'ῒ',
+ 'ΐ': 'ΐ',
+ 'ῖ': 'ῖ',
+ 'ῗ': 'ῗ',
+ 'ῢ': 'ῢ',
+ 'ΰ': 'ΰ',
+ 'ῤ': 'ῤ',
+ 'ῦ': 'ῦ',
+ 'ῧ': 'ῧ',
+ 'ῲ': 'ῲ',
+ 'ῳ': 'ῼ',
+ 'ῴ': 'ῴ',
+ 'ῶ': 'ῶ',
+ 'ῷ': 'ῷ',
+ 'ῼ': 'ῼ',
+ 'ⅰ': 'ⅰ',
+ 'ⅱ': 'ⅱ',
+ 'ⅲ': 'ⅲ',
+ 'ⅳ': 'ⅳ',
+ 'ⅴ': 'ⅴ',
+ 'ⅵ': 'ⅵ',
+ 'ⅶ': 'ⅶ',
+ 'ⅷ': 'ⅷ',
+ 'ⅸ': 'ⅸ',
+ 'ⅹ': 'ⅹ',
+ 'ⅺ': 'ⅺ',
+ 'ⅻ': 'ⅻ',
+ 'ⅼ': 'ⅼ',
+ 'ⅽ': 'ⅽ',
+ 'ⅾ': 'ⅾ',
+ 'ⅿ': 'ⅿ',
+ 'ⓐ': 'ⓐ',
+ 'ⓑ': 'ⓑ',
+ 'ⓒ': 'ⓒ',
+ 'ⓓ': 'ⓓ',
+ 'ⓔ': 'ⓔ',
+ 'ⓕ': 'ⓕ',
+ 'ⓖ': 'ⓖ',
+ 'ⓗ': 'ⓗ',
+ 'ⓘ': 'ⓘ',
+ 'ⓙ': 'ⓙ',
+ 'ⓚ': 'ⓚ',
+ 'ⓛ': 'ⓛ',
+ 'ⓜ': 'ⓜ',
+ 'ⓝ': 'ⓝ',
+ 'ⓞ': 'ⓞ',
+ 'ⓟ': 'ⓟ',
+ 'ⓠ': 'ⓠ',
+ 'ⓡ': 'ⓡ',
+ 'ⓢ': 'ⓢ',
+ 'ⓣ': 'ⓣ',
+ 'ⓤ': 'ⓤ',
+ 'ⓥ': 'ⓥ',
+ 'ⓦ': 'ⓦ',
+ 'ⓧ': 'ⓧ',
+ 'ⓨ': 'ⓨ',
+ 'ⓩ': 'ⓩ',
+ 'ꞵ': 'Ꞵ',
+ 'ꞷ': 'Ꞷ',
+ 'ꭓ': 'Ꭓ',
+ 'ꭰ': 'Ꭰ',
+ 'ꭱ': 'Ꭱ',
+ 'ꭲ': 'Ꭲ',
+ 'ꭳ': 'Ꭳ',
+ 'ꭴ': 'Ꭴ',
+ 'ꭵ': 'Ꭵ',
+ 'ꭶ': 'Ꭶ',
+ 'ꭷ': 'Ꭷ',
+ 'ꭸ': 'Ꭸ',
+ 'ꭹ': 'Ꭹ',
+ 'ꭺ': 'Ꭺ',
+ 'ꭻ': 'Ꭻ',
+ 'ꭼ': 'Ꭼ',
+ 'ꭽ': 'Ꭽ',
+ 'ꭾ': 'Ꭾ',
+ 'ꭿ': 'Ꭿ',
+ 'ꮀ': 'Ꮀ',
+ 'ꮁ': 'Ꮁ',
+ 'ꮂ': 'Ꮂ',
+ 'ꮃ': 'Ꮃ',
+ 'ꮄ': 'Ꮄ',
+ 'ꮅ': 'Ꮅ',
+ 'ꮆ': 'Ꮆ',
+ 'ꮇ': 'Ꮇ',
+ 'ꮈ': 'Ꮈ',
+ 'ꮉ': 'Ꮉ',
+ 'ꮊ': 'Ꮊ',
+ 'ꮋ': 'Ꮋ',
+ 'ꮌ': 'Ꮌ',
+ 'ꮍ': 'Ꮍ',
+ 'ꮎ': 'Ꮎ',
+ 'ꮏ': 'Ꮏ',
+ 'ꮐ': 'Ꮐ',
+ 'ꮑ': 'Ꮑ',
+ 'ꮒ': 'Ꮒ',
+ 'ꮓ': 'Ꮓ',
+ 'ꮔ': 'Ꮔ',
+ 'ꮕ': 'Ꮕ',
+ 'ꮖ': 'Ꮖ',
+ 'ꮗ': 'Ꮗ',
+ 'ꮘ': 'Ꮘ',
+ 'ꮙ': 'Ꮙ',
+ 'ꮚ': 'Ꮚ',
+ 'ꮛ': 'Ꮛ',
+ 'ꮜ': 'Ꮜ',
+ 'ꮝ': 'Ꮝ',
+ 'ꮞ': 'Ꮞ',
+ 'ꮟ': 'Ꮟ',
+ 'ꮠ': 'Ꮠ',
+ 'ꮡ': 'Ꮡ',
+ 'ꮢ': 'Ꮢ',
+ 'ꮣ': 'Ꮣ',
+ 'ꮤ': 'Ꮤ',
+ 'ꮥ': 'Ꮥ',
+ 'ꮦ': 'Ꮦ',
+ 'ꮧ': 'Ꮧ',
+ 'ꮨ': 'Ꮨ',
+ 'ꮩ': 'Ꮩ',
+ 'ꮪ': 'Ꮪ',
+ 'ꮫ': 'Ꮫ',
+ 'ꮬ': 'Ꮬ',
+ 'ꮭ': 'Ꮭ',
+ 'ꮮ': 'Ꮮ',
+ 'ꮯ': 'Ꮯ',
+ 'ꮰ': 'Ꮰ',
+ 'ꮱ': 'Ꮱ',
+ 'ꮲ': 'Ꮲ',
+ 'ꮳ': 'Ꮳ',
+ 'ꮴ': 'Ꮴ',
+ 'ꮵ': 'Ꮵ',
+ 'ꮶ': 'Ꮶ',
+ 'ꮷ': 'Ꮷ',
+ 'ꮸ': 'Ꮸ',
+ 'ꮹ': 'Ꮹ',
+ 'ꮺ': 'Ꮺ',
+ 'ꮻ': 'Ꮻ',
+ 'ꮼ': 'Ꮼ',
+ 'ꮽ': 'Ꮽ',
+ 'ꮾ': 'Ꮾ',
+ 'ꮿ': 'Ꮿ',
+ 'ff': 'ff',
+ 'fi': 'fi',
+ 'fl': 'fl',
+ 'ffi': 'ffi',
+ 'ffl': 'ffl',
+ 'ſt': 'ſt',
+ 'st': 'st',
+ 'ﬓ': 'ﬓ',
+ 'ﬔ': 'ﬔ',
+ 'ﬕ': 'ﬕ',
+ 'ﬖ': 'ﬖ',
+ 'ﬗ': 'ﬗ'
+ };
+ mw.Title.phpCharToUpper = function ( chr ) {
+ var mapped = toUpperMapping[ chr ];
+ return mapped || chr.toUpperCase();
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.Upload.BookletLayout.css b/www/wiki/resources/src/mediawiki/mediawiki.Upload.BookletLayout.css
new file mode 100644
index 00000000..72ce9f0b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.Upload.BookletLayout.css
@@ -0,0 +1,34 @@
+.mw-upload-bookletLayout-filePreview {
+ width: 100%;
+ height: 1em;
+ background-color: #eaecf0;
+ background-size: cover;
+ background-position: center center;
+ padding: 1.5em;
+ margin: -1.5em;
+ margin-bottom: 1.5em;
+ position: relative;
+}
+
+.mw-upload-bookletLayout-infoForm.mw-upload-bookletLayout-hasThumbnail .mw-upload-bookletLayout-filePreview {
+ height: 10em;
+}
+
+.mw-upload-bookletLayout-filePreview p {
+ line-height: 1em;
+ margin: 0;
+}
+
+.mw-upload-bookletLayout-filePreview .oo-ui-progressBarWidget {
+ border: 0;
+ border-radius: 0;
+ background-color: transparent;
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ right: 0;
+}
+
+.mw-upload-bookletLayout-filePreview .oo-ui-progressBarWidget-bar {
+ height: 0.5em;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js b/www/wiki/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js
new file mode 100644
index 00000000..3ade332c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.Upload.BookletLayout.js
@@ -0,0 +1,711 @@
+/* global moment */
+( function ( $, mw, moment ) {
+
+ /**
+ * mw.Upload.BookletLayout encapsulates the process of uploading a file
+ * to MediaWiki using the {@link mw.Upload upload model}.
+ * The booklet emits events that can be used to get the stashed
+ * upload and the final file. It can be extended to accept
+ * additional fields from the user for specific scenarios like
+ * for Commons, or campaigns.
+ *
+ * ## Structure
+ *
+ * The {@link OO.ui.BookletLayout booklet layout} has three steps:
+ *
+ * - **Upload**: Has a {@link OO.ui.SelectFileWidget field} to get the file object.
+ *
+ * - **Information**: Has a {@link OO.ui.FormLayout form} to collect metadata. This can be
+ * extended.
+ *
+ * - **Insert**: Has details on how to use the file that was uploaded.
+ *
+ * Each step has a form associated with it defined in
+ * {@link #renderUploadForm renderUploadForm},
+ * {@link #renderInfoForm renderInfoForm}, and
+ * {@link #renderInsertForm renderInfoForm}. The
+ * {@link #getFile getFile},
+ * {@link #getFilename getFilename}, and
+ * {@link #getText getText} methods are used to get
+ * the information filled in these forms, required to call
+ * {@link mw.Upload mw.Upload}.
+ *
+ * ## Usage
+ *
+ * See the {@link mw.Upload.Dialog upload dialog}.
+ *
+ * The {@link #event-fileUploaded fileUploaded},
+ * and {@link #event-fileSaved fileSaved} events can
+ * be used to get details of the upload.
+ *
+ * ## Extending
+ *
+ * To extend using {@link mw.Upload mw.Upload}, override
+ * {@link #renderInfoForm renderInfoForm} to render
+ * the form required for the specific use-case. Update the
+ * {@link #getFilename getFilename}, and
+ * {@link #getText getText} methods to return data
+ * from your newly created form. If you added new fields you'll also have
+ * to update the {@link #clear} method.
+ *
+ * If you plan to use a different upload model, apart from what is mentioned
+ * above, you'll also have to override the
+ * {@link #createUpload createUpload} method to
+ * return the new model. The {@link #saveFile saveFile}, and
+ * the {@link #uploadFile uploadFile} methods need to be
+ * overridden to use the new model and data returned from the forms.
+ *
+ * @class
+ * @extends OO.ui.BookletLayout
+ *
+ * @constructor
+ * @param {Object} config Configuration options
+ * @cfg {jQuery} [$overlay] Overlay to use for widgets in the booklet
+ * @cfg {string} [filekey] Sets the stashed file to finish uploading. Overrides most of the file selection process, and fetches a thumbnail from the server.
+ */
+ mw.Upload.BookletLayout = function ( config ) {
+ // Parent constructor
+ mw.Upload.BookletLayout.parent.call( this, config );
+
+ this.$overlay = config.$overlay;
+
+ this.filekey = config.filekey;
+
+ this.renderUploadForm();
+ this.renderInfoForm();
+ this.renderInsertForm();
+
+ this.addPages( [
+ new OO.ui.PageLayout( 'upload', {
+ scrollable: true,
+ padded: true,
+ content: [ this.uploadForm ]
+ } ),
+ new OO.ui.PageLayout( 'info', {
+ scrollable: true,
+ padded: true,
+ content: [ this.infoForm ]
+ } ),
+ new OO.ui.PageLayout( 'insert', {
+ scrollable: true,
+ padded: true,
+ content: [ this.insertForm ]
+ } )
+ ] );
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.Upload.BookletLayout, OO.ui.BookletLayout );
+
+ /* Events */
+
+ /**
+ * Progress events for the uploaded file
+ *
+ * @event fileUploadProgress
+ * @param {number} progress In percentage
+ * @param {Object} duration Duration object from `moment.duration()`
+ */
+
+ /**
+ * The file has finished uploading
+ *
+ * @event fileUploaded
+ */
+
+ /**
+ * The file has been saved to the database
+ *
+ * @event fileSaved
+ * @param {Object} imageInfo See mw.Upload#getImageInfo
+ */
+
+ /**
+ * The upload form has changed
+ *
+ * @event uploadValid
+ * @param {boolean} isValid The form is valid
+ */
+
+ /**
+ * The info form has changed
+ *
+ * @event infoValid
+ * @param {boolean} isValid The form is valid
+ */
+
+ /* Properties */
+
+ /**
+ * @property {OO.ui.FormLayout} uploadForm
+ * The form rendered in the first step to get the file object.
+ * Rendered in {@link #renderUploadForm renderUploadForm}.
+ */
+
+ /**
+ * @property {OO.ui.FormLayout} infoForm
+ * The form rendered in the second step to get metadata.
+ * Rendered in {@link #renderInfoForm renderInfoForm}
+ */
+
+ /**
+ * @property {OO.ui.FormLayout} insertForm
+ * The form rendered in the third step to show usage
+ * Rendered in {@link #renderInsertForm renderInsertForm}
+ */
+
+ /* Methods */
+
+ /**
+ * Initialize for a new upload
+ *
+ * @return {jQuery.Promise} Promise resolved when everything is initialized
+ */
+ mw.Upload.BookletLayout.prototype.initialize = function () {
+ var booklet = this;
+
+ this.clear();
+ this.upload = this.createUpload();
+
+ this.setPage( 'upload' );
+
+ if ( this.filekey ) {
+ this.setFilekey( this.filekey );
+ }
+
+ return this.upload.getApi().then(
+ function ( api ) {
+ // If the user can't upload anything, don't give them the option to.
+ return api.getUserInfo().then(
+ function ( userInfo ) {
+ if ( userInfo.rights.indexOf( 'upload' ) === -1 ) {
+ if ( mw.user.isAnon() ) {
+ booklet.getPage( 'upload' ).$element.msg( 'apierror-mustbeloggedin', mw.msg( 'action-upload' ) );
+ } else {
+ booklet.getPage( 'upload' ).$element.msg( 'apierror-permissiondenied', mw.msg( 'action-upload' ) );
+ }
+ }
+ return $.Deferred().resolve();
+ },
+ // Always resolve, never reject
+ function () { return $.Deferred().resolve(); }
+ );
+ },
+ function ( errorMsg ) {
+ booklet.getPage( 'upload' ).$element.msg( errorMsg );
+ return $.Deferred().resolve();
+ }
+ );
+ };
+
+ /**
+ * Create a new upload model
+ *
+ * @protected
+ * @return {mw.Upload} Upload model
+ */
+ mw.Upload.BookletLayout.prototype.createUpload = function () {
+ return new mw.Upload( {
+ parameters: {
+ errorformat: 'html',
+ errorlang: mw.config.get( 'wgUserLanguage' ),
+ errorsuselocal: 1,
+ formatversion: 2
+ }
+ } );
+ };
+
+ /* Uploading */
+
+ /**
+ * Uploads the file that was added in the upload form. Uses
+ * {@link #getFile getFile} to get the HTML5
+ * file object.
+ *
+ * @protected
+ * @fires fileUploadProgress
+ * @fires fileUploaded
+ * @return {jQuery.Promise}
+ */
+ mw.Upload.BookletLayout.prototype.uploadFile = function () {
+ var deferred = $.Deferred(),
+ startTime = mw.now(),
+ layout = this,
+ file = this.getFile();
+
+ this.setPage( 'info' );
+
+ if ( this.filekey ) {
+ if ( file === null ) {
+ // Someone gonna get-a hurt real bad
+ throw new Error( 'filekey not passed into file select widget, which is impossible. Quitting while we\'re behind.' );
+ }
+
+ // Stashed file already uploaded.
+ deferred.resolve();
+ this.uploadPromise = deferred;
+ this.emit( 'fileUploaded' );
+ return deferred;
+ }
+
+ this.setFilename( file.name );
+
+ this.upload.setFile( file );
+ // The original file name might contain invalid characters, so use our sanitized one
+ this.upload.setFilename( this.getFilename() );
+
+ this.uploadPromise = this.upload.uploadToStash();
+ this.uploadPromise.then( function () {
+ deferred.resolve();
+ layout.emit( 'fileUploaded' );
+ }, function () {
+ // These errors will be thrown while the user is on the info page.
+ layout.getErrorMessageForStateDetails().then( function ( errorMessage ) {
+ deferred.reject( errorMessage );
+ } );
+ }, function ( progress ) {
+ var elapsedTime = mw.now() - startTime,
+ estimatedTotalTime = ( 1 / progress ) * elapsedTime,
+ estimatedRemainingTime = moment.duration( estimatedTotalTime - elapsedTime );
+ layout.emit( 'fileUploadProgress', progress, estimatedRemainingTime );
+ } );
+
+ // If there is an error in uploading, come back to the upload page
+ deferred.fail( function () {
+ layout.setPage( 'upload' );
+ } );
+
+ return deferred;
+ };
+
+ /**
+ * Saves the stash finalizes upload. Uses
+ * {@link #getFilename getFilename}, and
+ * {@link #getText getText} to get details from
+ * the form.
+ *
+ * @protected
+ * @fires fileSaved
+ * @return {jQuery.Promise} Rejects the promise with an
+ * {@link OO.ui.Error error}, or resolves if the upload was successful.
+ */
+ mw.Upload.BookletLayout.prototype.saveFile = function () {
+ var layout = this,
+ deferred = $.Deferred();
+
+ this.upload.setFilename( this.getFilename() );
+ this.upload.setText( this.getText() );
+
+ this.uploadPromise.then( function () {
+ layout.upload.finishStashUpload().then( function () {
+ var name;
+
+ // Normalize page name and localise the 'File:' prefix
+ name = new mw.Title( 'File:' + layout.upload.getFilename() ).toString();
+ layout.filenameUsageWidget.setValue( '[[' + name + ']]' );
+ layout.setPage( 'insert' );
+
+ deferred.resolve();
+ layout.emit( 'fileSaved', layout.upload.getImageInfo() );
+ }, function () {
+ layout.getErrorMessageForStateDetails().then( function ( errorMessage ) {
+ deferred.reject( errorMessage );
+ } );
+ } );
+ } );
+
+ return deferred.promise();
+ };
+
+ /**
+ * Get an error message (as OO.ui.Error object) that should be displayed to the user for current
+ * state and state details.
+ *
+ * @protected
+ * @return {jQuery.Promise} A Promise that will be resolved with an OO.ui.Error.
+ */
+ mw.Upload.BookletLayout.prototype.getErrorMessageForStateDetails = function () {
+ var state = this.upload.getState(),
+ stateDetails = this.upload.getStateDetails(),
+ error = stateDetails.errors ? stateDetails.errors[ 0 ] : false,
+ warnings = stateDetails.upload && stateDetails.upload.warnings,
+ $ul = $( '<ul>' ),
+ errorText;
+
+ if ( state === mw.Upload.State.ERROR ) {
+ if ( !error ) {
+ if ( stateDetails.textStatus === 'timeout' ) {
+ // in case of $.ajax.fail(), there is no response json
+ errorText = mw.message( 'apierror-timeout' ).parse();
+ } else if ( stateDetails.xhr && stateDetails.xhr.status === 0 ) {
+ // failed to even connect to server
+ errorText = mw.message( 'apierror-offline' ).parse();
+ } else if ( stateDetails.textStatus ) {
+ errorText = stateDetails.textStatus;
+ } else {
+ errorText = mw.message( 'apierror-unknownerror', JSON.stringify( stateDetails ) ).parse();
+ }
+
+ // If there's an 'exception' key, this might be a timeout, or other connection problem
+ return $.Deferred().resolve( new OO.ui.Error(
+ $( '<p>' ).html( errorText ),
+ { recoverable: false }
+ ) );
+ }
+
+ return $.Deferred().resolve( new OO.ui.Error(
+ $( '<p>' ).html( error.html ),
+ { recoverable: false }
+ ) );
+ }
+
+ if ( state === mw.Upload.State.WARNING ) {
+ // We could get more than one of these errors, these are in order
+ // of importance. For example fixing the thumbnail like file name
+ // won't help the fact that the file already exists.
+ if ( warnings.exists !== undefined ) {
+ return $.Deferred().resolve( new OO.ui.Error(
+ $( '<p>' ).msg( 'fileexists', 'File:' + warnings.exists ),
+ { recoverable: false }
+ ) );
+ } else if ( warnings[ 'exists-normalized' ] !== undefined ) {
+ return $.Deferred().resolve( new OO.ui.Error(
+ $( '<p>' ).msg( 'fileexists', 'File:' + warnings[ 'exists-normalized' ] ),
+ { recoverable: false }
+ ) );
+ } else if ( warnings[ 'page-exists' ] !== undefined ) {
+ return $.Deferred().resolve( new OO.ui.Error(
+ $( '<p>' ).msg( 'filepageexists', 'File:' + warnings[ 'page-exists' ] ),
+ { recoverable: false }
+ ) );
+ } else if ( warnings.duplicate !== undefined ) {
+ $.each( warnings.duplicate, function ( i, filename ) {
+ var $a = $( '<a>' ).text( filename ),
+ href = mw.Title.makeTitle( mw.config.get( 'wgNamespaceIds' ).file, filename ).getUrl( {} );
+
+ $a.attr( { href: href, target: '_blank' } );
+ $ul.append( $( '<li>' ).append( $a ) );
+ } );
+
+ return $.Deferred().resolve( new OO.ui.Error(
+ $( '<p>' ).msg( 'file-exists-duplicate', warnings.duplicate.length ).append( $ul ),
+ { recoverable: false }
+ ) );
+ } else if ( warnings[ 'thumb-name' ] !== undefined ) {
+ return $.Deferred().resolve( new OO.ui.Error(
+ $( '<p>' ).msg( 'filename-thumb-name' ),
+ { recoverable: false }
+ ) );
+ } else if ( warnings[ 'bad-prefix' ] !== undefined ) {
+ return $.Deferred().resolve( new OO.ui.Error(
+ $( '<p>' ).msg( 'filename-bad-prefix', warnings[ 'bad-prefix' ] ),
+ { recoverable: false }
+ ) );
+ } else if ( warnings[ 'duplicate-archive' ] !== undefined ) {
+ return $.Deferred().resolve( new OO.ui.Error(
+ $( '<p>' ).msg( 'file-deleted-duplicate', 'File:' + warnings[ 'duplicate-archive' ] ),
+ { recoverable: false }
+ ) );
+ } else if ( warnings[ 'was-deleted' ] !== undefined ) {
+ return $.Deferred().resolve( new OO.ui.Error(
+ $( '<p>' ).msg( 'filewasdeleted', 'File:' + warnings[ 'was-deleted' ] ),
+ { recoverable: false }
+ ) );
+ } else if ( warnings.badfilename !== undefined ) {
+ // Change the name if the current name isn't acceptable
+ // TODO This might not really be the best place to do this
+ this.setFilename( warnings.badfilename );
+ return $.Deferred().resolve( new OO.ui.Error(
+ $( '<p>' ).msg( 'badfilename', warnings.badfilename )
+ ) );
+ } else {
+ return $.Deferred().resolve( new OO.ui.Error(
+ // Let's get all the help we can if we can't pin point the error
+ $( '<p>' ).msg( 'api-error-unknown-warning', JSON.stringify( stateDetails ) ),
+ { recoverable: false }
+ ) );
+ }
+ }
+ };
+
+ /* Form renderers */
+
+ /**
+ * Renders and returns the upload form and sets the
+ * {@link #uploadForm uploadForm} property.
+ *
+ * @protected
+ * @fires selectFile
+ * @return {OO.ui.FormLayout}
+ */
+ mw.Upload.BookletLayout.prototype.renderUploadForm = function () {
+ var fieldset,
+ layout = this;
+
+ this.selectFileWidget = this.getFileWidget();
+ fieldset = new OO.ui.FieldsetLayout();
+ fieldset.addItems( [ this.selectFileWidget ] );
+ this.uploadForm = new OO.ui.FormLayout( { items: [ fieldset ] } );
+
+ // Validation (if the SFW is for a stashed file, this never fires)
+ this.selectFileWidget.on( 'change', this.onUploadFormChange.bind( this ) );
+
+ this.selectFileWidget.on( 'change', function () {
+ layout.updateFilePreview();
+ } );
+
+ return this.uploadForm;
+ };
+
+ /**
+ * Gets the widget for displaying or inputting the file to upload.
+ *
+ * @return {OO.ui.SelectFileWidget|mw.widgets.StashedFileWidget}
+ */
+ mw.Upload.BookletLayout.prototype.getFileWidget = function () {
+ if ( this.filekey ) {
+ return new mw.widgets.StashedFileWidget( {
+ filekey: this.filekey
+ } );
+ }
+
+ return new OO.ui.SelectFileWidget( {
+ showDropTarget: true
+ } );
+ };
+
+ /**
+ * Updates the file preview on the info form when a file is added.
+ *
+ * @protected
+ */
+ mw.Upload.BookletLayout.prototype.updateFilePreview = function () {
+ this.selectFileWidget.loadAndGetImageUrl().done( function ( url ) {
+ this.filePreview.$element.find( 'p' ).remove();
+ this.filePreview.$element.css( 'background-image', 'url(' + url + ')' );
+ this.infoForm.$element.addClass( 'mw-upload-bookletLayout-hasThumbnail' );
+ }.bind( this ) ).fail( function () {
+ this.filePreview.$element.find( 'p' ).remove();
+ if ( this.selectFileWidget.getValue() ) {
+ this.filePreview.$element.append(
+ $( '<p>' ).text( this.selectFileWidget.getValue().name )
+ );
+ }
+ this.filePreview.$element.css( 'background-image', '' );
+ this.infoForm.$element.removeClass( 'mw-upload-bookletLayout-hasThumbnail' );
+ }.bind( this ) );
+ };
+
+ /**
+ * Handle change events to the upload form
+ *
+ * @protected
+ * @fires uploadValid
+ */
+ mw.Upload.BookletLayout.prototype.onUploadFormChange = function () {
+ this.emit( 'uploadValid', !!this.selectFileWidget.getValue() );
+ };
+
+ /**
+ * Renders and returns the information form for collecting
+ * metadata and sets the {@link #infoForm infoForm}
+ * property.
+ *
+ * @protected
+ * @return {OO.ui.FormLayout}
+ */
+ mw.Upload.BookletLayout.prototype.renderInfoForm = function () {
+ var fieldset;
+
+ this.filePreview = new OO.ui.Widget( {
+ classes: [ 'mw-upload-bookletLayout-filePreview' ]
+ } );
+ this.progressBarWidget = new OO.ui.ProgressBarWidget( {
+ progress: 0
+ } );
+ this.filePreview.$element.append( this.progressBarWidget.$element );
+
+ this.filenameWidget = new OO.ui.TextInputWidget( {
+ indicator: 'required',
+ required: true,
+ validate: /.+/
+ } );
+ this.descriptionWidget = new OO.ui.MultilineTextInputWidget( {
+ indicator: 'required',
+ required: true,
+ validate: /\S+/,
+ autosize: true
+ } );
+
+ fieldset = new OO.ui.FieldsetLayout( {
+ label: mw.msg( 'upload-form-label-infoform-title' )
+ } );
+ fieldset.addItems( [
+ new OO.ui.FieldLayout( this.filenameWidget, {
+ label: mw.msg( 'upload-form-label-infoform-name' ),
+ align: 'top',
+ help: mw.msg( 'upload-form-label-infoform-name-tooltip' )
+ } ),
+ new OO.ui.FieldLayout( this.descriptionWidget, {
+ label: mw.msg( 'upload-form-label-infoform-description' ),
+ align: 'top',
+ help: mw.msg( 'upload-form-label-infoform-description-tooltip' )
+ } )
+ ] );
+ this.infoForm = new OO.ui.FormLayout( {
+ classes: [ 'mw-upload-bookletLayout-infoForm' ],
+ items: [ this.filePreview, fieldset ]
+ } );
+
+ this.on( 'fileUploadProgress', function ( progress ) {
+ this.progressBarWidget.setProgress( progress * 100 );
+ }.bind( this ) );
+
+ this.filenameWidget.on( 'change', this.onInfoFormChange.bind( this ) );
+ this.descriptionWidget.on( 'change', this.onInfoFormChange.bind( this ) );
+
+ return this.infoForm;
+ };
+
+ /**
+ * Handle change events to the info form
+ *
+ * @protected
+ * @fires infoValid
+ */
+ mw.Upload.BookletLayout.prototype.onInfoFormChange = function () {
+ var layout = this;
+ $.when(
+ this.filenameWidget.getValidity(),
+ this.descriptionWidget.getValidity()
+ ).done( function () {
+ layout.emit( 'infoValid', true );
+ } ).fail( function () {
+ layout.emit( 'infoValid', false );
+ } );
+ };
+
+ /**
+ * Renders and returns the insert form to show file usage and
+ * sets the {@link #insertForm insertForm} property.
+ *
+ * @protected
+ * @return {OO.ui.FormLayout}
+ */
+ mw.Upload.BookletLayout.prototype.renderInsertForm = function () {
+ var fieldset;
+
+ this.filenameUsageWidget = new OO.ui.TextInputWidget();
+ fieldset = new OO.ui.FieldsetLayout( {
+ label: mw.msg( 'upload-form-label-usage-title' )
+ } );
+ fieldset.addItems( [
+ new OO.ui.FieldLayout( this.filenameUsageWidget, {
+ label: mw.msg( 'upload-form-label-usage-filename' ),
+ align: 'top'
+ } )
+ ] );
+ this.insertForm = new OO.ui.FormLayout( { items: [ fieldset ] } );
+
+ return this.insertForm;
+ };
+
+ /* Getters */
+
+ /**
+ * Gets the file object from the
+ * {@link #uploadForm upload form}.
+ *
+ * @protected
+ * @return {File|null}
+ */
+ mw.Upload.BookletLayout.prototype.getFile = function () {
+ return this.selectFileWidget.getValue();
+ };
+
+ /**
+ * Gets the file name from the
+ * {@link #infoForm information form}.
+ *
+ * @protected
+ * @return {string}
+ */
+ mw.Upload.BookletLayout.prototype.getFilename = function () {
+ var filename = this.filenameWidget.getValue();
+ if ( this.filenameExtension ) {
+ filename += '.' + this.filenameExtension;
+ }
+ return filename;
+ };
+
+ /**
+ * Prefills the {@link #infoForm information form} with the given filename.
+ *
+ * @protected
+ * @param {string} filename
+ */
+ mw.Upload.BookletLayout.prototype.setFilename = function ( filename ) {
+ var title = mw.Title.newFromFileName( filename );
+
+ if ( title ) {
+ this.filenameWidget.setValue( title.getNameText() );
+ this.filenameExtension = mw.Title.normalizeExtension( title.getExtension() );
+ } else {
+ // Seems to happen for files with no extension, which should fail some checks anyway...
+ this.filenameWidget.setValue( filename );
+ this.filenameExtension = null;
+ }
+ };
+
+ /**
+ * Gets the page text from the
+ * {@link #infoForm information form}.
+ *
+ * @protected
+ * @return {string}
+ */
+ mw.Upload.BookletLayout.prototype.getText = function () {
+ return this.descriptionWidget.getValue();
+ };
+
+ /* Setters */
+
+ /**
+ * Sets the file object
+ *
+ * @protected
+ * @param {File|null} file File to select
+ */
+ mw.Upload.BookletLayout.prototype.setFile = function ( file ) {
+ this.selectFileWidget.setValue( file );
+ };
+
+ /**
+ * Sets the filekey of a file already stashed on the server
+ * as the target of this upload operation.
+ *
+ * @protected
+ * @param {string} filekey
+ */
+ mw.Upload.BookletLayout.prototype.setFilekey = function ( filekey ) {
+ this.upload.setFilekey( this.filekey );
+ this.selectFileWidget.setValue( filekey );
+
+ this.onUploadFormChange();
+ };
+
+ /**
+ * Clear the values of all fields
+ *
+ * @protected
+ */
+ mw.Upload.BookletLayout.prototype.clear = function () {
+ this.selectFileWidget.setValue( null );
+ this.progressBarWidget.setProgress( 0 );
+ this.filenameWidget.setValue( null ).setValidityFlag( true );
+ this.descriptionWidget.setValue( null ).setValidityFlag( true );
+ this.filenameUsageWidget.setValue( null );
+ };
+
+}( jQuery, mediaWiki, moment ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.Upload.Dialog.js b/www/wiki/resources/src/mediawiki/mediawiki.Upload.Dialog.js
new file mode 100644
index 00000000..00c04bc8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.Upload.Dialog.js
@@ -0,0 +1,230 @@
+( function ( $, mw ) {
+
+ /**
+ * mw.Upload.Dialog controls a {@link mw.Upload.BookletLayout BookletLayout}.
+ *
+ * ## Usage
+ *
+ * To use, setup a {@link OO.ui.WindowManager window manager} like for normal
+ * dialogs:
+ *
+ * var uploadDialog = new mw.Upload.Dialog();
+ * var windowManager = new OO.ui.WindowManager();
+ * $( 'body' ).append( windowManager.$element );
+ * windowManager.addWindows( [ uploadDialog ] );
+ * windowManager.openWindow( uploadDialog );
+ *
+ * The dialog's closing promise can be used to get details of the upload.
+ *
+ * If you want to use a different OO.ui.BookletLayout, for example the
+ * mw.ForeignStructuredUpload.BookletLayout, like in the case of of the upload
+ * interface in VisualEditor, you can pass it in the {@link #cfg-bookletClass}:
+ *
+ * var uploadDialog = new mw.Upload.Dialog( {
+ * bookletClass: mw.ForeignStructuredUpload.BookletLayout
+ * } );
+ *
+ *
+ * @class mw.Upload.Dialog
+ * @uses mw.Upload
+ * @uses mw.Upload.BookletLayout
+ * @extends OO.ui.ProcessDialog
+ *
+ * @constructor
+ * @param {Object} [config] Configuration options
+ * @cfg {Function} [bookletClass=mw.Upload.BookletLayout] Booklet class to be
+ * used for the steps
+ * @cfg {Object} [booklet] Booklet constructor configuration
+ */
+ mw.Upload.Dialog = function ( config ) {
+ // Config initialization
+ config = $.extend( {
+ bookletClass: mw.Upload.BookletLayout
+ }, config );
+
+ // Parent constructor
+ mw.Upload.Dialog.parent.call( this, config );
+
+ // Initialize
+ this.bookletClass = config.bookletClass;
+ this.bookletConfig = config.booklet;
+ };
+
+ /* Setup */
+
+ OO.inheritClass( mw.Upload.Dialog, OO.ui.ProcessDialog );
+
+ /* Static Properties */
+
+ /**
+ * @inheritdoc
+ * @property name
+ */
+ mw.Upload.Dialog.static.name = 'mwUploadDialog';
+
+ /**
+ * @inheritdoc
+ * @property title
+ */
+ mw.Upload.Dialog.static.title = mw.msg( 'upload-dialog-title' );
+
+ /**
+ * @inheritdoc
+ * @property actions
+ */
+ mw.Upload.Dialog.static.actions = [
+ {
+ flags: 'safe',
+ action: 'cancel',
+ label: mw.msg( 'upload-dialog-button-cancel' ),
+ modes: [ 'upload', 'insert' ]
+ },
+ {
+ flags: 'safe',
+ action: 'cancelupload',
+ label: mw.msg( 'upload-dialog-button-back' ),
+ modes: [ 'info' ]
+ },
+ {
+ flags: [ 'primary', 'progressive' ],
+ label: mw.msg( 'upload-dialog-button-done' ),
+ action: 'insert',
+ modes: 'insert'
+ },
+ {
+ flags: [ 'primary', 'progressive' ],
+ label: mw.msg( 'upload-dialog-button-save' ),
+ action: 'save',
+ modes: 'info'
+ },
+ {
+ flags: [ 'primary', 'progressive' ],
+ label: mw.msg( 'upload-dialog-button-upload' ),
+ action: 'upload',
+ modes: 'upload'
+ }
+ ];
+
+ /* Methods */
+
+ /**
+ * @inheritdoc
+ */
+ mw.Upload.Dialog.prototype.initialize = function () {
+ // Parent method
+ mw.Upload.Dialog.parent.prototype.initialize.call( this );
+
+ this.uploadBooklet = this.createUploadBooklet();
+ this.uploadBooklet.connect( this, {
+ set: 'onUploadBookletSet',
+ uploadValid: 'onUploadValid',
+ infoValid: 'onInfoValid'
+ } );
+
+ this.$body.append( this.uploadBooklet.$element );
+ };
+
+ /**
+ * Create an upload booklet
+ *
+ * @protected
+ * @return {mw.Upload.BookletLayout} An upload booklet
+ */
+ mw.Upload.Dialog.prototype.createUploadBooklet = function () {
+ // eslint-disable-next-line new-cap
+ return new this.bookletClass( $.extend( {
+ $overlay: this.$overlay
+ }, this.bookletConfig ) );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.Upload.Dialog.prototype.getBodyHeight = function () {
+ return 600;
+ };
+
+ /**
+ * Handle panelNameSet events from the upload booklet
+ *
+ * @protected
+ * @param {OO.ui.PageLayout} page Current page
+ */
+ mw.Upload.Dialog.prototype.onUploadBookletSet = function ( page ) {
+ this.actions.setMode( page.getName() );
+ this.actions.setAbilities( { upload: false, save: false } );
+ };
+
+ /**
+ * Handle uploadValid events
+ *
+ * {@link OO.ui.ActionSet#setAbilities Sets abilities}
+ * for the dialog accordingly.
+ *
+ * @protected
+ * @param {boolean} isValid The panel is complete and valid
+ */
+ mw.Upload.Dialog.prototype.onUploadValid = function ( isValid ) {
+ this.actions.setAbilities( { upload: isValid } );
+ };
+
+ /**
+ * Handle infoValid events
+ *
+ * {@link OO.ui.ActionSet#setAbilities Sets abilities}
+ * for the dialog accordingly.
+ *
+ * @protected
+ * @param {boolean} isValid The panel is complete and valid
+ */
+ mw.Upload.Dialog.prototype.onInfoValid = function ( isValid ) {
+ this.actions.setAbilities( { save: isValid } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.Upload.Dialog.prototype.getSetupProcess = function ( data ) {
+ return mw.Upload.Dialog.parent.prototype.getSetupProcess.call( this, data )
+ .next( function () {
+ return this.uploadBooklet.initialize();
+ }, this );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.Upload.Dialog.prototype.getActionProcess = function ( action ) {
+ var dialog = this;
+
+ if ( action === 'upload' ) {
+ return new OO.ui.Process( this.uploadBooklet.uploadFile() );
+ }
+ if ( action === 'save' ) {
+ return new OO.ui.Process( this.uploadBooklet.saveFile() );
+ }
+ if ( action === 'insert' ) {
+ return new OO.ui.Process( function () {
+ dialog.close( dialog.upload );
+ } );
+ }
+ if ( action === 'cancel' ) {
+ return new OO.ui.Process( this.close().closed );
+ }
+ if ( action === 'cancelupload' ) {
+ return new OO.ui.Process( this.uploadBooklet.initialize() );
+ }
+
+ return mw.Upload.Dialog.parent.prototype.getActionProcess.call( this, action );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.Upload.Dialog.prototype.getTeardownProcess = function ( data ) {
+ return mw.Upload.Dialog.parent.prototype.getTeardownProcess.call( this, data )
+ .next( function () {
+ this.uploadBooklet.clear();
+ }, this );
+ };
+}( jQuery, mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.Upload.js b/www/wiki/resources/src/mediawiki/mediawiki.Upload.js
new file mode 100644
index 00000000..7e6cfb68
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.Upload.js
@@ -0,0 +1,393 @@
+( function ( mw, $ ) {
+ var UP;
+
+ /**
+ * Used to represent an upload in progress on the frontend.
+ * Most of the functionality is implemented in mw.Api.plugin.upload,
+ * but this model class will tie it together as well as let you perform
+ * actions in a logical way.
+ *
+ * A simple example:
+ *
+ * var file = new OO.ui.SelectFileWidget(),
+ * button = new OO.ui.ButtonWidget( { label: 'Save' } ),
+ * upload = new mw.Upload;
+ *
+ * button.on( 'click', function () {
+ * upload.setFile( file.getValue() );
+ * upload.setFilename( file.getValue().name );
+ * upload.upload();
+ * } );
+ *
+ * $( 'body' ).append( file.$element, button.$element );
+ *
+ * You can also choose to {@link #uploadToStash stash the upload} and
+ * {@link #finishStashUpload finalize} it later:
+ *
+ * var file, // Some file object
+ * upload = new mw.Upload,
+ * stashPromise = $.Deferred();
+ *
+ * upload.setFile( file );
+ * upload.uploadToStash().then( function () {
+ * stashPromise.resolve();
+ * } );
+ *
+ * stashPromise.then( function () {
+ * upload.setFilename( 'foo' );
+ * upload.setText( 'bar' );
+ * upload.finishStashUpload().then( function () {
+ * console.log( 'Done!' );
+ * } );
+ * } );
+ *
+ * @class mw.Upload
+ *
+ * @constructor
+ * @param {Object|mw.Api} [apiconfig] A mw.Api object (or subclass), or configuration
+ * to pass to the constructor of mw.Api.
+ */
+ function Upload( apiconfig ) {
+ this.api = ( apiconfig instanceof mw.Api ) ? apiconfig : new mw.Api( apiconfig );
+
+ this.watchlist = false;
+ this.text = '';
+ this.comment = '';
+ this.filename = null;
+ this.file = null;
+ this.setState( Upload.State.NEW );
+
+ this.imageinfo = undefined;
+ }
+
+ UP = Upload.prototype;
+
+ /**
+ * Get the mw.Api instance used by this Upload object.
+ *
+ * @return {jQuery.Promise}
+ * @return {Function} return.done
+ * @return {mw.Api} return.done.api
+ */
+ UP.getApi = function () {
+ return $.Deferred().resolve( this.api ).promise();
+ };
+
+ /**
+ * Set the text of the file page, to be created on file upload.
+ *
+ * @param {string} text
+ */
+ UP.setText = function ( text ) {
+ this.text = text;
+ };
+
+ /**
+ * Set the filename, to be finalized on upload.
+ *
+ * @param {string} filename
+ */
+ UP.setFilename = function ( filename ) {
+ this.filename = filename;
+ };
+
+ /**
+ * Set the stashed file to finish uploading.
+ *
+ * @param {string} filekey
+ */
+ UP.setFilekey = function ( filekey ) {
+ var upload = this;
+
+ this.setState( Upload.State.STASHED );
+ this.stashPromise = $.Deferred().resolve( function ( data ) {
+ return upload.api.uploadFromStash( filekey, data );
+ } );
+ };
+
+ /**
+ * Sets the filename based on the filename as it was on the upload.
+ */
+ UP.setFilenameFromFile = function () {
+ var file = this.getFile();
+ if ( !file ) {
+ return;
+ }
+ if ( file.nodeType && file.nodeType === Node.ELEMENT_NODE ) {
+ // File input element, use getBasename to cut out the path
+ this.setFilename( this.getBasename( file.value ) );
+ } else if ( file.name ) {
+ // HTML5 FileAPI File object, but use getBasename to be safe
+ this.setFilename( this.getBasename( file.name ) );
+ } else {
+ // If we ever implement uploading files from clipboard, they might not have a name
+ this.setFilename( '?' );
+ }
+ };
+
+ /**
+ * Set the file to be uploaded.
+ *
+ * @param {HTMLInputElement|File|Blob} file
+ */
+ UP.setFile = function ( file ) {
+ this.file = file;
+ };
+
+ /**
+ * Set whether the file should be watchlisted after upload.
+ *
+ * @param {boolean} watchlist
+ */
+ UP.setWatchlist = function ( watchlist ) {
+ this.watchlist = watchlist;
+ };
+
+ /**
+ * Set the edit comment for the upload.
+ *
+ * @param {string} comment
+ */
+ UP.setComment = function ( comment ) {
+ this.comment = comment;
+ };
+
+ /**
+ * Get the text of the file page, to be created on file upload.
+ *
+ * @return {string}
+ */
+ UP.getText = function () {
+ return this.text;
+ };
+
+ /**
+ * Get the filename, to be finalized on upload.
+ *
+ * @return {string}
+ */
+ UP.getFilename = function () {
+ return this.filename;
+ };
+
+ /**
+ * Get the file being uploaded.
+ *
+ * @return {HTMLInputElement|File|Blob}
+ */
+ UP.getFile = function () {
+ return this.file;
+ };
+
+ /**
+ * Get the boolean for whether the file will be watchlisted after upload.
+ *
+ * @return {boolean}
+ */
+ UP.getWatchlist = function () {
+ return this.watchlist;
+ };
+
+ /**
+ * Get the current value of the edit comment for the upload.
+ *
+ * @return {string}
+ */
+ UP.getComment = function () {
+ return this.comment;
+ };
+
+ /**
+ * Gets the base filename from a path name.
+ *
+ * @param {string} path
+ * @return {string}
+ */
+ UP.getBasename = function ( path ) {
+ if ( path === undefined || path === null ) {
+ return '';
+ }
+
+ // Find the index of the last path separator in the
+ // path, and add 1. Then, take the entire string after that.
+ return path.slice(
+ Math.max(
+ path.lastIndexOf( '/' ),
+ path.lastIndexOf( '\\' )
+ ) + 1
+ );
+ };
+
+ /**
+ * Sets the state and state details (if any) of the upload.
+ *
+ * @param {mw.Upload.State} state
+ * @param {Object} stateDetails
+ */
+ UP.setState = function ( state, stateDetails ) {
+ this.state = state;
+ this.stateDetails = stateDetails;
+ };
+
+ /**
+ * Gets the state of the upload.
+ *
+ * @return {mw.Upload.State}
+ */
+ UP.getState = function () {
+ return this.state;
+ };
+
+ /**
+ * Gets details of the current state.
+ *
+ * @return {string}
+ */
+ UP.getStateDetails = function () {
+ return this.stateDetails;
+ };
+
+ /**
+ * Get the imageinfo object for the finished upload.
+ * Only available once the upload is finished! Don't try to get it
+ * beforehand.
+ *
+ * @return {Object|undefined}
+ */
+ UP.getImageInfo = function () {
+ return this.imageinfo;
+ };
+
+ /**
+ * Upload the file directly.
+ *
+ * @return {jQuery.Promise}
+ */
+ UP.upload = function () {
+ var upload = this;
+
+ if ( !this.getFile() ) {
+ return $.Deferred().reject( 'No file to upload. Call setFile to add one.' );
+ }
+
+ if ( !this.getFilename() ) {
+ return $.Deferred().reject( 'No filename set. Call setFilename to add one.' );
+ }
+
+ this.setState( Upload.State.UPLOADING );
+
+ return this.api.chunkedUpload( this.getFile(), {
+ watchlist: ( this.getWatchlist() ) ? 1 : undefined,
+ comment: this.getComment(),
+ filename: this.getFilename(),
+ text: this.getText()
+ } ).then( function ( result ) {
+ upload.setState( Upload.State.UPLOADED );
+ upload.imageinfo = result.upload.imageinfo;
+ return result;
+ }, function ( errorCode, result ) {
+ if ( result && result.upload && result.upload.warnings ) {
+ upload.setState( Upload.State.WARNING, result );
+ } else {
+ upload.setState( Upload.State.ERROR, result );
+ }
+ return $.Deferred().reject( errorCode, result );
+ } );
+ };
+
+ /**
+ * Upload the file to the stash to be completed later.
+ *
+ * @return {jQuery.Promise}
+ */
+ UP.uploadToStash = function () {
+ var upload = this;
+
+ if ( !this.getFile() ) {
+ return $.Deferred().reject( 'No file to upload. Call setFile to add one.' );
+ }
+
+ if ( !this.getFilename() ) {
+ this.setFilenameFromFile();
+ }
+
+ this.setState( Upload.State.UPLOADING );
+
+ this.stashPromise = this.api.chunkedUploadToStash( this.getFile(), {
+ filename: this.getFilename()
+ } ).then( function ( finishStash ) {
+ upload.setState( Upload.State.STASHED );
+ return finishStash;
+ }, function ( errorCode, result ) {
+ if ( result && result.upload && result.upload.warnings ) {
+ upload.setState( Upload.State.WARNING, result );
+ } else {
+ upload.setState( Upload.State.ERROR, result );
+ }
+ return $.Deferred().reject( errorCode, result );
+ } );
+
+ return this.stashPromise;
+ };
+
+ /**
+ * Finish a stash upload.
+ *
+ * @return {jQuery.Promise}
+ */
+ UP.finishStashUpload = function () {
+ var upload = this;
+
+ if ( !this.stashPromise ) {
+ return $.Deferred().reject( 'This upload has not been stashed, please upload it to the stash first.' );
+ }
+
+ return this.stashPromise.then( function ( finishStash ) {
+ upload.setState( Upload.State.UPLOADING );
+
+ return finishStash( {
+ watchlist: ( upload.getWatchlist() ) ? 1 : undefined,
+ comment: upload.getComment(),
+ filename: upload.getFilename(),
+ text: upload.getText()
+ } ).then( function ( result ) {
+ upload.setState( Upload.State.UPLOADED );
+ upload.imageinfo = result.upload.imageinfo;
+ return result;
+ }, function ( errorCode, result ) {
+ if ( result && result.upload && result.upload.warnings ) {
+ upload.setState( Upload.State.WARNING, result );
+ } else {
+ upload.setState( Upload.State.ERROR, result );
+ }
+ return $.Deferred().reject( errorCode, result );
+ } );
+ } );
+ };
+
+ /**
+ * @enum mw.Upload.State
+ * State of uploads represented in simple terms.
+ */
+ Upload.State = {
+ /** Upload not yet started */
+ NEW: 0,
+
+ /** Upload finished, but there was a warning */
+ WARNING: 1,
+
+ /** Upload finished, but there was an error */
+ ERROR: 2,
+
+ /** Upload in progress */
+ UPLOADING: 3,
+
+ /** Upload finished, but not published, call #finishStashUpload */
+ STASHED: 4,
+
+ /** Upload finished and published */
+ UPLOADED: 5
+ };
+
+ mw.Upload = Upload;
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.Uri.js b/www/wiki/resources/src/mediawiki/mediawiki.Uri.js
new file mode 100644
index 00000000..59261cdc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.Uri.js
@@ -0,0 +1,433 @@
+/**
+ * Library for simple URI parsing and manipulation.
+ *
+ * Intended to be minimal, but featureful; do not expect full RFC 3986 compliance. The use cases we
+ * have in mind are constructing 'next page' or 'previous page' URLs, detecting whether we need to
+ * use cross-domain proxies for an API, constructing simple URL-based API calls, etc. Parsing here
+ * is regex-based, so may not work on all URIs, but is good enough for most.
+ *
+ * You can modify the properties directly, then use the #toString method to extract the full URI
+ * string again. Example:
+ *
+ * var uri = new mw.Uri( 'http://example.com/mysite/mypage.php?quux=2' );
+ *
+ * if ( uri.host == 'example.com' ) {
+ * uri.host = 'foo.example.com';
+ * uri.extend( { bar: 1 } );
+ *
+ * $( 'a#id1' ).attr( 'href', uri );
+ * // anchor with id 'id1' now links to http://foo.example.com/mysite/mypage.php?bar=1&quux=2
+ *
+ * $( 'a#id2' ).attr( 'href', uri.clone().extend( { bar: 3, pif: 'paf' } ) );
+ * // anchor with id 'id2' now links to http://foo.example.com/mysite/mypage.php?bar=3&quux=2&pif=paf
+ * }
+ *
+ * Given a URI like
+ * `http://usr:pwd@www.example.com:81/dir/dir.2/index.htm?q1=0&&test1&test2=&test3=value+%28escaped%29&r=1&r=2#top`
+ * the returned object will have the following properties:
+ *
+ * protocol 'http'
+ * user 'usr'
+ * password 'pwd'
+ * host 'www.example.com'
+ * port '81'
+ * path '/dir/dir.2/index.htm'
+ * query {
+ * q1: '0',
+ * test1: null,
+ * test2: '',
+ * test3: 'value (escaped)'
+ * r: ['1', '2']
+ * }
+ * fragment 'top'
+ *
+ * (N.b., 'password' is technically not allowed for HTTP URIs, but it is possible with other kinds
+ * of URIs.)
+ *
+ * Parsing based on parseUri 1.2.2 (c) Steven Levithan <http://stevenlevithan.com>, MIT License.
+ * <http://stevenlevithan.com/demo/parseuri/js/>
+ *
+ * @class mw.Uri
+ */
+
+/* eslint-disable no-use-before-define */
+
+( function ( mw, $ ) {
+ var parser, properties;
+
+ /**
+ * Function that's useful when constructing the URI string -- we frequently encounter the pattern
+ * of having to add something to the URI as we go, but only if it's present, and to include a
+ * character before or after if so.
+ *
+ * @private
+ * @static
+ * @param {string|undefined} pre To prepend
+ * @param {string} val To include
+ * @param {string} post To append
+ * @param {boolean} raw If true, val will not be encoded
+ * @return {string} Result
+ */
+ function cat( pre, val, post, raw ) {
+ if ( val === undefined || val === null || val === '' ) {
+ return '';
+ }
+
+ return pre + ( raw ? val : mw.Uri.encode( val ) ) + post;
+ }
+
+ /**
+ * Regular expressions to parse many common URIs.
+ *
+ * As they are gnarly, they have been moved to separate files to allow us to format them in the
+ * 'extended' regular expression format (which JavaScript normally doesn't support). The subset of
+ * features handled is minimal, but just the free whitespace gives us a lot.
+ *
+ * @private
+ * @static
+ * @property {Object} parser
+ */
+ parser = {
+ strict: mw.template.get( 'mediawiki.Uri', 'strict.regexp' ).render(),
+ loose: mw.template.get( 'mediawiki.Uri', 'loose.regexp' ).render()
+ };
+
+ /**
+ * The order here matches the order of captured matches in the `parser` property regexes.
+ *
+ * @private
+ * @static
+ * @property {Array} properties
+ */
+ properties = [
+ 'protocol',
+ 'user',
+ 'password',
+ 'host',
+ 'port',
+ 'path',
+ 'query',
+ 'fragment'
+ ];
+
+ /**
+ * @property {string} protocol For example `http` (always present)
+ */
+ /**
+ * @property {string|undefined} user For example `usr`
+ */
+ /**
+ * @property {string|undefined} password For example `pwd`
+ */
+ /**
+ * @property {string} host For example `www.example.com` (always present)
+ */
+ /**
+ * @property {string|undefined} port For example `81`
+ */
+ /**
+ * @property {string} path For example `/dir/dir.2/index.htm` (always present)
+ */
+ /**
+ * @property {Object} query For example `{ a: '0', b: '', c: 'value' }` (always present)
+ */
+ /**
+ * @property {string|undefined} fragment For example `top`
+ */
+
+ /**
+ * A factory method to create a Uri class with a default location to resolve relative URLs
+ * against (including protocol-relative URLs).
+ *
+ * @method
+ * @param {string|Function} documentLocation A full url, or function returning one.
+ * If passed a function, the return value may change over time and this will be honoured. (T74334)
+ * @member mw
+ * @return {Function} Uri class
+ */
+ mw.UriRelative = function ( documentLocation ) {
+ var getDefaultUri = ( function () {
+ // Cache
+ var href, uri;
+
+ return function () {
+ var hrefCur = typeof documentLocation === 'string' ? documentLocation : documentLocation();
+ if ( href === hrefCur ) {
+ return uri;
+ }
+ href = hrefCur;
+ uri = new Uri( href );
+ return uri;
+ };
+ }() );
+
+ /**
+ * Construct a new URI object. Throws error if arguments are illegal/impossible, or
+ * otherwise don't parse.
+ *
+ * @class mw.Uri
+ * @constructor
+ * @param {Object|string} [uri] URI string, or an Object with appropriate properties (especially
+ * another URI object to clone). Object must have non-blank `protocol`, `host`, and `path`
+ * properties. If omitted (or set to `undefined`, `null` or empty string), then an object
+ * will be created for the default `uri` of this constructor (`location.href` for mw.Uri,
+ * other values for other instances -- see mw.UriRelative for details).
+ * @param {Object|boolean} [options] Object with options, or (backwards compatibility) a boolean
+ * for strictMode
+ * @param {boolean} [options.strictMode=false] Trigger strict mode parsing of the url.
+ * @param {boolean} [options.overrideKeys=false] Whether to let duplicate query parameters
+ * override each other (`true`) or automagically convert them to an array (`false`).
+ */
+ function Uri( uri, options ) {
+ var prop, hrefCur,
+ hasOptions = ( options !== undefined ),
+ defaultUri = getDefaultUri();
+
+ options = typeof options === 'object' ? options : { strictMode: !!options };
+ options = $.extend( {
+ strictMode: false,
+ overrideKeys: false
+ }, options );
+
+ if ( uri !== undefined && uri !== null && uri !== '' ) {
+ if ( typeof uri === 'string' ) {
+ this.parse( uri, options );
+ } else if ( typeof uri === 'object' ) {
+ // Copy data over from existing URI object
+ for ( prop in uri ) {
+ // Only copy direct properties, not inherited ones
+ if ( uri.hasOwnProperty( prop ) ) {
+ // Deep copy object properties
+ if ( Array.isArray( uri[ prop ] ) || $.isPlainObject( uri[ prop ] ) ) {
+ this[ prop ] = $.extend( true, {}, uri[ prop ] );
+ } else {
+ this[ prop ] = uri[ prop ];
+ }
+ }
+ }
+ if ( !this.query ) {
+ this.query = {};
+ }
+ }
+ } else if ( hasOptions ) {
+ // We didn't get a URI in the constructor, but we got options.
+ hrefCur = typeof documentLocation === 'string' ? documentLocation : documentLocation();
+ this.parse( hrefCur, options );
+ } else {
+ // We didn't get a URI or options in the constructor, use the default instance.
+ return defaultUri.clone();
+ }
+
+ // protocol-relative URLs
+ if ( !this.protocol ) {
+ this.protocol = defaultUri.protocol;
+ }
+ // No host given:
+ if ( !this.host ) {
+ this.host = defaultUri.host;
+ // port ?
+ if ( !this.port ) {
+ this.port = defaultUri.port;
+ }
+ }
+ if ( this.path && this.path[ 0 ] !== '/' ) {
+ // A real relative URL, relative to defaultUri.path. We can't really handle that since we cannot
+ // figure out whether the last path component of defaultUri.path is a directory or a file.
+ throw new Error( 'Bad constructor arguments' );
+ }
+ if ( !( this.protocol && this.host && this.path ) ) {
+ throw new Error( 'Bad constructor arguments' );
+ }
+ }
+
+ /**
+ * Encode a value for inclusion in a url.
+ *
+ * Standard encodeURIComponent, with extra stuff to make all browsers work similarly and more
+ * compliant with RFC 3986. Similar to rawurlencode from PHP and our JS library
+ * mw.util.rawurlencode, except this also replaces spaces with `+`.
+ *
+ * @static
+ * @param {string} s String to encode
+ * @return {string} Encoded string for URI
+ */
+ Uri.encode = function ( s ) {
+ return encodeURIComponent( s )
+ .replace( /!/g, '%21' ).replace( /'/g, '%27' ).replace( /\(/g, '%28' )
+ .replace( /\)/g, '%29' ).replace( /\*/g, '%2A' )
+ .replace( /%20/g, '+' );
+ };
+
+ /**
+ * Decode a url encoded value.
+ *
+ * Reversed #encode. Standard decodeURIComponent, with addition of replacing
+ * `+` with a space.
+ *
+ * @static
+ * @param {string} s String to decode
+ * @return {string} Decoded string
+ */
+ Uri.decode = function ( s ) {
+ return decodeURIComponent( s.replace( /\+/g, '%20' ) );
+ };
+
+ Uri.prototype = {
+
+ /**
+ * Parse a string and set our properties accordingly.
+ *
+ * @private
+ * @param {string} str URI, see constructor.
+ * @param {Object} options See constructor.
+ */
+ parse: function ( str, options ) {
+ var q, matches,
+ uri = this,
+ hasOwn = Object.prototype.hasOwnProperty;
+
+ // Apply parser regex and set all properties based on the result
+ matches = parser[ options.strictMode ? 'strict' : 'loose' ].exec( str );
+ $.each( properties, function ( i, property ) {
+ uri[ property ] = matches[ i + 1 ];
+ } );
+
+ // uri.query starts out as the query string; we will parse it into key-val pairs then make
+ // that object the "query" property.
+ // we overwrite query in uri way to make cloning easier, it can use the same list of properties.
+ q = {};
+ // using replace to iterate over a string
+ if ( uri.query ) {
+ uri.query.replace( /(?:^|&)([^&=]*)(?:(=)([^&]*))?/g, function ( $0, $1, $2, $3 ) {
+ var k, v;
+ if ( $1 ) {
+ k = Uri.decode( $1 );
+ v = ( $2 === '' || $2 === undefined ) ? null : Uri.decode( $3 );
+
+ // If overrideKeys, always (re)set top level value.
+ // If not overrideKeys but this key wasn't set before, then we set it as well.
+ if ( options.overrideKeys || !hasOwn.call( q, k ) ) {
+ q[ k ] = v;
+
+ // Use arrays if overrideKeys is false and key was already seen before
+ } else {
+ // Once before, still a string, turn into an array
+ if ( typeof q[ k ] === 'string' ) {
+ q[ k ] = [ q[ k ] ];
+ }
+ // Add to the array
+ if ( Array.isArray( q[ k ] ) ) {
+ q[ k ].push( v );
+ }
+ }
+ }
+ } );
+ }
+ uri.query = q;
+ },
+
+ /**
+ * Get user and password section of a URI.
+ *
+ * @return {string}
+ */
+ getUserInfo: function () {
+ return cat( '', this.user, cat( ':', this.password, '' ) );
+ },
+
+ /**
+ * Get host and port section of a URI.
+ *
+ * @return {string}
+ */
+ getHostPort: function () {
+ return this.host + cat( ':', this.port, '' );
+ },
+
+ /**
+ * Get the userInfo, host and port section of the URI.
+ *
+ * In most real-world URLs this is simply the hostname, but the definition of 'authority' section is more general.
+ *
+ * @return {string}
+ */
+ getAuthority: function () {
+ return cat( '', this.getUserInfo(), '@' ) + this.getHostPort();
+ },
+
+ /**
+ * Get the query arguments of the URL, encoded into a string.
+ *
+ * Does not preserve the original order of arguments passed in the URI. Does handle escaping.
+ *
+ * @return {string}
+ */
+ getQueryString: function () {
+ var args = [];
+ $.each( this.query, function ( key, val ) {
+ var k = Uri.encode( key ),
+ vals = Array.isArray( val ) ? val : [ val ];
+ $.each( vals, function ( i, v ) {
+ if ( v === null ) {
+ args.push( k );
+ } else if ( k === 'title' ) {
+ args.push( k + '=' + mw.util.wikiUrlencode( v ) );
+ } else {
+ args.push( k + '=' + Uri.encode( v ) );
+ }
+ } );
+ } );
+ return args.join( '&' );
+ },
+
+ /**
+ * Get everything after the authority section of the URI.
+ *
+ * @return {string}
+ */
+ getRelativePath: function () {
+ return this.path + cat( '?', this.getQueryString(), '', true ) + cat( '#', this.fragment, '' );
+ },
+
+ /**
+ * Get the entire URI string.
+ *
+ * May not be precisely the same as input due to order of query arguments.
+ *
+ * @return {string} The URI string
+ */
+ toString: function () {
+ return this.protocol + '://' + this.getAuthority() + this.getRelativePath();
+ },
+
+ /**
+ * Clone this URI
+ *
+ * @return {Object} New URI object with same properties
+ */
+ clone: function () {
+ return new Uri( this );
+ },
+
+ /**
+ * Extend the query section of the URI with new parameters.
+ *
+ * @param {Object} parameters Query parameters to add to ours (or to override ours with) as an
+ * object
+ * @return {Object} This URI object
+ */
+ extend: function ( parameters ) {
+ $.extend( this.query, parameters );
+ return this;
+ }
+ };
+
+ return Uri;
+ };
+
+ // Default to the current browsing location (for relative URLs).
+ mw.Uri = mw.UriRelative( function () {
+ return location.href;
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.Uri.loose.regexp b/www/wiki/resources/src/mediawiki/mediawiki.Uri.loose.regexp
new file mode 100644
index 00000000..300ab3ba
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.Uri.loose.regexp
@@ -0,0 +1,22 @@
+^
+(?:
+ (?![^:@]+:[^:@/]*@)
+ (?<protocol>[^:/?#.]+):
+)?
+(?://)?
+(?:(?:
+ (?<user>[^:@/?#]*)
+ (?::(?<password>[^:@/?#]*))?
+)?@)?
+(?<host>[^:/?#]*)
+(?::(?<port>\d*))?
+(
+ (?:/
+ (?:[^?#]
+ (?![^?#/]*\.[^?#/.]+(?:[?#]|$))
+ )*/?
+ )?
+ [^?#/]*
+)
+(?:\?(?<query>[^#]*))?
+(?:\#(?<fragment>.*))?
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.Uri.strict.regexp b/www/wiki/resources/src/mediawiki/mediawiki.Uri.strict.regexp
new file mode 100644
index 00000000..2ac7d2fc
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.Uri.strict.regexp
@@ -0,0 +1,13 @@
+^
+(?:(?<protocol>[^:/?#]+):)?
+(?://(?:
+ (?:
+ (?<user>[^:@/?#]*)
+ (?::(?<password>[^:@/?#]*))?
+ )?@)?
+ (?<host>[^:/?#]*)
+ (?::(?<port>\d*))?
+)?
+(?<path>(?:[^?#/]*/)*[^?#]*)
+(?:\?(?<query>[^#]*))?
+(?:\#(?<fragment>.*))?
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.apihelp.css b/www/wiki/resources/src/mediawiki/mediawiki.apihelp.css
new file mode 100644
index 00000000..d3e49500
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.apihelp.css
@@ -0,0 +1,105 @@
+.apihelp-header {
+ clear: both;
+ margin-bottom: 0.1em;
+}
+
+.apihelp-header.apihelp-module-name {
+ /*
+ * This element is explicitly set to dir="ltr" in HTML.
+ * Set explicit alignment so that CSSJanus will flip it to "right";
+ * otherwise the alignment will be automatically set to "left" according
+ * to the element's direction, and this will have an inconsistent look.
+ */
+ text-align: left;
+}
+
+div.apihelp-linktrail {
+ font-size: smaller;
+}
+
+.apihelp-block {
+ margin-top: 0.5em;
+}
+
+.apihelp-block-head {
+ font-weight: bold;
+}
+
+.apihelp-flags {
+ font-size: smaller;
+ float: right;
+ border: 1px solid #000;
+ padding: 0.25em;
+ width: 20em;
+}
+
+.apihelp-deprecated,
+.apihelp-flag-deprecated,
+.apihelp-flag-internal strong {
+ font-weight: bold;
+ color: #d33;
+}
+
+.apihelp-deprecated-value {
+ text-decoration: line-through;
+}
+
+.apihelp-unknown {
+ color: #72777d;
+}
+
+.apihelp-empty {
+ color: #72777d;
+}
+
+.apihelp-help-urls ul {
+ list-style-image: none;
+ list-style-type: none;
+ margin-left: 0;
+}
+
+.apihelp-parameters dl,
+.apihelp-examples dl,
+.apihelp-permissions dl {
+ margin-left: 2em;
+}
+
+.apihelp-parameters dt {
+ float: left;
+ clear: left;
+ min-width: 10em;
+ white-space: nowrap;
+ line-height: 1.5em;
+}
+
+.apihelp-parameters dt:after {
+ content: ':\A0';
+}
+
+.apihelp-parameters dd {
+ margin: 0 0 0.5em 10em;
+ line-height: 1.5em;
+}
+
+.apihelp-parameters dd p:first-child {
+ margin-top: 0;
+}
+
+.apihelp-parameters dd.info {
+ margin-left: 12em;
+ text-indent: -2em;
+}
+
+.apihelp-examples dt {
+ font-weight: normal;
+}
+
+.api-main-links {
+ text-align: center;
+}
+.api-main-links ul:before {
+ content: '[';
+}
+.api-main-links ul:after {
+ content: ']';
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.apipretty.css b/www/wiki/resources/src/mediawiki/mediawiki.apipretty.css
new file mode 100644
index 00000000..99e45695
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.apipretty.css
@@ -0,0 +1,11 @@
+.mw-special-ApiHelp h1.firstHeading {
+ display: none;
+}
+
+.api-pretty-header {
+ font-size: small;
+}
+
+.api-pretty-content {
+ white-space: pre-wrap;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.checkboxtoggle.css b/www/wiki/resources/src/mediawiki/mediawiki.checkboxtoggle.css
new file mode 100644
index 00000000..3da0d438
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.checkboxtoggle.css
@@ -0,0 +1,3 @@
+.client-nojs .mw-checkbox-toggle-controls {
+ display: none;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.checkboxtoggle.js b/www/wiki/resources/src/mediawiki/mediawiki.checkboxtoggle.js
new file mode 100644
index 00000000..36090ea1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.checkboxtoggle.js
@@ -0,0 +1,38 @@
+/*!
+ * Allows users to perform all / none / invert operations on a list of
+ * checkboxes on the page.
+ *
+ * @licence GNU GPL v2+
+ * @author Luke Faraone <luke at faraone dot cc>
+ *
+ * Based on ext.nuke.js from https://www.mediawiki.org/wiki/Extension:Nuke by
+ * Jeroen De Dauw <jeroendedauw at gmail dot com>
+ */
+
+( function ( mw, $ ) {
+ 'use strict';
+
+ $( function () {
+ // FIXME: This shouldn't be a global selector to avoid conflicts
+ // with unrelated content on the same page. (T131318)
+ var $checkboxes = $( 'li input[type="checkbox"]' );
+
+ function selectAll( check ) {
+ $checkboxes.prop( 'checked', check );
+ }
+
+ $( '.mw-checkbox-all' ).click( function () {
+ selectAll( true );
+ } );
+ $( '.mw-checkbox-none' ).click( function () {
+ selectAll( false );
+ } );
+ $( '.mw-checkbox-invert' ).click( function () {
+ $checkboxes.prop( 'checked', function ( i, val ) {
+ return !val;
+ } );
+ } );
+
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.confirmCloseWindow.js b/www/wiki/resources/src/mediawiki/mediawiki.confirmCloseWindow.js
new file mode 100644
index 00000000..ee3bac24
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.confirmCloseWindow.js
@@ -0,0 +1,111 @@
+( function ( mw, $ ) {
+ /**
+ * Prevent the closing of a window with a confirm message (the onbeforeunload event seems to
+ * work in most browsers.)
+ *
+ * This supersedes any previous onbeforeunload handler. If there was a handler before, it is
+ * restored when you execute the returned release() function.
+ *
+ * var allowCloseWindow = mw.confirmCloseWindow();
+ * // ... do stuff that can't be interrupted ...
+ * allowCloseWindow.release();
+ *
+ * The second function returned is a trigger function to trigger the check and an alert
+ * window manually, e.g.:
+ *
+ * var allowCloseWindow = mw.confirmCloseWindow();
+ * // ... do stuff that can't be interrupted ...
+ * if ( allowCloseWindow.trigger() ) {
+ * // don't do anything (e.g. destroy the input field)
+ * } else {
+ * // do whatever you wanted to do
+ * }
+ *
+ * @method confirmCloseWindow
+ * @member mw
+ * @param {Object} [options]
+ * @param {string} [options.namespace] Namespace for the event registration
+ * @param {string} [options.message]
+ * @param {string} options.message.return The string message to show in the confirm dialog.
+ * @param {Function} [options.test]
+ * @param {boolean} [options.test.return=true] Whether to show the dialog to the user.
+ * @return {Object} An object of functions to work with this module
+ */
+ mw.confirmCloseWindow = function ( options ) {
+ var savedUnloadHandler,
+ mainEventName = 'beforeunload',
+ showEventName = 'pageshow',
+ message;
+
+ options = $.extend( {
+ message: mw.message( 'mwe-prevent-close' ).text(),
+ test: function () { return true; }
+ }, options );
+
+ if ( options.namespace ) {
+ mainEventName += '.' + options.namespace;
+ showEventName += '.' + options.namespace;
+ }
+
+ if ( $.isFunction( options.message ) ) {
+ message = options.message();
+ } else {
+ message = options.message;
+ }
+
+ $( window ).on( mainEventName, function () {
+ if ( options.test() ) {
+ // remove the handler while the alert is showing - otherwise breaks caching in Firefox (3?).
+ // but if they continue working on this page, immediately re-register this handler
+ savedUnloadHandler = window.onbeforeunload;
+ window.onbeforeunload = null;
+ setTimeout( function () {
+ window.onbeforeunload = savedUnloadHandler;
+ }, 1 );
+
+ // show an alert with this message
+ return message;
+ }
+ } ).on( showEventName, function () {
+ // Re-add onbeforeunload handler
+ if ( !window.onbeforeunload && savedUnloadHandler ) {
+ window.onbeforeunload = savedUnloadHandler;
+ }
+ } );
+
+ /**
+ * Return the object with functions to release and manually trigger the confirm alert
+ *
+ * @ignore
+ */
+ return {
+ /**
+ * Remove all event listeners and don't show an alert anymore, if the user wants to leave
+ * the page.
+ *
+ * @ignore
+ */
+ release: function () {
+ $( window ).off( mainEventName + ' ' + showEventName );
+ },
+ /**
+ * Trigger the module's function manually: Check, if options.test() returns true and show
+ * an alert to the user if he/she want to leave this page. Returns false, if options.test() returns
+ * false or the user cancelled the alert window (~don't leave the page), true otherwise.
+ *
+ * @ignore
+ * @return {boolean}
+ */
+ trigger: function () {
+ // use confirm to show the message to the user (if options.text() is true)
+ // eslint-disable-next-line no-alert
+ if ( options.test() && !confirm( message ) ) {
+ // the user want to keep the actual page
+ return false;
+ }
+ // otherwise return true
+ return true;
+ }
+ };
+ };
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.content.json.css b/www/wiki/resources/src/mediawiki/mediawiki.content.json.css
new file mode 100644
index 00000000..9e20264f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.content.json.css
@@ -0,0 +1,59 @@
+/*!
+ * CSS for styling HTML-formatted JSON Schema objects
+ *
+ * @file
+ * @author Munaf Assaf <massaf@wikimedia.org>
+ */
+
+.mw-json {
+ border-collapse: collapse;
+ border-spacing: 0;
+ font-style: normal;
+}
+
+.mw-json th,
+.mw-json td {
+ border: 1px solid gray;
+ font-size: 16px;
+ padding: 0.5em 1em;
+}
+
+.mw-json .value,
+.mw-json-single-value {
+ background-color: #dcfae3;
+ font-family: monospace, monospace;
+ white-space: pre-wrap;
+}
+
+.mw-json-single-value {
+ background-color: #eee;
+}
+
+.mw-json-empty {
+ background-color: #fff;
+ font-style: italic;
+}
+
+.mw-json tr {
+ margin-bottom: 0.5em;
+ background-color: #eee;
+}
+
+.mw-json th {
+ background-color: #fff;
+ font-weight: normal;
+}
+
+.mw-json caption {
+ /* For stylistic reasons, suppress the caption of the outermost table */
+ display: none;
+}
+
+.mw-json table caption {
+ color: gray;
+ display: inline-block;
+ font-size: 10px;
+ font-style: italic;
+ margin-bottom: 0.5em;
+ text-align: left;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.content.json.less b/www/wiki/resources/src/mediawiki/mediawiki.content.json.less
new file mode 100644
index 00000000..91fa02a3
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.content.json.less
@@ -0,0 +1,59 @@
+/*!
+ * CSS for styling HTML-formatted JSON Schema objects
+ *
+ * @file
+ * @author Munaf Assaf <massaf@wikimedia.org>
+ */
+
+.mw-json {
+ border-collapse: collapse;
+ border-spacing: 0;
+ font-style: normal;
+}
+
+.mw-json th,
+.mw-json td {
+ border: 1px solid #808080;
+ font-size: 16px;
+ padding: 0.5em 1em;
+}
+
+.mw-json .value,
+.mw-json-single-value {
+ background-color: #dcfae3;
+ font-family: monospace, monospace;
+ white-space: pre-wrap;
+}
+
+.mw-json-single-value {
+ background-color: #eee;
+}
+
+.mw-json-empty {
+ background-color: #fff;
+ font-style: italic;
+}
+
+.mw-json tr {
+ margin-bottom: 0.5em;
+ background-color: #eee;
+}
+
+.mw-json th {
+ background-color: #fff;
+ font-weight: normal;
+}
+
+.mw-json caption {
+ /* For stylistic reasons, suppress the caption of the outermost table */
+ display: none;
+}
+
+.mw-json table caption {
+ color: #808080;
+ display: inline-block;
+ font-size: 10px;
+ font-style: italic;
+ margin-bottom: 0.5em;
+ text-align: left;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.cookie.js b/www/wiki/resources/src/mediawiki/mediawiki.cookie.js
new file mode 100644
index 00000000..d260fca6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.cookie.js
@@ -0,0 +1,131 @@
+( function ( mw, $ ) {
+ 'use strict';
+
+ /**
+ * Provides an API for getting and setting cookies that is
+ * syntactically and functionally similar to the server-side cookie
+ * API (`WebRequest#getCookie` and `WebResponse#setcookie`).
+ *
+ * @author Sam Smith <samsmith@wikimedia.org>
+ * @author Matthew Flaschen <mflaschen@wikimedia.org>
+ * @author Timo Tijhof <krinklemail@gmail.com>
+ *
+ * @class mw.cookie
+ * @singleton
+ */
+ mw.cookie = {
+
+ /**
+ * Set or delete a cookie.
+ *
+ * While this is natural in JavaScript, contrary to `WebResponse#setcookie` in PHP, the
+ * default values for the `options` properties only apply if that property isn't set
+ * already in your options object (e.g. passing `{ secure: null }` or `{ secure: undefined }`
+ * overrides the default value for `options.secure`).
+ *
+ * @param {string} key
+ * @param {string|null} value Value of cookie. If `value` is `null` then this method will
+ * instead remove a cookie by name of `key`.
+ * @param {Object|Date} [options] Options object, or expiry date
+ * @param {Date|number|null} [options.expires] The expiry date of the cookie, or lifetime in seconds.
+ *
+ * If `options.expires` is null, then a session cookie is set.
+ *
+ * By default cookie expiration is based on `wgCookieExpiration`. Similar to `WebResponse`
+ * in PHP, we set a session cookie if `wgCookieExpiration` is 0. And for non-zero values
+ * it is interpreted as lifetime in seconds.
+ *
+ * @param {string} [options.prefix=wgCookiePrefix] The prefix of the key
+ * @param {string} [options.domain=wgCookieDomain] The domain attribute of the cookie
+ * @param {string} [options.path=wgCookiePath] The path attribute of the cookie
+ * @param {boolean} [options.secure=false] Whether or not to include the secure attribute.
+ * (Does **not** use the wgCookieSecure configuration variable)
+ */
+ set: function ( key, value, options ) {
+ var config, defaultOptions, date;
+
+ // wgCookieSecure is not used for now, since 'detect' could not work with
+ // ResourceLoaderStartUpModule, as module cache is not fragmented by protocol.
+ config = mw.config.get( [
+ 'wgCookiePrefix',
+ 'wgCookieDomain',
+ 'wgCookiePath',
+ 'wgCookieExpiration'
+ ] );
+
+ defaultOptions = {
+ prefix: config.wgCookiePrefix,
+ domain: config.wgCookieDomain,
+ path: config.wgCookiePath,
+ secure: false
+ };
+
+ // Options argument can also be a shortcut for the expiry
+ // Expiry can be a Date or null
+ if ( $.type( options ) !== 'object' ) {
+ // Also takes care of options = undefined, in which case we also don't need $.extend()
+ defaultOptions.expires = options;
+ options = defaultOptions;
+ } else {
+ options = $.extend( defaultOptions, options );
+ }
+
+ // Default to using wgCookieExpiration (lifetime in seconds).
+ // If wgCookieExpiration is 0, that is considered a special value indicating
+ // all cookies should be session cookies by default.
+ if ( options.expires === undefined && config.wgCookieExpiration !== 0 ) {
+ date = new Date();
+ date.setTime( Number( date ) + ( config.wgCookieExpiration * 1000 ) );
+ options.expires = date;
+ } else if ( typeof options.expires === 'number' ) {
+ // Lifetime in seconds
+ date = new Date();
+ date.setTime( Number( date ) + ( options.expires * 1000 ) );
+ options.expires = date;
+ } else if ( options.expires === null ) {
+ // $.cookie makes a session cookie when options.expires is omitted
+ delete options.expires;
+ }
+
+ // Process prefix
+ key = options.prefix + key;
+ delete options.prefix;
+
+ // Process value
+ if ( value !== null ) {
+ value = String( value );
+ }
+
+ // Other options are handled by $.cookie
+ $.cookie( key, value, options );
+ },
+
+ /**
+ * Get the value of a cookie.
+ *
+ * @param {string} key
+ * @param {string} [prefix=wgCookiePrefix] The prefix of the key. If `prefix` is
+ * `undefined` or `null`, then `wgCookiePrefix` is used
+ * @param {Mixed} [defaultValue=null]
+ * @return {string|null|Mixed} If the cookie exists, then the value of the
+ * cookie, otherwise `defaultValue`
+ */
+ get: function ( key, prefix, defaultValue ) {
+ var result;
+
+ if ( prefix === undefined || prefix === null ) {
+ prefix = mw.config.get( 'wgCookiePrefix' );
+ }
+
+ // Was defaultValue omitted?
+ if ( arguments.length < 3 ) {
+ defaultValue = null;
+ }
+
+ result = $.cookie( prefix + key );
+
+ return result !== null ? result : defaultValue;
+ }
+ };
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.debug.init.js b/www/wiki/resources/src/mediawiki/mediawiki.debug.init.js
new file mode 100644
index 00000000..0f85e80d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.debug.init.js
@@ -0,0 +1,3 @@
+jQuery( function () {
+ mediaWiki.Debug.init();
+} );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.debug.js b/www/wiki/resources/src/mediawiki/mediawiki.debug.js
new file mode 100644
index 00000000..939b8412
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.debug.js
@@ -0,0 +1,389 @@
+( function ( mw, $ ) {
+ 'use strict';
+
+ var debug,
+ hovzer = $.getFootHovzer();
+
+ /**
+ * Debug toolbar.
+ *
+ * Enabled server-side through `$wgDebugToolbar`.
+ *
+ * @class mw.Debug
+ * @singleton
+ * @author John Du Hart
+ * @since 1.19
+ */
+ debug = mw.Debug = {
+ /**
+ * Toolbar container element
+ *
+ * @property {jQuery}
+ */
+ $container: null,
+
+ /**
+ * Object containing data for the debug toolbar
+ *
+ * @property {Object}
+ */
+ data: {},
+
+ /**
+ * Initialize the debugging pane
+ *
+ * Shouldn't be called before the document is ready
+ * (since it binds to elements on the page).
+ *
+ * @param {Object} [data] Defaults to 'debugInfo' from mw.config
+ */
+ init: function ( data ) {
+
+ this.data = data || mw.config.get( 'debugInfo' );
+ this.buildHtml();
+
+ // Insert the container into the DOM
+ hovzer.$.append( this.$container );
+ hovzer.update();
+
+ $( '.mw-debug-panelink' ).click( this.switchPane );
+ },
+
+ /**
+ * Switch between panes
+ *
+ * Should be called with an HTMLElement as its thisArg,
+ * because it's meant to be an event handler.
+ *
+ * TODO: Store cookie for last pane open.
+ *
+ * @param {jQuery.Event} e
+ */
+ switchPane: function ( e ) {
+ var currentPaneId = debug.$container.data( 'currentPane' ),
+ requestedPaneId = $( this ).prop( 'id' ).slice( 9 ),
+ $currentPane = $( '#mw-debug-pane-' + currentPaneId ),
+ $requestedPane = $( '#mw-debug-pane-' + requestedPaneId ),
+ hovDone = false;
+
+ function updateHov() {
+ if ( !hovDone ) {
+ hovzer.update();
+ hovDone = true;
+ }
+ }
+
+ // Skip hash fragment handling. Prevents screen from jumping.
+ e.preventDefault();
+
+ $( this ).addClass( 'current ' );
+ $( '.mw-debug-panelink' ).not( this ).removeClass( 'current ' );
+
+ // Hide the current pane
+ if ( requestedPaneId === currentPaneId ) {
+ $currentPane.slideUp( updateHov );
+ debug.$container.data( 'currentPane', null );
+ return;
+ }
+
+ debug.$container.data( 'currentPane', requestedPaneId );
+
+ if ( currentPaneId === undefined || currentPaneId === null ) {
+ $requestedPane.slideDown( updateHov );
+ } else {
+ $currentPane.hide();
+ $requestedPane.show();
+ updateHov();
+ }
+ },
+
+ /**
+ * Construct the HTML for the debugging toolbar
+ */
+ buildHtml: function () {
+ var $container, $bits, panes, id, gitInfo;
+
+ $container = $( '<div id="mw-debug-toolbar" class="mw-debug" lang="en" dir="ltr"></div>' );
+
+ $bits = $( '<div class="mw-debug-bits"></div>' );
+
+ /**
+ * Returns a jQuery element for a debug-bit div
+ *
+ * @ignore
+ * @param {string} id
+ * @return {jQuery}
+ */
+ function bitDiv( id ) {
+ return $( '<div>' ).prop( {
+ id: 'mw-debug-' + id,
+ className: 'mw-debug-bit'
+ } ).appendTo( $bits );
+ }
+
+ /**
+ * Returns a jQuery element for a pane link
+ *
+ * @ignore
+ * @param {string} id
+ * @param {string} text
+ * @return {jQuery}
+ */
+ function paneLabel( id, text ) {
+ return $( '<a>' )
+ .prop( {
+ className: 'mw-debug-panelabel',
+ href: '#mw-debug-pane-' + id
+ } )
+ .text( text );
+ }
+
+ /**
+ * Returns a jQuery element for a debug-bit div with a for a pane link
+ *
+ * @ignore
+ * @param {string} id CSS id snippet. Will be prefixed with 'mw-debug-'
+ * @param {string} text Text to show
+ * @param {string} count Optional count to show
+ * @return {jQuery}
+ */
+ function paneTriggerBitDiv( id, text, count ) {
+ if ( count ) {
+ text = text + ' (' + count + ')';
+ }
+ return $( '<div>' ).prop( {
+ id: 'mw-debug-' + id,
+ className: 'mw-debug-bit mw-debug-panelink'
+ } )
+ .append( paneLabel( id, text ) )
+ .appendTo( $bits );
+ }
+
+ paneTriggerBitDiv( 'console', 'Console', this.data.log.length );
+
+ paneTriggerBitDiv( 'querylist', 'Queries', this.data.queries.length );
+
+ paneTriggerBitDiv( 'debuglog', 'Debug log', this.data.debugLog.length );
+
+ paneTriggerBitDiv( 'request', 'Request' );
+
+ paneTriggerBitDiv( 'includes', 'PHP includes', this.data.includes.length );
+
+ gitInfo = '';
+ if ( this.data.gitRevision !== false ) {
+ gitInfo = '(' + this.data.gitRevision.slice( 0, 7 ) + ')';
+ if ( this.data.gitViewUrl !== false ) {
+ gitInfo = $( '<a>' )
+ .attr( 'href', this.data.gitViewUrl )
+ .text( gitInfo );
+ }
+ }
+
+ bitDiv( 'mwversion' )
+ .append( $( '<a href="//www.mediawiki.org/">MediaWiki</a>' ) )
+ .append( document.createTextNode( ': ' + this.data.mwVersion + ' ' ) )
+ .append( gitInfo );
+
+ if ( this.data.gitBranch !== false ) {
+ bitDiv( 'gitbranch' ).text( 'Git branch: ' + this.data.gitBranch );
+ }
+
+ bitDiv( 'phpversion' )
+ .append( $( this.data.phpEngine === 'HHVM' ?
+ '<a href="http://hhvm.com/">HHVM</a>' :
+ '<a href="https://php.net/">PHP</a>'
+ ) )
+ .append( ': ' + this.data.phpVersion );
+
+ bitDiv( 'time' )
+ .text( 'Time: ' + this.data.time.toFixed( 5 ) );
+
+ bitDiv( 'memory' )
+ .text( 'Memory: ' + this.data.memory + ' (Peak: ' + this.data.memoryPeak + ')' );
+
+ $bits.appendTo( $container );
+
+ panes = {
+ console: this.buildConsoleTable(),
+ querylist: this.buildQueryTable(),
+ debuglog: this.buildDebugLogTable(),
+ request: this.buildRequestPane(),
+ includes: this.buildIncludesPane()
+ };
+
+ for ( id in panes ) {
+ if ( !panes.hasOwnProperty( id ) ) {
+ continue;
+ }
+
+ $( '<div>' )
+ .prop( {
+ className: 'mw-debug-pane',
+ id: 'mw-debug-pane-' + id
+ } )
+ .append( panes[ id ] )
+ .appendTo( $container );
+ }
+
+ this.$container = $container;
+ },
+
+ /**
+ * Build the console panel
+ *
+ * @return {jQuery} Console panel
+ */
+ buildConsoleTable: function () {
+ var $table, entryTypeText, i, length, entry;
+
+ $table = $( '<table id="mw-debug-console">' );
+
+ $( '<colgroup>' ).css( 'width', /* padding = */ 20 + ( 10 * /* fontSize = */ 11 ) ).appendTo( $table );
+ $( '<colgroup>' ).appendTo( $table );
+ $( '<colgroup>' ).css( 'width', 350 ).appendTo( $table );
+
+ entryTypeText = function ( entryType ) {
+ switch ( entryType ) {
+ case 'log':
+ return 'Log';
+ case 'warn':
+ return 'Warning';
+ case 'deprecated':
+ return 'Deprecated';
+ default:
+ return 'Unknown';
+ }
+ };
+
+ for ( i = 0, length = this.data.log.length; i < length; i += 1 ) {
+ entry = this.data.log[ i ];
+ entry.typeText = entryTypeText( entry.type );
+
+ $( '<tr>' )
+ .append( $( '<td>' )
+ .text( entry.typeText )
+ .addClass( 'mw-debug-console-' + entry.type )
+ )
+ .append( $( '<td>' ).html( entry.msg ) )
+ .append( $( '<td>' ).text( entry.caller ) )
+ .appendTo( $table );
+ }
+
+ return $table;
+ },
+
+ /**
+ * Build query list pane
+ *
+ * @return {jQuery}
+ */
+ buildQueryTable: function () {
+ var $table, i, length, query;
+
+ $table = $( '<table id="mw-debug-querylist"></table>' );
+
+ $( '<tr>' )
+ .append( $( '<th>#</th>' ).css( 'width', '4em' ) )
+ .append( $( '<th>SQL</th>' ) )
+ .append( $( '<th>Time</th>' ).css( 'width', '8em' ) )
+ .append( $( '<th>Call</th>' ).css( 'width', '18em' ) )
+ .appendTo( $table );
+
+ for ( i = 0, length = this.data.queries.length; i < length; i += 1 ) {
+ query = this.data.queries[ i ];
+
+ $( '<tr>' )
+ .append( $( '<td>' ).text( i + 1 ) )
+ .append( $( '<td>' ).text( query.sql ) )
+ .append( $( '<td class="stats">' ).text( ( query.time * 1000 ).toFixed( 4 ) + 'ms' ) )
+ .append( $( '<td>' ).text( query[ 'function' ] ) )
+ .appendTo( $table );
+ }
+
+ return $table;
+ },
+
+ /**
+ * Build legacy debug log pane
+ *
+ * @return {jQuery}
+ */
+ buildDebugLogTable: function () {
+ var $list, i, length, line;
+ $list = $( '<ul>' );
+
+ for ( i = 0, length = this.data.debugLog.length; i < length; i += 1 ) {
+ line = this.data.debugLog[ i ];
+ $( '<li>' )
+ .html( mw.html.escape( line ).replace( /\n/g, '<br />\n' ) )
+ .appendTo( $list );
+ }
+
+ return $list;
+ },
+
+ /**
+ * Build request information pane
+ *
+ * @return {jQuery}
+ */
+ buildRequestPane: function () {
+
+ function buildTable( title, data ) {
+ var $unit, $table, key;
+
+ $unit = $( '<div>' ).append( $( '<h2>' ).text( title ) );
+
+ $table = $( '<table>' ).appendTo( $unit );
+
+ $( '<tr>' )
+ .html( '<th>Key</th><th>Value</th>' )
+ .appendTo( $table );
+
+ for ( key in data ) {
+ if ( !data.hasOwnProperty( key ) ) {
+ continue;
+ }
+
+ $( '<tr>' )
+ .append( $( '<th>' ).text( key ) )
+ .append( $( '<td>' ).text( data[ key ] ) )
+ .appendTo( $table );
+ }
+
+ return $unit;
+ }
+
+ return $( '<div>' )
+ .text( this.data.request.method + ' ' + this.data.request.url )
+ .append( buildTable( 'Headers', this.data.request.headers ) )
+ .append( buildTable( 'Parameters', this.data.request.params ) );
+ },
+
+ /**
+ * Build included files pane
+ *
+ * @return {jQuery}
+ */
+ buildIncludesPane: function () {
+ var $table, i, length, file;
+
+ $table = $( '<table>' );
+
+ for ( i = 0, length = this.data.includes.length; i < length; i += 1 ) {
+ file = this.data.includes[ i ];
+ $( '<tr>' )
+ .append( $( '<td>' ).text( file.name ) )
+ .append( $( '<td class="nr">' ).text( file.size ) )
+ .appendTo( $table );
+ }
+
+ return $table;
+ }
+ };
+
+ $( function () {
+ debug.init();
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.debug.less b/www/wiki/resources/src/mediawiki/mediawiki.debug.less
new file mode 100644
index 00000000..dec05715
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.debug.less
@@ -0,0 +1,187 @@
+.mw-debug {
+ width: 100%;
+ background-color: #eee;
+ border-top: 1px solid #aaa;
+
+ pre {
+ font-size: 11px;
+ padding: 0;
+ margin: 0;
+ background: none;
+ border: 0;
+ }
+
+ table {
+ border-spacing: 0;
+ width: 100%;
+ table-layout: fixed;
+
+ td,
+ th {
+ padding: 4px 10px;
+ }
+
+ td {
+ border-bottom: 1px solid #eee;
+ word-wrap: break-word;
+
+ &.nr {
+ text-align: right;
+ }
+
+ span.stats {
+ color: #808080;
+ }
+ }
+
+ tr {
+ background-color: #fff;
+
+ &:nth-child( even ) {
+ background-color: #f9f9f9;
+ }
+ }
+ }
+
+ ul {
+ margin: 0;
+ list-style: none;
+ }
+
+ li {
+ padding: 4px 0;
+ width: 100%;
+ }
+}
+
+.mw-debug-bits {
+ text-align: center;
+ border-bottom: 1px solid #aaa;
+}
+
+.mw-debug-bit {
+ display: inline-block;
+ padding: 10px 5px;
+ font-size: 13px;
+}
+
+.mw-debug-panelink {
+ background-color: #eee;
+ border-right: 1px solid #ccc;
+
+ &:first-child {
+ border-left: 1px solid #ccc;
+ }
+
+ &:hover {
+ background-color: #fefefe;
+ cursor: pointer;
+ }
+
+ &.current {
+ background-color: #dedede;
+ }
+}
+
+a.mw-debug-panelabel,
+a.mw-debug-panelabel:visited {
+ color: #000;
+}
+
+.mw-debug-pane {
+ height: 300px;
+ overflow: scroll;
+ display: none;
+ font-family: monospace;
+ font-size: 11px;
+ background-color: #e1eff2;
+ box-sizing: border-box;
+}
+
+#mw-debug-pane-debuglog,
+#mw-debug-pane-request {
+ padding: 20px;
+}
+
+#mw-debug-pane-request {
+ table {
+ width: 100%;
+ margin: 10px 0 30px;
+ }
+
+ tr,
+ th,
+ td,
+ table {
+ border: 1px solid #d0dbb3;
+ border-collapse: collapse;
+ margin: 0;
+ }
+
+ th,
+ td {
+ font-size: 12px;
+ padding: 8px 10px;
+ }
+
+ th {
+ background-color: #f1f7e2;
+ font-weight: bold;
+ }
+
+ td {
+ background-color: #fff;
+ }
+}
+
+#mw-debug-console tr td {
+ &:first-child {
+ font-weight: bold;
+ vertical-align: top;
+ }
+
+ &:last-child {
+ vertical-align: top;
+ }
+}
+
+.mw-debug-backtrace {
+ padding: 5px 10px;
+ margin: 5px;
+ background-color: #dedede;
+
+ span {
+ font-weight: bold;
+ color: #111;
+ }
+
+ ul {
+ padding-left: 10px;
+ }
+
+ li {
+ width: auto;
+ padding: 0;
+ color: #333;
+ font-size: 10px;
+ margin-bottom: 0;
+ line-height: 1em;
+ }
+}
+
+.mw-debug-console-log {
+ background-color: #add8e6;
+}
+
+.mw-debug-console-warn {
+ background-color: #ffa07a;
+}
+
+.mw-debug-console-deprecated {
+ background-color: #ffb6c1;
+}
+
+/* Cheapo hack to hide the first 3 lines of the backtrace */
+.mw-debug-backtrace li:nth-child( -n+3 ) {
+ display: none;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.diff.styles.css b/www/wiki/resources/src/mediawiki/mediawiki.diff.styles.css
new file mode 100644
index 00000000..7a73e984
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.diff.styles.css
@@ -0,0 +1,121 @@
+/*!
+ * Diff rendering
+ */
+
+.diff {
+ border: 0;
+ border-spacing: 4px;
+ margin: 0;
+ width: 100%;
+ /* Ensure that colums are of equal width */
+ table-layout: fixed;
+}
+
+.diff td {
+ padding: 0.33em 0.5em;
+}
+
+.diff td.diff-marker {
+ /* Compensate padding for increased font-size */
+ padding: 0.25em;
+}
+
+.diff col.diff-marker {
+ width: 2%;
+}
+
+.diff .diff-content {
+ width: 48%;
+}
+
+.diff td div {
+ /* Force-wrap very long lines such as URLs or page-widening char strings */
+ word-wrap: break-word;
+}
+
+.diff-otitle,
+.diff-ntitle {
+ text-align: center;
+}
+
+.diff-lineno {
+ font-weight: bold;
+}
+
+td.diff-marker {
+ text-align: right;
+ font-weight: bold;
+ font-size: 1.25em;
+ line-height: 1.2;
+}
+
+.diff-addedline,
+.diff-deletedline,
+.diff-context {
+ font-size: 88%;
+ line-height: 1.6;
+ vertical-align: top;
+ white-space: -moz-pre-wrap;
+ white-space: pre-wrap;
+ border-style: solid;
+ border-width: 1px 1px 1px 4px;
+ border-radius: 0.33em;
+}
+
+.diff-addedline {
+ border-color: #a3d3ff;
+}
+
+.diff-deletedline {
+ border-color: #ffe49c;
+}
+
+.diff-context {
+ background: #f9f9f9;
+ border-color: #e6e6e6;
+ color: #333;
+}
+
+.diffchange {
+ font-weight: bold;
+ text-decoration: none;
+}
+
+.diff-addedline .diffchange,
+.diff-deletedline .diffchange {
+ border-radius: 0.33em;
+ padding: 0.25em 0;
+}
+
+.diff-addedline .diffchange {
+ background: #d8ecff;
+}
+
+.diff-deletedline .diffchange {
+ background: #feeec8;
+}
+
+/* Correct user & content directionality when viewing a diff */
+.diff-currentversion-title,
+.diff {
+ direction: ltr;
+ unicode-bidi: embed;
+}
+
+/* @noflip */ .diff-contentalign-right td {
+ direction: rtl;
+ unicode-bidi: embed;
+}
+
+/* @noflip */ .diff-contentalign-left td {
+ direction: ltr;
+ unicode-bidi: embed;
+}
+
+.diff-multi,
+.diff-otitle,
+.diff-ntitle,
+.diff-lineno {
+ direction: ltr !important; /* stylelint-disable-line declaration-no-important */
+ unicode-bidi: embed;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.diff.styles.print.css b/www/wiki/resources/src/mediawiki/mediawiki.diff.styles.print.css
new file mode 100644
index 00000000..76b5c9b7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.diff.styles.print.css
@@ -0,0 +1,16 @@
+/*!
+ * Diff rendering
+ */
+td.diff-context,
+td.diff-addedline .diffchange,
+td.diff-deletedline .diffchange {
+ background-color: transparent;
+}
+
+td.diff-addedline .diffchange {
+ text-decoration: underline;
+}
+
+td.diff-deletedline .diffchange {
+ text-decoration: line-through;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.errorLogger.js b/www/wiki/resources/src/mediawiki/mediawiki.errorLogger.js
new file mode 100644
index 00000000..e86aff6b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.errorLogger.js
@@ -0,0 +1,58 @@
+/**
+ * Try to catch errors in modules which don't do their own error handling.
+ *
+ * @class mw.errorLogger
+ * @singleton
+ */
+( function ( mw ) {
+ 'use strict';
+
+ mw.errorLogger = {
+ /**
+ * Fired via mw.track when an error is not handled by local code and is caught by the
+ * window.onerror handler.
+ *
+ * @event global_error
+ * @param {string} errorMessage Error errorMessage.
+ * @param {string} url URL where error was raised.
+ * @param {number} lineNumber Line number where error was raised.
+ * @param {number} [columnNumber] Line number where error was raised. Not all browsers
+ * support this.
+ * @param {Error|Mixed} [errorObject] The error object. Typically an instance of Error, but anything
+ * (even a primitive value) passed to a throw clause will end up here.
+ */
+
+ /**
+ * Install a window.onerror handler that will report via mw.track, while preserving
+ * any previous handler.
+ *
+ * @param {Object} window
+ */
+ installGlobalHandler: function ( window ) {
+ // We will preserve the return value of the previous handler. window.onerror works the
+ // opposite way than normal event handlers (returning true will prevent the default
+ // action, returning false will let the browser handle the error normally, by e.g.
+ // logging to the console), so our fallback old handler needs to return false.
+ var oldHandler = window.onerror || function () { return false; };
+
+ /**
+ * Dumb window.onerror handler which forwards the errors via mw.track.
+ *
+ * @param {string} errorMessage
+ * @param {string} url
+ * @param {number} lineNumber
+ * @param {number} [columnNumber]
+ * @param {Error|Mixed} [errorObject]
+ * @return {boolean} True to prevent the default action
+ * @fires global_error
+ */
+ window.onerror = function ( errorMessage, url, lineNumber, columnNumber, errorObject ) {
+ mw.track( 'global.error', { errorMessage: errorMessage, url: url,
+ lineNumber: lineNumber, columnNumber: columnNumber, errorObject: errorObject } );
+ return oldHandler.apply( this, arguments );
+ };
+ }
+ };
+
+ mw.errorLogger.installGlobalHandler( window );
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.experiments.js b/www/wiki/resources/src/mediawiki/mediawiki.experiments.js
new file mode 100644
index 00000000..4fedbeae
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.experiments.js
@@ -0,0 +1,109 @@
+( function ( mw, $ ) {
+
+ var CONTROL_BUCKET = 'control',
+ MAX_INT32_UNSIGNED = 4294967295;
+
+ /**
+ * An implementation of Jenkins' one-at-a-time hash.
+ *
+ * @see https://en.wikipedia.org/wiki/Jenkins_hash_function
+ *
+ * @param {string} string String to hash
+ * @return {number} The hash as a 32-bit unsigned integer
+ * @ignore
+ *
+ * @author Ori Livneh <ori@wikimedia.org>
+ * @see https://jsbin.com/kejewi/4/watch?js,console
+ */
+ function hashString( string ) {
+ /* eslint-disable no-bitwise */
+ var hash = 0,
+ i = string.length;
+
+ while ( i-- ) {
+ hash += string.charCodeAt( i );
+ hash += ( hash << 10 );
+ hash ^= ( hash >> 6 );
+ }
+ hash += ( hash << 3 );
+ hash ^= ( hash >> 11 );
+ hash += ( hash << 15 );
+
+ return hash >>> 0;
+ /* eslint-enable no-bitwise */
+ }
+
+ /**
+ * Provides an API for bucketing users in experiments.
+ *
+ * @class mw.experiments
+ * @singleton
+ */
+ mw.experiments = {
+
+ /**
+ * Gets the bucket for the experiment given the token.
+ *
+ * The name of the experiment and the token are hashed. The hash is converted
+ * to a number which is then used to get a bucket.
+ *
+ * Consider the following experiment specification:
+ *
+ * ```
+ * {
+ * name: 'My first experiment',
+ * enabled: true,
+ * buckets: {
+ * control: 0.5
+ * A: 0.25,
+ * B: 0.25
+ * }
+ * }
+ * ```
+ *
+ * The experiment has three buckets: control, A, and B. The user has a 50%
+ * chance of being assigned to the control bucket, and a 25% chance of being
+ * assigned to either the A or B buckets. If the experiment were disabled,
+ * then the user would always be assigned to the control bucket.
+ *
+ * @param {Object} experiment
+ * @param {string} experiment.name The name of the experiment
+ * @param {boolean} experiment.enabled Whether or not the experiment is
+ * enabled. If the experiment is disabled, then the user is always assigned
+ * to the control bucket
+ * @param {Object} experiment.buckets A map of bucket name to probability
+ * that the user will be assigned to that bucket
+ * @param {string} token A token that uniquely identifies the user for the
+ * duration of the experiment
+ * @return {string} The bucket
+ */
+ getBucket: function ( experiment, token ) {
+ var buckets = experiment.buckets,
+ key,
+ range = 0,
+ hash,
+ max,
+ acc = 0;
+
+ if ( !experiment.enabled || $.isEmptyObject( experiment.buckets ) ) {
+ return CONTROL_BUCKET;
+ }
+
+ for ( key in buckets ) {
+ range += buckets[ key ];
+ }
+
+ hash = hashString( experiment.name + ':' + token );
+ max = ( hash / MAX_INT32_UNSIGNED ) * range;
+
+ for ( key in buckets ) {
+ acc += buckets[ key ];
+
+ if ( max <= acc ) {
+ return key;
+ }
+ }
+ }
+ };
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.feedback.css b/www/wiki/resources/src/mediawiki/mediawiki.feedback.css
new file mode 100644
index 00000000..c4363ed0
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.feedback.css
@@ -0,0 +1,31 @@
+.feedback-spinner {
+ display: inline-block;
+ zoom: 1;
+ *display: inline; /* IE7 and below */ /* stylelint-disable declaration-block-no-duplicate-properties */
+ /* @embed */
+ background: url( mediawiki.feedback.spinner.gif );
+ width: 18px;
+ height: 18px;
+}
+
+.mw-feedbackDialog-welcome-message,
+.mw-feedbackDialog-feedback-terms {
+ line-height: 1.4;
+}
+
+.mw-feedbackDialog-welcome-message {
+ margin-bottom: 1em;
+}
+
+/* Overwriting OOUI is no fun */
+.mw-feedbackDialog-feedback-form .oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header {
+ min-width: 4.2em;
+ width: 10%;
+}
+.mw-feedbackDialog-feedback-form .oo-ui-fieldLayout.oo-ui-labelElement.oo-ui-fieldLayout-align-left > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-field {
+ width: 80%;
+}
+
+.mw-feedbackDialog-feedback-termsofuse {
+ margin-left: 2em;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.feedback.js b/www/wiki/resources/src/mediawiki/mediawiki.feedback.js
new file mode 100644
index 00000000..2d55094f
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.feedback.js
@@ -0,0 +1,502 @@
+/*!
+ * mediawiki.feedback
+ *
+ * @author Ryan Kaldari, 2010
+ * @author Neil Kandalgaonkar, 2010-11
+ * @author Moriel Schottlender, 2015
+ * @since 1.19
+ */
+( function ( mw, $ ) {
+ /**
+ * This is a way of getting simple feedback from users. It's useful
+ * for testing new features -- users can give you feedback without
+ * the difficulty of opening a whole new talk page. For this reason,
+ * it also tends to collect a wider range of both positive and negative
+ * comments. However you do need to tend to the feedback page. It will
+ * get long relatively quickly, and you often get multiple messages
+ * reporting the same issue.
+ *
+ * It takes the form of thing on your page which, when clicked, opens a small
+ * dialog box. Submitting that dialog box appends its contents to a
+ * wiki page that you specify, as a new section.
+ *
+ * This feature works with any content model that defines a
+ * `mw.messagePoster.MessagePoster`.
+ *
+ * Minimal usage example:
+ *
+ * var feedback = new mw.Feedback();
+ * $( '#myButton' ).click( function () { feedback.launch(); } );
+ *
+ * You can also launch the feedback form with a prefilled subject and body.
+ * See the docs for the #launch() method.
+ *
+ * @class
+ * @constructor
+ * @param {Object} [config] Configuration object
+ * @cfg {mw.Title} [title="Feedback"] The title of the page where you collect
+ * feedback.
+ * @cfg {string} [apiUrl] api.php URL if the feedback page is on another wiki
+ * @cfg {string} [dialogTitleMessageKey="feedback-dialog-title"] Message key for the
+ * title of the dialog box
+ * @cfg {mw.Uri|string} [bugsLink="//phabricator.wikimedia.org/maniphest/task/edit/form/1/"] URL where
+ * bugs can be posted
+ * @cfg {mw.Uri|string} [bugsListLink="//phabricator.wikimedia.org/maniphest/query/advanced"] URL
+ * where bugs can be listed
+ * @cfg {boolean} [showUseragentCheckbox=false] Show a Useragent agreement checkbox as part of the form.
+ * @cfg {boolean} [useragentCheckboxMandatory=false] Make the Useragent checkbox mandatory.
+ * @cfg {string|jQuery} [useragentCheckboxMessage] Supply a custom message for the useragent checkbox.
+ * defaults to the message 'feedback-terms'.
+ */
+ mw.Feedback = function MwFeedback( config ) {
+ config = config || {};
+
+ this.dialogTitleMessageKey = config.dialogTitleMessageKey || 'feedback-dialog-title';
+
+ // Feedback page title
+ this.feedbackPageTitle = config.title || new mw.Title( 'Feedback' );
+
+ this.messagePosterPromise = mw.messagePoster.factory.create( this.feedbackPageTitle, config.apiUrl );
+
+ // Links
+ this.bugsTaskSubmissionLink = config.bugsLink || '//phabricator.wikimedia.org/maniphest/task/edit/form/1/';
+ this.bugsTaskListLink = config.bugsListLink || '//phabricator.wikimedia.org/maniphest/query/advanced';
+
+ // Terms of use
+ this.useragentCheckboxShow = !!config.showUseragentCheckbox;
+ this.useragentCheckboxMandatory = !!config.useragentCheckboxMandatory;
+ this.useragentCheckboxMessage = config.useragentCheckboxMessage ||
+ $( '<p>' ).append( mw.msg( 'feedback-terms' ) );
+
+ // Message dialog
+ this.thankYouDialog = new OO.ui.MessageDialog();
+ };
+
+ /* Initialize */
+ OO.initClass( mw.Feedback );
+
+ /* Static Properties */
+ mw.Feedback.static.windowManager = null;
+ mw.Feedback.static.dialog = null;
+
+ /* Methods */
+
+ /**
+ * Respond to dialog submit event. If the information was
+ * submitted, either successfully or with an error, open
+ * a MessageDialog to thank the user.
+ *
+ * @param {string} [status] A status of the end of operation
+ * of the main feedback dialog. Empty if the dialog was
+ * dismissed with no action or the user followed the button
+ * to the external task reporting site.
+ */
+ mw.Feedback.prototype.onDialogSubmit = function ( status ) {
+ var dialogConfig = {};
+ switch ( status ) {
+ case 'submitted':
+ dialogConfig = {
+ title: mw.msg( 'feedback-thanks-title' ),
+ message: $( '<span>' ).msg(
+ 'feedback-thanks',
+ this.feedbackPageTitle.getNameText(),
+ $( '<a>' ).attr( {
+ target: '_blank',
+ href: this.feedbackPageTitle.getUrl()
+ } )
+ ),
+ actions: [
+ {
+ action: 'accept',
+ label: mw.msg( 'feedback-close' ),
+ flags: 'primary'
+ }
+ ]
+ };
+ break;
+ }
+
+ // Show the message dialog
+ if ( !$.isEmptyObject( dialogConfig ) ) {
+ this.constructor.static.windowManager.openWindow(
+ this.thankYouDialog,
+ dialogConfig
+ );
+ }
+ };
+
+ /**
+ * Modify the display form, and then open it, focusing interface on the subject.
+ *
+ * @param {Object} [contents] Prefilled contents for the feedback form.
+ * @param {string} [contents.subject] The subject of the feedback, as plaintext
+ * @param {string} [contents.message] The content of the feedback, as wikitext
+ */
+ mw.Feedback.prototype.launch = function ( contents ) {
+ // Dialog
+ if ( !this.constructor.static.dialog ) {
+ this.constructor.static.dialog = new mw.Feedback.Dialog();
+ this.constructor.static.dialog.connect( this, { submit: 'onDialogSubmit' } );
+ }
+ if ( !this.constructor.static.windowManager ) {
+ this.constructor.static.windowManager = new OO.ui.WindowManager();
+ this.constructor.static.windowManager.addWindows( [
+ this.constructor.static.dialog,
+ this.thankYouDialog
+ ] );
+ $( 'body' )
+ .append( this.constructor.static.windowManager.$element );
+ }
+ // Open the dialog
+ this.constructor.static.windowManager.openWindow(
+ this.constructor.static.dialog,
+ {
+ title: mw.msg( this.dialogTitleMessageKey ),
+ settings: {
+ messagePosterPromise: this.messagePosterPromise,
+ title: this.feedbackPageTitle,
+ dialogTitleMessageKey: this.dialogTitleMessageKey,
+ bugsTaskSubmissionLink: this.bugsTaskSubmissionLink,
+ bugsTaskListLink: this.bugsTaskListLink,
+ useragentCheckbox: {
+ show: this.useragentCheckboxShow,
+ mandatory: this.useragentCheckboxMandatory,
+ message: this.useragentCheckboxMessage
+ }
+ },
+ contents: contents
+ }
+ );
+ };
+
+ /**
+ * mw.Feedback Dialog
+ *
+ * @class
+ * @extends OO.ui.ProcessDialog
+ *
+ * @constructor
+ * @param {Object} config Configuration object
+ */
+ mw.Feedback.Dialog = function mwFeedbackDialog( config ) {
+ // Parent constructor
+ mw.Feedback.Dialog.parent.call( this, config );
+
+ this.status = '';
+ this.feedbackPageTitle = null;
+ // Initialize
+ this.$element.addClass( 'mwFeedback-Dialog' );
+ };
+
+ OO.inheritClass( mw.Feedback.Dialog, OO.ui.ProcessDialog );
+
+ /* Static properties */
+ mw.Feedback.Dialog.static.name = 'mwFeedbackDialog';
+ mw.Feedback.Dialog.static.title = mw.msg( 'feedback-dialog-title' );
+ mw.Feedback.Dialog.static.size = 'medium';
+ mw.Feedback.Dialog.static.actions = [
+ {
+ action: 'submit',
+ label: mw.msg( 'feedback-submit' ),
+ flags: [ 'primary', 'progressive' ]
+ },
+ {
+ action: 'external',
+ label: mw.msg( 'feedback-external-bug-report-button' ),
+ flags: 'progressive'
+ },
+ {
+ action: 'cancel',
+ label: mw.msg( 'feedback-cancel' ),
+ flags: 'safe'
+ }
+ ];
+
+ /**
+ * @inheritdoc
+ */
+ mw.Feedback.Dialog.prototype.initialize = function () {
+ var feedbackSubjectFieldLayout, feedbackMessageFieldLayout,
+ feedbackFieldsetLayout, termsOfUseLabel;
+
+ // Parent method
+ mw.Feedback.Dialog.parent.prototype.initialize.call( this );
+
+ this.feedbackPanel = new OO.ui.PanelLayout( {
+ scrollable: false,
+ expanded: false,
+ padded: true
+ } );
+
+ this.$spinner = $( '<div>' )
+ .addClass( 'feedback-spinner' );
+
+ // Feedback form
+ this.feedbackMessageLabel = new OO.ui.LabelWidget( {
+ classes: [ 'mw-feedbackDialog-welcome-message' ]
+ } );
+ this.feedbackSubjectInput = new OO.ui.TextInputWidget( {
+ indicator: 'required'
+ } );
+ this.feedbackMessageInput = new OO.ui.MultilineTextInputWidget( {
+ autosize: true
+ } );
+ feedbackSubjectFieldLayout = new OO.ui.FieldLayout( this.feedbackSubjectInput, {
+ label: mw.msg( 'feedback-subject' )
+ } );
+ feedbackMessageFieldLayout = new OO.ui.FieldLayout( this.feedbackMessageInput, {
+ label: mw.msg( 'feedback-message' )
+ } );
+ feedbackFieldsetLayout = new OO.ui.FieldsetLayout( {
+ items: [ feedbackSubjectFieldLayout, feedbackMessageFieldLayout ],
+ classes: [ 'mw-feedbackDialog-feedback-form' ]
+ } );
+
+ // Useragent terms of use
+ this.useragentCheckbox = new OO.ui.CheckboxInputWidget();
+ this.useragentFieldLayout = new OO.ui.FieldLayout( this.useragentCheckbox, {
+ classes: [ 'mw-feedbackDialog-feedback-terms' ],
+ align: 'inline'
+ } );
+
+ termsOfUseLabel = new OO.ui.LabelWidget( {
+ classes: [ 'mw-feedbackDialog-feedback-termsofuse' ],
+ label: $( '<p>' ).append( mw.msg( 'feedback-termsofuse' ) )
+ } );
+
+ this.feedbackPanel.$element.append(
+ this.feedbackMessageLabel.$element,
+ feedbackFieldsetLayout.$element,
+ this.useragentFieldLayout.$element,
+ termsOfUseLabel.$element
+ );
+
+ // Events
+ this.feedbackSubjectInput.connect( this, { change: 'validateFeedbackForm' } );
+ this.feedbackMessageInput.connect( this, { change: 'validateFeedbackForm' } );
+ this.feedbackMessageInput.connect( this, { change: 'updateSize' } );
+ this.useragentCheckbox.connect( this, { change: 'validateFeedbackForm' } );
+
+ this.$body.append( this.feedbackPanel.$element );
+ };
+
+ /**
+ * Validate the feedback form
+ */
+ mw.Feedback.Dialog.prototype.validateFeedbackForm = function () {
+ var isValid = (
+ (
+ !this.useragentMandatory ||
+ this.useragentCheckbox.isSelected()
+ ) &&
+ this.feedbackSubjectInput.getValue()
+ );
+
+ this.actions.setAbilities( { submit: isValid } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.Feedback.Dialog.prototype.getBodyHeight = function () {
+ return this.feedbackPanel.$element.outerHeight( true );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.Feedback.Dialog.prototype.getSetupProcess = function ( data ) {
+ return mw.Feedback.Dialog.parent.prototype.getSetupProcess.call( this, data )
+ .next( function () {
+ var plainMsg, parsedMsg,
+ settings = data.settings;
+ data.contents = data.contents || {};
+
+ // Prefill subject/message
+ this.feedbackSubjectInput.setValue( data.contents.subject );
+ this.feedbackMessageInput.setValue( data.contents.message );
+
+ this.status = '';
+ this.messagePosterPromise = settings.messagePosterPromise;
+ this.setBugReportLink( settings.bugsTaskSubmissionLink );
+ this.feedbackPageTitle = settings.title;
+ this.feedbackPageName = settings.title.getNameText();
+ this.feedbackPageUrl = settings.title.getUrl();
+
+ // Useragent checkbox
+ if ( settings.useragentCheckbox.show ) {
+ this.useragentFieldLayout.setLabel( settings.useragentCheckbox.message );
+ }
+
+ this.useragentMandatory = settings.useragentCheckbox.mandatory;
+ this.useragentFieldLayout.toggle( settings.useragentCheckbox.show );
+
+ // HACK: Setting a link in the messages doesn't work. There is already a report
+ // about this, and the bug report offers a somewhat hacky work around that
+ // includes setting a separate message to be parsed.
+ // We want to make sure the user can configure both the title of the page and
+ // a separate url, so this must be allowed to parse correctly.
+ // See https://phabricator.wikimedia.org/T49395#490610
+ mw.messages.set( {
+ 'feedback-dialog-temporary-message':
+ '<a href="' + this.feedbackPageUrl + '" target="_blank">' + this.feedbackPageName + '</a>'
+ } );
+ plainMsg = mw.message( 'feedback-dialog-temporary-message' ).plain();
+ mw.messages.set( { 'feedback-dialog-temporary-message-parsed': plainMsg } );
+ parsedMsg = mw.message( 'feedback-dialog-temporary-message-parsed' );
+ this.feedbackMessageLabel.setLabel(
+ // Double-parse
+ $( '<span>' )
+ .append( mw.message( 'feedback-dialog-intro', parsedMsg ).parse() )
+ );
+
+ this.validateFeedbackForm();
+ }, this );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.Feedback.Dialog.prototype.getReadyProcess = function ( data ) {
+ return mw.Feedback.Dialog.parent.prototype.getReadyProcess.call( this, data )
+ .next( function () {
+ this.feedbackSubjectInput.focus();
+ }, this );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.Feedback.Dialog.prototype.getActionProcess = function ( action ) {
+ if ( action === 'cancel' ) {
+ return new OO.ui.Process( function () {
+ this.close( { action: action } );
+ }, this );
+ } else if ( action === 'external' ) {
+ return new OO.ui.Process( function () {
+ // Open in a new window
+ window.open( this.getBugReportLink(), '_blank' );
+ // Close the dialog
+ this.close();
+ }, this );
+ } else if ( action === 'submit' ) {
+ return new OO.ui.Process( function () {
+ var fb = this,
+ userAgentMessage = ':' +
+ '<small>' +
+ mw.msg( 'feedback-useragent' ) +
+ ' ' +
+ mw.html.escape( navigator.userAgent ) +
+ '</small>\n\n',
+ subject = this.feedbackSubjectInput.getValue(),
+ message = this.feedbackMessageInput.getValue();
+
+ // Add user agent if checkbox is selected
+ if ( this.useragentCheckbox.isSelected() ) {
+ message = userAgentMessage + message;
+ }
+
+ // Post the message
+ return this.messagePosterPromise.then( function ( poster ) {
+ return fb.postMessage( poster, subject, message );
+ }, function () {
+ fb.status = 'error4';
+ mw.log.warn( 'Feedback report failed because MessagePoster could not be fetched' );
+ } ).then( function () {
+ fb.close();
+ }, function () {
+ return fb.getErrorMessage();
+ } );
+ }, this );
+ }
+ // Fallback to parent handler
+ return mw.Feedback.Dialog.parent.prototype.getActionProcess.call( this, action );
+ };
+
+ /**
+ * Returns an error message for the current status.
+ *
+ * @private
+ *
+ * @return {OO.ui.Error}
+ */
+ mw.Feedback.Dialog.prototype.getErrorMessage = function () {
+ switch ( this.status ) {
+ case 'error1':
+ case 'error2':
+ case 'error3':
+ case 'error4':
+ // Messages: feedback-error1, feedback-error2, feedback-error3, feedback-error4
+ return new OO.ui.Error( mw.msg( 'feedback-' + this.status ) );
+ }
+ };
+
+ /**
+ * Posts the message
+ *
+ * @private
+ *
+ * @param {mw.messagePoster.MessagePoster} poster Poster implementation used to leave feedback
+ * @param {string} subject Subject of message
+ * @param {string} message Body of message
+ * @return {jQuery.Promise} Promise representing success of message posting action
+ */
+ mw.Feedback.Dialog.prototype.postMessage = function ( poster, subject, message ) {
+ var fb = this;
+
+ return poster.post(
+ subject,
+ message
+ ).then( function () {
+ fb.status = 'submitted';
+ }, function ( mainCode, secondaryCode, details ) {
+ if ( mainCode === 'api-fail' ) {
+ if ( secondaryCode === 'http' ) {
+ fb.status = 'error3';
+ // ajax request failed
+ mw.log.warn( 'Feedback report failed with HTTP error: ' + details.textStatus );
+ } else {
+ fb.status = 'error2';
+ mw.log.warn( 'Feedback report failed with API error: ' + secondaryCode );
+ }
+ } else {
+ fb.status = 'error1';
+ }
+ } );
+ };
+
+ /**
+ * @inheritdoc
+ */
+ mw.Feedback.Dialog.prototype.getTeardownProcess = function ( data ) {
+ return mw.Feedback.Dialog.parent.prototype.getTeardownProcess.call( this, data )
+ .first( function () {
+ this.emit( 'submit', this.status, this.feedbackPageName, this.feedbackPageUrl );
+ // Cleanup
+ this.status = '';
+ this.feedbackPageTitle = null;
+ this.feedbackSubjectInput.setValue( '' );
+ this.feedbackMessageInput.setValue( '' );
+ this.useragentCheckbox.setSelected( false );
+ }, this );
+ };
+
+ /**
+ * Set the bug report link
+ *
+ * @param {string} link Link to the external bug report form
+ */
+ mw.Feedback.Dialog.prototype.setBugReportLink = function ( link ) {
+ this.bugReportLink = link;
+ };
+
+ /**
+ * Get the bug report link
+ *
+ * @return {string} Link to the external bug report form
+ */
+ mw.Feedback.Dialog.prototype.getBugReportLink = function () {
+ return this.bugReportLink;
+ };
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.feedback.spinner.gif b/www/wiki/resources/src/mediawiki/mediawiki.feedback.spinner.gif
new file mode 100644
index 00000000..aed0ea41
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.feedback.spinner.gif
Binary files differ
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.feedlink.css b/www/wiki/resources/src/mediawiki/mediawiki.feedlink.css
new file mode 100644
index 00000000..37808d57
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.feedlink.css
@@ -0,0 +1,14 @@
+/* Styles for links to RSS/Atom feeds in sidebar */
+
+a.feedlink {
+ /* SVG support using a transparent gradient to guarantee cross-browser
+ * compatibility (browsers able to understand gradient syntax support also SVG).
+ * http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique */
+ background-image: url( images/feed-icon.png );
+ /* @embed */
+ background-image: linear-gradient( transparent, transparent ), url( images/feed-icon.svg );
+ background-position: center left;
+ background-repeat: no-repeat;
+ background-size: 12px 12px;
+ padding-left: 16px;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.filewarning.js b/www/wiki/resources/src/mediawiki/mediawiki.filewarning.js
new file mode 100644
index 00000000..72bf3d76
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.filewarning.js
@@ -0,0 +1,67 @@
+/*!
+ * mediawiki.filewarning
+ *
+ * @author Mark Holmquist, 2015
+ * @since 1.25
+ */
+( function ( mw, $, oo ) {
+ var warningConfig = mw.config.get( 'wgFileWarning' ),
+ warningMessages = warningConfig.messages,
+ warningLink = warningConfig.link,
+ $origMimetype = $( '.fullMedia .fileInfo .mime-type' ),
+ $mimetype = $origMimetype.clone(),
+ $header = $( '<h3>' )
+ .addClass( 'mediawiki-filewarning-header empty' ),
+ $main = $( '<p>' )
+ .addClass( 'mediawiki-filewarning-main empty' ),
+ $info = $( '<a>' )
+ .addClass( 'mediawiki-filewarning-info empty' ),
+ $footer = $( '<p>' )
+ .addClass( 'mediawiki-filewarning-footer empty' ),
+ dialog = new oo.ui.PopupButtonWidget( {
+ classes: [ 'mediawiki-filewarning-anchor' ],
+ label: $mimetype,
+ flags: [ 'warning' ],
+ icon: 'alert',
+ framed: false,
+ popup: {
+ classes: [ 'mediawiki-filewarning' ],
+ padded: true,
+ width: 400,
+ $content: $header.add( $main ).add( $info ).add( $footer )
+ }
+ } );
+
+ function loadMessage( $target, message ) {
+ if ( message ) {
+ $target.removeClass( 'empty' )
+ .text( mw.message( message ).text() );
+ }
+ }
+
+ // The main message must be populated for the dialog to show.
+ if ( warningConfig && warningConfig.messages && warningConfig.messages.main ) {
+ $mimetype.addClass( 'has-warning' );
+
+ $origMimetype.replaceWith( dialog.$element );
+
+ if ( warningMessages ) {
+ loadMessage( $main, warningMessages.main );
+ loadMessage( $header, warningMessages.header );
+ loadMessage( $footer, warningMessages.footer );
+
+ if ( warningLink ) {
+ loadMessage( $info, warningMessages.info );
+ $info.attr( 'href', warningLink );
+ }
+ }
+
+ // Make OOUI open the dialog, it won't appear until the user
+ // hovers over the warning.
+ dialog.getPopup().toggle( true );
+
+ // Override toggle handler because we don't need it for this popup
+ // object at all. Sort of nasty, but it gets the job done.
+ dialog.getPopup().toggle = $.noop;
+ }
+}( mediaWiki, jQuery, OO ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.filewarning.less b/www/wiki/resources/src/mediawiki/mediawiki.filewarning.less
new file mode 100644
index 00000000..bf9634f6
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.filewarning.less
@@ -0,0 +1,36 @@
+@import 'mediawiki.ui/variables';
+
+// Increase the area of the button, so that the user can move the mouse cursor
+// to the popup without the popup disappearing. (T157544)
+.mediawiki-filewarning-anchor {
+ padding-bottom: 10px;
+ margin-bottom: -10px;
+}
+
+.mediawiki-filewarning {
+ visibility: hidden;
+
+ .mediawiki-filewarning-header {
+ padding: 0;
+ font-weight: 600;
+ }
+
+ .mediawiki-filewarning-footer {
+ color: #72777d;
+ }
+
+ .empty {
+ display: none;
+ }
+
+ .mediawiki-filewarning-anchor:hover & {
+ visibility: visible;
+ }
+}
+
+.mime-type {
+ &.has-warning {
+ font-weight: bold;
+ color: @colorMediumSevere;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.helplink.less b/www/wiki/resources/src/mediawiki/mediawiki.helplink.less
new file mode 100644
index 00000000..4eed90ae
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.helplink.less
@@ -0,0 +1,11 @@
+@import 'mediawiki.mixins';
+
+#mw-indicator-mw-helplink a {
+ .background-image-svg('images/help.svg', 'images/help.png');
+ background-repeat: no-repeat;
+ background-position: left center;
+ padding-left: 28px;
+ display: inline-block;
+ height: 24px;
+ line-height: 24px;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.hidpi.js b/www/wiki/resources/src/mediawiki/mediawiki.hidpi.js
new file mode 100644
index 00000000..ecee450c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.hidpi.js
@@ -0,0 +1,5 @@
+jQuery( function ( $ ) {
+ // Apply hidpi images on DOM-ready
+ // Some may have already partly preloaded at low resolution.
+ $( 'body' ).hidpi();
+} );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.hlist-allskins.less b/www/wiki/resources/src/mediawiki/mediawiki.hlist-allskins.less
new file mode 100644
index 00000000..d7071e45
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.hlist-allskins.less
@@ -0,0 +1,21 @@
+.hlist {
+ dl,
+ ol,
+ ul {
+ margin: 0;
+ padding: 0;
+
+ dl,
+ ol,
+ ul {
+ display: inline;
+ }
+ }
+
+ dd,
+ dt,
+ li {
+ margin: 0;
+ display: inline;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.hlist.css b/www/wiki/resources/src/mediawiki/mediawiki.hlist.css
new file mode 100644
index 00000000..2663d873
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.hlist.css
@@ -0,0 +1,90 @@
+/*!
+ * Stylesheet for mediawiki.hlist module
+ * @author [[User:Edokter]]
+ */
+/* Generate interpuncts */
+.hlist dt:after {
+ content: ':';
+}
+.hlist dd:after,
+.hlist li:after {
+ content: ' ·';
+ font-weight: bold;
+}
+.hlist dd:last-child:after,
+.hlist dt:last-child:after,
+.hlist li:last-child:after {
+ content: none;
+}
+/* For IE8 */
+.hlist dd.hlist-last-child:after,
+.hlist dt.hlist-last-child:after,
+.hlist li.hlist-last-child:after {
+ content: none;
+}
+/* Add parentheses around nested lists */
+.hlist dd dd:first-child:before,
+.hlist dd dt:first-child:before,
+.hlist dd li:first-child:before,
+.hlist dt dd:first-child:before,
+.hlist dt dt:first-child:before,
+.hlist dt li:first-child:before,
+.hlist li dd:first-child:before,
+.hlist li dt:first-child:before,
+.hlist li li:first-child:before {
+ content: '(';
+ font-weight: normal;
+}
+.hlist dd dd:last-child:after,
+.hlist dd dt:last-child:after,
+.hlist dd li:last-child:after,
+.hlist dt dd:last-child:after,
+.hlist dt dt:last-child:after,
+.hlist dt li:last-child:after,
+.hlist li dd:last-child:after,
+.hlist li dt:last-child:after,
+.hlist li li:last-child:after {
+ content: ')';
+ font-weight: normal;
+}
+/* For IE8 */
+.hlist dd dd.hlist-last-child:after,
+.hlist dd dt.hlist-last-child:after,
+.hlist dd li.hlist-last-child:after,
+.hlist dt dd.hlist-last-child:after,
+.hlist dt dt.hlist-last-child:after,
+.hlist dt li.hlist-last-child:after,
+.hlist li dd.hlist-last-child:after,
+.hlist li dt.hlist-last-child:after,
+.hlist li li.hlist-last-child:after {
+ content: ')';
+ font-weight: normal;
+}
+/* Put ordinals in front of ordered list items */
+.hlist ol {
+ counter-reset: list-item;
+}
+.hlist ol > li {
+ counter-increment: list-item;
+}
+.hlist ol > li:before {
+ content: counter( list-item ) ' ';
+}
+.hlist dd ol > li:first-child:before,
+.hlist dt ol > li:first-child:before,
+.hlist li ol > li:first-child:before {
+ content: '(' counter( list-item ) ' ';
+}
+
+/* Support hlist styles inside *boxes */
+.errorbox .hlist,
+.successbox .hlist,
+.warningbox .hlist {
+ margin-left: 0;
+}
+
+.errorbox .hlist li:after,
+.successbox .hlist li:after,
+.warningbox .hlist li:after {
+ margin-right: 3px;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.htmlform.css b/www/wiki/resources/src/mediawiki/mediawiki.htmlform.css
new file mode 100644
index 00000000..c3341bb1
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.htmlform.css
@@ -0,0 +1,49 @@
+/* HTMLForm styles */
+
+table.mw-htmlform-nolabel td.mw-label {
+ display: none;
+}
+
+.mw-htmlform-invalid-input td.mw-input input {
+ border-color: red;
+}
+
+.mw-htmlform-flatlist div.mw-htmlform-flatlist-item {
+ display: inline;
+ margin-right: 1em;
+ white-space: nowrap;
+}
+
+/* HTMLCheckMatrix */
+
+.mw-htmlform-matrix td {
+ padding-left: 0.5em;
+ padding-right: 0.5em;
+}
+
+tr.mw-htmlform-vertical-label td.mw-label {
+ text-align: left !important;
+}
+
+.mw-icon-question {
+ /* SVG support using a transparent gradient to guarantee cross-browser
+ * compatibility (browsers able to understand gradient syntax support also SVG).
+ * http://pauginer.tumblr.com/post/36614680636/invisible-gradient-technique */
+ background-image: url(images/question.png);
+ /* @embed */
+ background-image: linear-gradient(transparent, transparent), url(images/question.svg);
+ background-repeat: no-repeat;
+ background-size: 13px 13px;
+ display: inline-block;
+ height: 13px;
+ width: 13px;
+ margin-left: 4px;
+}
+
+.mw-icon-question:lang(ar),
+.mw-icon-question:lang(fa),
+.mw-icon-question:lang(ur) {
+ -webkit-transform: scaleX(-1);
+ -ms-transform: scaleX(-1);
+ transform: scaleX(-1);
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.htmlform.js b/www/wiki/resources/src/mediawiki/mediawiki.htmlform.js
new file mode 100644
index 00000000..4cc7f09b
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.htmlform.js
@@ -0,0 +1,440 @@
+/**
+ * Utility functions for jazzing up HTMLForm elements.
+ *
+ * @class jQuery.plugin.htmlform
+ */
+( function ( mw, $ ) {
+
+ var cloneCounter = 0;
+
+ /**
+ * Helper function for hide-if to find the nearby form field.
+ *
+ * Find the closest match for the given name, "closest" being the minimum
+ * level of parents to go to find a form field matching the given name or
+ * ending in array keys matching the given name (e.g. "baz" matches
+ * "foo[bar][baz]").
+ *
+ * @private
+ * @param {jQuery} $el
+ * @param {string} name
+ * @return {jQuery|null}
+ */
+ function hideIfGetField( $el, name ) {
+ var $found, $p,
+ suffix = name.replace( /^([^\[]+)/, '[$1]' );
+
+ function nameFilter() {
+ return this.name === name ||
+ ( this.name === ( 'wp' + name ) ) ||
+ this.name.slice( -suffix.length ) === suffix;
+ }
+
+ for ( $p = $el.parent(); $p.length > 0; $p = $p.parent() ) {
+ $found = $p.find( '[name]' ).filter( nameFilter );
+ if ( $found.length ) {
+ return $found;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Helper function for hide-if to return a test function and list of
+ * dependent fields for a hide-if specification.
+ *
+ * @private
+ * @param {jQuery} $el
+ * @param {Array} spec
+ * @return {Array}
+ * @return {jQuery} return.0 Dependent fields
+ * @return {Function} return.1 Test function
+ */
+ function hideIfParse( $el, spec ) {
+ var op, i, l, v, $field, $fields, fields, func, funcs, getVal;
+
+ op = spec[ 0 ];
+ l = spec.length;
+ switch ( op ) {
+ case 'AND':
+ case 'OR':
+ case 'NAND':
+ case 'NOR':
+ funcs = [];
+ fields = [];
+ for ( i = 1; i < l; i++ ) {
+ if ( !$.isArray( spec[ i ] ) ) {
+ throw new Error( op + ' parameters must be arrays' );
+ }
+ v = hideIfParse( $el, spec[ i ] );
+ fields = fields.concat( v[ 0 ].toArray() );
+ funcs.push( v[ 1 ] );
+ }
+ $fields = $( fields );
+
+ l = funcs.length;
+ switch ( op ) {
+ case 'AND':
+ func = function () {
+ var i;
+ for ( i = 0; i < l; i++ ) {
+ if ( !funcs[ i ]() ) {
+ return false;
+ }
+ }
+ return true;
+ };
+ break;
+
+ case 'OR':
+ func = function () {
+ var i;
+ for ( i = 0; i < l; i++ ) {
+ if ( funcs[ i ]() ) {
+ return true;
+ }
+ }
+ return false;
+ };
+ break;
+
+ case 'NAND':
+ func = function () {
+ var i;
+ for ( i = 0; i < l; i++ ) {
+ if ( !funcs[ i ]() ) {
+ return true;
+ }
+ }
+ return false;
+ };
+ break;
+
+ case 'NOR':
+ func = function () {
+ var i;
+ for ( i = 0; i < l; i++ ) {
+ if ( funcs[ i ]() ) {
+ return false;
+ }
+ }
+ return true;
+ };
+ break;
+ }
+
+ return [ $fields, func ];
+
+ case 'NOT':
+ if ( l !== 2 ) {
+ throw new Error( 'NOT takes exactly one parameter' );
+ }
+ if ( !$.isArray( spec[ 1 ] ) ) {
+ throw new Error( 'NOT parameters must be arrays' );
+ }
+ v = hideIfParse( $el, spec[ 1 ] );
+ $fields = v[ 0 ];
+ func = v[ 1 ];
+ return [ $fields, function () {
+ return !func();
+ } ];
+
+ case '===':
+ case '!==':
+ if ( l !== 3 ) {
+ throw new Error( op + ' takes exactly two parameters' );
+ }
+ $field = hideIfGetField( $el, spec[ 1 ] );
+ if ( !$field ) {
+ return [ $(), function () {
+ return false;
+ } ];
+ }
+ v = spec[ 2 ];
+
+ if ( $field.first().prop( 'type' ) === 'radio' ||
+ $field.first().prop( 'type' ) === 'checkbox'
+ ) {
+ getVal = function () {
+ var $selected = $field.filter( ':checked' );
+ return $selected.length ? $selected.val() : '';
+ };
+ } else {
+ getVal = function () {
+ return $field.val();
+ };
+ }
+
+ switch ( op ) {
+ case '===':
+ func = function () {
+ return getVal() === v;
+ };
+ break;
+ case '!==':
+ func = function () {
+ return getVal() !== v;
+ };
+ break;
+ }
+
+ return [ $field, func ];
+
+ default:
+ throw new Error( 'Unrecognized operation \'' + op + '\'' );
+ }
+ }
+
+ /**
+ * jQuery plugin to fade or snap to visible state.
+ *
+ * @param {boolean} [instantToggle=false]
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.goIn = function ( instantToggle ) {
+ if ( instantToggle === true ) {
+ return this.show();
+ }
+ return this.stop( true, true ).fadeIn();
+ };
+
+ /**
+ * jQuery plugin to fade or snap to hiding state.
+ *
+ * @param {boolean} [instantToggle=false]
+ * @return {jQuery}
+ * @chainable
+ */
+ $.fn.goOut = function ( instantToggle ) {
+ if ( instantToggle === true ) {
+ return this.hide();
+ }
+ return this.stop( true, true ).fadeOut();
+ };
+
+ /**
+ * Bind a function to the jQuery object via live(), and also immediately trigger
+ * the function on the objects with an 'instant' parameter set to true.
+ *
+ * @method liveAndTestAtStart
+ * @deprecated since 1.24 Use .on() and .each() directly.
+ * @param {Function} callback
+ * @param {boolean|jQuery.Event} callback.immediate True when the event is called immediately,
+ * an event object when triggered from an event.
+ * @chainable
+ * @return {jQuery}
+ */
+ mw.log.deprecate( $.fn, 'liveAndTestAtStart', function ( callback ) {
+ return this
+ // Can't really migrate to .on() generically, needs knowledge of
+ // calling code to know the correct selector. Fix callers and
+ // get rid of this .liveAndTestAtStart() hack.
+ .live( 'change', callback )
+ .each( function () {
+ callback.call( this, true );
+ } );
+ } );
+
+ function enhance( $root ) {
+ var $matrixTooltips, $autocomplete,
+ // cache the separator to avoid object creation on each keypress
+ colonSeparator = mw.message( 'colon-separator' ).text();
+
+ /**
+ * @ignore
+ * @param {boolean|jQuery.Event} instant
+ */
+ function handleSelectOrOther( instant ) {
+ var $other = $root.find( '#' + $( this ).attr( 'id' ) + '-other' );
+ $other = $other.add( $other.siblings( 'br' ) );
+ if ( $( this ).val() === 'other' ) {
+ $other.goIn( instant );
+ } else {
+ $other.goOut( instant );
+ }
+ }
+
+ // Animate the SelectOrOther fields, to only show the text field when
+ // 'other' is selected.
+ $root
+ .on( 'change', '.mw-htmlform-select-or-other', handleSelectOrOther )
+ .each( function () {
+ handleSelectOrOther.call( this, true );
+ } );
+
+ // Add a dynamic max length to the reason field of SelectAndOther
+ // This checks the length together with the value from the select field
+ // When the reason list is changed and the bytelimit is longer than the allowed,
+ // nothing is done
+ $root
+ .find( '.mw-htmlform-select-and-other-field' )
+ .each( function () {
+ var $this = $( this ),
+ // find the reason list
+ $reasonList = $root.find( '#' + $this.data( 'id-select' ) ),
+ // cache the current selection to avoid expensive lookup
+ currentValReasonList = $reasonList.val();
+
+ $reasonList.change( function () {
+ currentValReasonList = $reasonList.val();
+ } );
+
+ $this.byteLimit( function ( input ) {
+ // Should be built the same as in HTMLSelectAndOtherField::loadDataFromRequest
+ var comment = currentValReasonList;
+ if ( comment === 'other' ) {
+ comment = input;
+ } else if ( input !== '' ) {
+ // Entry from drop down menu + additional comment
+ comment += colonSeparator + input;
+ }
+ return comment;
+ } );
+ } );
+
+ // Set up hide-if elements
+ $root.find( '.mw-htmlform-hide-if' ).each( function () {
+ var v, $fields, test, func,
+ $el = $( this ),
+ spec = $el.data( 'hideIf' );
+
+ if ( !spec ) {
+ return;
+ }
+
+ v = hideIfParse( $el, spec );
+ $fields = v[ 0 ];
+ test = v[ 1 ];
+ func = function () {
+ if ( test() ) {
+ $el.hide();
+ } else {
+ $el.show();
+ }
+ };
+ $fields.on( 'change', func );
+ func();
+ } );
+
+ function addMulti( $oldContainer, $container ) {
+ var name = $oldContainer.find( 'input:first-child' ).attr( 'name' ),
+ oldClass = ( ' ' + $oldContainer.attr( 'class' ) + ' ' ).replace( /(mw-htmlform-field-HTMLMultiSelectField|mw-chosen)/g, '' ),
+ $select = $( '<select>' ),
+ dataPlaceholder = mw.message( 'htmlform-chosen-placeholder' );
+ oldClass = $.trim( oldClass );
+ $select.attr( {
+ name: name,
+ multiple: 'multiple',
+ 'data-placeholder': dataPlaceholder.plain(),
+ 'class': 'htmlform-chzn-select mw-input ' + oldClass
+ } );
+ $oldContainer.find( 'input' ).each( function () {
+ var $oldInput = $( this ),
+ checked = $oldInput.prop( 'checked' ),
+ $option = $( '<option>' );
+ $option.prop( 'value', $oldInput.prop( 'value' ) );
+ if ( checked ) {
+ $option.prop( 'selected', true );
+ }
+ $option.text( $oldInput.prop( 'value' ) );
+ $select.append( $option );
+ } );
+ $container.append( $select );
+ }
+
+ function convertCheckboxesToMulti( $oldContainer, type ) {
+ var $fieldLabel = $( '<td>' ),
+ $td = $( '<td>' ),
+ $fieldLabelText = $( '<label>' ),
+ $container;
+ if ( type === 'tr' ) {
+ addMulti( $oldContainer, $td );
+ $container = $( '<tr>' );
+ $container.append( $td );
+ } else if ( type === 'div' ) {
+ $fieldLabel = $( '<div>' );
+ $container = $( '<div>' );
+ addMulti( $oldContainer, $container );
+ }
+ $fieldLabel.attr( 'class', 'mw-label' );
+ $fieldLabelText.text( $oldContainer.find( '.mw-label label' ).text() );
+ $fieldLabel.append( $fieldLabelText );
+ $container.prepend( $fieldLabel );
+ $oldContainer.replaceWith( $container );
+ return $container;
+ }
+
+ if ( $root.find( '.mw-chosen' ).length ) {
+ mw.loader.using( 'jquery.chosen', function () {
+ $root.find( '.mw-chosen' ).each( function () {
+ var type = this.nodeName.toLowerCase(),
+ $converted = convertCheckboxesToMulti( $( this ), type );
+ $converted.find( '.htmlform-chzn-select' ).chosen( { width: 'auto' } );
+ } );
+ } );
+ }
+
+ $matrixTooltips = $root.find( '.mw-htmlform-matrix .mw-htmlform-tooltip' );
+ if ( $matrixTooltips.length ) {
+ mw.loader.using( 'jquery.tipsy', function () {
+ $matrixTooltips.tipsy( { gravity: 's' } );
+ } );
+ }
+
+ // Set up autocomplete fields
+ $autocomplete = $root.find( '.mw-htmlform-autocomplete' );
+ if ( $autocomplete.length ) {
+ mw.loader.using( 'jquery.suggestions', function () {
+ $autocomplete.suggestions( {
+ fetch: function ( val ) {
+ var $el = $( this );
+ $el.suggestions( 'suggestions',
+ $.grep( $el.data( 'autocomplete' ), function ( v ) {
+ return v.indexOf( val ) === 0;
+ } )
+ );
+ }
+ } );
+ } );
+ }
+
+ // Add/remove cloner clones without having to resubmit the form
+ $root.find( '.mw-htmlform-cloner-delete-button' ).filter( ':input' ).click( function ( ev ) {
+ ev.preventDefault();
+ $( this ).closest( 'li.mw-htmlform-cloner-li' ).remove();
+ } );
+
+ $root.find( '.mw-htmlform-cloner-create-button' ).filter( ':input' ).click( function ( ev ) {
+ var $ul, $li, html;
+
+ ev.preventDefault();
+
+ $ul = $( this ).prev( 'ul.mw-htmlform-cloner-ul' );
+
+ html = $ul.data( 'template' ).replace(
+ new RegExp( mw.RegExp.escape( $ul.data( 'uniqueId' ) ), 'g' ),
+ 'clone' + ( ++cloneCounter )
+ );
+
+ $li = $( '<li>' )
+ .addClass( 'mw-htmlform-cloner-li' )
+ .html( html )
+ .appendTo( $ul );
+
+ enhance( $li );
+ } );
+
+ mw.hook( 'htmlform.enhance' ).fire( $root );
+
+ }
+
+ $( function () {
+ enhance( $( document ) );
+ } );
+
+ /**
+ * @class jQuery
+ * @mixins jQuery.plugin.htmlform
+ */
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.htmlform.ooui.css b/www/wiki/resources/src/mediawiki/mediawiki.htmlform.ooui.css
new file mode 100644
index 00000000..260fd37e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.htmlform.ooui.css
@@ -0,0 +1,34 @@
+/* OOUIHTMLForm styles */
+
+.mw-htmlform-ooui-wrapper {
+ margin: 1em 0;
+}
+
+.oo-ui-fieldLayout.mw-htmlform-ooui-header-empty,
+.oo-ui-fieldLayout.mw-htmlform-ooui-header-empty .oo-ui-fieldLayout-body {
+ display: none;
+}
+
+.oo-ui-fieldLayout.mw-htmlform-ooui-header-errors {
+ /* Override 'display: none' from above */
+ display: block;
+}
+
+.mw-htmlform-ooui .mw-htmlform-submit-buttons {
+ margin-top: 1em;
+}
+
+.mw-htmlform-ooui .mw-htmlform-field-HTMLCheckMatrix,
+.mw-htmlform-ooui .mw-htmlform-matrix,
+.mw-htmlform-ooui .mw-htmlform-matrix tr {
+ width: 100%;
+}
+
+.mw-htmlform-ooui .mw-htmlform-matrix tr td.first {
+ margin-right: 5%;
+ width: 39%;
+}
+
+.oo-ui-fieldLayout .oo-ui-fieldLayout.oo-ui-fieldLayout-align-inline {
+ margin-bottom: 0;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.icon.less b/www/wiki/resources/src/mediawiki/mediawiki.icon.less
new file mode 100644
index 00000000..c6925388
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.icon.less
@@ -0,0 +1,19 @@
+/* General-purpose icons via CSS. Classes here should be named "mw-icon-*". */
+
+@import 'mediawiki.mixins';
+
+/* For the collapsed and expanded arrows, we also provide selectors to make it
+ * easy to use them with jquery.makeCollapsible. */
+.mw-icon-arrow-collapsed,
+.mw-collapsible-arrow.mw-collapsible-toggle-collapsed {
+ .background-image-svg('images/arrow-collapsed-ltr.svg', 'images/arrow-collapsed-ltr.png');
+ background-repeat: no-repeat;
+ background-position: left bottom;
+}
+
+.mw-icon-arrow-expanded,
+.mw-collapsible-arrow.mw-collapsible-toggle-expanded {
+ .background-image-svg('images/arrow-expanded.svg', 'images/arrow-expanded.png');
+ background-repeat: no-repeat;
+ background-position: left bottom;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.inspect.js b/www/wiki/resources/src/mediawiki/mediawiki.inspect.js
new file mode 100644
index 00000000..9332773e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.inspect.js
@@ -0,0 +1,337 @@
+/*!
+ * Tools for inspecting page composition and performance.
+ *
+ * @author Ori Livneh
+ * @since 1.22
+ */
+
+/* eslint-disable no-console */
+
+( function ( mw, $ ) {
+
+ var inspect,
+ hasOwn = Object.prototype.hasOwnProperty;
+
+ function sortByProperty( array, prop, descending ) {
+ var order = descending ? -1 : 1;
+ return array.sort( function ( a, b ) {
+ return a[ prop ] > b[ prop ] ? order : a[ prop ] < b[ prop ] ? -order : 0;
+ } );
+ }
+
+ function humanSize( bytes ) {
+ var i,
+ units = [ '', ' KiB', ' MiB', ' GiB', ' TiB', ' PiB' ];
+
+ if ( !$.isNumeric( bytes ) || bytes === 0 ) { return bytes; }
+
+ for ( i = 0; bytes >= 1024; bytes /= 1024 ) { i++; }
+ // Maintain one decimal for kB and above, but don't
+ // add ".0" for bytes.
+ return bytes.toFixed( i > 0 ? 1 : 0 ) + units[ i ];
+ }
+
+ /**
+ * @class mw.inspect
+ * @singleton
+ */
+ inspect = {
+
+ /**
+ * Return a map of all dependency relationships between loaded modules.
+ *
+ * @return {Object} Maps module names to objects. Each sub-object has
+ * two properties, 'requires' and 'requiredBy'.
+ */
+ getDependencyGraph: function () {
+ var modules = inspect.getLoadedModules(),
+ graph = {};
+
+ $.each( modules, function ( moduleIndex, moduleName ) {
+ var dependencies = mw.loader.moduleRegistry[ moduleName ].dependencies || [];
+
+ if ( !hasOwn.call( graph, moduleName ) ) {
+ graph[ moduleName ] = { requiredBy: [] };
+ }
+ graph[ moduleName ].requires = dependencies;
+
+ $.each( dependencies, function ( depIndex, depName ) {
+ if ( !hasOwn.call( graph, depName ) ) {
+ graph[ depName ] = { requiredBy: [] };
+ }
+ graph[ depName ].requiredBy.push( moduleName );
+ } );
+ } );
+ return graph;
+ },
+
+ /**
+ * Calculate the byte size of a ResourceLoader module.
+ *
+ * @param {string} moduleName The name of the module
+ * @return {number|null} Module size in bytes or null
+ */
+ getModuleSize: function ( moduleName ) {
+ var module = mw.loader.moduleRegistry[ moduleName ],
+ args, i, size;
+
+ if ( module.state !== 'ready' ) {
+ return null;
+ }
+
+ if ( !module.style && !module.script ) {
+ return 0;
+ }
+
+ function getFunctionBody( func ) {
+ return String( func )
+ // To ensure a deterministic result, replace the start of the function
+ // declaration with a fixed string. For example, in Chrome 55, it seems
+ // V8 seemingly-at-random decides to sometimes put a line break between
+ // the opening brace and first statement of the function body. T159751.
+ .replace( /^\s*function\s*\([^)]*\)\s*{\s*/, 'function(){' )
+ .replace( /\s*}\s*$/, '}' );
+ }
+
+ // Based on the load.php response for this module.
+ // For example: `mw.loader.implement("example", function(){}, {"css":[".x{color:red}"]});`
+ // @see mw.loader.store.set().
+ args = [
+ moduleName,
+ module.script,
+ module.style,
+ module.messages,
+ module.templates
+ ];
+ // Trim trailing null or empty object, as load.php would have done.
+ // @see ResourceLoader::makeLoaderImplementScript and ResourceLoader::trimArray.
+ i = args.length;
+ while ( i-- ) {
+ if ( args[ i ] === null || ( $.isPlainObject( args[ i ] ) && $.isEmptyObject( args[ i ] ) ) ) {
+ args.splice( i, 1 );
+ } else {
+ break;
+ }
+ }
+
+ size = 0;
+ for ( i = 0; i < args.length; i++ ) {
+ if ( typeof args[ i ] === 'function' ) {
+ size += $.byteLength( getFunctionBody( args[ i ] ) );
+ } else {
+ size += $.byteLength( JSON.stringify( args[ i ] ) );
+ }
+ }
+
+ return size;
+ },
+
+ /**
+ * Given CSS source, count both the total number of selectors it
+ * contains and the number which match some element in the current
+ * document.
+ *
+ * @param {string} css CSS source
+ * @return {Object} Selector counts
+ * @return {number} return.selectors Total number of selectors
+ * @return {number} return.matched Number of matched selectors
+ */
+ auditSelectors: function ( css ) {
+ var selectors = { total: 0, matched: 0 },
+ style = document.createElement( 'style' );
+
+ style.textContent = css;
+ document.body.appendChild( style );
+ $.each( style.sheet.cssRules, function ( index, rule ) {
+ selectors.total++;
+ // document.querySelector() on prefixed pseudo-elements can throw exceptions
+ // in Firefox and Safari. Ignore these exceptions.
+ // https://bugs.webkit.org/show_bug.cgi?id=149160
+ // https://bugzilla.mozilla.org/show_bug.cgi?id=1204880
+ try {
+ if ( document.querySelector( rule.selectorText ) !== null ) {
+ selectors.matched++;
+ }
+ } catch ( e ) {}
+ } );
+ document.body.removeChild( style );
+ return selectors;
+ },
+
+ /**
+ * Get a list of all loaded ResourceLoader modules.
+ *
+ * @return {Array} List of module names
+ */
+ getLoadedModules: function () {
+ return $.grep( mw.loader.getModuleNames(), function ( module ) {
+ return mw.loader.getState( module ) === 'ready';
+ } );
+ },
+
+ /**
+ * Print tabular data to the console, using console.table, console.log,
+ * or mw.log (in declining order of preference).
+ *
+ * @param {Array} data Tabular data represented as an array of objects
+ * with common properties.
+ */
+ dumpTable: function ( data ) {
+ try {
+ // Bartosz made me put this here.
+ if ( window.opera ) { throw window.opera; }
+ // Use Function.prototype#call to force an exception on Firefox,
+ // which doesn't define console#table but doesn't complain if you
+ // try to invoke it.
+ // eslint-disable-next-line no-useless-call
+ console.table.call( console, data );
+ return;
+ } catch ( e ) {}
+ try {
+ console.log( JSON.stringify( data, null, 2 ) );
+ return;
+ } catch ( e ) {}
+ mw.log( data );
+ },
+
+ /**
+ * Generate and print one more reports. When invoked with no arguments,
+ * print all reports.
+ *
+ * @param {...string} [reports] Report names to run, or unset to print
+ * all available reports.
+ */
+ runReports: function () {
+ var reports = arguments.length > 0 ?
+ Array.prototype.slice.call( arguments ) :
+ $.map( inspect.reports, function ( v, k ) { return k; } );
+
+ $.each( reports, function ( index, name ) {
+ inspect.dumpTable( inspect.reports[ name ]() );
+ } );
+ },
+
+ /**
+ * @class mw.inspect.reports
+ * @singleton
+ */
+ reports: {
+ /**
+ * Generate a breakdown of all loaded modules and their size in
+ * kilobytes. Modules are ordered from largest to smallest.
+ *
+ * @return {Object[]} Size reports
+ */
+ size: function () {
+ // Map each module to a descriptor object.
+ var modules = $.map( inspect.getLoadedModules(), function ( module ) {
+ return {
+ name: module,
+ size: inspect.getModuleSize( module )
+ };
+ } );
+
+ // Sort module descriptors by size, largest first.
+ sortByProperty( modules, 'size', true );
+
+ // Convert size to human-readable string.
+ $.each( modules, function ( i, module ) {
+ module.sizeInBytes = module.size;
+ module.size = humanSize( module.size );
+ } );
+
+ return modules;
+ },
+
+ /**
+ * For each module with styles, count the number of selectors, and
+ * count how many match against some element currently in the DOM.
+ *
+ * @return {Object[]} CSS reports
+ */
+ css: function () {
+ var modules = [];
+
+ $.each( inspect.getLoadedModules(), function ( index, name ) {
+ var css, stats, module = mw.loader.moduleRegistry[ name ];
+
+ try {
+ css = module.style.css.join();
+ } catch ( e ) { return; } // skip
+
+ stats = inspect.auditSelectors( css );
+ modules.push( {
+ module: name,
+ allSelectors: stats.total,
+ matchedSelectors: stats.matched,
+ percentMatched: stats.total !== 0 ?
+ ( stats.matched / stats.total * 100 ).toFixed( 2 ) + '%' : null
+ } );
+ } );
+ sortByProperty( modules, 'allSelectors', true );
+ return modules;
+ },
+
+ /**
+ * Report stats on mw.loader.store: the number of localStorage
+ * cache hits and misses, the number of items purged from the
+ * cache, and the total size of the module blob in localStorage.
+ *
+ * @return {Object[]} Store stats
+ */
+ store: function () {
+ var raw, stats = { enabled: mw.loader.store.enabled };
+ if ( stats.enabled ) {
+ $.extend( stats, mw.loader.store.stats );
+ try {
+ raw = localStorage.getItem( mw.loader.store.getStoreKey() );
+ stats.totalSizeInBytes = $.byteLength( raw );
+ stats.totalSize = humanSize( $.byteLength( raw ) );
+ } catch ( e ) {}
+ }
+ return [ stats ];
+ }
+ },
+
+ /**
+ * Perform a string search across the JavaScript and CSS source code
+ * of all loaded modules and return an array of the names of the
+ * modules that matched.
+ *
+ * @param {string|RegExp} pattern String or regexp to match.
+ * @return {Array} Array of the names of modules that matched.
+ */
+ grep: function ( pattern ) {
+ if ( typeof pattern.test !== 'function' ) {
+ pattern = new RegExp( mw.RegExp.escape( pattern ), 'g' );
+ }
+
+ return $.grep( inspect.getLoadedModules(), function ( moduleName ) {
+ var module = mw.loader.moduleRegistry[ moduleName ];
+
+ // Grep module's JavaScript
+ if ( $.isFunction( module.script ) && pattern.test( module.script.toString() ) ) {
+ return true;
+ }
+
+ // Grep module's CSS
+ if (
+ $.isPlainObject( module.style ) && Array.isArray( module.style.css ) &&
+ pattern.test( module.style.css.join( '' ) )
+ ) {
+ // Module's CSS source matches
+ return true;
+ }
+
+ return false;
+ } );
+ }
+ };
+
+ if ( mw.config.get( 'debug' ) ) {
+ mw.log( 'mw.inspect: reports are not available in debug mode.' );
+ }
+
+ mw.inspect = inspect;
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.jqueryMsg.js b/www/wiki/resources/src/mediawiki/mediawiki.jqueryMsg.js
new file mode 100644
index 00000000..e1681fa2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.jqueryMsg.js
@@ -0,0 +1,1390 @@
+/*!
+* Experimental advanced wikitext parser-emitter.
+* See: https://www.mediawiki.org/wiki/Extension:UploadWizard/MessageParser for docs
+*
+* @author neilk@wikimedia.org
+* @author mflaschen@wikimedia.org
+*/
+( function ( mw, $ ) {
+ /**
+ * @class mw.jqueryMsg
+ * @singleton
+ */
+
+ var oldParser,
+ slice = Array.prototype.slice,
+ parserDefaults = {
+ magic: {
+ PAGENAME: mw.config.get( 'wgPageName' ),
+ PAGENAMEE: mw.util.wikiUrlencode( mw.config.get( 'wgPageName' ) )
+ },
+ // Whitelist for allowed HTML elements in wikitext.
+ // Self-closing tags are not currently supported.
+ // Can be populated via setPrivateData().
+ allowedHtmlElements: [],
+ // Key tag name, value allowed attributes for that tag.
+ // See Sanitizer::setupAttributeWhitelist
+ allowedHtmlCommonAttributes: [
+ // HTML
+ 'id',
+ 'class',
+ 'style',
+ 'lang',
+ 'dir',
+ 'title',
+
+ // WAI-ARIA
+ 'role'
+ ],
+
+ // Attributes allowed for specific elements.
+ // Key is element name in lower case
+ // Value is array of allowed attributes for that element
+ allowedHtmlAttributesByElement: {},
+ messages: mw.messages,
+ language: mw.language,
+
+ // Same meaning as in mediawiki.js.
+ //
+ // Only 'text', 'parse', and 'escaped' are supported, and the
+ // actual escaping for 'escaped' is done by other code (generally
+ // through mediawiki.js).
+ //
+ // However, note that this default only
+ // applies to direct calls to jqueryMsg. The default for mediawiki.js itself
+ // is 'text', including when it uses jqueryMsg.
+ format: 'parse'
+ };
+
+ /**
+ * Wrapper around jQuery append that converts all non-objects to TextNode so append will not
+ * convert what it detects as an htmlString to an element.
+ *
+ * If our own htmlEmitter jQuery object is given, its children will be unwrapped and appended to
+ * new parent.
+ *
+ * Object elements of children (jQuery, HTMLElement, TextNode, etc.) will be left as is.
+ *
+ * @private
+ * @param {jQuery} $parent Parent node wrapped by jQuery
+ * @param {Object|string|Array} children What to append, with the same possible types as jQuery
+ * @return {jQuery} $parent
+ */
+ function appendWithoutParsing( $parent, children ) {
+ var i, len;
+
+ if ( !Array.isArray( children ) ) {
+ children = [ children ];
+ }
+
+ for ( i = 0, len = children.length; i < len; i++ ) {
+ if ( typeof children[ i ] !== 'object' ) {
+ children[ i ] = document.createTextNode( children[ i ] );
+ }
+ if ( children[ i ] instanceof jQuery && children[ i ].hasClass( 'mediaWiki_htmlEmitter' ) ) {
+ children[ i ] = children[ i ].contents();
+ }
+ }
+
+ return $parent.append( children );
+ }
+
+ /**
+ * Decodes the main HTML entities, those encoded by mw.html.escape.
+ *
+ * @private
+ * @param {string} encoded Encoded string
+ * @return {string} String with those entities decoded
+ */
+ function decodePrimaryHtmlEntities( encoded ) {
+ return encoded
+ .replace( /&#039;/g, '\'' )
+ .replace( /&quot;/g, '"' )
+ .replace( /&lt;/g, '<' )
+ .replace( /&gt;/g, '>' )
+ .replace( /&amp;/g, '&' );
+ }
+
+ /**
+ * Turn input into a string.
+ *
+ * @private
+ * @param {string|jQuery} input
+ * @return {string} Textual value of input
+ */
+ function textify( input ) {
+ if ( input instanceof jQuery ) {
+ input = input.text();
+ }
+ return String( input );
+ }
+
+ /**
+ * Given parser options, return a function that parses a key and replacements, returning jQuery object
+ *
+ * Try to parse a key and optional replacements, returning a jQuery object that may be a tree of jQuery nodes.
+ * If there was an error parsing, return the key and the error message (wrapped in jQuery). This should put the error right into
+ * the interface, without causing the page to halt script execution, and it hopefully should be clearer how to fix it.
+ *
+ * @private
+ * @param {Object} options Parser options
+ * @return {Function}
+ * @return {Array} return.args First element is the key, replacements may be in array in 2nd element, or remaining elements.
+ * @return {jQuery} return.return
+ */
+ function getFailableParserFn( options ) {
+ return function ( args ) {
+ var fallback,
+ // eslint-disable-next-line new-cap
+ parser = new mw.jqueryMsg.parser( options ),
+ key = args[ 0 ],
+ argsArray = Array.isArray( args[ 1 ] ) ? args[ 1 ] : slice.call( args, 1 );
+ try {
+ return parser.parse( key, argsArray );
+ } catch ( e ) {
+ fallback = parser.settings.messages.get( key );
+ mw.log.warn( 'mediawiki.jqueryMsg: ' + key + ': ' + e.message );
+ mw.track( 'mediawiki.jqueryMsg.error', {
+ messageKey: key,
+ errorMessage: e.message
+ } );
+ return $( '<span>' ).text( fallback );
+ }
+ };
+ }
+
+ mw.jqueryMsg = {};
+
+ /**
+ * Initialize parser defaults.
+ *
+ * ResourceLoaderJqueryMsgModule calls this to provide default values from
+ * Sanitizer.php for allowed HTML elements. To override this data for individual
+ * parsers, pass the relevant options to mw.jqueryMsg.parser.
+ *
+ * @private
+ * @param {Object} data New data to extend parser defaults with
+ * @param {boolean} [deep=false] Whether the extend is done recursively (deep)
+ */
+ mw.jqueryMsg.setParserDefaults = function ( data, deep ) {
+ if ( deep ) {
+ $.extend( true, parserDefaults, data );
+ } else {
+ $.extend( parserDefaults, data );
+ }
+ };
+
+ /**
+ * Get current parser defaults.
+ *
+ * Primarily used for the unit test. Returns a copy.
+ *
+ * @private
+ * @return {Object}
+ */
+ mw.jqueryMsg.getParserDefaults = function () {
+ return $.extend( {}, parserDefaults );
+ };
+
+ /**
+ * Returns a function suitable for use as a global, to construct strings from the message key (and optional replacements).
+ * e.g.
+ *
+ * window.gM = mediaWiki.jqueryMsg.getMessageFunction( options );
+ * $( 'p#headline' ).html( gM( 'hello-user', username ) );
+ *
+ * Like the old gM() function this returns only strings, so it destroys any bindings. If you want to preserve bindings use the
+ * jQuery plugin version instead. This is only included for backwards compatibility with gM().
+ *
+ * N.B. replacements are variadic arguments or an array in second parameter. In other words:
+ * somefunction( a, b, c, d )
+ * is equivalent to
+ * somefunction( a, [b, c, d] )
+ *
+ * @param {Object} options parser options
+ * @return {Function} Function suitable for assigning to window.gM
+ * @return {string} return.key Message key.
+ * @return {Array|Mixed} return.replacements Optional variable replacements (variadically or an array).
+ * @return {string} return.return Rendered HTML.
+ */
+ mw.jqueryMsg.getMessageFunction = function ( options ) {
+ var failableParserFn, format;
+
+ if ( options && options.format !== undefined ) {
+ format = options.format;
+ } else {
+ format = parserDefaults.format;
+ }
+
+ return function () {
+ var failableResult;
+ if ( !failableParserFn ) {
+ failableParserFn = getFailableParserFn( options );
+ }
+ failableResult = failableParserFn( arguments );
+ if ( format === 'text' || format === 'escaped' ) {
+ return failableResult.text();
+ } else {
+ return failableResult.html();
+ }
+ };
+ };
+
+ /**
+ * Returns a jQuery plugin which parses the message in the message key, doing replacements optionally, and appends the nodes to
+ * the current selector. Bindings to passed-in jquery elements are preserved. Functions become click handlers for [$1 linktext] links.
+ * e.g.
+ *
+ * $.fn.msg = mediaWiki.jqueryMsg.getPlugin( options );
+ * var userlink = $( '<a>' ).click( function () { alert( "hello!!" ) } );
+ * $( 'p#headline' ).msg( 'hello-user', userlink );
+ *
+ * N.B. replacements are variadic arguments or an array in second parameter. In other words:
+ * somefunction( a, b, c, d )
+ * is equivalent to
+ * somefunction( a, [b, c, d] )
+ *
+ * We append to 'this', which in a jQuery plugin context will be the selected elements.
+ *
+ * @param {Object} options Parser options
+ * @return {Function} Function suitable for assigning to jQuery plugin, such as jQuery#msg
+ * @return {string} return.key Message key.
+ * @return {Array|Mixed} return.replacements Optional variable replacements (variadically or an array).
+ * @return {jQuery} return.return
+ */
+ mw.jqueryMsg.getPlugin = function ( options ) {
+ var failableParserFn;
+
+ return function () {
+ var $target;
+ if ( !failableParserFn ) {
+ failableParserFn = getFailableParserFn( options );
+ }
+ $target = this.empty();
+ appendWithoutParsing( $target, failableParserFn( arguments ) );
+ return $target;
+ };
+ };
+
+ /**
+ * The parser itself.
+ * Describes an object, whose primary duty is to .parse() message keys.
+ *
+ * @class
+ * @private
+ * @param {Object} options
+ */
+ mw.jqueryMsg.parser = function ( options ) {
+ this.settings = $.extend( {}, parserDefaults, options );
+ this.settings.onlyCurlyBraceTransform = ( this.settings.format === 'text' || this.settings.format === 'escaped' );
+ this.astCache = {};
+
+ // eslint-disable-next-line new-cap
+ this.emitter = new mw.jqueryMsg.htmlEmitter( this.settings.language, this.settings.magic );
+ };
+
+ mw.jqueryMsg.parser.prototype = {
+ /**
+ * Where the magic happens.
+ * Parses a message from the key, and swaps in replacements as necessary, wraps in jQuery
+ * If an error is thrown, returns original key, and logs the error
+ *
+ * @param {string} key Message key.
+ * @param {Array} replacements Variable replacements for $1, $2... $n
+ * @return {jQuery}
+ */
+ parse: function ( key, replacements ) {
+ var ast = this.getAst( key );
+ return this.emitter.emit( ast, replacements );
+ },
+
+ /**
+ * Fetch the message string associated with a key, return parsed structure. Memoized.
+ * Note that we pass '⧼' + key + '⧽' back for a missing message here.
+ *
+ * @param {string} key
+ * @return {string|Array} string of '⧼key⧽' if message missing, simple string if possible, array of arrays if needs parsing
+ */
+ getAst: function ( key ) {
+ var wikiText;
+
+ if ( !this.astCache.hasOwnProperty( key ) ) {
+ wikiText = this.settings.messages.get( key );
+ if ( typeof wikiText !== 'string' ) {
+ wikiText = '⧼' + key + '⧽';
+ }
+ this.astCache[ key ] = this.wikiTextToAst( wikiText );
+ }
+ return this.astCache[ key ];
+ },
+
+ /**
+ * Parses the input wikiText into an abstract syntax tree, essentially an s-expression.
+ *
+ * CAVEAT: This does not parse all wikitext. It could be more efficient, but it's pretty good already.
+ * n.b. We want to move this functionality to the server. Nothing here is required to be on the client.
+ *
+ * @param {string} input Message string wikitext
+ * @throws Error
+ * @return {Mixed} abstract syntax tree
+ */
+ wikiTextToAst: function ( input ) {
+ var pos,
+ regularLiteral, regularLiteralWithoutBar, regularLiteralWithoutSpace, regularLiteralWithSquareBrackets,
+ doubleQuote, singleQuote, backslash, anyCharacter, asciiAlphabetLiteral,
+ escapedOrLiteralWithoutSpace, escapedOrLiteralWithoutBar, escapedOrRegularLiteral,
+ whitespace, dollar, digits, htmlDoubleQuoteAttributeValue, htmlSingleQuoteAttributeValue,
+ htmlAttributeEquals, openHtmlStartTag, optionalForwardSlash, openHtmlEndTag, closeHtmlTag,
+ openExtlink, closeExtlink, wikilinkContents, openWikilink, closeWikilink, templateName, pipe, colon,
+ templateContents, openTemplate, closeTemplate,
+ nonWhitespaceExpression, paramExpression, expression, curlyBraceTransformExpression, result,
+ settings = this.settings,
+ concat = Array.prototype.concat;
+
+ // Indicates current position in input as we parse through it.
+ // Shared among all parsing functions below.
+ pos = 0;
+
+ // =========================================================
+ // parsing combinators - could be a library on its own
+ // =========================================================
+
+ /**
+ * Try parsers until one works, if none work return null
+ *
+ * @private
+ * @param {Function[]} ps
+ * @return {string|null}
+ */
+ function choice( ps ) {
+ return function () {
+ var i, result;
+ for ( i = 0; i < ps.length; i++ ) {
+ result = ps[ i ]();
+ if ( result !== null ) {
+ return result;
+ }
+ }
+ return null;
+ };
+ }
+
+ /**
+ * Try several ps in a row, all must succeed or return null.
+ * This is the only eager one.
+ *
+ * @private
+ * @param {Function[]} ps
+ * @return {string|null}
+ */
+ function sequence( ps ) {
+ var i, res,
+ originalPos = pos,
+ result = [];
+ for ( i = 0; i < ps.length; i++ ) {
+ res = ps[ i ]();
+ if ( res === null ) {
+ pos = originalPos;
+ return null;
+ }
+ result.push( res );
+ }
+ return result;
+ }
+
+ /**
+ * Run the same parser over and over until it fails.
+ * Must succeed a minimum of n times or return null.
+ *
+ * @private
+ * @param {number} n
+ * @param {Function} p
+ * @return {string|null}
+ */
+ function nOrMore( n, p ) {
+ return function () {
+ var originalPos = pos,
+ result = [],
+ parsed = p();
+ while ( parsed !== null ) {
+ result.push( parsed );
+ parsed = p();
+ }
+ if ( result.length < n ) {
+ pos = originalPos;
+ return null;
+ }
+ return result;
+ };
+ }
+
+ /**
+ * There is a general pattern -- parse a thing, if that worked, apply transform, otherwise return null.
+ *
+ * TODO: But using this as a combinator seems to cause problems when combined with #nOrMore().
+ * May be some scoping issue
+ *
+ * @private
+ * @param {Function} p
+ * @param {Function} fn
+ * @return {string|null}
+ */
+ function transform( p, fn ) {
+ return function () {
+ var result = p();
+ return result === null ? null : fn( result );
+ };
+ }
+
+ /**
+ * Just make parsers out of simpler JS builtin types
+ *
+ * @private
+ * @param {string} s
+ * @return {Function}
+ * @return {string} return.return
+ */
+ function makeStringParser( s ) {
+ var len = s.length;
+ return function () {
+ var result = null;
+ if ( input.substr( pos, len ) === s ) {
+ result = s;
+ pos += len;
+ }
+ return result;
+ };
+ }
+
+ /**
+ * Makes a regex parser, given a RegExp object.
+ * The regex being passed in should start with a ^ to anchor it to the start
+ * of the string.
+ *
+ * @private
+ * @param {RegExp} regex anchored regex
+ * @return {Function} function to parse input based on the regex
+ */
+ function makeRegexParser( regex ) {
+ return function () {
+ var matches = input.slice( pos ).match( regex );
+ if ( matches === null ) {
+ return null;
+ }
+ pos += matches[ 0 ].length;
+ return matches[ 0 ];
+ };
+ }
+
+ // ===================================================================
+ // General patterns above this line -- wikitext specific parsers below
+ // ===================================================================
+
+ // Parsing functions follow. All parsing functions work like this:
+ // They don't accept any arguments.
+ // Instead, they just operate non destructively on the string 'input'
+ // As they can consume parts of the string, they advance the shared variable pos,
+ // and return tokens (or whatever else they want to return).
+ // some things are defined as closures and other things as ordinary functions
+ // converting everything to a closure makes it a lot harder to debug... errors pop up
+ // but some debuggers can't tell you exactly where they come from. Also the mutually
+ // recursive functions seem not to work in all browsers then. (Tested IE6-7, Opera, Safari, FF)
+ // This may be because, to save code, memoization was removed
+
+ /* eslint-disable no-useless-escape */
+ regularLiteral = makeRegexParser( /^[^{}\[\]$<\\]/ );
+ regularLiteralWithoutBar = makeRegexParser( /^[^{}\[\]$\\|]/ );
+ regularLiteralWithoutSpace = makeRegexParser( /^[^{}\[\]$\s]/ );
+ regularLiteralWithSquareBrackets = makeRegexParser( /^[^{}$\\]/ );
+ /* eslint-enable no-useless-escape */
+
+ backslash = makeStringParser( '\\' );
+ doubleQuote = makeStringParser( '"' );
+ singleQuote = makeStringParser( '\'' );
+ anyCharacter = makeRegexParser( /^./ );
+
+ openHtmlStartTag = makeStringParser( '<' );
+ optionalForwardSlash = makeRegexParser( /^\/?/ );
+ openHtmlEndTag = makeStringParser( '</' );
+ htmlAttributeEquals = makeRegexParser( /^\s*=\s*/ );
+ closeHtmlTag = makeRegexParser( /^\s*>/ );
+
+ function escapedLiteral() {
+ var result = sequence( [
+ backslash,
+ anyCharacter
+ ] );
+ return result === null ? null : result[ 1 ];
+ }
+ escapedOrLiteralWithoutSpace = choice( [
+ escapedLiteral,
+ regularLiteralWithoutSpace
+ ] );
+ escapedOrLiteralWithoutBar = choice( [
+ escapedLiteral,
+ regularLiteralWithoutBar
+ ] );
+ escapedOrRegularLiteral = choice( [
+ escapedLiteral,
+ regularLiteral
+ ] );
+ // Used to define "literals" without spaces, in space-delimited situations
+ function literalWithoutSpace() {
+ var result = nOrMore( 1, escapedOrLiteralWithoutSpace )();
+ return result === null ? null : result.join( '' );
+ }
+ // Used to define "literals" within template parameters. The pipe character is the parameter delimeter, so by default
+ // it is not a literal in the parameter
+ function literalWithoutBar() {
+ var result = nOrMore( 1, escapedOrLiteralWithoutBar )();
+ return result === null ? null : result.join( '' );
+ }
+
+ function literal() {
+ var result = nOrMore( 1, escapedOrRegularLiteral )();
+ return result === null ? null : result.join( '' );
+ }
+
+ function curlyBraceTransformExpressionLiteral() {
+ var result = nOrMore( 1, regularLiteralWithSquareBrackets )();
+ return result === null ? null : result.join( '' );
+ }
+
+ asciiAlphabetLiteral = makeRegexParser( /^[A-Za-z]+/ );
+ htmlDoubleQuoteAttributeValue = makeRegexParser( /^[^"]*/ );
+ htmlSingleQuoteAttributeValue = makeRegexParser( /^[^']*/ );
+
+ whitespace = makeRegexParser( /^\s+/ );
+ dollar = makeStringParser( '$' );
+ digits = makeRegexParser( /^\d+/ );
+
+ function replacement() {
+ var result = sequence( [
+ dollar,
+ digits
+ ] );
+ if ( result === null ) {
+ return null;
+ }
+ return [ 'REPLACE', parseInt( result[ 1 ], 10 ) - 1 ];
+ }
+ openExtlink = makeStringParser( '[' );
+ closeExtlink = makeStringParser( ']' );
+ // this extlink MUST have inner contents, e.g. [foo] not allowed; [foo bar] [foo <i>bar</i>], etc. are allowed
+ function extlink() {
+ var result, parsedResult, target;
+ result = null;
+ parsedResult = sequence( [
+ openExtlink,
+ nOrMore( 1, nonWhitespaceExpression ),
+ whitespace,
+ nOrMore( 1, expression ),
+ closeExtlink
+ ] );
+ if ( parsedResult !== null ) {
+ // When the entire link target is a single parameter, we can't use CONCAT, as we allow
+ // passing fancy parameters (like a whole jQuery object or a function) to use for the
+ // link. Check only if it's a single match, since we can either do CONCAT or not for
+ // singles with the same effect.
+ target = parsedResult[ 1 ].length === 1 ?
+ parsedResult[ 1 ][ 0 ] :
+ [ 'CONCAT' ].concat( parsedResult[ 1 ] );
+ result = [
+ 'EXTLINK',
+ target,
+ [ 'CONCAT' ].concat( parsedResult[ 3 ] )
+ ];
+ }
+ return result;
+ }
+ openWikilink = makeStringParser( '[[' );
+ closeWikilink = makeStringParser( ']]' );
+ pipe = makeStringParser( '|' );
+
+ function template() {
+ var result = sequence( [
+ openTemplate,
+ templateContents,
+ closeTemplate
+ ] );
+ return result === null ? null : result[ 1 ];
+ }
+
+ function pipedWikilink() {
+ var result = sequence( [
+ nOrMore( 1, paramExpression ),
+ pipe,
+ nOrMore( 1, expression )
+ ] );
+ return result === null ? null : [
+ [ 'CONCAT' ].concat( result[ 0 ] ),
+ [ 'CONCAT' ].concat( result[ 2 ] )
+ ];
+ }
+
+ function unpipedWikilink() {
+ var result = sequence( [
+ nOrMore( 1, paramExpression )
+ ] );
+ return result === null ? null : [
+ [ 'CONCAT' ].concat( result[ 0 ] )
+ ];
+ }
+
+ wikilinkContents = choice( [
+ pipedWikilink,
+ unpipedWikilink
+ ] );
+
+ function wikilink() {
+ var result, parsedResult, parsedLinkContents;
+ result = null;
+
+ parsedResult = sequence( [
+ openWikilink,
+ wikilinkContents,
+ closeWikilink
+ ] );
+ if ( parsedResult !== null ) {
+ parsedLinkContents = parsedResult[ 1 ];
+ result = [ 'WIKILINK' ].concat( parsedLinkContents );
+ }
+ return result;
+ }
+
+ // TODO: Support data- if appropriate
+ function doubleQuotedHtmlAttributeValue() {
+ var parsedResult = sequence( [
+ doubleQuote,
+ htmlDoubleQuoteAttributeValue,
+ doubleQuote
+ ] );
+ return parsedResult === null ? null : parsedResult[ 1 ];
+ }
+
+ function singleQuotedHtmlAttributeValue() {
+ var parsedResult = sequence( [
+ singleQuote,
+ htmlSingleQuoteAttributeValue,
+ singleQuote
+ ] );
+ return parsedResult === null ? null : parsedResult[ 1 ];
+ }
+
+ function htmlAttribute() {
+ var parsedResult = sequence( [
+ whitespace,
+ asciiAlphabetLiteral,
+ htmlAttributeEquals,
+ choice( [
+ doubleQuotedHtmlAttributeValue,
+ singleQuotedHtmlAttributeValue
+ ] )
+ ] );
+ return parsedResult === null ? null : [ parsedResult[ 1 ], parsedResult[ 3 ] ];
+ }
+
+ /**
+ * Checks if HTML is allowed
+ *
+ * @param {string} startTagName HTML start tag name
+ * @param {string} endTagName HTML start tag name
+ * @param {Object} attributes array of consecutive key value pairs,
+ * with index 2 * n being a name and 2 * n + 1 the associated value
+ * @return {boolean} true if this is HTML is allowed, false otherwise
+ */
+ function isAllowedHtml( startTagName, endTagName, attributes ) {
+ var i, len, attributeName;
+
+ startTagName = startTagName.toLowerCase();
+ endTagName = endTagName.toLowerCase();
+ if ( startTagName !== endTagName || $.inArray( startTagName, settings.allowedHtmlElements ) === -1 ) {
+ return false;
+ }
+
+ for ( i = 0, len = attributes.length; i < len; i += 2 ) {
+ attributeName = attributes[ i ];
+ if ( $.inArray( attributeName, settings.allowedHtmlCommonAttributes ) === -1 &&
+ $.inArray( attributeName, settings.allowedHtmlAttributesByElement[ startTagName ] || [] ) === -1 ) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ function htmlAttributes() {
+ var parsedResult = nOrMore( 0, htmlAttribute )();
+ // Un-nest attributes array due to structure of jQueryMsg operations (see emit).
+ return concat.apply( [ 'HTMLATTRIBUTES' ], parsedResult );
+ }
+
+ // Subset of allowed HTML markup.
+ // Most elements and many attributes allowed on the server are not supported yet.
+ function html() {
+ var parsedOpenTagResult, parsedHtmlContents, parsedCloseTagResult,
+ wrappedAttributes, attributes, startTagName, endTagName, startOpenTagPos,
+ startCloseTagPos, endOpenTagPos, endCloseTagPos,
+ result = null;
+
+ // Break into three sequence calls. That should allow accurate reconstruction of the original HTML, and requiring an exact tag name match.
+ // 1. open through closeHtmlTag
+ // 2. expression
+ // 3. openHtmlEnd through close
+ // This will allow recording the positions to reconstruct if HTML is to be treated as text.
+
+ startOpenTagPos = pos;
+ parsedOpenTagResult = sequence( [
+ openHtmlStartTag,
+ asciiAlphabetLiteral,
+ htmlAttributes,
+ optionalForwardSlash,
+ closeHtmlTag
+ ] );
+
+ if ( parsedOpenTagResult === null ) {
+ return null;
+ }
+
+ endOpenTagPos = pos;
+ startTagName = parsedOpenTagResult[ 1 ];
+
+ parsedHtmlContents = nOrMore( 0, expression )();
+
+ startCloseTagPos = pos;
+ parsedCloseTagResult = sequence( [
+ openHtmlEndTag,
+ asciiAlphabetLiteral,
+ closeHtmlTag
+ ] );
+
+ if ( parsedCloseTagResult === null ) {
+ // Closing tag failed. Return the start tag and contents.
+ return [ 'CONCAT', input.slice( startOpenTagPos, endOpenTagPos ) ]
+ .concat( parsedHtmlContents );
+ }
+
+ endCloseTagPos = pos;
+ endTagName = parsedCloseTagResult[ 1 ];
+ wrappedAttributes = parsedOpenTagResult[ 2 ];
+ attributes = wrappedAttributes.slice( 1 );
+ if ( isAllowedHtml( startTagName, endTagName, attributes ) ) {
+ result = [ 'HTMLELEMENT', startTagName, wrappedAttributes ]
+ .concat( parsedHtmlContents );
+ } else {
+ // HTML is not allowed, so contents will remain how
+ // it was, while HTML markup at this level will be
+ // treated as text
+ // E.g. assuming script tags are not allowed:
+ //
+ // <script>[[Foo|bar]]</script>
+ //
+ // results in '&lt;script&gt;' and '&lt;/script&gt;'
+ // (not treated as an HTML tag), surrounding a fully
+ // parsed HTML link.
+ //
+ // Concatenate everything from the tag, flattening the contents.
+ result = [ 'CONCAT', input.slice( startOpenTagPos, endOpenTagPos ) ]
+ .concat( parsedHtmlContents, input.slice( startCloseTagPos, endCloseTagPos ) );
+ }
+
+ return result;
+ }
+
+ // <nowiki>...</nowiki> tag. The tags are stripped and the contents are returned unparsed.
+ function nowiki() {
+ var parsedResult, plainText,
+ result = null;
+
+ parsedResult = sequence( [
+ makeStringParser( '<nowiki>' ),
+ // We use a greedy non-backtracking parser, so we must ensure here that we don't take too much
+ makeRegexParser( /^.*?(?=<\/nowiki>)/ ),
+ makeStringParser( '</nowiki>' )
+ ] );
+ if ( parsedResult !== null ) {
+ plainText = parsedResult[ 1 ];
+ result = [ 'CONCAT' ].concat( plainText );
+ }
+
+ return result;
+ }
+
+ templateName = transform(
+ // see $wgLegalTitleChars
+ // not allowing : due to the need to catch "PLURAL:$1"
+ makeRegexParser( /^[ !"$&'()*,./0-9;=?@A-Z^_`a-z~\x80-\xFF+-]+/ ),
+ function ( result ) { return result.toString(); }
+ );
+ function templateParam() {
+ var expr, result;
+ result = sequence( [
+ pipe,
+ nOrMore( 0, paramExpression )
+ ] );
+ if ( result === null ) {
+ return null;
+ }
+ expr = result[ 1 ];
+ // use a CONCAT operator if there are multiple nodes, otherwise return the first node, raw.
+ return expr.length > 1 ? [ 'CONCAT' ].concat( expr ) : expr[ 0 ];
+ }
+
+ function templateWithReplacement() {
+ var result = sequence( [
+ templateName,
+ colon,
+ replacement
+ ] );
+ return result === null ? null : [ result[ 0 ], result[ 2 ] ];
+ }
+ function templateWithOutReplacement() {
+ var result = sequence( [
+ templateName,
+ colon,
+ paramExpression
+ ] );
+ return result === null ? null : [ result[ 0 ], result[ 2 ] ];
+ }
+ function templateWithOutFirstParameter() {
+ var result = sequence( [
+ templateName,
+ colon
+ ] );
+ return result === null ? null : [ result[ 0 ], '' ];
+ }
+ colon = makeStringParser( ':' );
+ templateContents = choice( [
+ function () {
+ var res = sequence( [
+ // templates can have placeholders for dynamic replacement eg: {{PLURAL:$1|one car|$1 cars}}
+ // or no placeholders eg: {{GRAMMAR:genitive|{{SITENAME}}}
+ choice( [ templateWithReplacement, templateWithOutReplacement, templateWithOutFirstParameter ] ),
+ nOrMore( 0, templateParam )
+ ] );
+ return res === null ? null : res[ 0 ].concat( res[ 1 ] );
+ },
+ function () {
+ var res = sequence( [
+ templateName,
+ nOrMore( 0, templateParam )
+ ] );
+ if ( res === null ) {
+ return null;
+ }
+ return [ res[ 0 ] ].concat( res[ 1 ] );
+ }
+ ] );
+ openTemplate = makeStringParser( '{{' );
+ closeTemplate = makeStringParser( '}}' );
+ nonWhitespaceExpression = choice( [
+ template,
+ wikilink,
+ extlink,
+ replacement,
+ literalWithoutSpace
+ ] );
+ paramExpression = choice( [
+ template,
+ wikilink,
+ extlink,
+ replacement,
+ literalWithoutBar
+ ] );
+
+ expression = choice( [
+ template,
+ wikilink,
+ extlink,
+ replacement,
+ nowiki,
+ html,
+ literal
+ ] );
+
+ // Used when only {{-transformation is wanted, for 'text'
+ // or 'escaped' formats
+ curlyBraceTransformExpression = choice( [
+ template,
+ replacement,
+ curlyBraceTransformExpressionLiteral
+ ] );
+
+ /**
+ * Starts the parse
+ *
+ * @param {Function} rootExpression Root parse function
+ * @return {Array|null}
+ */
+ function start( rootExpression ) {
+ var result = nOrMore( 0, rootExpression )();
+ if ( result === null ) {
+ return null;
+ }
+ return [ 'CONCAT' ].concat( result );
+ }
+ // everything above this point is supposed to be stateless/static, but
+ // I am deferring the work of turning it into prototypes & objects. It's quite fast enough
+ // finally let's do some actual work...
+
+ result = start( this.settings.onlyCurlyBraceTransform ? curlyBraceTransformExpression : expression );
+
+ /*
+ * For success, the p must have gotten to the end of the input
+ * and returned a non-null.
+ * n.b. This is part of language infrastructure, so we do not throw an internationalizable message.
+ */
+ if ( result === null || pos !== input.length ) {
+ throw new Error( 'Parse error at position ' + pos.toString() + ' in input: ' + input );
+ }
+ return result;
+ }
+
+ };
+
+ /**
+ * htmlEmitter - object which primarily exists to emit HTML from parser ASTs
+ *
+ * @param {Object} language
+ * @param {Object} magic
+ */
+ mw.jqueryMsg.htmlEmitter = function ( language, magic ) {
+ var jmsg = this;
+ this.language = language;
+ $.each( magic, function ( key, val ) {
+ jmsg[ key.toLowerCase() ] = function () {
+ return val;
+ };
+ } );
+
+ /**
+ * (We put this method definition here, and not in prototype, to make sure it's not overwritten by any magic.)
+ * Walk entire node structure, applying replacements and template functions when appropriate
+ *
+ * @param {Mixed} node Abstract syntax tree (top node or subnode)
+ * @param {Array} replacements for $1, $2, ... $n
+ * @return {Mixed} single-string node or array of nodes suitable for jQuery appending
+ */
+ this.emit = function ( node, replacements ) {
+ var ret, subnodes, operation,
+ jmsg = this;
+ switch ( typeof node ) {
+ case 'string':
+ case 'number':
+ ret = node;
+ break;
+ // typeof returns object for arrays
+ case 'object':
+ // node is an array of nodes
+ subnodes = $.map( node.slice( 1 ), function ( n ) {
+ return jmsg.emit( n, replacements );
+ } );
+ operation = node[ 0 ].toLowerCase();
+ if ( typeof jmsg[ operation ] === 'function' ) {
+ ret = jmsg[ operation ]( subnodes, replacements );
+ } else {
+ throw new Error( 'Unknown operation "' + operation + '"' );
+ }
+ break;
+ case 'undefined':
+ // Parsing the empty string (as an entire expression, or as a paramExpression in a template) results in undefined
+ // Perhaps a more clever parser can detect this, and return the empty string? Or is that useful information?
+ // The logical thing is probably to return the empty string here when we encounter undefined.
+ ret = '';
+ break;
+ default:
+ throw new Error( 'Unexpected type in AST: ' + typeof node );
+ }
+ return ret;
+ };
+ };
+
+ // For everything in input that follows double-open-curly braces, there should be an equivalent parser
+ // function. For instance {{PLURAL ... }} will be processed by 'plural'.
+ // If you have 'magic words' then configure the parser to have them upon creation.
+ //
+ // An emitter method takes the parent node, the array of subnodes and the array of replacements (the values that $1, $2... should translate to).
+ // Note: all such functions must be pure, with the exception of referring to other pure functions via this.language (convertPlural and so on)
+ mw.jqueryMsg.htmlEmitter.prototype = {
+ /**
+ * Parsing has been applied depth-first we can assume that all nodes here are single nodes
+ * Must return a single node to parents -- a jQuery with synthetic span
+ * However, unwrap any other synthetic spans in our children and pass them upwards
+ *
+ * @param {Mixed[]} nodes Some single nodes, some arrays of nodes
+ * @return {jQuery}
+ */
+ concat: function ( nodes ) {
+ var $span = $( '<span>' ).addClass( 'mediaWiki_htmlEmitter' );
+ $.each( nodes, function ( i, node ) {
+ // Let jQuery append nodes, arrays of nodes and jQuery objects
+ // other things (strings, numbers, ..) are appended as text nodes (not as HTML strings)
+ appendWithoutParsing( $span, node );
+ } );
+ return $span;
+ },
+
+ /**
+ * Return escaped replacement of correct index, or string if unavailable.
+ * Note that we expect the parsed parameter to be zero-based. i.e. $1 should have become [ 0 ].
+ * if the specified parameter is not found return the same string
+ * (e.g. "$99" -> parameter 98 -> not found -> return "$99" )
+ *
+ * TODO: Throw error if nodes.length > 1 ?
+ *
+ * @param {Array} nodes List of one element, integer, n >= 0
+ * @param {Array} replacements List of at least n strings
+ * @return {string} replacement
+ */
+ replace: function ( nodes, replacements ) {
+ var index = parseInt( nodes[ 0 ], 10 );
+
+ if ( index < replacements.length ) {
+ return replacements[ index ];
+ } else {
+ // index not found, fallback to displaying variable
+ return '$' + ( index + 1 );
+ }
+ },
+
+ /**
+ * Transform wiki-link
+ *
+ * TODO:
+ * It only handles basic cases, either no pipe, or a pipe with an explicit
+ * anchor.
+ *
+ * It does not attempt to handle features like the pipe trick.
+ * However, the pipe trick should usually not be present in wikitext retrieved
+ * from the server, since the replacement is done at save time.
+ * It may, though, if the wikitext appears in extension-controlled content.
+ *
+ * @param {string[]} nodes
+ * @return {jQuery}
+ */
+ wikilink: function ( nodes ) {
+ var page, anchor, url, $el;
+
+ page = textify( nodes[ 0 ] );
+ // Strip leading ':', which is used to suppress special behavior in wikitext links,
+ // e.g. [[:Category:Foo]] or [[:File:Foo.jpg]]
+ if ( page.charAt( 0 ) === ':' ) {
+ page = page.slice( 1 );
+ }
+ url = mw.util.getUrl( page );
+
+ if ( nodes.length === 1 ) {
+ // [[Some Page]] or [[Namespace:Some Page]]
+ anchor = page;
+ } else {
+ // [[Some Page|anchor text]] or [[Namespace:Some Page|anchor]]
+ anchor = nodes[ 1 ];
+ }
+
+ $el = $( '<a>' ).attr( {
+ title: page,
+ href: url
+ } );
+ return appendWithoutParsing( $el, anchor );
+ },
+
+ /**
+ * Converts array of HTML element key value pairs to object
+ *
+ * @param {Array} nodes Array of consecutive key value pairs, with index 2 * n being a
+ * name and 2 * n + 1 the associated value
+ * @return {Object} Object mapping attribute name to attribute value
+ */
+ htmlattributes: function ( nodes ) {
+ var i, len, mapping = {};
+ for ( i = 0, len = nodes.length; i < len; i += 2 ) {
+ mapping[ nodes[ i ] ] = decodePrimaryHtmlEntities( nodes[ i + 1 ] );
+ }
+ return mapping;
+ },
+
+ /**
+ * Handles an (already-validated) HTML element.
+ *
+ * @param {Array} nodes Nodes to process when creating element
+ * @return {jQuery|Array} jQuery node for valid HTML or array for disallowed element
+ */
+ htmlelement: function ( nodes ) {
+ var tagName, attributes, contents, $element;
+
+ tagName = nodes.shift();
+ attributes = nodes.shift();
+ contents = nodes;
+ $element = $( document.createElement( tagName ) ).attr( attributes );
+ return appendWithoutParsing( $element, contents );
+ },
+
+ /**
+ * Transform parsed structure into external link.
+ *
+ * The "href" can be:
+ * - a jQuery object, treat it as "enclosing" the link text.
+ * - a function, treat it as the click handler.
+ * - a string, or our htmlEmitter jQuery object, treat it as a URI after stringifying.
+ *
+ * TODO: throw an error if nodes.length > 2 ?
+ *
+ * @param {Array} nodes List of two elements, {jQuery|Function|String} and {string}
+ * @return {jQuery}
+ */
+ extlink: function ( nodes ) {
+ var $el,
+ arg = nodes[ 0 ],
+ contents = nodes[ 1 ];
+ if ( arg instanceof jQuery && !arg.hasClass( 'mediaWiki_htmlEmitter' ) ) {
+ $el = arg;
+ } else {
+ $el = $( '<a>' );
+ if ( typeof arg === 'function' ) {
+ $el.attr( {
+ role: 'button',
+ tabindex: 0
+ } ).on( 'click keypress', function ( e ) {
+ if (
+ e.type === 'click' ||
+ e.type === 'keypress' && e.which === 13
+ ) {
+ arg.call( this, e );
+ }
+ } );
+ } else {
+ $el.attr( 'href', textify( arg ) );
+ }
+ }
+ return appendWithoutParsing( $el.empty(), contents );
+ },
+
+ /**
+ * Transform parsed structure into pluralization
+ * n.b. The first node may be a non-integer (for instance, a string representing an Arabic number).
+ * So convert it back with the current language's convertNumber.
+ *
+ * @param {Array} nodes List of nodes, [ {string|number}, {string}, {string} ... ]
+ * @return {string} selected pluralized form according to current language
+ */
+ plural: function ( nodes ) {
+ var forms, firstChild, firstChildText, explicitPluralFormNumber, formIndex, form, count,
+ explicitPluralForms = {};
+
+ count = parseFloat( this.language.convertNumber( nodes[ 0 ], true ) );
+ forms = nodes.slice( 1 );
+ for ( formIndex = 0; formIndex < forms.length; formIndex++ ) {
+ form = forms[ formIndex ];
+
+ if ( form instanceof jQuery && form.hasClass( 'mediaWiki_htmlEmitter' ) ) {
+ // This is a nested node, may be an explicit plural form like 5=[$2 linktext]
+ firstChild = form.contents().get( 0 );
+ if ( firstChild && firstChild.nodeType === Node.TEXT_NODE ) {
+ firstChildText = firstChild.textContent;
+ if ( /^\d+=/.test( firstChildText ) ) {
+ explicitPluralFormNumber = parseInt( firstChildText.split( /=/ )[ 0 ], 10 );
+ // Use the digit part as key and rest of first text node and
+ // rest of child nodes as value.
+ firstChild.textContent = firstChildText.slice( firstChildText.indexOf( '=' ) + 1 );
+ explicitPluralForms[ explicitPluralFormNumber ] = form;
+ forms[ formIndex ] = undefined;
+ }
+ }
+ } else if ( /^\d+=/.test( form ) ) {
+ // Simple explicit plural forms like 12=a dozen
+ explicitPluralFormNumber = parseInt( form.split( /=/ )[ 0 ], 10 );
+ explicitPluralForms[ explicitPluralFormNumber ] = form.slice( form.indexOf( '=' ) + 1 );
+ forms[ formIndex ] = undefined;
+ }
+ }
+
+ // Remove explicit plural forms from the forms. They were set undefined in the above loop.
+ forms = $.map( forms, function ( form ) {
+ return form;
+ } );
+
+ return this.language.convertPlural( count, forms, explicitPluralForms );
+ },
+
+ /**
+ * Transform parsed structure according to gender.
+ *
+ * Usage: {{gender:[ mw.user object | '' | 'male' | 'female' | 'unknown' ] | masculine form | feminine form | neutral form}}.
+ *
+ * The first node must be one of:
+ * - the mw.user object (or a compatible one)
+ * - an empty string - indicating the current user, same effect as passing the mw.user object
+ * - a gender string ('male', 'female' or 'unknown')
+ *
+ * @param {Array} nodes List of nodes, [ {string|mw.user}, {string}, {string}, {string} ]
+ * @return {string} Selected gender form according to current language
+ */
+ gender: function ( nodes ) {
+ var gender,
+ maybeUser = nodes[ 0 ],
+ forms = nodes.slice( 1 );
+
+ if ( maybeUser === '' ) {
+ maybeUser = mw.user;
+ }
+
+ // If we are passed a mw.user-like object, check their gender.
+ // Otherwise, assume the gender string itself was passed .
+ if ( maybeUser && maybeUser.options instanceof mw.Map ) {
+ gender = maybeUser.options.get( 'gender' );
+ } else {
+ gender = maybeUser;
+ }
+
+ return this.language.gender( gender, forms );
+ },
+
+ /**
+ * Transform parsed structure into grammar conversion.
+ * Invoked by putting `{{grammar:form|word}}` in a message
+ *
+ * @param {Array} nodes List of nodes [{Grammar case eg: genitive}, {string word}]
+ * @return {string} selected grammatical form according to current language
+ */
+ grammar: function ( nodes ) {
+ var form = nodes[ 0 ],
+ word = nodes[ 1 ];
+ return word && form && this.language.convertGrammar( word, form );
+ },
+
+ /**
+ * Tranform parsed structure into a int: (interface language) message include
+ * Invoked by putting `{{int:othermessage}}` into a message
+ *
+ * @param {Array} nodes List of nodes
+ * @return {string} Other message
+ */
+ 'int': function ( nodes ) {
+ var msg = nodes[ 0 ];
+ return mw.jqueryMsg.getMessageFunction()( msg.charAt( 0 ).toLowerCase() + msg.slice( 1 ) );
+ },
+
+ /**
+ * Get localized namespace name from canonical name or namespace number.
+ * Invoked by putting `{{ns:foo}}` into a message
+ *
+ * @param {Array} nodes List of nodes
+ * @return {string} Localized namespace name
+ */
+ ns: function ( nodes ) {
+ var ns = $.trim( textify( nodes[ 0 ] ) );
+ if ( !/^\d+$/.test( ns ) ) {
+ ns = mw.config.get( 'wgNamespaceIds' )[ ns.replace( / /g, '_' ).toLowerCase() ];
+ }
+ ns = mw.config.get( 'wgFormattedNamespaces' )[ ns ];
+ return ns || '';
+ },
+
+ /**
+ * Takes an unformatted number (arab, no group separators and . as decimal separator)
+ * and outputs it in the localized digit script and formatted with decimal
+ * separator, according to the current language.
+ *
+ * @param {Array} nodes List of nodes
+ * @return {number|string} Formatted number
+ */
+ formatnum: function ( nodes ) {
+ var isInteger = !!nodes[ 1 ] && nodes[ 1 ] === 'R',
+ number = nodes[ 0 ];
+
+ return this.language.convertNumber( number, isInteger );
+ },
+
+ /**
+ * Lowercase text
+ *
+ * @param {Array} nodes List of nodes
+ * @return {string} The given text, all in lowercase
+ */
+ lc: function ( nodes ) {
+ return textify( nodes[ 0 ] ).toLowerCase();
+ },
+
+ /**
+ * Uppercase text
+ *
+ * @param {Array} nodes List of nodes
+ * @return {string} The given text, all in uppercase
+ */
+ uc: function ( nodes ) {
+ return textify( nodes[ 0 ] ).toUpperCase();
+ },
+
+ /**
+ * Lowercase first letter of input, leaving the rest unchanged
+ *
+ * @param {Array} nodes List of nodes
+ * @return {string} The given text, with the first character in lowercase
+ */
+ lcfirst: function ( nodes ) {
+ var text = textify( nodes[ 0 ] );
+ return text.charAt( 0 ).toLowerCase() + text.slice( 1 );
+ },
+
+ /**
+ * Uppercase first letter of input, leaving the rest unchanged
+ *
+ * @param {Array} nodes List of nodes
+ * @return {string} The given text, with the first character in uppercase
+ */
+ ucfirst: function ( nodes ) {
+ var text = textify( nodes[ 0 ] );
+ return text.charAt( 0 ).toUpperCase() + text.slice( 1 );
+ }
+ };
+
+ // Deprecated! don't rely on gM existing.
+ // The window.gM ought not to be required - or if required, not required here.
+ // But moving it to extensions breaks it (?!)
+ // Need to fix plugin so it could do attributes as well, then will be okay to remove this.
+ // @deprecated since 1.23
+ mw.log.deprecate( window, 'gM', mw.jqueryMsg.getMessageFunction(), 'Use mw.message( ... ).parse() instead.' );
+
+ /**
+ * @method
+ * @member jQuery
+ * @see mw.jqueryMsg#getPlugin
+ */
+ $.fn.msg = mw.jqueryMsg.getPlugin();
+
+ // Replace the default message parser with jqueryMsg
+ oldParser = mw.Message.prototype.parser;
+ mw.Message.prototype.parser = function () {
+ if ( this.format === 'plain' || !/\{\{|[<>[&]/.test( this.map.get( this.key ) ) ) {
+ // Fall back to mw.msg's simple parser
+ return oldParser.apply( this );
+ }
+
+ if ( !this.map.hasOwnProperty( this.format ) ) {
+ this.map[ this.format ] = mw.jqueryMsg.getMessageFunction( {
+ messages: this.map,
+ // For format 'escaped', escaping part is handled by mediawiki.js
+ format: this.format
+ } );
+ }
+ return this.map[ this.format ]( this.key, this.parameters );
+ };
+
+ /**
+ * Parse the message to DOM nodes, rather than HTML string like #parse.
+ *
+ * This method is only available when jqueryMsg is loaded.
+ *
+ * @since 1.27
+ * @method parseDom
+ * @member mw.Message
+ * @return {jQuery}
+ */
+ mw.Message.prototype.parseDom = ( function () {
+ var reusableParent = $( '<div>' );
+ return function () {
+ return reusableParent.msg( this.key, this.parameters ).contents().detach();
+ };
+ }() );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.jqueryMsg.peg b/www/wiki/resources/src/mediawiki/mediawiki.jqueryMsg.peg
new file mode 100644
index 00000000..716c3261
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.jqueryMsg.peg
@@ -0,0 +1,85 @@
+/* PEG grammar for a subset of wikitext, useful in the MediaWiki frontend */
+
+start
+ = e:expression* { return e.length > 1 ? [ "CONCAT" ].concat(e) : e[0]; }
+
+expression
+ = template
+ / link
+ / extlink
+ / replacement
+ / literal
+
+paramExpression
+ = template
+ / link
+ / extlink
+ / replacement
+ / literalWithoutBar
+
+template
+ = "{{" t:templateContents "}}" { return t; }
+
+templateContents
+ = twr:templateWithReplacement p:templateParam* { return twr.concat(p) }
+ / twr:templateWithOutReplacement p:templateParam* { return twr.concat(p) }
+ / twr:templateWithOutFirstParameter p:templateParam* { return twr.concat(p) }
+ / t:templateName p:templateParam* { return p.length ? [ t, p ] : [ t ] }
+
+templateWithReplacement
+ = t:templateName ":" r:replacement { return [ t, r ] }
+
+templateWithOutReplacement
+ = t:templateName ":" p:paramExpression { return [ t, p ] }
+
+templateWithOutFirstParameter
+ = t:templateName ":" { return [ t, "" ] }
+
+templateParam
+ = "|" e:paramExpression* { return e.length > 1 ? [ "CONCAT" ].concat(e) : e[0]; }
+
+templateName
+ = tn:[A-Za-z_]+ { return tn.join('').toUpperCase() }
+
+/* TODO: Update to reflect separate piped and unpiped handling */
+link
+ = "[[" w:expression "]]" { return [ 'WLINK', w ]; }
+
+extlink
+ = "[" url:url whitespace text:expression "]" { return [ 'LINK', url, text ] }
+
+url
+ = url:[^ ]+ { return url.join(''); }
+
+whitespace
+ = [ ]+
+
+replacement
+ = '$' digits:digits { return [ 'REPLACE', parseInt( digits, 10 ) - 1 ] }
+
+digits
+ = [0-9]+
+
+literal
+ = lit:escapedOrRegularLiteral+ { return lit.join(''); }
+
+literalWithoutBar
+ = lit:escapedOrLiteralWithoutBar+ { return lit.join(''); }
+
+escapedOrRegularLiteral
+ = escapedLiteral
+ / regularLiteral
+
+escapedOrLiteralWithoutBar
+ = escapedLiteral
+ / regularLiteralWithoutBar
+
+escapedLiteral
+ = "\\" escaped:. { return escaped; }
+
+regularLiteral
+ = [^{}\[\]$\\]
+
+regularLiteralWithoutBar
+ = [^{}\[\]$\\|]
+
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.js b/www/wiki/resources/src/mediawiki/mediawiki.js
new file mode 100644
index 00000000..b5224867
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.js
@@ -0,0 +1,2799 @@
+/**
+ * Base library for MediaWiki.
+ *
+ * Exposed globally as `mediaWiki` with `mw` as shortcut.
+ *
+ * @class mw
+ * @alternateClassName mediaWiki
+ * @singleton
+ */
+
+/* global mwNow */
+/* eslint-disable no-use-before-define */
+
+( function ( $ ) {
+ 'use strict';
+
+ var mw, StringSet, log,
+ hasOwn = Object.prototype.hasOwnProperty,
+ slice = Array.prototype.slice,
+ trackCallbacks = $.Callbacks( 'memory' ),
+ trackHandlers = [],
+ trackQueue = [];
+
+ /**
+ * FNV132 hash function
+ *
+ * This function implements the 32-bit version of FNV-1.
+ * It is equivalent to hash( 'fnv132', ... ) in PHP, except
+ * its output is base 36 rather than hex.
+ * See <https://en.wikipedia.org/wiki/FNV_hash_function>
+ *
+ * @private
+ * @param {string} str String to hash
+ * @return {string} hash as an seven-character base 36 string
+ */
+ function fnv132( str ) {
+ /* eslint-disable no-bitwise */
+ var hash = 0x811C9DC5,
+ i;
+
+ for ( i = 0; i < str.length; i++ ) {
+ hash += ( hash << 1 ) + ( hash << 4 ) + ( hash << 7 ) + ( hash << 8 ) + ( hash << 24 );
+ hash ^= str.charCodeAt( i );
+ }
+
+ hash = ( hash >>> 0 ).toString( 36 );
+ while ( hash.length < 7 ) {
+ hash = '0' + hash;
+ }
+
+ return hash;
+ /* eslint-enable no-bitwise */
+ }
+
+ function defineFallbacks() {
+ // <https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Set>
+ StringSet = window.Set || ( function () {
+ /**
+ * @private
+ * @class
+ */
+ function StringSet() {
+ this.set = {};
+ }
+ StringSet.prototype.add = function ( value ) {
+ this.set[ value ] = true;
+ };
+ StringSet.prototype.has = function ( value ) {
+ return hasOwn.call( this.set, value );
+ };
+ return StringSet;
+ }() );
+ }
+
+ /**
+ * Create an object that can be read from or written to via methods that allow
+ * interaction both with single and multiple properties at once.
+ *
+ * @private
+ * @class mw.Map
+ *
+ * @constructor
+ * @param {boolean} [global=false] Whether to synchronise =values to the global
+ * window object (for backwards-compatibility with mw.config; T72470). Values are
+ * copied in one direction only. Changes to globals do not reflect in the map.
+ */
+ function Map( global ) {
+ this.values = {};
+ if ( global === true ) {
+ // Override #set to also set the global variable
+ this.set = function ( selection, value ) {
+ var s;
+
+ if ( $.isPlainObject( selection ) ) {
+ for ( s in selection ) {
+ setGlobalMapValue( this, s, selection[ s ] );
+ }
+ return true;
+ }
+ if ( typeof selection === 'string' && arguments.length ) {
+ setGlobalMapValue( this, selection, value );
+ return true;
+ }
+ return false;
+ };
+ }
+ }
+
+ /**
+ * Alias property to the global object.
+ *
+ * @private
+ * @static
+ * @param {mw.Map} map
+ * @param {string} key
+ * @param {Mixed} value
+ */
+ function setGlobalMapValue( map, key, value ) {
+ map.values[ key ] = value;
+ log.deprecate(
+ window,
+ key,
+ value,
+ // Deprecation notice for mw.config globals (T58550, T72470)
+ map === mw.config && 'Use mw.config instead.'
+ );
+ }
+
+ Map.prototype = {
+ constructor: Map,
+
+ /**
+ * Get the value of one or more keys.
+ *
+ * If called with no arguments, all values are returned.
+ *
+ * @param {string|Array} [selection] Key or array of keys to retrieve values for.
+ * @param {Mixed} [fallback=null] Value for keys that don't exist.
+ * @return {Mixed|Object|null} If selection was a string, returns the value,
+ * If selection was an array, returns an object of key/values.
+ * If no selection is passed, a new object with all key/values is returned.
+ */
+ get: function ( selection, fallback ) {
+ var results, i;
+ fallback = arguments.length > 1 ? fallback : null;
+
+ if ( Array.isArray( selection ) ) {
+ results = {};
+ for ( i = 0; i < selection.length; i++ ) {
+ if ( typeof selection[ i ] === 'string' ) {
+ results[ selection[ i ] ] = hasOwn.call( this.values, selection[ i ] ) ?
+ this.values[ selection[ i ] ] :
+ fallback;
+ }
+ }
+ return results;
+ }
+
+ if ( typeof selection === 'string' ) {
+ return hasOwn.call( this.values, selection ) ?
+ this.values[ selection ] :
+ fallback;
+ }
+
+ if ( selection === undefined ) {
+ results = {};
+ for ( i in this.values ) {
+ results[ i ] = this.values[ i ];
+ }
+ return results;
+ }
+
+ // Invalid selection key
+ return fallback;
+ },
+
+ /**
+ * Set one or more key/value pairs.
+ *
+ * @param {string|Object} selection Key to set value for, or object mapping keys to values
+ * @param {Mixed} [value] Value to set (optional, only in use when key is a string)
+ * @return {boolean} True on success, false on failure
+ */
+ set: function ( selection, value ) {
+ var s;
+
+ if ( $.isPlainObject( selection ) ) {
+ for ( s in selection ) {
+ this.values[ s ] = selection[ s ];
+ }
+ return true;
+ }
+ if ( typeof selection === 'string' && arguments.length > 1 ) {
+ this.values[ selection ] = value;
+ return true;
+ }
+ return false;
+ },
+
+ /**
+ * Check if one or more keys exist.
+ *
+ * @param {Mixed} selection Key or array of keys to check
+ * @return {boolean} True if the key(s) exist
+ */
+ exists: function ( selection ) {
+ var i;
+ if ( Array.isArray( selection ) ) {
+ for ( i = 0; i < selection.length; i++ ) {
+ if ( typeof selection[ i ] !== 'string' || !hasOwn.call( this.values, selection[ i ] ) ) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return typeof selection === 'string' && hasOwn.call( this.values, selection );
+ }
+ };
+
+ /**
+ * Object constructor for messages.
+ *
+ * Similar to the Message class in MediaWiki PHP.
+ *
+ * Format defaults to 'text'.
+ *
+ * @example
+ *
+ * var obj, str;
+ * mw.messages.set( {
+ * 'hello': 'Hello world',
+ * 'hello-user': 'Hello, $1!',
+ * 'welcome-user': 'Welcome back to $2, $1! Last visit by $1: $3'
+ * } );
+ *
+ * obj = new mw.Message( mw.messages, 'hello' );
+ * mw.log( obj.text() );
+ * // Hello world
+ *
+ * obj = new mw.Message( mw.messages, 'hello-user', [ 'John Doe' ] );
+ * mw.log( obj.text() );
+ * // Hello, John Doe!
+ *
+ * obj = new mw.Message( mw.messages, 'welcome-user', [ 'John Doe', 'Wikipedia', '2 hours ago' ] );
+ * mw.log( obj.text() );
+ * // Welcome back to Wikipedia, John Doe! Last visit by John Doe: 2 hours ago
+ *
+ * // Using mw.message shortcut
+ * obj = mw.message( 'hello-user', 'John Doe' );
+ * mw.log( obj.text() );
+ * // Hello, John Doe!
+ *
+ * // Using mw.msg shortcut
+ * str = mw.msg( 'hello-user', 'John Doe' );
+ * mw.log( str );
+ * // Hello, John Doe!
+ *
+ * // Different formats
+ * obj = new mw.Message( mw.messages, 'hello-user', [ 'John "Wiki" <3 Doe' ] );
+ *
+ * obj.format = 'text';
+ * str = obj.toString();
+ * // Same as:
+ * str = obj.text();
+ *
+ * mw.log( str );
+ * // Hello, John "Wiki" <3 Doe!
+ *
+ * mw.log( obj.escaped() );
+ * // Hello, John &quot;Wiki&quot; &lt;3 Doe!
+ *
+ * @class mw.Message
+ *
+ * @constructor
+ * @param {mw.Map} map Message store
+ * @param {string} key
+ * @param {Array} [parameters]
+ */
+ function Message( map, key, parameters ) {
+ this.format = 'text';
+ this.map = map;
+ this.key = key;
+ this.parameters = parameters === undefined ? [] : slice.call( parameters );
+ return this;
+ }
+
+ Message.prototype = {
+ /**
+ * Get parsed contents of the message.
+ *
+ * The default parser does simple $N replacements and nothing else.
+ * This may be overridden to provide a more complex message parser.
+ * The primary override is in the mediawiki.jqueryMsg module.
+ *
+ * This function will not be called for nonexistent messages.
+ *
+ * @return {string} Parsed message
+ */
+ parser: function () {
+ return mw.format.apply( null, [ this.map.get( this.key ) ].concat( this.parameters ) );
+ },
+
+ // eslint-disable-next-line valid-jsdoc
+ /**
+ * Add (does not replace) parameters for `$N` placeholder values.
+ *
+ * @param {Array} parameters
+ * @chainable
+ */
+ params: function ( parameters ) {
+ var i;
+ for ( i = 0; i < parameters.length; i++ ) {
+ this.parameters.push( parameters[ i ] );
+ }
+ return this;
+ },
+
+ /**
+ * Convert message object to its string form based on current format.
+ *
+ * @return {string} Message as a string in the current form, or `<key>` if key
+ * does not exist.
+ */
+ toString: function () {
+ var text;
+
+ if ( !this.exists() ) {
+ // Use ⧼key⧽ as text if key does not exist
+ // Err on the side of safety, ensure that the output
+ // is always html safe in the event the message key is
+ // missing, since in that case its highly likely the
+ // message key is user-controlled.
+ // '⧼' is used instead of '<' to side-step any
+ // double-escaping issues.
+ // (Keep synchronised with Message::toString() in PHP.)
+ return '⧼' + mw.html.escape( this.key ) + '⧽';
+ }
+
+ if ( this.format === 'plain' || this.format === 'text' || this.format === 'parse' ) {
+ text = this.parser();
+ }
+
+ if ( this.format === 'escaped' ) {
+ text = this.parser();
+ text = mw.html.escape( text );
+ }
+
+ return text;
+ },
+
+ /**
+ * Change format to 'parse' and convert message to string
+ *
+ * If jqueryMsg is loaded, this parses the message text from wikitext
+ * (where supported) to HTML
+ *
+ * Otherwise, it is equivalent to plain.
+ *
+ * @return {string} String form of parsed message
+ */
+ parse: function () {
+ this.format = 'parse';
+ return this.toString();
+ },
+
+ /**
+ * Change format to 'plain' and convert message to string
+ *
+ * This substitutes parameters, but otherwise does not change the
+ * message text.
+ *
+ * @return {string} String form of plain message
+ */
+ plain: function () {
+ this.format = 'plain';
+ return this.toString();
+ },
+
+ /**
+ * Change format to 'text' and convert message to string
+ *
+ * If jqueryMsg is loaded, {{-transformation is done where supported
+ * (such as {{plural:}}, {{gender:}}, {{int:}}).
+ *
+ * Otherwise, it is equivalent to plain
+ *
+ * @return {string} String form of text message
+ */
+ text: function () {
+ this.format = 'text';
+ return this.toString();
+ },
+
+ /**
+ * Change the format to 'escaped' and convert message to string
+ *
+ * This is equivalent to using the 'text' format (see #text), then
+ * HTML-escaping the output.
+ *
+ * @return {string} String form of html escaped message
+ */
+ escaped: function () {
+ this.format = 'escaped';
+ return this.toString();
+ },
+
+ /**
+ * Check if a message exists
+ *
+ * @see mw.Map#exists
+ * @return {boolean}
+ */
+ exists: function () {
+ return this.map.exists( this.key );
+ }
+ };
+
+ defineFallbacks();
+
+ /* eslint-disable no-console */
+ log = ( function () {
+ /**
+ * Write a verbose message to the browser's console in debug mode.
+ *
+ * This method is mainly intended for verbose logging. It is a no-op in production mode.
+ * In ResourceLoader debug mode, it will use the browser's console if available, with
+ * fallback to creating a console interface in the DOM and logging messages there.
+ *
+ * See {@link mw.log} for other logging methods.
+ *
+ * @member mw
+ * @param {...string} msg Messages to output to console.
+ */
+ var log = function () {},
+ console = window.console;
+
+ // Note: Keep list of methods in sync with restoration in mediawiki.log.js
+ // when adding or removing mw.log methods below!
+
+ /**
+ * Collection of methods to help log messages to the console.
+ *
+ * @class mw.log
+ * @singleton
+ */
+
+ /**
+ * Write a message to the browser console's warning channel.
+ *
+ * This method is a no-op in browsers that don't implement the Console API.
+ *
+ * @param {...string} msg Messages to output to console
+ */
+ log.warn = console && console.warn && Function.prototype.bind ?
+ Function.prototype.bind.call( console.warn, console ) :
+ $.noop;
+
+ /**
+ * Write a message to the browser console's error channel.
+ *
+ * Most browsers also print a stacktrace when calling this method if the
+ * argument is an Error object.
+ *
+ * This method is a no-op in browsers that don't implement the Console API.
+ *
+ * @since 1.26
+ * @param {Error|...string} msg Messages to output to console
+ */
+ log.error = console && console.error && Function.prototype.bind ?
+ Function.prototype.bind.call( console.error, console ) :
+ $.noop;
+
+ /**
+ * Create a property on a host object that, when accessed, will produce
+ * a deprecation warning in the console.
+ *
+ * @param {Object} obj Host object of deprecated property
+ * @param {string} key Name of property to create in `obj`
+ * @param {Mixed} val The value this property should return when accessed
+ * @param {string} [msg] Optional text to include in the deprecation message
+ * @param {string} [logName=key] Optional custom name for the feature.
+ * This is used instead of `key` in the message and `mw.deprecate` tracking.
+ */
+ log.deprecate = !Object.defineProperty ? function ( obj, key, val ) {
+ obj[ key ] = val;
+ } : function ( obj, key, val, msg, logName ) {
+ var logged = new StringSet();
+ logName = logName || key;
+ msg = 'Use of "' + logName + '" is deprecated.' + ( msg ? ( ' ' + msg ) : '' );
+ function uniqueTrace() {
+ var trace = new Error().stack;
+ if ( logged.has( trace ) ) {
+ return false;
+ }
+ logged.add( trace );
+ return true;
+ }
+ // Support: Safari 5.0
+ // Throws "not supported on DOM Objects" for Node or Element objects (incl. document)
+ // Safari 4.0 doesn't have this method, and it was fixed in Safari 5.1.
+ try {
+ Object.defineProperty( obj, key, {
+ configurable: true,
+ enumerable: true,
+ get: function () {
+ if ( uniqueTrace() ) {
+ mw.track( 'mw.deprecate', logName );
+ mw.log.warn( msg );
+ }
+ return val;
+ },
+ set: function ( newVal ) {
+ if ( uniqueTrace() ) {
+ mw.track( 'mw.deprecate', logName );
+ mw.log.warn( msg );
+ }
+ val = newVal;
+ }
+ } );
+ } catch ( err ) {
+ obj[ key ] = val;
+ }
+ };
+
+ return log;
+ }() );
+ /* eslint-enable no-console */
+
+ /**
+ * @class mw
+ */
+ mw = {
+ redefineFallbacksForTest: function () {
+ if ( !window.QUnit ) {
+ throw new Error( 'Reset not allowed outside unit tests' );
+ }
+ defineFallbacks();
+ },
+
+ /**
+ * Get the current time, measured in milliseconds since January 1, 1970 (UTC).
+ *
+ * On browsers that implement the Navigation Timing API, this function will produce floating-point
+ * values with microsecond precision that are guaranteed to be monotonic. On all other browsers,
+ * it will fall back to using `Date`.
+ *
+ * @return {number} Current time
+ */
+ now: mwNow,
+ // mwNow is defined in startup.js
+
+ /**
+ * Format a string. Replace $1, $2 ... $N with positional arguments.
+ *
+ * Used by Message#parser().
+ *
+ * @since 1.25
+ * @param {string} formatString Format string
+ * @param {...Mixed} parameters Values for $N replacements
+ * @return {string} Formatted string
+ */
+ format: function ( formatString ) {
+ var parameters = slice.call( arguments, 1 );
+ return formatString.replace( /\$(\d+)/g, function ( str, match ) {
+ var index = parseInt( match, 10 ) - 1;
+ return parameters[ index ] !== undefined ? parameters[ index ] : '$' + match;
+ } );
+ },
+
+ /**
+ * Track an analytic event.
+ *
+ * This method provides a generic means for MediaWiki JavaScript code to capture state
+ * information for analysis. Each logged event specifies a string topic name that describes
+ * the kind of event that it is. Topic names consist of dot-separated path components,
+ * arranged from most general to most specific. Each path component should have a clear and
+ * well-defined purpose.
+ *
+ * Data handlers are registered via `mw.trackSubscribe`, and receive the full set of
+ * events that match their subcription, including those that fired before the handler was
+ * bound.
+ *
+ * @param {string} topic Topic name
+ * @param {Object} [data] Data describing the event, encoded as an object
+ */
+ track: function ( topic, data ) {
+ trackQueue.push( { topic: topic, timeStamp: mw.now(), data: data } );
+ trackCallbacks.fire( trackQueue );
+ },
+
+ /**
+ * Register a handler for subset of analytic events, specified by topic.
+ *
+ * Handlers will be called once for each tracked event, including any events that fired before the
+ * handler was registered; 'this' is set to a plain object with a 'timeStamp' property indicating
+ * the exact time at which the event fired, a string 'topic' property naming the event, and a
+ * 'data' property which is an object of event-specific data. The event topic and event data are
+ * also passed to the callback as the first and second arguments, respectively.
+ *
+ * @param {string} topic Handle events whose name starts with this string prefix
+ * @param {Function} callback Handler to call for each matching tracked event
+ * @param {string} callback.topic
+ * @param {Object} [callback.data]
+ */
+ trackSubscribe: function ( topic, callback ) {
+ var seen = 0;
+ function handler( trackQueue ) {
+ var event;
+ for ( ; seen < trackQueue.length; seen++ ) {
+ event = trackQueue[ seen ];
+ if ( event.topic.indexOf( topic ) === 0 ) {
+ callback.call( event, event.topic, event.data );
+ }
+ }
+ }
+
+ trackHandlers.push( [ handler, callback ] );
+
+ trackCallbacks.add( handler );
+ },
+
+ /**
+ * Stop handling events for a particular handler
+ *
+ * @param {Function} callback
+ */
+ trackUnsubscribe: function ( callback ) {
+ trackHandlers = $.grep( trackHandlers, function ( fns ) {
+ if ( fns[ 1 ] === callback ) {
+ trackCallbacks.remove( fns[ 0 ] );
+ // Ensure the tuple is removed to avoid holding on to closures
+ return false;
+ }
+ return true;
+ } );
+ },
+
+ // Expose Map constructor
+ Map: Map,
+
+ // Expose Message constructor
+ Message: Message,
+
+ /**
+ * Map of configuration values.
+ *
+ * Check out [the complete list of configuration values](https://www.mediawiki.org/wiki/Manual:Interface/JavaScript#mw.config)
+ * on mediawiki.org.
+ *
+ * If `$wgLegacyJavaScriptGlobals` is true, this Map will add its values to the
+ * global `window` object.
+ *
+ * @property {mw.Map} config
+ */
+ // Dummy placeholder later assigned in ResourceLoaderStartUpModule
+ config: null,
+
+ /**
+ * Empty object for third-party libraries, for cases where you don't
+ * want to add a new global, or the global is bad and needs containment
+ * or wrapping.
+ *
+ * @property
+ */
+ libs: {},
+
+ /**
+ * Access container for deprecated functionality that can be moved from
+ * from their legacy location and attached to this object (e.g. a global
+ * function that is deprecated and as stop-gap can be exposed through here).
+ *
+ * This was reserved for future use but never ended up being used.
+ *
+ * @deprecated since 1.22 Let deprecated identifiers keep their original name
+ * and use mw.log#deprecate to create an access container for tracking.
+ * @property
+ */
+ legacy: {},
+
+ /**
+ * Store for messages.
+ *
+ * @property {mw.Map}
+ */
+ messages: new Map(),
+
+ /**
+ * Store for templates associated with a module.
+ *
+ * @property {mw.Map}
+ */
+ templates: new Map(),
+
+ /**
+ * Get a message object.
+ *
+ * Shortcut for `new mw.Message( mw.messages, key, parameters )`.
+ *
+ * @see mw.Message
+ * @param {string} key Key of message to get
+ * @param {...Mixed} parameters Values for $N replacements
+ * @return {mw.Message}
+ */
+ message: function ( key ) {
+ var parameters = slice.call( arguments, 1 );
+ return new Message( mw.messages, key, parameters );
+ },
+
+ /**
+ * Get a message string using the (default) 'text' format.
+ *
+ * Shortcut for `mw.message( key, parameters... ).text()`.
+ *
+ * @see mw.Message
+ * @param {string} key Key of message to get
+ * @param {...Mixed} parameters Values for $N replacements
+ * @return {string}
+ */
+ msg: function () {
+ return mw.message.apply( mw.message, arguments ).toString();
+ },
+
+ // Expose mw.log
+ log: log,
+
+ /**
+ * Client for ResourceLoader server end point.
+ *
+ * This client is in charge of maintaining the module registry and state
+ * machine, initiating network (batch) requests for loading modules, as
+ * well as dependency resolution and execution of source code.
+ *
+ * For more information, refer to
+ * <https://www.mediawiki.org/wiki/ResourceLoader/Features>
+ *
+ * @class mw.loader
+ * @singleton
+ */
+ loader: ( function () {
+
+ /**
+ * Fired via mw.track on various resource loading errors.
+ *
+ * @event resourceloader_exception
+ * @param {Error|Mixed} e The error that was thrown. Almost always an Error
+ * object, but in theory module code could manually throw something else, and that
+ * might also end up here.
+ * @param {string} [module] Name of the module which caused the error. Omitted if the
+ * error is not module-related or the module cannot be easily identified due to
+ * batched handling.
+ * @param {string} source Source of the error. Possible values:
+ *
+ * - style: stylesheet error (only affects old IE where a special style loading method
+ * is used)
+ * - load-callback: exception thrown by user callback
+ * - module-execute: exception thrown by module code
+ * - resolve: failed to sort dependencies for a module in mw.loader.load
+ * - store-eval: could not evaluate module code cached in localStorage
+ * - store-localstorage-init: localStorage or JSON parse error in mw.loader.store.init
+ * - store-localstorage-json: JSON conversion error in mw.loader.store.set
+ * - store-localstorage-update: localStorage or JSON conversion error in mw.loader.store.update
+ */
+
+ /**
+ * Fired via mw.track on resource loading error conditions.
+ *
+ * @event resourceloader_assert
+ * @param {string} source Source of the error. Possible values:
+ *
+ * - bug-T59567: failed to cache script due to an Opera function -> string conversion
+ * bug; see <https://phabricator.wikimedia.org/T59567> for details
+ */
+
+ /**
+ * Mapping of registered modules.
+ *
+ * See #implement and #execute for exact details on support for script, style and messages.
+ *
+ * Format:
+ *
+ * {
+ * 'moduleName': {
+ * // From mw.loader.register()
+ * 'version': '########' (hash)
+ * 'dependencies': ['required.foo', 'bar.also', ...], (or) function () {}
+ * 'group': 'somegroup', (or) null
+ * 'source': 'local', (or) 'anotherwiki'
+ * 'skip': 'return !!window.Example', (or) null
+ * 'module': export Object
+ *
+ * // Set from execute() or mw.loader.state()
+ * 'state': 'registered', 'loaded', 'loading', 'ready', 'error', or 'missing'
+ *
+ * // Optionally added at run-time by mw.loader.implement()
+ * 'skipped': true
+ * 'script': closure, array of urls, or string
+ * 'style': { ... } (see #execute)
+ * 'messages': { 'key': 'value', ... }
+ * }
+ * }
+ *
+ * State machine:
+ *
+ * - `registered`:
+ * The module is known to the system but not yet required.
+ * Meta data is registered via mw.loader#register. Calls to that method are
+ * generated server-side by the startup module.
+ * - `loading`:
+ * The module was required through mw.loader (either directly or as dependency of
+ * another module). The client will fetch module contents from the server.
+ * The contents are then stashed in the registry via mw.loader#implement.
+ * - `loaded`:
+ * The module has been loaded from the server and stashed via mw.loader#implement.
+ * If the module has no more dependencies in-flight, the module will be executed
+ * immediately. Otherwise execution is deferred, controlled via #handlePending.
+ * - `executing`:
+ * The module is being executed.
+ * - `ready`:
+ * The module has been successfully executed.
+ * - `error`:
+ * The module (or one of its dependencies) produced an error during execution.
+ * - `missing`:
+ * The module was registered client-side and requested, but the server denied knowledge
+ * of the module's existence.
+ *
+ * @property
+ * @private
+ */
+ var registry = {},
+ // Mapping of sources, keyed by source-id, values are strings.
+ //
+ // Format:
+ //
+ // {
+ // 'sourceId': 'http://example.org/w/load.php'
+ // }
+ //
+ sources = {},
+
+ // For queueModuleScript()
+ handlingPendingRequests = false,
+ pendingRequests = [],
+
+ // List of modules to be loaded
+ queue = [],
+
+ /**
+ * List of callback jobs waiting for modules to be ready.
+ *
+ * Jobs are created by #enqueue() and run by #handlePending().
+ *
+ * Typically when a job is created for a module, the job's dependencies contain
+ * both the required module and all its recursive dependencies.
+ *
+ * Format:
+ *
+ * {
+ * 'dependencies': [ module names ],
+ * 'ready': Function callback
+ * 'error': Function callback
+ * }
+ *
+ * @property {Object[]} jobs
+ * @private
+ */
+ jobs = [],
+
+ // For getMarker()
+ marker = null,
+
+ // For addEmbeddedCSS()
+ cssBuffer = '',
+ cssBufferTimer = null,
+ cssCallbacks = $.Callbacks(),
+ rAF = window.requestAnimationFrame || setTimeout;
+
+ function getMarker() {
+ if ( !marker ) {
+ // Cache
+ marker = document.querySelector( 'meta[name="ResourceLoaderDynamicStyles"]' );
+ if ( !marker ) {
+ mw.log( 'Create <meta name="ResourceLoaderDynamicStyles"> dynamically' );
+ marker = $( '<meta>' ).attr( 'name', 'ResourceLoaderDynamicStyles' ).appendTo( 'head' )[ 0 ];
+ }
+ }
+ return marker;
+ }
+
+ /**
+ * Create a new style element and add it to the DOM.
+ *
+ * @private
+ * @param {string} text CSS text
+ * @param {Node} [nextNode] The element where the style tag
+ * should be inserted before
+ * @return {HTMLElement} Reference to the created style element
+ */
+ function newStyleTag( text, nextNode ) {
+ var s = document.createElement( 'style' );
+
+ s.appendChild( document.createTextNode( text ) );
+ if ( nextNode && nextNode.parentNode ) {
+ nextNode.parentNode.insertBefore( s, nextNode );
+ } else {
+ document.getElementsByTagName( 'head' )[ 0 ].appendChild( s );
+ }
+
+ return s;
+ }
+
+ /**
+ * Add a bit of CSS text to the current browser page.
+ *
+ * The CSS will be appended to an existing ResourceLoader-created `<style>` tag
+ * or create a new one based on whether the given `cssText` is safe for extension.
+ *
+ * @private
+ * @param {string} [cssText=cssBuffer] If called without cssText,
+ * the internal buffer will be inserted instead.
+ * @param {Function} [callback]
+ */
+ function addEmbeddedCSS( cssText, callback ) {
+ function fireCallbacks() {
+ var oldCallbacks = cssCallbacks;
+ // Reset cssCallbacks variable so it's not polluted by any calls to
+ // addEmbeddedCSS() from one of the callbacks (T105973)
+ cssCallbacks = $.Callbacks();
+ oldCallbacks.fire().empty();
+ }
+
+ if ( callback ) {
+ cssCallbacks.add( callback );
+ }
+
+ // Yield once before creating the <style> tag. This lets multiple stylesheets
+ // accumulate into one buffer, allowing us to reduce how often new stylesheets
+ // are inserted in the browser. Appending a stylesheet and waiting for the
+ // browser to repaint is fairly expensive. (T47810)
+ if ( cssText ) {
+ // Don't extend the buffer if the item needs its own stylesheet.
+ // Keywords like `@import` are only valid at the start of a stylesheet (T37562).
+ if ( !cssBuffer || cssText.slice( 0, '@import'.length ) !== '@import' ) {
+ // Linebreak for somewhat distinguishable sections
+ cssBuffer += '\n' + cssText;
+ if ( !cssBufferTimer ) {
+ cssBufferTimer = rAF( function () {
+ // Wrap in anonymous function that takes no arguments
+ // Support: Firefox < 13
+ // Firefox 12 has non-standard behaviour of passing a number
+ // as first argument to a setTimeout callback.
+ // http://benalman.com/news/2009/07/the-mysterious-firefox-settime/
+ addEmbeddedCSS();
+ } );
+ }
+ return;
+ }
+
+ // This is a scheduled flush for the buffer
+ } else {
+ cssBufferTimer = null;
+ cssText = cssBuffer;
+ cssBuffer = '';
+ }
+
+ $( newStyleTag( cssText, getMarker() ) );
+
+ fireCallbacks();
+ }
+
+ /**
+ * @private
+ * @param {Array} modules List of module names
+ * @return {string} Hash of concatenated version hashes.
+ */
+ function getCombinedVersion( modules ) {
+ var hashes = modules.map( function ( module ) {
+ return registry[ module ].version;
+ } );
+ return fnv132( hashes.join( '' ) );
+ }
+
+ /**
+ * Determine whether all dependencies are in state 'ready', which means we may
+ * execute the module or job now.
+ *
+ * @private
+ * @param {Array} modules Names of modules to be checked
+ * @return {boolean} True if all modules are in state 'ready', false otherwise
+ */
+ function allReady( modules ) {
+ var i;
+ for ( i = 0; i < modules.length; i++ ) {
+ if ( mw.loader.getState( modules[ i ] ) !== 'ready' ) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Determine whether all dependencies are in state 'ready', which means we may
+ * execute the module or job now.
+ *
+ * @private
+ * @param {Array} modules Names of modules to be checked
+ * @return {boolean} True if no modules are in state 'error' or 'missing', false otherwise
+ */
+ function anyFailed( modules ) {
+ var i, state;
+ for ( i = 0; i < modules.length; i++ ) {
+ state = mw.loader.getState( modules[ i ] );
+ if ( state === 'error' || state === 'missing' ) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * A module has entered state 'ready', 'error', or 'missing'. Automatically update
+ * pending jobs and modules that depend upon this module. If the given module failed,
+ * propagate the 'error' state up the dependency tree. Otherwise, go ahead and execute
+ * all jobs/modules now having their dependencies satisfied.
+ *
+ * Jobs that depend on a failed module, will have their error callback ran (if any).
+ *
+ * @private
+ * @param {string} module Name of module that entered one of the states 'ready', 'error', or 'missing'.
+ */
+ function handlePending( module ) {
+ var j, job, hasErrors, m, stateChange;
+
+ if ( registry[ module ].state === 'error' || registry[ module ].state === 'missing' ) {
+ // If the current module failed, mark all dependent modules also as failed.
+ // Iterate until steady-state to propagate the error state upwards in the
+ // dependency tree.
+ do {
+ stateChange = false;
+ for ( m in registry ) {
+ if ( registry[ m ].state !== 'error' && registry[ m ].state !== 'missing' ) {
+ if ( anyFailed( registry[ m ].dependencies ) ) {
+ registry[ m ].state = 'error';
+ stateChange = true;
+ }
+ }
+ }
+ } while ( stateChange );
+ }
+
+ // Execute all jobs whose dependencies are either all satisfied or contain at least one failed module.
+ for ( j = 0; j < jobs.length; j++ ) {
+ hasErrors = anyFailed( jobs[ j ].dependencies );
+ if ( hasErrors || allReady( jobs[ j ].dependencies ) ) {
+ // All dependencies satisfied, or some have errors
+ job = jobs[ j ];
+ jobs.splice( j, 1 );
+ j -= 1;
+ try {
+ if ( hasErrors ) {
+ if ( typeof job.error === 'function' ) {
+ job.error( new Error( 'Module ' + module + ' has failed dependencies' ), [ module ] );
+ }
+ } else {
+ if ( typeof job.ready === 'function' ) {
+ job.ready();
+ }
+ }
+ } catch ( e ) {
+ // A user-defined callback raised an exception.
+ // Swallow it to protect our state machine!
+ mw.track( 'resourceloader.exception', { exception: e, module: module, source: 'load-callback' } );
+ }
+ }
+ }
+
+ if ( registry[ module ].state === 'ready' ) {
+ // The current module became 'ready'. Set it in the module store, and recursively execute all
+ // dependent modules that are loaded and now have all dependencies satisfied.
+ mw.loader.store.set( module, registry[ module ] );
+ for ( m in registry ) {
+ if ( registry[ m ].state === 'loaded' && allReady( registry[ m ].dependencies ) ) {
+ execute( m );
+ }
+ }
+ }
+ }
+
+ /**
+ * Resolve dependencies and detect circular references.
+ *
+ * @private
+ * @param {string} module Name of the top-level module whose dependencies shall be
+ * resolved and sorted.
+ * @param {Array} resolved Returns a topological sort of the given module and its
+ * dependencies, such that later modules depend on earlier modules. The array
+ * contains the module names. If the array contains already some module names,
+ * this function appends its result to the pre-existing array.
+ * @param {StringSet} [unresolved] Used to track the current dependency
+ * chain, and to report loops in the dependency graph.
+ * @throws {Error} If any unregistered module or a dependency loop is encountered
+ */
+ function sortDependencies( module, resolved, unresolved ) {
+ var i, deps, skip;
+
+ if ( !hasOwn.call( registry, module ) ) {
+ throw new Error( 'Unknown dependency: ' + module );
+ }
+
+ if ( registry[ module ].skip !== null ) {
+ // eslint-disable-next-line no-new-func
+ skip = new Function( registry[ module ].skip );
+ registry[ module ].skip = null;
+ if ( skip() ) {
+ registry[ module ].skipped = true;
+ registry[ module ].dependencies = [];
+ registry[ module ].state = 'ready';
+ handlePending( module );
+ return;
+ }
+ }
+
+ // Resolves dynamic loader function and replaces it with its own results
+ if ( typeof registry[ module ].dependencies === 'function' ) {
+ registry[ module ].dependencies = registry[ module ].dependencies();
+ // Ensures the module's dependencies are always in an array
+ if ( typeof registry[ module ].dependencies !== 'object' ) {
+ registry[ module ].dependencies = [ registry[ module ].dependencies ];
+ }
+ }
+ if ( $.inArray( module, resolved ) !== -1 ) {
+ // Module already resolved; nothing to do
+ return;
+ }
+ // Create unresolved if not passed in
+ if ( !unresolved ) {
+ unresolved = new StringSet();
+ }
+ // Tracks down dependencies
+ deps = registry[ module ].dependencies;
+ for ( i = 0; i < deps.length; i++ ) {
+ if ( $.inArray( deps[ i ], resolved ) === -1 ) {
+ if ( unresolved.has( deps[ i ] ) ) {
+ throw new Error( mw.format(
+ 'Circular reference detected: $1 -> $2',
+ module,
+ deps[ i ]
+ ) );
+ }
+
+ unresolved.add( module );
+ sortDependencies( deps[ i ], resolved, unresolved );
+ }
+ }
+ resolved.push( module );
+ }
+
+ /**
+ * Get names of module that a module depends on, in their proper dependency order.
+ *
+ * @private
+ * @param {string[]} modules Array of string module names
+ * @return {Array} List of dependencies, including 'module'.
+ * @throws {Error} If an unregistered module or a dependency loop is encountered
+ */
+ function resolve( modules ) {
+ var i, resolved = [];
+ for ( i = 0; i < modules.length; i++ ) {
+ sortDependencies( modules[ i ], resolved );
+ }
+ return resolved;
+ }
+
+ /**
+ * Like #resolve(), except it will silently ignore modules that
+ * are missing or have missing dependencies.
+ *
+ * @private
+ * @param {string[]} modules Array of string module names
+ * @return {Array} List of dependencies.
+ */
+ function resolveStubbornly( modules ) {
+ var i, saved, resolved = [];
+ for ( i = 0; i < modules.length; i++ ) {
+ saved = resolved.slice();
+ try {
+ sortDependencies( modules[ i ], resolved );
+ } catch ( err ) {
+ // This module is unknown or has unknown dependencies.
+ // Undo any incomplete resolutions made and keep going.
+ resolved = saved;
+ mw.track( 'resourceloader.exception', {
+ exception: err,
+ source: 'resolve'
+ } );
+ }
+ }
+ return resolved;
+ }
+
+ /**
+ * Load and execute a script.
+ *
+ * @private
+ * @param {string} src URL to script, will be used as the src attribute in the script tag
+ * @return {jQuery.Promise}
+ */
+ function addScript( src ) {
+ return $.ajax( {
+ url: src,
+ dataType: 'script',
+ // Force jQuery behaviour to be for crossDomain. Otherwise jQuery would use
+ // XHR for a same domain request instead of <script>, which changes the request
+ // headers (potentially missing a cache hit), and reduces caching in general
+ // since browsers cache XHR much less (if at all). And XHR means we retrieve
+ // text, so we'd need to $.globalEval, which then messes up line numbers.
+ crossDomain: true,
+ cache: true
+ } );
+ }
+
+ /**
+ * Queue the loading and execution of a script for a particular module.
+ *
+ * @private
+ * @param {string} src URL of the script
+ * @param {string} [moduleName] Name of currently executing module
+ * @return {jQuery.Promise}
+ */
+ function queueModuleScript( src, moduleName ) {
+ var r = $.Deferred();
+
+ pendingRequests.push( function () {
+ if ( moduleName && hasOwn.call( registry, moduleName ) ) {
+ // Emulate runScript() part of execute()
+ window.require = mw.loader.require;
+ window.module = registry[ moduleName ].module;
+ }
+ addScript( src ).always( function () {
+ // 'module.exports' should not persist after the file is executed to
+ // avoid leakage to unrelated code. 'require' should be kept, however,
+ // as asynchronous access to 'require' is allowed and expected. (T144879)
+ delete window.module;
+ r.resolve();
+
+ // Start the next one (if any)
+ if ( pendingRequests[ 0 ] ) {
+ pendingRequests.shift()();
+ } else {
+ handlingPendingRequests = false;
+ }
+ } );
+ } );
+ if ( !handlingPendingRequests && pendingRequests[ 0 ] ) {
+ handlingPendingRequests = true;
+ pendingRequests.shift()();
+ }
+ return r.promise();
+ }
+
+ /**
+ * Utility function for execute()
+ *
+ * @ignore
+ * @param {string} [media] Media attribute
+ * @param {string} url URL
+ */
+ function addLink( media, url ) {
+ var el = document.createElement( 'link' );
+
+ el.rel = 'stylesheet';
+ if ( media && media !== 'all' ) {
+ el.media = media;
+ }
+ // If you end up here from an IE exception "SCRIPT: Invalid property value.",
+ // see #addEmbeddedCSS, T33676, T43331, and T49277 for details.
+ el.href = url;
+
+ $( getMarker() ).before( el );
+ }
+
+ /**
+ * Executes a loaded module, making it ready to use
+ *
+ * @private
+ * @param {string} module Module name to execute
+ */
+ function execute( module ) {
+ var key, value, media, i, urls, cssHandle, checkCssHandles, runScript,
+ cssHandlesRegistered = false;
+
+ if ( !hasOwn.call( registry, module ) ) {
+ throw new Error( 'Module has not been registered yet: ' + module );
+ }
+ if ( registry[ module ].state !== 'loaded' ) {
+ throw new Error( 'Module in state "' + registry[ module ].state + '" may not be executed: ' + module );
+ }
+
+ registry[ module ].state = 'executing';
+
+ runScript = function () {
+ var script, markModuleReady, nestedAddScript;
+
+ script = registry[ module ].script;
+ markModuleReady = function () {
+ registry[ module ].state = 'ready';
+ handlePending( module );
+ };
+ nestedAddScript = function ( arr, callback, i ) {
+ // Recursively call queueModuleScript() in its own callback
+ // for each element of arr.
+ if ( i >= arr.length ) {
+ // We're at the end of the array
+ callback();
+ return;
+ }
+
+ queueModuleScript( arr[ i ], module ).always( function () {
+ nestedAddScript( arr, callback, i + 1 );
+ } );
+ };
+
+ try {
+ if ( Array.isArray( script ) ) {
+ nestedAddScript( script, markModuleReady, 0 );
+ } else if ( typeof script === 'function' ) {
+ // Pass jQuery twice so that the signature of the closure which wraps
+ // the script can bind both '$' and 'jQuery'.
+ script( $, $, mw.loader.require, registry[ module ].module );
+ markModuleReady();
+
+ } else if ( typeof script === 'string' ) {
+ // Site and user modules are legacy scripts that run in the global scope.
+ // This is transported as a string instead of a function to avoid needing
+ // to use string manipulation to undo the function wrapper.
+ $.globalEval( script );
+ markModuleReady();
+
+ } else {
+ // Module without script
+ markModuleReady();
+ }
+ } catch ( e ) {
+ // Use mw.track instead of mw.log because these errors are common in production mode
+ // (e.g. undefined variable), and mw.log is only enabled in debug mode.
+ registry[ module ].state = 'error';
+ mw.track( 'resourceloader.exception', { exception: e, module: module, source: 'module-execute' } );
+ handlePending( module );
+ }
+ };
+
+ // Add localizations to message system
+ if ( registry[ module ].messages ) {
+ mw.messages.set( registry[ module ].messages );
+ }
+
+ // Initialise templates
+ if ( registry[ module ].templates ) {
+ mw.templates.set( module, registry[ module ].templates );
+ }
+
+ // Make sure we don't run the scripts until all stylesheet insertions have completed.
+ ( function () {
+ var pending = 0;
+ checkCssHandles = function () {
+ // cssHandlesRegistered ensures we don't take off too soon, e.g. when
+ // one of the cssHandles is fired while we're still creating more handles.
+ if ( cssHandlesRegistered && pending === 0 && runScript ) {
+ if ( module === 'user' ) {
+ // Implicit dependency on the site module. Not real dependency because
+ // it should run after 'site' regardless of whether it succeeds or fails.
+ mw.loader.using( [ 'site' ] ).always( runScript );
+ } else {
+ runScript();
+ }
+ runScript = undefined; // Revoke
+ }
+ };
+ cssHandle = function () {
+ var check = checkCssHandles;
+ pending++;
+ return function () {
+ if ( check ) {
+ pending--;
+ check();
+ check = undefined; // Revoke
+ }
+ };
+ };
+ }() );
+
+ // Process styles (see also mw.loader.implement)
+ // * back-compat: { <media>: css }
+ // * back-compat: { <media>: [url, ..] }
+ // * { "css": [css, ..] }
+ // * { "url": { <media>: [url, ..] } }
+ if ( registry[ module ].style ) {
+ for ( key in registry[ module ].style ) {
+ value = registry[ module ].style[ key ];
+ media = undefined;
+
+ if ( key !== 'url' && key !== 'css' ) {
+ // Backwards compatibility, key is a media-type
+ if ( typeof value === 'string' ) {
+ // back-compat: { <media>: css }
+ // Ignore 'media' because it isn't supported (nor was it used).
+ // Strings are pre-wrapped in "@media". The media-type was just ""
+ // (because it had to be set to something).
+ // This is one of the reasons why this format is no longer used.
+ addEmbeddedCSS( value, cssHandle() );
+ } else {
+ // back-compat: { <media>: [url, ..] }
+ media = key;
+ key = 'bc-url';
+ }
+ }
+
+ // Array of css strings in key 'css',
+ // or back-compat array of urls from media-type
+ if ( Array.isArray( value ) ) {
+ for ( i = 0; i < value.length; i++ ) {
+ if ( key === 'bc-url' ) {
+ // back-compat: { <media>: [url, ..] }
+ addLink( media, value[ i ] );
+ } else if ( key === 'css' ) {
+ // { "css": [css, ..] }
+ addEmbeddedCSS( value[ i ], cssHandle() );
+ }
+ }
+ // Not an array, but a regular object
+ // Array of urls inside media-type key
+ } else if ( typeof value === 'object' ) {
+ // { "url": { <media>: [url, ..] } }
+ for ( media in value ) {
+ urls = value[ media ];
+ for ( i = 0; i < urls.length; i++ ) {
+ addLink( media, urls[ i ] );
+ }
+ }
+ }
+ }
+ }
+
+ // Kick off.
+ cssHandlesRegistered = true;
+ checkCssHandles();
+ }
+
+ /**
+ * Add one or more modules to the module load queue.
+ *
+ * See also #work().
+ *
+ * @private
+ * @param {string|string[]} dependencies Module name or array of string module names
+ * @param {Function} [ready] Callback to execute when all dependencies are ready
+ * @param {Function} [error] Callback to execute when any dependency fails
+ */
+ function enqueue( dependencies, ready, error ) {
+ // Allow calling by single module name
+ if ( typeof dependencies === 'string' ) {
+ dependencies = [ dependencies ];
+ }
+
+ // Add ready and error callbacks if they were given
+ if ( ready !== undefined || error !== undefined ) {
+ jobs.push( {
+ // Narrow down the list to modules that are worth waiting for
+ dependencies: $.grep( dependencies, function ( module ) {
+ var state = mw.loader.getState( module );
+ return state === 'registered' || state === 'loaded' || state === 'loading' || state === 'executing';
+ } ),
+ ready: ready,
+ error: error
+ } );
+ }
+
+ $.each( dependencies, function ( idx, module ) {
+ var state = mw.loader.getState( module );
+ // Only queue modules that are still in the initial 'registered' state
+ // (not ones already loading, ready or error).
+ if ( state === 'registered' && $.inArray( module, queue ) === -1 ) {
+ // Private modules must be embedded in the page. Don't bother queuing
+ // these as the server will deny them anyway (T101806).
+ if ( registry[ module ].group === 'private' ) {
+ registry[ module ].state = 'error';
+ handlePending( module );
+ return;
+ }
+ queue.push( module );
+ }
+ } );
+
+ mw.loader.work();
+ }
+
+ function sortQuery( o ) {
+ var key,
+ sorted = {},
+ a = [];
+
+ for ( key in o ) {
+ a.push( key );
+ }
+ a.sort();
+ for ( key = 0; key < a.length; key++ ) {
+ sorted[ a[ key ] ] = o[ a[ key ] ];
+ }
+ return sorted;
+ }
+
+ /**
+ * Converts a module map of the form { foo: [ 'bar', 'baz' ], bar: [ 'baz, 'quux' ] }
+ * to a query string of the form foo.bar,baz|bar.baz,quux
+ *
+ * @private
+ * @param {Object} moduleMap Module map
+ * @return {string} Module query string
+ */
+ function buildModulesString( moduleMap ) {
+ var p, prefix,
+ arr = [];
+
+ for ( prefix in moduleMap ) {
+ p = prefix === '' ? '' : prefix + '.';
+ arr.push( p + moduleMap[ prefix ].join( ',' ) );
+ }
+ return arr.join( '|' );
+ }
+
+ /**
+ * Make a network request to load modules from the server.
+ *
+ * @private
+ * @param {Object} moduleMap Module map, see #buildModulesString
+ * @param {Object} currReqBase Object with other parameters (other than 'modules') to use in the request
+ * @param {string} sourceLoadScript URL of load.php
+ */
+ function doRequest( moduleMap, currReqBase, sourceLoadScript ) {
+ // Optimisation: Inherit (Object.create), not copy ($.extend)
+ var query = Object.create( currReqBase );
+ query.modules = buildModulesString( moduleMap );
+ query = sortQuery( query );
+ addScript( sourceLoadScript + '?' + $.param( query ) );
+ }
+
+ /**
+ * Resolve indexed dependencies.
+ *
+ * ResourceLoader uses an optimization to save space which replaces module names in
+ * dependency lists with the index of that module within the array of module
+ * registration data if it exists. The benefit is a significant reduction in the data
+ * size of the startup module. This function changes those dependency lists back to
+ * arrays of strings.
+ *
+ * @private
+ * @param {Array} modules Modules array
+ */
+ function resolveIndexedDependencies( modules ) {
+ var i, j, deps;
+ function resolveIndex( dep ) {
+ return typeof dep === 'number' ? modules[ dep ][ 0 ] : dep;
+ }
+ for ( i = 0; i < modules.length; i++ ) {
+ deps = modules[ i ][ 2 ];
+ if ( deps ) {
+ for ( j = 0; j < deps.length; j++ ) {
+ deps[ j ] = resolveIndex( deps[ j ] );
+ }
+ }
+ }
+ }
+
+ /**
+ * Create network requests for a batch of modules.
+ *
+ * This is an internal method for #work(). This must not be called directly
+ * unless the modules are already registered, and no request is in progress,
+ * and the module state has already been set to `loading`.
+ *
+ * @private
+ * @param {string[]} batch
+ */
+ function batchRequest( batch ) {
+ var reqBase, splits, maxQueryLength, b, bSource, bGroup, bSourceGroup,
+ source, group, i, modules, sourceLoadScript,
+ currReqBase, currReqBaseLength, moduleMap, l,
+ lastDotIndex, prefix, suffix, bytesAdded;
+
+ if ( !batch.length ) {
+ return;
+ }
+
+ // Always order modules alphabetically to help reduce cache
+ // misses for otherwise identical content.
+ batch.sort();
+
+ // Build a list of query parameters common to all requests
+ reqBase = {
+ skin: mw.config.get( 'skin' ),
+ lang: mw.config.get( 'wgUserLanguage' ),
+ debug: mw.config.get( 'debug' )
+ };
+ maxQueryLength = mw.config.get( 'wgResourceLoaderMaxQueryLength', 2000 );
+
+ // Split module list by source and by group.
+ splits = {};
+ for ( b = 0; b < batch.length; b++ ) {
+ bSource = registry[ batch[ b ] ].source;
+ bGroup = registry[ batch[ b ] ].group;
+ if ( !hasOwn.call( splits, bSource ) ) {
+ splits[ bSource ] = {};
+ }
+ if ( !hasOwn.call( splits[ bSource ], bGroup ) ) {
+ splits[ bSource ][ bGroup ] = [];
+ }
+ bSourceGroup = splits[ bSource ][ bGroup ];
+ bSourceGroup.push( batch[ b ] );
+ }
+
+ for ( source in splits ) {
+
+ sourceLoadScript = sources[ source ];
+
+ for ( group in splits[ source ] ) {
+
+ // Cache access to currently selected list of
+ // modules for this group from this source.
+ modules = splits[ source ][ group ];
+
+ // Optimisation: Inherit (Object.create), not copy ($.extend)
+ currReqBase = Object.create( reqBase );
+ currReqBase.version = getCombinedVersion( modules );
+
+ // For user modules append a user name to the query string.
+ if ( group === 'user' && mw.config.get( 'wgUserName' ) !== null ) {
+ currReqBase.user = mw.config.get( 'wgUserName' );
+ }
+ currReqBaseLength = $.param( currReqBase ).length;
+ // We may need to split up the request to honor the query string length limit,
+ // so build it piece by piece.
+ l = currReqBaseLength + 9; // '&modules='.length == 9
+
+ moduleMap = {}; // { prefix: [ suffixes ] }
+
+ for ( i = 0; i < modules.length; i++ ) {
+ // Determine how many bytes this module would add to the query string
+ lastDotIndex = modules[ i ].lastIndexOf( '.' );
+
+ // If lastDotIndex is -1, substr() returns an empty string
+ prefix = modules[ i ].substr( 0, lastDotIndex );
+ suffix = modules[ i ].slice( lastDotIndex + 1 );
+
+ bytesAdded = hasOwn.call( moduleMap, prefix ) ?
+ suffix.length + 3 : // '%2C'.length == 3
+ modules[ i ].length + 3; // '%7C'.length == 3
+
+ // If the url would become too long, create a new one,
+ // but don't create empty requests
+ if ( maxQueryLength > 0 && !$.isEmptyObject( moduleMap ) && l + bytesAdded > maxQueryLength ) {
+ // This url would become too long, create a new one, and start the old one
+ doRequest( moduleMap, currReqBase, sourceLoadScript );
+ moduleMap = {};
+ l = currReqBaseLength + 9;
+ mw.track( 'resourceloader.splitRequest', { maxQueryLength: maxQueryLength } );
+ }
+ if ( !hasOwn.call( moduleMap, prefix ) ) {
+ moduleMap[ prefix ] = [];
+ }
+ moduleMap[ prefix ].push( suffix );
+ l += bytesAdded;
+ }
+ // If there's anything left in moduleMap, request that too
+ if ( !$.isEmptyObject( moduleMap ) ) {
+ doRequest( moduleMap, currReqBase, sourceLoadScript );
+ }
+ }
+ }
+ }
+
+ /**
+ * @private
+ * @param {string[]} implementations Array containing pieces of JavaScript code in the
+ * form of calls to mw.loader#implement().
+ * @param {Function} cb Callback in case of failure
+ * @param {Error} cb.err
+ */
+ function asyncEval( implementations, cb ) {
+ if ( !implementations.length ) {
+ return;
+ }
+ mw.requestIdleCallback( function () {
+ try {
+ $.globalEval( implementations.join( ';' ) );
+ } catch ( err ) {
+ cb( err );
+ }
+ } );
+ }
+
+ /**
+ * Make a versioned key for a specific module.
+ *
+ * @private
+ * @param {string} module Module name
+ * @return {string|null} Module key in format '`[name]@[version]`',
+ * or null if the module does not exist
+ */
+ function getModuleKey( module ) {
+ return hasOwn.call( registry, module ) ?
+ ( module + '@' + registry[ module ].version ) : null;
+ }
+
+ /**
+ * @private
+ * @param {string} key Module name or '`[name]@[version]`'
+ * @return {Object}
+ */
+ function splitModuleKey( key ) {
+ var index = key.indexOf( '@' );
+ if ( index === -1 ) {
+ return { name: key };
+ }
+ return {
+ name: key.slice( 0, index ),
+ version: key.slice( index + 1 )
+ };
+ }
+
+ /* Public Members */
+ return {
+ /**
+ * The module registry is exposed as an aid for debugging and inspecting page
+ * state; it is not a public interface for modifying the registry.
+ *
+ * @see #registry
+ * @property
+ * @private
+ */
+ moduleRegistry: registry,
+
+ /**
+ * @inheritdoc #newStyleTag
+ * @method
+ */
+ addStyleTag: newStyleTag,
+
+ /**
+ * Start loading of all queued module dependencies.
+ *
+ * @protected
+ */
+ work: function () {
+ var q, batch, implementations, sourceModules;
+
+ batch = [];
+
+ // Appends a list of modules from the queue to the batch
+ for ( q = 0; q < queue.length; q++ ) {
+ // Only load modules which are registered
+ if ( hasOwn.call( registry, queue[ q ] ) && registry[ queue[ q ] ].state === 'registered' ) {
+ // Prevent duplicate entries
+ if ( $.inArray( queue[ q ], batch ) === -1 ) {
+ batch.push( queue[ q ] );
+ // Mark registered modules as loading
+ registry[ queue[ q ] ].state = 'loading';
+ }
+ }
+ }
+
+ // Now that the queue has been processed into a batch, clear the queue.
+ // This MUST happen before we initiate any eval or network request. Otherwise,
+ // it is possible for a cached script to instantly trigger the same work queue
+ // again; all before we've cleared it causing each request to include modules
+ // which are already loaded.
+ queue = [];
+
+ if ( !batch.length ) {
+ return;
+ }
+
+ mw.loader.store.init();
+ if ( mw.loader.store.enabled ) {
+ implementations = [];
+ sourceModules = [];
+ batch = $.grep( batch, function ( module ) {
+ var implementation = mw.loader.store.get( module );
+ if ( implementation ) {
+ implementations.push( implementation );
+ sourceModules.push( module );
+ return false;
+ }
+ return true;
+ } );
+ asyncEval( implementations, function ( err ) {
+ var failed;
+ // Not good, the cached mw.loader.implement calls failed! This should
+ // never happen, barring ResourceLoader bugs, browser bugs and PEBKACs.
+ // Depending on how corrupt the string is, it is likely that some
+ // modules' implement() succeeded while the ones after the error will
+ // never run and leave their modules in the 'loading' state forever.
+ mw.loader.store.stats.failed++;
+
+ // Since this is an error not caused by an individual module but by
+ // something that infected the implement call itself, don't take any
+ // risks and clear everything in this cache.
+ mw.loader.store.clear();
+
+ mw.track( 'resourceloader.exception', { exception: err, source: 'store-eval' } );
+ // Re-add the failed ones that are still pending back to the batch
+ failed = $.grep( sourceModules, function ( module ) {
+ return registry[ module ].state === 'loading';
+ } );
+ batchRequest( failed );
+ } );
+ }
+
+ batchRequest( batch );
+ },
+
+ /**
+ * Register a source.
+ *
+ * The #work() method will use this information to split up requests by source.
+ *
+ * mw.loader.addSource( 'mediawikiwiki', '//www.mediawiki.org/w/load.php' );
+ *
+ * @param {string|Object} id Source ID, or object mapping ids to load urls
+ * @param {string} loadUrl Url to a load.php end point
+ * @throws {Error} If source id is already registered
+ */
+ addSource: function ( id, loadUrl ) {
+ var source;
+ // Allow multiple additions
+ if ( typeof id === 'object' ) {
+ for ( source in id ) {
+ mw.loader.addSource( source, id[ source ] );
+ }
+ return;
+ }
+
+ if ( hasOwn.call( sources, id ) ) {
+ throw new Error( 'source already registered: ' + id );
+ }
+
+ sources[ id ] = loadUrl;
+ },
+
+ /**
+ * Register a module, letting the system know about it and its properties.
+ *
+ * The startup modules contain calls to this method.
+ *
+ * When using multiple module registration by passing an array, dependencies that
+ * are specified as references to modules within the array will be resolved before
+ * the modules are registered.
+ *
+ * @param {string|Array} module Module name or array of arrays, each containing
+ * a list of arguments compatible with this method
+ * @param {string|number} version Module version hash (falls backs to empty string)
+ * Can also be a number (timestamp) for compatibility with MediaWiki 1.25 and earlier.
+ * @param {string|Array|Function} dependencies One string or array of strings of module
+ * names on which this module depends, or a function that returns that array.
+ * @param {string} [group=null] Group which the module is in
+ * @param {string} [source='local'] Name of the source
+ * @param {string} [skip=null] Script body of the skip function
+ */
+ register: function ( module, version, dependencies, group, source, skip ) {
+ var i, deps;
+ // Allow multiple registration
+ if ( typeof module === 'object' ) {
+ resolveIndexedDependencies( module );
+ for ( i = 0; i < module.length; i++ ) {
+ // module is an array of module names
+ if ( typeof module[ i ] === 'string' ) {
+ mw.loader.register( module[ i ] );
+ // module is an array of arrays
+ } else if ( typeof module[ i ] === 'object' ) {
+ mw.loader.register.apply( mw.loader, module[ i ] );
+ }
+ }
+ return;
+ }
+ if ( hasOwn.call( registry, module ) ) {
+ throw new Error( 'module already registered: ' + module );
+ }
+ if ( typeof dependencies === 'string' ) {
+ // A single module name
+ deps = [ dependencies ];
+ } else if ( typeof dependencies === 'object' || typeof dependencies === 'function' ) {
+ // Array of module names or a function that returns an array
+ deps = dependencies;
+ }
+ // List the module as registered
+ registry[ module ] = {
+ // Exposed to execute() for mw.loader.implement() closures.
+ // Import happens via require().
+ module: {
+ exports: {}
+ },
+ version: version !== undefined ? String( version ) : '',
+ dependencies: deps || [],
+ group: typeof group === 'string' ? group : null,
+ source: typeof source === 'string' ? source : 'local',
+ state: 'registered',
+ skip: typeof skip === 'string' ? skip : null
+ };
+ },
+
+ /**
+ * Implement a module given the components that make up the module.
+ *
+ * When #load() or #using() requests one or more modules, the server
+ * response contain calls to this function.
+ *
+ * @param {string} module Name of module and current module version. Formatted
+ * as '`[name]@[version]`". This version should match the requested version
+ * (from #batchRequest and #registry). This avoids race conditions (T117587).
+ * For back-compat with MediaWiki 1.27 and earlier, the version may be omitted.
+ * @param {Function|Array|string} [script] Function with module code, list of URLs
+ * to load via `<script src>`, or string of module code for `$.globalEval()`.
+ * @param {Object} [style] Should follow one of the following patterns:
+ *
+ * { "css": [css, ..] }
+ * { "url": { <media>: [url, ..] } }
+ *
+ * And for backwards compatibility (needs to be supported forever due to caching):
+ *
+ * { <media>: css }
+ * { <media>: [url, ..] }
+ *
+ * The reason css strings are not concatenated anymore is T33676. We now check
+ * whether it's safe to extend the stylesheet.
+ *
+ * @protected
+ * @param {Object} [messages] List of key/value pairs to be added to mw#messages.
+ * @param {Object} [templates] List of key/value pairs to be added to mw#templates.
+ */
+ implement: function ( module, script, style, messages, templates ) {
+ var split = splitModuleKey( module ),
+ name = split.name,
+ version = split.version;
+ // Automatically register module
+ if ( !hasOwn.call( registry, name ) ) {
+ mw.loader.register( name );
+ }
+ // Check for duplicate implementation
+ if ( hasOwn.call( registry, name ) && registry[ name ].script !== undefined ) {
+ throw new Error( 'module already implemented: ' + name );
+ }
+ if ( version ) {
+ // Without this reset, if there is a version mismatch between the
+ // requested and received module version, then mw.loader.store would
+ // cache the response under the requested key. Thus poisoning the cache
+ // indefinitely with a stale value. (T117587)
+ registry[ name ].version = version;
+ }
+ // Attach components
+ registry[ name ].script = script || null;
+ registry[ name ].style = style || null;
+ registry[ name ].messages = messages || null;
+ registry[ name ].templates = templates || null;
+ // The module may already have been marked as erroneous
+ if ( $.inArray( registry[ name ].state, [ 'error', 'missing' ] ) === -1 ) {
+ registry[ name ].state = 'loaded';
+ if ( allReady( registry[ name ].dependencies ) ) {
+ execute( name );
+ }
+ }
+ },
+
+ /**
+ * Execute a function as soon as one or more required modules are ready.
+ *
+ * Example of inline dependency on OOjs:
+ *
+ * mw.loader.using( 'oojs', function () {
+ * OO.compare( [ 1 ], [ 1 ] );
+ * } );
+ *
+ * Since MediaWiki 1.23 this also returns a promise.
+ *
+ * Since MediaWiki 1.28 the promise is resolved with a `require` function.
+ *
+ * @param {string|Array} dependencies Module name or array of modules names the
+ * callback depends on to be ready before executing
+ * @param {Function} [ready] Callback to execute when all dependencies are ready
+ * @param {Function} [error] Callback to execute if one or more dependencies failed
+ * @return {jQuery.Promise} With a `require` function
+ */
+ using: function ( dependencies, ready, error ) {
+ var deferred = $.Deferred();
+
+ // Allow calling with a single dependency as a string
+ if ( typeof dependencies === 'string' ) {
+ dependencies = [ dependencies ];
+ }
+
+ if ( ready ) {
+ deferred.done( ready );
+ }
+ if ( error ) {
+ deferred.fail( error );
+ }
+
+ try {
+ // Resolve entire dependency map
+ dependencies = resolve( dependencies );
+ } catch ( e ) {
+ return deferred.reject( e ).promise();
+ }
+ if ( allReady( dependencies ) ) {
+ // Run ready immediately
+ deferred.resolve( mw.loader.require );
+ } else if ( anyFailed( dependencies ) ) {
+ // Execute error immediately if any dependencies have errors
+ deferred.reject(
+ new Error( 'One or more dependencies failed to load' ),
+ dependencies
+ );
+ } else {
+ // Not all dependencies are ready, add to the load queue
+ enqueue( dependencies, function () {
+ deferred.resolve( mw.loader.require );
+ }, deferred.reject );
+ }
+
+ return deferred.promise();
+ },
+
+ /**
+ * Load an external script or one or more modules.
+ *
+ * This method takes a list of unrelated modules. Use cases:
+ *
+ * - A web page will be composed of many different widgets. These widgets independently
+ * queue their ResourceLoader modules (`OutputPage::addModules()`). If any of them
+ * have problems, or are no longer known (e.g. cached HTML), the other modules
+ * should still be loaded.
+ * - This method is used for preloading, which must not throw. Later code that
+ * calls #using() will handle the error.
+ *
+ * @param {string|Array} modules Either the name of a module, array of modules,
+ * or a URL of an external script or style
+ * @param {string} [type='text/javascript'] MIME type to use if calling with a URL of an
+ * external script or style; acceptable values are "text/css" and
+ * "text/javascript"; if no type is provided, text/javascript is assumed.
+ */
+ load: function ( modules, type ) {
+ var filtered, l;
+
+ // Allow calling with a url or single dependency as a string
+ if ( typeof modules === 'string' ) {
+ // "https://example.org/x.js", "http://example.org/x.js", "//example.org/x.js", "/x.js"
+ if ( /^(https?:)?\/?\//.test( modules ) ) {
+ if ( type === 'text/css' ) {
+ l = document.createElement( 'link' );
+ l.rel = 'stylesheet';
+ l.href = modules;
+ $( 'head' ).append( l );
+ return;
+ }
+ if ( type === 'text/javascript' || type === undefined ) {
+ addScript( modules );
+ return;
+ }
+ // Unknown type
+ throw new Error( 'invalid type for external url, must be text/css or text/javascript. not ' + type );
+ }
+ // Called with single module
+ modules = [ modules ];
+ }
+
+ // Filter out top-level modules that are unknown or failed to load before.
+ filtered = $.grep( modules, function ( module ) {
+ var state = mw.loader.getState( module );
+ return state !== 'error' && state !== 'missing';
+ } );
+ // Resolve remaining list using the known dependency tree.
+ // This also filters out modules with unknown dependencies. (T36853)
+ filtered = resolveStubbornly( filtered );
+ // If all modules are ready, or if any modules have errors, nothing to be done.
+ if ( allReady( filtered ) || anyFailed( filtered ) ) {
+ return;
+ }
+ if ( filtered.length === 0 ) {
+ return;
+ }
+ // Some modules are not yet ready, add to module load queue.
+ enqueue( filtered, undefined, undefined );
+ },
+
+ /**
+ * Change the state of one or more modules.
+ *
+ * @param {string|Object} module Module name or object of module name/state pairs
+ * @param {string} state State name
+ */
+ state: function ( module, state ) {
+ var m;
+
+ if ( typeof module === 'object' ) {
+ for ( m in module ) {
+ mw.loader.state( m, module[ m ] );
+ }
+ return;
+ }
+ if ( !hasOwn.call( registry, module ) ) {
+ mw.loader.register( module );
+ }
+ registry[ module ].state = state;
+ if ( $.inArray( state, [ 'ready', 'error', 'missing' ] ) !== -1 ) {
+ // Make sure pending modules depending on this one get executed if their
+ // dependencies are now fulfilled!
+ handlePending( module );
+ }
+ },
+
+ /**
+ * Get the version of a module.
+ *
+ * @param {string} module Name of module
+ * @return {string|null} The version, or null if the module (or its version) is not
+ * in the registry.
+ */
+ getVersion: function ( module ) {
+ if ( !hasOwn.call( registry, module ) || registry[ module ].version === undefined ) {
+ return null;
+ }
+ return registry[ module ].version;
+ },
+
+ /**
+ * Get the state of a module.
+ *
+ * @param {string} module Name of module
+ * @return {string|null} The state, or null if the module (or its state) is not
+ * in the registry.
+ */
+ getState: function ( module ) {
+ if ( !hasOwn.call( registry, module ) || registry[ module ].state === undefined ) {
+ return null;
+ }
+ return registry[ module ].state;
+ },
+
+ /**
+ * Get the names of all registered modules.
+ *
+ * @return {Array}
+ */
+ getModuleNames: function () {
+ return Object.keys( registry );
+ },
+
+ /**
+ * Get the exported value of a module.
+ *
+ * Modules may provide this via their local `module.exports`.
+ *
+ * @protected
+ * @since 1.27
+ * @param {string} moduleName Module name
+ * @return {Mixed} Exported value
+ */
+ require: function ( moduleName ) {
+ var state = mw.loader.getState( moduleName );
+
+ // Only ready modules can be required
+ if ( state !== 'ready' ) {
+ // Module may've forgotten to declare a dependency
+ throw new Error( 'Module "' + moduleName + '" is not loaded.' );
+ }
+
+ return registry[ moduleName ].module.exports;
+ },
+
+ /**
+ * @inheritdoc mw.inspect#runReports
+ * @method
+ */
+ inspect: function () {
+ var args = slice.call( arguments );
+ mw.loader.using( 'mediawiki.inspect', function () {
+ mw.inspect.runReports.apply( mw.inspect, args );
+ } );
+ },
+
+ /**
+ * On browsers that implement the localStorage API, the module store serves as a
+ * smart complement to the browser cache. Unlike the browser cache, the module store
+ * can slice a concatenated response from ResourceLoader into its constituent
+ * modules and cache each of them separately, using each module's versioning scheme
+ * to determine when the cache should be invalidated.
+ *
+ * @singleton
+ * @class mw.loader.store
+ */
+ store: {
+ // Whether the store is in use on this page.
+ enabled: null,
+
+ // Modules whose string representation exceeds 100 kB are
+ // ineligible for storage. See bug T66721.
+ MODULE_SIZE_MAX: 100 * 1000,
+
+ // The contents of the store, mapping '[name]@[version]' keys
+ // to module implementations.
+ items: {},
+
+ // Cache hit stats
+ stats: { hits: 0, misses: 0, expired: 0, failed: 0 },
+
+ /**
+ * Construct a JSON-serializable object representing the content of the store.
+ *
+ * @return {Object} Module store contents.
+ */
+ toJSON: function () {
+ return { items: mw.loader.store.items, vary: mw.loader.store.getVary() };
+ },
+
+ /**
+ * Get the localStorage key for the entire module store. The key references
+ * $wgDBname to prevent clashes between wikis which share a common host.
+ *
+ * @return {string} localStorage item key
+ */
+ getStoreKey: function () {
+ return 'MediaWikiModuleStore:' + mw.config.get( 'wgDBname' );
+ },
+
+ /**
+ * Get a key on which to vary the module cache.
+ *
+ * @return {string} String of concatenated vary conditions.
+ */
+ getVary: function () {
+ return [
+ mw.config.get( 'skin' ),
+ mw.config.get( 'wgResourceLoaderStorageVersion' ),
+ mw.config.get( 'wgUserLanguage' )
+ ].join( ':' );
+ },
+
+ /**
+ * Initialize the store.
+ *
+ * Retrieves store from localStorage and (if successfully retrieved) decoding
+ * the stored JSON value to a plain object.
+ *
+ * The try / catch block is used for JSON & localStorage feature detection.
+ * See the in-line documentation for Modernizr's localStorage feature detection
+ * code for a full account of why we need a try / catch:
+ * <https://github.com/Modernizr/Modernizr/blob/v2.7.1/modernizr.js#L771-L796>.
+ */
+ init: function () {
+ var raw, data;
+
+ if ( mw.loader.store.enabled !== null ) {
+ // Init already ran
+ return;
+ }
+
+ if (
+ // Disabled because localStorage quotas are tight and (in Firefox's case)
+ // shared by multiple origins.
+ // See T66721, and <https://bugzilla.mozilla.org/show_bug.cgi?id=1064466>.
+ /Firefox|Opera/.test( navigator.userAgent ) ||
+
+ // Disabled by configuration.
+ !mw.config.get( 'wgResourceLoaderStorageEnabled' )
+ ) {
+ // Clear any previous store to free up space. (T66721)
+ mw.loader.store.clear();
+ mw.loader.store.enabled = false;
+ return;
+ }
+ if ( mw.config.get( 'debug' ) ) {
+ // Disable module store in debug mode
+ mw.loader.store.enabled = false;
+ return;
+ }
+
+ try {
+ raw = localStorage.getItem( mw.loader.store.getStoreKey() );
+ // If we get here, localStorage is available; mark enabled
+ mw.loader.store.enabled = true;
+ data = JSON.parse( raw );
+ if ( data && typeof data.items === 'object' && data.vary === mw.loader.store.getVary() ) {
+ mw.loader.store.items = data.items;
+ return;
+ }
+ } catch ( e ) {
+ mw.track( 'resourceloader.exception', { exception: e, source: 'store-localstorage-init' } );
+ }
+
+ if ( raw === undefined ) {
+ // localStorage failed; disable store
+ mw.loader.store.enabled = false;
+ } else {
+ mw.loader.store.update();
+ }
+ },
+
+ /**
+ * Retrieve a module from the store and update cache hit stats.
+ *
+ * @param {string} module Module name
+ * @return {string|boolean} Module implementation or false if unavailable
+ */
+ get: function ( module ) {
+ var key;
+
+ if ( !mw.loader.store.enabled ) {
+ return false;
+ }
+
+ key = getModuleKey( module );
+ if ( key in mw.loader.store.items ) {
+ mw.loader.store.stats.hits++;
+ return mw.loader.store.items[ key ];
+ }
+ mw.loader.store.stats.misses++;
+ return false;
+ },
+
+ /**
+ * Stringify a module and queue it for storage.
+ *
+ * @param {string} module Module name
+ * @param {Object} descriptor The module's descriptor as set in the registry
+ * @return {boolean} Module was set
+ */
+ set: function ( module, descriptor ) {
+ var args, key, src;
+
+ if ( !mw.loader.store.enabled ) {
+ return false;
+ }
+
+ key = getModuleKey( module );
+
+ if (
+ // Already stored a copy of this exact version
+ key in mw.loader.store.items ||
+ // Module failed to load
+ descriptor.state !== 'ready' ||
+ // Unversioned, private, or site-/user-specific
+ ( !descriptor.version || $.inArray( descriptor.group, [ 'private', 'user' ] ) !== -1 ) ||
+ // Partial descriptor
+ // (e.g. skipped module, or style module with state=ready)
+ $.inArray( undefined, [ descriptor.script, descriptor.style,
+ descriptor.messages, descriptor.templates ] ) !== -1
+ ) {
+ // Decline to store
+ return false;
+ }
+
+ try {
+ args = [
+ JSON.stringify( key ),
+ typeof descriptor.script === 'function' ?
+ String( descriptor.script ) :
+ JSON.stringify( descriptor.script ),
+ JSON.stringify( descriptor.style ),
+ JSON.stringify( descriptor.messages ),
+ JSON.stringify( descriptor.templates )
+ ];
+ // Attempted workaround for a possible Opera bug (bug T59567).
+ // This regex should never match under sane conditions.
+ if ( /^\s*\(/.test( args[ 1 ] ) ) {
+ args[ 1 ] = 'function' + args[ 1 ];
+ mw.track( 'resourceloader.assert', { source: 'bug-T59567' } );
+ }
+ } catch ( e ) {
+ mw.track( 'resourceloader.exception', { exception: e, source: 'store-localstorage-json' } );
+ return false;
+ }
+
+ src = 'mw.loader.implement(' + args.join( ',' ) + ');';
+ if ( src.length > mw.loader.store.MODULE_SIZE_MAX ) {
+ return false;
+ }
+ mw.loader.store.items[ key ] = src;
+ mw.loader.store.update();
+ return true;
+ },
+
+ /**
+ * Iterate through the module store, removing any item that does not correspond
+ * (in name and version) to an item in the module registry.
+ *
+ * @return {boolean} Store was pruned
+ */
+ prune: function () {
+ var key, module;
+
+ if ( !mw.loader.store.enabled ) {
+ return false;
+ }
+
+ for ( key in mw.loader.store.items ) {
+ module = key.slice( 0, key.indexOf( '@' ) );
+ if ( getModuleKey( module ) !== key ) {
+ mw.loader.store.stats.expired++;
+ delete mw.loader.store.items[ key ];
+ } else if ( mw.loader.store.items[ key ].length > mw.loader.store.MODULE_SIZE_MAX ) {
+ // This value predates the enforcement of a size limit on cached modules.
+ delete mw.loader.store.items[ key ];
+ }
+ }
+ return true;
+ },
+
+ /**
+ * Clear the entire module store right now.
+ */
+ clear: function () {
+ mw.loader.store.items = {};
+ try {
+ localStorage.removeItem( mw.loader.store.getStoreKey() );
+ } catch ( ignored ) {}
+ },
+
+ /**
+ * Sync in-memory store back to localStorage.
+ *
+ * This function debounces updates. When called with a flush already pending,
+ * the call is coalesced into the pending update. The call to
+ * localStorage.setItem will be naturally deferred until the page is quiescent.
+ *
+ * Because localStorage is shared by all pages from the same origin, if multiple
+ * pages are loaded with different module sets, the possibility exists that
+ * modules saved by one page will be clobbered by another. But the impact would
+ * be minor and the problem would be corrected by subsequent page views.
+ *
+ * @method
+ */
+ update: ( function () {
+ var hasPendingWrite = false;
+
+ function flushWrites() {
+ var data, key;
+ if ( !hasPendingWrite || !mw.loader.store.enabled ) {
+ return;
+ }
+
+ mw.loader.store.prune();
+ key = mw.loader.store.getStoreKey();
+ try {
+ // Replacing the content of the module store might fail if the new
+ // contents would exceed the browser's localStorage size limit. To
+ // avoid clogging the browser with stale data, always remove the old
+ // value before attempting to set the new one.
+ localStorage.removeItem( key );
+ data = JSON.stringify( mw.loader.store );
+ localStorage.setItem( key, data );
+ } catch ( e ) {
+ mw.track( 'resourceloader.exception', { exception: e, source: 'store-localstorage-update' } );
+ }
+
+ hasPendingWrite = false;
+ }
+
+ return function () {
+ if ( !hasPendingWrite ) {
+ hasPendingWrite = true;
+ mw.requestIdleCallback( flushWrites );
+ }
+ };
+ }() )
+ }
+ };
+ }() ),
+
+ /**
+ * HTML construction helper functions
+ *
+ * @example
+ *
+ * var Html, output;
+ *
+ * Html = mw.html;
+ * output = Html.element( 'div', {}, new Html.Raw(
+ * Html.element( 'img', { src: '<' } )
+ * ) );
+ * mw.log( output ); // <div><img src="&lt;"/></div>
+ *
+ * @class mw.html
+ * @singleton
+ */
+ html: ( function () {
+ function escapeCallback( s ) {
+ switch ( s ) {
+ case '\'':
+ return '&#039;';
+ case '"':
+ return '&quot;';
+ case '<':
+ return '&lt;';
+ case '>':
+ return '&gt;';
+ case '&':
+ return '&amp;';
+ }
+ }
+
+ return {
+ /**
+ * Escape a string for HTML.
+ *
+ * Converts special characters to HTML entities.
+ *
+ * mw.html.escape( '< > \' & "' );
+ * // Returns &lt; &gt; &#039; &amp; &quot;
+ *
+ * @param {string} s The string to escape
+ * @return {string} HTML
+ */
+ escape: function ( s ) {
+ return s.replace( /['"<>&]/g, escapeCallback );
+ },
+
+ /**
+ * Create an HTML element string, with safe escaping.
+ *
+ * @param {string} name The tag name.
+ * @param {Object} [attrs] An object with members mapping element names to values
+ * @param {string|mw.html.Raw|mw.html.Cdata|null} [contents=null] The contents of the element.
+ *
+ * - string: Text to be escaped.
+ * - null: The element is treated as void with short closing form, e.g. `<br/>`.
+ * - this.Raw: The raw value is directly included.
+ * - this.Cdata: The raw value is directly included. An exception is
+ * thrown if it contains any illegal ETAGO delimiter.
+ * See <https://www.w3.org/TR/html401/appendix/notes.html#h-B.3.2>.
+ * @return {string} HTML
+ */
+ element: function ( name, attrs, contents ) {
+ var v, attrName, s = '<' + name;
+
+ if ( attrs ) {
+ for ( attrName in attrs ) {
+ v = attrs[ attrName ];
+ // Convert name=true, to name=name
+ if ( v === true ) {
+ v = attrName;
+ // Skip name=false
+ } else if ( v === false ) {
+ continue;
+ }
+ s += ' ' + attrName + '="' + this.escape( String( v ) ) + '"';
+ }
+ }
+ if ( contents === undefined || contents === null ) {
+ // Self close tag
+ s += '/>';
+ return s;
+ }
+ // Regular open tag
+ s += '>';
+ switch ( typeof contents ) {
+ case 'string':
+ // Escaped
+ s += this.escape( contents );
+ break;
+ case 'number':
+ case 'boolean':
+ // Convert to string
+ s += String( contents );
+ break;
+ default:
+ if ( contents instanceof this.Raw ) {
+ // Raw HTML inclusion
+ s += contents.value;
+ } else if ( contents instanceof this.Cdata ) {
+ // CDATA
+ if ( /<\/[a-zA-z]/.test( contents.value ) ) {
+ throw new Error( 'mw.html.element: Illegal end tag found in CDATA' );
+ }
+ s += contents.value;
+ } else {
+ throw new Error( 'mw.html.element: Invalid type of contents' );
+ }
+ }
+ s += '</' + name + '>';
+ return s;
+ },
+
+ /**
+ * Wrapper object for raw HTML passed to mw.html.element().
+ *
+ * @class mw.html.Raw
+ * @constructor
+ * @param {string} value
+ */
+ Raw: function ( value ) {
+ this.value = value;
+ },
+
+ /**
+ * Wrapper object for CDATA element contents passed to mw.html.element()
+ *
+ * @class mw.html.Cdata
+ * @constructor
+ * @param {string} value
+ */
+ Cdata: function ( value ) {
+ this.value = value;
+ }
+ };
+ }() ),
+
+ // Skeleton user object, extended by the 'mediawiki.user' module.
+ /**
+ * @class mw.user
+ * @singleton
+ */
+ user: {
+ /**
+ * @property {mw.Map}
+ */
+ options: new Map(),
+ /**
+ * @property {mw.Map}
+ */
+ tokens: new Map()
+ },
+
+ // OOUI widgets specific to MediaWiki
+ widgets: {},
+
+ /**
+ * Registry and firing of events.
+ *
+ * MediaWiki has various interface components that are extended, enhanced
+ * or manipulated in some other way by extensions, gadgets and even
+ * in core itself.
+ *
+ * This framework helps streamlining the timing of when these other
+ * code paths fire their plugins (instead of using document-ready,
+ * which can and should be limited to firing only once).
+ *
+ * Features like navigating to other wiki pages, previewing an edit
+ * and editing itself – without a refresh – can then retrigger these
+ * hooks accordingly to ensure everything still works as expected.
+ *
+ * Example usage:
+ *
+ * mw.hook( 'wikipage.content' ).add( fn ).remove( fn );
+ * mw.hook( 'wikipage.content' ).fire( $content );
+ *
+ * Handlers can be added and fired for arbitrary event names at any time. The same
+ * event can be fired multiple times. The last run of an event is memorized
+ * (similar to `$(document).ready` and `$.Deferred().done`).
+ * This means if an event is fired, and a handler added afterwards, the added
+ * function will be fired right away with the last given event data.
+ *
+ * Like Deferreds and Promises, the mw.hook object is both detachable and chainable.
+ * Thus allowing flexible use and optimal maintainability and authority control.
+ * You can pass around the `add` and/or `fire` method to another piece of code
+ * without it having to know the event name (or `mw.hook` for that matter).
+ *
+ * var h = mw.hook( 'bar.ready' );
+ * new mw.Foo( .. ).fetch( { callback: h.fire } );
+ *
+ * Note: Events are documented with an underscore instead of a dot in the event
+ * name due to jsduck not supporting dots in that position.
+ *
+ * @class mw.hook
+ */
+ hook: ( function () {
+ var lists = {};
+
+ /**
+ * Create an instance of mw.hook.
+ *
+ * @method hook
+ * @member mw
+ * @param {string} name Name of hook.
+ * @return {mw.hook}
+ */
+ return function ( name ) {
+ var list = hasOwn.call( lists, name ) ?
+ lists[ name ] :
+ lists[ name ] = $.Callbacks( 'memory' );
+
+ return {
+ /**
+ * Register a hook handler
+ *
+ * @param {...Function} handler Function to bind.
+ * @chainable
+ */
+ add: list.add,
+
+ /**
+ * Unregister a hook handler
+ *
+ * @param {...Function} handler Function to unbind.
+ * @chainable
+ */
+ remove: list.remove,
+
+ // eslint-disable-next-line valid-jsdoc
+ /**
+ * Run a hook.
+ *
+ * @param {...Mixed} data
+ * @chainable
+ */
+ fire: function () {
+ return list.fireWith.call( this, null, slice.call( arguments ) );
+ }
+ };
+ };
+ }() )
+ };
+
+ // Alias $j to jQuery for backwards compatibility
+ // @deprecated since 1.23 Use $ or jQuery instead
+ mw.log.deprecate( window, '$j', $, 'Use $ or jQuery instead.' );
+
+ /**
+ * Log a message to window.console, if possible.
+ *
+ * Useful to force logging of some errors that are otherwise hard to detect (i.e., this logs
+ * also in production mode). Gets console references in each invocation instead of caching the
+ * reference, so that debugging tools loaded later are supported (e.g. Firebug Lite in IE).
+ *
+ * @private
+ * @param {string} topic Stream name passed by mw.track
+ * @param {Object} data Data passed by mw.track
+ * @param {Error} [data.exception]
+ * @param {string} data.source Error source
+ * @param {string} [data.module] Name of module which caused the error
+ */
+ function logError( topic, data ) {
+ /* eslint-disable no-console */
+ var msg,
+ e = data.exception,
+ source = data.source,
+ module = data.module,
+ console = window.console;
+
+ if ( console && console.log ) {
+ msg = ( e ? 'Exception' : 'Error' ) + ' in ' + source;
+ if ( module ) {
+ msg += ' in module ' + module;
+ }
+ msg += ( e ? ':' : '.' );
+ console.log( msg );
+
+ // If we have an exception object, log it to the warning channel to trigger
+ // proper stacktraces in browsers that support it.
+ if ( e && console.warn ) {
+ console.warn( String( e ), e );
+ }
+ }
+ /* eslint-enable no-console */
+ }
+
+ // Subscribe to error streams
+ mw.trackSubscribe( 'resourceloader.exception', logError );
+ mw.trackSubscribe( 'resourceloader.assert', logError );
+
+ /**
+ * Fired when all modules associated with the page have finished loading.
+ *
+ * @event resourceloader_loadEnd
+ * @member mw.hook
+ */
+ $( function () {
+ var loading, modules;
+
+ modules = $.grep( mw.loader.getModuleNames(), function ( module ) {
+ return mw.loader.getState( module ) === 'loading';
+ } );
+ // We only need a callback, not any actual module. First try a single using()
+ // for all loading modules. If one fails, fall back to tracking each module
+ // separately via $.when(), this is expensive.
+ loading = mw.loader.using( modules ).then( null, function () {
+ var all = modules.map( function ( module ) {
+ return mw.loader.using( module ).then( null, function () {
+ return $.Deferred().resolve();
+ } );
+ } );
+ return $.when.apply( $, all );
+ } );
+ loading.then( function () {
+ /* global mwPerformance */
+ mwPerformance.mark( 'mwLoadEnd' );
+ mw.hook( 'resourceloader.loadEnd' ).fire();
+ } );
+ } );
+
+ // Attach to window and globally alias
+ window.mw = window.mediaWiki = mw;
+}( jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.log.js b/www/wiki/resources/src/mediawiki/mediawiki.log.js
new file mode 100644
index 00000000..969e872d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.log.js
@@ -0,0 +1,74 @@
+/*!
+ * Logger for MediaWiki javascript.
+ * Implements the stub left by the main 'mediawiki' module.
+ *
+ * @author Michael Dale <mdale@wikimedia.org>
+ * @author Trevor Parscal <tparscal@wikimedia.org>
+ */
+
+( function ( mw, $ ) {
+
+ // Keep reference to the dummy placeholder from mediawiki.js
+ // The root is replaced below, but it has other methods that we need to restore.
+ var original = mw.log,
+ slice = Array.prototype.slice;
+
+ mw.log = function () {
+ // Turn arguments into an array
+ var args = slice.call( arguments ),
+ // Allow log messages to use a configured prefix to identify the source window (ie. frame)
+ prefix = mw.config.exists( 'mw.log.prefix' ) ? mw.config.get( 'mw.log.prefix' ) + '> ' : '';
+
+ // Try to use an existing console
+ // Generally we can cache this, but in this case we want to re-evaluate this as a
+ // global property live so that things like Firebug Lite can take precedence.
+ if ( window.console && window.console.log && window.console.log.apply ) {
+ args.unshift( prefix );
+ window.console.log.apply( window.console, args );
+ return;
+ }
+
+ // If there is no console, use our own log box
+ mw.loader.using( 'jquery.footHovzer', function () {
+
+ var hovzer,
+ d = new Date(),
+ // Create HH:MM:SS.MIL timestamp
+ time = ( d.getHours() < 10 ? '0' + d.getHours() : d.getHours() ) +
+ ':' + ( d.getMinutes() < 10 ? '0' + d.getMinutes() : d.getMinutes() ) +
+ ':' + ( d.getSeconds() < 10 ? '0' + d.getSeconds() : d.getSeconds() ) +
+ '.' + ( d.getMilliseconds() < 10 ? '00' + d.getMilliseconds() : ( d.getMilliseconds() < 100 ? '0' + d.getMilliseconds() : d.getMilliseconds() ) ),
+ $log = $( '#mw-log-console' );
+
+ if ( !$log.length ) {
+ $log = $( '<div id="mw-log-console"></div>' ).css( {
+ overflow: 'auto',
+ height: '150px',
+ backgroundColor: 'white',
+ borderTop: 'solid 2px #ADADAD'
+ } );
+ hovzer = $.getFootHovzer();
+ hovzer.$.append( $log );
+ hovzer.update();
+ }
+ $log.append(
+ $( '<div>' )
+ .css( {
+ borderBottom: 'solid 1px #DDDDDD',
+ fontSize: 'small',
+ fontFamily: 'monospace',
+ whiteSpace: 'pre-wrap',
+ padding: '0.125em 0.25em'
+ } )
+ .text( prefix + args.join( ', ' ) )
+ .prepend( '<span style="float: right;">[' + time + ']</span>' )
+ );
+ } );
+ };
+
+ // Restore original methods
+ mw.log.warn = original.warn;
+ mw.log.error = original.error;
+ mw.log.deprecate = original.deprecate;
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.notification.common.css b/www/wiki/resources/src/mediawiki/mediawiki.notification.common.css
new file mode 100644
index 00000000..a1309c29
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.notification.common.css
@@ -0,0 +1,7 @@
+.mw-notification-area {
+ position: absolute;
+}
+
+.mw-notification-area-floating {
+ position: fixed;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.notification.convertmessagebox.js b/www/wiki/resources/src/mediawiki/mediawiki.notification.convertmessagebox.js
new file mode 100644
index 00000000..5d46de60
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.notification.convertmessagebox.js
@@ -0,0 +1,64 @@
+/**
+ * Usage:
+ *
+ * var convertmessagebox = require( 'mediawiki.notification.convertmessagebox' );
+ *
+ * @class mw.plugin.convertmessagebox
+ * @singleton
+ */
+( function ( mw, $ ) {
+ 'use strict';
+
+ /**
+ * Convert a messagebox to a notification.
+ *
+ * Checks if a message box with class `.mw-notify-success`, `.mw-notify-warning`, or `.mw-notify-error`
+ * exists and converts it into a mw.Notification with the text of the element or a given message key.
+ *
+ * By default the notification will automatically hide after 5s, or when the user clicks the element.
+ * This can be overridden by setting attribute `data-mw-autohide="true"`.
+ *
+ * @param {Object} [options] Options
+ * @param {mw.Message} [options.msg] Message key (must be loaded already)
+ */
+ function convertmessagebox( options ) {
+ var $msgBox, type, autoHide, msg, notif,
+ $successBox = $( '.mw-notify-success' ),
+ $warningBox = $( '.mw-notify-warning' ),
+ $errorBox = $( '.mw-notify-error' );
+
+ // If there is a message box and javascript is enabled, use a slick notification instead!
+ if ( $successBox.length ) {
+ $msgBox = $successBox;
+ type = 'info';
+ } else if ( $warningBox.length ) {
+ $msgBox = $warningBox;
+ type = 'warn';
+ } else if ( $errorBox.length ) {
+ $msgBox = $errorBox;
+ type = 'error';
+ } else {
+ return;
+ }
+
+ autoHide = $msgBox.attr( 'data-mw-autohide' ) === 'true';
+
+ // If the msg param is given, use it, otherwise use the text of the successbox
+ msg = options && options.msg || $msgBox.text();
+ $msgBox.detach();
+
+ notif = mw.notification.notify( msg, { autoHide: autoHide, type: type } );
+ if ( !autoHide ) {
+ // 'change' event not reliable!
+ $( document ).one( 'keydown mousedown', function () {
+ if ( notif ) {
+ notif.close();
+ notif = null;
+ }
+ } );
+ }
+ }
+
+ module.exports = convertmessagebox;
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.notification.convertmessagebox.styles.less b/www/wiki/resources/src/mediawiki/mediawiki.notification.convertmessagebox.styles.less
new file mode 100644
index 00000000..2371f4e8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.notification.convertmessagebox.styles.less
@@ -0,0 +1,7 @@
+.client-js {
+ .mw-notify-success,
+ .mw-notify-warning,
+ .mw-notify-error {
+ display: none;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.notification.css b/www/wiki/resources/src/mediawiki/mediawiki.notification.css
new file mode 100644
index 00000000..633798d9
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.notification.css
@@ -0,0 +1,53 @@
+.mw-notification-area {
+ top: 0;
+ right: 0;
+ /* Padding on all sides so drop shadows aren't cut by overflow: hidden */
+ padding: 1em;
+ width: 20em;
+ line-height: 1.35;
+ z-index: 10000;
+ /* Avoid horizontal scrollbar on fade in and on fade out */
+ overflow: hidden;
+}
+
+.mw-notification {
+ padding: 0.25em 1em;
+ margin-bottom: 0.5em;
+ border: solid 1px #ddd;
+ background-color: #fcfcfc;
+ /* Click handler in mediawiki.notification.js */
+ cursor: pointer;
+
+ opacity: 0;
+ -webkit-transform: translateX( 35px );
+ transform: translateX( 35px );
+ -webkit-transition: opacity 0.35s ease-in-out, -webkit-transform 0.35s ease-in-out;
+ transition: opacity 0.35s ease-in-out, transform 0.35s ease-in-out;
+}
+
+.mw-notification-visible {
+ opacity: 1;
+ -webkit-transform: translateX( 0 );
+ transform: translateX( 0 );
+}
+
+.mw-notification-replaced {
+ opacity: 0;
+ -webkit-transform: translateY( -35px );
+ transform: translateY( -35px );
+ pointer-events: none;
+}
+
+.mw-notification-title {
+ font-weight: bold;
+}
+
+.mw-notification-type-warn {
+ border-color: #f5be00; /* yellow */
+ background-color: #ffffe8;
+}
+
+.mw-notification-type-error {
+ border-color: #eb3941; /* red */
+ background-color: #fff8f8;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.notification.hideForPrint.css b/www/wiki/resources/src/mediawiki/mediawiki.notification.hideForPrint.css
new file mode 100644
index 00000000..4f9162e2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.notification.hideForPrint.css
@@ -0,0 +1,3 @@
+.mw-notification-area {
+ display: none;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.notification.js b/www/wiki/resources/src/mediawiki/mediawiki.notification.js
new file mode 100644
index 00000000..dfacfc66
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.notification.js
@@ -0,0 +1,441 @@
+( function ( mw, $ ) {
+ 'use strict';
+
+ var notification,
+ // The #mw-notification-area div that all notifications are contained inside.
+ $area,
+ // Number of open notification boxes at any time
+ openNotificationCount = 0,
+ isPageReady = false,
+ preReadyNotifQueue = [],
+ rAF = window.requestAnimationFrame || setTimeout;
+
+ /**
+ * A Notification object for 1 message.
+ *
+ * The underscore in the name is to avoid a bug <https://github.com/senchalabs/jsduck/issues/304>.
+ * It is not part of the actual class name.
+ *
+ * The constructor is not publicly accessible; use mw.notification#notify instead.
+ * This does not insert anything into the document (see #start).
+ *
+ * @class mw.Notification_
+ * @alternateClassName mw.Notification
+ * @constructor
+ * @private
+ * @param {mw.Message|jQuery|HTMLElement|string} message
+ * @param {Object} options
+ */
+ function Notification( message, options ) {
+ var $notification, $notificationContent;
+
+ $notification = $( '<div class="mw-notification"></div>' )
+ .data( 'mw.notification', this )
+ .addClass( options.autoHide ? 'mw-notification-autohide' : 'mw-notification-noautohide' );
+
+ if ( options.tag ) {
+ // Sanitize options.tag before it is used by any code. (Including Notification class methods)
+ options.tag = options.tag.replace( /[ _-]+/g, '-' ).replace( /[^-a-z0-9]+/ig, '' );
+ if ( options.tag ) {
+ $notification.addClass( 'mw-notification-tag-' + options.tag );
+ } else {
+ delete options.tag;
+ }
+ }
+
+ if ( options.type ) {
+ // Sanitize options.type
+ options.type = options.type.replace( /[ _-]+/g, '-' ).replace( /[^-a-z0-9]+/ig, '' );
+ $notification.addClass( 'mw-notification-type-' + options.type );
+ }
+
+ if ( options.title ) {
+ $( '<div class="mw-notification-title"></div>' )
+ .text( options.title )
+ .appendTo( $notification );
+ }
+
+ $notificationContent = $( '<div class="mw-notification-content"></div>' );
+
+ if ( typeof message === 'object' ) {
+ // Handle mw.Message objects separately from DOM nodes and jQuery objects
+ if ( message instanceof mw.Message ) {
+ $notificationContent.html( message.parse() );
+ } else {
+ $notificationContent.append( message );
+ }
+ } else {
+ $notificationContent.text( message );
+ }
+
+ $notificationContent.appendTo( $notification );
+
+ // Private state parameters, meant for internal use only
+ // autoHideSeconds: String alias for number of seconds for timeout of auto-hiding notifications.
+ // isOpen: Set to true after .start() is called to avoid double calls.
+ // Set back to false after .close() to avoid duplicating the close animation.
+ // isPaused: false after .resume(), true after .pause(). Avoids duplicating or breaking the hide timeouts.
+ // Set to true initially so .start() can call .resume().
+ // message: The message passed to the notification. Unused now but may be used in the future
+ // to stop replacement of a tagged notification with another notification using the same message.
+ // options: The options passed to the notification with a little sanitization. Used by various methods.
+ // $notification: jQuery object containing the notification DOM node.
+ this.autoHideSeconds = options.autoHideSeconds &&
+ notification.autoHideSeconds[ options.autoHideSeconds ] ||
+ notification.autoHideSeconds.short;
+ this.isOpen = false;
+ this.isPaused = true;
+ this.message = message;
+ this.options = options;
+ this.$notification = $notification;
+ }
+
+ /**
+ * Start the notification. Called automatically by mw.notification#notify
+ * (possibly asynchronously on document-ready).
+ *
+ * This inserts the notification into the page, closes any matching tagged notifications,
+ * handles the fadeIn animations and replacement transitions, and starts autoHide timers.
+ *
+ * @private
+ */
+ Notification.prototype.start = function () {
+ var options, $notification, $tagMatches, autohideCount;
+
+ $area.show();
+
+ if ( this.isOpen ) {
+ return;
+ }
+
+ this.isOpen = true;
+ openNotificationCount++;
+
+ options = this.options;
+ $notification = this.$notification;
+
+ if ( options.tag ) {
+ // Find notifications with the same tag
+ $tagMatches = $area.find( '.mw-notification-tag-' + options.tag );
+ }
+
+ // If we found existing notification with the same tag, replace them
+ if ( options.tag && $tagMatches.length ) {
+
+ // While there can be only one "open" notif with a given tag, there can be several
+ // matches here because they remain in the DOM until the animation is finished.
+ $tagMatches.each( function () {
+ var notif = $( this ).data( 'mw.notification' );
+ if ( notif && notif.isOpen ) {
+ // Detach from render flow with position absolute so that the new tag can
+ // occupy its space instead.
+ notif.$notification
+ .css( {
+ position: 'absolute',
+ width: notif.$notification.width()
+ } )
+ .css( notif.$notification.position() )
+ .addClass( 'mw-notification-replaced' );
+ notif.close();
+ }
+ } );
+
+ $notification
+ .insertBefore( $tagMatches.first() )
+ .addClass( 'mw-notification-visible' );
+ } else {
+ $area.append( $notification );
+ rAF( function () {
+ // This frame renders the element in the area (invisible)
+ rAF( function () {
+ $notification.addClass( 'mw-notification-visible' );
+ } );
+ } );
+ }
+
+ // By default a notification is paused.
+ // If this notification is within the first {autoHideLimit} notifications then
+ // start the auto-hide timer as soon as it's created.
+ autohideCount = $area.find( '.mw-notification-autohide' ).length;
+ if ( autohideCount <= notification.autoHideLimit ) {
+ this.resume();
+ }
+ };
+
+ /**
+ * Pause any running auto-hide timer for this notification
+ */
+ Notification.prototype.pause = function () {
+ if ( this.isPaused ) {
+ return;
+ }
+ this.isPaused = true;
+
+ if ( this.timeout ) {
+ clearTimeout( this.timeout );
+ delete this.timeout;
+ }
+ };
+
+ /**
+ * Start autoHide timer if not already started.
+ * Does nothing if autoHide is disabled.
+ * Either to resume from pause or to make the first start.
+ */
+ Notification.prototype.resume = function () {
+ var notif = this;
+ if ( !notif.isPaused ) {
+ return;
+ }
+ // Start any autoHide timeouts
+ if ( notif.options.autoHide ) {
+ notif.isPaused = false;
+ notif.timeout = setTimeout( function () {
+ // Already finished, so don't try to re-clear it
+ delete notif.timeout;
+ notif.close();
+ }, this.autoHideSeconds * 1000 );
+ }
+ };
+
+ /**
+ * Close the notification.
+ */
+ Notification.prototype.close = function () {
+ var notif = this;
+
+ if ( !this.isOpen ) {
+ return;
+ }
+
+ this.isOpen = false;
+ openNotificationCount--;
+
+ // Clear any remaining timeout on close
+ this.pause();
+
+ // Remove the mw-notification-autohide class from the notification to avoid
+ // having a half-closed notification counted as a notification to resume
+ // when handling {autoHideLimit}.
+ this.$notification.removeClass( 'mw-notification-autohide' );
+
+ // Now that a notification is being closed. Start auto-hide timers for any
+ // notification that has now become one of the first {autoHideLimit} notifications.
+ notification.resume();
+
+ rAF( function () {
+ notif.$notification.removeClass( 'mw-notification-visible' );
+
+ setTimeout( function () {
+ if ( openNotificationCount === 0 ) {
+ // Hide the area after the last notification closes. Otherwise, the padding on
+ // the area can be obscure content, despite the area being empty/invisible (T54659). // FIXME
+ $area.hide();
+ notif.$notification.remove();
+ } else {
+ notif.$notification.slideUp( 'fast', function () {
+ $( this ).remove();
+ } );
+ }
+ }, 500 );
+ } );
+ };
+
+ /**
+ * Helper function, take a list of notification divs and call
+ * a function on the Notification instance attached to them.
+ *
+ * @private
+ * @static
+ * @param {jQuery} $notifications A jQuery object containing notification divs
+ * @param {string} fn The name of the function to call on the Notification instance
+ */
+ function callEachNotification( $notifications, fn ) {
+ $notifications.each( function () {
+ var notif = $( this ).data( 'mw.notification' );
+ if ( notif ) {
+ notif[ fn ]();
+ }
+ } );
+ }
+
+ /**
+ * Initialisation.
+ * Must only be called once, and not before the document is ready.
+ *
+ * @ignore
+ */
+ function init() {
+ var offset,
+ isFloating = false;
+
+ $area = $( '<div id="mw-notification-area" class="mw-notification-area mw-notification-area-layout"></div>' )
+ // Pause auto-hide timers when the mouse is in the notification area.
+ .on( {
+ mouseenter: notification.pause,
+ mouseleave: notification.resume
+ } )
+ // When clicking on a notification close it.
+ .on( 'click', '.mw-notification', function () {
+ var notif = $( this ).data( 'mw.notification' );
+ if ( notif ) {
+ notif.close();
+ }
+ } )
+ // Stop click events from <a> tags from propogating to prevent clicking.
+ // on links from hiding a notification.
+ .on( 'click', 'a', function ( e ) {
+ e.stopPropagation();
+ } );
+
+ // Prepend the notification area to the content area and save it's object.
+ mw.util.$content.prepend( $area );
+ offset = $area.offset();
+ $area.hide();
+
+ function updateAreaMode() {
+ var shouldFloat = window.pageYOffset > offset.top;
+ if ( isFloating === shouldFloat ) {
+ return;
+ }
+ isFloating = shouldFloat;
+ $area
+ .toggleClass( 'mw-notification-area-floating', isFloating )
+ .toggleClass( 'mw-notification-area-layout', !isFloating );
+ }
+
+ $( window ).on( 'scroll', updateAreaMode );
+
+ // Initial mode
+ updateAreaMode();
+ }
+
+ /**
+ * @class mw.notification
+ * @singleton
+ */
+ notification = {
+ /**
+ * Pause auto-hide timers for all notifications.
+ * Notifications will not auto-hide until resume is called.
+ *
+ * @see mw.Notification#pause
+ */
+ pause: function () {
+ callEachNotification(
+ $area.children( '.mw-notification' ),
+ 'pause'
+ );
+ },
+
+ /**
+ * Resume any paused auto-hide timers from the beginning.
+ * Only the first #autoHideLimit timers will be resumed.
+ */
+ resume: function () {
+ callEachNotification(
+ // Only call resume on the first #autoHideLimit notifications.
+ // Exclude noautohide notifications to avoid bugs where #autoHideLimit
+ // `{ autoHide: false }` notifications are at the start preventing any
+ // auto-hide notifications from being autohidden.
+ $area.children( '.mw-notification-autohide' ).slice( 0, notification.autoHideLimit ),
+ 'resume'
+ );
+ },
+
+ /**
+ * Display a notification message to the user.
+ *
+ * @param {HTMLElement|HTMLElement[]|jQuery|mw.Message|string} message
+ * @param {Object} options The options to use for the notification.
+ * See #defaults for details.
+ * @return {mw.Notification} Notification object
+ */
+ notify: function ( message, options ) {
+ var notif;
+ options = $.extend( {}, notification.defaults, options );
+
+ notif = new Notification( message, options );
+
+ if ( isPageReady ) {
+ notif.start();
+ } else {
+ preReadyNotifQueue.push( notif );
+ }
+
+ return notif;
+ },
+
+ /**
+ * @property {Object}
+ * The defaults for #notify options parameter.
+ *
+ * - autoHide:
+ * A boolean indicating whether the notifification should automatically
+ * be hidden after shown. Or if it should persist.
+ *
+ * - autoHideSeconds:
+ * Key to #autoHideSeconds for number of seconds for timeout of auto-hide
+ * notifications.
+ *
+ * - tag:
+ * An optional string. When a notification is tagged only one message
+ * with that tag will be displayed. Trying to display a new notification
+ * with the same tag as one already being displayed will cause the other
+ * notification to be closed and this new notification to open up inside
+ * the same place as the previous notification.
+ *
+ * - title:
+ * An optional title for the notification. Will be displayed above the
+ * content. Usually in bold.
+ *
+ * - type:
+ * An optional string for the type of the message used for styling:
+ * Examples: 'info', 'warn', 'error'.
+ */
+ defaults: {
+ autoHide: true,
+ autoHideSeconds: 'short',
+ tag: null,
+ title: null,
+ type: null
+ },
+
+ /**
+ * @private
+ * @property {Object}
+ */
+ autoHideSeconds: {
+ 'short': 5,
+ 'long': 30
+ },
+
+ /**
+ * @property {number}
+ * Maximum number of simultaneous notifications to start auto-hide timers for.
+ * Only this number of notifications being displayed will be auto-hidden at one time.
+ * Any additional notifications in the list will only start counting their timeout for
+ * auto-hiding after the previous messages have been closed.
+ *
+ * This basically represents the minimal number of notifications the user should
+ * be able to process during the {@link #defaults default} #autoHideSeconds time.
+ */
+ autoHideLimit: 3
+ };
+
+ $( function () {
+ var notif;
+
+ init();
+
+ // Handle pre-ready queue.
+ isPageReady = true;
+ while ( preReadyNotifQueue.length ) {
+ notif = preReadyNotifQueue.shift();
+ notif.start();
+ }
+ } );
+
+ mw.notification = notification;
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.notification.print.css b/www/wiki/resources/src/mediawiki/mediawiki.notification.print.css
new file mode 100644
index 00000000..4f9162e2
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.notification.print.css
@@ -0,0 +1,3 @@
+.mw-notification-area {
+ display: none;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.notify.js b/www/wiki/resources/src/mediawiki/mediawiki.notify.js
new file mode 100644
index 00000000..0f3a0867
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.notify.js
@@ -0,0 +1,28 @@
+/**
+ * @class mw.plugin.notify
+ */
+( function ( mw ) {
+ 'use strict';
+
+ /**
+ * @see mw.notification#notify
+ * @see mw.notification#defaults
+ * @param {HTMLElement|HTMLElement[]|jQuery|mw.Message|string} message
+ * @param {Object} options See mw.notification#defaults for details.
+ * @return {jQuery.Promise}
+ */
+ mw.notify = function ( message, options ) {
+ // Don't bother loading the whole notification system if we never use it.
+ return mw.loader.using( 'mediawiki.notification' )
+ .then( function () {
+ // Call notify with the notification the user requested of us.
+ return mw.notification.notify( message, options );
+ } );
+ };
+
+ /**
+ * @class mw
+ * @mixins mw.plugin.notify
+ */
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.pager.tablePager.less b/www/wiki/resources/src/mediawiki/mediawiki.pager.tablePager.less
new file mode 100644
index 00000000..5b3519e5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.pager.tablePager.less
@@ -0,0 +1,28 @@
+/*!
+ * Structures generated by the TablePager PHP class
+ * in MediaWiki (used e.g. on Special:ListFiles).
+ */
+
+@import 'mediawiki.mixins';
+
+.TablePager {
+ min-width: 80%;
+}
+
+.TablePager .TablePager_sort-ascending a {
+ padding-left: 15px;
+ background: none left center no-repeat;
+ .background-image-svg('images/arrow-sort-ascending.svg', 'images/arrow-sort-ascending.png');
+}
+
+.TablePager .TablePager_sort-descending a {
+ padding-left: 15px;
+ background: none left center no-repeat;
+ .background-image-svg('images/arrow-sort-descending.svg', 'images/arrow-sort-descending.png');
+}
+
+.TablePager_nav.oo-ui-buttonGroupWidget {
+ display: block;
+ text-align: center;
+ margin: 1em;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.raggett.css b/www/wiki/resources/src/mediawiki/mediawiki.raggett.css
new file mode 100644
index 00000000..1e1e973c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.raggett.css
@@ -0,0 +1,3 @@
+.mw-empty-li {
+ display: none;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.requestIdleCallback.js b/www/wiki/resources/src/mediawiki/mediawiki.requestIdleCallback.js
new file mode 100644
index 00000000..650092bd
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.requestIdleCallback.js
@@ -0,0 +1,52 @@
+( function ( mw ) {
+ var maxBusy = 50;
+
+ mw.requestIdleCallbackInternal = function ( callback ) {
+ setTimeout( function () {
+ var start = mw.now();
+ callback( {
+ didTimeout: false,
+ timeRemaining: function () {
+ return Math.max( 0, maxBusy - ( mw.now() - start ) );
+ }
+ } );
+ }, 1 );
+ };
+
+ /**
+ * Schedule a deferred task to run in the background.
+ *
+ * This allows code to perform tasks in the main thread without impacting
+ * time-critical operations such as animations and response to input events.
+ *
+ * Basic logic is as follows:
+ *
+ * - User input event should be acknowledged within 100ms per [RAIL].
+ * - Idle work should be grouped in blocks of upto 50ms so that enough time
+ * remains for the event handler to execute and any rendering to take place.
+ * - Whenever a native event happens (e.g. user input), the deadline for any
+ * running idle callback drops to 0.
+ * - As long as the deadline is non-zero, other callbacks pending may be
+ * executed in the same idle period.
+ *
+ * See also:
+ *
+ * - <https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback>
+ * - <https://w3c.github.io/requestidlecallback/>
+ * - <https://developers.google.com/web/updates/2015/08/using-requestidlecallback>
+ * [RAIL]: https://developers.google.com/web/fundamentals/performance/rail
+ *
+ * @member mw
+ * @param {Function} callback
+ * @param {Object} [options]
+ * @param {number} [options.timeout] If set, the callback will be scheduled for
+ * immediate execution after this amount of time (in milliseconds) if it didn't run
+ * by that time.
+ */
+ mw.requestIdleCallback = window.requestIdleCallback ?
+ window.requestIdleCallback.bind( window ) : // Bind because it throws TypeError if context is not window
+ mw.requestIdleCallbackInternal;
+ // Note: Polyfill was previously disabled due to
+ // https://bugs.chromium.org/p/chromium/issues/detail?id=647870
+ // See also <http://codepen.io/Krinkle/full/XNGEvv>
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.searchSuggest.css b/www/wiki/resources/src/mediawiki/mediawiki.searchSuggest.css
new file mode 100644
index 00000000..ce3cfbd7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.searchSuggest.css
@@ -0,0 +1,24 @@
+/* Make sure the links are not underlined or colored, ever. */
+/* There is already a :focus / :hover indication on the <div>. */
+.suggestions a.mw-searchSuggest-link,
+.suggestions a.mw-searchSuggest-link:hover,
+.suggestions a.mw-searchSuggest-link:active,
+.suggestions a.mw-searchSuggest-link:focus {
+ color: #000;
+ text-decoration: none;
+}
+
+.suggestions-result-current a.mw-searchSuggest-link,
+.suggestions-result-current a.mw-searchSuggest-link:hover,
+.suggestions-result-current a.mw-searchSuggest-link:active,
+.suggestions-result-current a.mw-searchSuggest-link:focus {
+ color: #fff;
+}
+
+.suggestions a.mw-searchSuggest-link .special-query {
+ /* Apply ellipsis to suggestions */
+ overflow: hidden;
+ -o-text-overflow: ellipsis; /* Opera 9 to 10 */
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.searchSuggest.js b/www/wiki/resources/src/mediawiki/mediawiki.searchSuggest.js
new file mode 100644
index 00000000..1c1150e4
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.searchSuggest.js
@@ -0,0 +1,316 @@
+/*!
+ * Add search suggestions to the search form.
+ */
+( function ( mw, $ ) {
+ mw.searchSuggest = {
+ // queries the wiki and calls response with the result
+ request: function ( api, query, response, maxRows, namespace ) {
+ return api.get( {
+ formatversion: 2,
+ action: 'opensearch',
+ search: query,
+ namespace: namespace || 0,
+ limit: maxRows,
+ suggest: true
+ } ).done( function ( data, jqXHR ) {
+ response( data[ 1 ], {
+ type: jqXHR.getResponseHeader( 'X-OpenSearch-Type' ),
+ query: query
+ } );
+ } );
+ }
+ };
+
+ $( function () {
+ var api, searchboxesSelectors,
+ // Region where the suggestions box will appear directly below
+ // (using the same width). Can be a container element or the input
+ // itself, depending on what suits best in the environment.
+ // For Vector the suggestion box should align with the simpleSearch
+ // container's borders, in other skins it should align with the input
+ // element (not the search form, as that would leave the buttons
+ // vertically between the input and the suggestions).
+ $searchRegion = $( '#simpleSearch, #searchInput' ).first(),
+ $searchInput = $( '#searchInput' ),
+ previousSearchText = $searchInput.val();
+
+ // Compute form data for search suggestions functionality.
+ function getFormData( context ) {
+ var $form, baseHref, linkParams;
+
+ if ( !context.formData ) {
+ // Compute common parameters for links' hrefs
+ $form = context.config.$region.closest( 'form' );
+
+ baseHref = $form.attr( 'action' );
+ baseHref += baseHref.indexOf( '?' ) > -1 ? '&' : '?';
+
+ linkParams = $form.serializeObject();
+
+ context.formData = {
+ textParam: context.data.$textbox.attr( 'name' ),
+ linkParams: linkParams,
+ baseHref: baseHref
+ };
+ }
+
+ return context.formData;
+ }
+
+ /**
+ * Callback that's run when the user changes the search input text
+ * 'this' is the search input box (jQuery object)
+ *
+ * @ignore
+ */
+ function onBeforeUpdate() {
+ var searchText = this.val();
+
+ if ( searchText && searchText !== previousSearchText ) {
+ mw.track( 'mediawiki.searchSuggest', {
+ action: 'session-start'
+ } );
+ }
+ previousSearchText = searchText;
+ }
+
+ /**
+ * Defines the location of autocomplete. Typically either
+ * header, which is in the top right of vector (for example)
+ * and content which identifies the main search bar on
+ * Special:Search. Defaults to header for skins that don't set
+ * explicitly.
+ *
+ * @ignore
+ * @param {Object} context
+ * @return {string}
+ */
+ function getInputLocation( context ) {
+ return context.config.$region
+ .closest( 'form' )
+ .find( '[data-search-loc]' )
+ .data( 'search-loc' ) || 'header';
+ }
+
+ /**
+ * Callback that's run when suggestions have been updated either from the cache or the API
+ * 'this' is the search input box (jQuery object)
+ *
+ * @ignore
+ * @param {Object} metadata
+ */
+ function onAfterUpdate( metadata ) {
+ var context = this.data( 'suggestionsContext' );
+
+ mw.track( 'mediawiki.searchSuggest', {
+ action: 'impression-results',
+ numberOfResults: context.config.suggestions.length,
+ resultSetType: metadata.type || 'unknown',
+ query: metadata.query,
+ inputLocation: getInputLocation( context )
+ } );
+ }
+
+ // The function used to render the suggestions.
+ function renderFunction( text, context ) {
+ var formData = getFormData( context ),
+ textboxConfig = context.data.$textbox.data( 'mw-searchsuggest' ) || {};
+
+ // linkParams object is modified and reused
+ formData.linkParams[ formData.textParam ] = text;
+
+ // Allow trackers to attach tracking information, such
+ // as wprov, to clicked links.
+ mw.track( 'mediawiki.searchSuggest', {
+ action: 'render-one',
+ formData: formData,
+ index: context.config.suggestions.indexOf( text )
+ } );
+
+ // this is the container <div>, jQueryfied
+ this.text( text );
+
+ // wrap only as link, if the config doesn't disallow it
+ if ( textboxConfig.wrapAsLink !== false ) {
+ this.wrap(
+ $( '<a>' )
+ .attr( 'href', formData.baseHref + $.param( formData.linkParams ) )
+ .attr( 'title', text )
+ .addClass( 'mw-searchSuggest-link' )
+ );
+ }
+ }
+
+ // The function used when the user makes a selection
+ function selectFunction( $input, source ) {
+ var context = $input.data( 'suggestionsContext' ),
+ text = $input.val();
+
+ // Selecting via keyboard triggers a form submission. That will fire
+ // the submit-form event in addition to this click-result event.
+ if ( source !== 'keyboard' ) {
+ mw.track( 'mediawiki.searchSuggest', {
+ action: 'click-result',
+ numberOfResults: context.config.suggestions.length,
+ index: context.config.suggestions.indexOf( text )
+ } );
+ }
+
+ // allow the form to be submitted
+ return true;
+ }
+
+ function specialRenderFunction( query, context ) {
+ var $el = this,
+ formData = getFormData( context );
+
+ // linkParams object is modified and reused
+ formData.linkParams[ formData.textParam ] = query;
+
+ mw.track( 'mediawiki.searchSuggest', {
+ action: 'render-one',
+ formData: formData,
+ index: context.config.suggestions.indexOf( query )
+ } );
+
+ if ( $el.children().length === 0 ) {
+ $el
+ .append(
+ $( '<div>' )
+ .addClass( 'special-label' )
+ .text( mw.msg( 'searchsuggest-containing' ) ),
+ $( '<div>' )
+ .addClass( 'special-query' )
+ .text( query )
+ )
+ .show();
+ } else {
+ $el.find( '.special-query' )
+ .text( query );
+ }
+
+ if ( $el.parent().hasClass( 'mw-searchSuggest-link' ) ) {
+ $el.parent().attr( 'href', formData.baseHref + $.param( formData.linkParams ) + '&fulltext=1' );
+ } else {
+ $el.wrap(
+ $( '<a>' )
+ .attr( 'href', formData.baseHref + $.param( formData.linkParams ) + '&fulltext=1' )
+ .addClass( 'mw-searchSuggest-link' )
+ );
+ }
+ }
+
+ // Generic suggestions functionality for all search boxes
+ searchboxesSelectors = [
+ // Primary searchbox on every page in standard skins
+ '#searchInput',
+ // Generic selector for skins with multiple searchboxes (used by CologneBlue)
+ // and for MediaWiki itself (special pages with page title inputs)
+ '.mw-searchInput'
+ ];
+ $( searchboxesSelectors.join( ', ' ) )
+ .suggestions( {
+ fetch: function ( query, response, maxRows ) {
+ var node = this[ 0 ];
+
+ api = api || new mw.Api();
+
+ $.data( node, 'request', mw.searchSuggest.request( api, query, response, maxRows ) );
+ },
+ cancel: function () {
+ var node = this[ 0 ],
+ request = $.data( node, 'request' );
+
+ if ( request ) {
+ request.abort();
+ $.removeData( node, 'request' );
+ }
+ },
+ result: {
+ render: renderFunction,
+ select: function () {
+ // allow the form to be submitted
+ return true;
+ }
+ },
+ update: {
+ before: onBeforeUpdate,
+ after: onAfterUpdate
+ },
+ cache: true,
+ highlightInput: true
+ } )
+ .on( 'paste cut drop', function () {
+ // make sure paste and cut events from the mouse and drag&drop events
+ // trigger the keypress handler and cause the suggestions to update
+ $( this ).trigger( 'keypress' );
+ } )
+ // In most skins (at least Monobook and Vector), the font-size is messed up in <body>.
+ // (they use 2 elements to get a sane font-height). So, instead of making exceptions for
+ // each skin or adding more stylesheets, just copy it from the active element so auto-fit.
+ .each( function () {
+ var $this = $( this );
+ $this
+ .data( 'suggestions-context' )
+ .data.$container.css( 'fontSize', $this.css( 'fontSize' ) );
+ } );
+
+ // Ensure that the thing is actually present!
+ if ( $searchRegion.length === 0 ) {
+ // Don't try to set anything up if simpleSearch is disabled sitewide.
+ // The loader code loads us if the option is present, even if we're
+ // not actually enabled (anymore).
+ return;
+ }
+
+ // Special suggestions functionality and tracking for skin-provided search box
+ $searchInput.suggestions( {
+ update: {
+ before: onBeforeUpdate,
+ after: onAfterUpdate
+ },
+ result: {
+ render: renderFunction,
+ select: selectFunction
+ },
+ special: {
+ render: specialRenderFunction,
+ select: function ( $input, source ) {
+ var context = $input.data( 'suggestionsContext' ),
+ text = $input.val();
+ if ( source === 'mouse' ) {
+ // mouse click won't trigger form submission, so we need to send a click event
+ mw.track( 'mediawiki.searchSuggest', {
+ action: 'click-result',
+ numberOfResults: context.config.suggestions.length,
+ index: context.config.suggestions.indexOf( text )
+ } );
+ } else {
+ $input.closest( 'form' )
+ .append( $( '<input type="hidden" name="fulltext" value="1"/>' ) );
+ }
+ return true; // allow the form to be submitted
+ }
+ },
+ $region: $searchRegion
+ } );
+
+ $searchInput.closest( 'form' )
+ // track the form submit event
+ .on( 'submit', function () {
+ var context = $searchInput.data( 'suggestionsContext' );
+ mw.track( 'mediawiki.searchSuggest', {
+ action: 'submit-form',
+ numberOfResults: context.config.suggestions.length,
+ $form: context.config.$region.closest( 'form' ),
+ inputLocation: getInputLocation( context ),
+ index: context.config.suggestions.indexOf(
+ context.data.$textbox.val()
+ )
+ } );
+ } )
+ // If the form includes any fallback fulltext search buttons, remove them
+ .find( '.mw-fallbackSearchButton' ).remove();
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.sectionAnchor.css b/www/wiki/resources/src/mediawiki/mediawiki.sectionAnchor.css
new file mode 100644
index 00000000..f8f00221
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.sectionAnchor.css
@@ -0,0 +1,3 @@
+.mw-headline-anchor {
+ display: none;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.storage.js b/www/wiki/resources/src/mediawiki/mediawiki.storage.js
new file mode 100644
index 00000000..84e146a7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.storage.js
@@ -0,0 +1,94 @@
+( function ( mw ) {
+ 'use strict';
+
+ // Catch exceptions to avoid fatal in Chrome's "Block data storage" mode
+ // which throws when accessing the localStorage property itself, as opposed
+ // to the standard behaviour of throwing on getItem/setItem. (T148998)
+ var
+ localStorage = ( function () {
+ try {
+ return window.localStorage;
+ } catch ( e ) {}
+ }() ),
+ sessionStorage = ( function () {
+ try {
+ return window.sessionStorage;
+ } catch ( e ) {}
+ }() );
+
+ /**
+ * A wrapper for an HTML5 Storage interface (`localStorage` or `sessionStorage`)
+ * that is safe to call on all browsers.
+ *
+ * @class mw.SafeStorage
+ * @private
+ * @param {Object|undefined} store The Storage instance to wrap around
+ */
+ function SafeStorage( store ) {
+ this.store = store;
+ }
+
+ /**
+ * Retrieve value from device storage.
+ *
+ * @param {string} key Key of item to retrieve
+ * @return {string|null|boolean} String value, null if no value exists, or false
+ * if localStorage is not available.
+ */
+ SafeStorage.prototype.get = function ( key ) {
+ try {
+ return this.store.getItem( key );
+ } catch ( e ) {}
+ return false;
+ };
+
+ /**
+ * Set a value in device storage.
+ *
+ * @param {string} key Key name to store under
+ * @param {string} value Value to be stored
+ * @return {boolean} Whether the save succeeded or not
+ */
+ SafeStorage.prototype.set = function ( key, value ) {
+ try {
+ this.store.setItem( key, value );
+ return true;
+ } catch ( e ) {}
+ return false;
+ };
+
+ /**
+ * Remove a value from device storage.
+ *
+ * @param {string} key Key of item to remove
+ * @return {boolean} Whether the save succeeded or not
+ */
+ SafeStorage.prototype.remove = function ( key ) {
+ try {
+ this.store.removeItem( key );
+ return true;
+ } catch ( e ) {}
+ return false;
+ };
+
+ /**
+ * A wrapper for the HTML5 `localStorage` interface
+ * that is safe to call on all browsers.
+ *
+ * @class
+ * @singleton
+ * @extends mw.SafeStorage
+ */
+ mw.storage = new SafeStorage( localStorage );
+
+ /**
+ * A wrapper for the HTML5 `sessionStorage` interface
+ * that is safe to call on all browsers.
+ *
+ * @class
+ * @singleton
+ * @extends mw.SafeStorage
+ */
+ mw.storage.session = new SafeStorage( sessionStorage );
+
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.template.js b/www/wiki/resources/src/mediawiki/mediawiki.template.js
new file mode 100644
index 00000000..5e0e3432
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.template.js
@@ -0,0 +1,124 @@
+/**
+ * @class mw.template
+ * @singleton
+ */
+( function ( mw, $ ) {
+ var compiledTemplates = {},
+ compilers = {};
+
+ mw.template = {
+ /**
+ * Register a new compiler.
+ *
+ * A compiler is any object that implements a compile() method. The compile() method must
+ * return a Template interface with a method render() that returns HTML.
+ *
+ * The compiler name must correspond with the name suffix of templates that use this compiler.
+ *
+ * @param {string} name Compiler name
+ * @param {Object} compiler
+ */
+ registerCompiler: function ( name, compiler ) {
+ if ( !compiler.compile ) {
+ throw new Error( 'Compiler must implement a compile method' );
+ }
+ compilers[ name ] = compiler;
+ },
+
+ /**
+ * Get the name of the associated compiler based on a template name.
+ *
+ * @param {string} templateName Name of a template (including suffix)
+ * @return {string} Name of a compiler
+ */
+ getCompilerName: function ( templateName ) {
+ var nameParts = templateName.split( '.' );
+ if ( nameParts.length < 2 ) {
+ throw new Error( 'Template name must have a suffix' );
+ }
+ return nameParts[ nameParts.length - 1 ];
+ },
+
+ /**
+ * Get a compiler via its name.
+ *
+ * @param {string} name Name of a compiler
+ * @return {Object} The compiler
+ */
+ getCompiler: function ( name ) {
+ var compiler = compilers[ name ];
+ if ( !compiler ) {
+ throw new Error( 'Unknown compiler ' + name );
+ }
+ return compiler;
+ },
+
+ /**
+ * Register a template associated with a module.
+ *
+ * Precompiles the newly added template based on the suffix in its name.
+ *
+ * @param {string} moduleName Name of the ResourceLoader module the template is associated with
+ * @param {string} templateName Name of the template (including suffix)
+ * @param {string} templateBody Contents of the template (e.g. html markup)
+ * @return {Object} Compiled template
+ */
+ add: function ( moduleName, templateName, templateBody ) {
+ // Precompile and add to cache
+ var compiled = this.compile( templateBody, this.getCompilerName( templateName ) );
+ if ( !compiledTemplates[ moduleName ] ) {
+ compiledTemplates[ moduleName ] = {};
+ }
+ compiledTemplates[ moduleName ][ templateName ] = compiled;
+
+ return compiled;
+ },
+
+ /**
+ * Get a compiled template by module and template name.
+ *
+ * @param {string} moduleName Name of the module to retrieve the template from
+ * @param {string} templateName Name of template to be retrieved
+ * @return {Object} Compiled template
+ */
+ get: function ( moduleName, templateName ) {
+ var moduleTemplates;
+
+ // Try cache first
+ if ( compiledTemplates[ moduleName ] && compiledTemplates[ moduleName ][ templateName ] ) {
+ return compiledTemplates[ moduleName ][ templateName ];
+ }
+
+ moduleTemplates = mw.templates.get( moduleName );
+ if ( !moduleTemplates || !moduleTemplates[ templateName ] ) {
+ throw new Error( 'Template ' + templateName + ' not found in module ' + moduleName );
+ }
+
+ // Compiled and add to cache
+ return this.add( moduleName, templateName, moduleTemplates[ templateName ] );
+ },
+
+ /**
+ * Compile a string of template markup with an engine of choice.
+ *
+ * @param {string} templateBody Template body
+ * @param {string} compilerName The name of a registered compiler
+ * @return {Object} Compiled template
+ */
+ compile: function ( templateBody, compilerName ) {
+ return this.getCompiler( compilerName ).compile( templateBody );
+ }
+ };
+
+ // Register basic html compiler
+ mw.template.registerCompiler( 'html', {
+ compile: function ( src ) {
+ return {
+ render: function () {
+ return $( $.parseHTML( $.trim( src ) ) );
+ }
+ };
+ }
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.template.mustache.js b/www/wiki/resources/src/mediawiki/mediawiki.template.mustache.js
new file mode 100644
index 00000000..9f5e5c4e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.template.mustache.js
@@ -0,0 +1,34 @@
+/* global Mustache */
+( function ( mw, $ ) {
+ // Register mustache compiler
+ mw.template.registerCompiler( 'mustache', {
+ compile: function ( src ) {
+ return {
+ /**
+ * @ignore
+ * @return {string} The raw source code of the template
+ */
+ getSource: function () {
+ return src;
+ },
+ /**
+ * @ignore
+ * @param {Object} data Data to render
+ * @param {Object} partialTemplates Map partial names to Mustache template objects
+ * returned by mw.template.get()
+ * @return {jQuery} Rendered HTML
+ */
+ render: function ( data, partialTemplates ) {
+ var partials = {};
+ if ( partialTemplates ) {
+ $.each( partialTemplates, function ( name, template ) {
+ partials[ name ] = template.getSource();
+ } );
+ }
+ return $( $.parseHTML( Mustache.render( src, data, partials ) ) );
+ }
+ };
+ }
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.template.regexp.js b/www/wiki/resources/src/mediawiki/mediawiki.template.regexp.js
new file mode 100644
index 00000000..3ec0a1f5
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.template.regexp.js
@@ -0,0 +1,15 @@
+mediaWiki.template.registerCompiler( 'regexp', {
+ compile: function ( src ) {
+ return {
+ render: function () {
+ return new RegExp(
+ src
+ // Remove whitespace
+ .replace( /\s+/g, '' )
+ // Remove named capturing groups
+ .replace( /\?<\w+?>/g, '' )
+ );
+ }
+ };
+ }
+} );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.toc.css b/www/wiki/resources/src/mediawiki/mediawiki.toc.css
new file mode 100644
index 00000000..835a4516
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.toc.css
@@ -0,0 +1,11 @@
+.tochidden,
+.toctoggle {
+ -moz-user-select: none;
+ -webkit-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+
+.toctoggle {
+ font-size: 94%;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.toc.js b/www/wiki/resources/src/mediawiki/mediawiki.toc.js
new file mode 100644
index 00000000..5e10a5be
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.toc.js
@@ -0,0 +1,60 @@
+( function ( mw, $ ) {
+ 'use strict';
+
+ // Table of contents toggle
+ mw.hook( 'wikipage.content' ).add( function ( $content ) {
+ $content.find( '.toc' ).addBack( '.toc' ).each( function () {
+ var hideToc,
+ $this = $( this ),
+ $tocTitle = $this.find( '.toctitle' ),
+ $tocToggleLink = $this.find( '.togglelink' ),
+ $tocList = $this.find( 'ul' ).eq( 0 );
+
+ // Hide/show the table of contents element
+ function toggleToc() {
+ if ( $tocList.is( ':hidden' ) ) {
+ $tocList.slideDown( 'fast' );
+ $tocToggleLink.text( mw.msg( 'hidetoc' ) );
+ $this.removeClass( 'tochidden' );
+ mw.cookie.set( 'hidetoc', null );
+ } else {
+ $tocList.slideUp( 'fast' );
+ $tocToggleLink.text( mw.msg( 'showtoc' ) );
+ $this.addClass( 'tochidden' );
+ mw.cookie.set( 'hidetoc', '1' );
+ }
+ }
+
+ // Only add it if there is a complete TOC and it doesn't
+ // have a toggle added already
+ if ( $tocTitle.length && $tocList.length && !$tocToggleLink.length ) {
+ hideToc = mw.cookie.get( 'hidetoc' ) === '1';
+
+ $tocToggleLink = $( '<a role="button" tabindex="0" class="togglelink"></a>' )
+ .text( mw.msg( hideToc ? 'showtoc' : 'hidetoc' ) )
+ .on( 'click keypress', function ( e ) {
+ if (
+ e.type === 'click' ||
+ e.type === 'keypress' && e.which === 13
+ ) {
+ toggleToc();
+ }
+ } );
+
+ $tocTitle.append(
+ $tocToggleLink
+ .wrap( '<span class="toctoggle"></span>' )
+ .parent()
+ .prepend( '&nbsp;[' )
+ .append( ']&nbsp;' )
+ );
+
+ if ( hideToc ) {
+ $tocList.hide();
+ $this.addClass( 'tochidden' );
+ }
+ }
+ } );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.toc.print.css b/www/wiki/resources/src/mediawiki/mediawiki.toc.print.css
new file mode 100644
index 00000000..5f6eb258
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.toc.print.css
@@ -0,0 +1,5 @@
+#toc.tochidden,
+.toc.tochidden,
+.toctoggle {
+ display: none;
+}
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.user.js b/www/wiki/resources/src/mediawiki/mediawiki.user.js
new file mode 100644
index 00000000..65e9e416
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.user.js
@@ -0,0 +1,175 @@
+/**
+ * @class mw.user
+ * @singleton
+ */
+/* global Uint32Array */
+( function ( mw, $ ) {
+ var userInfoPromise;
+
+ /**
+ * Get the current user's groups or rights
+ *
+ * @private
+ * @return {jQuery.Promise}
+ */
+ function getUserInfo() {
+ if ( !userInfoPromise ) {
+ userInfoPromise = new mw.Api().getUserInfo();
+ }
+ return userInfoPromise;
+ }
+
+ // mw.user with the properties options and tokens gets defined in mediawiki.js.
+ $.extend( mw.user, {
+
+ /**
+ * Generate a random user session ID.
+ *
+ * This information would potentially be stored in a cookie to identify a user during a
+ * session or series of sessions. Its uniqueness should not be depended on unless the
+ * browser supports the crypto API.
+ *
+ * Known problems with Math.random():
+ * Using the Math.random function we have seen sets
+ * with 1% of non uniques among 200,000 values with Safari providing most of these.
+ * Given the prevalence of Safari in mobile the percentage of duplicates in
+ * mobile usages of this code is probably higher.
+ *
+ * Rationale:
+ * We need about 64 bits to make sure that probability of collision
+ * on 500 million (5*10^8) is <= 1%
+ * See https://en.wikipedia.org/wiki/Birthday_problem#Probability_table
+ *
+ * @return {string} 64 bit integer in hex format, padded
+ */
+ generateRandomSessionId: function () {
+ var rnds, i,
+ hexRnds = new Array( 2 ),
+ // Support: IE 11
+ crypto = window.crypto || window.msCrypto;
+
+ if ( crypto && crypto.getRandomValues ) {
+ // Fill an array with 2 random values, each of which is 32 bits.
+ // Note that Uint32Array is array-like but does not implement Array.
+ rnds = new Uint32Array( 2 );
+ crypto.getRandomValues( rnds );
+ } else {
+ rnds = [
+ Math.floor( Math.random() * 0x100000000 ),
+ Math.floor( Math.random() * 0x100000000 )
+ ];
+ }
+ // Convert number to a string with 16 hex characters
+ for ( i = 0; i < 2; i++ ) {
+ // Add 0x100000000 before converting to hex and strip the extra character
+ // after converting to keep the leading zeros.
+ hexRnds[ i ] = ( rnds[ i ] + 0x100000000 ).toString( 16 ).slice( 1 );
+ }
+
+ // Concatenation of two random integers with entropy n and m
+ // returns a string with entropy n+m if those strings are independent
+ return hexRnds.join( '' );
+ },
+
+ /**
+ * Get the current user's database id
+ *
+ * Not to be confused with #id.
+ *
+ * @return {number} Current user's id, or 0 if user is anonymous
+ */
+ getId: function () {
+ return mw.config.get( 'wgUserId' ) || 0;
+ },
+
+ /**
+ * Get the current user's name
+ *
+ * @return {string|null} User name string or null if user is anonymous
+ */
+ getName: function () {
+ return mw.config.get( 'wgUserName' );
+ },
+
+ /**
+ * Get date user registered, if available
+ *
+ * @return {boolean|null|Date} False for anonymous users, null if data is
+ * unavailable, or Date for when the user registered.
+ */
+ getRegistration: function () {
+ var registration;
+ if ( mw.user.isAnon() ) {
+ return false;
+ }
+ registration = mw.config.get( 'wgUserRegistration' );
+ // Registration may be unavailable if the user signed up before MediaWiki
+ // began tracking this.
+ return !registration ? null : new Date( registration );
+ },
+
+ /**
+ * Whether the current user is anonymous
+ *
+ * @return {boolean}
+ */
+ isAnon: function () {
+ return mw.user.getName() === null;
+ },
+
+ /**
+ * Get an automatically generated random ID (persisted in sessionStorage)
+ *
+ * This ID is ephemeral for everyone, staying in their browser only until they
+ * close their browsing session.
+ *
+ * @return {string} Random session ID
+ */
+ sessionId: function () {
+ var sessionId = mw.storage.session.get( 'mwuser-sessionId' );
+ if ( !sessionId ) {
+ sessionId = mw.user.generateRandomSessionId();
+ mw.storage.session.set( 'mwuser-sessionId', sessionId );
+ }
+ return sessionId;
+ },
+
+ /**
+ * Get the current user's name or the session ID
+ *
+ * Not to be confused with #getId.
+ *
+ * @return {string} User name or random session ID
+ */
+ id: function () {
+ return mw.user.getName() || mw.user.sessionId();
+ },
+
+ /**
+ * Get the current user's groups
+ *
+ * @param {Function} [callback]
+ * @return {jQuery.Promise}
+ */
+ getGroups: function ( callback ) {
+ var userGroups = mw.config.get( 'wgUserGroups', [] );
+
+ // Uses promise for backwards compatibility
+ return $.Deferred().resolve( userGroups ).done( callback );
+ },
+
+ /**
+ * Get the current user's rights
+ *
+ * @param {Function} [callback]
+ * @return {jQuery.Promise}
+ */
+ getRights: function ( callback ) {
+ return getUserInfo().then(
+ function ( userInfo ) { return userInfo.rights; },
+ function () { return []; }
+ ).done( callback );
+ }
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.userSuggest.js b/www/wiki/resources/src/mediawiki/mediawiki.userSuggest.js
new file mode 100644
index 00000000..99e9dbe0
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.userSuggest.js
@@ -0,0 +1,42 @@
+/*!
+ * Add autocomplete suggestions for names of registered users.
+ */
+( function ( mw, $ ) {
+ var api, config;
+
+ config = {
+ fetch: function ( userInput, response, maxRows ) {
+ var node = this[ 0 ];
+
+ api = api || new mw.Api();
+
+ $.data( node, 'request', api.get( {
+ formatversion: 2,
+ action: 'query',
+ list: 'allusers',
+ // Prefix of list=allusers is case sensitive. Normalise first
+ // character to uppercase so that "fo" may yield "Foo".
+ auprefix: userInput[ 0 ].toUpperCase() + userInput.slice( 1 ),
+ aulimit: maxRows
+ } ).done( function ( data ) {
+ var users = $.map( data.query.allusers, function ( userObj ) {
+ return userObj.name;
+ } );
+ response( users );
+ } ) );
+ },
+ cancel: function () {
+ var node = this[ 0 ],
+ request = $.data( node, 'request' );
+
+ if ( request ) {
+ request.abort();
+ $.removeData( node, 'request' );
+ }
+ }
+ };
+
+ $( function () {
+ $( '.mw-autocomplete-user' ).suggestions( config );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.util.js b/www/wiki/resources/src/mediawiki/mediawiki.util.js
new file mode 100644
index 00000000..fb34a890
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.util.js
@@ -0,0 +1,648 @@
+( function ( mw, $ ) {
+ 'use strict';
+
+ var util;
+
+ /**
+ * Encode the string like PHP's rawurlencode
+ * @ignore
+ *
+ * @param {string} str String to be encoded.
+ * @return {string} Encoded string
+ */
+ function rawurlencode( str ) {
+ str = String( str );
+ return encodeURIComponent( str )
+ .replace( /!/g, '%21' ).replace( /'/g, '%27' ).replace( /\(/g, '%28' )
+ .replace( /\)/g, '%29' ).replace( /\*/g, '%2A' ).replace( /~/g, '%7E' );
+ }
+
+ /**
+ * Private helper function used by util.escapeId*()
+ * @ignore
+ *
+ * @param {string} str String to be encoded
+ * @param {string} mode Encoding mode, see documentation for $wgFragmentMode
+ * in DefaultSettings.php
+ * @return {string} Encoded string
+ */
+ function escapeIdInternal( str, mode ) {
+ str = String( str );
+
+ switch ( mode ) {
+ case 'html5':
+ return str.replace( / /g, '_' );
+ case 'html5-legacy':
+ str = str.replace( /[ \t\n\r\f_'"&#%]+/g, '_' )
+ .replace( /^_+|_+$/, '' );
+ if ( str === '' ) {
+ str = '_';
+ }
+ return str;
+ case 'legacy':
+ return rawurlencode( str.replace( / /g, '_' ) )
+ .replace( /%3A/g, ':' )
+ .replace( /%/g, '.' );
+ default:
+ throw new Error( 'Unrecognized ID escaping mode ' + mode );
+ }
+ }
+
+ /**
+ * Utility library
+ * @class mw.util
+ * @singleton
+ */
+ util = {
+
+ /* Main body */
+
+ /**
+ * Encode the string like PHP's rawurlencode
+ *
+ * @param {string} str String to be encoded.
+ * @return {string} Encoded string
+ */
+ rawurlencode: rawurlencode,
+
+ /**
+ * Encode string into HTML id compatible form suitable for use in HTML
+ * Analog to PHP Sanitizer::escapeIdForAttribute()
+ *
+ * @since 1.30
+ *
+ * @param {string} str String to encode
+ * @return {string} Encoded string
+ */
+ escapeIdForAttribute: function ( str ) {
+ var mode = mw.config.get( 'wgFragmentMode' )[ 0 ];
+
+ return escapeIdInternal( str, mode );
+ },
+
+ /**
+ * Encode string into HTML id compatible form suitable for use in links
+ * Analog to PHP Sanitizer::escapeIdForLink()
+ *
+ * @since 1.30
+ *
+ * @param {string} str String to encode
+ * @return {string} Encoded string
+ */
+ escapeIdForLink: function ( str ) {
+ var mode = mw.config.get( 'wgFragmentMode' )[ 0 ];
+
+ return escapeIdInternal( str, mode );
+ },
+
+ /**
+ * Encode page titles for use in a URL
+ *
+ * We want / and : to be included as literal characters in our title URLs
+ * as they otherwise fatally break the title.
+ *
+ * The others are decoded because we can, it's prettier and matches behaviour
+ * of `wfUrlencode` in PHP.
+ *
+ * @param {string} str String to be encoded.
+ * @return {string} Encoded string
+ */
+ wikiUrlencode: function ( str ) {
+ return util.rawurlencode( str )
+ .replace( /%20/g, '_' )
+ // wfUrlencode replacements
+ .replace( /%3B/g, ';' )
+ .replace( /%40/g, '@' )
+ .replace( /%24/g, '$' )
+ .replace( /%21/g, '!' )
+ .replace( /%2A/g, '*' )
+ .replace( /%28/g, '(' )
+ .replace( /%29/g, ')' )
+ .replace( /%2C/g, ',' )
+ .replace( /%2F/g, '/' )
+ .replace( /%7E/g, '~' )
+ .replace( /%3A/g, ':' );
+ },
+
+ /**
+ * Get the link to a page name (relative to `wgServer`),
+ *
+ * @param {string|null} [pageName=wgPageName] Page name
+ * @param {Object} [params] A mapping of query parameter names to values,
+ * e.g. `{ action: 'edit' }`
+ * @return {string} Url of the page with name of `pageName`
+ */
+ getUrl: function ( pageName, params ) {
+ var titleFragmentStart, url, query,
+ fragment = '',
+ title = typeof pageName === 'string' ? pageName : mw.config.get( 'wgPageName' );
+
+ // Find any fragment
+ titleFragmentStart = title.indexOf( '#' );
+ if ( titleFragmentStart !== -1 ) {
+ fragment = title.slice( titleFragmentStart + 1 );
+ // Exclude the fragment from the page name
+ title = title.slice( 0, titleFragmentStart );
+ }
+
+ // Produce query string
+ if ( params ) {
+ query = $.param( params );
+ }
+ if ( query ) {
+ url = title ?
+ util.wikiScript() + '?title=' + util.wikiUrlencode( title ) + '&' + query :
+ util.wikiScript() + '?' + query;
+ } else {
+ url = mw.config.get( 'wgArticlePath' )
+ .replace( '$1', util.wikiUrlencode( title ).replace( /\$/g, '$$$$' ) );
+ }
+
+ // Append the encoded fragment
+ if ( fragment.length ) {
+ url += '#' + util.escapeIdForLink( fragment );
+ }
+
+ return url;
+ },
+
+ /**
+ * Get address to a script in the wiki root.
+ * For index.php use `mw.config.get( 'wgScript' )`.
+ *
+ * @since 1.18
+ * @param {string} str Name of script (e.g. 'api'), defaults to 'index'
+ * @return {string} Address to script (e.g. '/w/api.php' )
+ */
+ wikiScript: function ( str ) {
+ str = str || 'index';
+ if ( str === 'index' ) {
+ return mw.config.get( 'wgScript' );
+ } else if ( str === 'load' ) {
+ return mw.config.get( 'wgLoadScript' );
+ } else {
+ return mw.config.get( 'wgScriptPath' ) + '/' + str + '.php';
+ }
+ },
+
+ /**
+ * Append a new style block to the head and return the CSSStyleSheet object.
+ * Use .ownerNode to access the `<style>` element, or use mw.loader#addStyleTag.
+ * This function returns the styleSheet object for convience (due to cross-browsers
+ * difference as to where it is located).
+ *
+ * var sheet = util.addCSS( '.foobar { display: none; }' );
+ * $( foo ).click( function () {
+ * // Toggle the sheet on and off
+ * sheet.disabled = !sheet.disabled;
+ * } );
+ *
+ * @param {string} text CSS to be appended
+ * @return {CSSStyleSheet} Use .ownerNode to get to the `<style>` element.
+ */
+ addCSS: function ( text ) {
+ var s = mw.loader.addStyleTag( text );
+ return s.sheet || s.styleSheet || s;
+ },
+
+ /**
+ * Grab the URL parameter value for the given parameter.
+ * Returns null if not found.
+ *
+ * @param {string} param The parameter name.
+ * @param {string} [url=location.href] URL to search through, defaulting to the current browsing location.
+ * @return {Mixed} Parameter value or null.
+ */
+ getParamValue: function ( param, url ) {
+ // Get last match, stop at hash
+ var re = new RegExp( '^[^#]*[&?]' + mw.RegExp.escape( param ) + '=([^&#]*)' ),
+ m = re.exec( url !== undefined ? url : location.href );
+
+ if ( m ) {
+ // Beware that decodeURIComponent is not required to understand '+'
+ // by spec, as encodeURIComponent does not produce it.
+ return decodeURIComponent( m[ 1 ].replace( /\+/g, '%20' ) );
+ }
+ return null;
+ },
+
+ /**
+ * The content wrapper of the skin (e.g. `.mw-body`).
+ *
+ * Populated on document ready. To use this property,
+ * wait for `$.ready` and be sure to have a module dependency on
+ * `mediawiki.util` which will ensure
+ * your document ready handler fires after initialization.
+ *
+ * Because of the lazy-initialised nature of this property,
+ * you're discouraged from using it.
+ *
+ * If you need just the wikipage content (not any of the
+ * extra elements output by the skin), use `$( '#mw-content-text' )`
+ * instead. Or listen to mw.hook#wikipage_content which will
+ * allow your code to re-run when the page changes (e.g. live preview
+ * or re-render after ajax save).
+ *
+ * @property {jQuery}
+ */
+ $content: null,
+
+ /**
+ * Add a link to a portlet menu on the page, such as:
+ *
+ * p-cactions (Content actions), p-personal (Personal tools),
+ * p-navigation (Navigation), p-tb (Toolbox)
+ *
+ * The first three parameters are required, the others are optional and
+ * may be null. Though providing an id and tooltip is recommended.
+ *
+ * By default the new link will be added to the end of the list. To
+ * add the link before a given existing item, pass the DOM node
+ * (e.g. `document.getElementById( 'foobar' )`) or a jQuery-selector
+ * (e.g. `'#foobar'`) for that item.
+ *
+ * util.addPortletLink(
+ * 'p-tb', 'https://www.mediawiki.org/',
+ * 'mediawiki.org', 't-mworg', 'Go to mediawiki.org', 'm', '#t-print'
+ * );
+ *
+ * var node = util.addPortletLink(
+ * 'p-tb',
+ * new mw.Title( 'Special:Example' ).getUrl(),
+ * 'Example'
+ * );
+ * $( node ).on( 'click', function ( e ) {
+ * console.log( 'Example' );
+ * e.preventDefault();
+ * } );
+ *
+ * @param {string} portlet ID of the target portlet ( 'p-cactions' or 'p-personal' etc.)
+ * @param {string} href Link URL
+ * @param {string} text Link text
+ * @param {string} [id] ID of the new item, should be unique and preferably have
+ * the appropriate prefix ( 'ca-', 'pt-', 'n-' or 't-' )
+ * @param {string} [tooltip] Text to show when hovering over the link, without accesskey suffix
+ * @param {string} [accesskey] Access key to activate this link (one character, try
+ * to avoid conflicts. Use `$( '[accesskey=x]' ).get()` in the console to
+ * see if 'x' is already used.
+ * @param {HTMLElement|jQuery|string} [nextnode] Element or jQuery-selector string to the item that
+ * the new item should be added before, should be another item in the same
+ * list, it will be ignored otherwise
+ *
+ * @return {HTMLElement|null} The added element (a ListItem or Anchor element,
+ * depending on the skin) or null if no element was added to the document.
+ */
+ addPortletLink: function ( portlet, href, text, id, tooltip, accesskey, nextnode ) {
+ var $item, $link, $portlet, $ul;
+
+ // Check if there's at least 3 arguments to prevent a TypeError
+ if ( arguments.length < 3 ) {
+ return null;
+ }
+ // Setup the anchor tag
+ $link = $( '<a>' ).attr( 'href', href ).text( text );
+ if ( tooltip ) {
+ $link.attr( 'title', tooltip );
+ }
+
+ // Select the specified portlet
+ $portlet = $( '#' + portlet );
+ if ( $portlet.length === 0 ) {
+ return null;
+ }
+ // Select the first (most likely only) unordered list inside the portlet
+ $ul = $portlet.find( 'ul' ).eq( 0 );
+
+ // If it didn't have an unordered list yet, create it
+ if ( $ul.length === 0 ) {
+
+ $ul = $( '<ul>' );
+
+ // If there's no <div> inside, append it to the portlet directly
+ if ( $portlet.find( 'div:first' ).length === 0 ) {
+ $portlet.append( $ul );
+ } else {
+ // otherwise if there's a div (such as div.body or div.pBody)
+ // append the <ul> to last (most likely only) div
+ $portlet.find( 'div' ).eq( -1 ).append( $ul );
+ }
+ }
+ // Just in case..
+ if ( $ul.length === 0 ) {
+ return null;
+ }
+
+ // Unhide portlet if it was hidden before
+ $portlet.removeClass( 'emptyPortlet' );
+
+ // Wrap the anchor tag in a list item (and a span if $portlet is a Vector tab)
+ // and back up the selector to the list item
+ if ( $portlet.hasClass( 'vectorTabs' ) ) {
+ $item = $link.wrap( '<li><span></span></li>' ).parent().parent();
+ } else {
+ $item = $link.wrap( '<li></li>' ).parent();
+ }
+
+ // Implement the properties passed to the function
+ if ( id ) {
+ $item.attr( 'id', id );
+ }
+
+ if ( accesskey ) {
+ $link.attr( 'accesskey', accesskey );
+ }
+
+ if ( tooltip ) {
+ $link.attr( 'title', tooltip );
+ }
+
+ if ( nextnode ) {
+ // Case: nextnode is a DOM element (was the only option before MW 1.17, in wikibits.js)
+ // Case: nextnode is a CSS selector for jQuery
+ if ( nextnode.nodeType || typeof nextnode === 'string' ) {
+ nextnode = $ul.find( nextnode );
+ } else if ( !nextnode.jquery ) {
+ // Error: Invalid nextnode
+ nextnode = undefined;
+ }
+ if ( nextnode && ( nextnode.length !== 1 || nextnode[ 0 ].parentNode !== $ul[ 0 ] ) ) {
+ // Error: nextnode must resolve to a single node
+ // Error: nextnode must have the associated <ul> as its parent
+ nextnode = undefined;
+ }
+ }
+
+ // Case: nextnode is a jQuery-wrapped DOM element
+ if ( nextnode ) {
+ nextnode.before( $item );
+ } else {
+ // Fallback (this is the default behavior)
+ $ul.append( $item );
+ }
+
+ // Update tooltip for the access key after inserting into DOM
+ // to get a localized access key label (T69946).
+ $link.updateTooltipAccessKeys();
+
+ return $item[ 0 ];
+ },
+
+ /**
+ * Validate a string as representing a valid e-mail address
+ * according to HTML5 specification. Please note the specification
+ * does not validate a domain with one character.
+ *
+ * FIXME: should be moved to or replaced by a validation module.
+ *
+ * @param {string} mailtxt E-mail address to be validated.
+ * @return {boolean|null} Null if `mailtxt` was an empty string, otherwise true/false
+ * as determined by validation.
+ */
+ validateEmail: function ( mailtxt ) {
+ var rfc5322Atext, rfc1034LdhStr, html5EmailRegexp;
+
+ if ( mailtxt === '' ) {
+ return null;
+ }
+
+ // HTML5 defines a string as valid e-mail address if it matches
+ // the ABNF:
+ // 1 * ( atext / "." ) "@" ldh-str 1*( "." ldh-str )
+ // With:
+ // - atext : defined in RFC 5322 section 3.2.3
+ // - ldh-str : defined in RFC 1034 section 3.5
+ //
+ // (see STD 68 / RFC 5234 https://tools.ietf.org/html/std68)
+ // First, define the RFC 5322 'atext' which is pretty easy:
+ // atext = ALPHA / DIGIT / ; Printable US-ASCII
+ // "!" / "#" / ; characters not including
+ // "$" / "%" / ; specials. Used for atoms.
+ // "&" / "'" /
+ // "*" / "+" /
+ // "-" / "/" /
+ // "=" / "?" /
+ // "^" / "_" /
+ // "`" / "{" /
+ // "|" / "}" /
+ // "~"
+ rfc5322Atext = 'a-z0-9!#$%&\'*+\\-/=?^_`{|}~';
+
+ // Next define the RFC 1034 'ldh-str'
+ // <domain> ::= <subdomain> | " "
+ // <subdomain> ::= <label> | <subdomain> "." <label>
+ // <label> ::= <letter> [ [ <ldh-str> ] <let-dig> ]
+ // <ldh-str> ::= <let-dig-hyp> | <let-dig-hyp> <ldh-str>
+ // <let-dig-hyp> ::= <let-dig> | "-"
+ // <let-dig> ::= <letter> | <digit>
+ rfc1034LdhStr = 'a-z0-9\\-';
+
+ html5EmailRegexp = new RegExp(
+ // start of string
+ '^' +
+ // User part which is liberal :p
+ '[' + rfc5322Atext + '\\.]+' +
+ // 'at'
+ '@' +
+ // Domain first part
+ '[' + rfc1034LdhStr + ']+' +
+ // Optional second part and following are separated by a dot
+ '(?:\\.[' + rfc1034LdhStr + ']+)*' +
+ // End of string
+ '$',
+ // RegExp is case insensitive
+ 'i'
+ );
+ return ( mailtxt.match( html5EmailRegexp ) !== null );
+ },
+
+ /**
+ * Note: borrows from IP::isIPv4
+ *
+ * @param {string} address
+ * @param {boolean} allowBlock
+ * @return {boolean}
+ */
+ isIPv4Address: function ( address, allowBlock ) {
+ var block, RE_IP_BYTE, RE_IP_ADD;
+
+ if ( typeof address !== 'string' ) {
+ return false;
+ }
+
+ block = allowBlock ? '(?:\\/(?:3[0-2]|[12]?\\d))?' : '';
+ RE_IP_BYTE = '(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|0?[0-9]?[0-9])';
+ RE_IP_ADD = '(?:' + RE_IP_BYTE + '\\.){3}' + RE_IP_BYTE;
+
+ return ( new RegExp( '^' + RE_IP_ADD + block + '$' ).test( address ) );
+ },
+
+ /**
+ * Note: borrows from IP::isIPv6
+ *
+ * @param {string} address
+ * @param {boolean} allowBlock
+ * @return {boolean}
+ */
+ isIPv6Address: function ( address, allowBlock ) {
+ var block, RE_IPV6_ADD;
+
+ if ( typeof address !== 'string' ) {
+ return false;
+ }
+
+ block = allowBlock ? '(?:\\/(?:12[0-8]|1[01][0-9]|[1-9]?\\d))?' : '';
+ RE_IPV6_ADD =
+ '(?:' + // starts with "::" (including "::")
+ ':(?::|(?::' +
+ '[0-9A-Fa-f]{1,4}' +
+ '){1,7})' +
+ '|' + // ends with "::" (except "::")
+ '[0-9A-Fa-f]{1,4}' +
+ '(?::' +
+ '[0-9A-Fa-f]{1,4}' +
+ '){0,6}::' +
+ '|' + // contains no "::"
+ '[0-9A-Fa-f]{1,4}' +
+ '(?::' +
+ '[0-9A-Fa-f]{1,4}' +
+ '){7}' +
+ ')';
+
+ if ( new RegExp( '^' + RE_IPV6_ADD + block + '$' ).test( address ) ) {
+ return true;
+ }
+
+ // contains one "::" in the middle (single '::' check below)
+ RE_IPV6_ADD =
+ '[0-9A-Fa-f]{1,4}' +
+ '(?:::?' +
+ '[0-9A-Fa-f]{1,4}' +
+ '){1,6}';
+
+ return (
+ new RegExp( '^' + RE_IPV6_ADD + block + '$' ).test( address ) &&
+ /::/.test( address ) &&
+ !/::.*::/.test( address )
+ );
+ },
+
+ /**
+ * Check whether a string is an IP address
+ *
+ * @since 1.25
+ * @param {string} address String to check
+ * @param {boolean} allowBlock True if a block of IPs should be allowed
+ * @return {boolean}
+ */
+ isIPAddress: function ( address, allowBlock ) {
+ return util.isIPv4Address( address, allowBlock ) ||
+ util.isIPv6Address( address, allowBlock );
+ }
+ };
+
+ /**
+ * @method wikiGetlink
+ * @inheritdoc #getUrl
+ * @deprecated since 1.23 Use #getUrl instead.
+ */
+ mw.log.deprecate( util, 'wikiGetlink', util.getUrl, 'Use mw.util.getUrl instead.', 'mw.util.wikiGetlink' );
+
+ /**
+ * Add the appropriate prefix to the accesskey shown in the tooltip.
+ *
+ * If the `$nodes` parameter is given, only those nodes are updated;
+ * otherwise we update all elements with accesskeys on the page.
+ *
+ * @method updateTooltipAccessKeys
+ * @param {Array|jQuery} [$nodes] A jQuery object, or array of nodes to update.
+ * @deprecated since 1.24 Use the module jquery.accessKeyLabel instead.
+ */
+ mw.log.deprecate( util, 'updateTooltipAccessKeys', function ( $nodes ) {
+ if ( !$nodes ) {
+ $nodes = $( '[accesskey]' );
+ } else if ( !( $nodes instanceof $ ) ) {
+ $nodes = $( $nodes );
+ }
+
+ $nodes.updateTooltipAccessKeys();
+ }, 'Use jquery.accessKeyLabel instead.', 'mw.util.updateTooltipAccessKeys' );
+
+ /**
+ * Add a little box at the top of the screen to inform the user of
+ * something, replacing any previous message.
+ * Calling with no arguments, with an empty string or null will hide the message
+ *
+ * @method jsMessage
+ * @deprecated since 1.20 Use mw#notify
+ * @param {Mixed} message The DOM-element, jQuery object or HTML-string to be put inside the message box.
+ * to allow CSS/JS to hide different boxes. null = no class used.
+ */
+ mw.log.deprecate( util, 'jsMessage', function ( message ) {
+ if ( !arguments.length || message === '' || message === null ) {
+ return true;
+ }
+ if ( typeof message !== 'object' ) {
+ message = $.parseHTML( message );
+ }
+ mw.notify( message, { autoHide: true, tag: 'legacy' } );
+ return true;
+ }, 'Use mw.notify instead.', 'mw.util.jsMessage' );
+
+ /**
+ * Encode the string like Sanitizer::escapeId() in PHP
+ *
+ * @method escapeId
+ * @deprecated since 1.30 use escapeIdForAttribute() or escapeIdForLink()
+ * @param {string} str String to be encoded.
+ * @return {string} Encoded string
+ */
+ mw.log.deprecate( util, 'escapeId', function ( str ) {
+ return escapeIdInternal( str, 'legacy' );
+ }, 'Use mw.util.escapeIdForAttribute or mw.util.escapeIdForLink instead.', 'mw.util.escapeId' );
+
+ /**
+ * Initialisation of mw.util.$content
+ */
+ function init() {
+ util.$content = ( function () {
+ var i, l, $node, selectors;
+
+ selectors = [
+ // The preferred standard is class "mw-body".
+ // You may also use class "mw-body mw-body-primary" if you use
+ // mw-body in multiple locations. Or class "mw-body-primary" if
+ // you use mw-body deeper in the DOM.
+ '.mw-body-primary',
+ '.mw-body',
+
+ // If the skin has no such class, fall back to the parser output
+ '#mw-content-text'
+ ];
+
+ for ( i = 0, l = selectors.length; i < l; i++ ) {
+ $node = $( selectors[ i ] );
+ if ( $node.length ) {
+ return $node.first();
+ }
+ }
+
+ // Should never happen... well, it could if someone is not finished writing a
+ // skin and has not yet inserted bodytext yet.
+ return $( 'body' );
+ }() );
+ }
+
+ /**
+ * Former public initialisation. Now a no-op function.
+ *
+ * @method util_init
+ * @deprecated since 1.30
+ */
+ mw.log.deprecate( util, 'init', $.noop, 'Remove the call of mw.util.init().', 'mw.util.init' );
+
+ $( init );
+
+ mw.util = util;
+ module.exports = util;
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/mediawiki.viewport.js b/www/wiki/resources/src/mediawiki/mediawiki.viewport.js
new file mode 100644
index 00000000..b453ac8d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/mediawiki.viewport.js
@@ -0,0 +1,101 @@
+( function ( mw, $ ) {
+ 'use strict';
+
+ /**
+ * Utility library for viewport-related functions
+ *
+ * Notable references:
+ * - https://github.com/tuupola/jquery_lazyload
+ * - https://github.com/luis-almeida/unveil
+ *
+ * @class mw.viewport
+ * @singleton
+ */
+ var viewport = {
+
+ /**
+ * This is a private method pulled inside the module for testing purposes.
+ *
+ * @ignore
+ * @private
+ * @return {Object} Viewport positions
+ */
+ makeViewportFromWindow: function () {
+ var $window = $( window ),
+ scrollTop = $window.scrollTop(),
+ scrollLeft = $window.scrollLeft();
+
+ return {
+ top: scrollTop,
+ left: scrollLeft,
+ right: scrollLeft + $window.width(),
+ bottom: ( window.innerHeight ? window.innerHeight : $window.height() ) + scrollTop
+ };
+ },
+
+ /**
+ * Check if any part of a given element is in a given viewport
+ *
+ * @method
+ * @param {HTMLElement} el Element that's being tested
+ * @param {Object} [rectangle] Viewport to test against; structured as such:
+ *
+ * var rectangle = {
+ * top: topEdge,
+ * left: leftEdge,
+ * right: rightEdge,
+ * bottom: bottomEdge
+ * }
+ * Defaults to viewport made from `window`.
+ *
+ * @return {boolean}
+ */
+ isElementInViewport: function ( el, rectangle ) {
+ var $el = $( el ),
+ offset = $el.offset(),
+ rect = {
+ height: $el.height(),
+ width: $el.width(),
+ top: offset.top,
+ left: offset.left
+ },
+ viewport = rectangle || this.makeViewportFromWindow();
+
+ return (
+ // Top border must be above viewport's bottom
+ ( viewport.bottom >= rect.top ) &&
+ // Left border must be before viewport's right border
+ ( viewport.right >= rect.left ) &&
+ // Bottom border must be below viewport's top
+ ( viewport.top <= rect.top + rect.height ) &&
+ // Right border must be after viewport's left border
+ ( viewport.left <= rect.left + rect.width )
+ );
+ },
+
+ /**
+ * Check if an element is a given threshold away in any direction from a given viewport
+ *
+ * @method
+ * @param {HTMLElement} el Element that's being tested
+ * @param {number} [threshold] Pixel distance considered "close". Must be a positive number.
+ * Defaults to 50.
+ * @param {Object} [rectangle] Viewport to test against.
+ * Defaults to viewport made from `window`.
+ * @return {boolean}
+ */
+ isElementCloseToViewport: function ( el, threshold, rectangle ) {
+ var viewport = rectangle ? $.extend( {}, rectangle ) : this.makeViewportFromWindow();
+ threshold = threshold || 50;
+
+ viewport.top -= threshold;
+ viewport.left -= threshold;
+ viewport.right += threshold;
+ viewport.bottom += threshold;
+ return this.isElementInViewport( el, viewport );
+ }
+
+ };
+
+ mw.viewport = viewport;
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/page/gallery-print.css b/www/wiki/resources/src/mediawiki/page/gallery-print.css
new file mode 100644
index 00000000..0c14865e
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/page/gallery-print.css
@@ -0,0 +1,35 @@
+li.gallerybox {
+ vertical-align: top;
+ display: inline-block;
+}
+
+ul.gallery, li.gallerybox {
+ zoom: 1;
+ *display: inline;
+}
+
+ul.gallery {
+ margin: 2px;
+ padding: 2px;
+ display: block;
+}
+
+li.gallerycaption {
+ font-weight: bold;
+ text-align: center;
+ display: block;
+ word-wrap: break-word;
+}
+
+li.gallerybox div.thumb {
+ text-align: center;
+ border: 1px solid #ccc;
+ margin: 2px;
+}
+
+div.gallerytext {
+ overflow: hidden;
+ font-size: 94%;
+ padding: 2px 4px;
+ word-wrap: break-word;
+}
diff --git a/www/wiki/resources/src/mediawiki/page/gallery-slideshow.js b/www/wiki/resources/src/mediawiki/page/gallery-slideshow.js
new file mode 100644
index 00000000..6e9ff0e7
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/page/gallery-slideshow.js
@@ -0,0 +1,460 @@
+/*!
+ * mw.GallerySlideshow: Interface controls for the slideshow gallery
+ */
+( function ( mw, $, OO ) {
+ /**
+ * mw.GallerySlideshow encapsulates the user interface of the slideshow
+ * galleries. An object is instantiated for each `.mw-gallery-slideshow`
+ * element.
+ *
+ * @class mw.GallerySlideshow
+ * @uses mw.Title
+ * @uses mw.Api
+ * @param {jQuery} gallery The `<ul>` element of the gallery.
+ */
+ mw.GallerySlideshow = function ( gallery ) {
+ // Properties
+ this.$gallery = $( gallery );
+ this.$galleryCaption = this.$gallery.find( '.gallerycaption' );
+ this.$galleryBox = this.$gallery.find( '.gallerybox' );
+ this.$currentImage = null;
+ this.imageInfoCache = {};
+ if ( this.$gallery.parent().attr( 'id' ) !== 'mw-content-text' ) {
+ this.$container = this.$gallery.parent();
+ }
+
+ // Initialize
+ this.drawCarousel();
+ this.setSizeRequirement();
+ this.toggleThumbnails( !!this.$gallery.attr( 'data-showthumbnails' ) );
+ this.showCurrentImage();
+
+ // Events
+ $( window ).on(
+ 'resize',
+ OO.ui.debounce(
+ this.setSizeRequirement.bind( this ),
+ 100
+ )
+ );
+
+ // Disable thumbnails' link, instead show the image in the carousel
+ this.$galleryBox.on( 'click', function ( e ) {
+ this.$currentImage = $( e.currentTarget );
+ this.showCurrentImage();
+ return false;
+ }.bind( this ) );
+ };
+
+ /* Properties */
+ /**
+ * @property {jQuery} $gallery The `<ul>` element of the gallery.
+ */
+
+ /**
+ * @property {jQuery} $galleryCaption The `<li>` that has the gallery caption.
+ */
+
+ /**
+ * @property {jQuery} $galleryBox Selection of `<li>` elements that have thumbnails.
+ */
+
+ /**
+ * @property {jQuery} $carousel The `<li>` elements that contains the carousel.
+ */
+
+ /**
+ * @property {jQuery} $interface The `<div>` elements that contains the interface buttons.
+ */
+
+ /**
+ * @property {jQuery} $img The `<img>` element that'll display the current image.
+ */
+
+ /**
+ * @property {jQuery} $imgLink The `<a>` element that links to the image's File page.
+ */
+
+ /**
+ * @property {jQuery} $imgCaption The `<p>` element that holds the image caption.
+ */
+
+ /**
+ * @property {jQuery} $imgContainer The `<div>` element that contains the image.
+ */
+
+ /**
+ * @property {jQuery} $currentImage The `<li>` element of the current image.
+ */
+
+ /**
+ * @property {jQuery} $container If the gallery contained in an element that is
+ * not the main content element, then it stores that element.
+ */
+
+ /**
+ * @property {Object} imageInfoCache A key value pair of thumbnail URLs and image info.
+ */
+
+ /**
+ * @property {number} imageWidth Width of the image based on viewport size
+ */
+
+ /**
+ * @property {number} imageHeight Height of the image based on viewport size
+ * the URLs in the required size.
+ */
+
+ /* Setup */
+ OO.initClass( mw.GallerySlideshow );
+
+ /* Methods */
+ /**
+ * Draws the carousel and the interface around it.
+ */
+ mw.GallerySlideshow.prototype.drawCarousel = function () {
+ var next, prev, toggle, interfaceElements, carouselStack;
+
+ this.$carousel = $( '<li>' ).addClass( 'gallerycarousel' );
+
+ // Buttons for the interface
+ prev = new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'previous'
+ } ).on( 'click', this.prevImage.bind( this ) );
+
+ next = new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'next'
+ } ).on( 'click', this.nextImage.bind( this ) );
+
+ toggle = new OO.ui.ButtonWidget( {
+ framed: false,
+ icon: 'imageGallery',
+ title: mw.msg( 'gallery-slideshow-toggle' )
+ } ).on( 'click', this.toggleThumbnails.bind( this ) );
+
+ interfaceElements = new OO.ui.PanelLayout( {
+ expanded: false,
+ classes: [ 'mw-gallery-slideshow-buttons' ],
+ $content: $( '<div>' ).append(
+ prev.$element,
+ toggle.$element,
+ next.$element
+ )
+ } );
+ this.$interface = interfaceElements.$element;
+
+ // Containers for the current image, caption etc.
+ this.$img = $( '<img>' );
+ this.$imgLink = $( '<a>' ).append( this.$img );
+ this.$imgCaption = $( '<p>' ).attr( 'class', 'mw-gallery-slideshow-caption' );
+ this.$imgContainer = $( '<div>' )
+ .attr( 'class', 'mw-gallery-slideshow-img-container' )
+ .append( this.$imgLink );
+
+ carouselStack = new OO.ui.StackLayout( {
+ continuous: true,
+ expanded: false,
+ items: [
+ interfaceElements,
+ new OO.ui.PanelLayout( {
+ expanded: false,
+ $content: this.$imgContainer
+ } ),
+ new OO.ui.PanelLayout( {
+ expanded: false,
+ $content: this.$imgCaption
+ } )
+ ]
+ } );
+ this.$carousel.append( carouselStack.$element );
+
+ // Append below the caption or as the first element in the gallery
+ if ( this.$galleryCaption.length !== 0 ) {
+ this.$galleryCaption.after( this.$carousel );
+ } else {
+ this.$gallery.prepend( this.$carousel );
+ }
+ };
+
+ /**
+ * Sets the {@link #imageWidth} and {@link #imageHeight} properties
+ * based on the size of the window. Also flushes the
+ * {@link #imageInfoCache} as we'll now need URLs for a different
+ * size.
+ */
+ mw.GallerySlideshow.prototype.setSizeRequirement = function () {
+ var w, h;
+
+ if ( this.$container !== undefined ) {
+ w = this.$container.width() * 0.9;
+ h = ( this.$container.height() - this.getChromeHeight() ) * 0.9;
+ } else {
+ w = this.$imgContainer.width();
+ h = Math.min( $( window ).height() * ( 3 / 4 ), this.$imgContainer.width() ) - this.getChromeHeight();
+ }
+
+ // Only update and flush the cache if the size changed
+ if ( w !== this.imageWidth || h !== this.imageHeight ) {
+ this.imageWidth = w;
+ this.imageHeight = h;
+ this.imageInfoCache = {};
+ this.setImageSize();
+ }
+ };
+
+ /**
+ * Gets the height of the interface elements and the
+ * gallery's caption.
+ *
+ * @return {number} Height
+ */
+ mw.GallerySlideshow.prototype.getChromeHeight = function () {
+ return this.$interface.outerHeight() + this.$galleryCaption.outerHeight();
+ };
+
+ /**
+ * Sets the height and width of {@link #$img} based on the
+ * proportion of the image and the values generated by
+ * {@link #setSizeRequirement}.
+ *
+ * @return {boolean} Whether or not the image was sized.
+ */
+ mw.GallerySlideshow.prototype.setImageSize = function () {
+ if ( this.$img === undefined || this.$thumbnail === undefined ) {
+ return false;
+ }
+
+ // Reset height and width
+ this.$img
+ .removeAttr( 'width' )
+ .removeAttr( 'height' );
+
+ // Stretch image to take up the required size
+ this.$img.attr( 'height', ( this.imageHeight - this.$imgCaption.outerHeight() ) + 'px' );
+
+ // Make the image smaller in case the current image
+ // size is larger than the original file size.
+ this.getImageInfo( this.$thumbnail ).done( function ( info ) {
+ // NOTE: There will be a jump when resizing the window
+ // because the cache is cleared and this a new network request.
+ if (
+ info.thumbwidth < this.$img.width() ||
+ info.thumbheight < this.$img.height()
+ ) {
+ this.$img.attr( 'width', info.thumbwidth + 'px' );
+ this.$img.attr( 'height', info.thumbheight + 'px' );
+ }
+ }.bind( this ) );
+
+ return true;
+ };
+
+ /**
+ * Displays the image set as {@link #$currentImage} in the carousel.
+ */
+ mw.GallerySlideshow.prototype.showCurrentImage = function () {
+ var imageLi = this.getCurrentImage(),
+ caption = imageLi.find( '.gallerytext' );
+
+ // The order of the following is important for size calculations
+ // 1. Highlight current thumbnail
+ this.$gallery
+ .find( '.gallerybox.slideshow-current' )
+ .removeClass( 'slideshow-current' );
+ imageLi.addClass( 'slideshow-current' );
+
+ // 2. Show thumbnail
+ this.$thumbnail = imageLi.find( 'img' );
+ this.$img.attr( 'src', this.$thumbnail.attr( 'src' ) );
+ this.$img.attr( 'alt', this.$thumbnail.attr( 'alt' ) );
+ this.$imgLink.attr( 'href', imageLi.find( 'a' ).eq( 0 ).attr( 'href' ) );
+
+ // 3. Copy caption
+ this.$imgCaption
+ .empty()
+ .append( caption.clone() );
+
+ // 4. Stretch thumbnail to correct size
+ this.setImageSize();
+
+ // 5. Load image at the required size
+ this.loadImage( this.$thumbnail ).done( function ( info, $img ) {
+ // Show this image to the user only if its still the current one
+ if ( this.$thumbnail.attr( 'src' ) === $img.attr( 'src' ) ) {
+ this.$img.attr( 'src', info.thumburl );
+ this.setImageSize();
+
+ // Keep the next image ready
+ this.loadImage( this.getNextImage().find( 'img' ) );
+ }
+ }.bind( this ) );
+ };
+
+ /**
+ * Loads the full image given the `<img>` element of the thumbnail.
+ *
+ * @param {Object} $img
+ * @return {jQuery.Promise} Resolves with the images URL and original
+ * element once the image has loaded.
+ */
+ mw.GallerySlideshow.prototype.loadImage = function ( $img ) {
+ var img, d = $.Deferred();
+
+ this.getImageInfo( $img ).done( function ( info ) {
+ img = new Image();
+ img.src = info.thumburl;
+ img.onload = function () {
+ d.resolve( info, $img );
+ };
+ img.onerror = function () {
+ d.reject();
+ };
+ } ).fail( function () {
+ d.reject();
+ } );
+
+ return d.promise();
+ };
+
+ /**
+ * Gets the image's info given an `<img>` element.
+ *
+ * @param {Object} $img
+ * @return {jQuery.Promise} Resolves with the image's info.
+ */
+ mw.GallerySlideshow.prototype.getImageInfo = function ( $img ) {
+ var api, title, params,
+ imageSrc = $img.attr( 'src' );
+
+ // Reject promise if there is no thumbnail image
+ if ( $img[ 0 ] === undefined ) {
+ return $.Deferred().reject();
+ }
+
+ if ( this.imageInfoCache[ imageSrc ] === undefined ) {
+ api = new mw.Api();
+ // TODO: This supports only gallery of images
+ title = mw.Title.newFromImg( $img );
+ params = {
+ action: 'query',
+ formatversion: 2,
+ titles: title.toString(),
+ prop: 'imageinfo',
+ iiprop: 'url'
+ };
+
+ // Check which dimension we need to request, based on
+ // image and container proportions.
+ if ( this.getDimensionToRequest( $img ) === 'height' ) {
+ params.iiurlheight = this.imageHeight;
+ } else {
+ params.iiurlwidth = this.imageWidth;
+ }
+
+ this.imageInfoCache[ imageSrc ] = api.get( params ).then( function ( data ) {
+ if ( OO.getProp( data, 'query', 'pages', 0, 'imageinfo', 0, 'thumburl' ) !== undefined ) {
+ return data.query.pages[ 0 ].imageinfo[ 0 ];
+ } else {
+ return $.Deferred().reject();
+ }
+ } );
+ }
+
+ return this.imageInfoCache[ imageSrc ];
+ };
+
+ /**
+ * Given an image, the method checks whether to use the height
+ * or the width to request the larger image.
+ *
+ * @param {jQuery} $img
+ * @return {string}
+ */
+ mw.GallerySlideshow.prototype.getDimensionToRequest = function ( $img ) {
+ var ratio = $img.width() / $img.height();
+
+ if ( this.imageHeight * ratio <= this.imageWidth ) {
+ return 'height';
+ } else {
+ return 'width';
+ }
+ };
+
+ /**
+ * Toggles visibility of the thumbnails.
+ *
+ * @param {boolean} show Optional argument to control the state
+ */
+ mw.GallerySlideshow.prototype.toggleThumbnails = function ( show ) {
+ this.$galleryBox.toggle( show );
+ this.$carousel.toggleClass( 'mw-gallery-slideshow-thumbnails-toggled', show );
+ };
+
+ /**
+ * Getter method for {@link #$currentImage}
+ *
+ * @return {jQuery}
+ */
+ mw.GallerySlideshow.prototype.getCurrentImage = function () {
+ this.$currentImage = this.$currentImage || this.$galleryBox.eq( 0 );
+ return this.$currentImage;
+ };
+
+ /**
+ * Gets the image after the current one. Returns the first image if
+ * the current one is the last.
+ *
+ * @return {jQuery}
+ */
+ mw.GallerySlideshow.prototype.getNextImage = function () {
+ // Not the last image in the gallery
+ if ( this.$currentImage.next( '.gallerybox' )[ 0 ] !== undefined ) {
+ return this.$currentImage.next( '.gallerybox' );
+ } else {
+ return this.$galleryBox.eq( 0 );
+ }
+ };
+
+ /**
+ * Gets the image before the current one. Returns the last image if
+ * the current one is the first.
+ *
+ * @return {jQuery}
+ */
+ mw.GallerySlideshow.prototype.getPrevImage = function () {
+ // Not the first image in the gallery
+ if ( this.$currentImage.prev( '.gallerybox' )[ 0 ] !== undefined ) {
+ return this.$currentImage.prev( '.gallerybox' );
+ } else {
+ return this.$galleryBox.last();
+ }
+ };
+
+ /**
+ * Sets the {@link #$currentImage} to the next one and shows
+ * it in the carousel
+ */
+ mw.GallerySlideshow.prototype.nextImage = function () {
+ this.$currentImage = this.getNextImage();
+ this.showCurrentImage();
+ };
+
+ /**
+ * Sets the {@link #$currentImage} to the previous one and shows
+ * it in the carousel
+ */
+ mw.GallerySlideshow.prototype.prevImage = function () {
+ this.$currentImage = this.getPrevImage();
+ this.showCurrentImage();
+ };
+
+ // Bootstrap all slideshow galleries
+ mw.hook( 'wikipage.content' ).add( function ( $content ) {
+ $content.find( '.mw-gallery-slideshow' ).each( function () {
+ // eslint-disable-next-line no-new
+ new mw.GallerySlideshow( this );
+ } );
+ } );
+}( mediaWiki, jQuery, OO ) );
diff --git a/www/wiki/resources/src/mediawiki/page/gallery.css b/www/wiki/resources/src/mediawiki/page/gallery.css
new file mode 100644
index 00000000..6a331b6c
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/page/gallery.css
@@ -0,0 +1,188 @@
+/* Galleries */
+/* These display attributes look nonsensical, but are needed to support IE and FF2 */
+/* Don't forget to update gallery.print.css */
+li.gallerybox {
+ vertical-align: top;
+ display: -moz-inline-box;
+ display: inline-block;
+}
+
+ul.gallery,
+li.gallerybox {
+ zoom: 1;
+ *display: inline;
+}
+
+ul.gallery {
+ margin: 2px;
+ padding: 2px;
+ display: block;
+}
+
+li.gallerycaption {
+ font-weight: bold;
+ text-align: center;
+ display: block;
+ word-wrap: break-word;
+}
+
+li.gallerybox div.thumb {
+ text-align: center;
+ margin: 2px;
+}
+
+li.gallerybox div.thumb img {
+ display: block;
+ margin: 0 auto;
+}
+
+div.gallerytext {
+ overflow: hidden;
+ font-size: 94%;
+ padding: 2px 4px;
+ word-wrap: break-word;
+}
+
+.galleryfilename {
+ display: block;
+}
+
+.galleryfilename-truncate {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+/* new gallery stuff */
+ul.mw-gallery-nolines li.gallerybox div.thumb {
+ background-color: transparent;
+ border: 0;
+}
+
+ul.mw-gallery-nolines li.gallerybox div.gallerytext {
+ text-align: center;
+}
+
+/* height constrained gallery */
+
+ul.mw-gallery-packed li.gallerybox div.thumb,
+ul.mw-gallery-packed-overlay li.gallerybox div.thumb,
+ul.mw-gallery-packed-hover li.gallerybox div.thumb {
+ background-color: transparent;
+ border: 0;
+}
+
+ul.mw-gallery-packed li.gallerybox div.thumb img,
+ul.mw-gallery-packed-overlay li.gallerybox div.thumb img,
+ul.mw-gallery-packed-hover li.gallerybox div.thumb img {
+ margin: 0 auto;
+}
+
+ul.mw-gallery-packed-hover li.gallerybox,
+ul.mw-gallery-packed-overlay li.gallerybox {
+ position: relative;
+}
+
+ul.mw-gallery-packed-hover div.gallerytextwrapper {
+ overflow: hidden;
+ height: 0;
+}
+
+ul.mw-gallery-packed-hover li.gallerybox:hover div.gallerytextwrapper,
+ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper,
+ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper {
+ position: absolute;
+ background: #fff;
+ background: rgba( 255, 255, 255, 0.8 );
+ padding: 5px 10px;
+ bottom: 0;
+ left: 0; /* Needed for IE */
+ height: auto;
+ max-height: 40%;
+ overflow: hidden;
+ font-weight: bold;
+ margin: 2px; /* correspond to style on div.thumb */
+}
+
+ul.mw-gallery-packed-hover li.gallerybox:hover div.gallerytextwrapper p,
+ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper p,
+ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper p {
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ overflow: hidden;
+}
+
+ul.mw-gallery-packed-hover li.gallerybox div.gallerytextwrapper:hover,
+ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper:hover,
+ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper:hover {
+ overflow: visible;
+ max-height: none;
+}
+
+ul.mw-gallery-packed-hover li.gallerybox div.gallerytextwrapper:hover p,
+ul.mw-gallery-packed-overlay li.gallerybox div.gallerytextwrapper:hover p,
+ul.mw-gallery-packed-hover li.gallerybox.mw-gallery-focused div.gallerytextwrapper:hover p {
+ text-overflow: clip;
+ white-space: normal;
+ overflow: visible;
+}
+
+ul.mw-gallery-packed-hover,
+ul.mw-gallery-packed-overlay,
+ul.mw-gallery-packed {
+ text-align: center;
+}
+
+/* Slideshow */
+ul.gallery.mw-gallery-slideshow {
+ display: block;
+ margin: 4em 0;
+}
+
+ul.gallery.mw-gallery-slideshow .gallerycaption {
+ font-size: 1.3em;
+ margin: 0;
+}
+
+ul.gallery.mw-gallery-slideshow .gallerycarousel.mw-gallery-slideshow-thumbnails-toggled {
+ margin-bottom: 1.3em;
+}
+
+ul.gallery.mw-gallery-slideshow .mw-gallery-slideshow-buttons {
+ opacity: 0.5;
+ padding: 1.3em 0;
+}
+
+ul.gallery.mw-gallery-slideshow .mw-gallery-slideshow-buttons .oo-ui-buttonElement {
+ margin: 0 2em;
+}
+
+.mw-gallery-slideshow li.gallerybox.slideshow-current {
+ background: #efefef;
+}
+
+.mw-gallery-slideshow .gallerybox > div {
+ max-width: 120px;
+}
+
+ul.mw-gallery-slideshow li.gallerybox div.thumb {
+ border: 0;
+ background: transparent;
+}
+
+ul.mw-gallery-slideshow li.gallerycarousel {
+ display: block;
+ text-align: center;
+}
+
+.mw-gallery-slideshow-img-container a {
+ display: block;
+}
+
+@media screen {
+ /* Background and border colors are defined separately for print mode */
+ li.gallerybox div.thumb {
+ border: 1px solid #c8ccd1;
+ background-color: #f8f9fa;
+ }
+}
diff --git a/www/wiki/resources/src/mediawiki/page/gallery.js b/www/wiki/resources/src/mediawiki/page/gallery.js
new file mode 100644
index 00000000..79937e57
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/page/gallery.js
@@ -0,0 +1,268 @@
+/*!
+ * Show gallery captions when focused. Copied directly from jquery.mw-jump.js.
+ * Also Dynamically resize images to justify them.
+ */
+( function ( mw, $ ) {
+ var $galleries,
+ bound = false,
+ // Is there a better way to detect a touchscreen? Current check taken from stack overflow.
+ isTouchScreen = !!( window.ontouchstart !== undefined ||
+ window.DocumentTouch !== undefined && document instanceof window.DocumentTouch
+ );
+
+ /**
+ * Perform the layout justification.
+ *
+ * @ignore
+ * @context {HTMLElement} A `ul.mw-gallery-*` element
+ */
+ function justify() {
+ var lastTop,
+ $img,
+ imgWidth,
+ imgHeight,
+ captionWidth,
+ rows = [],
+ $gallery = $( this );
+
+ $gallery.children( 'li.gallerybox' ).each( function () {
+ // Math.floor to be paranoid if things are off by 0.00000000001
+ var top = Math.floor( $( this ).position().top ),
+ $this = $( this );
+
+ if ( top !== lastTop ) {
+ rows[ rows.length ] = [];
+ lastTop = top;
+ }
+
+ $img = $this.find( 'div.thumb a.image img' );
+ if ( $img.length && $img[ 0 ].height ) {
+ imgHeight = $img[ 0 ].height;
+ imgWidth = $img[ 0 ].width;
+ } else {
+ // If we don't have a real image, get the containing divs width/height.
+ // Note that if we do have a real image, using this method will generally
+ // give the same answer, but can be different in the case of a very
+ // narrow image where extra padding is added.
+ imgHeight = $this.children().children( 'div:first' ).height();
+ imgWidth = $this.children().children( 'div:first' ).width();
+ }
+
+ // Hack to make an edge case work ok
+ if ( imgHeight < 30 ) {
+ // Don't try and resize this item.
+ imgHeight = 0;
+ }
+
+ captionWidth = $this.children().children( 'div.gallerytextwrapper' ).width();
+ rows[ rows.length - 1 ][ rows[ rows.length - 1 ].length ] = {
+ $elm: $this,
+ width: $this.outerWidth(),
+ imgWidth: imgWidth,
+ // XXX: can divide by 0 ever happen?
+ aspect: imgWidth / imgHeight,
+ captionWidth: captionWidth,
+ height: imgHeight
+ };
+
+ // Save all boundaries so we can restore them on window resize
+ $this.data( 'imgWidth', imgWidth );
+ $this.data( 'imgHeight', imgHeight );
+ $this.data( 'width', $this.outerWidth() );
+ $this.data( 'captionWidth', captionWidth );
+ } );
+
+ ( function () {
+ var maxWidth,
+ combinedAspect,
+ combinedPadding,
+ curRow,
+ curRowHeight,
+ wantedWidth,
+ preferredHeight,
+ newWidth,
+ padding,
+ $outerDiv,
+ $innerDiv,
+ $imageDiv,
+ $imageElm,
+ imageElm,
+ $caption,
+ i,
+ j,
+ avgZoom,
+ totalZoom = 0;
+
+ for ( i = 0; i < rows.length; i++ ) {
+ maxWidth = $gallery.width();
+ combinedAspect = 0;
+ combinedPadding = 0;
+ curRow = rows[ i ];
+ curRowHeight = 0;
+
+ for ( j = 0; j < curRow.length; j++ ) {
+ if ( curRowHeight === 0 ) {
+ if ( isFinite( curRow[ j ].height ) ) {
+ // Get the height of this row, by taking the first
+ // non-out of bounds height
+ curRowHeight = curRow[ j ].height;
+ }
+ }
+
+ if ( curRow[ j ].aspect === 0 || !isFinite( curRow[ j ].aspect ) ) {
+ // One of the dimensions are 0. Probably should
+ // not try to resize.
+ combinedPadding += curRow[ j ].width;
+ } else {
+ combinedAspect += curRow[ j ].aspect;
+ combinedPadding += curRow[ j ].width - curRow[ j ].imgWidth;
+ }
+ }
+
+ // Add some padding for inter-element spacing.
+ combinedPadding += 5 * curRow.length;
+ wantedWidth = maxWidth - combinedPadding;
+ preferredHeight = wantedWidth / combinedAspect;
+
+ if ( preferredHeight > curRowHeight * 1.5 ) {
+ // Only expand at most 1.5 times current size
+ // As that's as high a resolution as we have.
+ // Also on the off chance there is a bug in this
+ // code, would prevent accidentally expanding to
+ // be 10 billion pixels wide.
+ if ( i === rows.length - 1 ) {
+ // If its the last row, and we can't fit it,
+ // don't make the entire row huge.
+ avgZoom = ( totalZoom / ( rows.length - 1 ) ) * curRowHeight;
+ if ( isFinite( avgZoom ) && avgZoom >= 1 && avgZoom <= 1.5 ) {
+ preferredHeight = avgZoom;
+ } else {
+ // Probably a single row gallery
+ preferredHeight = curRowHeight;
+ }
+ } else {
+ preferredHeight = 1.5 * curRowHeight;
+ }
+ }
+ if ( !isFinite( preferredHeight ) ) {
+ // This *definitely* should not happen.
+ // Skip this row.
+ continue;
+ }
+ if ( preferredHeight < 5 ) {
+ // Well something clearly went wrong...
+ // Skip this row.
+ continue;
+ }
+
+ if ( preferredHeight / curRowHeight > 1 ) {
+ totalZoom += preferredHeight / curRowHeight;
+ } else {
+ // If we shrink, still consider that a zoom of 1
+ totalZoom += 1;
+ }
+
+ for ( j = 0; j < curRow.length; j++ ) {
+ newWidth = preferredHeight * curRow[ j ].aspect;
+ padding = curRow[ j ].width - curRow[ j ].imgWidth;
+ $outerDiv = curRow[ j ].$elm;
+ $innerDiv = $outerDiv.children( 'div' ).first();
+ $imageDiv = $innerDiv.children( 'div.thumb' );
+ $imageElm = $imageDiv.find( 'img' ).first();
+ imageElm = $imageElm.length ? $imageElm[ 0 ] : null;
+ $caption = $outerDiv.find( 'div.gallerytextwrapper' );
+
+ // Since we are going to re-adjust the height, the vertical
+ // centering margins need to be reset.
+ $imageDiv.children( 'div' ).css( 'margin', '0px auto' );
+
+ if ( newWidth < 60 || !isFinite( newWidth ) ) {
+ // Making something skinnier than this will mess up captions,
+ if ( newWidth < 1 || !isFinite( newWidth ) ) {
+ $innerDiv.height( preferredHeight );
+ // Don't even try and touch the image size if it could mean
+ // making it disappear.
+ continue;
+ }
+ } else {
+ $outerDiv.width( newWidth + padding );
+ $innerDiv.width( newWidth + padding );
+ $imageDiv.width( newWidth );
+ $caption.width( curRow[ j ].captionWidth + ( newWidth - curRow[ j ].imgWidth ) );
+ }
+
+ if ( imageElm ) {
+ // We don't always have an img, e.g. in the case of an invalid file.
+ imageElm.width = newWidth;
+ imageElm.height = preferredHeight;
+ } else {
+ // Not a file box.
+ $imageDiv.height( preferredHeight );
+ }
+ }
+ }
+ }() );
+ }
+
+ function handleResizeStart() {
+ $galleries.children( 'li.gallerybox' ).each( function () {
+ var imgWidth = $( this ).data( 'imgWidth' ),
+ imgHeight = $( this ).data( 'imgHeight' ),
+ width = $( this ).data( 'width' ),
+ captionWidth = $( this ).data( 'captionWidth' ),
+ $innerDiv = $( this ).children( 'div' ).first(),
+ $imageDiv = $innerDiv.children( 'div.thumb' ),
+ $imageElm, imageElm;
+
+ // Restore original sizes so we can arrange the elements as on freshly loaded page
+ $( this ).width( width );
+ $innerDiv.width( width );
+ $imageDiv.width( imgWidth );
+ $( this ).find( 'div.gallerytextwrapper' ).width( captionWidth );
+
+ $imageElm = $( this ).find( 'img' ).first();
+ imageElm = $imageElm.length ? $imageElm[ 0 ] : null;
+ if ( imageElm ) {
+ imageElm.width = imgWidth;
+ imageElm.height = imgHeight;
+ } else {
+ $imageDiv.height( imgHeight );
+ }
+ } );
+ }
+
+ function handleResizeEnd() {
+ $galleries.each( justify );
+ }
+
+ mw.hook( 'wikipage.content' ).add( function ( $content ) {
+ if ( isTouchScreen ) {
+ // Always show the caption for a touch screen.
+ $content.find( 'ul.mw-gallery-packed-hover' )
+ .addClass( 'mw-gallery-packed-overlay' )
+ .removeClass( 'mw-gallery-packed-hover' );
+ } else {
+ // Note use of just "a", not a.image, since we want this to trigger if a link in
+ // the caption receives focus
+ $content.find( 'ul.mw-gallery-packed-hover li.gallerybox' ).on( 'focus blur', 'a', function ( e ) {
+ // Confusingly jQuery leaves e.type as focusout for delegated blur events
+ var gettingFocus = e.type !== 'blur' && e.type !== 'focusout';
+ $( this ).closest( 'li.gallerybox' ).toggleClass( 'mw-gallery-focused', gettingFocus );
+ } );
+ }
+
+ $galleries = $content.find( 'ul.mw-gallery-packed-overlay, ul.mw-gallery-packed-hover, ul.mw-gallery-packed' );
+ // Call the justification asynchronous because live preview fires the hook with detached $content.
+ setTimeout( function () {
+ $galleries.each( justify );
+
+ // Bind here instead of in the top scope as the callbacks use $galleries.
+ if ( !bound ) {
+ bound = true;
+ $( window )
+ .resize( $.debounce( 300, true, handleResizeStart ) )
+ .resize( $.debounce( 300, handleResizeEnd ) );
+ }
+ } );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/page/gallery.print.css b/www/wiki/resources/src/mediawiki/page/gallery.print.css
new file mode 100644
index 00000000..2ae670b8
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/page/gallery.print.css
@@ -0,0 +1,35 @@
+li.gallerybox {
+ vertical-align: top;
+ display: inline-block;
+}
+
+ul.gallery,
+li.gallerybox {
+ zoom: 1;
+ *display: inline;
+}
+
+ul.gallery {
+ margin: 2px;
+ padding: 2px;
+ display: block;
+}
+
+li.gallerycaption {
+ font-weight: bold;
+ text-align: center;
+ display: block;
+ word-wrap: break-word;
+}
+
+li.gallerybox div.thumb {
+ background-color: #fff;
+ border: 1px solid #ccc;
+}
+
+div.gallerytext {
+ overflow: hidden;
+ font-size: 10pt;
+ padding: 2px 4px;
+ word-wrap: break-word;
+}
diff --git a/www/wiki/resources/src/mediawiki/page/image-pagination.js b/www/wiki/resources/src/mediawiki/page/image-pagination.js
new file mode 100644
index 00000000..6a7d0b92
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/page/image-pagination.js
@@ -0,0 +1,143 @@
+/*!
+ * Implement AJAX navigation for multi-page images so the user may browse without a full page reload.
+ */
+
+/* eslint-disable no-use-before-define */
+
+( function ( mw, $ ) {
+ var jqXhr, $multipageimage, $spinner,
+ cache = {},
+ cacheOrder = [];
+
+ /* Fetch the next page, caching up to 10 last-loaded pages.
+ * @param {string} url
+ * @return {jQuery.Promise}
+ */
+ function fetchPageData( url ) {
+ if ( jqXhr && jqXhr.abort ) {
+ // Prevent race conditions and piling up pending requests
+ jqXhr.abort();
+ }
+ jqXhr = undefined;
+
+ // Try the cache
+ if ( cache[ url ] ) {
+ // Update access freshness
+ cacheOrder.splice( $.inArray( url, cacheOrder ), 1 );
+ cacheOrder.push( url );
+ return $.Deferred().resolve( cache[ url ] ).promise();
+ }
+
+ // TODO Don't fetch the entire page. Ideally we'd only fetch the content portion or the data
+ // (thumbnail urls) and update the interface manually.
+ jqXhr = $.ajax( url ).then( function ( data ) {
+ return $( data ).find( 'table.multipageimage' ).contents();
+ } );
+
+ // Handle cache updates
+ jqXhr.done( function ( $contents ) {
+ jqXhr = undefined;
+
+ // Cache the newly loaded page
+ cache[ url ] = $contents;
+ cacheOrder.push( url );
+
+ // Remove the oldest entry if we're over the limit
+ if ( cacheOrder.length > 10 ) {
+ delete cache[ cacheOrder[ 0 ] ];
+ cacheOrder = cacheOrder.slice( 1 );
+ }
+ } );
+
+ return jqXhr.promise();
+ }
+
+ /* Fetch the next page and use jQuery to swap the table.multipageimage contents.
+ * @param {string} url
+ * @param {boolean} [hist=false] Whether this is a load triggered by history navigation (if
+ * true, this function won't push a new history state, for the browser did so already).
+ */
+ function switchPage( url, hist ) {
+ var $tr, promise;
+
+ // Start fetching data (might be cached)
+ promise = fetchPageData( url );
+
+ // Add a new spinner if one doesn't already exist and the data is not already ready
+ if ( !$spinner && promise.state() !== 'resolved' ) {
+ $tr = $multipageimage.find( 'tr' );
+ $spinner = $.createSpinner( {
+ size: 'large',
+ type: 'block'
+ } )
+ // Copy the old content dimensions equal so that the current scroll position is not
+ // lost between emptying the table is and receiving the new contents.
+ .css( {
+ height: $tr.outerHeight(),
+ width: $tr.outerWidth()
+ } );
+
+ $multipageimage.empty().append( $spinner );
+ }
+
+ promise.done( function ( $contents ) {
+ $spinner = undefined;
+
+ // Replace table contents
+ $multipageimage.empty().append( $contents.clone() );
+
+ bindPageNavigation( $multipageimage );
+
+ // Fire hook because the page's content has changed
+ mw.hook( 'wikipage.content' ).fire( $multipageimage );
+
+ // Update browser history and address bar. But not if we came here from a history
+ // event, in which case the url is already updated by the browser.
+ if ( history.pushState && !hist ) {
+ history.pushState( { tag: 'mw-pagination' }, document.title, url );
+ }
+ } );
+ }
+
+ function bindPageNavigation( $container ) {
+ $container.find( '.multipageimagenavbox' ).one( 'click', 'a', function ( e ) {
+ var page, url;
+
+ // Generate the same URL on client side as the one generated in ImagePage::openShowImage.
+ // We avoid using the URL in the link directly since it could have been manipulated (T68608)
+ page = Number( mw.util.getParamValue( 'page', this.href ) );
+ url = mw.util.getUrl( mw.config.get( 'wgPageName' ), { page: page } );
+
+ switchPage( url );
+ e.preventDefault();
+ } );
+
+ $container.find( 'form[name="pageselector"]' ).one( 'change submit', function ( e ) {
+ switchPage( this.action + '?' + $( this ).serialize() );
+ e.preventDefault();
+ } );
+ }
+
+ $( function () {
+ if ( mw.config.get( 'wgCanonicalNamespace' ) !== 'File' ) {
+ return;
+ }
+ $multipageimage = $( 'table.multipageimage' );
+ if ( !$multipageimage.length ) {
+ return;
+ }
+
+ bindPageNavigation( $multipageimage );
+
+ // Update the url using the History API (if available)
+ if ( history.pushState && history.replaceState ) {
+ history.replaceState( { tag: 'mw-pagination' }, '' );
+ $( window ).on( 'popstate', function ( e ) {
+ var state = e.originalEvent.state;
+ if ( state && state.tag === 'mw-pagination' ) {
+ switchPage( location.href, true );
+ }
+ } );
+ }
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/page/patrol.ajax.js b/www/wiki/resources/src/mediawiki/page/patrol.ajax.js
new file mode 100644
index 00000000..d8fb249d
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/page/patrol.ajax.js
@@ -0,0 +1,64 @@
+/*!
+ * Animate patrol links to use asynchronous API requests to
+ * patrol pages, rather than navigating to a different URI.
+ *
+ * @since 1.21
+ * @author Marius Hoch <hoo@online.de>
+ */
+( function ( mw, $ ) {
+ if ( !mw.user.tokens.exists( 'patrolToken' ) ) {
+ // Current user has no patrol right, or an old cached version of user.tokens
+ // that didn't have patrolToken yet.
+ return;
+ }
+ $( function () {
+ var $patrolLinks = $( '.patrollink[data-mw="interface"] a' );
+ $patrolLinks.on( 'click', function ( e ) {
+ var $spinner, rcid, apiRequest;
+
+ // Preload the notification module for mw.notify
+ mw.loader.load( 'mediawiki.notification' );
+
+ // Hide the link and create a spinner to show it inside the brackets.
+ $spinner = $.createSpinner( {
+ size: 'small',
+ type: 'inline'
+ } );
+ $( this ).hide().after( $spinner );
+
+ rcid = mw.util.getParamValue( 'rcid', this.href );
+ apiRequest = new mw.Api();
+
+ apiRequest.postWithToken( 'patrol', {
+ formatversion: 2,
+ action: 'patrol',
+ rcid: rcid
+ } ).done( function ( data ) {
+ var title;
+ // Remove all patrollinks from the page (including any spinners inside).
+ $patrolLinks.closest( '.patrollink' ).remove();
+ if ( data.patrol !== undefined ) {
+ // Success
+ title = new mw.Title( data.patrol.title );
+ mw.notify( mw.msg( 'markedaspatrollednotify', title.toText() ) );
+ } else {
+ // This should never happen as errors should trigger fail
+ mw.notify( mw.msg( 'markedaspatrollederrornotify' ), { type: 'error' } );
+ }
+ } ).fail( function ( error ) {
+ $spinner.remove();
+ // Restore the patrol link. This allows the user to try again
+ // (or open it in a new window, bypassing this ajax module).
+ $patrolLinks.show();
+ if ( error === 'noautopatrol' ) {
+ // Can't patrol own
+ mw.notify( mw.msg( 'markedaspatrollederror-noautopatrol' ), { type: 'warn' } );
+ } else {
+ mw.notify( mw.msg( 'markedaspatrollederrornotify' ), { type: 'error' } );
+ }
+ } );
+
+ e.preventDefault();
+ } );
+ } );
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/page/ready.js b/www/wiki/resources/src/mediawiki/page/ready.js
new file mode 100644
index 00000000..e1476641
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/page/ready.js
@@ -0,0 +1,58 @@
+( function ( mw, $ ) {
+ mw.hook( 'wikipage.content' ).add( function ( $content ) {
+ var $sortable, $collapsible;
+
+ $collapsible = $content.find( '.mw-collapsible' );
+ if ( $collapsible.length ) {
+ // Preloaded by Skin::getDefaultModules()
+ mw.loader.using( 'jquery.makeCollapsible', function () {
+ $collapsible.makeCollapsible();
+ } );
+ }
+
+ $sortable = $content.find( 'table.sortable' );
+ if ( $sortable.length ) {
+ // Preloaded by Skin::getDefaultModules()
+ mw.loader.using( 'jquery.tablesorter', function () {
+ $sortable.tablesorter();
+ } );
+ }
+
+ // Run jquery.checkboxShiftClick
+ $content.find( 'input[type="checkbox"]:not(.noshiftselect)' ).checkboxShiftClick();
+ } );
+
+ // Things outside the wikipage content
+ $( function () {
+ var $nodes;
+
+ // Add accesskey hints to the tooltips
+ $( '[accesskey]' ).updateTooltipAccessKeys();
+
+ $nodes = $( '.catlinks[data-mw="interface"]' );
+ if ( $nodes.length ) {
+ /**
+ * Fired when categories are being added to the DOM
+ *
+ * It is encouraged to fire it before the main DOM is changed (when $content
+ * is still detached). However, this order is not defined either way, so you
+ * should only rely on $content itself.
+ *
+ * This includes the ready event on a page load (including post-edit loads)
+ * and when content has been previewed with LivePreview.
+ *
+ * @event wikipage_categories
+ * @member mw.hook
+ * @param {jQuery} $content The most appropriate element containing the content,
+ * such as .catlinks
+ */
+ mw.hook( 'wikipage.categories' ).fire( $nodes );
+ }
+
+ $( '#t-print a' ).click( function ( e ) {
+ window.print();
+ e.preventDefault();
+ } );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/page/rollback.js b/www/wiki/resources/src/mediawiki/page/rollback.js
new file mode 100644
index 00000000..6db518db
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/page/rollback.js
@@ -0,0 +1,67 @@
+/*!
+ * Enhance rollback links by using asynchronous API requests,
+ * rather than navigating to an action page.
+ *
+ * @since 1.28
+ * @author Timo Tijhof
+ */
+( function ( mw, $ ) {
+
+ $( function () {
+ $( '.mw-rollback-link' ).on( 'click', 'a[data-mw="interface"]', function ( e ) {
+ var api, $spinner,
+ $link = $( this ),
+ url = this.href,
+ page = mw.util.getParamValue( 'title', url ),
+ user = mw.util.getParamValue( 'from', url );
+
+ if ( !page || user === null ) {
+ // Let native browsing handle the link
+ return true;
+ }
+
+ // Preload the notification module for mw.notify
+ mw.loader.load( 'mediawiki.notification' );
+
+ // Remove event handler so that next click (re-try) uses server action
+ $( e.delegateTarget ).off( 'click' );
+
+ // Hide the link and create a spinner to show it inside the brackets.
+ $spinner = $.createSpinner( { size: 'small', type: 'inline' } );
+ $link.hide().after( $spinner );
+
+ // @todo: data.messageHtml is no more. Convert to using errorformat=html.
+ api = new mw.Api();
+ api.rollback( page, user )
+ .then( function ( data ) {
+ mw.notify( $.parseHTML( data.messageHtml ), {
+ title: mw.msg( 'actioncomplete' )
+ } );
+
+ // Remove link container and the subsequent text node containing " | ".
+ if ( e.delegateTarget.nextSibling && e.delegateTarget.nextSibling.nodeType === Node.TEXT_NODE ) {
+ $( e.delegateTarget.nextSibling ).remove();
+ }
+ $( e.delegateTarget ).remove();
+ }, function ( errorCode, data ) {
+ var message = data && data.error && data.error.messageHtml ?
+ $.parseHTML( data.error.messageHtml ) :
+ mw.msg( 'rollbackfailed' ),
+ type = errorCode === 'alreadyrolled' ? 'warn' : 'error';
+
+ mw.notify( message, {
+ type: type,
+ title: mw.msg( 'rollbackfailed' ),
+ autoHide: false
+ } );
+
+ // Restore the link (enables user to try again)
+ $spinner.remove();
+ $link.show();
+ } );
+
+ e.preventDefault();
+ } );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/page/startup.js b/www/wiki/resources/src/mediawiki/page/startup.js
new file mode 100644
index 00000000..75140445
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/page/startup.js
@@ -0,0 +1,49 @@
+( function ( mw, $ ) {
+ // Break out of framesets
+ if ( mw.config.get( 'wgBreakFrames' ) ) {
+ // Note: In IE < 9 strict comparison to window is non-standard (the standard didn't exist yet)
+ // it works only comparing to window.self or window.window (http://stackoverflow.com/q/4850978/319266)
+ if ( window.top !== window.self ) {
+ // Un-trap us from framesets
+ window.top.location.href = location.href;
+ }
+ }
+
+ $( function () {
+ var $diff;
+
+ /**
+ * Fired when wiki content is being added to the DOM
+ *
+ * It is encouraged to fire it before the main DOM is changed (when $content
+ * is still detached). However, this order is not defined either way, so you
+ * should only rely on $content itself.
+ *
+ * This includes the ready event on a page load (including post-edit loads)
+ * and when content has been previewed with LivePreview.
+ *
+ * @event wikipage_content
+ * @member mw.hook
+ * @param {jQuery} $content The most appropriate element containing the content,
+ * such as #mw-content-text (regular content root) or #wikiPreview (live preview
+ * root)
+ */
+ mw.hook( 'wikipage.content' ).fire( $( '#mw-content-text' ) );
+
+ $diff = $( 'table.diff[data-mw="interface"]' );
+ if ( $diff.length ) {
+ /**
+ * Fired when the diff is added to a page containing a diff
+ *
+ * Similar to the {@link mw.hook#event-wikipage_content wikipage.content hook}
+ * $diff may still be detached when the hook is fired.
+ *
+ * @event wikipage_diff
+ * @member mw.hook
+ * @param {jQuery} $diff The root element of the MediaWiki diff (`table.diff`).
+ */
+ mw.hook( 'wikipage.diff' ).fire( $diff.eq( 0 ) );
+ }
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/mediawiki/page/watch.js b/www/wiki/resources/src/mediawiki/page/watch.js
new file mode 100644
index 00000000..e56e8078
--- /dev/null
+++ b/www/wiki/resources/src/mediawiki/page/watch.js
@@ -0,0 +1,192 @@
+/**
+ * Animate watch/unwatch links to use asynchronous API requests to
+ * watch pages, rather than navigating to a different URI.
+ *
+ * @class mw.page.watch.ajax
+ */
+( function ( mw, $ ) {
+ var watch,
+ // The name of the page to watch or unwatch
+ title = mw.config.get( 'wgRelevantPageName' );
+
+ /**
+ * Update the link text, link href attribute and (if applicable)
+ * "loading" class.
+ *
+ * @param {jQuery} $link Anchor tag of (un)watch link
+ * @param {string} action One of 'watch', 'unwatch'
+ * @param {string} [state="idle"] 'idle' or 'loading'. Default is 'idle'
+ */
+ function updateWatchLink( $link, action, state ) {
+ var msgKey, $li, otherAction;
+
+ // A valid but empty jQuery object shouldn't throw a TypeError
+ if ( !$link.length ) {
+ return;
+ }
+
+ // Invalid actions shouldn't silently turn the page in an unrecoverable state
+ if ( action !== 'watch' && action !== 'unwatch' ) {
+ throw new Error( 'Invalid action' );
+ }
+
+ // message keys 'watch', 'watching', 'unwatch' or 'unwatching'.
+ msgKey = state === 'loading' ? action + 'ing' : action;
+ otherAction = action === 'watch' ? 'unwatch' : 'watch';
+ $li = $link.closest( 'li' );
+
+ // Trigger a 'watchpage' event for this List item.
+ // Announce the otherAction value as the first param.
+ // Used to monitor the state of watch link.
+ // TODO: Revise when system wide hooks are implemented
+ if ( state === undefined ) {
+ $li.trigger( 'watchpage.mw', otherAction );
+ }
+
+ $link
+ .text( mw.msg( msgKey ) )
+ .attr( 'title', mw.msg( 'tooltip-ca-' + action ) )
+ .updateTooltipAccessKeys()
+ .attr( 'href', mw.util.getUrl( title, { action: action } ) );
+
+ // Most common ID style
+ if ( $li.prop( 'id' ) === 'ca-' + otherAction ) {
+ $li.prop( 'id', 'ca-' + action );
+ }
+
+ if ( state === 'loading' ) {
+ $link.addClass( 'loading' );
+ } else {
+ $link.removeClass( 'loading' );
+ }
+ }
+
+ /**
+ * TODO: This should be moved somewhere more accessible.
+ *
+ * @private
+ * @param {string} url
+ * @return {string} The extracted action, defaults to 'view'
+ */
+ function mwUriGetAction( url ) {
+ var action, actionPaths, key, i, m, parts;
+
+ // TODO: Does MediaWiki give action path or query param
+ // precedence? If the former, move this to the bottom
+ action = mw.util.getParamValue( 'action', url );
+ if ( action !== null ) {
+ return action;
+ }
+
+ actionPaths = mw.config.get( 'wgActionPaths' );
+ for ( key in actionPaths ) {
+ if ( actionPaths.hasOwnProperty( key ) ) {
+ parts = actionPaths[ key ].split( '$1' );
+ for ( i = 0; i < parts.length; i++ ) {
+ parts[ i ] = mw.RegExp.escape( parts[ i ] );
+ }
+ m = new RegExp( parts.join( '(.+)' ) ).exec( url );
+ if ( m && m[ 1 ] ) {
+ return key;
+ }
+
+ }
+ }
+
+ return 'view';
+ }
+
+ // Expose public methods
+ watch = {
+ updateWatchLink: updateWatchLink
+ };
+ module.exports = watch;
+
+ // Deprecated since 1.30
+ mw.log.deprecate( mw, 'page',
+ { watch: watch },
+ 'Use require( \'mediawiki.page.watch.ajax\' ) instead.',
+ 'mw.page'
+ );
+
+ $( function () {
+ var $links = $( '.mw-watchlink a[data-mw="interface"], a.mw-watchlink[data-mw="interface"]' );
+ if ( !$links.length ) {
+ // Fallback to the class-based exclusion method for backwards-compatibility
+ $links = $( '.mw-watchlink a, a.mw-watchlink' );
+ // Restrict to core interfaces, ignore user-generated content
+ $links = $links.filter( ':not( #bodyContent *, #content * )' );
+ }
+
+ $links.click( function ( e ) {
+ var mwTitle, action, api, $link;
+
+ mwTitle = mw.Title.newFromText( title );
+ action = mwUriGetAction( this.href );
+
+ if ( !mwTitle || ( action !== 'watch' && action !== 'unwatch' ) ) {
+ // Let native browsing handle the link
+ return true;
+ }
+ e.preventDefault();
+ e.stopPropagation();
+
+ $link = $( this );
+
+ if ( $link.hasClass( 'loading' ) ) {
+ return;
+ }
+
+ updateWatchLink( $link, action, 'loading' );
+
+ // Preload the notification module for mw.notify
+ mw.loader.load( 'mediawiki.notification' );
+
+ api = new mw.Api();
+
+ api[ action ]( title )
+ .done( function ( watchResponse ) {
+ var message, otherAction = action === 'watch' ? 'unwatch' : 'watch';
+
+ if ( mwTitle.getNamespaceId() > 0 && mwTitle.getNamespaceId() % 2 === 1 ) {
+ message = action === 'watch' ? 'addedwatchtext-talk' : 'removedwatchtext-talk';
+ } else {
+ message = action === 'watch' ? 'addedwatchtext' : 'removedwatchtext';
+ }
+
+ mw.notify( mw.message( message, mwTitle.getPrefixedText() ).parseDom(), {
+ tag: 'watch-self'
+ } );
+
+ // Set link to opposite
+ updateWatchLink( $link, otherAction );
+
+ // Update the "Watch this page" checkbox on action=edit when the
+ // page is watched or unwatched via the tab (T14395).
+ $( '#wpWatchthis' ).prop( 'checked', watchResponse.watched === true );
+ } )
+ .fail( function () {
+ var msg, link;
+
+ // Reset link to non-loading mode
+ updateWatchLink( $link, action );
+
+ // Format error message
+ link = mw.html.element(
+ 'a', {
+ href: mw.util.getUrl( title ),
+ title: mwTitle.getPrefixedText()
+ }, mwTitle.getPrefixedText()
+ );
+ msg = mw.message( 'watcherrortext', link );
+
+ // Report to user about the error
+ mw.notify( msg, {
+ tag: 'watch-self',
+ type: 'error'
+ } );
+ } );
+ } );
+ } );
+
+}( mediaWiki, jQuery ) );
diff --git a/www/wiki/resources/src/moment-dmy.js b/www/wiki/resources/src/moment-dmy.js
new file mode 100644
index 00000000..2b7ca161
--- /dev/null
+++ b/www/wiki/resources/src/moment-dmy.js
@@ -0,0 +1,16 @@
+// Use DMY date format for Moment.js, in accordance with MediaWiki's date formatting routines.
+// This affects English only (and languages without localisations, that fall back to English).
+// http://momentjs.com/docs/#/customization/long-date-formats/
+/* global moment */
+moment.updateLocale( 'en', {
+ longDateFormat: {
+ // Unchanged, but have to be repeated here:
+ LT: 'h:mm A',
+ LTS: 'h:mm:ss A',
+ // Customized:
+ L: 'DD/MM/YYYY',
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY LT',
+ LLLL: 'dddd, D MMMM YYYY LT'
+ }
+} );
diff --git a/www/wiki/resources/src/moment-global.js b/www/wiki/resources/src/moment-global.js
new file mode 100644
index 00000000..ba01a240
--- /dev/null
+++ b/www/wiki/resources/src/moment-global.js
@@ -0,0 +1,2 @@
+// Back-compat: Export module as global
+window.moment = module.exports;
diff --git a/www/wiki/resources/src/moment-locale-overrides.js b/www/wiki/resources/src/moment-locale-overrides.js
new file mode 100644
index 00000000..bafb86a2
--- /dev/null
+++ b/www/wiki/resources/src/moment-locale-overrides.js
@@ -0,0 +1,44 @@
+/* global mediaWiki, moment */
+
+( function ( mw ) {
+ // HACK: Overwrite moment's i18n with MediaWiki's for the current language so that
+ // wgTranslateNumerals is respected.
+ moment.updateLocale( moment.locale(), {
+ preparse: function ( s ) {
+ var i,
+ table = mw.language.getDigitTransformTable();
+ if ( mw.config.get( 'wgTranslateNumerals' ) ) {
+ for ( i = 0; i < 10; i++ ) {
+ if ( table[ i ] !== undefined ) {
+ s = s.replace( new RegExp( mw.RegExp.escape( table[ i ] ), 'g' ), i );
+ }
+ }
+ }
+ // HACK: momentjs replaces commas in some languages, which is the only other use of preparse
+ // aside from digit transformation. We can only override preparse, not extend it, so we
+ // have to replicate the comma replacement functionality here.
+ if ( [ 'ar', 'ar-sa', 'fa' ].indexOf( mw.config.get( 'wgUserLanguage' ) ) !== -1 ) {
+ s = s.replace( /،/g, ',' );
+ }
+ return s;
+ },
+ postformat: function ( s ) {
+ var i,
+ table = mw.language.getDigitTransformTable();
+ if ( mw.config.get( 'wgTranslateNumerals' ) ) {
+ for ( i = 0; i < 10; i++ ) {
+ if ( table[ i ] !== undefined ) {
+ s = s.replace( new RegExp( i, 'g' ), table[ i ] );
+ }
+ }
+ }
+ // HACK: momentjs replaces commas in some languages, which is the only other use of postformat
+ // aside from digit transformation. We can only override postformat, not extend it, so we
+ // have to replicate the comma replacement functionality here.
+ if ( [ 'ar', 'ar-sa', 'fa' ].indexOf( mw.config.get( 'wgUserLanguage' ) ) !== -1 ) {
+ s = s.replace( /,/g, '،' );
+ }
+ return s;
+ }
+ } );
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/oojs-global.js b/www/wiki/resources/src/oojs-global.js
new file mode 100644
index 00000000..de156f0b
--- /dev/null
+++ b/www/wiki/resources/src/oojs-global.js
@@ -0,0 +1,2 @@
+// Back-compat: Export module as global
+window.OO = module.exports;
diff --git a/www/wiki/resources/src/oojs-ui-local.css b/www/wiki/resources/src/oojs-ui-local.css
new file mode 100644
index 00000000..57e0d8d8
--- /dev/null
+++ b/www/wiki/resources/src/oojs-ui-local.css
@@ -0,0 +1,6 @@
+/* HACK: Set sane font-size for OOjs UI dialogs, in the most common case. This should be skin's
+ responsibility, but alas our skins tend to have the weirdest font-sizes on body. This shall be
+ removed when we make the MediaWiki skins bundled with tarball sane. (T91152) */
+body > .oo-ui-windowManager {
+ font-size: 0.8rem;
+}
diff --git a/www/wiki/resources/src/oojs-ui-local.js b/www/wiki/resources/src/oojs-ui-local.js
new file mode 100644
index 00000000..dffa863d
--- /dev/null
+++ b/www/wiki/resources/src/oojs-ui-local.js
@@ -0,0 +1,17 @@
+( function ( mw ) {
+ var isMobile;
+ // Connect OOjs UI to MediaWiki's localisation system
+ OO.ui.getUserLanguages = mw.language.getFallbackLanguageChain;
+ OO.ui.msg = mw.msg;
+ // Connect OOjs UI's deprecation warnings to MediaWiki's logging system
+ OO.ui.warnDeprecation = function ( message ) {
+ mw.track( 'mw.deprecate', 'oojs-ui' );
+ mw.log.warn( message );
+ };
+ OO.ui.isMobile = function () {
+ if ( isMobile === undefined ) {
+ isMobile = !!mw.config.get( 'wgMFMode' );
+ }
+ return isMobile;
+ };
+}( mediaWiki ) );
diff --git a/www/wiki/resources/src/oojs-ui-styles-skip.js b/www/wiki/resources/src/oojs-ui-styles-skip.js
new file mode 100644
index 00000000..57c905a3
--- /dev/null
+++ b/www/wiki/resources/src/oojs-ui-styles-skip.js
@@ -0,0 +1,9 @@
+/*!
+ * Skip function for OOjs UI PHP style modules.
+ *
+ * The `<meta name="X-OOUI-PHP" />` is added to pages by OutputPage::enableOOUI().
+ *
+ * Looking for elements in the DOM might be expensive, but it's probably better than double-loading
+ * 200 KB of CSS with embedded images because of bug T87871.
+ */
+return !!jQuery( 'meta[name="X-OOUI-PHP"]' ).length;
diff --git a/www/wiki/resources/src/polyfill-nodeTypes.js b/www/wiki/resources/src/polyfill-nodeTypes.js
new file mode 100644
index 00000000..556b51b4
--- /dev/null
+++ b/www/wiki/resources/src/polyfill-nodeTypes.js
@@ -0,0 +1,19 @@
+/**
+ * Adds window.Node with node types according to:
+ * http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-1950641247
+ */
+
+window.Node = window.Node || {
+ ELEMENT_NODE: 1,
+ ATTRIBUTE_NODE: 2,
+ TEXT_NODE: 3,
+ CDATA_SECTION_NODE: 4,
+ ENTITY_REFERENCE_NODE: 5,
+ ENTITY_NODE: 6,
+ PROCESSING_INSTRUCTION_NODE: 7,
+ COMMENT_NODE: 8,
+ DOCUMENT_NODE: 9,
+ DOCUMENT_TYPE_NODE: 10,
+ DOCUMENT_FRAGMENT_NODE: 11,
+ NOTATION_NODE: 12
+};
diff --git a/www/wiki/resources/src/polyfill-object-create.js b/www/wiki/resources/src/polyfill-object-create.js
new file mode 100644
index 00000000..607faf64
--- /dev/null
+++ b/www/wiki/resources/src/polyfill-object-create.js
@@ -0,0 +1,62 @@
+/**
+ * Simplified version of es5-sham#Object-create that also works around a bug
+ * in the actual es5-sham: https://github.com/es-shims/es5-shim/issues/252
+ *
+ * Does not:
+ * - Support empty inheritance via `Object.create(null)`.
+ * - Support getter and setter accessors via `Object.create( .., properties )`.
+ * - Support custom property descriptor (e.g. writable, configurtable, enumerable).
+ * - Leave behind an enumerable "__proto__" all over the place.
+ *
+ * @author Timo Tijhof, 2014
+ */
+
+// ES5 15.2.3.5
+// http://es5.github.com/#x15.2.3.5
+if ( !Object.create ) {
+ ( function () {
+ var hasOwn = Object.hasOwnProperty,
+ // https://developer.mozilla.org/en-US/docs/ECMAScript_DontEnum_attribute#JScript_DontEnum_Bug
+ // http://whattheheadsaid.com/2010/10/a-safer-object-keys-compatibility-implementation
+ isEnumBug = !{ valueOf: 0 }.propertyIsEnumerable( 'valueOf' );
+
+ // Reusable constructor function for Object.create
+ function Empty() {}
+
+ function defineProperty( object, key, property ) {
+ if ( hasOwn.call( property, 'value' ) ) {
+ object[ key ] = property.value;
+ } else {
+ object[ key ] = property;
+ }
+ }
+
+ Object.create = function create( prototype, properties ) {
+ var object, key;
+
+ if ( prototype !== Object( prototype ) ) {
+ throw new TypeError( 'Called on non-object' );
+ }
+
+ Empty.prototype = prototype;
+ object = new Empty();
+
+ if ( properties !== undefined ) {
+ if ( !isEnumBug ) {
+ for ( key in properties ) {
+ if ( hasOwn.call( properties, key ) ) {
+ defineProperty( object, key, properties[ key ] );
+ }
+ }
+ } else {
+ Object.keys( properties ).forEach( function ( key ) {
+ defineProperty( object, key, properties[ key ] );
+ } );
+ }
+ }
+
+ return object;
+ };
+
+ }() );
+}
diff --git a/www/wiki/resources/src/startup.js b/www/wiki/resources/src/startup.js
new file mode 100644
index 00000000..d672d769
--- /dev/null
+++ b/www/wiki/resources/src/startup.js
@@ -0,0 +1,168 @@
+/**
+ * This file is where we decide whether to initialise the Grade A run-time.
+ *
+ * - Beware: This file MUST parse without errors on even the most ancient of browsers!
+ * - Beware: Do not call mwNow before the isCompatible() check.
+ */
+
+/* global mw, mwPerformance, mwNow, isCompatible, $VARS, $CODE */
+
+window.mwPerformance = ( window.performance && performance.mark ) ? performance : {
+ mark: function () {}
+};
+// Define now() here to ensure valid comparison with mediaWikiLoadEnd (T153819).
+window.mwNow = ( function () {
+ var perf = window.performance,
+ navStart = perf && perf.timing && perf.timing.navigationStart;
+ return navStart && typeof perf.now === 'function' ?
+ function () { return navStart + perf.now(); } :
+ function () { return Date.now(); };
+}() );
+
+/**
+ * See <https://www.mediawiki.org/wiki/Compatibility#Browsers>
+ *
+ * Capabilities required for modern run-time:
+ * - ECMAScript 5
+ * - DOM Level 4 & Selectors API Level 1
+ * - HTML5 & Web Storage
+ * - DOM Level 2 Events
+ *
+ * Browsers we support in our modern run-time (Grade A):
+ * - Chrome 13+
+ * - IE 10+
+ * - Firefox 4+
+ * - Safari 5+
+ * - Opera 12.10+
+ * - Mobile Safari 5.1+ (iOS 5+)
+ * - Android 4.1+
+ *
+ * Browsers we support in our no-javascript run-time (Grade C):
+ * - Chrome 1+
+ * - IE 6+
+ * - Firefox 3+
+ * - Safari 3+
+ * - Opera 10+
+ * - Mobile Safari 5.0+ (iOS 4+)
+ * - Android 2.0+
+ * - WebOS < 1.5
+ * - PlayStation
+ * - Symbian-based browsers
+ * - NetFront-based browser
+ * - Opera Mini
+ * - Nokia's Ovi Browser
+ * - MeeGo's browser
+ * - Google Glass
+ * - UC Mini (speed mode on)
+ *
+ * Other browsers that pass the check are considered Grade X.
+ *
+ * @param {string} [str] User agent, defaults to navigator.userAgent
+ * @return {boolean} User agent is compatible with MediaWiki JS
+ */
+window.isCompatible = function ( str ) {
+ var ua = str || navigator.userAgent;
+ return !!(
+ // http://caniuse.com/#feat=es5
+ // http://caniuse.com/#feat=use-strict
+ // http://caniuse.com/#feat=json / https://phabricator.wikimedia.org/T141344#2784065
+ ( function () {
+ 'use strict';
+ return !this && !!Function.prototype.bind && !!window.JSON;
+ }() ) &&
+
+ // http://caniuse.com/#feat=queryselector
+ 'querySelector' in document &&
+
+ // http://caniuse.com/#feat=namevalue-storage
+ // https://developer.blackberry.com/html5/apis/v1_0/localstorage.html
+ // https://blog.whatwg.org/this-week-in-html-5-episode-30
+ 'localStorage' in window &&
+
+ // http://caniuse.com/#feat=addeventlistener
+ 'addEventListener' in window &&
+
+ // Hardcoded exceptions for browsers that pass the requirement but we don't want to
+ // support in the modern run-time.
+ // Note: Please extend the regex instead of adding new ones
+ !(
+ ua.match( /webOS\/1\.[0-4]|SymbianOS|Series60|NetFront|Opera Mini|S40OviBrowser|MeeGo|Android.+Glass|^Mozilla\/5\.0 .+ Gecko\/$|googleweblight/ ) ||
+ ua.match( /PlayStation/i )
+ )
+ );
+};
+
+// Conditional script injection
+( function () {
+ var NORLQ, script;
+ if ( !isCompatible() ) {
+ // Undo class swapping in case of an unsupported browser.
+ // See ResourceLoaderClientHtml::getDocumentAttributes().
+ document.documentElement.className = document.documentElement.className
+ .replace( /(^|\s)client-js(\s|$)/, '$1client-nojs$2' );
+
+ NORLQ = window.NORLQ || [];
+ while ( NORLQ.length ) {
+ NORLQ.shift()();
+ }
+ window.NORLQ = {
+ push: function ( fn ) {
+ fn();
+ }
+ };
+
+ // Clear and disable the other queue
+ window.RLQ = {
+ // No-op
+ push: function () {}
+ };
+
+ return;
+ }
+
+ /**
+ * The $CODE and $VARS placeholders are substituted in ResourceLoaderStartUpModule.php.
+ */
+ function startUp() {
+ mw.config = new mw.Map( $VARS.wgLegacyJavaScriptGlobals );
+
+ $CODE.registrations();
+
+ mw.config.set( $VARS.configuration );
+
+ // Must be after mw.config.set because these callbacks may use mw.loader which
+ // needs to have values 'skin', 'debug' etc. from mw.config.
+ // eslint-disable-next-line vars-on-top
+ var RLQ = window.RLQ || [];
+ while ( RLQ.length ) {
+ RLQ.shift()();
+ }
+ window.RLQ = {
+ push: function ( fn ) {
+ fn();
+ }
+ };
+
+ // Clear and disable the other queue
+ window.NORLQ = {
+ // No-op
+ push: function () {}
+ };
+ }
+
+ window.mediaWikiLoadStart = mwNow();
+ mwPerformance.mark( 'mwLoadStart' );
+
+ script = document.createElement( 'script' );
+ script.src = $VARS.baseModulesUri;
+ script.onload = script.onreadystatechange = function () {
+ if ( !script.readyState || /loaded|complete/.test( script.readyState ) ) {
+ // Clean up
+ script.onload = script.onreadystatechange = null;
+ script = null;
+ // Callback
+ startUp();
+ }
+ };
+ document.getElementsByTagName( 'head' )[ 0 ].appendChild( script );
+}() );